@bongos/core 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bongos-core.json +5727 -0
- package/.claude/skills/blocker-review/SKILL.md +91 -0
- package/.claude/skills/blocker-solve/SKILL.md +96 -0
- package/.claude/skills/builder-backup/SKILL.md +54 -0
- package/.claude/skills/builder-box/SKILL.md +45 -0
- package/.claude/skills/builder-claim/SKILL.md +76 -0
- package/.claude/skills/builder-connect/SKILL.md +59 -0
- package/.claude/skills/builder-cost/SKILL.md +47 -0
- package/.claude/skills/builder-end/SKILL.md +81 -0
- package/.claude/skills/builder-exit/SKILL.md +88 -0
- package/.claude/skills/builder-key/SKILL.md +40 -0
- package/.claude/skills/builder-reauth/SKILL.md +50 -0
- package/.claude/skills/builder-redteam/SKILL.md +109 -0
- package/.claude/skills/builder-release/SKILL.md +41 -0
- package/.claude/skills/builder-setup/SKILL.md +62 -0
- package/.claude/skills/builder-ship/SKILL.md +79 -0
- package/.claude/skills/builder-stage/SKILL.md +51 -0
- package/.claude/skills/builder-start/SKILL.md +46 -0
- package/.claude/skills/close-box/SKILL.md +43 -0
- package/.claude/skills/design-sync/SKILL.md +69 -0
- package/.claude/skills/dev/SKILL.md +49 -0
- package/.claude/skills/feedback/SKILL.md +32 -0
- package/.claude/skills/figma-design-sync/SKILL.md +74 -0
- package/.claude/skills/goal-review/SKILL.md +89 -0
- package/.claude/skills/idea-triage/SKILL.md +144 -0
- package/.claude/skills/ideate/SKILL.md +82 -0
- package/.claude/skills/merge-mode/SKILL.md +169 -0
- package/.claude/skills/new-project/SKILL.md +108 -0
- package/.claude/skills/otb-character-review/SKILL.md +71 -0
- package/.claude/skills/otb-design-review/SKILL.md +47 -0
- package/.claude/skills/otb-feedback-capture/SKILL.md +45 -0
- package/.claude/skills/otb-figma-sync/SKILL.md +54 -0
- package/.claude/skills/otb-tile-generate/SKILL.md +45 -0
- package/.claude/skills/paint/SKILL.md +70 -0
- package/.claude/skills/planning-session/SKILL.md +299 -0
- package/.claude/skills/priority-session/SKILL.md +134 -0
- package/.claude/skills/read-session-export/SKILL.md +58 -0
- package/.claude/skills/recall/SKILL.md +52 -0
- package/.claude/skills/session-handoff/SKILL.md +46 -0
- package/.claude/skills/status/SKILL.md +33 -0
- package/.devcontainer/Dockerfile +69 -0
- package/.devcontainer/README.md +73 -0
- package/.devcontainer/devcontainer-lock.json +19 -0
- package/.devcontainer/devcontainer.json +93 -0
- package/.devcontainer/healthcheck.sh +84 -0
- package/.devcontainer/init-firewall.sh +198 -0
- package/.devcontainer/post-create.sh +153 -0
- package/.dockerignore +36 -0
- package/.env.local.example +32 -0
- package/.gitattributes +83 -0
- package/.gitignore +91 -0
- package/CLAUDE.md +242 -0
- package/CODE_OF_CONDUCT.md +46 -0
- package/CONTRIBUTING.md +51 -0
- package/Dockerfile +46 -0
- package/GOVERNANCE.md +44 -0
- package/LICENSE +661 -0
- package/README.md +88 -0
- package/bin/bongos.js +222 -0
- package/clients/bongos-client/README.md +48 -0
- package/clients/bongos-client/bongos-client.global.js +617 -0
- package/clients/bongos-client/examples/hello-world.mjs +62 -0
- package/clients/bongos-client/index.cjs +619 -0
- package/clients/bongos-client/index.d.ts +793 -0
- package/clients/bongos-client/index.mjs +614 -0
- package/clients/bongos-client/package.json +32 -0
- package/config/branding.neutral.json +60 -0
- package/config/design-tokens.neutral.json +51 -0
- package/config/design-tokens.schema.json +96 -0
- package/config/modules.neutral.json +9 -0
- package/docker-compose.yml +52 -0
- package/docker-entrypoint.sh +30 -0
- package/docs/adr/0001-stack-choice-single-vps.md +45 -0
- package/docs/adr/0002-digitalocean-over-hetzner.md +27 -0
- package/docs/adr/0003-cloudflare-origin-cert-over-letsencrypt.md +35 -0
- package/docs/adr/0004-amazonprimea-name-and-trademark-acceptance.md +45 -0
- package/docs/adr/0005-invisible-other-players-in-v1.md +37 -0
- package/docs/adr/0006-singleton-worldroom-plus-queueroom.md +30 -0
- package/docs/adr/0007-persistent-identity-via-localstorage-uuid.md +31 -0
- package/docs/adr/0008-family-based-tile-generation.md +86 -0
- package/docs/adr/0008-google-chat-oauth-user-auth.md +37 -0
- package/docs/adr/0009-autotile-architecture.md +181 -0
- package/docs/adr/0010-pms-architecture.md +70 -0
- package/docs/adr/0011-terrain-id-rendering-model.md +174 -0
- package/docs/adr/0012-ground-object-cell-split.md +208 -0
- package/docs/adr/0013-paths-as-object-overlays-with-autotile-dispatch.md +158 -0
- package/docs/adr/0014-families-canonical-over-vocabulary.md +103 -0
- package/docs/adr/0015-task-dependencies-and-auto-promotion.md +125 -0
- package/docs/adr/0016-trust-boundary-server-enforced-permissions.md +132 -0
- package/docs/adr/0017-code-simplification-and-repo-cleanliness.md +74 -0
- package/docs/adr/0018-three-rank-model-goes-live.md +97 -0
- package/docs/adr/0019-red-team-bounty-payout-table.md +52 -0
- package/docs/adr/0020-security-model-public-stub.md +70 -0
- package/docs/adr/0021-per-builder-skill-model-preferences.md +99 -0
- package/docs/adr/0022-secrets-policy.md +124 -0
- package/docs/adr/0023-kind-multipliers-and-idea-bonus.md +118 -0
- package/docs/adr/0024-cloneable-repo-local-first-memory.md +277 -0
- package/docs/adr/0024-multi-agent-system-architecture.md +125 -0
- package/docs/adr/0025-offsite-backup-vendor-digitalocean-spaces.md +59 -0
- package/docs/adr/0025-structured-criterion-task-link.md +44 -0
- package/docs/adr/0026-bfg-memory-hygiene-and-cross-builder-learning.md +117 -0
- package/docs/adr/0027-bfg-session-inefficiency-evaluator.md +170 -0
- package/docs/adr/0028-honest-llm-spend-accounting.md +109 -0
- package/docs/adr/0029-status-page-outage-resilience.md +59 -0
- package/docs/adr/0030-builders-hall-live-updates.md +59 -0
- package/docs/adr/0031-cloud-dev-environments-for-builders.md +222 -0
- package/docs/adr/0032-discord-mirror-of-gds.md +50 -0
- package/docs/adr/0033-discord-bot-service-principal.md +82 -0
- package/docs/adr/0034-thetes-graduated-newcomer-rank.md +53 -0
- package/docs/adr/0035-builder-onboarding-three-paths.md +128 -0
- package/docs/adr/0036-builders-subdomain-and-ui-reorg.md +40 -0
- package/docs/adr/0037-discord-channel-management.md +51 -0
- package/docs/adr/0038-chromebook-ttyd-cloudflare-tunnel.md +111 -0
- package/docs/adr/0039-setup-first-onboarding-ux.md +49 -0
- package/docs/adr/0040-remote-control-default-browser-onramp.md +47 -0
- package/docs/adr/0041-temporary-grader-bypass-killswitch.md +40 -0
- package/docs/adr/0042-builder-self-deploy-ci-auto-merge.md +82 -0
- package/docs/adr/0043-git-ssh-trust-boundary-and-rank-floor-on-permission-paths.md +74 -0
- package/docs/adr/0044-mediterranean-palette-replacement.md +73 -0
- package/docs/adr/0044-per-box-live-game-preview.md +57 -0
- package/docs/adr/0045-devbox-desktop-app.md +133 -0
- package/docs/adr/0046-sandbox-first-review-gate.md +72 -0
- package/docs/adr/0047-discord-bugs-intake-anti-abuse.md +36 -0
- package/docs/adr/0048-works-in-progress-ia-split.md +32 -0
- package/docs/adr/0049-split-parallel-safety-contract.md +46 -0
- package/docs/adr/0050-device-flow-admission-invite-gated-by-default.md +43 -0
- package/docs/adr/0051-full-session-transcript-corpus.md +57 -0
- package/docs/adr/0052-sandbox-for-everyone-game-only-preview.md +70 -0
- package/docs/adr/0053-scoped-dev-box-session.md +55 -0
- package/docs/adr/0054-session-token-reward-cost-plus.md +63 -0
- package/docs/adr/0055-server-mediated-branch-publish.md +47 -0
- package/docs/adr/0056-prod-deploy-script-mirror-and-healthcheck-retry.md +62 -0
- package/docs/adr/0057-container-cost-ledger.md +28 -0
- package/docs/adr/0057-discord-archon-approval-channels.md +64 -0
- package/docs/adr/0058-automatic-gate-surface-gatekeeper.md +64 -0
- package/docs/adr/0059-single-approval-remove-devbox-approval-gate.md +37 -0
- package/docs/adr/0060-gds-retrieval-layer.md +97 -0
- package/docs/adr/0061-context-layer-decomposition.md +61 -0
- package/docs/adr/0062-medusa-instance-model-decoupling.md +107 -0
- package/docs/adr/0063-generated-repo-map-symbol-skeleton.md +44 -0
- package/docs/adr/0064-rename-medusa-to-cloud-bongos.md +49 -0
- package/docs/adr/0065-agpl-nonprofit-ai-first-governance.md +69 -0
- package/docs/adr/0066-generated-file-map-sections.md +51 -0
- package/docs/adr/0067-session-start-fast-forward-pull.md +43 -0
- package/docs/adr/0068-shared-art-key-for-newcomers.md +38 -0
- package/docs/adr/0069-hall-live-channel-sse-decouple.md +35 -0
- package/docs/adr/0070-deterministic-session-card-delivery.md +44 -0
- package/docs/adr/0071-box-confirm-before-destroyed-and-drift-reconcile.md +59 -0
- package/docs/adr/0072-bongos-app-mac-signed-first-windows-deferred.md +35 -0
- package/docs/adr/0072-dev-box-code-staleness-visibility.md +39 -0
- package/docs/adr/0073-builder-needs-signal-and-byok-gemini-key.md +64 -0
- package/docs/adr/0073-secrets-scan-exclude-uri-detector.md +37 -0
- package/docs/adr/0074-memory-map-stays-light.md +32 -0
- package/docs/adr/0075-per-system-cost-attribution.md +37 -0
- package/docs/adr/0076-in-session-deterministic-compaction.md +58 -0
- package/docs/adr/0077-content-addressed-llm-cache.md +32 -0
- package/docs/adr/0078-deterministic-first-cron.md +48 -0
- package/docs/adr/0079-value-gated-autonomous-engagement.md +39 -0
- package/docs/adr/0080-llm-cache-api-transport-and-trust-model.md +46 -0
- package/docs/adr/0081-tool-agnostic-design-layer.md +62 -0
- package/docs/adr/0082-productized-key-storage-provisioning.md +32 -0
- package/docs/adr/0082-server-side-merge-conflict-auto-resolution.md +55 -0
- package/docs/adr/0083-modular-architecture-strangler-build-plan.md +143 -0
- package/docs/adr/0084-auto-derived-per-task-rank-floor.md +86 -0
- package/docs/adr/0085-remove-default-per-builder-spend-cap.md +39 -0
- package/docs/adr/0086-goal-scoped-work-hierarchy.md +123 -0
- package/docs/adr/0087-bongos-app-architecture-and-handoff-contract.md +49 -0
- package/docs/adr/0087-compete-on-governance-not-tooling-cursor.md +65 -0
- package/docs/adr/0088-consistent-character-generative-animation.md +169 -0
- package/docs/adr/0089-modular-multi-model-adversarial-grader.md +179 -0
- package/docs/adr/0090-metic-task-authoring.md +73 -0
- package/docs/adr/0091-bounding-the-kernel-and-db-carve.md +106 -0
- package/docs/adr/0092-hosting-module-and-on-prem-target.md +117 -0
- package/docs/adr/0093-tranche-2-core-carve-sequence.md +72 -0
- package/docs/adr/0094-repo-atlas-self-drawing-codebase-map.md +49 -0
- package/docs/adr/0095-borrowed-memory-and-retrieval-concepts.md +65 -0
- package/docs/adr/0095-cross-agent-context-management.md +58 -0
- package/docs/adr/0096-require-reward-before-workable.md +209 -0
- package/docs/adr/0097-one-active-claim-per-session-and-worktree-binding.md +46 -0
- package/docs/adr/0097-retroactive-reward-backfill.md +124 -0
- package/docs/adr/0098-public-mirror-publish-manifest.md +92 -0
- package/docs/adr/0099-delayed-redacted-mirror-export.md +55 -0
- package/docs/adr/0100-two-repo-instance-model.md +60 -0
- package/docs/adr/0101-goal-hierarchy-phase-5-judge-membership-reward.md +90 -0
- package/docs/adr/0102-finish-bounding-the-kernel.md +36 -0
- package/docs/adr/0103-core-first-extraction-cloud-bongos-trunk.md +70 -0
- package/docs/adr/0103-gdsv4-bongos-consolidation.md +28 -0
- package/docs/adr/0104-trust-gds-api-channel-in-auto-mode.md +42 -0
- package/docs/adr/0105-instance-seed-migrations-out-of-core.md +47 -0
- package/docs/adr/0106-goal-owner-manager-authority.md +84 -0
- package/docs/adr/0107-module-upstreaming-contribution-to-core-catalog.md +83 -0
- package/docs/adr/0108-instance-composition-configurable-root.md +87 -0
- package/docs/adr/0109-self-describing-openapi-and-hosted-docs.md +44 -0
- package/docs/adr/0110-untrack-whole-file-generated-nav-docs.md +49 -0
- package/docs/adr/0111-instance-hosting-provisioning-module.md +135 -0
- package/docs/adr/0112-private-goals-invitations-join-requests.md +72 -0
- package/docs/adr/0113-sandbox-studio-descope-superseded-by-0044-0052.md +41 -0
- package/docs/adr/0114-instance-docs-discovery-contract.md +32 -0
- package/docs/adr/0115-scheduled-routines-portability.md +31 -0
- package/docs/adr/0116-api-error-envelope-and-code-taxonomy.md +62 -0
- package/docs/adr/0117-api-versioning-and-deprecation-policy.md +50 -0
- package/docs/adr/0118-api-contract-source-of-truth-code-first.md +47 -0
- package/docs/adr/0119-api-pagination-contract.md +34 -0
- package/docs/adr/0120-pay-on-land-and-builder-owned-rebase-gate.md +108 -0
- package/docs/adr/0121-greenfield-vs-brownfield-onboarding-adopt-existing-repo.md +97 -0
- package/docs/adr/0122-onboarding-diagram-renders-deploy-rendered-off-git.md +43 -0
- package/docs/adr/0123-box-idle-sweep-autosave-before-destroy.md +36 -0
- package/docs/adr/0124-typed-api-response-bodies.md +37 -0
- package/docs/adr/0125-control-plane-scaffolds-standalone-instance-repo.md +36 -0
- package/docs/adr/0126-dedicated-cloudbongos-control-plane-droplet.md +30 -0
- package/docs/adr/0127-cross-box-fleet-observability.md +64 -0
- package/docs/adr/0128-provisioning-runner-privilege-and-db-auth-model.md +46 -0
- package/docs/adr/0129-cloudbongos-control-plane-pull-deploy.md +34 -0
- package/docs/adr/0130-provision-remote-exec-over-ssh.md +61 -0
- package/docs/adr/0131-rank-scoped-skill-visibility.md +47 -0
- package/docs/adr/0132-cohost-fleet-control-plane-migration.md +54 -0
- package/docs/adr/0133-github-app-manifest-onboarding-signin.md +42 -0
- package/docs/adr/0134-private-first-npm-distribution.md +38 -0
- package/docs/adr/README.md +208 -0
- package/docs/api/openapi.json +13720 -0
- package/docs/api-reference.md +437 -0
- package/docs/architecture.md +244 -0
- package/docs/branding-contract.md +66 -0
- package/docs/branding-fill-prompt.md +25 -0
- package/docs/canonical-permissions.md +241 -0
- package/docs/design/container-exterior-tiles.md +49 -0
- package/docs/design/container-exterior.md +81 -0
- package/docs/design/container-interior.md +77 -0
- package/docs/design/modular-architecture/00-research-report.md +107 -0
- package/docs/design/modular-architecture/01-architecture.md +125 -0
- package/docs/design/modular-architecture/02-module-map.md +116 -0
- package/docs/design/modular-architecture/03-builder-flows.md +104 -0
- package/docs/design/modular-architecture/04-module-lifecycle.md +62 -0
- package/docs/design/modular-architecture/README.md +27 -0
- package/docs/design/vanilla-hall-ui-redesign-scope.md +284 -0
- package/docs/design/world-map-scroll.md +41 -0
- package/docs/design-contract.md +320 -0
- package/docs/file-map.md +418 -0
- package/docs/handoff-template.md +92 -0
- package/docs/modules-contract.md +293 -0
- package/docs/onboarding/browser-terminal-guide.md +73 -0
- package/docs/onboarding/diagrams/01-task-lifecycle.mmd +28 -0
- package/docs/onboarding/diagrams/02-rank-ladder.mmd +54 -0
- package/docs/onboarding/diagrams/03-drachmae-karma.mmd +37 -0
- package/docs/onboarding/diagrams/04-architecture.mmd +51 -0
- package/docs/onboarding/diagrams/05-versioning.mmd +29 -0
- package/docs/onboarding/diagrams/README.md +94 -0
- package/docs/onboarding/diagrams/assertions.json +170 -0
- package/docs/onboarding/diagrams/puppeteer-config.json +1 -0
- package/docs/onboarding/diagrams/render-config.json +9 -0
- package/docs/onboarding/drachmae-and-karma.md +178 -0
- package/docs/onboarding/primer.md +202 -0
- package/docs/project-context.template.md +67 -0
- package/docs/recipes/README.md +35 -0
- package/docs/recipes/audit-replay.md +100 -0
- package/docs/recipes/bongos-cli-release.md +66 -0
- package/docs/recipes/builder-box-lifecycle.md +152 -0
- package/docs/recipes/claude-design-loop.md +143 -0
- package/docs/recipes/claude-gemini-bongos-doors.md +155 -0
- package/docs/recipes/cloudbongos-staging-gate.md +139 -0
- package/docs/recipes/cloudbongos-standup.md +111 -0
- package/docs/recipes/devbox-app-release.md +93 -0
- package/docs/recipes/devbox-app-windows-test.md +128 -0
- package/docs/recipes/failed-ship-recovery-proof.md +102 -0
- package/docs/recipes/figma-design-loop.md +129 -0
- package/docs/recipes/gds-db-backup.md +255 -0
- package/docs/recipes/instance-deploy.md +37 -0
- package/docs/recipes/managed-settings-remote-control.md +416 -0
- package/docs/recipes/memory-backup.md +71 -0
- package/docs/recipes/memory-sync-conflicts.md +98 -0
- package/docs/recipes/multi-builder-merge.md +78 -0
- package/docs/recipes/ops-gotchas.md +212 -0
- package/docs/recipes/overnight-builder.md +53 -0
- package/docs/recipes/packaging-the-core.md +49 -0
- package/docs/recipes/parallel-load-results-2026-05-30.md +63 -0
- package/docs/recipes/parallel-load-test.md +32 -0
- package/docs/recipes/pixel-art-pipeline.md +411 -0
- package/docs/recipes/private-npm-distribution.md +79 -0
- package/docs/recipes/search-index-ingestion.md +67 -0
- package/docs/recipes/self-host.md +60 -0
- package/docs/recipes/ship-and-regrade.md +72 -0
- package/docs/recipes/staging-data.md +50 -0
- package/docs/recipes/staging-environment.md +215 -0
- package/docs/recipes/upgrading-the-core.md +58 -0
- package/docs/research/cursor-competitive-analysis.md +255 -0
- package/docs/research/llm-model-agnostic-and-cheaper-grader.md +227 -0
- package/migrations/003_pms.sql +284 -0
- package/migrations/004_pms_cost_idempotency.sql +13 -0
- package/migrations/005_pms_smoke_filter.sql +44 -0
- package/migrations/006_pms_v2.sql +378 -0
- package/migrations/007_pms_v2_hierarchy_trigger.sql +59 -0
- package/migrations/008_pms_v2_migration_allocator.sql +27 -0
- package/migrations/009_pms_v2_blockers_table.sql +68 -0
- package/migrations/010_uptime.sql +29 -0
- package/migrations/011_backfill_v2_v3_done_when.sql +20 -0
- package/migrations/012_pms_v2_task_lifecycle_states.sql +82 -0
- package/migrations/013_claim_locking.sql +22 -0
- package/migrations/014_pms_task_discipline.sql +86 -0
- package/migrations/015_pms_estimation_calibration.sql +140 -0
- package/migrations/016_pms_task_grades.sql +60 -0
- package/migrations/017_version_progress_exclude_abandoned.sql +49 -0
- package/migrations/019_rename_pms_v3_to_gds_v3.sql +65 -0
- package/migrations/020_task_dependencies.sql +99 -0
- package/migrations/021_v3_renumber_and_deps.sql +224 -0
- package/migrations/022_v3_reconcile_dep_gated_status.sql +41 -0
- package/migrations/023_pms_rank.sql +30 -0
- package/migrations/025_builder_exit_status.sql +15 -0
- package/migrations/027_builders_preferred_disciplines.sql +46 -0
- package/migrations/028_tasks_parallel_safe.sql +71 -0
- package/migrations/029_rank_three_live.sql +32 -0
- package/migrations/030_vulnerability_reports.sql +61 -0
- package/migrations/031_reward_simplification.sql +57 -0
- package/migrations/032_repo_health_snapshots.sql +56 -0
- package/migrations/033_audit_log.sql +64 -0
- package/migrations/034_lifecycle_breakdown_leaf_only.sql +62 -0
- package/migrations/035_auth_token_hygiene.sql +66 -0
- package/migrations/037_builder_skill_model_prefs.sql +44 -0
- package/migrations/038_task_override_requests.sql +51 -0
- package/migrations/039_newcomer_friendly_column.sql +124 -0
- package/migrations/040_builder_karma.sql +58 -0
- package/migrations/041_kind_multipliers_and_idea_bonus.sql +42 -0
- package/migrations/042_criterion_proposal_workflow.sql +78 -0
- package/migrations/043_builder_onboarding_observability.sql +66 -0
- package/migrations/044_tasks_requires_rank.sql +97 -0
- package/migrations/045_builder_onboarding_state.sql +147 -0
- package/migrations/046_cost_log_builder_attribution.sql +42 -0
- package/migrations/054_builder_memory.sql +108 -0
- package/migrations/055_task_criteria.sql +90 -0
- package/migrations/058_peer_votes.sql +41 -0
- package/migrations/059_onboarding_pick_disciplines.sql +59 -0
- package/migrations/060_access_requests.sql +46 -0
- package/migrations/061_backfill_override_ship_attribution.sql +29 -0
- package/migrations/062_session_records.sql +34 -0
- package/migrations/063_session_records_tool_errors_idx.sql +11 -0
- package/migrations/064_grade_attempts.sql +18 -0
- package/migrations/065_bfg_principal.sql +58 -0
- package/migrations/066_live_notify_triggers.sql +69 -0
- package/migrations/067_builder_boxes.sql +117 -0
- package/migrations/067_discord_bot_foundation.sql +69 -0
- package/migrations/068_thetes_requires_rank.sql +27 -0
- package/migrations/069_builder_ssh_keys.sql +66 -0
- package/migrations/070_box_intents.sql +101 -0
- package/migrations/071_box_first_provision_approval.sql +46 -0
- package/migrations/072_onboarding_ship_three_remove_primer.sql +80 -0
- package/migrations/073_box_terminal_access.sql +46 -0
- package/migrations/075_builder_sound_prefs.sql +28 -0
- package/migrations/078_box_claude_active.sql +22 -0
- package/migrations/079_box_first_connected_at.sql +20 -0
- package/migrations/081_tasks_needs_migration.sql +34 -0
- package/migrations/084_tasks_security_sensitive.sql +24 -0
- package/migrations/085_security_engagement_docs.sql +34 -0
- package/migrations/086_rename_disciplines.sql +125 -0
- package/migrations/088_builders_anthropic_link.sql +28 -0
- package/migrations/089_builders_monthly_budget.sql +19 -0
- package/migrations/090_box_scoped_sessions.sql +38 -0
- package/migrations/091_session_token_reward.sql +44 -0
- package/migrations/093_tasks_sandbox_review.sql +22 -0
- package/migrations/102_remove_box_first_provision_approval.sql +58 -0
- package/migrations/103_search_chunks.sql +90 -0
- package/migrations/104_builder_box_blocked.sql +34 -0
- package/migrations/105_box_host_keys.sql +35 -0
- package/migrations/111_medusa_customer0_framing.sql +35 -0
- package/migrations/112_drop_track_check.sql +25 -0
- package/migrations/113_merge_lease.sql +16 -0
- package/migrations/114_cloudbongos_rename_live_strings.sql +32 -0
- package/migrations/118_currency_label_decoupling.sql +23 -0
- package/migrations/119_builder_behavior_prefs.sql +31 -0
- package/migrations/121_box_code_version.sql +37 -0
- package/migrations/122_builder_gemini_key.sql +30 -0
- package/migrations/123_cost_log_tiers.sql +33 -0
- package/migrations/124_cost_baseline.sql +45 -0
- package/migrations/125_llm_cache.sql +54 -0
- package/migrations/126_autonomy_runs.sql +33 -0
- package/migrations/143_cost_calibration.sql +63 -0
- package/migrations/145_backfill_task_requires_rank.sql +84 -0
- package/migrations/160_goal_tier.sql +88 -0
- package/migrations/163_polymorphic_dependencies.sql +187 -0
- package/migrations/164_event_sound_prefs.sql +20 -0
- package/migrations/165_task_module_key.sql +15 -0
- package/migrations/171_claims_published_head_sha.sql +24 -0
- package/migrations/174_close_orphaned_claims_on_terminal_tasks.sql +30 -0
- package/migrations/175_task_grades_diff_hash.sql +9 -0
- package/migrations/176_promotion_respects_open_blockers.sql +58 -0
- package/migrations/176_ui_discipline.sql +40 -0
- package/migrations/177_require_reward_before_workable.sql +76 -0
- package/migrations/178_reward_gate_auto_assign_revert_autopromote.sql +61 -0
- package/migrations/179_search_chunk_usefulness.sql +33 -0
- package/migrations/180_one_active_claim_per_session.sql +54 -0
- package/migrations/181_cost_log_skill_name.sql +33 -0
- package/migrations/184_claim_release_requested.sql +25 -0
- package/migrations/185_module_upstreaming_goal_wiring.sql +59 -0
- package/migrations/187_goal_sort_order.sql +30 -0
- package/migrations/187_tasks_kind_check_add_verify.sql +21 -0
- package/migrations/README.md +88 -0
- package/migrations/core_188_goal_visibility_and_membership_requests.sql +71 -0
- package/migrations/core_189_core_upgrades_ledger.sql +37 -0
- package/migrations/core_189_credit_log_task_id_index.sql +19 -0
- package/migrations/core_190_rebuild_claimable_task_views.sql +71 -0
- package/migrations/instance/018_pms_v3_planning_seed.sql +131 -0
- package/migrations/instance/080_gds_v4_planning_seed.sql +75 -0
- package/migrations/instance/110_medusa_planning_seed.sql +70 -0
- package/migrations/instance/120_bongos_v1_planning_seed.sql +69 -0
- package/migrations/instance/144_bongos_v1_module_system_criterion.sql +26 -0
- package/migrations/instance/159_bongos_v1_goal_hierarchy_criterion.sql +29 -0
- package/migrations/instance/172_v2_world_planning_seed.sql +163 -0
- package/migrations/instance/173_bongos_v1_c7_core_modularized.sql +33 -0
- package/migrations/instance/182_gdsv4_bongos_consolidation.sql +132 -0
- package/migrations/instance/183_gdsv4_carryover_themed_goals.sql +116 -0
- package/migrations/instance/186_bongos_v1_governance_planning_seed.sql +69 -0
- package/modules/autonomy/CLAUDE.md +49 -0
- package/modules/autonomy/db.js +50 -0
- package/modules/autonomy/module.json +13 -0
- package/modules/autonomy/pollers/routine-timers.js +146 -0
- package/modules/autonomy/routes/autonomy.js +37 -0
- package/modules/builder-settings/CLAUDE.md +58 -0
- package/modules/builder-settings/builder-needs.js +115 -0
- package/modules/builder-settings/db.js +168 -0
- package/modules/builder-settings/display-name.js +84 -0
- package/modules/builder-settings/event-sound-prefs.js +169 -0
- package/modules/builder-settings/interaction-prefs.js +201 -0
- package/modules/builder-settings/model-alloc-prefs.js +147 -0
- package/modules/builder-settings/module.json +10 -0
- package/modules/builder-settings/render-prefs.js +103 -0
- package/modules/builder-settings/routes/settings.js +417 -0
- package/modules/builder-settings/settings.js +52 -0
- package/modules/builder-settings/skill-prefs.js +196 -0
- package/modules/builder-settings/sound-prefs.js +178 -0
- package/modules/builder-settings/wandering-prefs.js +282 -0
- package/modules/dev-box/CLAUDE.md +38 -0
- package/modules/dev-box/box-access.js +275 -0
- package/modules/dev-box/box-credential.js +94 -0
- package/modules/dev-box/box-onboard.js +486 -0
- package/modules/dev-box/boxes.js +842 -0
- package/modules/dev-box/db.js +39 -0
- package/modules/dev-box/module.json +14 -0
- package/modules/dev-box/routes/box.js +977 -0
- package/modules/discord/CLAUDE.md +50 -0
- package/modules/discord/auth.js +54 -0
- package/modules/discord/bug-attachments.js +210 -0
- package/modules/discord/db.js +96 -0
- package/modules/discord/discord-approvals.js +145 -0
- package/modules/discord/discord-audit.js +29 -0
- package/modules/discord/discord-bot.js +545 -0
- package/modules/discord/discord-bugs.js +257 -0
- package/modules/discord/discord-channels.js +412 -0
- package/modules/discord/discord-inbound.js +147 -0
- package/modules/discord/discord-message-buffer.js +54 -0
- package/modules/discord/discord-reaction.js +186 -0
- package/modules/discord/discord-role-sync.js +318 -0
- package/modules/discord/module.json +14 -0
- package/modules/discord/pollers/discord-bot.js +19 -0
- package/modules/discord/routes/bug-attachments.js +44 -0
- package/modules/discord/routes/discord.js +102 -0
- package/modules/discord/ship-broadcast.js +78 -0
- package/modules/discord/webhook.js +74 -0
- package/modules/economy/CLAUDE.md +48 -0
- package/modules/economy/achievements.js +594 -0
- package/modules/economy/cost-classify.js +331 -0
- package/modules/economy/cost-summary-shape.js +90 -0
- package/modules/economy/cost.js +438 -0
- package/modules/economy/credits.js +430 -0
- package/modules/economy/migrations/economy_001_fix_gds_shipper_description.sql +91 -0
- package/modules/economy/module.json +10 -0
- package/modules/economy/reward.js +61 -0
- package/modules/economy/routes/cost.js +97 -0
- package/modules/economy/routes/leaderboard.js +26 -0
- package/modules/economy/routes/reward.js +42 -0
- package/modules/economy/streak.js +285 -0
- package/modules/grading/CLAUDE.md +42 -0
- package/modules/grading/db.js +39 -0
- package/modules/grading/grader-rubric.json +151 -0
- package/modules/grading/grader-workers/efficiency.js +213 -0
- package/modules/grading/grader-workers/extract-json.js +80 -0
- package/modules/grading/grader-workers/fence.js +100 -0
- package/modules/grading/grader-workers/hacker.js +239 -0
- package/modules/grading/grader-workers/index.js +183 -0
- package/modules/grading/grader-workers/narc.js +207 -0
- package/modules/grading/grader-workers/quality.js +198 -0
- package/modules/grading/grader-workers/rubric.js +20 -0
- package/modules/grading/grader-workers/worker-prompt.js +89 -0
- package/modules/grading/grader-workers/worker-verdict.js +50 -0
- package/modules/grading/grader.js +1790 -0
- package/modules/grading/module.json +12 -0
- package/modules/grading/routes/grade.js +51 -0
- package/modules/hall-ui/CLAUDE.md +61 -0
- package/modules/hall-ui/module.json +14 -0
- package/modules/hall-ui/public/atlas.html +180 -0
- package/modules/hall-ui/public/atlas.js +336 -0
- package/modules/hall-ui/public/box-panel.js +423 -0
- package/modules/hall-ui/public/brand-apply.js +117 -0
- package/modules/hall-ui/public/builders.js +3028 -0
- package/modules/hall-ui/public/chime.wav +0 -0
- package/modules/hall-ui/public/copy-on-click.js +174 -0
- package/modules/hall-ui/public/cursors/arrow.png +0 -0
- package/modules/hall-ui/public/cursors/hand-pointer.png +0 -0
- package/modules/hall-ui/public/cursors/magnifier-out.png +0 -0
- package/modules/hall-ui/public/cursors/magnifier.png +0 -0
- package/modules/hall-ui/public/diagram-viewer.css +125 -0
- package/modules/hall-ui/public/diagram-viewer.js +330 -0
- package/modules/hall-ui/public/diagrams.html +113 -0
- package/modules/hall-ui/public/dom-utils.js +212 -0
- package/modules/hall-ui/public/drachmae.html +68 -0
- package/modules/hall-ui/public/drachmae.js +136 -0
- package/modules/hall-ui/public/gate.html +143 -0
- package/modules/hall-ui/public/gate.js +228 -0
- package/modules/hall-ui/public/goals-page.js +1297 -0
- package/modules/hall-ui/public/goals.html +376 -0
- package/modules/hall-ui/public/goals.js +119 -0
- package/modules/hall-ui/public/hall-widgets.js +189 -0
- package/modules/hall-ui/public/harbor.html +167 -0
- package/modules/hall-ui/public/harbor.js +335 -0
- package/modules/hall-ui/public/index.html +116 -0
- package/modules/hall-ui/public/instances-panel.js +172 -0
- package/modules/hall-ui/public/md-reader.js +234 -0
- package/modules/hall-ui/public/modules.html +119 -0
- package/modules/hall-ui/public/modules.js +154 -0
- package/modules/hall-ui/public/new-project-wizard.js +186 -0
- package/modules/hall-ui/public/not-ready.html +48 -0
- package/modules/hall-ui/public/pair.html +119 -0
- package/modules/hall-ui/public/pair.js +132 -0
- package/modules/hall-ui/public/primer.css +404 -0
- package/modules/hall-ui/public/primer.html +85 -0
- package/modules/hall-ui/public/primer.js +641 -0
- package/modules/hall-ui/public/profile.html +85 -0
- package/modules/hall-ui/public/profile.js +236 -0
- package/modules/hall-ui/public/ranks.html +69 -0
- package/modules/hall-ui/public/ranks.js +206 -0
- package/modules/hall-ui/public/roadmap.html +209 -0
- package/modules/hall-ui/public/roadmap.js +375 -0
- package/modules/hall-ui/public/sessions.html +92 -0
- package/modules/hall-ui/public/sessions.js +222 -0
- package/modules/hall-ui/public/settings.html +640 -0
- package/modules/hall-ui/public/settings.js +1219 -0
- package/modules/hall-ui/public/shell.js +495 -0
- package/modules/hall-ui/public/style.css +1748 -0
- package/modules/hall-ui/public/task-detail.js +253 -0
- package/modules/hall-ui/public/task.html +83 -0
- package/modules/hall-ui/public/task.js +326 -0
- package/modules/hall-ui/public/watch.html +333 -0
- package/modules/hall-ui/public/watch.js +859 -0
- package/modules/hall-ui/public/work.html +469 -0
- package/modules/hall-ui/public/work.js +1292 -0
- package/modules/ideas/CLAUDE.md +37 -0
- package/modules/ideas/blockers.js +100 -0
- package/modules/ideas/inbox.js +459 -0
- package/modules/ideas/module.json +10 -0
- package/modules/ideas/routes/blockers.js +120 -0
- package/modules/ideas/routes/inbox.js +230 -0
- package/modules/lifecycle/CLAUDE.md +63 -0
- package/modules/lifecycle/conflict-resolve.js +436 -0
- package/modules/lifecycle/db.js +4970 -0
- package/modules/lifecycle/done-when.js +355 -0
- package/modules/lifecycle/github-push.js +969 -0
- package/modules/lifecycle/goal-conflicts.js +133 -0
- package/modules/lifecycle/hierarchy.js +104 -0
- package/modules/lifecycle/lifecycle.js +58 -0
- package/modules/lifecycle/merge-lock.js +261 -0
- package/modules/lifecycle/migrations/lifecycle_001_goal_first_leads.sql +28 -0
- package/modules/lifecycle/migrations/lifecycle_002_backfill_orphan_task_goals.sql +36 -0
- package/modules/lifecycle/module.json +13 -0
- package/modules/lifecycle/pollers/publish-reconciler.js +20 -0
- package/modules/lifecycle/publish-reconciler.js +418 -0
- package/modules/lifecycle/routes/analytics.js +63 -0
- package/modules/lifecycle/routes/claims.js +506 -0
- package/modules/lifecycle/routes/dependencies.js +82 -0
- package/modules/lifecycle/routes/done-when.js +136 -0
- package/modules/lifecycle/routes/gate-approvals.js +197 -0
- package/modules/lifecycle/routes/goals.js +1419 -0
- package/modules/lifecycle/routes/lifecycle.js +43 -0
- package/modules/lifecycle/routes/tasks.js +1703 -0
- package/modules/lifecycle/routes/versions.js +128 -0
- package/modules/lifecycle/ship-card.js +505 -0
- package/modules/lifecycle/ship-preflight.js +225 -0
- package/modules/lifecycle/task-classifier.js +512 -0
- package/modules/lifecycle/version-close.js +106 -0
- package/modules/memory/CLAUDE.md +40 -0
- package/modules/memory/learnings.js +275 -0
- package/modules/memory/memory.js +572 -0
- package/modules/memory/module.json +12 -0
- package/modules/memory/routes/learnings.js +90 -0
- package/modules/memory/routes/memory.js +916 -0
- package/modules/memory/routes/search.js +188 -0
- package/modules/memory/search-chunker.js +252 -0
- package/modules/memory/search.js +320 -0
- package/modules/onboarding/CLAUDE.md +55 -0
- package/modules/onboarding/approval-broadcast.js +59 -0
- package/modules/onboarding/db.js +54 -0
- package/modules/onboarding/module.json +10 -0
- package/modules/onboarding/newcomer-restock.js +212 -0
- package/modules/onboarding/onboarding-state.js +532 -0
- package/modules/onboarding/onboarding.js +508 -0
- package/modules/onboarding/port.js +63 -0
- package/modules/onboarding/routes/access-requests.js +208 -0
- package/modules/onboarding/routes/onboarding.js +54 -0
- package/modules/security/CLAUDE.md +44 -0
- package/modules/security/module.json +10 -0
- package/modules/security/routes/reports.js +251 -0
- package/modules/security/secret-scrub.js +201 -0
- package/modules/security/security.js +294 -0
- package/modules/sessions/CLAUDE.md +39 -0
- package/modules/sessions/bfg.js +357 -0
- package/modules/sessions/db.js +326 -0
- package/modules/sessions/module.json +10 -0
- package/modules/sessions/pulse.js +149 -0
- package/modules/sessions/routes/sessions.js +331 -0
- package/modules/status-ui/CLAUDE.md +47 -0
- package/modules/status-ui/module.json +14 -0
- package/modules/status-ui/public/README.md +29 -0
- package/modules/status-ui/public/cursors/arrow.png +0 -0
- package/modules/status-ui/public/cursors/hand-pointer.png +0 -0
- package/modules/status-ui/public/index.html +363 -0
- package/modules/status-ui/public/snapshots/.gitkeep +0 -0
- package/modules/status-ui/public/status.js +1375 -0
- package/modules/status-ui/public/style.css +1342 -0
- package/package-lock.json +975 -0
- package/package.json +28 -0
- package/public-docs/index.html +35 -0
- package/public-docs/redoc.standalone.js +1838 -0
- package/public-docs/redoc.standalone.js.LICENSE.txt +102 -0
- package/public-landing/buddha.png +0 -0
- package/public-landing/create.html +868 -0
- package/public-landing/index.html +168 -0
- package/scripts/bongos-mcp.js +28 -0
- package/scripts/cron/style_guide_audit.sh +134 -0
- package/scripts/discord/README.md +52 -0
- package/scripts/discord/lib.js +80 -0
- package/scripts/discord/post.js +51 -0
- package/scripts/gds/CLAUDE.md +144 -0
- package/scripts/gds/abandon.js +58 -0
- package/scripts/gds/adopt-detect.js +123 -0
- package/scripts/gds/adopt-import.js +111 -0
- package/scripts/gds/adopt-preflight.js +121 -0
- package/scripts/gds/api.js +78 -0
- package/scripts/gds/architect-audit.js +288 -0
- package/scripts/gds/art-stage.js +152 -0
- package/scripts/gds/audit-authorship.sh +243 -0
- package/scripts/gds/audit-deps.js +121 -0
- package/scripts/gds/audit-exports.js +128 -0
- package/scripts/gds/audit-replay.sh +161 -0
- package/scripts/gds/audit-ships.js +251 -0
- package/scripts/gds/autonomy-gate.js +135 -0
- package/scripts/gds/backfill-cost.js +165 -0
- package/scripts/gds/backfill-sessions.js +351 -0
- package/scripts/gds/backfill-task-rewards.js +408 -0
- package/scripts/gds/backup.js +94 -0
- package/scripts/gds/bfg-principal-token.js +65 -0
- package/scripts/gds/box-auth-check.js +160 -0
- package/scripts/gds/box-connect-lib.js +453 -0
- package/scripts/gds/box.js +1258 -0
- package/scripts/gds/build-bongos.js +94 -0
- package/scripts/gds/capture.js +123 -0
- package/scripts/gds/cf-tunnel.js +419 -0
- package/scripts/gds/ci-grade.js +82 -0
- package/scripts/gds/claim-recall.js +112 -0
- package/scripts/gds/claim.js +333 -0
- package/scripts/gds/classify-discipline.js +153 -0
- package/scripts/gds/claude-materialize.js +176 -0
- package/scripts/gds/cleanup-orphans.js +74 -0
- package/scripts/gds/cli-lib.js +518 -0
- package/scripts/gds/code.js +101 -0
- package/scripts/gds/codemod-rename-src-gds.js +145 -0
- package/scripts/gds/conductor-dispatch.js +426 -0
- package/scripts/gds/context-pack.js +228 -0
- package/scripts/gds/coreB-carve-proof.sh +716 -0
- package/scripts/gds/cost.js +47 -0
- package/scripts/gds/db-backup-nightly.sh +160 -0
- package/scripts/gds/db-backup-offsite.sh +152 -0
- package/scripts/gds/demote.js +40 -0
- package/scripts/gds/design-sync.js +62 -0
- package/scripts/gds/diagnose-achievements.js +118 -0
- package/scripts/gds/diagram-facts.js +319 -0
- package/scripts/gds/discipline-modes.json +25 -0
- package/scripts/gds/discord-channels.js +66 -0
- package/scripts/gds/do-api.js +176 -0
- package/scripts/gds/docs-entropy.js +403 -0
- package/scripts/gds/doctor.js +389 -0
- package/scripts/gds/feedback-latest.js +94 -0
- package/scripts/gds/fetch-art-key.js +106 -0
- package/scripts/gds/fetch-sound-prefs.js +88 -0
- package/scripts/gds/figma-design-sync.js +61 -0
- package/scripts/gds/fitness.js +1446 -0
- package/scripts/gds/gate-review.js +322 -0
- package/scripts/gds/gating.js +325 -0
- package/scripts/gds/gds-db-backup.service +24 -0
- package/scripts/gds/gds-db-backup.timer +20 -0
- package/scripts/gds/gds-db-offsite.service +29 -0
- package/scripts/gds/gds-db-offsite.timer +18 -0
- package/scripts/gds/gen-api-client.js +508 -0
- package/scripts/gds/gen-api-docs.js +1037 -0
- package/scripts/gds/gen-atlas.js +366 -0
- package/scripts/gds/gen-diagrams.js +608 -0
- package/scripts/gds/gen-file-map.js +196 -0
- package/scripts/gds/gen-repo-map.js +519 -0
- package/scripts/gds/gen-session-index.js +210 -0
- package/scripts/gds/git-merge-regen.js +147 -0
- package/scripts/gds/grade-smoke.js +205 -0
- package/scripts/gds/hooks/pre-push.js +169 -0
- package/scripts/gds/http-api-client.js +88 -0
- package/scripts/gds/init.js +903 -0
- package/scripts/gds/install-git-hooks.js +114 -0
- package/scripts/gds/key-card.js +213 -0
- package/scripts/gds/key-status.js +126 -0
- package/scripts/gds/land-watch.js +168 -0
- package/scripts/gds/learning-capture.js +145 -0
- package/scripts/gds/lib.sh +44 -0
- package/scripts/gds/linkify-refs.js +473 -0
- package/scripts/gds/local-preview-lib.js +159 -0
- package/scripts/gds/local-preview.js +95 -0
- package/scripts/gds/login.js +225 -0
- package/scripts/gds/main-audit.js +279 -0
- package/scripts/gds/me.js +88 -0
- package/scripts/gds/memory-map.js +174 -0
- package/scripts/gds/merge-lock.js +71 -0
- package/scripts/gds/migration-namespace.js +200 -0
- package/scripts/gds/mirror-lineage-check.js +319 -0
- package/scripts/gds/mirror-redact.js +305 -0
- package/scripts/gds/module.js +482 -0
- package/scripts/gds/newcomer-floor.config.json +13 -0
- package/scripts/gds/newcomer-floor.js +415 -0
- package/scripts/gds/newcomer-floor.templates.json +86 -0
- package/scripts/gds/newcomer-floor.test.js +235 -0
- package/scripts/gds/next-number.js +163 -0
- package/scripts/gds/oauth-secret.js +197 -0
- package/scripts/gds/onboard.js +217 -0
- package/scripts/gds/onboarding-analyze.js +226 -0
- package/scripts/gds/onboarding-config.js +178 -0
- package/scripts/gds/onboarding-ship.js +92 -0
- package/scripts/gds/package-core.js +684 -0
- package/scripts/gds/paste-token.js +131 -0
- package/scripts/gds/portability-smoke-art.sh +85 -0
- package/scripts/gds/portability-smoke-memory.sh +147 -0
- package/scripts/gds/provision.js +1324 -0
- package/scripts/gds/publish-manifest.js +307 -0
- package/scripts/gds/pulse.js +309 -0
- package/scripts/gds/push-main.js +45 -0
- package/scripts/gds/read-session-export.js +359 -0
- package/scripts/gds/reauth.js +149 -0
- package/scripts/gds/recall.js +135 -0
- package/scripts/gds/release.js +71 -0
- package/scripts/gds/render-ideas.js +173 -0
- package/scripts/gds/repo-metrics.js +363 -0
- package/scripts/gds/resolve-skill-model.js +57 -0
- package/scripts/gds/run-routine.js +197 -0
- package/scripts/gds/run-unit-tests.js +178 -0
- package/scripts/gds/sandbox-stage.js +653 -0
- package/scripts/gds/search-ingest-db.js +209 -0
- package/scripts/gds/search-ingest-md.js +225 -0
- package/scripts/gds/security-baseline-check.sh +180 -0
- package/scripts/gds/seed-adopt-tasks.js +75 -0
- package/scripts/gds/seed-api-contract-goal-tasks.js +141 -0
- package/scripts/gds/seed-bongos-app-tasks.js +294 -0
- package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +81 -0
- package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +100 -0
- package/scripts/gds/seed-bongos-goal-hierarchy-tasks.js +307 -0
- package/scripts/gds/seed-bongos-module-system-tasks.js +346 -0
- package/scripts/gds/seed-bongos-tasks.js +214 -0
- package/scripts/gds/seed-gds-v4-tasks.js +624 -0
- package/scripts/gds/seed-governance-tasks.js +340 -0
- package/scripts/gds/seed-medusa-tasks.js +440 -0
- package/scripts/gds/seed-module-upstreaming.js +219 -0
- package/scripts/gds/seed-productization-tasks.js +235 -0
- package/scripts/gds/seed-provisioning-tasks.js +83 -0
- package/scripts/gds/seed-staging.sh +104 -0
- package/scripts/gds/seed-v2-world-tasks.js +283 -0
- package/scripts/gds/seed-v3-tasks.js +1981 -0
- package/scripts/gds/session-cost.js +393 -0
- package/scripts/gds/session-digest.js +179 -0
- package/scripts/gds/session-eval.js +576 -0
- package/scripts/gds/session.js +404 -0
- package/scripts/gds/setup.js +504 -0
- package/scripts/gds/shell.js +100 -0
- package/scripts/gds/ship.js +3618 -0
- package/scripts/gds/smoke-batch-claim.sh +213 -0
- package/scripts/gds/smoke-batch-release.sh +296 -0
- package/scripts/gds/smoke-box.sh +150 -0
- package/scripts/gds/smoke-claim-consistency.sh +212 -0
- package/scripts/gds/smoke-dependencies.sh +84 -0
- package/scripts/gds/smoke-gds.js +125 -0
- package/scripts/gds/smoke-write.sh +168 -0
- package/scripts/gds/start.js +782 -0
- package/scripts/gds/status.js +365 -0
- package/scripts/gds/triage.js +366 -0
- package/scripts/gds/upgrade.js +421 -0
- package/scripts/gds/validate-design.js +254 -0
- package/scripts/gds/version-close.js +549 -0
- package/scripts/migrate.sh +183 -0
- package/scripts/migrate_cost_ledger.sh +178 -0
- package/scripts/public-mirror-export.js +291 -0
- package/scripts/render-diagrams.sh +88 -0
- package/scripts/security/dep-audit.js +276 -0
- package/scripts/setup-builder.js +274 -0
- package/scripts/setup-builder.sh +28 -0
- package/scripts/snapshots/backfill-history.mjs +292 -0
- package/scripts/snapshots/maybe-render-on-deploy.sh +66 -0
- package/scripts/snapshots/render-pre-art-eras.mjs +329 -0
- package/scripts/snapshots/render-world.mjs +322 -0
- package/scripts/status-mirror-sync.js +192 -0
- package/scripts/status-probe.mjs +185 -0
- package/server.js +212 -0
- package/src/asset-version.js +71 -0
- package/src/bongos/CLAUDE.md +64 -0
- package/src/bongos/api-errors.js +281 -0
- package/src/bongos/api-path-404.js +67 -0
- package/src/bongos/api-prefix.js +38 -0
- package/src/bongos/app-pair.js +172 -0
- package/src/bongos/auth.js +979 -0
- package/src/bongos/cascade-dispatch.js +123 -0
- package/src/bongos/db-kernel.js +252 -0
- package/src/bongos/db.js +911 -0
- package/src/bongos/goal-scope-check.js +120 -0
- package/src/bongos/hierarchy-config.js +189 -0
- package/src/bongos/live-channel.js +145 -0
- package/src/bongos/llm-cache.js +260 -0
- package/src/bongos/llm-pricing.js +220 -0
- package/src/bongos/metrics.js +286 -0
- package/src/bongos/middleware/audit.js +274 -0
- package/src/bongos/middleware/error-envelope.js +93 -0
- package/src/bongos/middleware/rate-limit.js +195 -0
- package/src/bongos/module-scope-map.js +271 -0
- package/src/bongos/optimizer.js +166 -0
- package/src/bongos/path-match.js +47 -0
- package/src/bongos/permission-path-check.js +248 -0
- package/src/bongos/pool.js +55 -0
- package/src/bongos/repo-info.js +91 -0
- package/src/bongos/route-rank-check.js +420 -0
- package/src/bongos/routes/CLAUDE.md +43 -0
- package/src/bongos/routes/_helpers.js +369 -0
- package/src/bongos/routes/audit-log.js +59 -0
- package/src/bongos/routes/auth.js +755 -0
- package/src/bongos/routes/backup.js +104 -0
- package/src/bongos/routes/builders.js +526 -0
- package/src/bongos/routes/healthz.js +16 -0
- package/src/bongos/routes/instance.js +129 -0
- package/src/bongos/routes/live.js +125 -0
- package/src/bongos/routes/llm-cache.js +119 -0
- package/src/bongos/routes/me.js +380 -0
- package/src/bongos/routes/modules.js +131 -0
- package/src/bongos/routes/optimizer.js +54 -0
- package/src/bongos/routes/public.js +476 -0
- package/src/bongos/routes/security.js +207 -0
- package/src/bongos/routes.js +166 -0
- package/src/bongos/secret-box.js +177 -0
- package/src/bongos/sensitive-surfaces.js +30 -0
- package/src/bongos/serve-internal.js +889 -0
- package/src/bongos/uptime-poller.js +90 -0
- package/src/bongos-downloads.js +70 -0
- package/src/branding.js +182 -0
- package/src/build-info.js +77 -0
- package/src/devbox-downloads.js +67 -0
- package/src/instance-config.js +200 -0
- package/src/module-api.js +366 -0
- package/src/module-loader/loader.js +268 -0
- package/src/module-loader/manifest-schema.js +140 -0
- package/src/module-loader/provenance.js +28 -0
- package/src/module-loader/semver.js +100 -0
- package/src/module-seams.js +291 -0
- package/src/modules.js +254 -0
- package/src/platform-server.js +135 -0
- package/src/ui/adapters/claude-design/index.js +333 -0
- package/src/ui/adapters/figma/index.js +328 -0
- package/tests/abandon_task.mjs +138 -0
- package/tests/achievements_reconcile.mjs +167 -0
- package/tests/adopt_detect.mjs +141 -0
- package/tests/adopt_import.mjs +132 -0
- package/tests/adopt_preflight.mjs +105 -0
- package/tests/anti_grid.mjs +89 -0
- package/tests/api_client.mjs +231 -0
- package/tests/api_docs.mjs +283 -0
- package/tests/api_error_envelope_buildcheck.mjs +56 -0
- package/tests/api_error_envelope_middleware.mjs +99 -0
- package/tests/api_error_registry.mjs +108 -0
- package/tests/api_pagination_contract.mjs +51 -0
- package/tests/api_path_404.mjs +96 -0
- package/tests/app_pair.mjs +168 -0
- package/tests/architect.mjs +140 -0
- package/tests/art_key.mjs +121 -0
- package/tests/art_stage.mjs +121 -0
- package/tests/asset_version.mjs +94 -0
- package/tests/atlas.mjs +69 -0
- package/tests/audit_deps.mjs +74 -0
- package/tests/audit_middleware.mjs +385 -0
- package/tests/auth_admission_gate.mjs +164 -0
- package/tests/auth_anthropic_identity.mjs +95 -0
- package/tests/auth_duplicate_cookie.mjs +56 -0
- package/tests/auth_error_brand.mjs +77 -0
- package/tests/auth_flow_slice1.mjs +223 -0
- package/tests/auth_inactive_builder.mjs +94 -0
- package/tests/auth_page_gate.mjs +92 -0
- package/tests/auth_session_ttl.mjs +155 -0
- package/tests/autonomous_fit_protected_paths.mjs +115 -0
- package/tests/autonomy_gate.mjs +85 -0
- package/tests/autotile_variants.mjs +256 -0
- package/tests/autotile_xverify.mjs +133 -0
- package/tests/backfill_sessions.mjs +101 -0
- package/tests/backfill_task_rewards.mjs +152 -0
- package/tests/backup_cli.mjs +104 -0
- package/tests/bfg.mjs +327 -0
- package/tests/bfg_write.mjs +423 -0
- package/tests/bongos_box_connect.mjs +89 -0
- package/tests/bongos_dispatch.mjs +74 -0
- package/tests/bongos_downloads.mjs +118 -0
- package/tests/bongos_login.mjs +34 -0
- package/tests/box_access.mjs +186 -0
- package/tests/box_auth_check.mjs +114 -0
- package/tests/box_code_staleness.mjs +116 -0
- package/tests/box_connect_e2e.mjs +196 -0
- package/tests/box_cost.mjs +70 -0
- package/tests/box_dns_repoint.mjs +151 -0
- package/tests/box_host_keys.mjs +102 -0
- package/tests/box_onboard.mjs +317 -0
- package/tests/box_scope_session.mjs +115 -0
- package/tests/box_ship_permissions.mjs +71 -0
- package/tests/box_terminal_ssrf.mjs +90 -0
- package/tests/boxes.mjs +1255 -0
- package/tests/branding.mjs +88 -0
- package/tests/bug_attachments.mjs +189 -0
- package/tests/build_info.mjs +88 -0
- package/tests/builder_needs.mjs +99 -0
- package/tests/cap_newcomer_tasks.mjs +114 -0
- package/tests/cascade-dispatch.mjs +95 -0
- package/tests/cf_tunnel.mjs +459 -0
- package/tests/claim_recall.mjs +150 -0
- package/tests/claims_bind_session.mjs +47 -0
- package/tests/claude_materialize.mjs +148 -0
- package/tests/cli_box_scope.mjs +52 -0
- package/tests/cli_lib_formatters.mjs +87 -0
- package/tests/cli_token_reissue.mjs +147 -0
- package/tests/client_bundle_route.mjs +47 -0
- package/tests/cloud_bongos_pack.mjs +85 -0
- package/tests/conductor.mjs +496 -0
- package/tests/confirm_attribution.mjs +156 -0
- package/tests/conflict_resolve.mjs +462 -0
- package/tests/context_pack.mjs +240 -0
- package/tests/cost.mjs +94 -0
- package/tests/cost_audit.mjs +122 -0
- package/tests/cost_budget_status.mjs +78 -0
- package/tests/cost_reconcile.mjs +102 -0
- package/tests/cost_summary_shape.mjs +94 -0
- package/tests/credit_grant.mjs +376 -0
- package/tests/criterion_progress.mjs +220 -0
- package/tests/criterion_proposal.mjs +109 -0
- package/tests/criterion_ref_parse.mjs +53 -0
- package/tests/currency_label.mjs +119 -0
- package/tests/day_cycle.mjs +197 -0
- package/tests/dependencies_migration.mjs +77 -0
- package/tests/dependencies_polymorphic.mjs +212 -0
- package/tests/deploy_instance.mjs +78 -0
- package/tests/devbox_downloads.mjs +122 -0
- package/tests/diff_derived_signals.mjs +115 -0
- package/tests/discord_approvals.mjs +174 -0
- package/tests/discord_autojoin.mjs +158 -0
- package/tests/discord_bot.mjs +94 -0
- package/tests/discord_bugs.mjs +297 -0
- package/tests/discord_channels.mjs +337 -0
- package/tests/discord_foundation.mjs +76 -0
- package/tests/discord_inbound.mjs +190 -0
- package/tests/discord_message_buffer.mjs +87 -0
- package/tests/discord_oauth.mjs +55 -0
- package/tests/discord_reaction.mjs +170 -0
- package/tests/discord_role_sync.mjs +151 -0
- package/tests/display_name.mjs +123 -0
- package/tests/dns_preflight.mjs +74 -0
- package/tests/event_sound_prefs.mjs +194 -0
- package/tests/eviction_policy.mjs +279 -0
- package/tests/figma_adapter.mjs +199 -0
- package/tests/file_map.mjs +91 -0
- package/tests/first_admin_bootstrap.mjs +40 -0
- package/tests/fitness.mjs +435 -0
- package/tests/fitness_two_root.mjs +104 -0
- package/tests/fixtures/session-506-digest.json +34 -0
- package/tests/gate_approvals.mjs +451 -0
- package/tests/gate_review.mjs +152 -0
- package/tests/git_merge_regen.mjs +151 -0
- package/tests/github_push_ancestry.mjs +119 -0
- package/tests/github_push_land_proof.mjs +127 -0
- package/tests/github_push_merge_driver.mjs +175 -0
- package/tests/goal_abuse_matrix.mjs +187 -0
- package/tests/goal_achievement.mjs +146 -0
- package/tests/goal_conflicts.mjs +305 -0
- package/tests/goal_dependencies_read.mjs +73 -0
- package/tests/goal_member_roles.mjs +420 -0
- package/tests/goal_membership_requests.mjs +332 -0
- package/tests/goal_routes.mjs +203 -0
- package/tests/goal_scope_check.mjs +167 -0
- package/tests/goal_tier.mjs +312 -0
- package/tests/goal_wall_proof.mjs +112 -0
- package/tests/grade_attempts.mjs +73 -0
- package/tests/grade_attribution.mjs +117 -0
- package/tests/grade_diff_hash.mjs +191 -0
- package/tests/grade_server_authoritative.mjs +305 -0
- package/tests/grade_unavailable_display.mjs +66 -0
- package/tests/grader.mjs +1960 -0
- package/tests/grader_bypass.mjs +57 -0
- package/tests/grader_panel.mjs +252 -0
- package/tests/grader_prompt_fencing.mjs +192 -0
- package/tests/helpers.mjs +52 -0
- package/tests/hierarchy-config.mjs +81 -0
- package/tests/init.mjs +463 -0
- package/tests/instance_config.mjs +76 -0
- package/tests/instance_manifest.mjs +110 -0
- package/tests/interaction_prefs.mjs +72 -0
- package/tests/key-card.mjs +110 -0
- package/tests/key-status.mjs +45 -0
- package/tests/land_watch.mjs +115 -0
- package/tests/lifecycle-card.mjs +145 -0
- package/tests/lifecycle_breakdown_view.mjs +236 -0
- package/tests/linkify_refs.mjs +264 -0
- package/tests/live_channel.mjs +128 -0
- package/tests/live_sse.mjs +122 -0
- package/tests/llm-cache-route.mjs +110 -0
- package/tests/llm-cache.mjs +140 -0
- package/tests/llm-pricing.mjs +152 -0
- package/tests/local_preview.mjs +136 -0
- package/tests/main_audit.mjs +137 -0
- package/tests/memory_isolation.mjs +431 -0
- package/tests/memory_map.mjs +107 -0
- package/tests/memory_pull.mjs +429 -0
- package/tests/merge_lease.mjs +100 -0
- package/tests/merge_lock.mjs +312 -0
- package/tests/metrics.mjs +147 -0
- package/tests/migration_allocation.mjs +146 -0
- package/tests/migration_namespace.mjs +185 -0
- package/tests/migrations_fresh_replay_guard.mjs +38 -0
- package/tests/mirror_lineage_fulltree.mjs +45 -0
- package/tests/mirror_lineage_proof.mjs +72 -0
- package/tests/mirror_redact.mjs +193 -0
- package/tests/model_alloc_prefs.mjs +63 -0
- package/tests/module-scope-map.mjs +88 -0
- package/tests/module_api.mjs +110 -0
- package/tests/module_cli.mjs +292 -0
- package/tests/module_contributions.mjs +148 -0
- package/tests/module_loader.mjs +286 -0
- package/tests/module_manifest.mjs +194 -0
- package/tests/module_owned_tests.mjs +105 -0
- package/tests/module_provenance.mjs +34 -0
- package/tests/module_route_rank.mjs +147 -0
- package/tests/module_seams.mjs +68 -0
- package/tests/modules.mjs +156 -0
- package/tests/modules_route.mjs +38 -0
- package/tests/newcomer_floor.mjs +17 -0
- package/tests/newcomer_restock.mjs +80 -0
- package/tests/next_number.mjs +154 -0
- package/tests/oauth_secret.mjs +60 -0
- package/tests/onboard.mjs +70 -0
- package/tests/onboarding_gate.mjs +267 -0
- package/tests/onboarding_observability.mjs +344 -0
- package/tests/onboarding_route_signals.mjs +175 -0
- package/tests/onboarding_state.mjs +346 -0
- package/tests/one_active_claim_per_session.mjs +111 -0
- package/tests/orphaned_claim_ship.mjs +135 -0
- package/tests/override_attribution.mjs +142 -0
- package/tests/override_request_ownership.mjs +235 -0
- package/tests/package_core.mjs +435 -0
- package/tests/parallel-load.mjs +402 -0
- package/tests/path_match.mjs +62 -0
- package/tests/permission_path.mjs +151 -0
- package/tests/platform_boot.mjs +167 -0
- package/tests/pre_compact.mjs +60 -0
- package/tests/preview_server.mjs +127 -0
- package/tests/profile_route.mjs +197 -0
- package/tests/provision.mjs +805 -0
- package/tests/provisioning_github_app_routes.mjs +98 -0
- package/tests/public_mirror_export.mjs +124 -0
- package/tests/public_task_resolver.mjs +112 -0
- package/tests/publish_branch_route.mjs +422 -0
- package/tests/publish_manifest.mjs +184 -0
- package/tests/publish_reconciler.mjs +728 -0
- package/tests/rank_gate.mjs +463 -0
- package/tests/rate_limit_public.mjs +217 -0
- package/tests/read_session_export.mjs +89 -0
- package/tests/recall_cli.mjs +82 -0
- package/tests/recall_hints.mjs +119 -0
- package/tests/recent_shipped_window.mjs +80 -0
- package/tests/regrade_eligibility.mjs +202 -0
- package/tests/render_prefs.mjs +122 -0
- package/tests/repo_map.mjs +92 -0
- package/tests/reward_gate.mjs +284 -0
- package/tests/route_rank_check.mjs +243 -0
- package/tests/route_validation.mjs +490 -0
- package/tests/routine_timers.mjs +72 -0
- package/tests/rubric_fixtures.mjs +140 -0
- package/tests/run_routine.mjs +69 -0
- package/tests/sandbox_stage.mjs +582 -0
- package/tests/scrubber_corpus.mjs +257 -0
- package/tests/search_chunker.mjs +209 -0
- package/tests/search_ingest.mjs +96 -0
- package/tests/search_ingest_db.mjs +88 -0
- package/tests/search_isolation.mjs +204 -0
- package/tests/search_route.mjs +95 -0
- package/tests/secret_box.mjs +189 -0
- package/tests/security_docs.mjs +186 -0
- package/tests/security_route.mjs +108 -0
- package/tests/served_paths_shipped.mjs +118 -0
- package/tests/session-cards.mjs +142 -0
- package/tests/session_506_regression.mjs +69 -0
- package/tests/session_caps.mjs +238 -0
- package/tests/session_cost.mjs +133 -0
- package/tests/session_digest.mjs +73 -0
- package/tests/session_eval.mjs +386 -0
- package/tests/session_index.mjs +105 -0
- package/tests/session_records.mjs +369 -0
- package/tests/session_search.mjs +78 -0
- package/tests/session_start_freshness.mjs +123 -0
- package/tests/setup_smoke.mjs +154 -0
- package/tests/ship_autolinkify.mjs +60 -0
- package/tests/ship_automerge_injection.mjs +174 -0
- package/tests/ship_broadcast_routing.mjs +125 -0
- package/tests/ship_broadcast_server.mjs +175 -0
- package/tests/ship_card.mjs +280 -0
- package/tests/ship_ci_deploy.mjs +374 -0
- package/tests/ship_preflight.mjs +368 -0
- package/tests/ship_premerge.mjs +75 -0
- package/tests/ship_resume.mjs +129 -0
- package/tests/ship_upload_skip.mjs +89 -0
- package/tests/ship_zero_commit.mjs +60 -0
- package/tests/single_host_hall.mjs +98 -0
- package/tests/skill_prefs.mjs +150 -0
- package/tests/smoke_preflight.mjs +66 -0
- package/tests/snapshot_picker.mjs +233 -0
- package/tests/sound_prefs.mjs +198 -0
- package/tests/sprite_facing.mjs +35 -0
- package/tests/status-probe.mjs +89 -0
- package/tests/status_backfill.mjs +94 -0
- package/tests/stop_refcheck.mjs +127 -0
- package/tests/streak.mjs +175 -0
- package/tests/subdomain_auth.mjs +58 -0
- package/tests/task_classifier_vocab.mjs +41 -0
- package/tests/task_create_idempotency.mjs +96 -0
- package/tests/task_goal_link.mjs +93 -0
- package/tests/task_ownership_gate.mjs +125 -0
- package/tests/terrain_picker.mjs +298 -0
- package/tests/touches_overlap.mjs +75 -0
- package/tests/triage_development.mjs +140 -0
- package/tests/turn_in_place.mjs +280 -0
- package/tests/upgrade.mjs +357 -0
- package/tests/verify_task_guard.mjs +64 -0
- package/tests/version_close.mjs +76 -0
- package/tests/versions_route.mjs +93 -0
- package/tests/walkability.mjs +188 -0
- package/tests/wandering_prefs.mjs +176 -0
- package/tests/worktree_disambiguation.mjs +105 -0
- package/tests/worktree_guard.mjs +90 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// scripts/gds/gate-review.js ā the automatic gate-surface gatekeeper (ADR 0058).
|
|
5
|
+
//
|
|
6
|
+
// WHY. In deploy mode 'ci' (config/deploy.json) PRs auto-merge on green checks and
|
|
7
|
+
// main auto-deploys to prod. CODEOWNERS (owner review on gate surfaces) was the ONLY
|
|
8
|
+
// human in that loop ā and the bottleneck. The owner chose a RANK-BASED trust model
|
|
9
|
+
// (2026-06-15): trust senior builders to auto-merge routine sensitive work, but keep a
|
|
10
|
+
// HARD, rank-independent floor for the gate's own machinery + deploy switch.
|
|
11
|
+
//
|
|
12
|
+
// WHAT. This is a PURE, deterministic classifier over the PR diff-as-DATA. It runs in
|
|
13
|
+
// CI (.github/workflows/gate-review.yml) from the TRUSTED BASE copy (the workflow
|
|
14
|
+
// overlays scripts/+src/ from origin/main before running, so a PR cannot edit the
|
|
15
|
+
// analyzer to pass itself). It emits one of three verdicts:
|
|
16
|
+
//
|
|
17
|
+
// PASS ā no gate surface touched, OR only AUTO pure-removal surfaces
|
|
18
|
+
// (un-mute a test, narrow the secret-scanner allowlist). Auto-merge.
|
|
19
|
+
// NEEDS_TRUST ā a sensitive-but-routine gate surface (migrations, deps, routes,
|
|
20
|
+
// server, ship plumbing, boxes, auth-adjacent, doctrine docs). The
|
|
21
|
+
// workflow auto-merges this IFF the author is Metic+ (rank trust) or
|
|
22
|
+
// the owner approved; otherwise it escalates.
|
|
23
|
+
// ESCALATE ā the HARD FLOOR: the gate's own machinery, the deploy switch, branch
|
|
24
|
+
// protection, CI workflows, the rank/permission enforcement, the
|
|
25
|
+
// grader, the deploy-time audit, or the hooks the gate ships through.
|
|
26
|
+
// Rank-trust does NOT apply ā this ALWAYS pings the owner. Also any
|
|
27
|
+
// pre-flight rejection (symlink / non-ASCII path / oversize / analyzer
|
|
28
|
+
// error) ā ESCALATE, fail-closed.
|
|
29
|
+
//
|
|
30
|
+
// The gate-surface SET is the authoritative src/bongos/permission-path-check.PROTECTED_GLOBS
|
|
31
|
+
// (imported, NEVER hand-retyped ā the red-team's #1 finding). The classifier only
|
|
32
|
+
// decides, per touched surface, whether it is HARD-FLOOR, NEEDS_TRUST, or AUTO. Anything
|
|
33
|
+
// matched-protected-but-unclassified defaults to ESCALATE (no allow-by-omission).
|
|
34
|
+
//
|
|
35
|
+
// The pure core (classifyChanges) takes diff data as arguments and is exhaustively
|
|
36
|
+
// unit-tested (tests/gate_review.mjs) with the red-team evasion matrix. The CLI wrapper
|
|
37
|
+
// (main) gathers the real diff via git and applies GATE_REPORT_ONLY / exit codes.
|
|
38
|
+
|
|
39
|
+
const { execFileSync } = require('node:child_process');
|
|
40
|
+
const fs = require('node:fs');
|
|
41
|
+
const permPath = require('../../src/bongos/permission-path-check');
|
|
42
|
+
const { PROTECTED_GLOBS, globToRegExp } = permPath;
|
|
43
|
+
|
|
44
|
+
// --- HARD FLOOR (rank-independent ESCALATE) -------------------------------------------
|
|
45
|
+
// A subset of PROTECTED_GLOBS: the surfaces that, if a compromised/injected senior
|
|
46
|
+
// session auto-merged them, would DISABLE the safety system itself or the deploy gate.
|
|
47
|
+
// Kept as globs so the matcher is identical to permission-path-check (trailing '/' =
|
|
48
|
+
// subtree). The owner can promote a NEEDS_TRUST surface here with a one-line edit (which
|
|
49
|
+
// is itself a hard-floor change to this file ā escalates ā correct).
|
|
50
|
+
const HARD_FLOOR_GLOBS = [
|
|
51
|
+
'scripts/gds/gate-review.js', // self
|
|
52
|
+
'src/bongos/permission-path-check.js', // defines the protected set this gate reads
|
|
53
|
+
'src/bongos/route-rank-check.js', // the route-gate auditor
|
|
54
|
+
'src/bongos/auth.js', // requireRank / requireBuilder ā the enforcement point
|
|
55
|
+
'modules/grading/grader.js', // BV1.R73: grading carved to modules/grading/
|
|
56
|
+
'modules/grading/grader-workers/',
|
|
57
|
+
'modules/grading/grader-rubric.json',
|
|
58
|
+
'scripts/gds/ci-grade.js', // CI grade-gate driver (task 1143 ā red-team #3)
|
|
59
|
+
'scripts/gds/grade-smoke.js', // grade-smoke driver
|
|
60
|
+
'scripts/gds/conductor-dispatch.js', // mid-flight grader dispatch
|
|
61
|
+
'scripts/gds/main-audit.js', // the authoritative deploy-time audit (the backstop)
|
|
62
|
+
'scripts/gds/push-main.js', // the sanctioned main-push carrying the override
|
|
63
|
+
'scripts/gds/run-unit-tests.js', // the test selector (AUTO pure-removal handled first)
|
|
64
|
+
'scripts/gds/install-git-hooks.js',
|
|
65
|
+
'scripts/gds/hooks/',
|
|
66
|
+
'scripts/migrate.sh',
|
|
67
|
+
'scripts/deploy/',
|
|
68
|
+
'config/deploy.json', // the laptop/ci/bypass deploy switch
|
|
69
|
+
'infra/', // branch-protection.json + deploy substrate
|
|
70
|
+
'.github/', // CI gates: gate-review.yml, deploy-prod.yml, secret scan, grade gate
|
|
71
|
+
'CODEOWNERS',
|
|
72
|
+
'.husky/', // pre-push/pre-commit gate delivery (secrets-allowlist.txt is AUTO, checked first)
|
|
73
|
+
'.claude/hooks/',
|
|
74
|
+
'.claude/settings.json',
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
// db.js is HARD-FLOOR only for the rank-tier brain (REQUIRES_RANK_TIER); every other
|
|
78
|
+
// db.js change is NEEDS_TRUST (it is a huge, routinely-edited module ā file-level
|
|
79
|
+
// hard-flooring it would ping the owner for ordinary query work). This is the one
|
|
80
|
+
// content-level rule; everything else is path-level.
|
|
81
|
+
const DB_JS = 'src/bongos/db.js';
|
|
82
|
+
const RANK_TIER_RE = /REQUIRES_RANK_TIER\s*=\s*\{[\s\S]*?\}/;
|
|
83
|
+
|
|
84
|
+
// AUTO pure-removal surfaces ā a NARROWING-only edit can only STRENGTHEN the gate, so
|
|
85
|
+
// it may auto-pass for ANY author. Any non-narrowing edit falls through to its glob
|
|
86
|
+
// classification (run-unit-tests.js ā HARD FLOOR; secrets-allowlist.txt ā .husky/ HARD FLOOR).
|
|
87
|
+
const AUTO_NARROWING = {
|
|
88
|
+
'scripts/gds/run-unit-tests.js': certifyRunUnitTestsNarrowing,
|
|
89
|
+
'.husky/secrets-allowlist.txt': certifyAllowlistNarrowing,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const COMPILED_HARD = HARD_FLOOR_GLOBS.map((g) => ({ glob: g, re: globToRegExp(g) }));
|
|
93
|
+
const matchesHardFloor = (f) => COMPILED_HARD.some((c) => c.re.test(f));
|
|
94
|
+
|
|
95
|
+
// A path is "protected" per the authoritative module.
|
|
96
|
+
const protectedRe = PROTECTED_GLOBS.map((g) => ({ glob: g, re: globToRegExp(g) }));
|
|
97
|
+
const matchesProtected = (f) => protectedRe.some((c) => c.re.test(f));
|
|
98
|
+
|
|
99
|
+
// Only [\x20-\x7e] path chars, NFC-stable, no leading/trailing whitespace. Defeats the
|
|
100
|
+
// unicode-homoglyph + whitespace-alias evasions (red-team Holes 6/8).
|
|
101
|
+
function isCanonicalPath(p) {
|
|
102
|
+
return typeof p === 'string' && p.length > 0 && /^[\x20-\x7e]+$/.test(p)
|
|
103
|
+
&& p === p.normalize('NFC') && p === p.trim();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// AUTO certifier: run-unit-tests.js may auto-pass ONLY if its sole semantic change is
|
|
107
|
+
// REMOVING entries from INTEGRATION/KNOWN_FAILING (un-muting tests) ā never adding, and
|
|
108
|
+
// the rest of the file byte-identical modulo those two set literals.
|
|
109
|
+
function certifyRunUnitTestsNarrowing(base, head) {
|
|
110
|
+
if (base == null || head == null) return { pass: false, reason: 'added/removed wholesale ā not a narrowing edit' };
|
|
111
|
+
const setOf = (t, name) => {
|
|
112
|
+
const m = new RegExp(`const ${name} = new Set\\(\\[([\\s\\S]*?)\\]\\)`).exec(t);
|
|
113
|
+
if (!m) return null;
|
|
114
|
+
return new Set([...m[1].matchAll(/['"]([^'"]+)['"]/g)].map((x) => x[1]));
|
|
115
|
+
};
|
|
116
|
+
const strip = (t) => t.replace(/const (INTEGRATION|KNOWN_FAILING) = new Set\(\[[\s\S]*?\]\)/g, 'SET');
|
|
117
|
+
if (strip(base) !== strip(head)) return { pass: false, reason: 'non-set code changed in run-unit-tests.js' };
|
|
118
|
+
for (const name of ['INTEGRATION', 'KNOWN_FAILING']) {
|
|
119
|
+
const b = setOf(base, name), h = setOf(head, name);
|
|
120
|
+
if (!b || !h) return { pass: false, reason: `cannot parse ${name} set ā fail-closed` };
|
|
121
|
+
for (const x of h) if (!b.has(x)) return { pass: false, reason: `${name} ADDED '${x}' (muting a test)` };
|
|
122
|
+
}
|
|
123
|
+
return { pass: true };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// AUTO certifier: secrets-allowlist.txt may auto-pass ONLY if its head line set is a
|
|
127
|
+
// subset of the base (removing/narrowing allowlist entries) ā never adding a new exclude.
|
|
128
|
+
function certifyAllowlistNarrowing(base, head) {
|
|
129
|
+
if (base == null || head == null) return { pass: false, reason: 'added/removed wholesale ā not a narrowing edit' };
|
|
130
|
+
const norm = (t) => new Set(t.split('\n').map((l) => l.trim()).filter((l) => l && !l.startsWith('#')));
|
|
131
|
+
const b = norm(base), h = norm(head);
|
|
132
|
+
for (const line of h) if (!b.has(line)) return { pass: false, reason: `allowlist ADDED/BROADENED: ${line}` };
|
|
133
|
+
return { pass: true };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ----------------------------------------------------------------------------------------
|
|
137
|
+
// PURE CORE. Inputs are diff DATA (no git, no fs) so the whole policy is unit-tested:
|
|
138
|
+
// files: [{ path, mode, deleted }] ā changed paths + git new-mode + delete flag
|
|
139
|
+
// blobAt: (which:'base'|'head', path) => string|null ā file content at base/head
|
|
140
|
+
// diffBytes: number ā total textual diff size
|
|
141
|
+
// Returns { verdict:'pass'|'needs_trust'|'escalate', escalations:[{path,reason}],
|
|
142
|
+
// needsTrust:[{path,reason}], autoPassed:[path], surfaces:[path] }.
|
|
143
|
+
// ----------------------------------------------------------------------------------------
|
|
144
|
+
const MAX_DIFF_BYTES = Number(process.env.GATE_MAX_DIFF_BYTES || 2 * 1024 * 1024);
|
|
145
|
+
|
|
146
|
+
function classifyChanges({ files, blobAt, diffBytes = 0 } = {}) {
|
|
147
|
+
const escalations = [];
|
|
148
|
+
const needsTrust = [];
|
|
149
|
+
const autoPassed = [];
|
|
150
|
+
const surfaces = [];
|
|
151
|
+
|
|
152
|
+
// --- Pre-flight, fail-closed (whole changed set) ---
|
|
153
|
+
for (const f of files || []) {
|
|
154
|
+
if (f.mode === '120000') escalations.push({ path: f.path, reason: 'symlink in diff ā refused (alias evasion)' });
|
|
155
|
+
if (!isCanonicalPath(f.path)) escalations.push({ path: String(f.path), reason: 'non-ASCII/whitespace path ā refused' });
|
|
156
|
+
}
|
|
157
|
+
if (diffBytes > MAX_DIFF_BYTES) {
|
|
158
|
+
escalations.push({ path: '<diff>', reason: `diff ${diffBytes}B exceeds ${MAX_DIFF_BYTES}B ā too large to certify` });
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
for (const f of files || []) {
|
|
162
|
+
const p = f.path;
|
|
163
|
+
if (!isCanonicalPath(p)) continue; // already escalated above
|
|
164
|
+
// A gate surface = the authoritative PROTECTED_GLOBS, OR a hard-floor glob (some
|
|
165
|
+
// floor paths ā gate-review.js itself, config/deploy.json, CODEOWNERS ā are also
|
|
166
|
+
// added to PROTECTED_GLOBS, but OR-ing keeps the gatekeeper correct even if a
|
|
167
|
+
// future hard-floor entry isn't yet in the shared list), OR a tests/*.mjs file.
|
|
168
|
+
const isProtected = matchesProtected(p) || matchesHardFloor(p);
|
|
169
|
+
const isTest = /^tests\/.+\.mjs$/.test(p);
|
|
170
|
+
if (!isProtected && !isTest) continue; // not a gate surface
|
|
171
|
+
|
|
172
|
+
surfaces.push(p);
|
|
173
|
+
|
|
174
|
+
// tests/*.mjs: deleting or shrinking a test silently weakens the suite ā NEEDS_TRUST
|
|
175
|
+
// (rank-trustable per the owner's model); adding/expanding is fine ā PASS.
|
|
176
|
+
if (isTest && !isProtected) {
|
|
177
|
+
if (f.deleted) { needsTrust.push({ path: p, reason: 'test file DELETED ā suite shrink' }); continue; }
|
|
178
|
+
const base = blobAt('base', p), head = blobAt('head', p);
|
|
179
|
+
if (base != null && head != null && head.length < base.length) {
|
|
180
|
+
needsTrust.push({ path: p, reason: 'test file SHRANK ā possible muting' });
|
|
181
|
+
}
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// AUTO pure-removal surfaces: certify a narrowing-only edit (any author).
|
|
186
|
+
if (Object.prototype.hasOwnProperty.call(AUTO_NARROWING, p)) {
|
|
187
|
+
const cert = AUTO_NARROWING[p](blobAt('base', p), blobAt('head', p));
|
|
188
|
+
if (cert.pass) { autoPassed.push(p); continue; }
|
|
189
|
+
// not a narrowing edit ā fall through to HARD FLOOR (both AUTO files are floor globs)
|
|
190
|
+
escalations.push({ path: p, reason: `AUTO surface failed narrowing cert (${cert.reason}) ā root-of-trust` });
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// db.js: HARD FLOOR only when the rank-tier brain changed; else NEEDS_TRUST.
|
|
195
|
+
if (p === DB_JS) {
|
|
196
|
+
const base = blobAt('base', p), head = blobAt('head', p);
|
|
197
|
+
const region = (t) => { const m = t == null ? null : RANK_TIER_RE.exec(t); return m ? m[0] : (t == null ? '<absent>' : '<no-region>'); };
|
|
198
|
+
if (base == null || head == null) { needsTrust.push({ path: p, reason: 'db.js added/removed' }); continue; }
|
|
199
|
+
if (region(base) !== region(head)) {
|
|
200
|
+
escalations.push({ path: p, reason: 'db.js REQUIRES_RANK_TIER (rank brain) changed ā root-of-trust' });
|
|
201
|
+
} else {
|
|
202
|
+
needsTrust.push({ path: p, reason: 'db.js change outside the rank-tier region' });
|
|
203
|
+
}
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// HARD FLOOR globs ā ESCALATE regardless of rank.
|
|
208
|
+
if (matchesHardFloor(p)) { escalations.push({ path: p, reason: 'gate machinery / deploy switch (hard floor) ā owner review required' }); continue; }
|
|
209
|
+
|
|
210
|
+
// Any other protected surface ā NEEDS_TRUST (rank-trustable).
|
|
211
|
+
needsTrust.push({ path: p, reason: 'sensitive gate surface ā auto-merges for Metic+ (rank trust)' });
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const verdict = escalations.length ? 'escalate' : (needsTrust.length ? 'needs_trust' : 'pass');
|
|
215
|
+
return { verdict, escalations, needsTrust, autoPassed, surfaces };
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Resolve the merge action from the verdict + the two trust signals (both injected by
|
|
219
|
+
// the workflow, never read by the pure classifier). RANK trust (server-attested Metic+)
|
|
220
|
+
// clears NEEDS_TRUST only; the HARD FLOOR (escalate) is cleared ONLY by an explicit
|
|
221
|
+
// owner review ā rank never bypasses it. An owner approval clears anything.
|
|
222
|
+
// pass ā 'pass'
|
|
223
|
+
// needs_trust ā 'pass' iff (rank-trusted OR owner-approved)
|
|
224
|
+
// escalate ā 'pass' iff owner-approved
|
|
225
|
+
function resolveAction({ verdict, trusted, ownerApproved }) {
|
|
226
|
+
if (verdict === 'pass') return 'pass';
|
|
227
|
+
if (verdict === 'escalate') return ownerApproved ? 'pass' : 'block';
|
|
228
|
+
return trusted || ownerApproved ? 'pass' : 'block';
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ----------------------------------------------------------------------------------------
|
|
232
|
+
// CLI wrapper ā gather the real diff and apply report-only / exit codes. Never returns 0
|
|
233
|
+
// on an analyzer error (fail-closed). The rank/owner-approval resolution for NEEDS_TRUST
|
|
234
|
+
// is provided by the workflow via GATE_AUTHOR_TRUSTED (set from the server-resolved rank /
|
|
235
|
+
// owner approval); the pure core never reads rank.
|
|
236
|
+
// ----------------------------------------------------------------------------------------
|
|
237
|
+
function git(args) { return execFileSync('git', args, { encoding: 'utf8', maxBuffer: 128 * 1024 * 1024 }); }
|
|
238
|
+
|
|
239
|
+
function gatherDiff(baseRef) {
|
|
240
|
+
const mb = git(['merge-base', baseRef, 'HEAD']).trim();
|
|
241
|
+
const raw = git(['diff', '--raw', `${mb}...HEAD`]).split('\n').filter(Boolean);
|
|
242
|
+
const files = [];
|
|
243
|
+
for (const line of raw) {
|
|
244
|
+
// ":100644 100644 sha sha M\tpath" (status D = delete; mode 120000 = symlink)
|
|
245
|
+
const m = /^:(\d{6}) (\d{6}) \S+ \S+ (\S+)\t(.+)$/.exec(line);
|
|
246
|
+
if (!m) { files.push({ path: '<unparseable>', mode: '000000', deleted: false, parseError: true }); continue; }
|
|
247
|
+
const [, , newMode, status, rawPath] = m;
|
|
248
|
+
files.push({ path: rawPath, mode: newMode, deleted: status.startsWith('D') });
|
|
249
|
+
}
|
|
250
|
+
const diffBytes = Buffer.byteLength(git(['diff', `${mb}...HEAD`]), 'utf8');
|
|
251
|
+
const blobAt = (which, p) => {
|
|
252
|
+
const ref = which === 'base' ? mb : 'HEAD';
|
|
253
|
+
try { return git(['show', `${ref}:${p}`]); } catch { return null; }
|
|
254
|
+
};
|
|
255
|
+
return { files, blobAt, diffBytes };
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async function main() {
|
|
259
|
+
const baseRef = process.env.GATE_BASE_REF || 'origin/main';
|
|
260
|
+
const reportOnly = process.env.GATE_REPORT_ONLY === '1';
|
|
261
|
+
const trusted = process.env.GATE_AUTHOR_TRUSTED === '1'; // set by the workflow from server-resolved rank / owner approval
|
|
262
|
+
|
|
263
|
+
let result;
|
|
264
|
+
try {
|
|
265
|
+
if ((process.env.GATE_FILES_JSON || '').trim()) {
|
|
266
|
+
// test/dry-run injection: {files, blobs:{ 'base:path':..., 'head:path':... }, diffBytes}
|
|
267
|
+
const inj = JSON.parse(process.env.GATE_FILES_JSON);
|
|
268
|
+
const blobAt = (which, p) => (inj.blobs && Object.prototype.hasOwnProperty.call(inj.blobs, `${which}:${p}`)) ? inj.blobs[`${which}:${p}`] : null;
|
|
269
|
+
result = classifyChanges({ files: inj.files, blobAt, diffBytes: inj.diffBytes || 0 });
|
|
270
|
+
} else {
|
|
271
|
+
const { files, blobAt, diffBytes } = gatherDiff(baseRef);
|
|
272
|
+
if (files.some((f) => f.parseError)) throw new Error('unparseable --raw diff line (fail-closed)');
|
|
273
|
+
result = classifyChanges({ files, blobAt, diffBytes });
|
|
274
|
+
}
|
|
275
|
+
} catch (e) {
|
|
276
|
+
console.error(`gate-review: analyzer error (fail-closed): ${e && e.stack ? e.stack : e}`);
|
|
277
|
+
process.exit(reportOnly ? 0 : 1);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Resolve the final action.
|
|
282
|
+
const ownerApproved = process.env.GATE_OWNER_APPROVED === '1';
|
|
283
|
+
const action = resolveAction({ verdict: result.verdict, trusted, ownerApproved });
|
|
284
|
+
|
|
285
|
+
const lines = [`## gate-review: ${result.verdict.toUpperCase()}${reportOnly ? ' (report-only)' : ''} ā would ${action === 'pass' ? 'PASS' : 'BLOCK + ping owner'}`, ''];
|
|
286
|
+
if (result.surfaces.length) lines.push(`Gate surfaces touched: ${result.surfaces.length}`);
|
|
287
|
+
for (const e of result.escalations) lines.push(`- ESCALATE \`${e.path}\` ā ${e.reason}`);
|
|
288
|
+
for (const n of result.needsTrust) lines.push(`- NEEDS-TRUST \`${n.path}\` ā ${n.reason} ā ${action === 'pass' ? 'PASS' : 'BLOCK (needs Metic+ attestation or owner approval)'}`);
|
|
289
|
+
for (const a of result.autoPassed) lines.push(`- AUTO-PASS \`${a}\` ā pure narrowing (strengthens the gate)`);
|
|
290
|
+
if (!result.surfaces.length) lines.push('No gate surface touched ā auto-merge.');
|
|
291
|
+
|
|
292
|
+
const out = lines.join('\n');
|
|
293
|
+
console.log(out);
|
|
294
|
+
if (process.env.GITHUB_STEP_SUMMARY) { try { fs.appendFileSync(process.env.GITHUB_STEP_SUMMARY, out + '\n'); } catch (_) { /* best-effort */ } }
|
|
295
|
+
|
|
296
|
+
if (action === 'block' && !reportOnly) {
|
|
297
|
+
await pingOwner(result).catch(() => {});
|
|
298
|
+
process.exit(1);
|
|
299
|
+
}
|
|
300
|
+
process.exit(0);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async function pingOwner(result) {
|
|
304
|
+
const url = process.env.DISCORD_GATE_APPROVALS_WEBHOOK;
|
|
305
|
+
const pr = process.env.GATE_PR_NUMBER;
|
|
306
|
+
if (!url || !pr) return;
|
|
307
|
+
const surfaces = [...new Set([...result.escalations, ...result.needsTrust].map((x) => x.path))].slice(0, 10).join(', ');
|
|
308
|
+
const body = { content: `gate-pr #${pr} ā gate-surface change needs your review: ${surfaces}\nReview + approve the PR to land it.`, allowed_mentions: { parse: [] } };
|
|
309
|
+
await fetch(url, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) });
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
module.exports = {
|
|
313
|
+
classifyChanges,
|
|
314
|
+
resolveAction,
|
|
315
|
+
certifyRunUnitTestsNarrowing,
|
|
316
|
+
certifyAllowlistNarrowing,
|
|
317
|
+
isCanonicalPath,
|
|
318
|
+
matchesHardFloor,
|
|
319
|
+
HARD_FLOOR_GLOBS,
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
if (require.main === module) main();
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// scripts/gds/gating.js ā owner kill-switch for main-branch merge gating.
|
|
3
|
+
//
|
|
4
|
+
// What "gating" means here ā TWO independent levers, both toggled together:
|
|
5
|
+
// 1. GitHub branch protection on `main`: required status checks (unit,
|
|
6
|
+
// trufflehog, gate-review) + required code-owner review (CODEOWNERS).
|
|
7
|
+
// 2. The application-layer trust gates that run on every PR ā the gate-review
|
|
8
|
+
// and grade-gate CI workflows. These post their own status checks and the
|
|
9
|
+
// ship / auto-merge pipeline refuses to land a PR while gate-review is red
|
|
10
|
+
// (it escalates gate-surface changes ā infra/, migrations/, CODEOWNERS,
|
|
11
|
+
// scripts/gds plumbing ā to owner approval). Branch protection alone does
|
|
12
|
+
// NOT neutralize these, which is why `off` also `gh workflow disable`s them.
|
|
13
|
+
// With gating ON, a gate-surface PR needs owner approval / --admin to merge.
|
|
14
|
+
// With gating OFF, ordinary `gh pr merge N` (and every builder / autonomous
|
|
15
|
+
// session) merges with no checks and no approval. `unit` + `trufflehog` keep
|
|
16
|
+
// running either way ā real safety nets that force no approval.
|
|
17
|
+
//
|
|
18
|
+
// It is REVERSIBLE by construction: `off` snapshots the live protection to a
|
|
19
|
+
// replay-ready file, then deletes protection; `on` PUTs the snapshot back,
|
|
20
|
+
// byte-for-byte. If the snapshot is missing, `on` falls back to a baked-in
|
|
21
|
+
// known-good config (printed loudly) so you can never get permanently stuck.
|
|
22
|
+
//
|
|
23
|
+
// ā While OFF, ANY merge to `main` reaches prod with no checks and no review ā
|
|
24
|
+
// yours, any builder's, any autonomous session's. This is a deliberate,
|
|
25
|
+
// owner-only, temporary posture. Flip it back with `on` when done.
|
|
26
|
+
//
|
|
27
|
+
// Usage:
|
|
28
|
+
// node scripts/gds/gating.js status # show current protection + snapshot state
|
|
29
|
+
// node scripts/gds/gating.js off # snapshot, then remove all protection
|
|
30
|
+
// node scripts/gds/gating.js on # restore protection from the snapshot
|
|
31
|
+
//
|
|
32
|
+
// Auth: uses the `gh` CLI, which must be authenticated as a repo admin (the
|
|
33
|
+
// owner). This is a trust-boundary surface (ADR 0016/0043) ā owner-gated in
|
|
34
|
+
// CODEOWNERS so a builder cannot weaken the gate by editing this file.
|
|
35
|
+
|
|
36
|
+
'use strict';
|
|
37
|
+
|
|
38
|
+
const { execFileSync } = require('node:child_process');
|
|
39
|
+
const fs = require('node:fs');
|
|
40
|
+
const os = require('node:os');
|
|
41
|
+
const path = require('node:path');
|
|
42
|
+
|
|
43
|
+
const BRANCH = 'main';
|
|
44
|
+
const SNAPSHOT = require('../../src/instance-config').configPath('gating-snapshot.json');
|
|
45
|
+
|
|
46
|
+
// The application-layer trust gates that run on every PR and force owner
|
|
47
|
+
// approval / --admin on gate-surface changes. Branch protection alone does NOT
|
|
48
|
+
// neutralize these ā they post their own status checks and the auto-merge /
|
|
49
|
+
// ship pipeline refuses to land a PR while gate-review is red. So the kill-switch
|
|
50
|
+
// also disables/enables these workflows. `unit` + `trufflehog` (secret scan) are
|
|
51
|
+
// deliberately left running ā they are real safety nets and force no approval.
|
|
52
|
+
const GATE_WORKFLOWS = ['gate-review.yml', 'grade-gate.yml'];
|
|
53
|
+
|
|
54
|
+
// Baked-in known-good config (the live state captured 2026-06-19). Used only as
|
|
55
|
+
// a restore fallback when no snapshot exists, so `on` can never be stuck.
|
|
56
|
+
const DEFAULT_PROTECTION = {
|
|
57
|
+
required_status_checks: {
|
|
58
|
+
strict: false,
|
|
59
|
+
checks: [
|
|
60
|
+
{ context: 'unit', app_id: 15368 },
|
|
61
|
+
{ context: 'trufflehog', app_id: 15368 },
|
|
62
|
+
{ context: 'gate-review', app_id: 15368 },
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
enforce_admins: false,
|
|
66
|
+
required_pull_request_reviews: {
|
|
67
|
+
dismiss_stale_reviews: false,
|
|
68
|
+
require_code_owner_reviews: true,
|
|
69
|
+
required_approving_review_count: 0,
|
|
70
|
+
require_last_push_approval: false,
|
|
71
|
+
},
|
|
72
|
+
restrictions: null,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
function gh(args, opts = {}) {
|
|
76
|
+
return execFileSync('gh', args, {
|
|
77
|
+
encoding: 'utf8',
|
|
78
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
79
|
+
...opts,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function repoSlug() {
|
|
84
|
+
try {
|
|
85
|
+
return gh(['repo', 'view', '--json', 'nameWithOwner', '-q', '.nameWithOwner']).trim();
|
|
86
|
+
} catch (e) {
|
|
87
|
+
fail('could not resolve the repo via `gh repo view` ā is gh installed and run inside the repo?', e);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// GET protection. Returns the parsed object, or null if protection is OFF
|
|
92
|
+
// (GitHub returns 404 "Branch not protected").
|
|
93
|
+
function getProtection(repo) {
|
|
94
|
+
try {
|
|
95
|
+
const out = gh(['api', `repos/${repo}/branches/${BRANCH}/protection`]);
|
|
96
|
+
return JSON.parse(out);
|
|
97
|
+
} catch (e) {
|
|
98
|
+
const msg = `${e.stderr || ''}${e.stdout || ''}`;
|
|
99
|
+
if (/Branch not protected|Not Found|HTTP 404/i.test(msg)) return null;
|
|
100
|
+
fail('failed to read branch protection', e);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Transform a GET-protection response into a valid PUT body (the two shapes
|
|
105
|
+
// differ ā GET nests booleans under {enabled}, PUT wants flat values).
|
|
106
|
+
function toPutBody(p) {
|
|
107
|
+
const body = {
|
|
108
|
+
required_status_checks: null,
|
|
109
|
+
enforce_admins: !!(p.enforce_admins && p.enforce_admins.enabled),
|
|
110
|
+
required_pull_request_reviews: null,
|
|
111
|
+
restrictions: null,
|
|
112
|
+
};
|
|
113
|
+
if (p.required_status_checks) {
|
|
114
|
+
const rsc = p.required_status_checks;
|
|
115
|
+
body.required_status_checks = { strict: !!rsc.strict };
|
|
116
|
+
if (Array.isArray(rsc.checks) && rsc.checks.length) {
|
|
117
|
+
body.required_status_checks.checks = rsc.checks.map((c) => ({
|
|
118
|
+
context: c.context,
|
|
119
|
+
app_id: c.app_id ?? null,
|
|
120
|
+
}));
|
|
121
|
+
} else {
|
|
122
|
+
body.required_status_checks.contexts = rsc.contexts || [];
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (p.required_pull_request_reviews) {
|
|
126
|
+
const r = p.required_pull_request_reviews;
|
|
127
|
+
const rb = {
|
|
128
|
+
dismiss_stale_reviews: !!r.dismiss_stale_reviews,
|
|
129
|
+
require_code_owner_reviews: !!r.require_code_owner_reviews,
|
|
130
|
+
required_approving_review_count: r.required_approving_review_count ?? 0,
|
|
131
|
+
};
|
|
132
|
+
if (typeof r.require_last_push_approval === 'boolean') {
|
|
133
|
+
rb.require_last_push_approval = r.require_last_push_approval;
|
|
134
|
+
}
|
|
135
|
+
body.required_pull_request_reviews = rb;
|
|
136
|
+
}
|
|
137
|
+
if (p.restrictions) {
|
|
138
|
+
body.restrictions = {
|
|
139
|
+
users: (p.restrictions.users || []).map((u) => u.login),
|
|
140
|
+
teams: (p.restrictions.teams || []).map((t) => t.slug),
|
|
141
|
+
apps: (p.restrictions.apps || []).map((a) => a.slug),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
for (const key of [
|
|
145
|
+
'required_linear_history',
|
|
146
|
+
'allow_force_pushes',
|
|
147
|
+
'allow_deletions',
|
|
148
|
+
'block_creations',
|
|
149
|
+
'required_conversation_resolution',
|
|
150
|
+
'lock_branch',
|
|
151
|
+
'allow_fork_syncing',
|
|
152
|
+
]) {
|
|
153
|
+
if (p[key] && typeof p[key].enabled === 'boolean') body[key] = p[key].enabled;
|
|
154
|
+
}
|
|
155
|
+
return body;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function putProtection(repo, putBody) {
|
|
159
|
+
gh(['api', '-X', 'PUT', `repos/${repo}/branches/${BRANCH}/protection`, '--input', '-'], {
|
|
160
|
+
input: JSON.stringify(putBody),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function deleteProtection(repo) {
|
|
165
|
+
gh(['api', '-X', 'DELETE', `repos/${repo}/branches/${BRANCH}/protection`]);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// --- gate CI workflows ('active' | 'disabled_manually' | 'disabled_inactivity') ---
|
|
169
|
+
function workflowState(repo, wf) {
|
|
170
|
+
try {
|
|
171
|
+
return gh(['api', `repos/${repo}/actions/workflows/${wf}`, '-q', '.state']).trim();
|
|
172
|
+
} catch {
|
|
173
|
+
return 'absent'; // not on the default branch / never registered
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function setWorkflow(repo, wf, enable) {
|
|
178
|
+
// `gh workflow enable/disable` resolves the workflow from the repo context.
|
|
179
|
+
gh(['workflow', enable ? 'enable' : 'disable', wf]);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function readSnapshot() {
|
|
183
|
+
try {
|
|
184
|
+
return JSON.parse(fs.readFileSync(SNAPSHOT, 'utf8'));
|
|
185
|
+
} catch {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function writeSnapshot(obj) {
|
|
191
|
+
fs.mkdirSync(path.dirname(SNAPSHOT), { recursive: true });
|
|
192
|
+
fs.writeFileSync(SNAPSHOT, JSON.stringify(obj, null, 2));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function fail(msg, err) {
|
|
196
|
+
console.error(`\nā gating: ${msg}`);
|
|
197
|
+
if (err && (err.stderr || err.message)) console.error(` ${(err.stderr || err.message).trim()}`);
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function summarize(putBody) {
|
|
202
|
+
const checks =
|
|
203
|
+
putBody.required_status_checks
|
|
204
|
+
? (putBody.required_status_checks.checks || putBody.required_status_checks.contexts || [])
|
|
205
|
+
.map((c) => c.context || c)
|
|
206
|
+
.join(', ') || '(none)'
|
|
207
|
+
: '(none)';
|
|
208
|
+
const review =
|
|
209
|
+
putBody.required_pull_request_reviews?.require_code_owner_reviews
|
|
210
|
+
? 'code-owner review required'
|
|
211
|
+
: putBody.required_pull_request_reviews
|
|
212
|
+
? `${putBody.required_pull_request_reviews.required_approving_review_count || 0} approving review(s)`
|
|
213
|
+
: 'no PR review required';
|
|
214
|
+
return { checks, review };
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function cmdStatus(repo) {
|
|
218
|
+
const live = getProtection(repo);
|
|
219
|
+
const snap = readSnapshot();
|
|
220
|
+
const wf = GATE_WORKFLOWS.map((w) => ({ w, state: workflowState(repo, w) }));
|
|
221
|
+
const wfActive = wf.filter((x) => x.state === 'active');
|
|
222
|
+
console.log(`repo: ${repo} branch: ${BRANCH}\n`);
|
|
223
|
+
|
|
224
|
+
// Lever 1 ā branch protection.
|
|
225
|
+
if (live) {
|
|
226
|
+
const { checks, review } = summarize(toPutBody(live));
|
|
227
|
+
console.log('branch protection : š¢ ON');
|
|
228
|
+
console.log(` required checks : ${checks}`);
|
|
229
|
+
console.log(` pr review : ${review}`);
|
|
230
|
+
console.log(` enforce_admins : ${!!(live.enforce_admins && live.enforce_admins.enabled)} (owner can --admin merge when false)`);
|
|
231
|
+
} else {
|
|
232
|
+
console.log('branch protection : š“ OFF ā `main` is UNPROTECTED.');
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Lever 2 ā gate CI workflows.
|
|
236
|
+
console.log(`\ngate CI workflows : ${wfActive.length ? 'š¢ ON' : 'š“ OFF'}`);
|
|
237
|
+
for (const x of wf) console.log(` ${x.w.padEnd(16)}: ${x.state}`);
|
|
238
|
+
|
|
239
|
+
const fullyOff = !live && wfActive.length === 0;
|
|
240
|
+
const fullyOn = !!live && wfActive.length === GATE_WORKFLOWS.length;
|
|
241
|
+
console.log(`\ngating: ${fullyOff ? 'š“ fully OFF ā merges sail through, no checks/approval' : fullyOn ? 'š¢ fully ON' : 'š” PARTIAL ā run `off` or `on` to make it consistent'}`);
|
|
242
|
+
console.log(`snapshot: ${snap ? SNAPSHOT : '(none yet ā `off` will create it; `on` would use the baked-in default)'}`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function cmdOff(repo) {
|
|
246
|
+
// Lever 1 ā branch protection (idempotent).
|
|
247
|
+
const live = getProtection(repo);
|
|
248
|
+
if (live) {
|
|
249
|
+
const putBody = toPutBody(live);
|
|
250
|
+
writeSnapshot({ saved_at_branch: BRANCH, repo, raw: live, put_body: putBody });
|
|
251
|
+
const { checks, review } = summarize(putBody);
|
|
252
|
+
console.log('branch protection: removing.');
|
|
253
|
+
console.log(` was: checks [${checks}] + ${review}`);
|
|
254
|
+
console.log(` snapshot saved: ${SNAPSHOT}`);
|
|
255
|
+
deleteProtection(repo);
|
|
256
|
+
} else {
|
|
257
|
+
console.log('branch protection: already off.');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Lever 2 ā gate CI workflows (idempotent).
|
|
261
|
+
for (const w of GATE_WORKFLOWS) {
|
|
262
|
+
const state = workflowState(repo, w);
|
|
263
|
+
if (state === 'active') {
|
|
264
|
+
setWorkflow(repo, w, false);
|
|
265
|
+
console.log(`gate workflow ${w}: disabled.`);
|
|
266
|
+
} else {
|
|
267
|
+
console.log(`gate workflow ${w}: already ${state}.`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
console.log('\nš“ gating OFF. `main` is UNPROTECTED and the gate-review/grade CI gates no longer');
|
|
272
|
+
console.log(' run ā ordinary `gh pr merge N` (and every builder / autonomous session) merges');
|
|
273
|
+
console.log(' with no checks and no approval. (unit + secret-scan still run.)');
|
|
274
|
+
console.log(' ā© restore everything: node scripts/gds/gating.js on');
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function cmdOn(repo) {
|
|
278
|
+
// Lever 1 ā branch protection (idempotent).
|
|
279
|
+
const live = getProtection(repo);
|
|
280
|
+
if (!live) {
|
|
281
|
+
const snap = readSnapshot();
|
|
282
|
+
let putBody;
|
|
283
|
+
if (snap?.put_body) {
|
|
284
|
+
putBody = snap.put_body;
|
|
285
|
+
console.log(`branch protection: restoring from snapshot ${SNAPSHOT}`);
|
|
286
|
+
} else {
|
|
287
|
+
putBody = DEFAULT_PROTECTION;
|
|
288
|
+
console.log('ā branch protection: no snapshot ā restoring the baked-in known-good default.');
|
|
289
|
+
}
|
|
290
|
+
putProtection(repo, putBody);
|
|
291
|
+
const after = getProtection(repo);
|
|
292
|
+
if (!after) fail('PUT returned but protection still reads as OFF ā check `gh` auth / admin rights');
|
|
293
|
+
const { checks, review } = summarize(toPutBody(after));
|
|
294
|
+
console.log(` restored: checks [${checks}] + ${review}`);
|
|
295
|
+
} else {
|
|
296
|
+
console.log('branch protection: already on.');
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Lever 2 ā gate CI workflows (idempotent).
|
|
300
|
+
for (const w of GATE_WORKFLOWS) {
|
|
301
|
+
const state = workflowState(repo, w);
|
|
302
|
+
if (state !== 'active' && state !== 'absent') {
|
|
303
|
+
setWorkflow(repo, w, true);
|
|
304
|
+
console.log(`gate workflow ${w}: re-enabled.`);
|
|
305
|
+
} else {
|
|
306
|
+
console.log(`gate workflow ${w}: already ${state}.`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
console.log('\nš¢ gating ON. Branch protection + the gate-review/grade CI gates are back.');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function main() {
|
|
314
|
+
const cmd = (process.argv[2] || 'status').toLowerCase();
|
|
315
|
+
if (!['status', 'off', 'on'].includes(cmd)) {
|
|
316
|
+
console.error('usage: node scripts/gds/gating.js <status|off|on>');
|
|
317
|
+
process.exit(2);
|
|
318
|
+
}
|
|
319
|
+
const repo = repoSlug();
|
|
320
|
+
if (cmd === 'status') cmdStatus(repo);
|
|
321
|
+
else if (cmd === 'off') cmdOff(repo);
|
|
322
|
+
else if (cmd === 'on') cmdOn(repo);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
main();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=Nightly pg_dump of GDS Postgres DB (filed by #412)
|
|
3
|
+
Documentation=file:///home/lars/amazonprimea/docs/recipes/gds-db-backup.md
|
|
4
|
+
After=postgresql.service
|
|
5
|
+
Requires=postgresql.service
|
|
6
|
+
|
|
7
|
+
[Service]
|
|
8
|
+
Type=oneshot
|
|
9
|
+
User=lars
|
|
10
|
+
Group=lars
|
|
11
|
+
# Run the canonical script from the deployed repo. Keep this path stable;
|
|
12
|
+
# the recipe doc points at it for restore + manual-one-shot use cases.
|
|
13
|
+
ExecStart=/home/lars/amazonprimea/scripts/gds/db-backup-nightly.sh
|
|
14
|
+
# Modest hardening ā the script only needs read on the socket + write on
|
|
15
|
+
# /var/backups/gds. Anything else is gravy for forensics.
|
|
16
|
+
NoNewPrivileges=true
|
|
17
|
+
ProtectSystem=strict
|
|
18
|
+
ReadWritePaths=/var/backups/gds
|
|
19
|
+
ProtectHome=read-only
|
|
20
|
+
PrivateTmp=true
|
|
21
|
+
|
|
22
|
+
[Install]
|
|
23
|
+
# Not socket-activated; timer drives this. No [Install] WantedBy needed ā
|
|
24
|
+
# the timer's WantedBy is what gets enabled.
|