@bongos/core 1.21.175 → 1.21.176
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 +3551 -1516
- package/.claude/skills/ask-for-help/SKILL.md +4 -4
- package/.claude/skills/backlog-review/SKILL.md +1 -1
- package/.claude/skills/blocker-review/SKILL.md +2 -2
- package/.claude/skills/blocker-solve/SKILL.md +4 -4
- package/.claude/skills/bongos-feedback/SKILL.md +1 -1
- package/.claude/skills/bug-triage/SKILL.md +8 -8
- package/.claude/skills/builder-backup/SKILL.md +3 -3
- package/.claude/skills/builder-claim/SKILL.md +5 -5
- package/.claude/skills/builder-cost/SKILL.md +5 -5
- package/.claude/skills/builder-end/SKILL.md +6 -6
- package/.claude/skills/builder-exit/SKILL.md +2 -2
- package/.claude/skills/builder-key/SKILL.md +6 -6
- package/.claude/skills/builder-reauth/SKILL.md +4 -4
- package/.claude/skills/builder-redteam/SKILL.md +3 -3
- package/.claude/skills/builder-release/SKILL.md +3 -3
- package/.claude/skills/builder-sequence/SKILL.md +8 -8
- package/.claude/skills/builder-setup/SKILL.md +4 -4
- package/.claude/skills/builder-ship/SKILL.md +7 -7
- package/.claude/skills/builder-stage/SKILL.md +8 -8
- package/.claude/skills/builder-start/SKILL.md +4 -4
- package/.claude/skills/collab-review/SKILL.md +5 -5
- package/.claude/skills/design/SKILL.md +6 -4
- package/.claude/skills/design-sync/SKILL.md +3 -3
- package/.claude/skills/figma-design-sync/SKILL.md +4 -4
- package/.claude/skills/fix-task/SKILL.md +8 -8
- package/.claude/skills/goal-close/SKILL.md +9 -9
- package/.claude/skills/goal-create/SKILL.md +18 -18
- package/.claude/skills/grade-recover/SKILL.md +8 -8
- package/.claude/skills/grade-sweep/SKILL.md +15 -15
- package/.claude/skills/idea-triage/SKILL.md +15 -15
- package/.claude/skills/merge-mode/SKILL.md +14 -14
- package/.claude/skills/new-project/SKILL.md +5 -5
- package/.claude/skills/owner-review/SKILL.md +1 -1
- package/.claude/skills/planning-session/SKILL.md +14 -14
- package/.claude/skills/priority-session/SKILL.md +6 -6
- package/.claude/skills/read-session-export/SKILL.md +3 -3
- package/.claude/skills/recall/SKILL.md +7 -7
- package/.claude/skills/scan-before-install/SKILL.md +3 -3
- package/.claude/skills/session-handoff/SKILL.md +1 -1
- package/.claude/skills/ship-check/SKILL.md +3 -3
- package/.claude/skills/status/SKILL.md +3 -3
- package/.claude/skills/strand-fix/SKILL.md +6 -6
- package/.claude/skills/worktree-clean/SKILL.md +4 -4
- package/.gitattributes +12 -32
- package/GOVERNMENT.md +1 -1
- package/README.md +8 -8
- package/bin/bongos.js +23 -23
- package/clients/bongos-client/README.md +2 -2
- package/clients/bongos-client/bongos-client.global.js +22 -4
- package/clients/bongos-client/index.cjs +22 -4
- package/clients/bongos-client/index.d.ts +33 -4
- package/clients/bongos-client/index.mjs +21 -3
- package/config/branding.neutral.json +1 -1
- package/config/design-tokens.schema.json +1 -1
- package/config/modules.neutral.json +1 -3
- package/docs/adr/0029-status-page-outage-resilience.md +6 -6
- package/docs/adr/0227-a-task-network-map-is-refused-the-goal-graph-is-the-map.md +1 -1
- package/docs/adr/0294-cli-sessions-do-not-expire.md +1 -1
- package/docs/adr/0383-sessions-end-after-ten-idle-days.md +35 -0
- package/docs/adr/0384-the-raise-page-is-a-hub-module-builders-edit-in-place.md +31 -0
- package/docs/adr/README.md +2 -0
- package/docs/api/openapi.json +606 -44
- package/docs/api-reference.md +25 -12
- package/docs/architecture.md +8 -7
- package/docs/canonical-permissions.md +3 -3
- package/docs/copy-inventory.md +1370 -1411
- package/docs/copy-registry.json +2136 -2536
- package/docs/design/demonolith-plan.md +6 -6
- package/docs/design/modular-architecture/00-research-report.md +1 -1
- package/docs/design/project-startup-direction.md +2 -2
- package/docs/design/projects-hub-direction-v2.md +1 -1
- package/docs/design/reviews/hall-v2/README.md +2 -2
- package/docs/design/vanilla-hall-ui-redesign-scope.md +1 -1
- package/docs/file-map.md +89 -88
- package/docs/handoff-template.md +4 -4
- package/docs/module-api-changelog.md +5 -3
- package/docs/modules-contract.md +8 -7
- package/docs/onboarding/diagrams/01-task-lifecycle.mmd +1 -1
- package/docs/onboarding/diagrams/02-rank-ladder.mmd +1 -1
- package/docs/onboarding/diagrams/03-drachmae-karma.mmd +1 -1
- package/docs/onboarding/diagrams/04-architecture.mmd +1 -1
- package/docs/onboarding/diagrams/05-versioning.mmd +1 -1
- package/docs/onboarding/diagrams/README.md +2 -2
- package/docs/onboarding/diagrams/assertions.json +2 -2
- package/docs/onboarding/slash-commands.md +2 -2
- package/docs/packs/artist.md +4 -4
- package/docs/packs/engineer.md +11 -10
- package/docs/packs/ideator.md +7 -7
- package/docs/page-inventory.json +20 -1
- package/docs/page-readings.json +4387 -4603
- package/docs/recipes/README.md +1 -1
- package/docs/recipes/audit-replay.md +4 -4
- package/docs/recipes/autobongos-windows-host.md +6 -6
- package/docs/recipes/bongos-cli-release.md +2 -2
- package/docs/recipes/claude-design-loop.md +7 -7
- package/docs/recipes/core-release-pipeline.md +19 -19
- package/docs/recipes/failed-ship-recovery-proof.md +2 -2
- package/docs/recipes/figma-design-loop.md +6 -6
- package/docs/recipes/gds-db-backup.md +9 -9
- package/docs/recipes/instance-deploy.md +3 -3
- package/docs/recipes/instance-first-run.md +1 -1
- package/docs/recipes/multi-builder-merge.md +2 -2
- package/docs/recipes/ops-gotchas.md +10 -9
- package/docs/recipes/packaging-the-core.md +6 -6
- package/docs/recipes/parallel-goal-waves.md +4 -4
- package/docs/recipes/private-npm-distribution.md +9 -9
- package/docs/recipes/redteam-patrol.md +5 -5
- package/docs/recipes/render-pilot.md +2 -2
- package/docs/recipes/reranking-a-goals-board.md +2 -2
- package/docs/recipes/search-index-ingestion.md +5 -5
- package/docs/recipes/self-host.md +1 -1
- package/docs/recipes/ship-and-regrade.md +4 -4
- package/docs/recipes/staging-environment.md +1 -1
- package/docs/recipes/standalone-live-docs.md +1 -1
- package/docs/recipes/ui-look-before-you-ship.md +2 -2
- package/docs/recipes/upgrading-the-core.md +11 -11
- package/docs/recipes/windows-builders.md +18 -18
- package/docs/research/llm-model-agnostic-and-cheaper-grader.md +6 -6
- package/docs/research/task-network-map-readability.md +3 -3
- package/migrations/core_278_builder_tester_tag.sql +18 -0
- package/migrations/core_279_bongos_shipper_new_scripts_path.sql +13 -0
- package/modules/agents/lib/answer-hold.js +1 -1
- package/modules/agents/lib/gate.js +1 -1
- package/modules/agents/lib/validate.js +1 -1
- package/modules/autonomy/gauge.js +1 -1
- package/modules/autonomy/governor-docket.js +2 -2
- package/modules/autonomy/pollers/routine-timers.js +3 -3
- package/modules/autonomy/routes/autonomy.js +3 -3
- package/modules/builder-settings/interaction-prefs.js +1 -1
- package/modules/builder-settings/render-prefs.js +1 -1
- package/modules/builder-settings/routes/settings.js +1 -1
- package/modules/builder-settings/skill-prefs.js +2 -2
- package/modules/builder-settings/wandering-prefs.js +2 -2
- package/modules/copy-desk/module.json +2 -2
- package/modules/copy-desk/page-data.js +5 -5
- package/modules/copy-desk/page-decisions.js +13 -1
- package/modules/copy-desk/proposals.js +4 -4
- package/modules/copy-desk/registry.js +2 -2
- package/modules/copy-desk/routes/copy-desk-release.js +119 -0
- package/modules/copy-desk/routes/copy-desk.js +3 -12
- package/modules/copy-desk/skills/tweak/SKILL.md +12 -12
- package/modules/copy-desk/tests/copy_flags.mjs +1 -1
- package/modules/copy-desk/tests/copy_no_cms.mjs +7 -3
- package/modules/copy-desk/tests/copy_proposals.mjs +2 -2
- package/modules/copy-desk/tests/copy_queue.mjs +1 -1
- package/modules/design-styles/skills/README.md +4 -4
- package/modules/design-styles/skills/imagegen-frontend-mobile/SKILL.md +1 -1
- package/modules/design-styles/skills/imagegen-frontend-web/SKILL.md +1 -1
- package/modules/discord/bug-attachments.js +1 -1
- package/modules/discord/ship-broadcast.js +1 -1
- package/modules/economy/achievements.js +49 -7
- package/modules/economy/cost-classify.js +6 -6
- package/modules/economy/cost-report.js +1 -1
- package/modules/economy/cost.js +1 -1
- package/modules/economy/credits.js +2 -1
- package/modules/economy/idea-size.js +2 -2
- package/modules/economy/reward.js +2 -0
- package/modules/economy/routes/cost.js +1 -1
- package/modules/economy/streak.js +43 -4
- package/modules/government/asks.js +1 -1
- package/modules/government/board.js +19 -2
- package/modules/government/catalog.js +3 -0
- package/modules/government/migrations/government_033_idea_vote.sql +46 -0
- package/modules/government/protected-surfaces.json +48 -47
- package/modules/government/recommendations.js +6 -2
- package/modules/government/routes/government.js +1 -1
- package/modules/grading/generated-provenance.js +13 -5
- package/modules/grading/grade-engine.js +1 -1
- package/modules/grading/grader-rubric.json +1 -1
- package/modules/grading/grader-score.js +1 -1
- package/modules/grading/grader-workers/index.js +1 -1
- package/modules/grading/grader.js +1 -1
- package/modules/grading/routes/grade.js +1 -1
- package/modules/hall-ui/public/atlas.html +5 -7
- package/modules/hall-ui/public/atlas.js +1 -1
- package/modules/hall-ui/public/atlas.states.json +1 -1
- package/modules/hall-ui/public/blockers.css +9 -0
- package/modules/hall-ui/public/blockers.html +4 -4
- package/modules/hall-ui/public/blockers.js +29 -30
- package/modules/hall-ui/public/board-room.css +5 -17
- package/modules/hall-ui/public/board-room.html +5 -6
- package/modules/hall-ui/public/board-room.js +41 -23
- package/modules/hall-ui/public/board-room.states.json +1 -1
- package/modules/hall-ui/public/brand-apply.js +1 -1
- package/modules/hall-ui/public/brand-holes.js +1 -1
- package/modules/hall-ui/public/builders.js +40 -86
- package/modules/hall-ui/public/city-decide.js +18 -4
- package/modules/hall-ui/public/city.html +1 -1
- package/modules/hall-ui/public/collab.html +1 -1
- package/modules/hall-ui/public/commands.html +6 -9
- package/modules/hall-ui/public/copy-desk.html +1 -1
- package/modules/hall-ui/public/copy-desk.js +2 -2
- package/modules/hall-ui/public/craft-mode.js +4 -0
- package/modules/hall-ui/public/deploy.html +6 -2
- package/modules/hall-ui/public/deploy.js +21 -13
- package/modules/hall-ui/public/diagrams.css +1 -1
- package/modules/hall-ui/public/diagrams.html +5 -8
- package/modules/hall-ui/public/diagrams.states.json +1 -1
- package/modules/hall-ui/public/drachmae.html +3 -7
- package/modules/hall-ui/public/fleet.html +3 -2
- package/modules/hall-ui/public/fleet.js +0 -4
- package/modules/hall-ui/public/gate.html +7 -7
- package/modules/hall-ui/public/gate.js +58 -77
- package/modules/hall-ui/public/goal-map.html +1 -1
- package/modules/hall-ui/public/goals-page.js +5 -5
- package/modules/hall-ui/public/goals-render.js +10 -11
- package/modules/hall-ui/public/goals.css +10 -0
- package/modules/hall-ui/public/goals.html +14 -7
- package/modules/hall-ui/public/government.html +3 -5
- package/modules/hall-ui/public/government.js +1 -5
- package/modules/hall-ui/public/hall-render.js +117 -57
- package/modules/hall-ui/public/hall-widgets.js +11 -11
- package/modules/hall-ui/public/idea.html +1 -1
- package/modules/hall-ui/public/ideas.html +3 -1
- package/modules/hall-ui/public/ideas.js +1 -0
- package/modules/hall-ui/public/index.html +12 -6
- package/modules/hall-ui/public/index.states.json +1 -1
- package/modules/hall-ui/public/mine-lens.js +1 -1
- package/modules/hall-ui/public/modules.html +7 -10
- package/modules/hall-ui/public/modules.js +0 -2
- package/modules/hall-ui/public/my-agents.html +1 -1
- package/modules/hall-ui/public/palette.js +5 -5
- package/modules/hall-ui/public/primer.html +4 -9
- package/modules/hall-ui/public/profile-connections.js +10 -2
- package/modules/hall-ui/public/profile-roles.js +3 -10
- package/modules/hall-ui/public/profile.html +12 -10
- package/modules/hall-ui/public/profile.js +13 -17
- package/modules/hall-ui/public/project-settings.html +3 -4
- package/modules/hall-ui/public/project-settings.js +0 -3
- package/modules/hall-ui/public/ranks.html +5 -11
- package/modules/hall-ui/public/ranks.js +6 -8
- package/modules/hall-ui/public/roadmap.css +0 -2
- package/modules/hall-ui/public/roadmap.html +1 -1
- package/modules/hall-ui/public/roadmap.js +16 -51
- package/modules/hall-ui/public/roster.html +1 -1
- package/modules/hall-ui/public/sessions.html +6 -8
- package/modules/hall-ui/public/sessions.js +7 -7
- package/modules/hall-ui/public/settings.html +1 -1
- package/modules/hall-ui/public/shell-trail.js +1 -1
- package/modules/hall-ui/public/shell.js +17 -17
- package/modules/hall-ui/public/street-deck.css +2 -1
- package/modules/hall-ui/public/street-deck.js +10 -2
- package/modules/hall-ui/public/street-desk.js +16 -5
- package/modules/hall-ui/public/street.html +1 -1
- package/modules/hall-ui/public/studio-lib.js +4 -0
- package/modules/hall-ui/public/studio.css +2 -0
- package/modules/hall-ui/public/studio.html +1 -1
- package/modules/hall-ui/public/studio.js +27 -1
- package/modules/hall-ui/public/style.css +43 -26
- package/modules/hall-ui/public/task-detail.js +10 -7
- package/modules/hall-ui/public/task.css +2 -0
- package/modules/hall-ui/public/task.html +3 -1
- package/modules/hall-ui/public/task.js +23 -7
- package/modules/hall-ui/public/thinking.html +1 -1
- package/modules/hall-ui/public/tweak-editor.html +1 -1
- package/modules/hall-ui/public/vote-control.js +208 -0
- package/modules/hall-ui/public/watch.html +3 -5
- package/modules/hall-ui/public/watch.js +5 -4
- package/modules/hall-ui/public/welcome-boot.css +130 -0
- package/modules/hall-ui/public/welcome-boot.js +334 -0
- package/modules/hall-ui/public/welcome-day.webp +0 -0
- package/modules/hall-ui/public/welcome-night.webp +0 -0
- package/modules/hall-ui/public/work-summary.js +1 -1
- package/modules/hall-ui/public/work.css +1 -0
- package/modules/hall-ui/public/work.html +3 -1
- package/modules/hall-ui/public/work.js +2 -1
- package/modules/hall-ui/records/accomplishments.md +16 -0
- package/modules/hall-ui/records/hall-ask-card.md +9 -0
- package/modules/hall-ui/records/karma-vote-control.md +13 -0
- package/modules/hall-ui/records/oversight-family.md +1 -1
- package/modules/hall-ui/records/profile-connections.md +2 -0
- package/modules/hall-ui/records/profile-roles.md +1 -1
- package/modules/hall-ui/records/reading-rooms.md +1 -1
- package/modules/hall-ui/records/welcome-tower.md +50 -0
- package/modules/ideas/migrations/ideas_011_idea_votes.sql +31 -0
- package/modules/ideas/projection.js +1 -1
- package/modules/ideas/routes/blockers.js +3 -3
- package/modules/ideas/routes/inbox.js +29 -1
- package/modules/ideas/routes/ratify-goal.js +1 -1
- package/modules/ideas/routing.js +1 -1
- package/modules/ideas/templates.js +1 -1
- package/modules/ideas/trail-descent.js +1 -1
- package/modules/ideas/trail-size.js +1 -1
- package/modules/ideas/votes.js +93 -0
- package/modules/lifecycle/abandon-leftovers.js +1 -1
- package/modules/lifecycle/cascade.js +1 -1
- package/modules/lifecycle/conflict-resolve.js +13 -21
- package/modules/lifecycle/criterion-ref.js +1 -1
- package/modules/lifecycle/db-analytics.js +57 -4
- package/modules/lifecycle/db-deps-criteria.js +1 -1
- package/modules/lifecycle/db-ship.js +2 -2
- package/modules/lifecycle/db-tasks.js +2 -2
- package/modules/lifecycle/db-versions.js +1 -1
- package/modules/lifecycle/db.js +2 -0
- package/modules/lifecycle/dead-deps.js +3 -3
- package/modules/lifecycle/dependency-advisory.js +3 -3
- package/modules/lifecycle/goal-category.js +1 -1
- package/modules/lifecycle/goal-forest.js +1 -1
- package/modules/lifecycle/goal-task-relevance-advisory.js +1 -1
- package/modules/lifecycle/kickoff-checklist.js +1 -1
- package/modules/lifecycle/kickoff-seed.js +1 -1
- package/modules/lifecycle/lifecycle.js +2 -0
- package/modules/lifecycle/merge-reach.js +29 -15
- package/modules/lifecycle/missing-dep-classify.js +3 -3
- package/modules/lifecycle/module.json +2 -1
- package/modules/lifecycle/page-tweak-approve.js +85 -1
- package/modules/lifecycle/page-tweak-hold.js +1 -1
- package/modules/lifecycle/publish-reconciler.js +1 -2
- package/modules/lifecycle/rot.js +1 -1
- package/modules/lifecycle/routes/artist-gate.js +1 -1
- package/modules/lifecycle/routes/gate-approvals.js +22 -1
- package/modules/lifecycle/routes/goals.js +1 -1
- package/modules/lifecycle/routes/task-route-helpers.js +1 -1
- package/modules/lifecycle/routes/task-votes.js +54 -0
- package/modules/lifecycle/routes/task-write-routes.js +1 -1
- package/modules/lifecycle/routes/tasks.js +2 -2
- package/modules/lifecycle/routes/versions.js +2 -2
- package/modules/lifecycle/ship-card.js +4 -4
- package/modules/lifecycle/ship-preflight.js +1 -1
- package/modules/lifecycle/task-classifier.js +1 -1
- package/modules/lifecycle/task-status.js +1 -1
- package/modules/lifecycle/task-visual-db.js +1 -1
- package/modules/memory/learnings.js +1 -1
- package/modules/memory/pollers/search-index.js +2 -2
- package/modules/memory/routes/learnings.js +1 -1
- package/modules/memory/routes/memory.js +1 -1
- package/modules/memory/search.js +2 -2
- package/modules/npm-release/release.js +1 -1
- package/modules/onboarding/howto-moments.js +1 -1
- package/modules/onboarding/newcomer-restock.js +3 -3
- package/modules/onboarding/onboarding.js +1 -1
- package/modules/pixel-art/skills/otb-tile-generate/SKILL.md +1 -1
- package/modules/platform-identity/origin-containment.js +1 -1
- package/modules/platform-identity/publish-gate.js +1 -1
- package/modules/platform-identity/tests/platform-identity.mjs +1 -1
- package/modules/provisioning/capacity.js +1 -1
- package/modules/provisioning/core-upgrade.js +15 -9
- package/modules/provisioning/credential-preflight.js +3 -3
- package/modules/provisioning/disconnect.js +1 -1
- package/modules/provisioning/dns-resolves.js +1 -1
- package/modules/provisioning/module.json +1 -1
- package/modules/provisioning/onboard-plan.js +1 -1
- package/modules/provisioning/paid-shape-gate.js +2 -2
- package/modules/provisioning/planet-physics.js +11 -2
- package/modules/provisioning/pollers/liveness-sweep.js +1 -1
- package/modules/provisioning/pollers/runner-drift-notify.js +5 -5
- package/modules/provisioning/provisioning.js +2 -2
- package/modules/provisioning/render-lookup.js +1 -1
- package/modules/provisioning/render-standup.js +3 -3
- package/modules/provisioning/repo-private.js +1 -1
- package/modules/provisioning/routes/callback-page.js +1 -1
- package/modules/provisioning/routes/core-upgrade.js +23 -3
- package/modules/provisioning/routes/provisioning.js +2 -2
- package/modules/provisioning/routes/render-standup.js +1 -1
- package/modules/provisioning/routes/repo-private.js +1 -1
- package/modules/provisioning/soft-limits.js +1 -1
- package/modules/provisioning/starter-bundles.js +4 -2
- package/modules/provisioning/tests/provisioning.mjs +1 -1
- package/modules/public-landing/public/account.html +4 -6
- package/modules/public-landing/public/assets/cosmos.css +13 -6
- package/modules/public-landing/public/connections.html +4 -6
- package/modules/public-landing/public/contact.html +4 -6
- package/modules/public-landing/public/guild.html +4 -6
- package/modules/public-landing/public/index.html +11 -9
- package/modules/public-landing/public/invitations.html +4 -6
- package/modules/public-landing/public/privacy.html +4 -6
- package/modules/public-landing/public/projects.html +168 -46
- package/modules/public-landing/public/terms.html +4 -6
- package/modules/raise/content/copy.json +40 -0
- package/modules/raise/content/nda.html +39 -0
- package/modules/raise/content/settings.json +49 -0
- package/modules/raise/db.js +95 -0
- package/modules/raise/migrations/raise_001_tables.sql +71 -0
- package/modules/raise/module.json +28 -0
- package/modules/raise/page.js +194 -0
- package/modules/raise/public/edit.js +152 -0
- package/modules/raise/public/favicon.svg +1 -0
- package/modules/raise/public/logo-ink.svg +1 -0
- package/modules/raise/public/logo-night.svg +1 -0
- package/modules/raise/public/mode.js +8 -0
- package/modules/raise/public/raise.css +234 -0
- package/modules/raise/public/raise.js +91 -0
- package/modules/raise/raise.js +174 -0
- package/modules/raise/routes/raise.js +152 -0
- package/modules/raise/views/gate.html +39 -0
- package/modules/raise/views/nda.html +21 -0
- package/modules/raise/views/page.html +133 -0
- package/modules/raise/web.js +72 -0
- package/modules/render-deploy/deploys.js +1 -1
- package/modules/render-deploy/render.js +2 -2
- package/modules/security/secret-scrub.js +3 -3
- package/modules/security/security.js +1 -1
- package/modules/security/tests/artifact_scan.mjs +1 -1
- package/modules/security/tests/mirror.mjs +1 -1
- package/modules/security/tests/scan_store.mjs +1 -1
- package/modules/sessions/db.js +2 -2
- package/modules/sessions/pulse.js +2 -2
- package/modules/sessions/routes/sessions.js +1 -1
- package/modules/specialities/specialities.js +1 -1
- package/modules/status-ui/public/README.md +3 -4
- package/modules/status-ui/public/index.html +5 -31
- package/modules/status-ui/public/status.js +6 -174
- package/modules/status-ui/public/style.css +4 -133
- package/modules/ui-design/docs/design-contract.md +3 -3
- package/modules/ui-design/kit/README.md +1 -1
- package/modules/ui-design/kit/serve.js +13 -4
- package/modules/ui-design/scripts/design-sync.js +1 -1
- package/modules/ui-design/scripts/figma-design-sync.js +1 -1
- package/modules/ui-design/scripts/validate-design.js +1 -1
- package/package-lock.json +27 -11
- package/package.json +2 -3
- package/release-notes.json +172 -0
- package/scripts/bongos/CLAUDE.md +15 -0
- package/scripts/bongos/abandon.js +137 -0
- package/scripts/bongos/accessibility-replay.js +195 -0
- package/scripts/bongos/address-park-sweep.sh +91 -0
- package/scripts/bongos/adopt-detect.js +123 -0
- package/scripts/bongos/adopt-import.js +111 -0
- package/scripts/bongos/adopt-preflight.js +187 -0
- package/scripts/bongos/adr-namespace.js +273 -0
- package/scripts/bongos/agent-invoke.js +689 -0
- package/scripts/bongos/agents-sync.js +502 -0
- package/scripts/bongos/api-alias-caller-scan.js +256 -0
- package/scripts/bongos/api-artifacts.js +91 -0
- package/scripts/bongos/api.js +86 -0
- package/scripts/bongos/api.ps1 +26 -0
- package/scripts/bongos/architect-audit.js +294 -0
- package/scripts/bongos/artifact-audit.js +326 -0
- package/scripts/bongos/artifact-format.js +203 -0
- package/scripts/bongos/artifact-staleness.js +267 -0
- package/scripts/bongos/ask.js +231 -0
- package/scripts/bongos/audit-authorship.sh +329 -0
- package/scripts/bongos/audit-deps.js +189 -0
- package/scripts/bongos/audit-gate.js +121 -0
- package/scripts/bongos/audit-rank-roles.js +172 -0
- package/scripts/bongos/audit-replay.sh +205 -0
- package/scripts/bongos/autobongos-digest.js +123 -0
- package/scripts/bongos/autobongos-grade-cap.js +187 -0
- package/scripts/bongos/autobongos-loop.js +210 -0
- package/scripts/bongos/autobongos-run.js +1361 -0
- package/scripts/bongos/autobongos-service.cmd +50 -0
- package/scripts/bongos/autobongos-service.ps1 +270 -0
- package/scripts/bongos/autobongos-tweak-lane.js +262 -0
- package/scripts/bongos/autobongos-verify.js +618 -0
- package/scripts/bongos/autonomy-gate.js +135 -0
- package/scripts/bongos/autonomy-gauge-statusline.js +124 -0
- package/scripts/bongos/autonomy-gauge.js +84 -0
- package/scripts/bongos/backfill-cost.js +176 -0
- package/scripts/bongos/backfill-disciplines.js +144 -0
- package/scripts/bongos/backfill-session-earnings.js +123 -0
- package/scripts/bongos/backfill-session-types.js +87 -0
- package/scripts/bongos/backfill-sessions.js +411 -0
- package/scripts/bongos/backfill-subagent-rewards.js +485 -0
- package/scripts/bongos/backfill-task-rewards.js +413 -0
- package/scripts/bongos/backlog-review.js +399 -0
- package/scripts/bongos/backup-dropin-sweep.sh +95 -0
- package/scripts/bongos/backup.js +116 -0
- package/scripts/bongos/baseline-staleness.js +217 -0
- package/scripts/bongos/bfg-principal-token.js +65 -0
- package/scripts/bongos/bug-attachment-audit.js +149 -0
- package/scripts/bongos/bug-attachment-recover.js +198 -0
- package/scripts/bongos/bug-triage.js +292 -0
- package/scripts/bongos/build-bongos.js +94 -0
- package/scripts/bongos/bump-version.js +221 -0
- package/scripts/bongos/capture.js +481 -0
- package/scripts/bongos/category-advisory-guard.js +206 -0
- package/scripts/bongos/ci-grade.js +82 -0
- package/scripts/bongos/claim-recall.js +112 -0
- package/scripts/bongos/claim.js +789 -0
- package/scripts/bongos/classify-discipline.js +153 -0
- package/scripts/bongos/claude-materialize.js +1200 -0
- package/scripts/bongos/claude-md-template.js +142 -0
- package/scripts/bongos/cleanup-orphans.js +74 -0
- package/scripts/bongos/cli-lib.js +1226 -0
- package/scripts/bongos/client-baseurl-guard.js +116 -0
- package/scripts/bongos/codemod-rename-scripts-gds.js +381 -0
- package/scripts/bongos/codemod-rename-src-gds.js +145 -0
- package/scripts/bongos/conductor-dispatch.js +535 -0
- package/scripts/bongos/context-pack.js +326 -0
- package/scripts/bongos/control-manifest.js +199 -0
- package/scripts/bongos/copy-apply.js +758 -0
- package/scripts/bongos/copy-inventory.js +571 -0
- package/scripts/bongos/core-origin-follow.js +185 -0
- package/scripts/bongos/core-pin-sync.js +260 -0
- package/scripts/bongos/coreB-carve-proof.sh +725 -0
- package/scripts/bongos/cost-report.js +63 -0
- package/scripts/bongos/cost.js +47 -0
- package/scripts/bongos/credential-presence.js +296 -0
- package/scripts/bongos/cutover-codemod.js +240 -0
- package/scripts/bongos/db-backup-nightly.sh +232 -0
- package/scripts/bongos/db-backup-offsite.sh +267 -0
- package/scripts/bongos/demote.js +45 -0
- package/scripts/bongos/deploy-divergence.js +454 -0
- package/scripts/bongos/deploy-main-audit-gate.sh +97 -0
- package/scripts/bongos/design-sync.js +12 -0
- package/scripts/bongos/dev-box-guard.js +166 -0
- package/scripts/bongos/dev-lib.js +722 -0
- package/scripts/bongos/dev.js +645 -0
- package/scripts/bongos/device-flow-help.js +72 -0
- package/scripts/bongos/diagnose-achievements.js +118 -0
- package/scripts/bongos/diagram-facts.js +355 -0
- package/scripts/bongos/discord-channels.js +77 -0
- package/scripts/bongos/do-api.js +109 -0
- package/scripts/bongos/doc-cli-guard.js +274 -0
- package/scripts/bongos/doc-comment-coverage.js +139 -0
- package/scripts/bongos/doc-control-claims.js +170 -0
- package/scripts/bongos/docs-entropy.js +453 -0
- package/scripts/bongos/doctor.js +493 -0
- package/scripts/bongos/enroll-control-plane.js +101 -0
- package/scripts/bongos/exec-path-guard.js +564 -0
- package/scripts/bongos/feedback-send.js +249 -0
- package/scripts/bongos/fetch-art-key.js +106 -0
- package/scripts/bongos/fetch-sound-prefs.js +126 -0
- package/scripts/bongos/figma-design-sync.js +11 -0
- package/scripts/bongos/find-untested.js +371 -0
- package/scripts/bongos/fitness-checks-error-envelope.js +134 -0
- package/scripts/bongos/fitness-checks-identity.js +343 -0
- package/scripts/bongos/fitness-checks-packaging.js +132 -0
- package/scripts/bongos/fitness-checks-route-pins.js +76 -0
- package/scripts/bongos/fitness-checks-vocabulary.js +392 -0
- package/scripts/bongos/fitness-checks-write-validation.js +157 -0
- package/scripts/bongos/fitness-lib.js +127 -0
- package/scripts/bongos/fitness-migration-contraction.js +50 -0
- package/scripts/bongos/fitness-ratchets.js +594 -0
- package/scripts/bongos/fitness.js +1498 -0
- package/scripts/bongos/forwarder.js +80 -0
- package/scripts/bongos/gate-review.js +330 -0
- package/scripts/bongos/gating.js +348 -0
- package/scripts/{gds → bongos}/gds-db-backup.service +6 -6
- package/scripts/{gds → bongos}/gds-db-backup.timer +4 -4
- package/scripts/{gds → bongos}/gds-db-offsite.service +4 -4
- package/scripts/{gds → bongos}/gds-db-offsite.timer +4 -4
- package/scripts/bongos/gds-literal-scan.js +196 -0
- package/scripts/bongos/gen-api-client.js +576 -0
- package/scripts/bongos/gen-api-docs.js +1111 -0
- package/scripts/bongos/gen-atlas.js +366 -0
- package/scripts/bongos/gen-diagrams.js +608 -0
- package/scripts/bongos/gen-file-map.js +337 -0
- package/scripts/bongos/gen-freshness.js +32 -0
- package/scripts/bongos/gen-interaction-posture.js +122 -0
- package/scripts/bongos/gen-repo-map.js +540 -0
- package/scripts/bongos/gen-role-responsibilities.js +134 -0
- package/scripts/bongos/gen-session-index.js +243 -0
- package/scripts/bongos/gen-sounds.js +176 -0
- package/scripts/bongos/git-merge-regen.js +254 -0
- package/scripts/bongos/go-live.js +1071 -0
- package/scripts/bongos/goal-names.js +102 -0
- package/scripts/bongos/goal.js +272 -0
- package/scripts/bongos/government-walk.js +1477 -0
- package/scripts/bongos/grade-correlation-audit.js +310 -0
- package/scripts/bongos/grade-replay.js +237 -0
- package/scripts/bongos/grade-smoke.js +205 -0
- package/scripts/bongos/home-isolation-guard.js +126 -0
- package/scripts/bongos/hooks/pre-push.js +211 -0
- package/scripts/bongos/howto.js +145 -0
- package/scripts/bongos/http-api-client.js +81 -0
- package/scripts/bongos/identity-strip.js +75 -0
- package/scripts/bongos/init.js +1159 -0
- package/scripts/bongos/install-git-hooks.js +200 -0
- package/scripts/bongos/instance-apex.js +38 -0
- package/scripts/bongos/intent-retry.js +52 -0
- package/scripts/bongos/key-card.js +222 -0
- package/scripts/bongos/key-status.js +126 -0
- package/scripts/bongos/land-watch.js +201 -0
- package/scripts/bongos/leak-scan-allowlist.js +293 -0
- package/scripts/bongos/learning-capture.js +145 -0
- package/scripts/bongos/lib.sh +74 -0
- package/scripts/bongos/linkify-refs.js +655 -0
- package/scripts/bongos/lint-infra-exec.js +70 -0
- package/scripts/bongos/lint-migrations.js +102 -0
- package/scripts/bongos/lint-workflow-exec.js +63 -0
- package/scripts/bongos/local-preview-lib.js +128 -0
- package/scripts/bongos/local-preview.js +82 -0
- package/scripts/bongos/login.js +360 -0
- package/scripts/bongos/main-audit.js +625 -0
- package/scripts/bongos/me.js +97 -0
- package/scripts/bongos/memory-map.js +176 -0
- package/scripts/bongos/merge-lock.js +71 -0
- package/scripts/bongos/migration-namespace.js +313 -0
- package/scripts/bongos/mirror-lineage-check.js +343 -0
- package/scripts/bongos/mirror-redact.js +350 -0
- package/scripts/bongos/module-artifact.js +289 -0
- package/scripts/bongos/module-assess-docs.js +238 -0
- package/scripts/bongos/module-assess-installs.js +228 -0
- package/scripts/bongos/module-assess-score.js +111 -0
- package/scripts/bongos/module-assess-security.js +252 -0
- package/scripts/bongos/module-assess-tests.js +278 -0
- package/scripts/bongos/module-assess-version.js +92 -0
- package/scripts/bongos/module-error-report.js +148 -0
- package/scripts/{gds → bongos}/module-test-runner/README.md +3 -3
- package/scripts/{gds → bongos}/module-test-runner/module-tests.yml +2 -2
- package/scripts/bongos/module-test-runner.js +414 -0
- package/scripts/bongos/module.js +1376 -0
- package/scripts/bongos/move-escalation.js +141 -0
- package/scripts/{gds → bongos}/newcomer-floor.config.json +1 -1
- package/scripts/bongos/newcomer-floor.js +421 -0
- package/scripts/{gds → bongos}/newcomer-floor.templates.json +13 -13
- package/scripts/bongos/newcomer-floor.test.js +235 -0
- package/scripts/bongos/next-number.js +163 -0
- package/scripts/bongos/oauth-secret.js +202 -0
- package/scripts/bongos/onboard.js +267 -0
- package/scripts/bongos/onboarding-analyze.js +226 -0
- package/scripts/bongos/onboarding-config.js +179 -0
- package/scripts/bongos/onboarding-ship.js +92 -0
- package/scripts/bongos/pack-env-prefix.js +73 -0
- package/scripts/bongos/package-core.js +1200 -0
- package/scripts/bongos/page-inventory.js +348 -0
- package/scripts/bongos/page-reader.js +722 -0
- package/scripts/bongos/paste-token.js +212 -0
- package/scripts/bongos/plain-cards.js +351 -0
- package/scripts/bongos/portability-smoke-art.sh +85 -0
- package/scripts/bongos/portability-smoke-memory.sh +176 -0
- package/scripts/bongos/preflight.js +214 -0
- package/scripts/bongos/probe-cache.js +246 -0
- package/scripts/bongos/prove-strict-versioning.js +284 -0
- package/scripts/bongos/provision-auto-upgrade.js +162 -0
- package/scripts/bongos/provision-byo-host.js +68 -0
- package/scripts/bongos/provision-capacity.js +79 -0
- package/scripts/bongos/provision-caps.js +63 -0
- package/scripts/bongos/provision-config.js +233 -0
- package/scripts/bongos/provision-core-upgrade.js +1166 -0
- package/scripts/bongos/provision-disconnect.js +88 -0
- package/scripts/bongos/provision-github-setup.js +168 -0
- package/scripts/bongos/provision-net.js +357 -0
- package/scripts/bongos/provision-pin-key.js +176 -0
- package/scripts/bongos/provision-pin-replay.js +126 -0
- package/scripts/bongos/provision-process.js +170 -0
- package/scripts/bongos/provision-render.js +201 -0
- package/scripts/bongos/provision-repo-auth.js +164 -0
- package/scripts/bongos/provision-repo-private.js +98 -0
- package/scripts/bongos/provision-repo.js +1337 -0
- package/scripts/bongos/provision-teardown.js +106 -0
- package/scripts/bongos/provision-units.js +469 -0
- package/scripts/bongos/provision.js +1479 -0
- package/scripts/bongos/publish-credential-check.js +66 -0
- package/scripts/bongos/publish-integration-gate.js +142 -0
- package/scripts/bongos/publish-manifest.js +440 -0
- package/scripts/bongos/publish-watch.js +268 -0
- package/scripts/bongos/pulse.js +336 -0
- package/scripts/bongos/push-main.js +56 -0
- package/scripts/bongos/push-path-brief.js +100 -0
- package/scripts/bongos/read-session-export.js +359 -0
- package/scripts/bongos/reauth.js +155 -0
- package/scripts/bongos/recall.js +183 -0
- package/scripts/bongos/redteam-patrol.js +437 -0
- package/scripts/bongos/regen-instance-docs.js +47 -0
- package/scripts/bongos/release-core.js +80 -0
- package/scripts/bongos/release-notes.js +271 -0
- package/scripts/bongos/release.js +139 -0
- package/scripts/bongos/rename-goals.js +109 -0
- package/scripts/bongos/rename-history-check.js +369 -0
- package/scripts/bongos/rename-ledger-prose.js +482 -0
- package/scripts/bongos/render-api.js +197 -0
- package/scripts/bongos/render-check.js +206 -0
- package/scripts/bongos/render-ideas.js +226 -0
- package/scripts/bongos/render-payload.js +85 -0
- package/scripts/bongos/repo-metrics.js +363 -0
- package/scripts/bongos/review-sheet.js +108 -0
- package/scripts/bongos/role-pack-guard.js +142 -0
- package/scripts/bongos/route-shadow-guard.js +175 -0
- package/scripts/bongos/routine-schedule.js +283 -0
- package/scripts/bongos/run-routine.js +257 -0
- package/scripts/bongos/run-unit-tests.js +654 -0
- package/scripts/bongos/runner-drift.js +151 -0
- package/scripts/bongos/sandbox-stage.js +459 -0
- package/scripts/bongos/scope-map-guard.js +300 -0
- package/scripts/bongos/scope-roster-guard.js +118 -0
- package/scripts/bongos/seam-wiring-guard.js +275 -0
- package/scripts/bongos/search-ingest-db.js +288 -0
- package/scripts/bongos/search-ingest-md.js +269 -0
- package/scripts/bongos/seed-adopt-tasks.js +75 -0
- package/scripts/bongos/seed-api-contract-goal-tasks.js +141 -0
- package/scripts/bongos/seed-board-room-tasks.js +196 -0
- package/scripts/bongos/seed-bongos-app-tasks.js +294 -0
- package/scripts/bongos/seed-bongos-coreB-tranche1-tasks.js +81 -0
- package/scripts/bongos/seed-bongos-coreB-tranche2-tasks.js +100 -0
- package/scripts/bongos/seed-bongos-goal-hierarchy-tasks.js +307 -0
- package/scripts/bongos/seed-bongos-module-system-tasks.js +346 -0
- package/scripts/bongos/seed-bongos-tasks.js +214 -0
- package/scripts/bongos/seed-bongos-v1-idea-routing-tasks.js +152 -0
- package/scripts/bongos/seed-bongos-v1-seo-tasks.js +104 -0
- package/scripts/bongos/seed-bv1-community-tasks.js +131 -0
- package/scripts/bongos/seed-bv1-privacy-invites-tasks.js +133 -0
- package/scripts/bongos/seed-bv1-profile-page-tasks.js +161 -0
- package/scripts/bongos/seed-bv1-profiles-tasks.js +135 -0
- package/scripts/bongos/seed-bv1-r01-delta-tasks.js +154 -0
- package/scripts/bongos/seed-bv2-ideator-surface-tasks.js +390 -0
- package/scripts/bongos/seed-bv2-tweak-mode-tasks.js +277 -0
- package/scripts/bongos/seed-gds-v4-tasks.js +624 -0
- package/scripts/bongos/seed-governance-tasks.js +340 -0
- package/scripts/bongos/seed-medusa-tasks.js +440 -0
- package/scripts/bongos/seed-module-upstreaming.js +219 -0
- package/scripts/bongos/seed-productization-tasks.js +235 -0
- package/scripts/bongos/seed-project-admin-console-tasks.js +88 -0
- package/scripts/bongos/seed-provisioning-tasks.js +83 -0
- package/scripts/bongos/seed-staging.sh +117 -0
- package/scripts/bongos/seed-strict-versioning-tasks.js +275 -0
- package/scripts/bongos/seed-v2-world-tasks.js +283 -0
- package/scripts/bongos/seed-verify-criteria.js +124 -0
- package/scripts/bongos/sequence.js +597 -0
- package/scripts/bongos/session-cost.js +430 -0
- package/scripts/bongos/session-digest-build.js +293 -0
- package/scripts/bongos/session-digest.js +200 -0
- package/scripts/bongos/session-eval.js +631 -0
- package/scripts/bongos/session-transcript-build.js +155 -0
- package/scripts/bongos/session-transcript-upload.js +29 -0
- package/scripts/bongos/session.js +404 -0
- package/scripts/bongos/setup.js +646 -0
- package/scripts/bongos/ship-check.js +89 -0
- package/scripts/bongos/ship-deploy-target.js +393 -0
- package/scripts/bongos/ship-escalation.js +167 -0
- package/scripts/bongos/ship-finish.js +420 -0
- package/scripts/bongos/ship-flow.js +1217 -0
- package/scripts/bongos/ship-git.js +100 -0
- package/scripts/bongos/ship-grade-steps.js +547 -0
- package/scripts/bongos/ship-grade.js +426 -0
- package/scripts/bongos/ship-honesty.js +314 -0
- package/scripts/bongos/ship-io.js +139 -0
- package/scripts/bongos/ship-land.js +1130 -0
- package/scripts/bongos/ship-memory-sync.js +249 -0
- package/scripts/bongos/ship-merge-gate.js +225 -0
- package/scripts/bongos/ship-merge.js +466 -0
- package/scripts/bongos/ship-mode-ask.js +138 -0
- package/scripts/bongos/ship-mode-manual.js +54 -0
- package/scripts/bongos/ship-preflight-steps.js +399 -0
- package/scripts/bongos/ship-regen.js +292 -0
- package/scripts/bongos/ship-resume.js +201 -0
- package/scripts/bongos/ship-session-upload.js +313 -0
- package/scripts/bongos/ship-state.js +110 -0
- package/scripts/bongos/ship-surprise.js +84 -0
- package/scripts/bongos/ship-visual.js +75 -0
- package/scripts/bongos/ship.js +382 -0
- package/scripts/bongos/shipping-mode.js +71 -0
- package/scripts/bongos/skill-lint.js +250 -0
- package/scripts/bongos/skill-preflight.js +361 -0
- package/scripts/bongos/smoke-batch-claim.sh +238 -0
- package/scripts/bongos/smoke-batch-release.sh +316 -0
- package/scripts/bongos/smoke-claim-consistency.sh +222 -0
- package/scripts/bongos/smoke-dependencies.sh +143 -0
- package/scripts/bongos/smoke-gds.js +256 -0
- package/scripts/bongos/smoke-write.sh +275 -0
- package/scripts/bongos/source-text-test-scan.js +106 -0
- package/scripts/bongos/spark.js +294 -0
- package/scripts/bongos/stale-worktrees.js +212 -0
- package/scripts/bongos/start-goals.js +102 -0
- package/scripts/bongos/start.js +1090 -0
- package/scripts/bongos/status.js +545 -0
- package/scripts/bongos/strand-watch.js +315 -0
- package/scripts/bongos/stranded-rows.js +200 -0
- package/scripts/bongos/stray-unit-sweep.sh +71 -0
- package/scripts/bongos/surface.js +101 -0
- package/scripts/bongos/task.js +273 -0
- package/scripts/bongos/test-path-guard.js +99 -0
- package/scripts/bongos/triage.js +742 -0
- package/scripts/bongos/turn-end-sound.js +74 -0
- package/scripts/bongos/tweak-halt.js +70 -0
- package/scripts/bongos/tweak-renders.js +200 -0
- package/scripts/bongos/uat.js +120 -0
- package/scripts/bongos/ui-kit-transform.js +43 -0
- package/scripts/bongos/update-channel.js +512 -0
- package/scripts/bongos/update-sweep.js +829 -0
- package/scripts/bongos/upgrade-artist-gate.js +46 -0
- package/scripts/bongos/upgrade-commit-identity.js +32 -0
- package/scripts/bongos/upgrade-migrate.js +224 -0
- package/scripts/bongos/upgrade-operator.js +73 -0
- package/scripts/bongos/upgrade-outcome.js +174 -0
- package/scripts/bongos/upgrade.js +1499 -0
- package/scripts/bongos/validate-design.js +12 -0
- package/scripts/bongos/version-close.js +621 -0
- package/scripts/bongos/version-literal-guard.js +140 -0
- package/scripts/bongos/version-select.js +79 -0
- package/scripts/bongos/visual-review-nudge.js +39 -0
- package/scripts/bongos/wedge-remedy.js +174 -0
- package/scripts/bongos/worktree-claim-guard.js +130 -0
- package/scripts/bongos/worktree.js +449 -0
- package/scripts/discord/post.js +1 -1
- package/scripts/gds/README.md +9 -0
- package/scripts/gds/abandon.js +6 -136
- package/scripts/gds/accessibility-replay.js +5 -194
- package/scripts/gds/address-park-sweep.sh +7 -90
- package/scripts/gds/adopt-detect.js +5 -121
- package/scripts/gds/adopt-import.js +5 -109
- package/scripts/gds/adopt-preflight.js +5 -185
- package/scripts/gds/adr-namespace.js +5 -271
- package/scripts/gds/agent-invoke.js +5 -687
- package/scripts/gds/agents-sync.js +5 -500
- package/scripts/gds/api-alias-caller-scan.js +5 -255
- package/scripts/gds/api-artifacts.js +6 -0
- package/scripts/gds/api.js +6 -85
- package/scripts/gds/api.ps1 +8 -26
- package/scripts/gds/architect-audit.js +6 -293
- package/scripts/gds/artifact-audit.js +5 -324
- package/scripts/gds/artifact-format.js +6 -203
- package/scripts/gds/artifact-staleness.js +5 -265
- package/scripts/gds/ask.js +5 -229
- package/scripts/gds/audit-authorship.sh +7 -328
- package/scripts/gds/audit-deps.js +6 -188
- package/scripts/gds/audit-gate.js +5 -119
- package/scripts/gds/audit-rank-roles.js +6 -171
- package/scripts/gds/audit-replay.sh +7 -204
- package/scripts/gds/autobongos-digest.js +5 -121
- package/scripts/gds/autobongos-grade-cap.js +5 -186
- package/scripts/gds/autobongos-loop.js +5 -208
- package/scripts/gds/autobongos-run.js +5 -1359
- package/scripts/gds/autobongos-service.cmd +8 -49
- package/scripts/gds/autobongos-service.ps1 +8 -270
- package/scripts/gds/autobongos-tweak-lane.js +5 -261
- package/scripts/gds/autobongos-verify.js +5 -616
- package/scripts/gds/autonomy-gate.js +5 -133
- package/scripts/gds/autonomy-gauge-statusline.js +5 -122
- package/scripts/gds/autonomy-gauge.js +5 -82
- package/scripts/gds/backfill-cost.js +6 -175
- package/scripts/gds/backfill-disciplines.js +5 -142
- package/scripts/gds/backfill-session-earnings.js +5 -121
- package/scripts/gds/backfill-session-types.js +5 -85
- package/scripts/gds/backfill-sessions.js +5 -409
- package/scripts/gds/backfill-subagent-rewards.js +5 -483
- package/scripts/gds/backfill-task-rewards.js +5 -411
- package/scripts/gds/backlog-review.js +6 -398
- package/scripts/gds/backup-dropin-sweep.sh +7 -94
- package/scripts/gds/backup.js +6 -115
- package/scripts/gds/baseline-staleness.js +5 -215
- package/scripts/gds/bfg-principal-token.js +6 -64
- package/scripts/gds/bug-attachment-audit.js +5 -147
- package/scripts/gds/bug-attachment-recover.js +5 -196
- package/scripts/gds/bug-triage.js +6 -291
- package/scripts/gds/build-bongos.js +5 -92
- package/scripts/gds/bump-version.js +5 -219
- package/scripts/gds/capture.js +6 -480
- package/scripts/gds/category-advisory-guard.js +5 -205
- package/scripts/gds/ci-grade.js +6 -81
- package/scripts/gds/claim-recall.js +6 -111
- package/scripts/gds/claim.js +6 -788
- package/scripts/gds/classify-discipline.js +6 -152
- package/scripts/gds/claude-materialize.js +5 -1198
- package/scripts/gds/claude-md-template.js +5 -140
- package/scripts/gds/cleanup-orphans.js +6 -73
- package/scripts/gds/cli-lib.js +6 -1204
- package/scripts/gds/client-baseurl-guard.js +5 -114
- package/scripts/gds/codemod-rename-src-gds.js +6 -144
- package/scripts/gds/conductor-dispatch.js +6 -534
- package/scripts/gds/context-pack.js +6 -325
- package/scripts/gds/control-manifest.js +5 -197
- package/scripts/gds/copy-apply.js +5 -756
- package/scripts/gds/copy-inventory.js +5 -569
- package/scripts/gds/core-origin-follow.js +5 -184
- package/scripts/gds/core-pin-sync.js +5 -258
- package/scripts/gds/coreB-carve-proof.sh +7 -724
- package/scripts/gds/cost-report.js +6 -62
- package/scripts/gds/cost.js +6 -46
- package/scripts/gds/credential-presence.js +5 -294
- package/scripts/gds/cutover-codemod.js +5 -239
- package/scripts/gds/db-backup-nightly.sh +7 -231
- package/scripts/gds/db-backup-offsite.sh +7 -266
- package/scripts/gds/demote.js +6 -44
- package/scripts/gds/deploy-divergence.js +6 -445
- package/scripts/gds/deploy-main-audit-gate.sh +7 -96
- package/scripts/gds/design-sync.js +5 -10
- package/scripts/gds/dev-box-guard.js +5 -164
- package/scripts/gds/dev-lib.js +5 -721
- package/scripts/gds/dev.js +5 -643
- package/scripts/gds/device-flow-help.js +5 -70
- package/scripts/gds/diagnose-achievements.js +5 -116
- package/scripts/gds/diagram-facts.js +6 -355
- package/scripts/gds/discord-channels.js +5 -75
- package/scripts/gds/do-api.js +6 -109
- package/scripts/gds/doc-cli-guard.js +5 -266
- package/scripts/gds/doc-comment-coverage.js +5 -137
- package/scripts/gds/doc-control-claims.js +5 -166
- package/scripts/gds/docs-entropy.js +5 -443
- package/scripts/gds/doctor.js +6 -492
- package/scripts/gds/enroll-control-plane.js +5 -99
- package/scripts/gds/exec-path-guard.js +5 -562
- package/scripts/gds/feedback-send.js +5 -247
- package/scripts/gds/fetch-art-key.js +5 -104
- package/scripts/gds/fetch-sound-prefs.js +5 -124
- package/scripts/gds/figma-design-sync.js +5 -9
- package/scripts/gds/find-untested.js +5 -369
- package/scripts/gds/fitness-checks-error-envelope.js +5 -133
- package/scripts/gds/fitness-checks-identity.js +5 -342
- package/scripts/gds/fitness-checks-packaging.js +5 -131
- package/scripts/gds/fitness-checks-route-pins.js +5 -75
- package/scripts/gds/fitness-checks-vocabulary.js +5 -391
- package/scripts/gds/fitness-checks-write-validation.js +5 -156
- package/scripts/gds/fitness-lib.js +5 -126
- package/scripts/gds/fitness-migration-contraction.js +5 -49
- package/scripts/gds/fitness-ratchets.js +5 -563
- package/scripts/gds/fitness.js +5 -1493
- package/scripts/gds/gate-review.js +5 -328
- package/scripts/gds/gating.js +5 -346
- package/scripts/gds/gds-literal-scan.js +5 -194
- package/scripts/gds/gen-api-client.js +5 -555
- package/scripts/gds/gen-api-docs.js +5 -1100
- package/scripts/gds/gen-atlas.js +5 -364
- package/scripts/gds/gen-diagrams.js +6 -607
- package/scripts/gds/gen-file-map.js +5 -335
- package/scripts/gds/gen-freshness.js +5 -31
- package/scripts/gds/gen-interaction-posture.js +5 -120
- package/scripts/gds/gen-repo-map.js +5 -538
- package/scripts/gds/gen-role-responsibilities.js +5 -133
- package/scripts/gds/gen-session-index.js +5 -241
- package/scripts/gds/gen-sounds.js +5 -174
- package/scripts/gds/git-merge-regen.js +6 -291
- package/scripts/gds/go-live.js +5 -1069
- package/scripts/gds/goal-names.js +5 -100
- package/scripts/gds/goal.js +6 -271
- package/scripts/gds/government-walk.js +5 -1475
- package/scripts/gds/grade-correlation-audit.js +5 -308
- package/scripts/gds/grade-replay.js +5 -235
- package/scripts/gds/grade-smoke.js +6 -204
- package/scripts/gds/home-isolation-guard.js +5 -125
- package/scripts/gds/hooks/pre-push.js +5 -209
- package/scripts/gds/howto.js +5 -143
- package/scripts/gds/http-api-client.js +6 -81
- package/scripts/gds/identity-strip.js +5 -74
- package/scripts/gds/init.js +5 -1157
- package/scripts/gds/install-git-hooks.js +5 -198
- package/scripts/gds/instance-apex.js +5 -37
- package/scripts/gds/intent-retry.js +5 -51
- package/scripts/gds/key-card.js +6 -221
- package/scripts/gds/key-status.js +5 -124
- package/scripts/gds/land-watch.js +5 -199
- package/scripts/gds/leak-scan-allowlist.js +5 -291
- package/scripts/gds/learning-capture.js +6 -144
- package/scripts/gds/lib.sh +7 -73
- package/scripts/gds/linkify-refs.js +6 -654
- package/scripts/gds/lint-infra-exec.js +5 -68
- package/scripts/gds/lint-migrations.js +5 -100
- package/scripts/gds/lint-workflow-exec.js +5 -61
- package/scripts/gds/local-preview-lib.js +6 -128
- package/scripts/gds/local-preview.js +6 -81
- package/scripts/gds/login.js +5 -358
- package/scripts/gds/main-audit.js +5 -623
- package/scripts/gds/me.js +6 -96
- package/scripts/gds/memory-map.js +5 -174
- package/scripts/gds/merge-lock.js +6 -70
- package/scripts/gds/migration-namespace.js +5 -311
- package/scripts/gds/mirror-lineage-check.js +5 -341
- package/scripts/gds/mirror-redact.js +5 -348
- package/scripts/gds/module-artifact.js +6 -289
- package/scripts/gds/module-assess-docs.js +6 -237
- package/scripts/gds/module-assess-installs.js +6 -227
- package/scripts/gds/module-assess-score.js +6 -110
- package/scripts/gds/module-assess-security.js +6 -251
- package/scripts/gds/module-assess-tests.js +6 -277
- package/scripts/gds/module-assess-version.js +6 -91
- package/scripts/gds/module-error-report.js +5 -146
- package/scripts/gds/module-test-runner.js +6 -413
- package/scripts/gds/module.js +5 -1374
- package/scripts/gds/move-escalation.js +5 -140
- package/scripts/gds/newcomer-floor.js +6 -420
- package/scripts/gds/newcomer-floor.test.js +6 -234
- package/scripts/gds/next-number.js +6 -162
- package/scripts/gds/oauth-secret.js +5 -200
- package/scripts/gds/onboard.js +5 -265
- package/scripts/gds/onboarding-analyze.js +6 -225
- package/scripts/gds/onboarding-config.js +6 -179
- package/scripts/gds/onboarding-ship.js +6 -91
- package/scripts/gds/pack-env-prefix.js +5 -72
- package/scripts/gds/package-core.js +5 -1102
- package/scripts/gds/page-inventory.js +5 -346
- package/scripts/gds/page-reader.js +5 -720
- package/scripts/gds/paste-token.js +6 -211
- package/scripts/gds/plain-cards.js +5 -350
- package/scripts/gds/portability-smoke-art.sh +7 -84
- package/scripts/gds/portability-smoke-memory.sh +7 -175
- package/scripts/gds/preflight.js +5 -212
- package/scripts/gds/probe-cache.js +5 -244
- package/scripts/gds/prove-strict-versioning.js +6 -283
- package/scripts/gds/provision-auto-upgrade.js +5 -161
- package/scripts/gds/provision-byo-host.js +5 -67
- package/scripts/gds/provision-capacity.js +5 -78
- package/scripts/gds/provision-caps.js +5 -62
- package/scripts/gds/provision-config.js +5 -232
- package/scripts/gds/provision-core-upgrade.js +5 -1165
- package/scripts/gds/provision-disconnect.js +5 -87
- package/scripts/gds/provision-github-setup.js +5 -167
- package/scripts/gds/provision-net.js +5 -356
- package/scripts/gds/provision-pin-key.js +5 -175
- package/scripts/gds/provision-pin-replay.js +5 -125
- package/scripts/gds/provision-process.js +5 -169
- package/scripts/gds/provision-render.js +5 -200
- package/scripts/gds/provision-repo-auth.js +5 -163
- package/scripts/gds/provision-repo-private.js +5 -97
- package/scripts/gds/provision-repo.js +5 -1336
- package/scripts/gds/provision-teardown.js +5 -105
- package/scripts/gds/provision-units.js +5 -468
- package/scripts/gds/provision.js +5 -1477
- package/scripts/gds/publish-credential-check.js +6 -65
- package/scripts/gds/publish-integration-gate.js +5 -140
- package/scripts/gds/publish-manifest.js +5 -437
- package/scripts/gds/publish-watch.js +5 -266
- package/scripts/gds/pulse.js +6 -335
- package/scripts/gds/push-main.js +5 -54
- package/scripts/gds/push-path-brief.js +5 -98
- package/scripts/gds/read-session-export.js +5 -357
- package/scripts/gds/reauth.js +6 -154
- package/scripts/gds/recall.js +6 -182
- package/scripts/gds/redteam-patrol.js +5 -435
- package/scripts/gds/regen-instance-docs.js +5 -45
- package/scripts/gds/release-core.js +5 -78
- package/scripts/gds/release-notes.js +5 -270
- package/scripts/gds/release.js +6 -138
- package/scripts/gds/rename-goals.js +5 -107
- package/scripts/gds/rename-history-check.js +5 -367
- package/scripts/gds/rename-ledger-prose.js +5 -480
- package/scripts/gds/render-api.js +5 -196
- package/scripts/gds/render-check.js +5 -204
- package/scripts/gds/render-ideas.js +6 -225
- package/scripts/gds/render-payload.js +5 -84
- package/scripts/gds/repo-metrics.js +6 -362
- package/scripts/gds/review-sheet.js +5 -106
- package/scripts/gds/role-pack-guard.js +5 -141
- package/scripts/gds/route-shadow-guard.js +5 -173
- package/scripts/gds/routine-schedule.js +5 -281
- package/scripts/gds/run-routine.js +5 -255
- package/scripts/gds/run-unit-tests.js +6 -659
- package/scripts/gds/runner-drift.js +5 -149
- package/scripts/gds/sandbox-stage.js +6 -458
- package/scripts/gds/scope-map-guard.js +5 -299
- package/scripts/gds/scope-roster-guard.js +5 -117
- package/scripts/gds/seam-wiring-guard.js +5 -274
- package/scripts/gds/search-ingest-db.js +6 -287
- package/scripts/gds/search-ingest-md.js +6 -268
- package/scripts/gds/seed-adopt-tasks.js +6 -74
- package/scripts/gds/seed-api-contract-goal-tasks.js +6 -140
- package/scripts/gds/seed-board-room-tasks.js +6 -196
- package/scripts/gds/seed-bongos-app-tasks.js +6 -293
- package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +6 -80
- package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +6 -99
- package/scripts/gds/seed-bongos-goal-hierarchy-tasks.js +6 -306
- package/scripts/gds/seed-bongos-module-system-tasks.js +6 -345
- package/scripts/gds/seed-bongos-tasks.js +6 -213
- package/scripts/gds/seed-bongos-v1-idea-routing-tasks.js +6 -152
- package/scripts/gds/seed-bongos-v1-seo-tasks.js +6 -104
- package/scripts/gds/seed-bv1-community-tasks.js +6 -131
- package/scripts/gds/seed-bv1-privacy-invites-tasks.js +6 -133
- package/scripts/gds/seed-bv1-profile-page-tasks.js +6 -161
- package/scripts/gds/seed-bv1-profiles-tasks.js +6 -135
- package/scripts/gds/seed-bv1-r01-delta-tasks.js +6 -154
- package/scripts/gds/seed-bv2-ideator-surface-tasks.js +6 -390
- package/scripts/gds/seed-bv2-tweak-mode-tasks.js +6 -277
- package/scripts/gds/seed-gds-v4-tasks.js +6 -623
- package/scripts/gds/seed-governance-tasks.js +6 -339
- package/scripts/gds/seed-medusa-tasks.js +6 -439
- package/scripts/gds/seed-module-upstreaming.js +5 -217
- package/scripts/gds/seed-productization-tasks.js +6 -234
- package/scripts/gds/seed-project-admin-console-tasks.js +6 -88
- package/scripts/gds/seed-provisioning-tasks.js +6 -82
- package/scripts/gds/seed-staging.sh +7 -116
- package/scripts/gds/seed-strict-versioning-tasks.js +6 -274
- package/scripts/gds/seed-v2-world-tasks.js +6 -282
- package/scripts/gds/seed-verify-criteria.js +6 -124
- package/scripts/gds/sequence.js +6 -596
- package/scripts/gds/session-cost.js +6 -429
- package/scripts/gds/session-digest-build.js +6 -293
- package/scripts/gds/session-digest.js +6 -199
- package/scripts/gds/session-eval.js +6 -630
- package/scripts/gds/session-transcript-build.js +6 -155
- package/scripts/gds/session-transcript-upload.js +6 -29
- package/scripts/gds/session.js +6 -403
- package/scripts/gds/setup.js +6 -645
- package/scripts/gds/ship-check.js +5 -85
- package/scripts/gds/ship-deploy-target.js +5 -392
- package/scripts/gds/ship-escalation.js +5 -166
- package/scripts/gds/ship-finish.js +5 -419
- package/scripts/gds/ship-flow.js +5 -1216
- package/scripts/gds/ship-git.js +5 -99
- package/scripts/gds/ship-grade-steps.js +5 -546
- package/scripts/gds/ship-grade.js +5 -425
- package/scripts/gds/ship-honesty.js +5 -312
- package/scripts/gds/ship-io.js +5 -138
- package/scripts/gds/ship-land.js +5 -1129
- package/scripts/gds/ship-memory-sync.js +5 -248
- package/scripts/gds/ship-merge-gate.js +5 -224
- package/scripts/gds/ship-merge.js +5 -465
- package/scripts/gds/ship-mode-ask.js +5 -137
- package/scripts/gds/ship-mode-manual.js +5 -53
- package/scripts/gds/ship-preflight-steps.js +5 -398
- package/scripts/gds/ship-regen.js +5 -313
- package/scripts/gds/ship-resume.js +5 -200
- package/scripts/gds/ship-session-upload.js +5 -312
- package/scripts/gds/ship-state.js +5 -109
- package/scripts/gds/ship-surprise.js +5 -83
- package/scripts/gds/ship-visual.js +5 -74
- package/scripts/gds/ship.js +5 -380
- package/scripts/gds/shipping-mode.js +5 -69
- package/scripts/gds/skill-lint.js +5 -248
- package/scripts/gds/skill-preflight.js +5 -359
- package/scripts/gds/smoke-batch-claim.sh +7 -237
- package/scripts/gds/smoke-batch-release.sh +7 -315
- package/scripts/gds/smoke-claim-consistency.sh +7 -221
- package/scripts/gds/smoke-dependencies.sh +7 -142
- package/scripts/gds/smoke-gds.js +6 -255
- package/scripts/gds/smoke-write.sh +7 -274
- package/scripts/gds/source-text-test-scan.js +7 -0
- package/scripts/gds/spark.js +6 -293
- package/scripts/gds/stale-worktrees.js +5 -210
- package/scripts/gds/start-goals.js +5 -101
- package/scripts/gds/start.js +6 -1089
- package/scripts/gds/status.js +6 -544
- package/scripts/gds/strand-watch.js +5 -313
- package/scripts/gds/stranded-rows.js +5 -198
- package/scripts/gds/stray-unit-sweep.sh +7 -70
- package/scripts/gds/surface.js +5 -100
- package/scripts/gds/task.js +6 -272
- package/scripts/gds/test-path-guard.js +5 -97
- package/scripts/gds/triage.js +6 -741
- package/scripts/gds/turn-end-sound.js +5 -72
- package/scripts/gds/tweak-halt.js +5 -68
- package/scripts/gds/tweak-renders.js +5 -198
- package/scripts/gds/uat.js +6 -119
- package/scripts/gds/ui-kit-transform.js +5 -41
- package/scripts/gds/update-channel.js +5 -510
- package/scripts/gds/update-sweep.js +5 -827
- package/scripts/gds/upgrade-artist-gate.js +5 -45
- package/scripts/gds/upgrade-commit-identity.js +5 -31
- package/scripts/gds/upgrade-migrate.js +5 -223
- package/scripts/gds/upgrade-operator.js +6 -73
- package/scripts/gds/upgrade-outcome.js +5 -173
- package/scripts/gds/upgrade.js +5 -1497
- package/scripts/gds/validate-design.js +5 -10
- package/scripts/gds/version-close.js +6 -620
- package/scripts/gds/version-literal-guard.js +5 -138
- package/scripts/gds/version-select.js +5 -77
- package/scripts/gds/visual-review-nudge.js +5 -38
- package/scripts/gds/wedge-remedy.js +5 -173
- package/scripts/gds/worktree-claim-guard.js +5 -129
- package/scripts/gds/worktree.js +6 -448
- package/scripts/hall-preview/refresh-fixtures.js +1 -1
- package/scripts/hall-preview/server.js +2 -2
- package/scripts/migrate.sh +3 -3
- package/scripts/public-mirror-export.js +3 -3
- package/scripts/setup-builder.js +7 -7
- package/src/bongos/api-errors.js +1 -0
- package/src/bongos/api-prefix.js +1 -1
- package/src/bongos/auth-github.js +19 -3
- package/src/bongos/auth-idp.js +7 -0
- package/src/bongos/claim-attribution.js +2 -2
- package/src/bongos/core-moves.js +1 -1
- package/src/bongos/core-update.js +3 -3
- package/src/bongos/craft-mode.js +2 -2
- package/src/bongos/db-kernel.js +15 -3
- package/src/bongos/db.js +30 -4
- package/src/bongos/github-repos.js +1 -1
- package/src/bongos/llm-cache.js +1 -1
- package/src/bongos/llm-pricing.js +1 -1
- package/src/bongos/metrics.js +1 -1
- package/src/bongos/middleware/rate-limit.js +2 -2
- package/src/bongos/module-listing.js +93 -1
- package/src/bongos/module-scope-map.js +90 -85
- package/src/bongos/module-store.js +1 -1
- package/src/bongos/module-submissions.js +1 -1
- package/src/bongos/optimizer.js +1 -1
- package/src/bongos/package-registry.js +1 -1
- package/src/bongos/path-match.js +1 -1
- package/src/bongos/permission-path-check.js +3 -3
- package/src/bongos/platform-visibility-gate.js +3 -5
- package/src/bongos/prelaunch-gate.js +7 -6
- package/src/bongos/route-rank-check.js +2 -2
- package/src/bongos/routes/auth.js +15 -2
- package/src/bongos/routes/backup.js +1 -1
- package/src/bongos/routes/builders.js +29 -1
- package/src/bongos/routes/me.js +49 -18
- package/src/bongos/routes/modules.js +29 -9
- package/src/bongos/routes/public.js +3 -72
- package/src/bongos/schema-lag.js +1 -1
- package/src/bongos/sensitive-surfaces.js +1 -1
- package/src/bongos/serve-internal.js +65 -16
- package/src/bongos/software-update.js +2 -2
- package/src/bongos/upgrade-hold.js +3 -3
- package/src/hall-look.js +6 -5
- package/src/module-api.js +3 -3
- package/src/module-loader/catalog.js +1 -1
- package/src/module-loader/error-tally.js +3 -3
- package/src/module-loader/manifest-schema.js +3 -3
- package/src/platform-server.js +10 -0
- package/src/role-responsibilities.js +1 -1
- package/src/stale-timer.js +2 -2
- package/tests/accessibility_replay.mjs +1 -1
- package/tests/activity_rollup_order_db.mjs +1 -1
- package/tests/activity_snapshots_db.mjs +1 -1
- package/tests/adopt_detect.mjs +1 -1
- package/tests/adopt_import.mjs +1 -1
- package/tests/adopt_preflight.mjs +1 -1
- package/tests/adr_0089_scope.mjs +10 -7
- package/tests/adr_0162_citation.mjs +1 -1
- package/tests/adr_0162_gate_citation.mjs +1 -1
- package/tests/agent_invoke.mjs +1 -1
- package/tests/agent_invoke_live.mjs +3 -3
- package/tests/agents_cron_trigger.mjs +2 -2
- package/tests/agents_roster.mjs +1 -1
- package/tests/agents_sync.mjs +4 -4
- package/tests/allow_rule_guard.mjs +20 -20
- package/tests/api_alias_caller_ratchet.mjs +9 -10
- package/tests/api_alias_exceptions.mjs +7 -6
- package/tests/api_artifacts.mjs +214 -0
- package/tests/api_cli_flags.mjs +3 -3
- package/tests/api_client.mjs +56 -54
- package/tests/api_docs.mjs +30 -9
- package/tests/api_error_envelope_buildcheck.mjs +1 -1
- package/tests/api_msys_path_repair.mjs +2 -2
- package/tests/architect.mjs +1 -1
- package/tests/art_stage.mjs +2 -2
- package/tests/artifact_audit.mjs +2 -2
- package/tests/artifact_staleness.mjs +9 -9
- package/tests/atlas.mjs +1 -1
- package/tests/audit_deps.mjs +1 -1
- package/tests/audit_gate.mjs +1 -1
- package/tests/auth_flow_slice1.mjs +3 -3
- package/tests/auth_inactive_builder.mjs +43 -5
- package/tests/auth_session_expiry_db.mjs +16 -4
- package/tests/auth_session_ttl.mjs +23 -0
- package/tests/authorship_audit.mjs +2 -2
- package/tests/autobongos_cadence.mjs +1 -1
- package/tests/autobongos_fence.mjs +1 -1
- package/tests/autobongos_grade_cap.mjs +2 -2
- package/tests/autobongos_heartbeat_head.mjs +1 -1
- package/tests/autobongos_host_access.mjs +3 -3
- package/tests/autobongos_loop.mjs +17 -17
- package/tests/autobongos_service_ps1.mjs +3 -3
- package/tests/autobongos_tweak_lane.mjs +2 -2
- package/tests/autobongos_verify.mjs +2 -2
- package/tests/autonomous_fit_protected_paths.mjs +3 -3
- package/tests/autonomy_config_idle.mjs +1 -1
- package/tests/autonomy_digest.mjs +1 -1
- package/tests/autonomy_gate.mjs +1 -1
- package/tests/autonomy_gauge.mjs +2 -2
- package/tests/autonomy_runner_identity.mjs +1 -1
- package/tests/backfill_sessions.mjs +8 -8
- package/tests/backfill_subagent_rewards.mjs +1 -1
- package/tests/backfill_task_rewards.mjs +2 -2
- package/tests/backlog_review.mjs +3 -3
- package/tests/baseline_staleness.mjs +2 -2
- package/tests/bfg.mjs +11 -5
- package/tests/bfg_write.mjs +20 -11
- package/tests/blockers_hall.mjs +14 -4
- package/tests/blockers_page_ui.mjs +56 -12
- package/tests/bongos_dispatch.mjs +5 -5
- package/tests/bongos_login.mjs +2 -2
- package/tests/bug_attachment_audit.mjs +1 -1
- package/tests/bug_attachment_recover.mjs +2 -2
- package/tests/bug_triage.mjs +3 -3
- package/tests/build_info.mjs +1 -1
- package/tests/builder_tester_tag.mjs +184 -0
- package/tests/bump_version.mjs +3 -3
- package/tests/canonical_profile_url.mjs +1 -1
- package/tests/capture_error_format.mjs +1 -1
- package/tests/capture_goal_routing.mjs +2 -2
- package/tests/category_advisory_guard.mjs +3 -3
- package/tests/claim_error_surface.mjs +2 -2
- package/tests/claim_from_task_and_home.mjs +1 -1
- package/tests/claim_gate_open_blocker.mjs +7 -4
- package/tests/claim_gate_rebase.mjs +12 -8
- package/tests/claim_recall.mjs +4 -4
- package/tests/claim_resolve_worktree_lock.mjs +1 -1
- package/tests/claude_materialize.mjs +58 -58
- package/tests/clawback_confirmed_backlog.mjs +8 -5
- package/tests/cli_allowlist_permissions.mjs +11 -11
- package/tests/cli_dispatcher.mjs +2 -2
- package/tests/cli_err_code.mjs +6 -6
- package/tests/cli_exit_no_abort.mjs +7 -7
- package/tests/cli_lib_formatters.mjs +2 -2
- package/tests/cli_sessions.mjs +5 -5
- package/tests/cli_surface.mjs +15 -15
- package/tests/cli_token_reissue.mjs +2 -2
- package/tests/client_baseurl_guard.mjs +1 -1
- package/tests/client_bundle_route.mjs +35 -4
- package/tests/cloud_bongos_pack.mjs +1 -1
- package/tests/community_leaderboard_db.mjs +1 -1
- package/tests/conductor.mjs +18 -18
- package/tests/conflict_resolve.mjs +14 -16
- package/tests/consumer_layout_boot.mjs +12 -12
- package/tests/context_pack.mjs +6 -6
- package/tests/control_manifest.mjs +4 -4
- package/tests/copy_desk_page_reads.mjs +1 -1
- package/tests/copy_desk_page_release.mjs +192 -0
- package/tests/copy_inventory.mjs +2 -2
- package/tests/core_auto_upgrade.mjs +1 -1
- package/tests/core_move_notice.mjs +2 -2
- package/tests/core_origin_follow.mjs +7 -7
- package/tests/core_pin_sync.mjs +3 -3
- package/tests/core_upgrade_door.mjs +2 -2
- package/tests/core_upgrade_owner_door.mjs +34 -1
- package/tests/core_upgrade_runner.mjs +19 -19
- package/tests/credential_presence.mjs +2 -2
- package/tests/credit_grant.mjs +3 -3
- package/tests/credit_log_single_writer.mjs +5 -5
- package/tests/criterion_ref_status.mjs +2 -2
- package/tests/cross_discipline_priority_direction.mjs +3 -3
- package/tests/cutover_codemod.mjs +2 -4
- package/tests/db_backup_nightly.mjs +1 -1
- package/tests/db_backup_offsite.mjs +1 -1
- package/tests/db_ownership_handover.mjs +2 -2
- package/tests/dead_deps.mjs +3 -3
- package/tests/dependency_advisory.mjs +1 -1
- package/tests/deploy_audit_gate.mjs +4 -4
- package/tests/deploy_divergence_line.mjs +36 -16
- package/tests/deploy_page_projects.mjs +35 -4
- package/tests/dev_lib.mjs +2 -2
- package/tests/dev_windows.mjs +2 -2
- package/tests/diagram_facts_offset.mjs +1 -1
- package/tests/diagram_repo_slug.mjs +1 -1
- package/tests/diff_derived_signals.mjs +2 -2
- package/tests/dns_preflight.mjs +2 -2
- package/tests/do_api.mjs +3 -3
- package/tests/doc_cli_guard.mjs +28 -28
- package/tests/doc_comment_coverage.mjs +1 -1
- package/tests/doc_control_claims.mjs +11 -11
- package/tests/docs_entropy.mjs +2 -2
- package/tests/docs_openapi_route.mjs +8 -6
- package/tests/doctor_hooks.mjs +1 -1
- package/tests/edit_hints.mjs +3 -2
- package/tests/effective_visibility_predicate.mjs +3 -3
- package/tests/env_knobs_neutral_prefix.mjs +13 -13
- package/tests/exec_path_guard.mjs +4 -4
- package/tests/executed_closure.mjs +18 -12
- package/tests/file_map.mjs +1 -1
- package/tests/find_untested.mjs +13 -13
- package/tests/first_admin_bootstrap.mjs +1 -1
- package/tests/fitness.mjs +16 -16
- package/tests/fitness_gds_ratchet.mjs +2 -2
- package/tests/fitness_installed_core.mjs +3 -3
- package/tests/fitness_no_raw_nul.mjs +1 -1
- package/tests/fitness_ratchets.mjs +3 -3
- package/tests/fitness_scope_roster.mjs +2 -2
- package/tests/fitness_two_root.mjs +8 -8
- package/tests/fixtures/accessibility-replay.json +5 -5
- package/tests/fixtures/grade-replay/recorded-panel-grades.json +1 -1
- package/tests/fixtures/ideator-prefold/README.md +1 -1
- package/tests/fixtures/page-ledger.mjs +22 -0
- package/tests/fixtures/session-506-digest.json +5 -5
- package/tests/gate_approvals.mjs +50 -0
- package/tests/gate_review.mjs +8 -8
- package/tests/gating_review_retired.mjs +2 -2
- package/tests/gen_freshness.mjs +3 -3
- package/tests/git_guard.mjs +3 -3
- package/tests/git_merge_regen.mjs +41 -65
- package/tests/github_one_trip.mjs +4 -4
- package/tests/github_pick_up.mjs +2 -2
- package/tests/github_push_merge_driver.mjs +1 -1
- package/tests/go_live.mjs +3 -2
- package/tests/goal_category.mjs +1 -1
- package/tests/goal_cli.mjs +2 -2
- package/tests/goal_create_spec_entry.mjs +1 -1
- package/tests/goal_invite_consent.mjs +3 -1
- package/tests/goal_move.mjs +1 -1
- package/tests/goal_names.mjs +2 -2
- package/tests/goal_working_area.mjs +1 -1
- package/tests/government_agent_asks.mjs +7 -7
- package/tests/government_board_room_copy.mjs +6 -1
- package/tests/government_board_view.mjs +39 -0
- package/tests/government_board_vote_ui.mjs +39 -1
- package/tests/government_config.mjs +2 -2
- package/tests/government_live_proof_shape.mjs +1 -1
- package/tests/government_protected_surfaces.mjs +54 -53
- package/tests/government_require_permission.mjs +9 -1
- package/tests/government_vanilla_boot.mjs +1 -1
- package/tests/government_vocabulary.mjs +2 -2
- package/tests/government_walk.mjs +2 -2
- package/tests/grade_body_limit.mjs +6 -4
- package/tests/grade_correlation_audit.mjs +3 -3
- package/tests/grade_diff_hash.mjs +1 -1
- package/tests/grade_engine_replay.mjs +2 -2
- package/tests/grade_server_authoritative.mjs +1 -1
- package/tests/grade_unavailable_display.mjs +1 -1
- package/tests/grader.mjs +8 -24
- package/tests/grader_generated_provenance.mjs +14 -14
- package/tests/grader_no_artifact.mjs +1 -1
- package/tests/grader_prompt_fencing.mjs +1 -1
- package/tests/grader_quality_window_overflow.mjs +1 -1
- package/tests/grader_reader_lens.mjs +3 -3
- package/tests/grader_regrade_delta.mjs +1 -1
- package/tests/grader_unbacked_score.mjs +2 -2
- package/tests/hall_acclaim_vote_control.mjs +113 -0
- package/tests/hall_asset_cache.mjs +127 -0
- package/tests/hall_audit.mjs +63 -0
- package/tests/hall_board_world.mjs +20 -0
- package/tests/hall_city_card_words.mjs +61 -0
- package/tests/hall_client_request_shape.mjs +5 -1
- package/tests/hall_home_ships_bounded.mjs +160 -0
- package/tests/hall_landing_boot.mjs +15 -2
- package/tests/hall_nav.mjs +33 -0
- package/tests/hall_onboarding_bongos_setup.mjs +1 -1
- package/tests/hall_oversight_world.mjs +44 -4
- package/tests/hall_palette.mjs +12 -9
- package/tests/hall_preview_security.mjs +1 -1
- package/tests/hall_profile_world.mjs +17 -0
- package/tests/hall_reading_world.mjs +16 -1
- package/tests/hall_roster_world.mjs +2 -1
- package/tests/hall_studio_world.mjs +4 -1
- package/tests/hall_work_history_id.mjs +39 -0
- package/tests/held_tweak_reporting.mjs +4 -4
- package/tests/helpers.mjs +3 -3
- package/tests/home_bounded_reads.mjs +1 -1
- package/tests/home_isolation_guard.mjs +1 -1
- package/tests/hook_core_resolve.mjs +7 -7
- package/tests/hook_user_agents.mjs +1 -1
- package/tests/hooks_drain.mjs +2 -2
- package/tests/host_topology_skips.mjs +1 -1
- package/tests/howto_guide.mjs +1 -1
- package/tests/howto_moments.mjs +3 -3
- package/tests/hub_account_page.mjs +1 -1
- package/tests/idea_capture_grades.mjs +2 -2
- package/tests/idea_develop_spark.mjs +1 -1
- package/tests/idea_filed_via.mjs +2 -2
- package/tests/idea_ideate_full.mjs +1 -1
- package/tests/idea_spark_mark.mjs +1 -1
- package/tests/idea_spark_queue.mjs +1 -1
- package/tests/idea_triage.mjs +1 -1
- package/tests/idea_triage_grade.mjs +3 -3
- package/tests/idea_vote_permission.mjs +113 -0
- package/tests/idea_votes_fold_db.mjs +123 -0
- package/tests/infra_exec_paths.mjs +12 -12
- package/tests/init.mjs +2 -2
- package/tests/instance_db_migrated_on_code_move.mjs +5 -5
- package/tests/instance_feedback.mjs +9 -9
- package/tests/instance_mismatch_guard.mjs +2 -2
- package/tests/integration_parked_ratchet.mjs +24 -2
- package/tests/intent_retry.mjs +1 -1
- package/tests/interaction_posture.mjs +3 -3
- package/tests/invite_expiry_db.mjs +1 -1
- package/tests/joinability_invite_only.mjs +1 -1
- package/tests/karma_vote_lists.mjs +270 -0
- package/tests/key-card.mjs +2 -2
- package/tests/key-status.mjs +2 -2
- package/tests/knip_ratchet_ambient.mjs +2 -2
- package/tests/known_failing_ratchet.mjs +1 -1
- package/tests/land_watch.mjs +2 -2
- package/tests/landing_legal_pages.mjs +1 -1
- package/tests/landing_page.mjs +2 -2
- package/tests/leaderboard_roles.mjs +4 -1
- package/tests/leak_scan_allowlist.mjs +8 -8
- package/tests/leak_scan_fail_closed.mjs +1 -1
- package/tests/lib_sh_resolution.mjs +9 -9
- package/tests/lifecycle-card.mjs +7 -7
- package/tests/linkify_check.mjs +2 -2
- package/tests/linkify_refs.mjs +1 -1
- package/tests/llm-cache-route.mjs +1 -1
- package/tests/local_preview.mjs +2 -2
- package/tests/main_audit.mjs +3 -3
- package/tests/main_audit_attestation.mjs +1 -1
- package/tests/main_audit_db_roster.mjs +2 -2
- package/tests/main_worktree_busy_reason.mjs +3 -3
- package/tests/markdown_line_endings.mjs +2 -2
- package/tests/me_streak_leaderboard_queries.mjs +193 -0
- package/tests/membership_kind_lockstep.mjs +1 -1
- package/tests/memory_isolation.mjs +16 -8
- package/tests/memory_map.mjs +2 -2
- package/tests/memory_pull.mjs +33 -25
- package/tests/merge_driver_register.mjs +3 -3
- package/tests/migration_allocation.mjs +2 -2
- package/tests/migration_namespace.mjs +1 -1
- package/tests/migrations_forward_safe.mjs +1 -1
- package/tests/mingle.mjs +1 -1
- package/tests/mirror_lineage_fulltree.mjs +3 -3
- package/tests/mirror_lineage_proof.mjs +2 -2
- package/tests/mirror_redact.mjs +4 -4
- package/tests/missing_dep_classify.mjs +3 -3
- package/tests/module-scope-map.mjs +22 -22
- package/tests/module_api_lazy.mjs +1 -1
- package/tests/module_assess_docs.mjs +2 -2
- package/tests/module_assess_installs.mjs +3 -3
- package/tests/module_assess_price_parity.mjs +5 -5
- package/tests/module_assess_score.mjs +5 -5
- package/tests/module_assess_security.mjs +4 -4
- package/tests/module_assess_tests.mjs +3 -3
- package/tests/module_assessments_migration.mjs +1 -1
- package/tests/module_catalog.mjs +2 -2
- package/tests/module_cli.mjs +3 -3
- package/tests/module_entitlements.mjs +1 -1
- package/tests/module_error_counts.mjs +1 -1
- package/tests/module_install.mjs +4 -4
- package/tests/module_loader.mjs +3 -1
- package/tests/module_owned_tests.mjs +1 -1
- package/tests/module_release_channels.mjs +1 -1
- package/tests/module_store_howto.mjs +3 -3
- package/tests/module_store_listing.mjs +139 -2
- package/tests/module_store_publish.mjs +4 -4
- package/tests/module_store_publish_route.mjs +1 -1
- package/tests/module_store_reassess.mjs +1 -1
- package/tests/module_store_registry_migration.mjs +1 -1
- package/tests/module_test_runner.mjs +3 -3
- package/tests/module_update.mjs +4 -4
- package/tests/module_upgrade_updates.mjs +1 -1
- package/tests/move_escalation.mjs +2 -2
- package/tests/nav_permission_atoms.mjs +3 -2
- package/tests/needs_rebase.mjs +7 -3
- package/tests/newcomer_floor.mjs +1 -1
- package/tests/newcomer_generator.mjs +48 -0
- package/tests/next_number.mjs +1 -1
- package/tests/no_artifact_escalation.mjs +3 -3
- package/tests/npm_release_where.mjs +1 -1
- package/tests/oauth_secret.mjs +2 -2
- package/tests/onboard.mjs +6 -6
- package/tests/onboarding_gate.mjs +2 -2
- package/tests/opt_in_skill_modules.mjs +3 -3
- package/tests/own_scope_guard.mjs +1 -1
- package/tests/own_session_revoke.mjs +4 -1
- package/tests/package_core.mjs +10 -11
- package/tests/page_inventory.mjs +5 -5
- package/tests/page_reader.mjs +7 -7
- package/tests/page_tweak_hold.mjs +6 -6
- package/tests/parallel-load.mjs +1 -1
- package/tests/paste_token_api_base.mjs +1 -1
- package/tests/paste_token_session_store.mjs +2 -2
- package/tests/pending_invite_purge_db.mjs +1 -1
- package/tests/permission_path.mjs +1 -1
- package/tests/pin_replay.mjs +1 -1
- package/tests/pin_write_key.mjs +7 -7
- package/tests/plain_cards.mjs +15 -15
- package/tests/pr_assign.mjs +1 -1
- package/tests/pre_push_hook.mjs +3 -3
- package/tests/preflight_checks.mjs +2 -2
- package/tests/prelaunch_gate.mjs +1 -1
- package/tests/privacy_matrix.mjs +1 -1
- package/tests/probe_cache.mjs +6 -6
- package/tests/profile_connections_ui.mjs +4 -3
- package/tests/profile_fields.mjs +11 -1
- package/tests/profile_privacy_owner_view.mjs +1 -1
- package/tests/profile_role_headline.mjs +10 -9
- package/tests/project_admin_console_model.mjs +1 -1
- package/tests/projects_hub.mjs +1 -1
- package/tests/projects_hub_cloud_hop.mjs +1 -1
- package/tests/promote_goal_id.mjs +6 -6
- package/tests/promotion_sweep.mjs +1 -1
- package/tests/provision.mjs +24 -24
- package/tests/provision_account_identity.mjs +2 -2
- package/tests/provision_byo_host.mjs +1 -1
- package/tests/provision_caddy_wiring.mjs +2 -2
- package/tests/provision_disconnect.mjs +2 -2
- package/tests/provision_dns_first.mjs +1 -1
- package/tests/provision_render.mjs +9 -9
- package/tests/provision_repo_private.mjs +3 -3
- package/tests/provision_resource_caps.mjs +5 -5
- package/tests/provision_restart.mjs +3 -3
- package/tests/provision_settings_apply.mjs +7 -7
- package/tests/provision_teardown_address.mjs +2 -2
- package/tests/provisioning_capacity.mjs +5 -5
- package/tests/provisioning_credential_preflight.mjs +1 -1
- package/tests/provisioning_disconnect.mjs +1 -1
- package/tests/provisioning_error_note_scope.mjs +4 -4
- package/tests/provisioning_paid_shape_gate.mjs +2 -2
- package/tests/provisioning_planet_physics.mjs +16 -0
- package/tests/provisioning_runner_drift_notice.mjs +2 -2
- package/tests/provisioning_settings_env.mjs +1 -1
- package/tests/pruned_lockfile_integrity.mjs +1 -1
- package/tests/public_mirror_export.mjs +1 -1
- package/tests/publish_integration_gate.mjs +2 -2
- package/tests/publish_manifest.mjs +6 -6
- package/tests/publish_watch.mjs +1 -1
- package/tests/push_path_brief.mjs +2 -2
- package/tests/raise.mjs +248 -0
- package/tests/rank_roles_audit.mjs +1 -1
- package/tests/rank_tier_single_source.mjs +2 -2
- package/tests/rate_limit_public.mjs +1 -1
- package/tests/read_default_meter.mjs +2 -2
- package/tests/read_session_export.mjs +1 -1
- package/tests/rebase_gate_set_aside.mjs +1 -1
- package/tests/recall_cli.mjs +1 -1
- package/tests/recall_corpus_health.mjs +3 -2
- package/tests/recall_hints.mjs +1 -1
- package/tests/recruiter_sliver_boundary.mjs +1 -1
- package/tests/redteam_patrol.mjs +2 -2
- package/tests/regrade_actual_minutes.mjs +2 -2
- package/tests/regrade_eligibility.mjs +2 -2
- package/tests/release_core.mjs +2 -2
- package/tests/release_notes.mjs +4 -4
- package/tests/rename_history_restraint.mjs +3 -3
- package/tests/rename_ledger_prose.mjs +6 -6
- package/tests/render_api.mjs +1 -1
- package/tests/render_check.mjs +4 -4
- package/tests/render_deploy.mjs +1 -1
- package/tests/repo_info_binding.mjs +1 -1
- package/tests/repo_map.mjs +5 -5
- package/tests/reward_mode_cost_plus_only.mjs +7 -3
- package/tests/reward_mode_surfacing.mjs +1 -1
- package/tests/role_responsibilities.mjs +1 -1
- package/tests/route_permission_check.mjs +1 -1
- package/tests/route_shadow_guard.mjs +1 -1
- package/tests/route_validation.mjs +1 -1
- package/tests/routine_capture_kind.mjs +6 -6
- package/tests/routine_schedule.mjs +9 -9
- package/tests/run_routine.mjs +5 -5
- package/tests/run_routine_two_root.mjs +5 -5
- package/tests/runner_drift.mjs +17 -17
- package/tests/sandbox_stage.mjs +5 -5
- package/tests/scope_map_guard.mjs +7 -7
- package/tests/scouting_owner_access_and_reach.mjs +1 -1
- package/tests/scripts_gds_forwarders.mjs +224 -0
- package/tests/scrubber_corpus.mjs +2 -2
- package/tests/seam_wiring_guard.mjs +1 -1
- package/tests/search_ingest.mjs +2 -2
- package/tests/search_ingest_db.mjs +1 -1
- package/tests/search_ingest_nul.mjs +6 -6
- package/tests/seed_verify_criteria.mjs +3 -3
- package/tests/sequence.mjs +3 -3
- package/tests/served_paths_shipped.mjs +3 -3
- package/tests/session_506_regression.mjs +1 -1
- package/tests/session_accessibility.mjs +1 -1
- package/tests/session_caps.mjs +1 -1
- package/tests/session_cost.mjs +1 -1
- package/tests/session_digest.mjs +2 -2
- package/tests/session_eval.mjs +6 -6
- package/tests/session_index.mjs +1 -1
- package/tests/session_records.mjs +4 -4
- package/tests/session_rename_fallback.mjs +2 -2
- package/tests/session_reward_on_land.mjs +7 -149
- package/tests/session_reward_on_land_db.mjs +191 -0
- package/tests/session_reward_reconcile.mjs +6 -88
- package/tests/session_reward_reconcile_db.mjs +132 -0
- package/tests/session_transcript.mjs +1 -1
- package/tests/sessions_kit_pager.mjs +2 -1
- package/tests/setup_device_flow_fallback.mjs +2 -2
- package/tests/setup_smoke.mjs +12 -5
- package/tests/setup_status_facts.mjs +54 -12
- package/tests/ship_autolinkify.mjs +2 -2
- package/tests/ship_automerge_injection.mjs +1 -1
- package/tests/ship_base_flag.mjs +1 -1
- package/tests/ship_broadcast_routing.mjs +1 -1
- package/tests/ship_broadcast_server.mjs +2 -2
- package/tests/ship_builder_model.mjs +1 -1
- package/tests/ship_cannot_lie.mjs +9 -9
- package/tests/ship_card.mjs +2 -2
- package/tests/ship_ci_deploy.mjs +7 -7
- package/tests/ship_error_shape.mjs +1 -1
- package/tests/ship_land_ci_not_started.mjs +3 -3
- package/tests/ship_land_conflict.mjs +3 -3
- package/tests/ship_land_proof.mjs +3 -3
- package/tests/ship_land_red_pr.mjs +5 -5
- package/tests/ship_merge_gate.mjs +14 -14
- package/tests/ship_mode.mjs +1 -1
- package/tests/ship_mode_first_ship.mjs +4 -4
- package/tests/ship_mode_hands_off.mjs +8 -8
- package/tests/ship_post_land_verify.mjs +1 -1
- package/tests/ship_preflight.mjs +19 -19
- package/tests/ship_premerge.mjs +1 -1
- package/tests/ship_publish_error.mjs +2 -2
- package/tests/ship_push_diagnosis.mjs +1 -1
- package/tests/ship_regen_copy_inventory.mjs +3 -3
- package/tests/ship_resume.mjs +4 -4
- package/tests/ship_smoke_gate.mjs +1 -1
- package/tests/ship_upload_skip.mjs +1 -1
- package/tests/ship_upstream_deletion.mjs +1 -1
- package/tests/ship_vendored_instance.mjs +8 -8
- package/tests/ship_visual_regrade.mjs +3 -3
- package/tests/ship_zero_commit.mjs +1 -1
- package/tests/skill_docs_unavailable_regrade.mjs +3 -3
- package/tests/skill_friction_kind.mjs +1 -1
- package/tests/skill_grade_recover.mjs +1 -1
- package/tests/skill_grader_health.mjs +1 -1
- package/tests/skill_lint.mjs +1 -1
- package/tests/skill_menu_ruling.mjs +1 -1
- package/tests/skill_preflight.mjs +7 -7
- package/tests/skip_is_not_pass.mjs +22 -1
- package/tests/smoke_dependencies_witness.mjs +2 -2
- package/tests/smoke_preflight.mjs +1 -1
- package/tests/smoke_target.mjs +2 -2
- package/tests/smoke_write_contract.mjs +2 -2
- package/tests/sound_player.mjs +8 -8
- package/tests/source_text_test_ratchet.mjs +97 -0
- package/tests/speciality_corpus_scope.mjs +1 -1
- package/tests/speciality_session_skills.mjs +1 -1
- package/tests/sso_checkin_legacy_field_gone.mjs +4 -2
- package/tests/stale_timer.mjs +3 -3
- package/tests/stale_worktrees.mjs +1 -1
- package/tests/start_env_guard.mjs +1 -1
- package/tests/start_goal_first.mjs +3 -3
- package/tests/start_inbox_count.mjs +1 -1
- package/tests/start_rebase_warning.mjs +1 -1
- package/tests/status_default_version.mjs +3 -3
- package/tests/status_mirror_sync.mjs +1 -1
- package/tests/status_page_no_dead_uptime.mjs +80 -0
- package/tests/stop_refcheck.mjs +1 -1
- package/tests/strand_watch.mjs +1 -1
- package/tests/stranded_rows.mjs +1 -1
- package/tests/stuck_detector.mjs +14 -14
- package/tests/sweep_app_account.mjs +3 -3
- package/tests/task_cli.mjs +2 -2
- package/tests/task_detail_ui.mjs +11 -1
- package/tests/task_discipline_required.mjs +2 -2
- package/tests/task_list_paging.mjs +1 -1
- package/tests/task_visual_slots.mjs +2 -2
- package/tests/terms_acceptance.mjs +1 -1
- package/tests/terms_grandfather_db.mjs +1 -1
- package/tests/test_path_guard.mjs +1 -1
- package/tests/triage_development.mjs +1 -1
- package/tests/tweak_batch_apply.mjs +2 -2
- package/tests/tweak_land_heal.mjs +3 -3
- package/tests/tweak_unattended.mjs +3 -3
- package/tests/ui_design_skills.mjs +2 -2
- package/tests/unit_report_status.mjs +2 -2
- package/tests/unit_runner_serial.mjs +2 -2
- package/tests/unit_runner_teardown_abort.mjs +1 -1
- package/tests/update_channel.mjs +2 -2
- package/tests/update_channel_db.mjs +4 -4
- package/tests/update_subscription_engine.mjs +26 -26
- package/tests/update_sweep_home.mjs +14 -14
- package/tests/upgrade.mjs +11 -11
- package/tests/upgrade_artist_gate.mjs +4 -4
- package/tests/upgrade_commit_identity.mjs +2 -2
- package/tests/upgrade_migrate.mjs +7 -7
- package/tests/upgrade_operator.mjs +2 -2
- package/tests/upgrade_outcome.mjs +2 -2
- package/tests/upgrade_persist_pin.mjs +5 -5
- package/tests/upkeep_home.mjs +1 -1
- package/tests/version_close.mjs +2 -2
- package/tests/version_close_cli.mjs +2 -2
- package/tests/version_close_route.mjs +1 -1
- package/tests/version_literals.mjs +23 -23
- package/tests/visual_review.mjs +5 -5
- package/tests/wedge_remedy.mjs +5 -5
- package/tests/welcome_boot.mjs +116 -0
- package/tests/welcome_boot_browser.mjs +271 -0
- package/tests/wizard_born_first_board.mjs +3 -3
- package/tests/wizard_demo.mjs +1 -1
- package/tests/wizard_one_page.mjs +4 -3
- package/tests/wizard_physics.mjs +3 -1
- package/tests/wizard_physics_more.mjs +42 -3
- package/tests/work_title_wrap.mjs +1 -1
- package/tests/workflow_exec_paths.mjs +6 -6
- package/tests/worktree_claim_guard.mjs +1 -1
- package/tests/worktree_helper.mjs +2 -2
- package/tests/write_validation_gaps.mjs +3 -3
- package/scripts/gds/api.sh +0 -6
- package/scripts/gds/audit-exports.js +0 -128
- package/scripts/gds/resolve-skill-model.js +0 -57
- package/scripts/gds/security-baseline-check.sh +0 -180
- package/scripts/gds/spike-task-map.js +0 -899
- package/scripts/status-probe.mjs +0 -213
- package/src/bongos/uptime-poller.js +0 -93
- package/tests/government_fold_bench.mjs +0 -50
- package/tests/spike_task_map.mjs +0 -422
- package/tests/status-probe.mjs +0 -89
- /package/{scripts/gds → modules/raise}/CLAUDE.md +0 -0
- /package/scripts/{gds → bongos}/cloudbongos-token-isolation.conf +0 -0
- /package/scripts/{gds → bongos}/discipline-modes.json +0 -0
- /package/scripts/{gds → bongos}/retired-core-skills.json +0 -0
package/scripts/gds/go-live.js
CHANGED
|
@@ -1,1071 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
// scripts/gds/go-live.js — @bongos-forwarder (task 1004848). Generated by
|
|
3
|
+
// scripts/bongos/codemod-rename-scripts-gds.js; do not edit.
|
|
4
|
+
// The real script is scripts/bongos/go-live.js. This forwarder keeps callers that still name
|
|
5
|
+
// the old path working, and warns once so they get repointed. Task 1003706 removes it.
|
|
2
6
|
'use strict';
|
|
3
|
-
|
|
4
|
-
// scripts/gds/go-live.js — run a go-live as ONE command instead of forty tool calls.
|
|
5
|
-
//
|
|
6
|
-
// WHY THIS EXISTS (task 1003189). Gate 3 of docs/recipes/core-release-pipeline.md —
|
|
7
|
-
// moving an instance's core pin, the only act that makes shipped work visible to
|
|
8
|
-
// users — is a DETERMINISTIC sequence that was nonetheless re-derived from prose by
|
|
9
|
-
// hand every time. The 2026-08-23 go-live took 101 tool calls / 211 model turns at a
|
|
10
|
-
// mean 143K context (29.7M cache-read tokens, ~69% of the bill). About four of those
|
|
11
|
-
// calls were engineering; the rest were lookups: what is on main, what is live, which
|
|
12
|
-
// PRs are green, what does the runbook say, what did the box just print. Cost here is
|
|
13
|
-
// turns x context, so collapsing the mechanical legs into one call is the whole fix.
|
|
14
|
-
//
|
|
15
|
-
// WHAT IT IS NOT. Not a new deploy mechanism, and not a privileged surface of its own.
|
|
16
|
-
// Every leg is an EXISTING proven part and this file only sequences them and reports:
|
|
17
|
-
// - deploy-divergence.js check() — live coreVersion vs main, UNRELEASED vs UNDEPLOYED
|
|
18
|
-
// - the published registry — proof a release carrying the work actually exists
|
|
19
|
-
// - `bongos upgrade --registry --commit-pin` — the pin move, health-gated, auto-rollback ON
|
|
20
|
-
// It is also NOT task 1003159: that gives the OWNER a door onto deploy without a shell
|
|
21
|
-
// (an authenticated control + an ADR settling the authority model). This is the AGENT
|
|
22
|
-
// side — a session that ALREADY holds the shell should spend two calls here, not forty.
|
|
23
|
-
//
|
|
24
|
-
// HALT, DO NOT GUESS. Every condition that needs judgement stops the run and names
|
|
25
|
-
// itself: a red CI check, unreleased commits, a registry missing the target, a dirty
|
|
26
|
-
// tree, a failed health check, an uncommitted pin. Those are exactly the parts worth
|
|
27
|
-
// an agent's attention; this script's job is to make everything AROUND them free.
|
|
28
|
-
//
|
|
29
|
-
// NO HOST TOPOLOGY LIVES HERE. This file ships in the portable core, so the ssh alias,
|
|
30
|
-
// paths, service names and health URLs come from a host-owned config (see --help for
|
|
31
|
-
// the schema) that is NOT publishable — the same shape as config/update-subscriptions.json.
|
|
32
|
-
// A core that named one instance's box would not be a core.
|
|
33
|
-
//
|
|
34
|
-
// Usage:
|
|
35
|
-
// node scripts/gds/go-live.js # PLAN only — read-only, the default
|
|
36
|
-
// node scripts/gds/go-live.js --apply # actually move the pin
|
|
37
|
-
// node scripts/gds/go-live.js --to 1.19.306 # pin a target instead of main's CORE_VERSION
|
|
38
|
-
// node scripts/gds/go-live.js --verify-marker src/x.js=needle
|
|
39
|
-
// # refuse a target that lacks the change
|
|
40
|
-
// node scripts/gds/go-live.js --target web --json
|
|
41
|
-
//
|
|
42
|
-
// Exit codes: 0 plan clean / apply succeeded · 1 halted (reason printed) · 2 bad invocation.
|
|
43
|
-
|
|
44
|
-
const fs = require('node:fs');
|
|
45
|
-
const path = require('node:path');
|
|
46
|
-
const { spawnSync } = require('node:child_process');
|
|
47
|
-
const { arg, hasFlag, apiCall } = require('./cli-lib');
|
|
48
|
-
const divergence = require('./deploy-divergence.js');
|
|
49
|
-
|
|
50
|
-
const ROOT = path.resolve(__dirname, '..', '..');
|
|
51
|
-
const DEFAULT_CONFIG = 'config/go-live.json';
|
|
52
|
-
|
|
53
|
-
// ---------------------------------------------------------------------------
|
|
54
|
-
// Validation. Everything below reaches a remote shell that runs as root, so it
|
|
55
|
-
// is checked against a strict allowlist BEFORE interpolation — never quoted and
|
|
56
|
-
// hoped for. A config file is host-owned, but "host-owned" is not "trusted to
|
|
57
|
-
// contain shell metacharacters".
|
|
58
|
-
// ---------------------------------------------------------------------------
|
|
59
|
-
|
|
60
|
-
const SEMVER_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
61
|
-
// Deliberately narrow: POSIX-portable path/identifier characters only. No spaces,
|
|
62
|
-
// no quotes, no $ ` \ ; & | < > ( ) newline — i.e. nothing with meaning to a shell.
|
|
63
|
-
//
|
|
64
|
-
// `~` IS allowed, and is the one deliberate exception. It is shell-interpreted, but
|
|
65
|
-
// it cannot start a subshell, chain a command, or redirect — the runbook's backup dir
|
|
66
|
-
// is literally `~/backups`, and under `sudo -u <owner> -H` that expansion to the
|
|
67
|
-
// owner's home is the BEHAVIOUR WE WANT, not a leak. Everything with control meaning
|
|
68
|
-
// stays out.
|
|
69
|
-
const SAFE_TOKEN_RE = /^[A-Za-z0-9._@:/+=~-]+$/;
|
|
70
|
-
const SAFE_ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
71
|
-
|
|
72
|
-
function isSafeToken(v) {
|
|
73
|
-
return typeof v === 'string' && v.length > 0 && v.length <= 512 && SAFE_TOKEN_RE.test(v);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// The fields a target must carry, and the ones it may. Unknown keys are reported
|
|
77
|
-
// rather than ignored: a typo'd `healthURL` that silently disables the health gate
|
|
78
|
-
// is precisely the class of quiet failure this pipeline keeps being bitten by.
|
|
79
|
-
// `ssh` is NOT required: a target with no ssh host is LOCAL (the box driving itself).
|
|
80
|
-
//
|
|
81
|
-
// `deployTimer` is NOT required either — that is CO-TENANT MODE (task 1003521). A
|
|
82
|
-
// provisioned instance under /srv/<host>/<slug> has no pull-deploy timer at all (only
|
|
83
|
-
// its <slug>-db-backup.timer), so requiring the field forced an operator to invent a
|
|
84
|
-
// unit name that the script would then try to `systemctl stop`. Absent, the stop and
|
|
85
|
-
// the restart are simply skipped: there is no `reset --hard` to race.
|
|
86
|
-
const REQUIRED_FIELDS = ['instanceDir', 'service', 'healthUrl', 'versionUrl'];
|
|
87
|
-
const OPTIONAL_FIELDS = ['ssh', 'local', 'deployTimer', 'deployService', 'runAs', 'backupDb', 'backupDir', 'env', 'registryPackage', 'pinMode'];
|
|
88
|
-
|
|
89
|
-
// How the bump is made durable — the other half of co-tenant mode (task 1003521).
|
|
90
|
-
//
|
|
91
|
-
// On the PLATFORM instance the repo of record is ours, and a pull-deploy
|
|
92
|
-
// `git reset --hard origin/main` reverts any pin that was not PUSHED (task 1002712 —
|
|
93
|
-
// thirteen releases were lost exactly that way). So the default is `push`.
|
|
94
|
-
//
|
|
95
|
-
// On a provisioned co-tenant the repo of record is the CUSTOMER's own GitHub repo, so
|
|
96
|
-
// that push is both wrong and, in practice, uncredentialed. With no pull-deploy timer
|
|
97
|
-
// nothing will revert the pin, so a local commit is enough to leave the tree clean:
|
|
98
|
-
// local-commit — commit the pin, do not push it
|
|
99
|
-
// leave-dirty — do not commit at all; the bump lives in the working tree by design
|
|
100
|
-
const PIN_MODES = ['push', 'local-commit', 'leave-dirty'];
|
|
101
|
-
const DEFAULT_PIN_MODE = 'push';
|
|
102
|
-
|
|
103
|
-
function pinModeOf(target) {
|
|
104
|
-
return (target && target.pinMode) || DEFAULT_PIN_MODE;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function validateTarget(name, t) {
|
|
108
|
-
const errors = [];
|
|
109
|
-
if (!t || typeof t !== 'object' || Array.isArray(t)) return [`target "${name}" is not an object`];
|
|
110
|
-
|
|
111
|
-
for (const f of REQUIRED_FIELDS) {
|
|
112
|
-
if (t[f] === undefined) errors.push(`target "${name}" is missing required field "${f}"`);
|
|
113
|
-
}
|
|
114
|
-
const known = new Set([...REQUIRED_FIELDS, ...OPTIONAL_FIELDS]);
|
|
115
|
-
for (const k of Object.keys(t)) {
|
|
116
|
-
if (!known.has(k)) errors.push(`target "${name}" has unknown field "${k}" (typo? known: ${[...known].sort().join(', ')})`);
|
|
117
|
-
}
|
|
118
|
-
for (const [k, v] of Object.entries(t)) {
|
|
119
|
-
if (k === 'env') {
|
|
120
|
-
if (typeof v !== 'object' || v === null || Array.isArray(v)) { errors.push(`target "${name}".env must be an object`); continue; }
|
|
121
|
-
for (const [ek, ev] of Object.entries(v)) {
|
|
122
|
-
if (!SAFE_ENV_KEY_RE.test(ek)) errors.push(`target "${name}".env key "${ek}" is not a valid environment-variable name`);
|
|
123
|
-
if (!isSafeToken(String(ev))) errors.push(`target "${name}".env.${ek} contains characters that are unsafe in a shell`);
|
|
124
|
-
}
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
if (!known.has(k)) continue;
|
|
128
|
-
if (k === 'local') { // a flag, never interpolated into a command
|
|
129
|
-
if (typeof v !== 'boolean') errors.push(`target "${name}".local must be true or false`);
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
if (k === 'pinMode') { // an enum, never interpolated into a command
|
|
133
|
-
if (!PIN_MODES.includes(v)) errors.push(`target "${name}".pinMode must be one of ${PIN_MODES.join(', ')} (got ${JSON.stringify(v)})`);
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
if (!isSafeToken(v)) errors.push(`target "${name}".${k} contains characters that are unsafe in a shell (got ${JSON.stringify(v)})`);
|
|
137
|
-
}
|
|
138
|
-
return errors;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// ---------------------------------------------------------------------------
|
|
142
|
-
// Config
|
|
143
|
-
// ---------------------------------------------------------------------------
|
|
144
|
-
|
|
145
|
-
const CONFIG_TEMPLATE = `{
|
|
146
|
-
"defaultTarget": "web",
|
|
147
|
-
"targets": {
|
|
148
|
-
"web": {
|
|
149
|
-
"ssh": "my-box", // ssh alias or user@host
|
|
150
|
-
"instanceDir": "/home/me/my-instance", // the instance repo (holds the pin)
|
|
151
|
-
"service": "my-instance.service", // systemd unit to restart
|
|
152
|
-
"healthUrl": "http://127.0.0.1:3002/healthz", // box-side, NOT the apex
|
|
153
|
-
"versionUrl": "http://127.0.0.1:3002/version", // box-side truth read back after
|
|
154
|
-
"deployTimer": "my-deploy.timer", // optional: pull-deploy timer (its reset --hard is the hazard)
|
|
155
|
-
"deployService": "my-deploy.service", // optional: forced tick proves the pin stuck
|
|
156
|
-
"runAs": "me", // optional: unprivileged owner of the instance
|
|
157
|
-
"backupDb": "mydb", // optional: pg_dump before the bump
|
|
158
|
-
"backupDir": "~/backups",
|
|
159
|
-
"env": { "PGDATABASE": "mydb" }, // optional: load-bearing for migrate
|
|
160
|
-
"registryPackage": "@bongos/core",
|
|
161
|
-
"pinMode": "push" // optional: push (default) | local-commit | leave-dirty
|
|
162
|
-
},
|
|
163
|
-
"a-co-tenant": {
|
|
164
|
-
// A PROVISIONED instance: no pull-deploy timer to stop, and the repo of record
|
|
165
|
-
// is the customer's own GitHub repo — so the pin is committed, never pushed.
|
|
166
|
-
"ssh": "my-box",
|
|
167
|
-
"instanceDir": "/srv/my-host/their-slug",
|
|
168
|
-
"service": "their-slug.service",
|
|
169
|
-
"healthUrl": "http://127.0.0.1:3101/healthz",
|
|
170
|
-
"versionUrl": "http://127.0.0.1:3101/version",
|
|
171
|
-
"runAs": "their-slug",
|
|
172
|
-
"env": { "PGDATABASE": "their_slug" },
|
|
173
|
-
"pinMode": "local-commit"
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}`;
|
|
177
|
-
|
|
178
|
-
function loadConfig({ configPath, readFile = fs.readFileSync, exists = fs.existsSync } = {}) {
|
|
179
|
-
const rel = configPath || DEFAULT_CONFIG;
|
|
180
|
-
const abs = path.isAbsolute(rel) ? rel : path.join(ROOT, rel);
|
|
181
|
-
if (!exists(abs)) {
|
|
182
|
-
return { error: 'NO_TARGET_CONFIG', path: rel, template: CONFIG_TEMPLATE };
|
|
183
|
-
}
|
|
184
|
-
let raw;
|
|
185
|
-
try { raw = readFile(abs, 'utf8'); } catch (e) { return { error: 'CONFIG_UNREADABLE', path: rel, detail: e.message }; }
|
|
186
|
-
let parsed;
|
|
187
|
-
// Tolerate // comments so the shipped template can stay self-documenting.
|
|
188
|
-
try { parsed = JSON.parse(raw.replace(/^\s*\/\/.*$/gm, '').replace(/(:\s*"[^"]*"|:\s*[\d.]+|[{[,])\s*\/\/.*$/gm, '$1')); }
|
|
189
|
-
catch (e) { return { error: 'CONFIG_MALFORMED', path: rel, detail: e.message }; }
|
|
190
|
-
if (!parsed || typeof parsed !== 'object' || !parsed.targets || typeof parsed.targets !== 'object') {
|
|
191
|
-
return { error: 'CONFIG_MALFORMED', path: rel, detail: 'expected a top-level "targets" object' };
|
|
192
|
-
}
|
|
193
|
-
return { ok: true, path: rel, config: parsed };
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function selectTarget(config, name) {
|
|
197
|
-
const wanted = name || config.defaultTarget || Object.keys(config.targets)[0];
|
|
198
|
-
if (!wanted) return { error: 'UNKNOWN_TARGET', detail: 'the config declares no targets' };
|
|
199
|
-
const t = config.targets[wanted];
|
|
200
|
-
if (!t) {
|
|
201
|
-
return { error: 'UNKNOWN_TARGET', detail: `no target "${wanted}" (have: ${Object.keys(config.targets).join(', ') || 'none'})` };
|
|
202
|
-
}
|
|
203
|
-
const errors = validateTarget(wanted, t);
|
|
204
|
-
if (errors.length) return { error: 'CONFIG_INVALID', detail: errors.join('; ') };
|
|
205
|
-
return { ok: true, name: wanted, target: t };
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// ---------------------------------------------------------------------------
|
|
209
|
-
// Remote execution. One ssh round-trip per phase, script fed on STDIN so no
|
|
210
|
-
// value is ever interpolated into an ssh ARGUMENT (which would be re-parsed by
|
|
211
|
-
// the remote login shell). Values are validated above; this is the second layer.
|
|
212
|
-
// ---------------------------------------------------------------------------
|
|
213
|
-
|
|
214
|
-
// Privilege preamble for any phase that touches systemd.
|
|
215
|
-
//
|
|
216
|
-
// Over ssh these phases run as ROOT, so `systemctl stop …` just works — which is what
|
|
217
|
-
// they originally assumed. Run LOCALLY by the nightly lane they run as the instance
|
|
218
|
-
// OWNER, where the same line fails with "Interactive authentication required" and the
|
|
219
|
-
// timer is never stopped: the pull-deploy `git reset --hard` then stays armed for the
|
|
220
|
-
// whole upgrade, which is the exact hazard the stop exists to remove. Deciding at RUN
|
|
221
|
-
// time keeps one script correct for both callers.
|
|
222
|
-
const SUDO_PREAMBLE = 'SUDO=""; [ "$(id -u)" -eq 0 ] || SUDO="sudo -n"';
|
|
223
|
-
|
|
224
|
-
// A target is LOCAL when it names no ssh host: the phases run through a local shell
|
|
225
|
-
// instead of a remote one. Everything else — the phases, the halts, the reporting —
|
|
226
|
-
// is byte-identical, which is the point: one deployment engine, reachable from a
|
|
227
|
-
// laptop (remote) or from the box itself (local, how the nightly lane uses it).
|
|
228
|
-
// Without this the unattended path would need its own second implementation, and the
|
|
229
|
-
// two would drift — which is exactly how the nightly deploy ended up with weaker
|
|
230
|
-
// checks than the manual one (task 1003219).
|
|
231
|
-
function isLocalTarget(target) {
|
|
232
|
-
return !target || !target.ssh;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function remote(target, script, { run = spawnSync, timeoutMs = 900000 } = {}) {
|
|
236
|
-
const [cmd, args] = isLocalTarget(target)
|
|
237
|
-
? ['bash', ['-s']]
|
|
238
|
-
: ['ssh', ['-o', 'ConnectTimeout=20', '-o', 'BatchMode=yes', target.ssh, 'bash', '-s']];
|
|
239
|
-
const res = run(cmd, args, {
|
|
240
|
-
input: script, encoding: 'utf8', timeout: timeoutMs, maxBuffer: 32 * 1024 * 1024,
|
|
241
|
-
});
|
|
242
|
-
if (!res || res.error) return { ok: false, status: null, stdout: '', stderr: res && res.error ? res.error.message : 'spawn failed' };
|
|
243
|
-
return { ok: res.status === 0, status: res.status, stdout: res.stdout || '', stderr: res.stderr || '' };
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// `sudo -u <user> -H env K=V … <cmd>` — the shape every runbook entry uses. Returns
|
|
247
|
-
// a string safe to embed because every component was allowlist-validated.
|
|
248
|
-
//
|
|
249
|
-
// `sudo -u <user> -H env K=V … <cmd>` — the shape every runbook entry uses. Returns
|
|
250
|
-
// a string safe to embed because every component was allowlist-validated.
|
|
251
|
-
//
|
|
252
|
-
// Only NON-secret configuration (PGDATABASE, HOME) travels in the plain `env K=V` list —
|
|
253
|
-
// seeing those in a log is useful rather than harmful.
|
|
254
|
-
//
|
|
255
|
-
// This used to take a `needsNpm` option wrapping the command in a preamble that DERIVED an
|
|
256
|
-
// npm credential on the far side, because sudo logs its whole invocation and there was no way
|
|
257
|
-
// to hand a privileged child a secret without journalling it (task 1003218). @bongos/core is
|
|
258
|
-
// public (task 1003872), so the deploy path needs no npm credential at all and the whole
|
|
259
|
-
// hazard is gone rather than mitigated (task 1003878).
|
|
260
|
-
function asOwner(target, cmd) {
|
|
261
|
-
const inner = cmd;
|
|
262
|
-
const envPairs = Object.entries(target.env || {}).map(([k, v]) => `${k}=${v}`);
|
|
263
|
-
if (!target.runAs) {
|
|
264
|
-
const joined = envPairs.join(' ');
|
|
265
|
-
return `${joined ? `env ${joined} ` : ''}${inner}`.trim();
|
|
266
|
-
}
|
|
267
|
-
const joined = [...envPairs, `HOME=/home/${target.runAs}`].join(' ');
|
|
268
|
-
return `sudo -u ${target.runAs} -H env ${joined} ${inner}`.trim();
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// POSIX single-quote a value for embedding in a shell command.
|
|
272
|
-
function shq(s) {
|
|
273
|
-
return `'${String(s).replace(/'/g, `'\\''`)}'`;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// The content proof, as a shell snippet.
|
|
277
|
-
//
|
|
278
|
-
// TWO bugs live here in the obvious version, and both FAIL OPEN — they report "your
|
|
279
|
-
// change is missing" for a version that has it, which reads exactly like the real
|
|
280
|
-
// ADR-0161 trap and sends you chasing a later release that does not exist:
|
|
281
|
-
//
|
|
282
|
-
// 1. Do NOT derive the tarball name. `npm pack @bongos/core` writes
|
|
283
|
-
// `bongos-core-<v>.tgz`, and hand-rolled `tr`/`sed` on the package name gets the
|
|
284
|
-
// leading dashes wrong — so `tar` reads a file that is not there and greps 0 hits.
|
|
285
|
-
// npm PRINTS the filename it wrote; use that.
|
|
286
|
-
// 2. Pass the path + needle as base64 and match with `grep -F`. Interpolating them
|
|
287
|
-
// lets a quote break out of the command, and an unescaped regex metacharacter in
|
|
288
|
-
// the needle silently changes what is being matched.
|
|
289
|
-
//
|
|
290
|
-
// `set -o pipefail` is deliberately absent: `grep -c` exits 1 on zero matches, which
|
|
291
|
-
// is a legitimate answer here, not a failure.
|
|
292
|
-
function markerProbe(pkg, version, marker) {
|
|
293
|
-
const p64 = Buffer.from(marker.path, 'utf8').toString('base64');
|
|
294
|
-
const n64 = Buffer.from(marker.needle, 'utf8').toString('base64');
|
|
295
|
-
return [
|
|
296
|
-
`set -u`,
|
|
297
|
-
// Run from a neutral cwd. `npm pack <spec>` behaves differently inside a
|
|
298
|
-
// project directory, and an earlier section's `cd` used to leak this far —
|
|
299
|
-
// which made the pack fail and read as "your change is missing".
|
|
300
|
-
`cd /tmp`,
|
|
301
|
-
`P=$(echo ${p64} | base64 -d)`,
|
|
302
|
-
`N=$(echo ${n64} | base64 -d)`,
|
|
303
|
-
`ERR=$(mktemp)`,
|
|
304
|
-
`T=$(npm pack ${pkg}@${version} --pack-destination /tmp 2>"$ERR" | tail -1)`,
|
|
305
|
-
// Say WHY it failed. A bare PACK_FAILED cost four diagnostic round-trips once.
|
|
306
|
-
`if [ -z "$T" ] || [ ! -f "/tmp/$T" ]; then echo "PACK_FAILED $(tail -2 "$ERR" | tr '\\n' ' ')"; rm -f "$ERR"; exit 0; fi`,
|
|
307
|
-
`rm -f "$ERR"`,
|
|
308
|
-
// `grep -c` PRINTS 0 *and* exits 1 on no match, so a bare `|| echo 0` emits TWO
|
|
309
|
-
// lines ("0\n0") — which parses to NaN and compares equal to nothing, so an
|
|
310
|
-
// absent marker silently passed. Emit exactly one line.
|
|
311
|
-
`tar -xzOf "/tmp/$T" "package/$P" 2>/dev/null | grep -c -F -- "$N" | head -1`,
|
|
312
|
-
].join('; ');
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// Read the marker section back. Fails CLOSED: anything that is not a clean count is
|
|
316
|
-
// 'PACK_FAILED' (could not check), never a 0 that would read as a confident "absent"
|
|
317
|
-
// — and never a NaN that silently compares equal to nothing and lets the run proceed.
|
|
318
|
-
function parseMarkerHits(raw) {
|
|
319
|
-
const s = String(raw == null ? '' : raw).trim();
|
|
320
|
-
if (!s || s.includes('PACK_FAILED')) return 'PACK_FAILED';
|
|
321
|
-
const first = s.split('\n')[0].trim();
|
|
322
|
-
if (!/^\d+$/.test(first)) return 'PACK_FAILED';
|
|
323
|
-
return Number(first);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// Does this process sit inside a git repo that knows the given ref?
|
|
327
|
-
function gitRefExists(ref, { run = spawnSync } = {}) {
|
|
328
|
-
const r = run('git', ['rev-parse', '--verify', '--quiet', ref], { cwd: ROOT, encoding: 'utf8' });
|
|
329
|
-
return !!r && !r.error && r.status === 0;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
// Refresh origin/main before reading anything from it.
|
|
333
|
-
//
|
|
334
|
-
// deploy-divergence reads CORE_VERSION at the local `origin/main` REF, and a ref is
|
|
335
|
-
// only as fresh as the last fetch. A worktree that has sat for an hour resolves a
|
|
336
|
-
// target version that is already superseded — and everything downstream agrees with
|
|
337
|
-
// it, because every check is consistent with the same stale ref. This actually
|
|
338
|
-
// happened mid-build: a parallel session merged twice, the plan targeted the older
|
|
339
|
-
// carrier, and only a manual fetch revealed it. Default ON; --no-fetch opts out.
|
|
340
|
-
//
|
|
341
|
-
// A fetch failure is NOT fatal: a box or a tarball checkout legitimately has no
|
|
342
|
-
// remote, and deploy-divergence already falls back to HEAD there.
|
|
343
|
-
function refreshMain({ run = spawnSync } = {}) {
|
|
344
|
-
const r = run('git', ['fetch', 'origin', 'main', '--quiet'], { cwd: ROOT, encoding: 'utf8', timeout: 60000 });
|
|
345
|
-
if (!r || r.error || r.status !== 0) {
|
|
346
|
-
return { ok: false, reason: (r && (r.stderr || '').trim().split('\n').pop()) || 'fetch failed' };
|
|
347
|
-
}
|
|
348
|
-
return { ok: true };
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// Ask the LIVE instance about its own artist gate (ADR 0241, task 1003575).
|
|
352
|
-
//
|
|
353
|
-
// The instance answers because it is the only party that can: the policy arrives
|
|
354
|
-
// in its web.env and its board holds the reviews. This script only decides what to
|
|
355
|
-
// do with the answer, and the refusal sentence is composed there rather than here
|
|
356
|
-
// so one wording serves every caller.
|
|
357
|
-
//
|
|
358
|
-
// NEVER THROWS. Every failure — no session, a 401, an instance too old to carry
|
|
359
|
-
// the route, a network error — resolves to { unread: <why> }, which renders as a
|
|
360
|
-
// note. See artistGateEntries for why an unread gate is not a halt.
|
|
361
|
-
// The FULL path, not a bare `/artist-gate`. cli-lib's apiCall composes
|
|
362
|
-
// `${base}${urlPath}` verbatim and `base` is the instance ORIGIN — every other
|
|
363
|
-
// caller in this repo spells `/api/bongos/…` by hand for the same reason. Getting
|
|
364
|
-
// this wrong is silent in the worst way: the request lands on the origin's
|
|
365
|
-
// catch-all, the gate reports itself unread on every instance including the ones
|
|
366
|
-
// that fully support it, and the deploy check never fires. Exported so a test can
|
|
367
|
-
// pin it against the route's REAL mount point in the generated OpenAPI spec.
|
|
368
|
-
const ARTIST_GATE_PATH = '/api/bongos/artist-gate';
|
|
369
|
-
// The levels a real answer can carry — mirrored from src/bongos/artist-gate.js
|
|
370
|
-
// rather than imported, because this script also runs from an INSTALLED core on a
|
|
371
|
-
// box where that path is inside the package, and a require of it here would make
|
|
372
|
-
// the deploy tool depend on the server's own tree. Pinned by the same test that
|
|
373
|
-
// pins the path.
|
|
374
|
-
const ARTIST_GATE_LEVELS = ['off', 'advisory', 'strict'];
|
|
375
|
-
|
|
376
|
-
async function readArtistGate(call = apiCall) {
|
|
377
|
-
try {
|
|
378
|
-
const res = await call('GET', ARTIST_GATE_PATH, null, { allowUnauthenticated: true });
|
|
379
|
-
if (res.status === 404) return { unread: `this instance does not serve ${ARTIST_GATE_PATH} — it predates ADR 0241` };
|
|
380
|
-
// A 5xx is a gate that EXISTS and BROKE, which is not the same class of
|
|
381
|
-
// unknown as "no session" or "too old to have the route". The gate is
|
|
382
|
-
// fail-closed by design, so the one case where we know it is there and
|
|
383
|
-
// cannot get an answer from it HALTS rather than degrading to a note —
|
|
384
|
-
// otherwise a broken read is a quieter way past the gate than the owner's
|
|
385
|
-
// own override, which is the asymmetry worth refusing.
|
|
386
|
-
if (res.status >= 500) return { broken: `GET ${ARTIST_GATE_PATH} returned ${res.status}` };
|
|
387
|
-
if (!res.ok) return { unread: `GET ${ARTIST_GATE_PATH} returned ${res.status}` };
|
|
388
|
-
const d = res.data || {};
|
|
389
|
-
// A 200 that is not this route's answer — an SPA index.html served by a
|
|
390
|
-
// catch-all, a proxy's own page — must read as UNREAD, never as a gate that
|
|
391
|
-
// holds nothing. "I got a 200 from something" is the one failure that would
|
|
392
|
-
// wave a deploy through in silence, which is worse than any halt.
|
|
393
|
-
if (!ARTIST_GATE_LEVELS.includes(d.mode)) {
|
|
394
|
-
return { unread: `GET ${ARTIST_GATE_PATH} answered ${res.status} but not with a gate — got mode ${JSON.stringify(d.mode)}` };
|
|
395
|
-
}
|
|
396
|
-
return { mode: d.mode, since: d.since || null, holds: !!d.holds, reviews: d.reviews || [], halt: d.halt || null };
|
|
397
|
-
} catch (e) {
|
|
398
|
-
return { unread: (e && e.message) || 'request failed' };
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// Parse a `key=value` marker into its parts. Kept pure + exported: the marker is
|
|
403
|
-
// the answer to the trap that the release current when your fix merges usually
|
|
404
|
-
// does NOT contain your fix (ADR 0161 carriers bump on their own cadence).
|
|
405
|
-
function parseMarker(spec) {
|
|
406
|
-
if (!spec) return null;
|
|
407
|
-
const i = String(spec).indexOf('=');
|
|
408
|
-
if (i <= 0 || i === spec.length - 1) return { error: 'expected --verify-marker <path>=<needle>' };
|
|
409
|
-
return { path: spec.slice(0, i), needle: spec.slice(i + 1) };
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// ---------------------------------------------------------------------------
|
|
413
|
-
// Planning. Pure given its inputs, so the halt matrix tests without a box.
|
|
414
|
-
// ---------------------------------------------------------------------------
|
|
415
|
-
|
|
416
|
-
const HALTS = {
|
|
417
|
-
DIRTY_CHECKOUT: 'the core checkout has uncommitted changes — CORE_VERSION here cannot be trusted to match what was released',
|
|
418
|
-
DIVERGENCE_UNDETERMINED: 'could not determine what is live',
|
|
419
|
-
UNRELEASED_ON_MAIN: 'main carries commits past the last CORE_VERSION bump — no pin can reach them',
|
|
420
|
-
ALREADY_LIVE: 'live is already at the target',
|
|
421
|
-
REGISTRY_MISSING_TARGET: 'the registry does not carry the target version',
|
|
422
|
-
MARKER_ABSENT: 'the target version does not contain the change you named',
|
|
423
|
-
MARKER_UNCHECKED: 'could not inspect the target version — the content proof did not run',
|
|
424
|
-
BOX_TREE_DIRTY: 'the instance repo on the box has uncommitted changes',
|
|
425
|
-
LIVE_AHEAD: 'live is AHEAD of the target',
|
|
426
|
-
ARTIST_REVIEW_UNRESOLVED: 'an unresolved artist review holds this deploy (ADR 0241)',
|
|
427
|
-
ARTIST_GATE_UNREADABLE: 'the artist gate is there and answering with an error — this deploy cannot tell whether a review holds it',
|
|
428
|
-
};
|
|
429
|
-
|
|
430
|
-
// The artist gate (ADR 0241, task 1003575). This is the ONE place in the deploy
|
|
431
|
-
// path that the artist's authority touches, and the boundary is the whole point:
|
|
432
|
-
// `strict` may delay a PIN MOVE and nothing else. Nothing in the ship, grade,
|
|
433
|
-
// merge or land path consults this — a builder's work is credited and on `main`
|
|
434
|
-
// long before a go-live runs, which is what lets this gate coexist with ADR 0162
|
|
435
|
-
// instead of recreating the strand it retired.
|
|
436
|
-
//
|
|
437
|
-
// It reads a STATE, not a verdict: the instance reports which artist review tasks
|
|
438
|
-
// are still open, never whether an artist approved anything. See
|
|
439
|
-
// src/bongos/artist-gate.js, which composes the refusal sentence this renders.
|
|
440
|
-
// The halt and/or note one gate read contributes. Shared by planGoLive and by the
|
|
441
|
-
// gitless (on-box, no checkout) path, so a lane that skips the git-derived checks
|
|
442
|
-
// does not also silently skip the gate — the deploy is the same deploy either way.
|
|
443
|
-
// PURE.
|
|
444
|
-
function artistGateEntries(gate) {
|
|
445
|
-
const halts = [];
|
|
446
|
-
const notes = [];
|
|
447
|
-
if (gate && gate.halt) {
|
|
448
|
-
halts.push({ code: 'ARTIST_REVIEW_UNRESOLVED', message: gate.halt.message, detail: gate.halt.detail });
|
|
449
|
-
}
|
|
450
|
-
// A gate that is THERE and BROKEN halts. This is the fail-closed half: we know
|
|
451
|
-
// the instance has the route, so "it 500s" is a gate we cannot get an answer
|
|
452
|
-
// from, not a gate that does not apply. Its remedy is the instance's own logs,
|
|
453
|
-
// and it is named as such rather than as an artist problem.
|
|
454
|
-
if (gate && gate.broken) {
|
|
455
|
-
halts.push({
|
|
456
|
-
code: 'ARTIST_GATE_UNREADABLE',
|
|
457
|
-
message: HALTS.ARTIST_GATE_UNREADABLE,
|
|
458
|
-
detail: `${gate.broken}. The route exists, so this is a fault on the instance, not a missing feature — read its logs for the GET /artist-gate failure. Deploying past it would mean moving the pin without knowing whether a review holds it.`,
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
// NOT KNOWING is a different thing again, and it must not render as "nothing
|
|
462
|
-
// holds". It is a note rather than a halt on purpose: a go-live is already
|
|
463
|
-
// deliberate and reversible, and halting every deploy because there is no CLI
|
|
464
|
-
// session — or because the instance predates the route entirely — would brick
|
|
465
|
-
// the pin with no task id to release against, which is the blocked-state-that-
|
|
466
|
-
// does-not-explain-itself failure ADR 0241 §4 names.
|
|
467
|
-
if (gate && gate.unread) {
|
|
468
|
-
notes.push({
|
|
469
|
-
code: 'ARTIST_GATE_UNREAD',
|
|
470
|
-
message: `could not read this instance's artist gate (${gate.unread}) — if the project runs artist_gate 'strict', an unresolved artist review may be holding this deploy and this plan cannot see it`,
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
return { halts, notes };
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
function planGoLive({ div, target, targetVersion, dirtyCheckout, allowUnreleased = false, artistGate = null }) {
|
|
477
|
-
const halts = [];
|
|
478
|
-
const notes = [];
|
|
479
|
-
|
|
480
|
-
// Evaluated FIRST, before the git-derived checks, because it is the halt whose
|
|
481
|
-
// remedy takes longest: a review someone has to do is not a thing you fix in the
|
|
482
|
-
// next ten seconds, and finding it out after the other five checks passed is
|
|
483
|
-
// strictly worse than finding it out now.
|
|
484
|
-
const gate = artistGateEntries(artistGate);
|
|
485
|
-
halts.push(...gate.halts);
|
|
486
|
-
notes.push(...gate.notes);
|
|
487
|
-
|
|
488
|
-
if (dirtyCheckout) halts.push({ code: 'DIRTY_CHECKOUT', message: HALTS.DIRTY_CHECKOUT, detail: dirtyCheckout });
|
|
489
|
-
|
|
490
|
-
if (!div || div.undetermined) {
|
|
491
|
-
halts.push({ code: 'DIVERGENCE_UNDETERMINED', message: HALTS.DIVERGENCE_UNDETERMINED, detail: div && div.reason });
|
|
492
|
-
return { halts, notes, targetVersion, from: null };
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
const from = div.live && div.live.coreVersion;
|
|
496
|
-
|
|
497
|
-
// UNRELEASED is not the same failure as UNDEPLOYED and must not be conflated:
|
|
498
|
-
// no pin, at any version, can reach a commit no release carries. Deploying
|
|
499
|
-
// anyway is the "textbook-clean go-live that changed nothing" trap.
|
|
500
|
-
if (div.hasUnreleased) {
|
|
501
|
-
const c = div.unreleased && div.unreleased.count;
|
|
502
|
-
const entry = {
|
|
503
|
-
code: 'UNRELEASED_ON_MAIN',
|
|
504
|
-
message: HALTS.UNRELEASED_ON_MAIN,
|
|
505
|
-
detail: `${c} commit(s) on main since the last bump. The publish-on-merge job can also FAIL on a benign push race — check \`gh run list --workflow publish.yml\` for a failure before assuming this is just timing.`,
|
|
506
|
-
};
|
|
507
|
-
if (allowUnreleased) notes.push({ ...entry, downgraded: true }); else halts.push(entry);
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
if (from && targetVersion) {
|
|
511
|
-
const cmp = divergence.cmpSemver(from, targetVersion);
|
|
512
|
-
if (cmp === 0) halts.push({ code: 'ALREADY_LIVE', message: HALTS.ALREADY_LIVE, detail: `live and target are both ${from}` });
|
|
513
|
-
else if (cmp > 0) halts.push({ code: 'LIVE_AHEAD', message: HALTS.LIVE_AHEAD, detail: `live ${from} > target ${targetVersion}` });
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
return { halts, notes, from, targetVersion, target };
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
// ---------------------------------------------------------------------------
|
|
520
|
-
// Rendering
|
|
521
|
-
// ---------------------------------------------------------------------------
|
|
522
|
-
|
|
523
|
-
const BAR = ' ──────────────────────────────────────────────────────────';
|
|
524
|
-
|
|
525
|
-
function renderPlan(p, { targetName, configPath } = {}) {
|
|
526
|
-
const L = [];
|
|
527
|
-
L.push('');
|
|
528
|
-
L.push(` Go-live plan · ${targetName || 'target'}${configPath ? ` · ${configPath}` : ''}`);
|
|
529
|
-
L.push(BAR);
|
|
530
|
-
L.push(` live now ${p.from || '(unknown)'}`);
|
|
531
|
-
L.push(` target ${p.targetVersion || '(unresolved)'}`);
|
|
532
|
-
if (p.marker) L.push(` verify ${p.marker.path} contains "${p.marker.needle}"`);
|
|
533
|
-
if (p.registry) L.push(` registry ${p.registry.ok ? `carries ${p.targetVersion}` : 'MISSING'}`);
|
|
534
|
-
// The gate's state is worth a line even when it holds nothing: "artist gate
|
|
535
|
-
// advisory" is the answer to "why did nothing stop?", and a reader who cannot
|
|
536
|
-
// see the level has to go and find it.
|
|
537
|
-
if (p.artistGate && p.artistGate.mode) {
|
|
538
|
-
const open = (p.artistGate.reviews || []).length;
|
|
539
|
-
L.push(` artist gate ${p.artistGate.mode}${open ? ` · ${open} unresolved review${open === 1 ? '' : 's'}` : ' · nothing open'}`);
|
|
540
|
-
}
|
|
541
|
-
L.push('');
|
|
542
|
-
for (const n of p.notes || []) L.push(` ⚠ ${n.code} — ${n.message}`);
|
|
543
|
-
if (!p.halts.length) {
|
|
544
|
-
L.push(' ✓ no halt conditions — re-run with --apply to move the pin');
|
|
545
|
-
} else {
|
|
546
|
-
L.push(` ✖ ${p.halts.length} halt condition(s) — this go-live will NOT proceed:`);
|
|
547
|
-
for (const h of p.halts) {
|
|
548
|
-
L.push(` ${h.code} — ${h.message}`);
|
|
549
|
-
if (h.detail) L.push(` ${h.detail}`);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
L.push('');
|
|
553
|
-
return L.join('\n');
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
// Pull the lines a human needs out of a failed phase. A report that says "exit 1"
|
|
557
|
-
// and swallows the tool's own words costs a whole extra round-trip to re-run the
|
|
558
|
-
// command by hand — which is the exact cost this script exists to remove.
|
|
559
|
-
function failureExcerpt(raw, max = 12) {
|
|
560
|
-
if (!raw) return [];
|
|
561
|
-
const text = `${raw.stdout || ''}\n${raw.stderr || ''}`;
|
|
562
|
-
const lines = text.split('\n').map((l) => l.trimEnd()).filter(Boolean);
|
|
563
|
-
// Prefer the lines that carry a diagnosis over the trailing noise.
|
|
564
|
-
const signal = lines.filter((l) => /error|fail|✖|✗|denied|not found|404|refus|rollback|↩|!\s/i.test(l));
|
|
565
|
-
return (signal.length ? signal : lines).slice(-max);
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
function renderReport(r) {
|
|
569
|
-
const L = [];
|
|
570
|
-
L.push('');
|
|
571
|
-
L.push(` Go-live · ${r.targetName}`);
|
|
572
|
-
L.push(BAR);
|
|
573
|
-
L.push(` ${r.from} → ${r.to}`);
|
|
574
|
-
for (const step of r.steps || []) L.push(` ${step.ok ? (step.warn ? '⚠' : '✓') : '✖'} ${step.name}${step.detail ? ` — ${step.detail}` : ''}`);
|
|
575
|
-
|
|
576
|
-
// A refused rehearsal moved nothing, so the pin and read-back lines below would only
|
|
577
|
-
// alarm: "pin committed NO — the next reset will revert this bump" about a bump that
|
|
578
|
-
// never started (task 1004306).
|
|
579
|
-
if (r.failedAt === 'PREFLIGHT') {
|
|
580
|
-
const ex = failureExcerpt(r.raw);
|
|
581
|
-
if (ex.length) {
|
|
582
|
-
L.push('');
|
|
583
|
-
L.push(' what the upgrade said:');
|
|
584
|
-
for (const l of ex) L.push(` ${l}`);
|
|
585
|
-
}
|
|
586
|
-
L.push('');
|
|
587
|
-
L.push(` Nothing changed — still on ${r.from || 'the current core'}. No timer was stopped and no backup was written.`);
|
|
588
|
-
L.push('');
|
|
589
|
-
return L.join('\n');
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
if (!r.ok) {
|
|
593
|
-
const ex = failureExcerpt(r.raw);
|
|
594
|
-
if (ex.length) {
|
|
595
|
-
L.push('');
|
|
596
|
-
L.push(` what ${r.failedAt ? r.failedAt.toLowerCase() : 'it'} actually said:`);
|
|
597
|
-
for (const l of ex) L.push(` ${l}`);
|
|
598
|
-
}
|
|
599
|
-
if (r.rolledBack) {
|
|
600
|
-
L.push('');
|
|
601
|
-
L.push(' The instance auto-rolled-back and is serving the PREVIOUS core — it is not broken.');
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
L.push('');
|
|
606
|
-
L.push(` live reads back ${r.liveVersion || '(unread)'}`);
|
|
607
|
-
const mode = r.pinMode || DEFAULT_PIN_MODE;
|
|
608
|
-
if (mode === 'leave-dirty') L.push(' pin left in the working tree (pinMode leave-dirty)');
|
|
609
|
-
else if (r.pinCommitted) L.push(` pin committed yes${mode === 'local-commit' ? ' (local commit — this target\'s remote is not ours to push)' : ''}`);
|
|
610
|
-
else L.push(' pin committed NO — the next pull-deploy reset will revert this bump');
|
|
611
|
-
L.push('');
|
|
612
|
-
return L.join('\n');
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
// ---------------------------------------------------------------------------
|
|
616
|
-
// Phases
|
|
617
|
-
// ---------------------------------------------------------------------------
|
|
618
|
-
|
|
619
|
-
// Registry proof + optional content proof, in ONE round-trip. The registry is still
|
|
620
|
-
// consulted ON THE BOX — not because auth lives there (the package is public now), but
|
|
621
|
-
// because the box's answer is the one that matters: its network, its resolver, its cache.
|
|
622
|
-
function probeRemote(target, targetVersion, marker, opts = {}) {
|
|
623
|
-
const pkg = target.registryPackage || '@bongos/core';
|
|
624
|
-
const script = `
|
|
625
|
-
set -uo pipefail
|
|
626
|
-
echo "##REGISTRY##"
|
|
627
|
-
${asOwner(target, `npm view ${pkg}@${targetVersion} version`)} 2>&1 | tail -1
|
|
628
|
-
echo "##TREE##"
|
|
629
|
-
( cd ${target.instanceDir} && ${target.runAs ? `sudo -u ${target.runAs} -H ` : ''}git status --porcelain | head -20 )
|
|
630
|
-
echo "##INSTALLED##"
|
|
631
|
-
${asOwner(target, `node -e "console.log(require('${target.instanceDir}/node_modules/${pkg}/package.json').version)"`)} 2>&1 | tail -1
|
|
632
|
-
${marker ? `echo "##MARKER##"
|
|
633
|
-
${asOwner(target, `sh -c ${shq(markerProbe(pkg, targetVersion, marker))}`)}` : ''}
|
|
634
|
-
echo "##END##"
|
|
635
|
-
`;
|
|
636
|
-
const res = remote(target, script, opts);
|
|
637
|
-
const section = (n) => {
|
|
638
|
-
const m = res.stdout.split(`##${n}##`)[1];
|
|
639
|
-
return m === undefined ? null : m.split('##')[0].trim();
|
|
640
|
-
};
|
|
641
|
-
// `npm view` on a missing version exits non-zero and its last line is a path to a
|
|
642
|
-
// debug log — useless in a report. Anything that is not a version is reported as
|
|
643
|
-
// "not published", which is the fact the reader actually needs.
|
|
644
|
-
const registryRaw = section('REGISTRY');
|
|
645
|
-
const registryVersion = registryRaw && SEMVER_RE.test(registryRaw) ? registryRaw : null;
|
|
646
|
-
return {
|
|
647
|
-
reachable: res.ok || res.stdout.includes('##END##'),
|
|
648
|
-
raw: res,
|
|
649
|
-
registry: { ok: registryVersion === targetVersion, reported: registryVersion, raw: registryRaw },
|
|
650
|
-
boxTreeDirty: (section('TREE') || '') !== '',
|
|
651
|
-
boxTreeDetail: section('TREE') || '',
|
|
652
|
-
installed: section('INSTALLED'),
|
|
653
|
-
// null = not asked · 'PACK_FAILED' = could not check (NOT the same as absent) · a count.
|
|
654
|
-
markerHits: marker ? parseMarkerHits(section('MARKER')) : null,
|
|
655
|
-
markerError: marker ? (String(section('MARKER') || '').replace(/^PACK_FAILED\s*/, '').trim() || null) : null,
|
|
656
|
-
};
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
// The `bongos upgrade` invocation, as its own function so the pin-mode wiring is
|
|
660
|
-
// assertable without a box.
|
|
661
|
-
//
|
|
662
|
-
// Both non-default modes pass --pin-no-push, which is what tells upgrade.js the repo of
|
|
663
|
-
// record is not ours: `local-commit` pairs it with --commit-pin (commit, no push), and
|
|
664
|
-
// `leave-dirty` sends it alone, which downgrades upgrade.js's "PIN NOT COMMITTED" alarm
|
|
665
|
-
// to a note. That alarm is correct on a pull-deploy instance and misleading here, and an
|
|
666
|
-
// alarm an operator learns to ignore is worse than no alarm.
|
|
667
|
-
function upgradeCommand(target, targetVersion) {
|
|
668
|
-
const mode = pinModeOf(target);
|
|
669
|
-
return [
|
|
670
|
-
`./node_modules/.bin/bongos upgrade`,
|
|
671
|
-
`--to ${targetVersion}`, '--registry',
|
|
672
|
-
`--instance ${target.instanceDir}`,
|
|
673
|
-
`--service ${target.service}`,
|
|
674
|
-
`--health-url ${target.healthUrl}`,
|
|
675
|
-
...(mode === 'leave-dirty' ? [] : ['--commit-pin']),
|
|
676
|
-
...(mode === 'push' ? [] : ['--pin-no-push']),
|
|
677
|
-
'--force',
|
|
678
|
-
].join(' ');
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
// Whether the post-bump pin state is what this target ASKED for. Under `leave-dirty` a
|
|
682
|
-
// modified working tree is the configured outcome, so reporting it as the durability
|
|
683
|
-
// failure it is on a pull-deploy instance would make a correct co-tenant run read as
|
|
684
|
-
// broken — the one place the three modes must not share a verdict.
|
|
685
|
-
function pinStep(mode, pinDirty, head) {
|
|
686
|
-
if (mode === 'leave-dirty') {
|
|
687
|
-
return {
|
|
688
|
-
name: 'pin left in the working tree (pinMode leave-dirty)',
|
|
689
|
-
ok: true,
|
|
690
|
-
detail: pinDirty ? 'package.json/-lock MODIFIED by design — this target has no pull-deploy to revert it' : (head || null),
|
|
691
|
-
};
|
|
692
|
-
}
|
|
693
|
-
return {
|
|
694
|
-
name: mode === 'local-commit' ? 'pin committed locally (not pushed)' : 'pin committed + pushed',
|
|
695
|
-
ok: !pinDirty,
|
|
696
|
-
detail: pinDirty ? 'package.json/-lock still MODIFIED — the next reset --hard reverts this bump' : (head || null),
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
// How many pre-upgrade dumps a backupDir keeps (task 1004306). Nothing pruned them, so
|
|
701
|
-
// the directory grew by one dump per attempt for as long as the lane ran: 37 dumps and
|
|
702
|
-
// 1.7 GB on cloudbongos.com by 2026-09-26, at about ONE attempt a day. The count, not an age,
|
|
703
|
-
// is the bound because the cadence is what varies — ten is ten at daily or at every
|
|
704
|
-
// fifteen minutes. These are the extra copies taken right before a pin move; the
|
|
705
|
-
// nightly backup (db-backup-nightly.sh, 30 days) is the history and is not touched.
|
|
706
|
-
const PRE_UPGRADE_KEEP = 10;
|
|
707
|
-
// Exactly the name Phase A writes: pre-<version>-<YYYYMMDDTHHMMSSZ>.sql.gz. A looser
|
|
708
|
-
// `pre-*` would also take a dump an operator named by hand — the box has a
|
|
709
|
-
// `pre-lane-sweep-<ts>.sql.gz` in that directory, and it is not ours to delete.
|
|
710
|
-
const D8 = '[0-9]'.repeat(8);
|
|
711
|
-
const D6 = '[0-9]'.repeat(6);
|
|
712
|
-
const PRE_UPGRADE_GLOB = `pre-[0-9]*-${D8}T${D6}Z.sql.gz`;
|
|
713
|
-
|
|
714
|
-
// Delete all but the newest PRE_UPGRADE_KEEP pre-upgrade dumps and print how many went.
|
|
715
|
-
// Newest by mtime, never by name: the name sorts 1.19.99 after 1.19.100. It runs only
|
|
716
|
-
// after a dump succeeded, so a run of failures can never empty the directory, and the
|
|
717
|
-
// dump just written is always the newest and always kept. No `$` anywhere, so the
|
|
718
|
-
// outer shell that feeds this to `bash -c` expands nothing in it.
|
|
719
|
-
function pruneCommand(dir, keep = PRE_UPGRADE_KEEP) {
|
|
720
|
-
return `bash -c "cd ${dir} && ls -1t -- ${PRE_UPGRADE_GLOB} 2>/dev/null | tail -n +${keep + 1} | xargs -r rm -v -- | wc -l"`;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
// Read the prune section back into a step. A prune that could not run is a WARNING,
|
|
724
|
-
// not a failure: the dump it follows is good, and refusing the upgrade over a full
|
|
725
|
-
// cleanup would trade a real deploy for tidiness. It still says so on screen.
|
|
726
|
-
function pruneStep(section, keep = PRE_UPGRADE_KEEP) {
|
|
727
|
-
const name = `prune old pre-upgrade backups (keep the newest ${keep})`;
|
|
728
|
-
const s = String(section == null ? '' : section).trim();
|
|
729
|
-
if (/^\d+$/.test(s)) return { name, ok: true, detail: s === '0' ? 'nothing to remove' : `removed ${s}` };
|
|
730
|
-
return { name, ok: true, warn: true, detail: `could not prune${s ? ` (${s.split('\n').pop()})` : ''} — the directory will keep growing until this is fixed` };
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
function applyGoLive(target, targetName, targetVersion, from, opts = {}) {
|
|
734
|
-
const pkg = target.registryPackage || '@bongos/core';
|
|
735
|
-
const pinMode = pinModeOf(target);
|
|
736
|
-
const steps = [];
|
|
737
|
-
const upgrade = upgradeCommand(target, targetVersion);
|
|
738
|
-
|
|
739
|
-
// Phase 0 — ask the upgrade whether it WILL go, before anything is stopped or copied
|
|
740
|
-
// (task 1004306). `bongos upgrade --dry-run` runs every refusal the real bump has —
|
|
741
|
-
// the artist gate, module compatibility, the database identity, the downgrade guard —
|
|
742
|
-
// and returns before it changes anything. Phase A used to come first, so on
|
|
743
|
-
// cloudbongos.com (2026-09-26 17:10 and 17:15 UTC) each attempt the artist gate
|
|
744
|
-
// refused had already stopped the deploy timer and written a 65 MB dump: one a day at
|
|
745
|
-
// the daily cadence, a full disk in about three days at every fifteen minutes.
|
|
746
|
-
// runGoLive's own gate read did not stop those runs either, and left no trace of what
|
|
747
|
-
// it saw: on --apply a plan with no halts is never printed, notes included. The bump's
|
|
748
|
-
// pre-flight asks the instance directly, and it was the first thing to say no.
|
|
749
|
-
const rehearsal = remote(target, `
|
|
750
|
-
set -uo pipefail
|
|
751
|
-
${asOwner(target, `bash -c "cd ${target.instanceDir} && ${upgrade} --dry-run"`)}
|
|
752
|
-
`, opts);
|
|
753
|
-
steps.push({
|
|
754
|
-
name: 'pre-flight (the upgrade, rehearsed with --dry-run)',
|
|
755
|
-
ok: rehearsal.ok,
|
|
756
|
-
detail: rehearsal.ok ? null : 'refused — nothing was stopped and nothing was backed up',
|
|
757
|
-
});
|
|
758
|
-
if (!rehearsal.ok) return { ok: false, steps, from, to: targetVersion, targetName, pinMode, failedAt: 'PREFLIGHT', refused: true, raw: rehearsal };
|
|
759
|
-
|
|
760
|
-
// Phase A — stop the pull-deploy timer, then back up. The timer's `reset --hard`
|
|
761
|
-
// is the hazard: it would revert an uncommitted pin mid-flight. A co-tenant has no
|
|
762
|
-
// such timer (see REQUIRED_FIELDS), so there is nothing to stop and no hazard.
|
|
763
|
-
//
|
|
764
|
-
// The dump must FAIL when pg_dump fails. `pg_dump | gzip > f` without pipefail
|
|
765
|
-
// reports gzip's success, leaving a 20-byte file that reads as a backup — harmless
|
|
766
|
-
// while nothing pruned, but the prune below keeps the newest ten, so a streak of
|
|
767
|
-
// those would retire every real dump (task 1004306). A failed dump removes its file
|
|
768
|
-
// and fails the phase, which stops the go-live before the pin moves: a bump with no
|
|
769
|
-
// backup behind it is not one to make unattended. $TS is expanded once by this
|
|
770
|
-
// script so the dump and its cleanup name the same file.
|
|
771
|
-
const backupDir = target.backupDir || '~/backups';
|
|
772
|
-
const dumpFile = `${backupDir}/pre-${targetVersion}-$TS.sql.gz`;
|
|
773
|
-
const backup = target.backupDb
|
|
774
|
-
? asOwner(target, `bash -c "set -o pipefail; mkdir -p ${backupDir} && { pg_dump ${target.backupDb} | gzip > ${dumpFile} || { rm -f ${dumpFile}; exit 1; }; }"`)
|
|
775
|
-
: 'echo "(no backupDb configured — skipping)"';
|
|
776
|
-
// `|| echo`: under `set -e` a failed prune would otherwise fail the whole phase and
|
|
777
|
-
// stop a deploy whose backup is already safely on disk (see pruneStep).
|
|
778
|
-
const prune = target.backupDb
|
|
779
|
-
? `echo "##PRUNE##"; ${asOwner(target, pruneCommand(backupDir))} || echo "prune exited non-zero"`
|
|
780
|
-
: '';
|
|
781
|
-
const phaseA = remote(target, `
|
|
782
|
-
set -euo pipefail
|
|
783
|
-
${SUDO_PREAMBLE}
|
|
784
|
-
echo "##TIMER##"; ${target.deployTimer
|
|
785
|
-
? `$SUDO systemctl stop ${target.deployTimer} && $SUDO systemctl is-active ${target.deployTimer} || true`
|
|
786
|
-
: 'echo "(no deployTimer configured — no pull-deploy to stop)"'}
|
|
787
|
-
TS="$(date -u +%Y%m%dT%H%M%SZ)"
|
|
788
|
-
echo "##BACKUP##"; ${backup}
|
|
789
|
-
${prune}
|
|
790
|
-
echo "##END##"
|
|
791
|
-
`, opts);
|
|
792
|
-
steps.push({
|
|
793
|
-
name: target.deployTimer ? `stop ${target.deployTimer} + backup` : 'backup (no pull-deploy timer)',
|
|
794
|
-
ok: phaseA.ok,
|
|
795
|
-
detail: phaseA.ok ? null : (phaseA.stderr || '').trim().split('\n').pop(),
|
|
796
|
-
});
|
|
797
|
-
if (!phaseA.ok) {
|
|
798
|
-
// The timer may already be stopped — Phase A stops it before the dump, and a dump
|
|
799
|
-
// can now fail on its own (above). Put it back, as a failed upgrade does below.
|
|
800
|
-
if (target.deployTimer) remote(target, `${SUDO_PREAMBLE}\n$SUDO systemctl start ${target.deployTimer} || true`, opts);
|
|
801
|
-
return { ok: false, steps, from, to: targetVersion, targetName, pinMode, failedAt: 'PREPARE', raw: phaseA };
|
|
802
|
-
}
|
|
803
|
-
if (target.backupDb) {
|
|
804
|
-
const m = (phaseA.stdout || '').split('##PRUNE##')[1];
|
|
805
|
-
steps.push(pruneStep(m === undefined ? null : m.split('##')[0]));
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
// Phase B — the upgrade itself. --commit-pin makes the bump durable against the
|
|
809
|
-
// pull-deploy reset; auto-rollback stays ON (do NOT pass --no-rollback-on-failure).
|
|
810
|
-
const phaseB = remote(target, `
|
|
811
|
-
set -uo pipefail
|
|
812
|
-
${asOwner(target, `bash -c "cd ${target.instanceDir} && ${upgrade}"`)}
|
|
813
|
-
`, opts);
|
|
814
|
-
const rolledBack = /rolled back/i.test(phaseB.stdout + phaseB.stderr);
|
|
815
|
-
steps.push({
|
|
816
|
-
name: `upgrade ${from} → ${targetVersion}`,
|
|
817
|
-
ok: phaseB.ok && !rolledBack,
|
|
818
|
-
detail: rolledBack ? 'AUTO-ROLLBACK ran — the health check failed after restart' : (phaseB.ok ? null : `exit ${phaseB.status}`),
|
|
819
|
-
});
|
|
820
|
-
if (!phaseB.ok || rolledBack) {
|
|
821
|
-
// Restart the timer even on failure — leaving it stopped silently disables
|
|
822
|
-
// the instance's pull-deploy until someone notices. Nothing was stopped on a
|
|
823
|
-
// co-tenant, so there is nothing to put back.
|
|
824
|
-
if (target.deployTimer) remote(target, `${SUDO_PREAMBLE}\n$SUDO systemctl start ${target.deployTimer} || true`, opts);
|
|
825
|
-
return { ok: false, steps, from, to: targetVersion, targetName, pinMode, failedAt: 'UPGRADE', rolledBack, raw: phaseB };
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
// Phase C — restart the timer, force one tick, and read back the BOX-SIDE truth.
|
|
829
|
-
// The apex may sit behind basic_auth and its HTML rides a CDN, so the apex is
|
|
830
|
-
// not evidence; 127.0.0.1 is.
|
|
831
|
-
const phaseC = remote(target, `
|
|
832
|
-
set -uo pipefail
|
|
833
|
-
${SUDO_PREAMBLE}
|
|
834
|
-
${target.deployTimer ? `echo "##TIMERSTART##"; $SUDO systemctl start ${target.deployTimer}; $SUDO systemctl is-active ${target.deployTimer}` : ''}
|
|
835
|
-
echo "##PIN##"; ( cd ${target.instanceDir} && ${target.runAs ? `sudo -u ${target.runAs} -H ` : ''}git status --porcelain -- package.json package-lock.json )
|
|
836
|
-
echo "##HEAD##"; ( cd ${target.instanceDir} && ${target.runAs ? `sudo -u ${target.runAs} -H ` : ''}git log -1 --format='%h %s' )
|
|
837
|
-
${target.deployService ? `echo "##TICK##"; $SUDO systemctl start ${target.deployService} || true; $SUDO journalctl -u ${target.deployService} -n 20 --no-pager | tail -8` : ''}
|
|
838
|
-
echo "##VERSION##"; curl -s --max-time 20 ${target.versionUrl} | head -c 400
|
|
839
|
-
echo ""
|
|
840
|
-
echo "##INSTALLED##"; ${asOwner(target, `node -e "console.log(require('${target.instanceDir}/node_modules/${pkg}/package.json').version)"`)} 2>&1 | tail -1
|
|
841
|
-
echo "##END##"
|
|
842
|
-
`, opts);
|
|
843
|
-
const section = (n) => {
|
|
844
|
-
const m = phaseC.stdout.split(`##${n}##`)[1];
|
|
845
|
-
return m === undefined ? null : m.split('##')[0].trim();
|
|
846
|
-
};
|
|
847
|
-
const pinDirty = (section('PIN') || '') !== '';
|
|
848
|
-
const installed = section('INSTALLED');
|
|
849
|
-
let liveVersion = null;
|
|
850
|
-
try { liveVersion = JSON.parse(section('VERSION') || '{}').coreVersion || null; } catch { liveVersion = null; }
|
|
851
|
-
|
|
852
|
-
if (target.deployTimer) steps.push({ name: `restart ${target.deployTimer}`, ok: (section('TIMERSTART') || '').includes('active') });
|
|
853
|
-
steps.push(pinStep(pinMode, pinDirty, section('HEAD')));
|
|
854
|
-
steps.push({ name: 'installed package version', ok: installed === targetVersion, detail: installed === targetVersion ? installed : `reports ${installed}, expected ${targetVersion}` });
|
|
855
|
-
steps.push({ name: 'live reads back (box-side)', ok: liveVersion === targetVersion, detail: liveVersion === targetVersion ? liveVersion : `reports ${liveVersion}, expected ${targetVersion}` });
|
|
856
|
-
|
|
857
|
-
const ok = steps.every((s) => s.ok);
|
|
858
|
-
return { ok, steps, from, to: targetVersion, targetName, pinMode, liveVersion, installed, pinCommitted: !pinDirty, raw: phaseC };
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
// ---------------------------------------------------------------------------
|
|
862
|
-
// CLI
|
|
863
|
-
// ---------------------------------------------------------------------------
|
|
864
|
-
|
|
865
|
-
function usage() {
|
|
866
|
-
console.log(`
|
|
867
|
-
go-live — move an enrolled instance's core pin, as one command.
|
|
868
|
-
|
|
869
|
-
node scripts/gds/go-live.js PLAN only (read-only, the default)
|
|
870
|
-
node scripts/gds/go-live.js --apply move the pin
|
|
871
|
-
node scripts/gds/go-live.js --to <version> target a version explicitly
|
|
872
|
-
node scripts/gds/go-live.js --verify-marker <path>=<needle>
|
|
873
|
-
refuse a target that lacks the change
|
|
874
|
-
node scripts/gds/go-live.js --target <name> pick a target from the config
|
|
875
|
-
node scripts/gds/go-live.js --config <path> default: ${DEFAULT_CONFIG}
|
|
876
|
-
node scripts/gds/go-live.js --allow-unreleased downgrade UNRELEASED_ON_MAIN to a warning
|
|
877
|
-
node scripts/gds/go-live.js --no-fetch skip the origin/main refresh (default: fetch)
|
|
878
|
-
node scripts/gds/go-live.js --target-json '{…}' pass a target inline instead of a config file
|
|
879
|
-
node scripts/gds/go-live.js --no-divergence skip the git-derived checks (needs --to)
|
|
880
|
-
node scripts/gds/go-live.js --json machine-readable
|
|
881
|
-
|
|
882
|
-
CO-TENANT TARGETS. A provisioned instance has no pull-deploy timer and its repo of
|
|
883
|
-
record is the customer's own, so omit "deployTimer" (the stop/restart is skipped) and
|
|
884
|
-
set "pinMode": "local-commit" (the pin is committed, never pushed). "leave-dirty"
|
|
885
|
-
leaves the bump in the working tree; "push" (the default) is the platform instance.
|
|
886
|
-
|
|
887
|
-
Host topology is NOT baked into the core. ${DEFAULT_CONFIG} (host-owned, not published):
|
|
888
|
-
|
|
889
|
-
${CONFIG_TEMPLATE}
|
|
890
|
-
`);
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
async function main() {
|
|
894
|
-
if (hasFlag('--help') || hasFlag('-h')) { usage(); return 0; }
|
|
895
|
-
|
|
896
|
-
const json = hasFlag('--json');
|
|
897
|
-
const apply = hasFlag('--apply');
|
|
898
|
-
const allowUnreleased = hasFlag('--allow-unreleased');
|
|
899
|
-
|
|
900
|
-
// An inline target lets a CALLER drive this without inventing a second host-owned
|
|
901
|
-
// config file beside the one it already has. The nightly lane already holds a roster
|
|
902
|
-
// entry; making it also maintain config/go-live.json would be two sources of truth
|
|
903
|
-
// for one box, which is how they drift.
|
|
904
|
-
const inline = arg('--target-json');
|
|
905
|
-
if (inline) {
|
|
906
|
-
let parsed;
|
|
907
|
-
try { parsed = JSON.parse(inline); }
|
|
908
|
-
catch (e) { console.error(` go-live: --target-json is not valid JSON — ${e.message}`); return 2; }
|
|
909
|
-
const errors = validateTarget('inline', parsed);
|
|
910
|
-
if (errors.length) {
|
|
911
|
-
if (json) { console.log(JSON.stringify({ ok: false, halt: 'CONFIG_INVALID', detail: errors.join('; ') }, null, 2)); return 1; }
|
|
912
|
-
console.error(`\n go-live: CONFIG_INVALID — ${errors.join('; ')}\n`);
|
|
913
|
-
return 1;
|
|
914
|
-
}
|
|
915
|
-
return runGoLive({ target: parsed, targetName: arg('--target') || 'inline', configPath: '--target-json', json, apply, allowUnreleased });
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
const cfg = loadConfig({ configPath: arg('--config') });
|
|
919
|
-
if (cfg.error) {
|
|
920
|
-
if (json) { console.log(JSON.stringify({ ok: false, halt: cfg.error, path: cfg.path, detail: cfg.detail }, null, 2)); return 1; }
|
|
921
|
-
console.error(`\n go-live: ${cfg.error} — ${cfg.path}${cfg.detail ? `\n ${cfg.detail}` : ''}`);
|
|
922
|
-
if (cfg.error === 'NO_TARGET_CONFIG') {
|
|
923
|
-
console.error(`\n This file is host-owned and deliberately not shipped in the core.\n Create it with your box's topology:\n\n${CONFIG_TEMPLATE}\n`);
|
|
924
|
-
}
|
|
925
|
-
return 1;
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
const sel = selectTarget(cfg.config, arg('--target'));
|
|
929
|
-
if (sel.error) {
|
|
930
|
-
if (json) { console.log(JSON.stringify({ ok: false, halt: sel.error, detail: sel.detail }, null, 2)); return 1; }
|
|
931
|
-
console.error(`\n go-live: ${sel.error} — ${sel.detail}\n`);
|
|
932
|
-
return 1;
|
|
933
|
-
}
|
|
934
|
-
const { target, name: targetName } = sel;
|
|
935
|
-
return runGoLive({ target, targetName, configPath: cfg.path, json, apply, allowUnreleased });
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
async function runGoLive({ target, targetName, configPath, json, apply, allowUnreleased }) {
|
|
939
|
-
const marker = parseMarker(arg('--verify-marker'));
|
|
940
|
-
if (marker && marker.error) { console.error(` go-live: ${marker.error}`); return 2; }
|
|
941
|
-
|
|
942
|
-
// Resolve the target version: an explicit --to, else CORE_VERSION on main.
|
|
943
|
-
let targetVersion = arg('--to');
|
|
944
|
-
if (targetVersion && !SEMVER_RE.test(targetVersion)) { console.error(` go-live: --to "${targetVersion}" is not a version`); return 2; }
|
|
945
|
-
|
|
946
|
-
// Is there a core GIT CHECKOUT to reason about at all?
|
|
947
|
-
//
|
|
948
|
-
// Every git-derived signal — the target read from origin/main, the UNRELEASED halt,
|
|
949
|
-
// the dirty-checkout halt — presumes this process is running inside a core repo.
|
|
950
|
-
// The nightly lane is NOT: it runs on the box, against an installed package, and it
|
|
951
|
-
// resolves its target from the REGISTRY under a channel policy instead. Running the
|
|
952
|
-
// git checks there would halt every sweep on a condition that does not apply.
|
|
953
|
-
//
|
|
954
|
-
// So the git legs are SKIPPED only when both are true: there is no resolvable
|
|
955
|
-
// origin/main, AND the caller named the version explicitly. A missing checkout with
|
|
956
|
-
// no --to is still an error — silently inventing a target is exactly the class of
|
|
957
|
-
// guess this script exists to refuse.
|
|
958
|
-
// "Am I in a SOURCE checkout?" is `.git` AT OUR ROOT — not "is there a git repo
|
|
959
|
-
// somewhere above me". The installed core package lives inside the INSTANCE's repo
|
|
960
|
-
// and ships its own src/module-api.js, so a naive `git rev-parse HEAD` succeeds
|
|
961
|
-
// there and CORE_VERSION resolves — against the instance repo's main, which is a
|
|
962
|
-
// meaningless answer delivered confidently. That is the failure this check avoids.
|
|
963
|
-
const hasCheckout = fs.existsSync(path.join(ROOT, '.git'));
|
|
964
|
-
const gitless = (!hasCheckout || hasFlag('--no-divergence')) && !!targetVersion;
|
|
965
|
-
|
|
966
|
-
const fetched = (gitless || hasFlag('--no-fetch')) ? { ok: false, skipped: true } : refreshMain();
|
|
967
|
-
const div = gitless ? null : await divergence.check({ base: arg('--url') });
|
|
968
|
-
if (!targetVersion) targetVersion = div && div.onMain;
|
|
969
|
-
if (!targetVersion || !SEMVER_RE.test(targetVersion)) {
|
|
970
|
-
console.error(` go-live: could not resolve a target version${hasCheckout ? ` (read ${JSON.stringify(targetVersion)} from main)` : ' — this is not a core source checkout, so pass --to <version>'}`);
|
|
971
|
-
return 1;
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
const dirtyRes = gitless ? { status: 1 } : spawnSync('git', ['status', '--porcelain'], { cwd: ROOT, encoding: 'utf8' });
|
|
975
|
-
const dirtyCheckout = dirtyRes.status === 0 && (dirtyRes.stdout || '').trim() ? (dirtyRes.stdout || '').trim().split('\n').slice(0, 5).join(', ') : null;
|
|
976
|
-
|
|
977
|
-
// Always read, and deliberately NOT skippable by a flag. ADR 0241 §3 names one
|
|
978
|
-
// escape hatch — the project OWNER's override-request, rationale required and
|
|
979
|
-
// audit-logged — and a `--skip` here would be a second authority path that any
|
|
980
|
-
// builder with the shell could take silently, which is exactly the shape that
|
|
981
|
-
// ADR rejects. An unread gate already degrades to a note; that is the only
|
|
982
|
-
// by-pass, and it says so on screen.
|
|
983
|
-
const artistGate = await readArtistGate();
|
|
984
|
-
|
|
985
|
-
const gitlessGate = artistGateEntries(artistGate);
|
|
986
|
-
const plan = gitless
|
|
987
|
-
? {
|
|
988
|
-
halts: gitlessGate.halts,
|
|
989
|
-
notes: [
|
|
990
|
-
{ code: 'NO_CORE_CHECKOUT', message: `no core git checkout here — target ${targetVersion} was given explicitly, so the git-derived checks (unreleased-on-main, dirty tree) are skipped` },
|
|
991
|
-
...gitlessGate.notes,
|
|
992
|
-
],
|
|
993
|
-
from: null,
|
|
994
|
-
targetVersion,
|
|
995
|
-
target,
|
|
996
|
-
}
|
|
997
|
-
: planGoLive({ div, target, targetVersion, dirtyCheckout, allowUnreleased, artistGate });
|
|
998
|
-
plan.artistGate = artistGate;
|
|
999
|
-
plan.marker = marker;
|
|
1000
|
-
if (!fetched.ok && !fetched.skipped) {
|
|
1001
|
-
// Say so rather than silently planning off a ref of unknown age.
|
|
1002
|
-
plan.notes.push({ code: 'MAIN_NOT_FETCHED', message: `could not refresh origin/main (${fetched.reason}) — the target below is read from a ref of unknown age` });
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
|
-
// Probe the box only once the local picture is worth acting on — an ssh
|
|
1006
|
-
// round-trip to confirm a plan that already has a halt is wasted.
|
|
1007
|
-
if (!plan.halts.length) {
|
|
1008
|
-
const probe = probeRemote(target, targetVersion, marker);
|
|
1009
|
-
plan.registry = probe.registry;
|
|
1010
|
-
// With no source checkout there is no git-derived `from`; the installed version on
|
|
1011
|
-
// the box IS the truth, and the probe just read it.
|
|
1012
|
-
if (gitless && probe.installed) {
|
|
1013
|
-
plan.from = probe.installed;
|
|
1014
|
-
if (probe.installed === targetVersion) {
|
|
1015
|
-
plan.halts.push({ code: 'ALREADY_LIVE', message: HALTS.ALREADY_LIVE, detail: `installed and target are both ${targetVersion}` });
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
if (!probe.reachable) {
|
|
1019
|
-
plan.halts.push({ code: 'BOX_UNREACHABLE', message: `could not reach ${target.ssh}`, detail: (probe.raw.stderr || '').trim().split('\n').pop() });
|
|
1020
|
-
} else {
|
|
1021
|
-
if (!probe.registry.ok) {
|
|
1022
|
-
plan.halts.push({
|
|
1023
|
-
code: 'REGISTRY_MISSING_TARGET', message: HALTS.REGISTRY_MISSING_TARGET,
|
|
1024
|
-
detail: `npm reports ${probe.registry.reported ? JSON.stringify(probe.registry.reported) : 'not published'} for ${target.registryPackage || '@bongos/core'}@${targetVersion}. A version bumped on main but never published leaves main's code reachable by no pin — check \`gh run list --workflow publish.yml\` for a failed run.`,
|
|
1025
|
-
});
|
|
1026
|
-
}
|
|
1027
|
-
if (probe.boxTreeDirty) {
|
|
1028
|
-
plan.halts.push({ code: 'BOX_TREE_DIRTY', message: HALTS.BOX_TREE_DIRTY, detail: probe.boxTreeDetail.split('\n').slice(0, 5).join(', ') });
|
|
1029
|
-
}
|
|
1030
|
-
if (marker && probe.markerHits === 'PACK_FAILED') {
|
|
1031
|
-
// "Could not check" must never render as "absent" — that reads exactly like
|
|
1032
|
-
// the real trap and sends you chasing a version that does not exist.
|
|
1033
|
-
plan.halts.push({
|
|
1034
|
-
code: 'MARKER_UNCHECKED', message: HALTS.MARKER_UNCHECKED,
|
|
1035
|
-
detail: `could not download ${target.registryPackage || '@bongos/core'}@${targetVersion} to inspect it${probe.markerError ? `: ${probe.markerError}` : ''}. This is NOT evidence the change is missing — fix the fetch, or drop --verify-marker and verify by hand.`,
|
|
1036
|
-
});
|
|
1037
|
-
} else if (marker && probe.markerHits === 0) {
|
|
1038
|
-
plan.halts.push({
|
|
1039
|
-
code: 'MARKER_ABSENT', message: HALTS.MARKER_ABSENT,
|
|
1040
|
-
detail: `${targetVersion} does not contain "${marker.needle}" in ${marker.path}. The carrier sitting on main when your fix merged was usually cut BEFORE it (ADR 0161) — try the next version.`,
|
|
1041
|
-
});
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
if (!apply || plan.halts.length) {
|
|
1047
|
-
if (json) { console.log(JSON.stringify({ ok: !plan.halts.length, mode: apply ? 'halted' : 'plan', targetName, ...plan }, null, 2)); }
|
|
1048
|
-
else { console.log(renderPlan(plan, { targetName, configPath })); }
|
|
1049
|
-
return plan.halts.length ? 1 : 0;
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
const result = applyGoLive(target, targetName, targetVersion, plan.from);
|
|
1053
|
-
if (json) console.log(JSON.stringify(result, null, 2));
|
|
1054
|
-
else console.log(renderReport(result));
|
|
1055
|
-
return result.ok ? 0 : 1;
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
if (require.main === module) {
|
|
1059
|
-
main().then((c) => { process.exitCode = c; }).catch((e) => {
|
|
1060
|
-
console.error(`go-live: fatal — ${e && e.message ? e.message : e}`);
|
|
1061
|
-
process.exitCode = 1;
|
|
1062
|
-
});
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
module.exports = {
|
|
1066
|
-
loadConfig, selectTarget, validateTarget, planGoLive, artistGateEntries, readArtistGate, ARTIST_GATE_PATH, ARTIST_GATE_LEVELS,
|
|
1067
|
-
parseMarker, parseMarkerHits,
|
|
1068
|
-
renderPlan, renderReport, failureExcerpt, asOwner, isSafeToken, refreshMain, isLocalTarget, gitRefExists, SUDO_PREAMBLE,
|
|
1069
|
-
applyGoLive, upgradeCommand, pinStep, pinModeOf, pruneCommand, pruneStep, PRE_UPGRADE_KEEP, PRE_UPGRADE_GLOB,
|
|
1070
|
-
CONFIG_TEMPLATE, HALTS, SEMVER_RE, PIN_MODES, DEFAULT_PIN_MODE,
|
|
1071
|
-
};
|
|
7
|
+
require('../bongos/forwarder.js').forward(module, 'go-live.js');
|