@bongos/core 1.21.175 → 1.21.177
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 +3371 -1636
- 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 +15 -15
- 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/config/scheduled-routines.json +3 -8
- package/docs/adr/0029-status-page-outage-resilience.md +6 -6
- package/docs/adr/0091-bounding-the-kernel-and-db-carve.md +1 -1
- package/docs/adr/0093-tranche-2-core-carve-sequence.md +1 -1
- 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 +4 -4
- 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 +92 -96
- package/docs/handoff-template.md +5 -5
- package/docs/module-api-changelog.md +7 -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 +5 -9
- package/docs/onboarding/diagrams/assertions.json +3 -3
- 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 +13 -10
- 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/db.js +9 -0
- package/modules/autonomy/gauge.js +1 -1
- package/modules/autonomy/governor-docket.js +2 -2
- package/modules/autonomy/module.json +2 -2
- package/modules/autonomy/pollers/daily-checks.js +262 -0
- package/modules/autonomy/pollers/routine-timers.js +9 -7
- package/modules/autonomy/rank-roles.js +64 -0
- package/modules/autonomy/routes/autonomy.js +3 -3
- package/modules/autonomy/server-schedule.js +37 -0
- 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 +186 -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/ask.js +231 -0
- package/scripts/bongos/audit-authorship.sh +324 -0
- package/scripts/bongos/audit-deps.js +189 -0
- package/scripts/bongos/audit-gate.js +121 -0
- package/scripts/bongos/audit-rank-roles.js +131 -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/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 +380 -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/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 +332 -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.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 +338 -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-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 +318 -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-bongos-v1-idea-routing-tasks.js +152 -0
- package/scripts/bongos/seed-bv1-profiles-tasks.js +135 -0
- package/scripts/bongos/seed-bv2-ideator-surface-tasks.js +390 -0
- package/scripts/bongos/seed-staging.sh +117 -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 +291 -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/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/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/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/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.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-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-bongos-v1-idea-routing-tasks.js +6 -152
- package/scripts/gds/seed-bv1-profiles-tasks.js +6 -135
- package/scripts/gds/seed-bv2-ideator-surface-tasks.js +6 -390
- package/scripts/gds/seed-staging.sh +7 -116
- 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/security/dep-audit.js +50 -124
- 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/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_daily_checks.mjs +201 -0
- 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 +68 -68
- 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 +1 -19
- 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_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/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 +24 -13
- package/tests/routine_schedule.mjs +51 -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/artifact-staleness.js +0 -267
- package/scripts/gds/audit-exports.js +0 -128
- package/scripts/gds/classify-discipline.js +0 -153
- package/scripts/gds/codemod-rename-src-gds.js +0 -145
- package/scripts/gds/coreB-carve-proof.sh +0 -725
- package/scripts/gds/goal-names.js +0 -102
- package/scripts/gds/rename-goals.js +0 -109
- package/scripts/gds/resolve-skill-model.js +0 -57
- package/scripts/gds/security-baseline-check.sh +0 -180
- package/scripts/gds/seed-adopt-tasks.js +0 -75
- package/scripts/gds/seed-api-contract-goal-tasks.js +0 -141
- package/scripts/gds/seed-board-room-tasks.js +0 -196
- package/scripts/gds/seed-bongos-app-tasks.js +0 -294
- package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +0 -81
- package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +0 -100
- package/scripts/gds/seed-bongos-goal-hierarchy-tasks.js +0 -307
- package/scripts/gds/seed-bongos-module-system-tasks.js +0 -346
- package/scripts/gds/seed-bongos-tasks.js +0 -214
- package/scripts/gds/seed-bongos-v1-seo-tasks.js +0 -104
- package/scripts/gds/seed-bv1-community-tasks.js +0 -131
- package/scripts/gds/seed-bv1-privacy-invites-tasks.js +0 -133
- package/scripts/gds/seed-bv1-profile-page-tasks.js +0 -161
- package/scripts/gds/seed-bv1-r01-delta-tasks.js +0 -154
- package/scripts/gds/seed-bv2-tweak-mode-tasks.js +0 -277
- package/scripts/gds/seed-gds-v4-tasks.js +0 -624
- package/scripts/gds/seed-governance-tasks.js +0 -340
- package/scripts/gds/seed-medusa-tasks.js +0 -440
- package/scripts/gds/seed-module-upstreaming.js +0 -219
- package/scripts/gds/seed-productization-tasks.js +0 -235
- package/scripts/gds/seed-project-admin-console-tasks.js +0 -88
- package/scripts/gds/seed-provisioning-tasks.js +0 -83
- package/scripts/gds/seed-strict-versioning-tasks.js +0 -275
- package/scripts/gds/seed-v2-world-tasks.js +0 -283
- package/scripts/gds/spike-task-map.js +0 -899
- package/scripts/migrate_cost_ledger.sh +0 -178
- package/scripts/status-probe.mjs +0 -213
- package/src/bongos/uptime-poller.js +0 -93
- package/tests/artifact_staleness.mjs +0 -207
- package/tests/goal_names.mjs +0 -120
- 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
|
@@ -1,1200 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
// scripts/gds/claude-materialize.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/claude-materialize.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
|
-
// (ADR 0108 §3, configurable-root W3 / task 1883).
|
|
5
|
-
//
|
|
6
|
-
// WHY. Claude Code discovers .claude/settings.json + hooks/ + skills/ from the PROJECT ROOT, never
|
|
7
|
-
// from a dependency. Once the Cloud Bongos core installs as a pinned npm package (ADR 0108), the
|
|
8
|
-
// ~35 skills sit in node_modules/@bongos/core/.claude/skills/ where Claude Code will not look —
|
|
9
|
-
// so `bongos init`/`upgrade` must COPY .claude/ into the instance repo. And a copied skill can't run
|
|
10
|
-
// `node scripts/gds/<x>.js`: scripts/ lives in the package, not at the instance root. So every
|
|
11
|
-
// invocation is rewritten to the `bongos` bin, which resolves the heavy CLI inside the package —
|
|
12
|
-
// a dedicated verb where one exists (`bongos ship`), else the generic `bongos exec scripts/gds/<x>.js`.
|
|
13
|
-
//
|
|
14
|
-
// BOUNDARY (publish-manifest). skills/ ships IN the core package (isPublishable) → materialized by
|
|
15
|
-
// copy+transform. hooks/ + settings.json are TOPOLOGY (PROTECTED_TOPOLOGY_EXCLUDE) → NOT in the
|
|
16
|
-
// package; this module copies+transforms them when they ARE present at the core root (today's single
|
|
17
|
-
// checkout, and the core repo itself), and no-ops with a note when they aren't (an installed package).
|
|
18
|
-
// Hooks self-resolve their core require()s at RUNTIME via the copied _core-resolve.js sibling
|
|
19
|
-
// (task 2139, the former W3 follow-up), so no require-path rewriting happens here. The topology
|
|
20
|
-
// STARTER for a package-only install is now HALF built: settings.json is written from
|
|
21
|
-
// renderStarterSettings() below — permissions only, no hooks — because an instance that received
|
|
22
|
-
// the skills but no permissions met the classifier on every blessed command (task 1003962). A hooks
|
|
23
|
-
// starter remains a follow-up (task 1883), and is a different question: hooks ARE gate machinery,
|
|
24
|
-
// where a list of allowed command names is not.
|
|
25
|
-
//
|
|
26
|
-
// SELF-COPY GUARD. When the instance dir IS the core root (running init inside the core checkout /
|
|
27
|
-
// OTB today), there is nothing to materialize — a self-copy would be a no-op at best and corrupting
|
|
28
|
-
// at worst. This module detects that and skips, so it is byte-identical for the live instance.
|
|
29
|
-
|
|
30
|
-
const fs = require('node:fs');
|
|
31
|
-
const path = require('node:path');
|
|
32
|
-
const { spawnSync } = require('node:child_process');
|
|
33
|
-
const crypto = require('node:crypto');
|
|
34
|
-
const { VERBS } = require('../../bin/bongos.js'); // side-effect-free require (guarded main)
|
|
35
|
-
const ic = require('../../src/instance-config'); // neutral configDir/envPrefix fallbacks (never a founder literal)
|
|
36
|
-
const { isCorePackageName, CORE_PACKAGE_NAMES } = require('../../src/module-loader/catalog'); // one definition of "this checkout IS the core"
|
|
37
|
-
const { renderInstanceClaudeMd, refreshStarterCliLines } = require('./claude-md-template'); // task 2104 — the starter CLAUDE.md
|
|
38
|
-
|
|
39
|
-
// script basename (e.g. "ship.js") → dedicated bongos verb, for verbs that map to a bare script with
|
|
40
|
-
// NO prefixArgs. Verbs whose script is driven by prefixArgs (box → api.js) are EXCLUDED so a generic
|
|
41
|
-
// `node scripts/gds/dev.js …` never mis-maps to `bongos serve`; those fall to `bongos exec`. `exec`
|
|
42
|
-
// itself has no script and is skipped.
|
|
43
|
-
function scriptToVerb(verbs = VERBS) {
|
|
44
|
-
const m = {};
|
|
45
|
-
for (const [verb, def] of Object.entries(verbs)) {
|
|
46
|
-
if (!def || def.prefixArgs || !def.script) continue;
|
|
47
|
-
if (!(def.script in m)) m[def.script] = verb;
|
|
48
|
-
}
|
|
49
|
-
return m;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Match `node [<quote>][$CLAUDE_PROJECT_DIR/|./]scripts/gds/<name>.js[<quote>]` — the invocation form
|
|
53
|
-
// skills + settings.json hooks use. The optional $CLAUDE_PROJECT_DIR/ or ./ prefix and surrounding
|
|
54
|
-
// quote are consumed so the whole thing collapses to the bongos form. `.claude/hooks/<x>.js` refs are
|
|
55
|
-
// deliberately NOT matched (this targets scripts/gds/) — those stay instance-local after materialize.
|
|
56
|
-
// The launcher is bare `node`, OR the hook resolver `sh "$CLAUDE_PROJECT_DIR/.claude/hooks/run-node.sh"`
|
|
57
|
-
// that every settings.json hook command goes through since task 1003548 (it finds node when the hook
|
|
58
|
-
// shell's PATH lacks it). Both collapse to the same bongos form; a resolver call whose target is a
|
|
59
|
-
// .claude/hooks/*.js stays untouched exactly like the bare-node form did.
|
|
60
|
-
const LAUNCHER = String.raw`(?:node|sh\s+"?(?:\$CLAUDE_PROJECT_DIR\/|\.\/)?\.claude\/hooks\/run-node\.sh"?)`;
|
|
61
|
-
const GDS_INVOCATION_RE = new RegExp(LAUNCHER + String.raw`\s+"?(?:\$CLAUDE_PROJECT_DIR\/|\.\/)?scripts\/gds\/([a-zA-Z0-9_-]+)\.js"?`, 'g');
|
|
62
|
-
// A non-gds core script under scripts/ (rare in skills, but keep the transform total).
|
|
63
|
-
const OTHER_SCRIPT_RE = new RegExp(LAUNCHER + String.raw`\s+"?(?:\$CLAUDE_PROJECT_DIR\/|\.\/)?scripts\/((?!gds\/)[a-zA-Z0-9_./-]+\.js)"?`, 'g');
|
|
64
|
-
|
|
65
|
-
// How a project runs the CLI (task 1004621). The `bongos` bin ships inside the @bongos/core
|
|
66
|
-
// dependency (node_modules/.bin/bongos), which is NOT on PATH, so a bare `bongos ship` written
|
|
67
|
-
// into a project's skills failed with `command not found` on every session's first call and the
|
|
68
|
-
// assistant had to recover by retrying through npx. `npx` finds the project's own bin right after
|
|
69
|
-
// `npm install`, with no setup, on every OS and shell — so that is the spelling a project reads.
|
|
70
|
-
const PROJECT_CLI = 'npx bongos';
|
|
71
|
-
|
|
72
|
-
// A hand-written bare `bongos <verb>` in skill prose (e.g. "`bongos paste-token <token>`"), so it
|
|
73
|
-
// takes the npx spelling too. Case-sensitive on purpose ("Bongos status" is a product noun), only a
|
|
74
|
-
// KNOWN verb, and never when already prefixed by `npx ` or glued to a path/name (`@bongos/core`,
|
|
75
|
-
// `bongos-feedback`, `bongos: command not found` all stay). The `npx ` lookbehind is what keeps a
|
|
76
|
-
// second run from writing `npx npx bongos`.
|
|
77
|
-
function bareVerbRe(verbs) {
|
|
78
|
-
const names = Object.keys(verbs || {}).filter((v) => /^[a-z][a-z-]*$/.test(v));
|
|
79
|
-
if (!names.length) return null;
|
|
80
|
-
names.sort((a, b) => b.length - a.length); // `paste-token` before a shorter prefix of it
|
|
81
|
-
return new RegExp(String.raw`(?<![\w@/.\-])(?<!npx )bongos (${names.join('|')})(?![\w-])`, 'g');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Pure: rewrite core-script invocations in a skill/settings command string to the project's CLI
|
|
85
|
-
// spelling (`npx bongos <verb>`, else `npx bongos exec scripts/gds/<x>.js`), and give any bare
|
|
86
|
-
// `bongos <verb>` the same npx prefix. Idempotent: its own output contains neither a
|
|
87
|
-
// `node scripts/…` invocation nor an un-prefixed `bongos <verb>`, so a second run changes nothing.
|
|
88
|
-
function bongosify(text, verbs = VERBS) {
|
|
89
|
-
const map = scriptToVerb(verbs);
|
|
90
|
-
const bare = bareVerbRe(verbs);
|
|
91
|
-
let out = String(text == null ? '' : text);
|
|
92
|
-
if (bare) out = out.replace(bare, (_whole, verb) => `${PROJECT_CLI} ${verb}`);
|
|
93
|
-
return out
|
|
94
|
-
.replace(GDS_INVOCATION_RE, (_whole, script) => {
|
|
95
|
-
const verb = map[`${script}.js`];
|
|
96
|
-
return verb ? `${PROJECT_CLI} ${verb}` : `${PROJECT_CLI} exec scripts/gds/${script}.js`;
|
|
97
|
-
})
|
|
98
|
-
.replace(OTHER_SCRIPT_RE, (_whole, rel) => `${PROJECT_CLI} exec scripts/${rel}`);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// ---- instance rebrand (task 2103) -----------------------------------------
|
|
102
|
-
// The scaffolded .claude/ used to carry the SOURCE instance's identity verbatim:
|
|
103
|
-
// hooks hardcoded the founder origin (e.g. a `https://example.com` fallback)
|
|
104
|
-
// and config dir (`~/.config/otb`), so a fresh clone's hooks phoned home to the
|
|
105
|
-
// WRONG instance — the 2026-07-08 demo-session failure. materialize now rewrites
|
|
106
|
-
// those founder literals to the TARGET instance's own values, derived from the two
|
|
107
|
-
// branding objects, so no source host survives. Focused + FULL-HOST (a subdomain
|
|
108
|
-
// like demo.cloudbongos.com is preserved), fail-open (a missing field drops that
|
|
109
|
-
// one rule), a no-op when source == target, and it touches ONLY the copied output
|
|
110
|
-
// (never the running source hooks). It does NOT rewrite hooks' internal
|
|
111
|
-
// require('scripts/gds/…') paths — those self-resolve at runtime via the copied
|
|
112
|
-
// _core-resolve.js sibling (task 2139); this rule lands the origin/config-dir neutralization.
|
|
113
|
-
|
|
114
|
-
function reEsc(s) { return String(s).replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }
|
|
115
|
-
function hostOf(origin) { try { return new URL(String(origin)).host || null; } catch { return null; } }
|
|
116
|
-
|
|
117
|
-
// Effective config dir / env prefix for a branding — the SAME neutral fallbacks
|
|
118
|
-
// instance-config uses, so nothing here is ever a founder literal (R76-safe).
|
|
119
|
-
function effConfigDir(b) { return (b && b.configDir) || ic.FALLBACK_DIR; }
|
|
120
|
-
function effEnvPrefix(b) { return (b && b.envPrefix) || ic.FALLBACK_ENV_PREFIX; }
|
|
121
|
-
// The brand token outbound User-Agents are built from, mirroring src/branding.js
|
|
122
|
-
// userAgent(): repo name, else env prefix, lowercased. Kept in sync by the
|
|
123
|
-
// tests/claude_materialize.mjs UA-rule case + tests/hook_user_agents.mjs.
|
|
124
|
-
function effUaBase(b) {
|
|
125
|
-
const base = (b && b.repo && b.repo.name) || (b && b.envPrefix) || '';
|
|
126
|
-
return String(base).toLowerCase();
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Ordered source→target rebrand rules from two branding objects. PURE + exported.
|
|
130
|
-
function buildRebrandRules(from = {}, to = {}) {
|
|
131
|
-
const rules = [];
|
|
132
|
-
const add = (a, b) => { if (a && b && a !== b) rules.push({ pattern: new RegExp(reEsc(a), 'g'), replace: b }); };
|
|
133
|
-
// Every configured origin HOST (public/builders/status/oauth) → the target's SAME-key
|
|
134
|
-
// host, or its publicOrigin host when that key is unset (so a source subdomain like
|
|
135
|
-
// builders.<founder> maps to the target's canonical origin, not builders.<target>).
|
|
136
|
-
// Full-host keeps real target subdomains; a bare founder host anywhere is caught too.
|
|
137
|
-
// Dedup by source host (first mapping wins) so one founder host can't spawn conflicting rules.
|
|
138
|
-
const fromD = from.domains || {}, toD = to.domains || {};
|
|
139
|
-
const toPublicHost = hostOf(toD.publicOrigin);
|
|
140
|
-
const hostMap = new Map();
|
|
141
|
-
for (const key of Object.keys(fromD)) {
|
|
142
|
-
const fh = hostOf(fromD[key]);
|
|
143
|
-
if (!fh || hostMap.has(fh)) continue;
|
|
144
|
-
const th = hostOf(toD[key]) || toPublicHost;
|
|
145
|
-
if (th) hostMap.set(fh, th);
|
|
146
|
-
}
|
|
147
|
-
for (const [fh, th] of hostMap) add(fh, th);
|
|
148
|
-
// Config dir in the shapes hooks reference it (~/.config/<dir>, /etc/<dir>, the [<dir>] log tag).
|
|
149
|
-
const fc = effConfigDir(from), tc = effConfigDir(to);
|
|
150
|
-
add(`.config/${fc}`, `.config/${tc}`);
|
|
151
|
-
add(`/etc/${fc}`, `/etc/${tc}`);
|
|
152
|
-
add(`[${fc}]`, `[${tc}]`);
|
|
153
|
-
// The instance env-var prefix (e.g. OTB_ → BONGOS_), bounded by its underscore.
|
|
154
|
-
add(`${effEnvPrefix(from)}_`, `${effEnvPrefix(to)}_`);
|
|
155
|
-
// task 1002672: the bare User-Agent brand token (e.g. `example-gds-cli/1.0`
|
|
156
|
-
// in a hook's outbound fetch). It carries no TLD, so none of the HOST rules above
|
|
157
|
-
// ever matched it and a founder-branded UA leaked into every materialized
|
|
158
|
-
// instance verbatim. Bounded by the `-gds` suffix (the userAgent() convention)
|
|
159
|
-
// so a bare founder word in prose is NOT rewritten — only the UA token shape.
|
|
160
|
-
// Both bases must resolve: an empty side would degenerate into a bare `-gds`
|
|
161
|
-
// rule that rewrites every occurrence of the suffix itself.
|
|
162
|
-
const fromUa = effUaBase(from), toUa = effUaBase(to);
|
|
163
|
-
if (fromUa && toUa) add(`${fromUa}-gds`, `${toUa}-gds`);
|
|
164
|
-
// Longest literal first so a full host is replaced before any bare token inside it.
|
|
165
|
-
rules.sort((x, y) => y.pattern.source.length - x.pattern.source.length);
|
|
166
|
-
return rules;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function rebrandText(text, rules) {
|
|
170
|
-
if (typeof text !== 'string' || !text || !rules || !rules.length) return text;
|
|
171
|
-
let out = text;
|
|
172
|
-
for (const r of rules) out = out.replace(r.pattern, r.replace);
|
|
173
|
-
return out;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function readJsonSafe(p) { try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return null; } }
|
|
177
|
-
|
|
178
|
-
// Every module that declares `contributes.skills`, with whether the TARGET instance
|
|
179
|
-
// enables it: the target's config/modules.json wins, else the module's own `default`.
|
|
180
|
-
// The one place that rule lives — disabledModuleSkills and moduleSkillSources both
|
|
181
|
-
// read it. PURE-ish (reads the fs) + exported.
|
|
182
|
-
function moduleSkillRoster({ coreRoot, instanceDir }) {
|
|
183
|
-
const roster = [];
|
|
184
|
-
const modulesDir = path.join(coreRoot, 'modules');
|
|
185
|
-
if (!fs.existsSync(modulesDir)) return roster;
|
|
186
|
-
const targetCfg = readJsonSafe(path.join(instanceDir, 'config', 'modules.json')) || {};
|
|
187
|
-
const enabledMap = (targetCfg.modules && typeof targetCfg.modules === 'object') ? targetCfg.modules : {};
|
|
188
|
-
for (const dir of fs.readdirSync(modulesDir)) {
|
|
189
|
-
const mj = readJsonSafe(path.join(modulesDir, dir, 'module.json'));
|
|
190
|
-
const skills = mj && mj.contributes && mj.contributes.skills;
|
|
191
|
-
if (!Array.isArray(skills)) continue;
|
|
192
|
-
const key = mj.key || dir;
|
|
193
|
-
const explicit = enabledMap[key];
|
|
194
|
-
const enabled = explicit === undefined ? mj.default === true : explicit === true;
|
|
195
|
-
roster.push({ key, dir: path.join(modulesDir, dir), enabled, skills });
|
|
196
|
-
}
|
|
197
|
-
return roster;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Skills owned by a module that is DISABLED in the TARGET instance (task 2103b).
|
|
201
|
-
// A skill owned by NO module is core and is never skipped.
|
|
202
|
-
function disabledModuleSkills(opts) {
|
|
203
|
-
const skip = new Set();
|
|
204
|
-
for (const m of moduleSkillRoster(opts)) if (!m.enabled) for (const s of m.skills) skip.add(s);
|
|
205
|
-
return skip;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// A declared skill name is a path segment the materialiser WRITES under
|
|
209
|
-
// .claude/skills/, so it is allowlisted before it ever reaches path.join: lowercase
|
|
210
|
-
// slug only, no dots, no separators. A manifest carrying "../x" names nothing.
|
|
211
|
-
const SKILL_NAME_RE = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
212
|
-
|
|
213
|
-
// The vendoring gate a THIRD-PARTY skill must pass at copy time, not only in CI
|
|
214
|
-
// (ADR 0198 §1–3): a PROVENANCE.md sidecar whose frontmatter names a licence on the
|
|
215
|
-
// allowlist and a scan verdict that may land. The module's own skills/policy.json
|
|
216
|
-
// (the ui-design shape) is the source of both lists when present; these defaults
|
|
217
|
-
// are the same five licences and two verdicts otherwise. A gate that cannot read
|
|
218
|
-
// the sidecar refuses — an unvetted copy never lands because a file was missing.
|
|
219
|
-
const VENDOR_DEFAULT_POLICY = Object.freeze({
|
|
220
|
-
licenceAllowlist: ['Apache-2.0', 'MIT', 'BSD-2-Clause', 'BSD-3-Clause', 'CC-BY-4.0'],
|
|
221
|
-
verdictsThatMayLand: ['clean', 'caution'],
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
function sidecarFrontmatter(file) {
|
|
225
|
-
let text;
|
|
226
|
-
try { text = fs.readFileSync(file, 'utf8').replace(/\r\n/g, '\n'); } catch { return null; }
|
|
227
|
-
const m = text.match(/^---\n([\s\S]*?)\n---\n/);
|
|
228
|
-
if (!m) return null;
|
|
229
|
-
const out = {};
|
|
230
|
-
for (const line of m[1].split('\n')) {
|
|
231
|
-
const kv = line.match(/^([A-Za-z][A-Za-z0-9_-]*):\s*(.*)$/);
|
|
232
|
-
if (kv) out[kv[1]] = kv[2].replace(/^["']|["']$/g, '').trim();
|
|
233
|
-
}
|
|
234
|
-
return out;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// → { ok: true } or { ok: false, reason } for one vendored skill dir. Exported for the test.
|
|
238
|
-
function vendoredSkillGate(dir, policy = VENDOR_DEFAULT_POLICY) {
|
|
239
|
-
const fm = sidecarFrontmatter(path.join(dir, 'PROVENANCE.md'));
|
|
240
|
-
if (!fm) return { ok: false, reason: 'no PROVENANCE.md sidecar (or no frontmatter)' };
|
|
241
|
-
const licences = Array.isArray(policy.licenceAllowlist) ? policy.licenceAllowlist : VENDOR_DEFAULT_POLICY.licenceAllowlist;
|
|
242
|
-
const verdicts = Array.isArray(policy.verdictsThatMayLand) ? policy.verdictsThatMayLand : VENDOR_DEFAULT_POLICY.verdictsThatMayLand;
|
|
243
|
-
if (!licences.includes(fm.licence)) return { ok: false, reason: `licence "${fm.licence || ''}" is not on the allowlist` };
|
|
244
|
-
if (!verdicts.includes(fm.scanVerdict)) return { ok: false, reason: `scan verdict "${fm.scanVerdict || ''}" may not land` };
|
|
245
|
-
return { ok: true };
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// Skills a module ships from its OWN tree instead of .claude/skills/ (task 1003321,
|
|
249
|
-
// ADR 0198): modules/<key>/skills/<name>/ for a skill the module authors, or
|
|
250
|
-
// modules/<key>/skills/vendor/<name>/ for a third-party skill carried with its
|
|
251
|
-
// PROVENANCE.md sidecar (the `vendor/` segment is the one fitness-ratchets exempts
|
|
252
|
-
// from the first-party line budgets). Only a name the module DECLARES in
|
|
253
|
-
// contributes.skills resolves — the manifest stays the single declaration — a name
|
|
254
|
-
// that fails SKILL_NAME_RE is refused before any path is built, a dir with no
|
|
255
|
-
// SKILL.md is not a skill, and a vendored dir must pass vendoredSkillGate. Refusals
|
|
256
|
-
// come back in `refused[]` so the caller can log them. Accepts a precomputed
|
|
257
|
-
// `roster` so materializeClaude walks modules/ once. PURE-ish (reads the fs) + exported.
|
|
258
|
-
function moduleSkillSources(opts) {
|
|
259
|
-
const out = [];
|
|
260
|
-
const refused = [];
|
|
261
|
-
const roster = (opts && opts.roster) || moduleSkillRoster(opts);
|
|
262
|
-
for (const m of roster) {
|
|
263
|
-
const policy = readJsonSafe(path.join(m.dir, 'skills', 'policy.json')) || VENDOR_DEFAULT_POLICY;
|
|
264
|
-
for (const name of m.skills) {
|
|
265
|
-
if (typeof name !== 'string' || !SKILL_NAME_RE.test(name)) { refused.push({ name: String(name), module: m.key, reason: 'name is not a lowercase slug' }); continue; }
|
|
266
|
-
const own = path.join(m.dir, 'skills', name);
|
|
267
|
-
const vendored = path.join(m.dir, 'skills', 'vendor', name);
|
|
268
|
-
const src = [own, vendored].find((p) => fs.existsSync(path.join(p, 'SKILL.md')));
|
|
269
|
-
if (!src) continue;
|
|
270
|
-
if (src === vendored) {
|
|
271
|
-
const gate = vendoredSkillGate(src, policy);
|
|
272
|
-
if (!gate.ok) { refused.push({ name, module: m.key, reason: gate.reason }); continue; }
|
|
273
|
-
}
|
|
274
|
-
out.push({ name, module: m.key, dir: src, enabled: m.enabled, vendored: src === vendored });
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
out.refused = refused;
|
|
278
|
-
return out;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// ---- retired core skills: the tombstone list (task 1004482) -----------------
|
|
282
|
-
// A skill the core USED to ship from its own .claude/skills/ and no longer does (the dev-box
|
|
283
|
-
// verbs, the old /dev /ideate /paint role playbooks, the pixel-art skills that moved into a
|
|
284
|
-
// default-off module). Every instance materialized before task 1004482 received them as core
|
|
285
|
-
// skills, and the provenance manifest then recorded only module-declared names — so step 1c
|
|
286
|
-
// could never prove it had put them there and they stayed in .claude/skills/ for the harness to
|
|
287
|
-
// load and the hall's Commands page to list, forever.
|
|
288
|
-
//
|
|
289
|
-
// From task 1004482 on the manifest records EVERY skill a materialize lands, so a skill the core
|
|
290
|
-
// drops later is withdrawn by step 1c's ordinary rule. This list closes the historical gap only,
|
|
291
|
-
// and is therefore a closed set: it should not need a new entry.
|
|
292
|
-
//
|
|
293
|
-
// "Never touch a skill the instance authored" is held by a fingerprint, not by the name: each
|
|
294
|
-
// entry lists sha256 digests (first 16 hex) of every description the core ever shipped under that
|
|
295
|
-
// name, as written and as bongosify() rewrote it. A dir whose SKILL.md description matches none of
|
|
296
|
-
// them is not ours and is left in place with a note — an owner who wrote their own /dev keeps it.
|
|
297
|
-
const RETIRED_CORE_SKILLS_FILE = path.join(__dirname, 'retired-core-skills.json');
|
|
298
|
-
|
|
299
|
-
// The `description:` value of a SKILL.md's frontmatter, whitespace-collapsed — a plain scalar,
|
|
300
|
-
// a quoted one, or a block scalar (`>` / `|`) with its indented continuation lines. null when
|
|
301
|
-
// the file has no frontmatter or no description. PURE + exported.
|
|
302
|
-
function skillDescription(text) {
|
|
303
|
-
const m = String(text == null ? '' : text).replace(/\r\n/g, '\n').match(/^---\n([\s\S]*?)\n---(?:\n|$)/);
|
|
304
|
-
if (!m) return null;
|
|
305
|
-
const lines = m[1].split('\n');
|
|
306
|
-
const i = lines.findIndex((l) => /^description:/.test(l));
|
|
307
|
-
if (i < 0) return null;
|
|
308
|
-
const parts = [lines[i].replace(/^description:\s*/, '')];
|
|
309
|
-
if (/^[>|][+-]?$/.test(parts[0])) parts[0] = '';
|
|
310
|
-
for (let j = i + 1; j < lines.length && /^\s+\S/.test(lines[j]); j += 1) parts.push(lines[j]);
|
|
311
|
-
const value = parts.join(' ').replace(/\s+/g, ' ').trim().replace(/^(["'])([\s\S]*)\1$/, '$2').trim();
|
|
312
|
-
return value || null;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
function descriptionDigest(desc) {
|
|
316
|
-
return crypto.createHash('sha256').update(String(desc)).digest('hex').slice(0, 16);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// Does this instance skill dir carry a description the core shipped under `name`? Reads the
|
|
320
|
-
// tombstone's digests; an unreadable SKILL.md or a missing description answers "no" (keep it).
|
|
321
|
-
function isRetiredCoreCopy(dir, digests) {
|
|
322
|
-
if (!Array.isArray(digests) || !digests.length) return false;
|
|
323
|
-
let text;
|
|
324
|
-
try { text = fs.readFileSync(path.join(dir, 'SKILL.md'), 'utf8'); } catch { return false; }
|
|
325
|
-
const desc = skillDescription(text);
|
|
326
|
-
return desc != null && digests.includes(descriptionDigest(desc));
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
function readRetiredCoreSkills(file = RETIRED_CORE_SKILLS_FILE) {
|
|
330
|
-
const j = readJsonSafe(file);
|
|
331
|
-
return j && j.skills && typeof j.skills === 'object' ? j.skills : {};
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// ---- I/O: copy a tree, transforming text files through bongosify ----------
|
|
335
|
-
|
|
336
|
-
const TEXT_EXT = new Set(['.md', '.txt', '.sh']); // command-bearing text we rewrite (skills are SKILL.md)
|
|
337
|
-
|
|
338
|
-
// Every file under `dir`, as paths relative to it. Used to name a withdrawn skill dir's
|
|
339
|
-
// files before it is removed — a deletion git reports one file at a time, never the dir.
|
|
340
|
-
function listFilesRecursive(dir, base = '') {
|
|
341
|
-
const out = [];
|
|
342
|
-
let entries;
|
|
343
|
-
try { entries = fs.readdirSync(path.join(dir, base), { withFileTypes: true }); } catch { return out; }
|
|
344
|
-
for (const e of entries) {
|
|
345
|
-
const rel = path.join(base, e.name);
|
|
346
|
-
if (e.isDirectory()) out.push(...listFilesRecursive(dir, rel));
|
|
347
|
-
else out.push(rel);
|
|
348
|
-
}
|
|
349
|
-
return out;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// `overwrite` defaults true (greenfield init / upgrade — byte-identical to before).
|
|
353
|
-
// `overwrite: false` is the `bongos init --adopt` layering path (ADR 0121): a file
|
|
354
|
-
// that already exists at the destination is NEVER clobbered — it is skipped and
|
|
355
|
-
// recorded in the returned `skipped[]` so the caller can report it.
|
|
356
|
-
// `transform` (text→text) is applied to any file whose extension is in `textExt`
|
|
357
|
-
// (default: bongosify over .md/.txt/.sh — the historical skills behavior). `skip(rel)`
|
|
358
|
-
// excludes a whole subtree BEFORE it is walked (task 2103b — drop a disabled module's
|
|
359
|
-
// skill dir); excluded top-level entries are returned in `excluded[]`.
|
|
360
|
-
function copyTreeTransformed(srcDir, destDir, { dryRun, onFile, overwrite = true, transform = bongosify, textExt = TEXT_EXT, skip } = {}) {
|
|
361
|
-
let files = 0;
|
|
362
|
-
const skipped = [];
|
|
363
|
-
const excluded = [];
|
|
364
|
-
const walk = (rel) => {
|
|
365
|
-
if (skip && skip(rel)) { excluded.push(rel); return; }
|
|
366
|
-
const absSrc = path.join(srcDir, rel);
|
|
367
|
-
const st = fs.statSync(absSrc);
|
|
368
|
-
if (st.isDirectory()) {
|
|
369
|
-
for (const name of fs.readdirSync(absSrc)) walk(path.join(rel, name));
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
const absDest = path.join(destDir, rel);
|
|
373
|
-
if (!overwrite && fs.existsSync(absDest)) { // adopt: leave-and-report, never clobber
|
|
374
|
-
skipped.push(rel);
|
|
375
|
-
if (onFile) onFile(rel, { skipped: true });
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
378
|
-
files += 1;
|
|
379
|
-
if (dryRun) { if (onFile) onFile(rel); return; }
|
|
380
|
-
fs.mkdirSync(path.dirname(absDest), { recursive: true });
|
|
381
|
-
if (textExt.has(path.extname(rel))) {
|
|
382
|
-
fs.writeFileSync(absDest, transform(fs.readFileSync(absSrc, 'utf8')));
|
|
383
|
-
} else {
|
|
384
|
-
fs.copyFileSync(absSrc, absDest); // binary / other — verbatim
|
|
385
|
-
}
|
|
386
|
-
if (onFile) onFile(rel);
|
|
387
|
-
};
|
|
388
|
-
if (!fs.existsSync(srcDir)) return { files: 0, skipped, excluded, present: false };
|
|
389
|
-
for (const name of fs.readdirSync(srcDir)) walk(name);
|
|
390
|
-
return { files, skipped, excluded, present: true };
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// Transform settings.json: parse, rewrite every hook command through bongosify, re-serialize. Keeps
|
|
394
|
-
// .claude/hooks/*.js commands (instance-local) untouched and rewrites the scripts/gds/*.js ones.
|
|
395
|
-
// The blessed commands an instance builder runs to do the methodology, one rule
|
|
396
|
-
// each (task 1003962). This MIRRORS the core repo's own `.claude/settings.json`
|
|
397
|
-
// allow-list (ADR 0104 / task 1051), translated from `node scripts/gds/<x>.js`
|
|
398
|
-
// into the verb form a materialized instance actually invokes — bongosify()
|
|
399
|
-
// rewrites every skill to `bongos <verb>`, so a path-shaped rule would match
|
|
400
|
-
// nothing there.
|
|
401
|
-
//
|
|
402
|
-
// THE GAP THIS CLOSES. `.claude/settings.json` is excluded from the published
|
|
403
|
-
// package on purpose (PROTECTED_TOPOLOGY_EXCLUDE, beside infra/ and .github/):
|
|
404
|
-
// the core's own copy is deploy and gate machinery that means nothing on an
|
|
405
|
-
// instance. But the skills ship, so an instance received the methodology and
|
|
406
|
-
// none of the permissions that let it run — every instance builder met the
|
|
407
|
-
// auto-mode classifier on the normal workflow, which is how a live builder came
|
|
408
|
-
// to be stuck mid-re-auth with no way forward.
|
|
409
|
-
//
|
|
410
|
-
// WHY THIS IS NOT AN AUTHORITY GRANT (ADR 0016). An allow-rule stops the local
|
|
411
|
-
// agent REFUSING to run a command; it changes nothing about what the server
|
|
412
|
-
// permits. Rank is read fresh from the database on every request by
|
|
413
|
-
// `requireRank`, so a builder who edits this file grants themselves exactly
|
|
414
|
-
// nothing. That is the distinction that makes shipping a list of command names
|
|
415
|
-
// safe where shipping hooks — actual local gate machinery — is not.
|
|
416
|
-
//
|
|
417
|
-
// DELIBERATELY ABSENT: `bongos exec`. It runs any script inside the core by
|
|
418
|
-
// path and is the agent's escape hatch, so allow-listing it would be a blanket
|
|
419
|
-
// grant wearing a narrow rule's clothes. The one script the core's own list
|
|
420
|
-
// blesses (`api.js`) is named in full instead.
|
|
421
|
-
//
|
|
422
|
-
// EVERY RULE IS THE `npx bongos` SPELLING (task 1004621): a project has no bare
|
|
423
|
-
// `bongos` on PATH, so its skills, its CLAUDE.md and Settings → CLI access
|
|
424
|
-
// (task 1004575) all say `npx bongos …`, and a bare-`bongos` rule would allow a
|
|
425
|
-
// command nothing runs. An instance that took the older bare starter gains the
|
|
426
|
-
// npx twin of each bare rule it still holds on its next upgrade
|
|
427
|
-
// (topUpNpxAllowTwins below).
|
|
428
|
-
const STARTER_COMMANDS = [
|
|
429
|
-
'npx bongos claim:*',
|
|
430
|
-
'npx bongos ship:*',
|
|
431
|
-
'npx bongos release:*',
|
|
432
|
-
'npx bongos reauth:*',
|
|
433
|
-
'npx bongos paste-token:*',
|
|
434
|
-
'npx bongos exec scripts/gds/api.js:*',
|
|
435
|
-
// The read-only subset (task 1003992, ADR 0304). `git branch` and `git fetch`
|
|
436
|
-
// are exact forms on purpose: a flag turns either into a write or an exec. No
|
|
437
|
-
// `git diff|log|show` rule, also on purpose: the harness already runs their
|
|
438
|
-
// read-only forms unprompted, and a prefix rule would switch off its flag check
|
|
439
|
-
// (`--output=<file>` writes anywhere, `diff --no-index` reads any file).
|
|
440
|
-
// tests/cli_allowlist_permissions.mjs pins this list to the core's, rule for rule.
|
|
441
|
-
'npx bongos start:*',
|
|
442
|
-
'npx bongos status:*',
|
|
443
|
-
// Exact form, no `:*`: reading the ship mode is how the agent knows whether to ship on its own
|
|
444
|
-
// (task 1004631, ADR 0369). `ship-mode auto|manual` WRITES it, and stays a prompt.
|
|
445
|
-
'npx bongos ship-mode',
|
|
446
|
-
'npx bongos recall:*',
|
|
447
|
-
'npx bongos exec scripts/gds/me.js:*',
|
|
448
|
-
'npx bongos doctor:*',
|
|
449
|
-
'npx bongos exec scripts/gds/preflight.js:*',
|
|
450
|
-
'npx bongos exec scripts/gds/skill-preflight.js:*',
|
|
451
|
-
'npx bongos exec scripts/gds/ship-check.js:*',
|
|
452
|
-
'npx bongos exec scripts/gds/fitness.js:*',
|
|
453
|
-
'npx bongos exec scripts/gds/strand-watch.js:*',
|
|
454
|
-
'npx bongos exec scripts/gds/stale-worktrees.js:*',
|
|
455
|
-
'npx bongos exec scripts/gds/read-session-export.js:*',
|
|
456
|
-
'git status:*',
|
|
457
|
-
'git branch --list',
|
|
458
|
-
'git branch --show-current',
|
|
459
|
-
'git branch -a',
|
|
460
|
-
'git branch -vv',
|
|
461
|
-
'git fetch',
|
|
462
|
-
'git fetch origin',
|
|
463
|
-
'git fetch origin main',
|
|
464
|
-
'gh pr view:*',
|
|
465
|
-
'gh pr checks:*',
|
|
466
|
-
'gh pr list:*',
|
|
467
|
-
'gh run view:*',
|
|
468
|
-
'gh run list:*',
|
|
469
|
-
];
|
|
470
|
-
// One rule per command PER SHELL TOOL (task 1004014): the shell tool is `PowerShell` on a Windows
|
|
471
|
-
// laptop, and a `Bash(...)` rule says nothing about its commands. The tools are the ones the guards
|
|
472
|
-
// see (`.claude/hooks/shell-tools.js`) — held equal by tests/cli_allowlist_permissions.mjs, not a require.
|
|
473
|
-
const STARTER_SHELL_TOOLS = ['Bash', 'PowerShell'];
|
|
474
|
-
const STARTER_ALLOW = STARTER_SHELL_TOOLS.flatMap((tool) => STARTER_COMMANDS.map((command) => `${tool}(${command})`));
|
|
475
|
-
|
|
476
|
-
// The deny half (task 1003966): what the local agent may not READ. Keys are the
|
|
477
|
-
// same exposure on every instance, so those rules ship verbatim.
|
|
478
|
-
const STARTER_DENY_SECRETS = [
|
|
479
|
-
'Read(.env)', 'Read(**/.env)', 'Read(.env.local)', 'Read(**/.env.local)',
|
|
480
|
-
'Read(.env.*.local)', 'Read(**/.env.*.local)',
|
|
481
|
-
'Read(**/*.pem)', 'Read(**/id_rsa*)', 'Read(**/id_ed25519*)',
|
|
482
|
-
];
|
|
483
|
-
const SESSION_STORE_DENY = `Read(~/.config/${ic.FALLBACK_DIR}/instances/**)`;
|
|
484
|
-
|
|
485
|
-
// A checkout's settings.json takes the identity rebrand like every copied file, and the store's
|
|
486
|
-
// dir is one of the core's `.config/<dir>` literals it rewrites. The store does not move with the
|
|
487
|
-
// brand (task 1003741), so its rule is put back where the CLI reads it (task 1004155).
|
|
488
|
-
function rebrandSettings(text, rebrand) {
|
|
489
|
-
const moved = rebrand(SESSION_STORE_DENY);
|
|
490
|
-
return rebrand(text).split(JSON.stringify(moved)).join(JSON.stringify(SESSION_STORE_DENY));
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
// Credential files are derived from where the CLI actually reads them, not rebranded from the
|
|
494
|
-
// core's literals: the rebrand would also move the host-keyed store, which sits at a fixed anchor
|
|
495
|
-
// whatever the brand (cli-lib sessionStoreDir, task 1003741).
|
|
496
|
-
//
|
|
497
|
-
// credentialDeny is the half that may be added to a settings.json the instance already owns.
|
|
498
|
-
// Every rule here stops the agent READING A SECRET, and nothing an instance legitimately does
|
|
499
|
-
// requires reading its own key or session token from inside an agent session — which is what
|
|
500
|
-
// makes appending one provably safe (ADR 0326: a deny rule is monotonic in the safe direction).
|
|
501
|
-
function credentialDeny(branding = {}) {
|
|
502
|
-
const dirs = [...new Set([effConfigDir(branding), ...ic.LEGACY_DIRS])];
|
|
503
|
-
const credentialFiles = ['env', ...ic.SESSION_FILENAMES];
|
|
504
|
-
return [
|
|
505
|
-
...STARTER_DENY_SECRETS,
|
|
506
|
-
...dirs.flatMap((dir) => credentialFiles.map((file) => `Read(~/.config/${dir}/${file})`)),
|
|
507
|
-
SESSION_STORE_DENY,
|
|
508
|
-
];
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
// starterDeny — what a FRESH instance gets: the credential half plus the shelf rules, which are
|
|
512
|
-
// the only layer an instance has against the repo-global stash stack since the git-guard hook is
|
|
513
|
-
// topology and does not ship.
|
|
514
|
-
//
|
|
515
|
-
// The shelf rules are starter-only, and deliberately NOT in the top-up (task 1004158, amending
|
|
516
|
-
// ADR 0326, which named this exclusion as the remedy if the rule ever bit). They guard a WORKFLOW
|
|
517
|
-
// rather than a secret, so the monotonicity argument that licenses the top-up does not reach them:
|
|
518
|
-
// with no provenance by design, and deny beating allow in Claude Code's permission order, an
|
|
519
|
-
// instance whose builders used the shelf as a set-aside could not re-enable it from its own
|
|
520
|
-
// settings.json afterwards. A fresh instance is different in kind — there the rule is a visible
|
|
521
|
-
// default present from the first commit, editable before any workflow has grown around it.
|
|
522
|
-
function starterDeny(branding = {}) {
|
|
523
|
-
return [
|
|
524
|
-
...credentialDeny(branding),
|
|
525
|
-
...STARTER_SHELL_TOOLS.map((tool) => `${tool}(git stash:*)`),
|
|
526
|
-
];
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
// topUpStarterDeny — the deny rules an instance's OWN settings.json is missing, added to it
|
|
530
|
-
// (task 1004156). The starter is only ever written when the file is ABSENT, so every instance
|
|
531
|
-
// that took the allow-only starter from task 1003962 keeps it forever and its local agent can
|
|
532
|
-
// still read .env files, keys and session tokens. ADDING is the whole safety argument: a deny
|
|
533
|
-
// rule can only ever narrow what the agent may do, so appending one cannot widen this instance's
|
|
534
|
-
// permissions — which is why the owner's call (task 1004156) was "add them, and say which".
|
|
535
|
-
// "Never clobber" is unchanged in the sense that matters: nothing the instance wrote is removed
|
|
536
|
-
// or rewritten. Returns { text, added, reason }; `text` is null when nothing should be written.
|
|
537
|
-
// `reason` is the STRUCTURED signal that the file could not be CHECKED — null means "healthy",
|
|
538
|
-
// so callers branch on its presence rather than on the wording of a message. An unparseable or
|
|
539
|
-
// unexpectedly-shaped file is LEFT ALONE and reported, the posture task 1004023 took for a
|
|
540
|
-
// settings.json that will not parse: a half-understood rewrite of a permissions file is worse
|
|
541
|
-
// than the gap it closes. Note the write re-emits the whole document at 2-space JSON, so an
|
|
542
|
-
// instance indented some other way sees a whole-file diff — the RULES are still append-only,
|
|
543
|
-
// which is what the safety argument rests on, and the run output says so.
|
|
544
|
-
function topUpStarterDeny(existingText, wanted) {
|
|
545
|
-
const isObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
546
|
-
const cannotCheck = (reason) => ({ text: null, added: [], reason });
|
|
547
|
-
let doc;
|
|
548
|
-
try { doc = JSON.parse(existingText); } catch (err) { return cannotCheck(`not valid JSON (${err.message})`); }
|
|
549
|
-
if (!isObject(doc)) return cannotCheck('its top level is not a JSON object');
|
|
550
|
-
const perms = doc.permissions === undefined ? {} : doc.permissions;
|
|
551
|
-
if (!isObject(perms)) return cannotCheck('its "permissions" is not an object');
|
|
552
|
-
const deny = perms.deny === undefined ? [] : perms.deny;
|
|
553
|
-
if (!Array.isArray(deny)) return cannotCheck('its "permissions.deny" is not an array');
|
|
554
|
-
const have = new Set(deny);
|
|
555
|
-
const added = wanted.filter((rule) => !have.has(rule));
|
|
556
|
-
if (!added.length) return { text: null, added: [], reason: null }; // healthy: every rule already there
|
|
557
|
-
const next = { ...doc, permissions: { ...perms, deny: [...deny, ...added] } };
|
|
558
|
-
return { text: `${JSON.stringify(next, null, 2)}\n`, added, reason: null };
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
// topUpNpxAllowTwins — the `npx bongos` twin of every bare-`bongos` allow rule an instance's OWN
|
|
562
|
-
// settings.json holds (task 1004621). The skills an upgrade lands now say `npx bongos ship`, and a
|
|
563
|
-
// `Bash(bongos ship:*)` rule does not match that, so without the twin the upgrade would trade a
|
|
564
|
-
// `command not found` for a permission prompt on every blessed command. This is NOT the shell-rule
|
|
565
|
-
// top-up task 1004158 ruled out: nothing new is offered. Each twin is a rule the owner already
|
|
566
|
-
// holds, respelled for the one launcher that reaches the same project-local bin — a rule they
|
|
567
|
-
// removed gets no twin, and nothing they wrote is removed or rewritten. Same { text, added, reason }
|
|
568
|
-
// contract as topUpStarterDeny; an unreadable shape is left alone and reported.
|
|
569
|
-
const BARE_BONGOS_RULE_RE = /^(\w+)\(bongos (.+)\)$/;
|
|
570
|
-
function topUpNpxAllowTwins(existingText) {
|
|
571
|
-
const isObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
572
|
-
const cannotCheck = (reason) => ({ text: null, added: [], reason });
|
|
573
|
-
let doc;
|
|
574
|
-
try { doc = JSON.parse(existingText); } catch (err) { return cannotCheck(`not valid JSON (${err.message})`); }
|
|
575
|
-
if (!isObject(doc)) return cannotCheck('its top level is not a JSON object');
|
|
576
|
-
const perms = doc.permissions === undefined ? {} : doc.permissions;
|
|
577
|
-
if (!isObject(perms)) return cannotCheck('its "permissions" is not an object');
|
|
578
|
-
const allow = perms.allow === undefined ? [] : perms.allow;
|
|
579
|
-
if (!Array.isArray(allow)) return cannotCheck('its "permissions.allow" is not an array');
|
|
580
|
-
const have = new Set(allow);
|
|
581
|
-
const added = [];
|
|
582
|
-
for (const rule of allow) {
|
|
583
|
-
const m = typeof rule === 'string' && rule.match(BARE_BONGOS_RULE_RE);
|
|
584
|
-
const twin = m && `${m[1]}(${PROJECT_CLI} ${m[2]})`;
|
|
585
|
-
if (twin && !have.has(twin)) { have.add(twin); added.push(twin); }
|
|
586
|
-
}
|
|
587
|
-
if (!added.length) return { text: null, added: [], reason: null };
|
|
588
|
-
const next = { ...doc, permissions: { ...perms, allow: [...allow, ...added] } };
|
|
589
|
-
return { text: `${JSON.stringify(next, null, 2)}\n`, added, reason: null };
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
// The starter an instance gets when the core root carries no settings.json — a
|
|
593
|
-
// package-only install. Permissions ONLY: no hooks (they are topology), no env.
|
|
594
|
-
function renderStarterSettings(branding = {}) {
|
|
595
|
-
return `${JSON.stringify({
|
|
596
|
-
_doc: 'Starter written by scripts/gds/claude-materialize.js (tasks 1003962, 1003966). Permissions only — the blessed Bongos commands, mirroring the core repo\'s own allow-list (ADR 0104), and the deny rules that keep the local agent from reading keys and session tokens. An allow-rule lets the local agent RUN a command; it grants no authority, which the server decides per request from your live rank (ADR 0016). Yours to edit: a later materialize never removes or rewrites a rule you wrote. It will ADD a CREDENTIAL deny rule this starter has gained since (task 1004156) and name it in the run output — additive only, so it can never widen what the local agent may do. Only that half is topped up: the shell rules below guard a workflow rather than a secret, so once this file exists they are yours alone and an upgrade will neither add nor remove one (task 1004158).',
|
|
597
|
-
permissions: { allow: STARTER_ALLOW, deny: starterDeny(branding) },
|
|
598
|
-
}, null, 2)}\n`;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
// readSettingsTransform — the transform, as a result rather than a string:
|
|
602
|
-
// { text, parsed, reason }. transformSettings below is the string face of it,
|
|
603
|
-
// kept because that is what the tests and the historical callers use.
|
|
604
|
-
//
|
|
605
|
-
// WHY A PARSE FAILURE IS COPIED THROUGH UNTOUCHED (task 1004023). The old
|
|
606
|
-
// fallback was `bongosify(raw)` — a best-effort regex rewrite over the whole
|
|
607
|
-
// file. The script-invocation regex ends in an optional quote so it can swallow the
|
|
608
|
-
// closing quote of a QUOTED PATH inside a command; run over raw JSON text it
|
|
609
|
-
// swallows the JSON string's own closing quote instead:
|
|
610
|
-
//
|
|
611
|
-
// bongosify('{"command": "node scripts/gds/strand-watch.js", }')
|
|
612
|
-
// -> {"command": "bongos exec scripts/gds/strand-watch.js, }
|
|
613
|
-
//
|
|
614
|
-
// So a file that was one trailing comma from valid was written to the instance
|
|
615
|
-
// MORE broken than it arrived, with its strings running into each other. A
|
|
616
|
-
// rewrite of text we could not parse is not worth a worse file: the raw bytes
|
|
617
|
-
// are copied through unchanged and the caller is handed a reason to report. The
|
|
618
|
-
// operator fixes one comma instead of unpicking mangled strings.
|
|
619
|
-
//
|
|
620
|
-
// The parse failure is NOT made fatal: the core's own settings.json is valid
|
|
621
|
-
// JSON (pinned by a test), so reaching this means the operator has edited
|
|
622
|
-
// theirs, and refusing the whole materialize over one file would be a worse
|
|
623
|
-
// trade than copying it and saying so.
|
|
624
|
-
function readSettingsTransform(srcPath) {
|
|
625
|
-
const raw = fs.readFileSync(srcPath, 'utf8');
|
|
626
|
-
let json;
|
|
627
|
-
try {
|
|
628
|
-
json = JSON.parse(raw);
|
|
629
|
-
} catch (err) {
|
|
630
|
-
return { text: raw, parsed: false, reason: (err && err.message) || 'not valid JSON' };
|
|
631
|
-
}
|
|
632
|
-
const hooks = json && json.hooks;
|
|
633
|
-
if (hooks && typeof hooks === 'object') {
|
|
634
|
-
for (const event of Object.values(hooks)) {
|
|
635
|
-
for (const matcher of Array.isArray(event) ? event : []) {
|
|
636
|
-
for (const h of (matcher && Array.isArray(matcher.hooks)) ? matcher.hooks : []) {
|
|
637
|
-
if (typeof h.command === 'string') h.command = bongosify(h.command);
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
// Permission rules name the SAME commands the hooks and skills do, so they take the same
|
|
643
|
-
// rewrite — a rule left as `node scripts/gds/ship.js` matches nothing once the instance's
|
|
644
|
-
// skills run `bongos ship` (task 1004012). `allow` gets the one spelling the skills use; a
|
|
645
|
-
// restrictive list gets BOTH ways an instance can reach the script, or it guards only one.
|
|
646
|
-
const perms = json && json.permissions;
|
|
647
|
-
if (perms && typeof perms === 'object') {
|
|
648
|
-
for (const [key, rules] of Object.entries(perms)) {
|
|
649
|
-
if (!Array.isArray(rules)) continue;
|
|
650
|
-
// an empty verb table makes bongosify emit the `bongos exec scripts/gds/<x>.js` spelling
|
|
651
|
-
const spellings =(r) => (key === 'allow' ? [bongosify(r)] : [bongosify(r), bongosify(r, {})]);
|
|
652
|
-
perms[key] = [...new Set(rules.flatMap((r) => (typeof r === 'string' ? spellings(r) : [r])))];
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
return { text: JSON.stringify(json, null, 2) + '\n', parsed: true, reason: null };
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
// transformSettings — the string face of readSettingsTransform. A caller that
|
|
659
|
-
// only wants the bytes keeps working; one that needs to know the file could not
|
|
660
|
-
// be parsed calls readSettingsTransform and reads `parsed`.
|
|
661
|
-
function transformSettings(srcPath) {
|
|
662
|
-
return readSettingsTransform(srcPath).text;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
// Materialize the .claude/ surface from `coreRoot` into `instanceDir`. Returns a summary.
|
|
666
|
-
// `overwrite` defaults true (greenfield init / upgrade — unchanged). `overwrite: false`
|
|
667
|
-
// is the `bongos init --adopt` layering path (ADR 0121): every pre-existing .claude/
|
|
668
|
-
// file is LEFT untouched and recorded in `summary.skippedFiles` (never clobbered). The ONE
|
|
669
|
-
// exception is settings.json in a package-only install, which GAINS any starter deny rule it is
|
|
670
|
-
// missing and reports them in `summary.settingsDenyAdded` (task 1004156) — additive only, so
|
|
671
|
-
// nothing the instance wrote is removed or rewritten.
|
|
672
|
-
const HOOK_TEXT_EXT = new Set(['.js', '.mjs', '.cjs', '.json', '.sh', '.md', '.txt']); // hooks are .js — rebrand them too
|
|
673
|
-
|
|
674
|
-
function materializeClaude({ coreRoot, instanceDir, dryRun = false, overwrite = true, log = () => {} }) {
|
|
675
|
-
const summary = { skipped: false, skills: 0, moduleSkills: 0, settings: false, settingsUnparsed: false, settingsDenyAdded: [], settingsDenyUncheckable: null, hooks: 0, scheduledTasks: 0, skippedFiles: [], excludedSkills: [], withdrawnSkills: [], rebrandRules: 0, claudeMd: false, writtenPaths: [], notes: [] };
|
|
676
|
-
// Every instance-relative path this run WROTE or REMOVED (task 1003957). `bongos upgrade`
|
|
677
|
-
// hands these to persistPin as artifactPaths, exactly as task 1003926 already does for
|
|
678
|
-
// regenerateApiArtifacts' output: committing only the pin left the materialized files dirty,
|
|
679
|
-
// so the NEXT sweep's clean-tree guard called them "a human's work" and skipped the instance
|
|
680
|
-
// FOREVER — an enrolled co-tenant upgraded exactly once (proven on `charter` 2026-09-16).
|
|
681
|
-
//
|
|
682
|
-
// Recording what we wrote is a STRONGER provenance than a static file list: every path here
|
|
683
|
-
// is one this very run produced. It cannot carry an owner's edit either, and not for the
|
|
684
|
-
// "generated end to end" reason API_ARTIFACT_FILES gives — for a sharper one. Under
|
|
685
|
-
// `overwrite` the copy ALREADY replaced whatever the file held before reaching this line, so
|
|
686
|
-
// the only choice left is commit that overwrite or strand the instance; leaving it dirty
|
|
687
|
-
// protects nothing and stops every future update. Under `overwrite: false` (the `init
|
|
688
|
-
// --adopt` path) nothing is clobbered — copyTreeTransformed reports those as `skipped` and
|
|
689
|
-
// addWritten ignores them — so an adopting instance records nothing here and commits nothing.
|
|
690
|
-
const rel = (p) => String(p).split(path.sep).join('/');
|
|
691
|
-
const addWritten = (p) => { summary.writtenPaths.push(rel(p)); };
|
|
692
|
-
// A copyTreeTransformed onFile that records real writes under `base` and ignores the
|
|
693
|
-
// leave-and-report entries adopt mode emits.
|
|
694
|
-
const recordUnder = (base) => (r, info) => { if (!info || !info.skipped) addWritten(path.join(base, r)); };
|
|
695
|
-
if (path.resolve(instanceDir) === path.resolve(coreRoot)) {
|
|
696
|
-
summary.skipped = true;
|
|
697
|
-
summary.notes.push('instance dir is the core root — nothing to materialize (byte-identical no-op).');
|
|
698
|
-
log(' • .claude/ materialize: instance dir == core root — skipped (nothing to copy).');
|
|
699
|
-
return summary;
|
|
700
|
-
}
|
|
701
|
-
const srcClaude = path.join(coreRoot, '.claude');
|
|
702
|
-
const destClaude = path.join(instanceDir, '.claude');
|
|
703
|
-
const left = (n) => (overwrite || n === 0 ? '' : ` (${n} left untouched)`);
|
|
704
|
-
|
|
705
|
-
// Rebrand: rewrite the SOURCE instance's identity (origin host, config dir, env
|
|
706
|
-
// prefix) to the TARGET's, so a copied hook never phones home to the founder's
|
|
707
|
-
// instance (task 2103a). Derived from both config/branding.json files; empty — and
|
|
708
|
-
// thus a no-op — when they match or either is unreadable.
|
|
709
|
-
const fromBranding = readJsonSafe(path.join(coreRoot, 'config', 'branding.json')) || {};
|
|
710
|
-
const toBranding = readJsonSafe(path.join(instanceDir, 'config', 'branding.json')) || {};
|
|
711
|
-
const rebrandRules = buildRebrandRules(fromBranding, toBranding);
|
|
712
|
-
const rebrand = (t) => rebrandText(t, rebrandRules);
|
|
713
|
-
summary.rebrandRules = rebrandRules.length;
|
|
714
|
-
if (rebrandRules.length) log(` • rebranding ${rebrandRules.length} founder literal(s) in the copied .claude/ → this instance's identity.`);
|
|
715
|
-
|
|
716
|
-
// Drop skills owned by a module this instance hasn't enabled (task 2103b). One
|
|
717
|
-
// walk of modules/ serves both this skip and step 1b's module-owned sources.
|
|
718
|
-
const roster = moduleSkillRoster({ coreRoot, instanceDir });
|
|
719
|
-
const skipSkills = new Set();
|
|
720
|
-
for (const m of roster) if (!m.enabled) for (const s of m.skills) skipSkills.add(s);
|
|
721
|
-
// A core checkout that materialised module skills into its own .claude/skills/ (task 1003330)
|
|
722
|
-
// carries them as untracked copies plus two dotfiles; step 1 must not ship those as core
|
|
723
|
-
// skills — step 1b lands them from the module, transformed, like everywhere else.
|
|
724
|
-
const materialisedInCore = readModuleSkillsManifest(path.join(coreRoot, '.claude', 'skills')).skills;
|
|
725
|
-
// The INSTANCE's own provenance record — what a PREVIOUS materialize landed here.
|
|
726
|
-
// Distinct from materialisedInCore above (that one is the core checkout's). Step 1c
|
|
727
|
-
// withdraws from this set and nothing else.
|
|
728
|
-
const landedPreviously = readInstanceSkillsManifest(path.join(destClaude, 'skills')).skills;
|
|
729
|
-
const skillSkip = (rel) => { const top = String(rel).split(/[\\/]/)[0]; return skipSkills.has(top) || top === MODULE_SKILLS_MANIFEST || top === INSTANCE_SKILLS_MANIFEST || top === '.gitignore' || Object.prototype.hasOwnProperty.call(materialisedInCore, top); };
|
|
730
|
-
|
|
731
|
-
// 1. skills — ship in the core package; copy, rewrite invocations→bongos, rebrand
|
|
732
|
-
// identity, and exclude any skill owned by a disabled module.
|
|
733
|
-
const skillsSrc = path.join(srcClaude, 'skills');
|
|
734
|
-
const skillsRes = copyTreeTransformed(skillsSrc, path.join(destClaude, 'skills'), {
|
|
735
|
-
dryRun, overwrite, transform: (t) => rebrand(bongosify(t)), skip: skillSkip,
|
|
736
|
-
onFile: recordUnder('.claude/skills'),
|
|
737
|
-
});
|
|
738
|
-
summary.skills = skillsRes.files;
|
|
739
|
-
summary.excludedSkills = skillsRes.excluded || [];
|
|
740
|
-
for (const rel of skillsRes.skipped || []) summary.skippedFiles.push(`skills/${rel}`);
|
|
741
|
-
if (!skillsRes.present) summary.notes.push('.claude/skills not found at the core root — none materialized.');
|
|
742
|
-
if (summary.excludedSkills.length) log(` • excluded ${summary.excludedSkills.length} skill(s) owned by disabled module(s): ${summary.excludedSkills.join(', ')}`);
|
|
743
|
-
log(` ${dryRun ? '[dry-run] would materialize' : '✓ materialized'} ${skillsRes.files} skill file(s) → .claude/skills/ (invocations→bongos, identity rebranded)${left((skillsRes.skipped || []).length)}`);
|
|
744
|
-
|
|
745
|
-
// 1b. module-owned skills — shipped from modules/<key>/skills/ (own) or
|
|
746
|
-
// modules/<key>/skills/vendor/ (third-party + PROVENANCE.md) and landed in the
|
|
747
|
-
// SAME .claude/skills/<name>/ the builder's harness reads (task 1003321, ADR
|
|
748
|
-
// 0198). Same transforms as step 1; a disabled module's are excluded by the same
|
|
749
|
-
// rule; a name the core's own .claude/skills/ already carries keeps the core copy;
|
|
750
|
-
// a name that is not a slug, or a vendored dir that fails the sidecar gate, is
|
|
751
|
-
// REFUSED here at copy time — the CI test is the second line, not the only one.
|
|
752
|
-
const sources = moduleSkillSources({ roster });
|
|
753
|
-
for (const r of sources.refused) {
|
|
754
|
-
summary.notes.push(`module skill "${r.name}" (${r.module}) refused: ${r.reason}.`);
|
|
755
|
-
log(` ✗ refused module skill "${r.name}" (${r.module}): ${r.reason}`);
|
|
756
|
-
}
|
|
757
|
-
for (const s of sources) {
|
|
758
|
-
if (!s.enabled) { if (!summary.excludedSkills.includes(s.name)) summary.excludedSkills.push(s.name); continue; }
|
|
759
|
-
if (fs.existsSync(path.join(skillsSrc, s.name)) && !Object.prototype.hasOwnProperty.call(materialisedInCore, s.name)) {
|
|
760
|
-
summary.notes.push(`module skill "${s.name}" (${s.module}) also exists under the core's .claude/skills/ — the core copy was materialized, the module copy ignored.`);
|
|
761
|
-
continue;
|
|
762
|
-
}
|
|
763
|
-
const r = copyTreeTransformed(s.dir, path.join(destClaude, 'skills', s.name), { dryRun, overwrite, transform: (t) => rebrand(bongosify(t)), onFile: recordUnder(`.claude/skills/${s.name}`) });
|
|
764
|
-
summary.moduleSkills += r.files;
|
|
765
|
-
for (const rel of r.skipped || []) summary.skippedFiles.push(`skills/${s.name}/${rel}`);
|
|
766
|
-
}
|
|
767
|
-
if (summary.moduleSkills) log(` ${dryRun ? '[dry-run] would materialize' : '✓ materialized'} ${summary.moduleSkills} module-owned skill file(s) → .claude/skills/ (from modules/<key>/skills/)`);
|
|
768
|
-
|
|
769
|
-
// 1c. WITHDRAW a skill a previous materialize landed here that this run no longer
|
|
770
|
-
// lands — the module was switched off (or stopped declaring the name) on an
|
|
771
|
-
// instance that ALREADY has the files. Step 1's skillSkip and step 1b's
|
|
772
|
-
// `enabled` check both only decline to COPY, which is the whole bug: disabling
|
|
773
|
-
// a module was honoured on a fresh instance and silently ignored on
|
|
774
|
-
// `bongos upgrade`, leaving stale dirs in .claude/skills/ for the harness to
|
|
775
|
-
// keep loading (task 1003632, found by the on/off proof of task 1003331).
|
|
776
|
-
// materializeModuleSkillsIntoCore has done this for the core checkout since
|
|
777
|
-
// task 1003330; this is the same mechanism for the instance side.
|
|
778
|
-
//
|
|
779
|
-
// PROVENANCE-GATED, and that gate is the safety property: only a name the
|
|
780
|
-
// manifest says a previous run LANDED is eligible. A skill the instance's owner
|
|
781
|
-
// wrote by hand was never in the manifest, so it can never be deleted here even
|
|
782
|
-
// if a module happens to declare the same name. With no manifest at all — an
|
|
783
|
-
// instance last materialized before this shipped — nothing is withdrawn and a
|
|
784
|
-
// note says so: that first run writes the provenance, and every run after it
|
|
785
|
-
// honours a disable. Refusing to guess is the point; deleting a builder's skill
|
|
786
|
-
// because we cannot prove we put it there is the one outcome worth avoiding.
|
|
787
|
-
const skillsDest = path.join(destClaude, 'skills');
|
|
788
|
-
const landedNow = {};
|
|
789
|
-
for (const src of sources) {
|
|
790
|
-
if (!src.enabled) continue;
|
|
791
|
-
// A dry run copied nothing, so it records what WOULD land; a real run confirms
|
|
792
|
-
// the dir is actually there before claiming provenance over it.
|
|
793
|
-
if (!dryRun && !fs.existsSync(path.join(skillsDest, src.name))) continue;
|
|
794
|
-
landedNow[src.name] = { module: src.module, source: path.relative(coreRoot, src.dir).split(path.sep).join('/'), vendored: src.vendored };
|
|
795
|
-
}
|
|
796
|
-
// A core-SHIPPED skill whose name a module also declares is landed by step 1, not
|
|
797
|
-
// step 1b — but it is withdrawable by the same disabled-module rule, so it needs
|
|
798
|
-
// provenance too.
|
|
799
|
-
for (const mod of roster) {
|
|
800
|
-
if (!mod.enabled) continue;
|
|
801
|
-
for (const name of mod.skills) {
|
|
802
|
-
if (landedNow[name] || !fs.existsSync(path.join(skillsSrc, name))) continue;
|
|
803
|
-
landedNow[name] = { module: mod.key, source: `.claude/skills/${name}`, coreShipped: true };
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
// A name the CORE ships now is the core's, whatever an older manifest said — a core
|
|
807
|
-
// skill can take over a name a module once owned, and step 1 copies it in on this very
|
|
808
|
-
// run. Without this guard 1c deleted it again immediately (task 1003818, a regression
|
|
809
|
-
// in 1003632's own first cut). materializeModuleSkillsIntoCore states the same rule for
|
|
810
|
-
// the checkout side via its `tracked(name)` check; this is the instance-side twin.
|
|
811
|
-
//
|
|
812
|
-
// The `!skipSkills.has(name)` half is load-bearing, not belt-and-braces: when a DISABLED
|
|
813
|
-
// module declares a core-shipped name, step 1 SKIPS the copy (that is the task 2103b
|
|
814
|
-
// exclusion), so the instance's dir really is stale and must still be withdrawn. Keeping
|
|
815
|
-
// it on the strength of "the core ships this name" would resurrect exactly the bug 1c
|
|
816
|
-
// exists to fix. Deliberately asked of the CORE source tree rather than the roster, so a
|
|
817
|
-
// name no enabled module declares any more is still recognised as legitimately sourced.
|
|
818
|
-
const coreShipsNow = (name) => fs.existsSync(path.join(skillsSrc, name)) && !skipSkills.has(name);
|
|
819
|
-
// Every CORE skill step 1 landed is recorded too (task 1004482), so a skill the core stops
|
|
820
|
-
// shipping in a later release is withdrawn by the rule below instead of lingering forever.
|
|
821
|
-
// When the core's .claude/skills/ could not be read at all, nothing was landed from it and
|
|
822
|
-
// nothing may be withdrawn on that account: the previous core entries are carried forward.
|
|
823
|
-
const coreTreeRead = skillsRes.present;
|
|
824
|
-
if (coreTreeRead) {
|
|
825
|
-
for (const name of fs.readdirSync(skillsSrc)) {
|
|
826
|
-
if (landedNow[name] || !SKILL_NAME_RE.test(name) || skillSkip(name)) continue;
|
|
827
|
-
if (!fs.statSync(path.join(skillsSrc, name)).isDirectory()) continue;
|
|
828
|
-
if (!dryRun && !fs.existsSync(path.join(skillsDest, name))) continue;
|
|
829
|
-
landedNow[name] = { source: `.claude/skills/${name}`, coreShipped: true };
|
|
830
|
-
}
|
|
831
|
-
} else {
|
|
832
|
-
for (const [name, rec] of Object.entries(landedPreviously)) if (rec && rec.coreShipped && !rec.module && !landedNow[name]) landedNow[name] = rec;
|
|
833
|
-
}
|
|
834
|
-
const withdrawable = Object.keys(landedPreviously).filter((n) => SKILL_NAME_RE.test(n) && !landedNow[n] && !coreShipsNow(n));
|
|
835
|
-
// The historical half (task 1004482): a skill the core retired BEFORE the manifest recorded
|
|
836
|
-
// core skills is withdrawn when its dir still carries a description the core shipped under
|
|
837
|
-
// that name. Anything else under a retired name is the instance's own and stays.
|
|
838
|
-
const retired = readRetiredCoreSkills();
|
|
839
|
-
const keptAsOwn = [];
|
|
840
|
-
for (const [name, entry] of Object.entries(retired)) {
|
|
841
|
-
if (!SKILL_NAME_RE.test(name) || landedNow[name] || coreShipsNow(name) || withdrawable.includes(name)) continue;
|
|
842
|
-
const dir = path.join(skillsDest, name);
|
|
843
|
-
if (!fs.existsSync(dir)) continue;
|
|
844
|
-
if (isRetiredCoreCopy(dir, entry && entry.descriptionDigests)) withdrawable.push(name);
|
|
845
|
-
else keptAsOwn.push(name);
|
|
846
|
-
}
|
|
847
|
-
if (keptAsOwn.length) summary.notes.push(`${keptAsOwn.length} skill dir(s) share a name the core once shipped but are not the core's copy (their description is not one it shipped), so they were left in place as the instance's own: ${keptAsOwn.sort().join(', ')}.`);
|
|
848
|
-
if (!overwrite) {
|
|
849
|
-
// adopt mode never clobbers what the owner already has; withdrawing is a clobber.
|
|
850
|
-
if (withdrawable.length) summary.notes.push(`${withdrawable.length} skill(s) the core no longer lands here were left in place (adopt mode does not withdraw): ${withdrawable.sort().join(', ')}.`);
|
|
851
|
-
} else {
|
|
852
|
-
for (const name of withdrawable.sort()) {
|
|
853
|
-
const dir = path.join(skillsDest, name);
|
|
854
|
-
if (!fs.existsSync(dir)) continue;
|
|
855
|
-
// A DELETION is a dirty path too, and `git status` names the individual files rather
|
|
856
|
-
// than the directory — so enumerate before removing, or the withdrawal is exactly the
|
|
857
|
-
// kind of leftover that wedges the next sweep (task 1003957).
|
|
858
|
-
for (const f of listFilesRecursive(dir)) addWritten(path.join('.claude/skills', name, f));
|
|
859
|
-
if (!dryRun) fs.rmSync(dir, { recursive: true, force: true });
|
|
860
|
-
summary.withdrawnSkills.push(name);
|
|
861
|
-
}
|
|
862
|
-
if (summary.withdrawnSkills.length) log(` ${dryRun ? '[dry-run] would withdraw' : '✓ withdrew'} ${summary.withdrawnSkills.length} stale skill dir(s) the core no longer ships here (retired, or its module is off): ${summary.withdrawnSkills.join(', ')}`);
|
|
863
|
-
}
|
|
864
|
-
if (!Object.keys(landedPreviously).length && summary.excludedSkills.length) {
|
|
865
|
-
summary.notes.push('no .instance-skills.json provenance in .claude/skills/ yet, so nothing was withdrawn — this run records it; a later run can withdraw the skills of a module that has since been disabled.');
|
|
866
|
-
}
|
|
867
|
-
// Record what landed, so the NEXT run can withdraw what this one placed.
|
|
868
|
-
//
|
|
869
|
-
// REPORTED on a dry run, written only on a real one — the same split the starter CLAUDE.md
|
|
870
|
-
// below already uses. writtenPaths is a "what this run rewrites" list, and a dry run's job is
|
|
871
|
-
// to preview exactly that: upgrade.js asks for one to decide which dirty paths its clean-tree
|
|
872
|
-
// pre-flight may ignore (task 1004122), so a generated file missing from the preview is a file
|
|
873
|
-
// the pre-flight halts on and the real run then rewrites anyway.
|
|
874
|
-
if (overwrite) {
|
|
875
|
-
const names = Object.keys(landedNow).sort();
|
|
876
|
-
const manifest = { _doc: 'GENERATED by scripts/gds/claude-materialize.js (tasks 1003632, 1004482): every skill a materialize landed in this instance, core and module alike. It is the provenance record that lets a later run WITHDRAW a skill the core stopped shipping or whose module has since been disabled — a name absent from here is never deleted on that account, so a hand-written skill is safe. Commit it; do not hand-edit.', skills: Object.fromEntries(names.map((n) => [n, landedNow[n]])) };
|
|
877
|
-
if (!dryRun) {
|
|
878
|
-
fs.mkdirSync(skillsDest, { recursive: true });
|
|
879
|
-
fs.writeFileSync(path.join(skillsDest, INSTANCE_SKILLS_MANIFEST), JSON.stringify(manifest, null, 2) + '\n');
|
|
880
|
-
}
|
|
881
|
-
addWritten(path.join('.claude/skills', INSTANCE_SKILLS_MANIFEST));
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
// 2. settings.json — topology; present in the checkout/core repo, absent in a package-only install.
|
|
885
|
-
const settingsSrc = path.join(srcClaude, 'settings.json');
|
|
886
|
-
if (fs.existsSync(settingsSrc)) {
|
|
887
|
-
const settingsDest = path.join(destClaude, 'settings.json');
|
|
888
|
-
if (!overwrite && fs.existsSync(settingsDest)) { // adopt: never clobber an owner's settings.json
|
|
889
|
-
summary.skippedFiles.push('settings.json');
|
|
890
|
-
log(' • .claude/settings.json already present — left untouched (adopt merges nothing here yet).');
|
|
891
|
-
} else {
|
|
892
|
-
// task 1004023: an unparseable settings.json is copied through BYTE FOR
|
|
893
|
-
// BYTE — no bongosify, no rebrand. Both are regex passes written for the
|
|
894
|
-
// strings inside a parsed file, and over raw JSON text they damage it.
|
|
895
|
-
// The instance gets what the core had, plus a note naming the parse error.
|
|
896
|
-
const settingsOut = readSettingsTransform(settingsSrc);
|
|
897
|
-
if (!dryRun) {
|
|
898
|
-
fs.mkdirSync(destClaude, { recursive: true });
|
|
899
|
-
fs.writeFileSync(settingsDest, settingsOut.parsed ? rebrandSettings(settingsOut.text, rebrand) : settingsOut.text);
|
|
900
|
-
}
|
|
901
|
-
addWritten('.claude/settings.json');
|
|
902
|
-
summary.settings = true;
|
|
903
|
-
if (!settingsOut.parsed) {
|
|
904
|
-
summary.settingsUnparsed = true;
|
|
905
|
-
summary.notes.push(`.claude/settings.json is not valid JSON (${settingsOut.reason}) — copied through UNCHANGED: no hook-command or permission-rule rewrite to bongos, and no identity rebrand. Fix the JSON at the core root and materialize again, or edit the instance copy by hand.`);
|
|
906
|
-
}
|
|
907
|
-
log(` ${dryRun ? '[dry-run] would write' : '✓ wrote'} .claude/settings.json ${settingsOut.parsed ? '(hook commands + permission rules→bongos, identity rebranded)' : '(UNCHANGED — not valid JSON, nothing rewritten)'}`);
|
|
908
|
-
}
|
|
909
|
-
} else {
|
|
910
|
-
// Package-only install: the core root carries no settings.json to copy, so
|
|
911
|
-
// write the STARTER instead of leaving the instance with no permissions at
|
|
912
|
-
// all (task 1003962 — the note that used to sit here said "provide it from a
|
|
913
|
-
// starter" and nothing ever did). Written only when ABSENT, the same rule
|
|
914
|
-
// the starter CLAUDE.md below follows: an instance that has grown its own
|
|
915
|
-
// permissions owns them, and a later materialize must never clobber them.
|
|
916
|
-
const settingsDest = path.join(destClaude, 'settings.json');
|
|
917
|
-
if (fs.existsSync(settingsDest)) {
|
|
918
|
-
// The instance owns this file — but a deny rule the starter has gained since is ADDED to
|
|
919
|
-
// it rather than withheld forever (task 1004156). Nothing of theirs is removed or changed.
|
|
920
|
-
// Only the CREDENTIAL half is offered: the starter's shelf rules guard a workflow, not a
|
|
921
|
-
// secret, and are starter-only (task 1004158).
|
|
922
|
-
// The read is guarded: existsSync passing does not mean readable (a directory at that path,
|
|
923
|
-
// a locked or root-owned file), and this runs AFTER the pin moved and the migrations ran, so
|
|
924
|
-
// a throw here would leave a half-applied upgrade. It fails soft, like its sibling above.
|
|
925
|
-
// The npx twins of the owner's own bare-`bongos` allow rules ride the same single read and
|
|
926
|
-
// write (task 1004621): applied first, so the deny top-up below works on — and writes — the
|
|
927
|
-
// text that already carries them. An unparseable file trips both the same way and is
|
|
928
|
-
// reported once, by the deny half.
|
|
929
|
-
let topUp;
|
|
930
|
-
let twins = { text: null, added: [], reason: null };
|
|
931
|
-
try {
|
|
932
|
-
const raw = fs.readFileSync(settingsDest, 'utf8');
|
|
933
|
-
twins = topUpNpxAllowTwins(raw);
|
|
934
|
-
topUp = topUpStarterDeny(twins.text || raw, credentialDeny(toBranding));
|
|
935
|
-
} catch (err) { topUp = { text: null, added: [], reason: `it could not be read (${err.code || err.message})` }; }
|
|
936
|
-
if (twins.added.length) {
|
|
937
|
-
summary.settingsAllowTwinsAdded = twins.added;
|
|
938
|
-
summary.notes.push(`.claude/settings.json kept every rule it already had and GAINED the \`npx bongos\` twin of ${twins.added.length} bare-\`bongos\` allow rule(s) it held — the skills now say \`npx bongos …\`, which a bare rule does not match: ${twins.added.join(', ')}`);
|
|
939
|
-
log(` ${dryRun ? '[dry-run] would add' : '✓ added'} the npx twin of ${twins.added.length} bare-bongos allow rule(s) to .claude/settings.json (skills now run \`npx bongos …\`; every rule you wrote is kept): ${twins.added.join(', ')}`);
|
|
940
|
-
if (!topUp.text && !topUp.reason) {
|
|
941
|
-
if (!dryRun) fs.writeFileSync(settingsDest, twins.text);
|
|
942
|
-
if (!dryRun) addWritten('.claude/settings.json'); // real run only — the same reasoning as the deny write below
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
if (topUp.text) {
|
|
946
|
-
if (!dryRun) fs.writeFileSync(settingsDest, topUp.text);
|
|
947
|
-
// Reported as written only on the REAL run, deliberately. writtenPaths doubles as the set
|
|
948
|
-
// the upgrade pre-flight IGNORES when it checks for a dirty tree (task 1004122), and that
|
|
949
|
-
// waiver is justified by "materialize overwrites these unconditionally, so whatever they
|
|
950
|
-
// hold now is discarded either way" — which is precisely NOT true of a top-up, the one
|
|
951
|
-
// path here that preserves existing content. Leaving it out of the dry-run preview keeps
|
|
952
|
-
// an owner's uncommitted edit to settings.json halting the bump, as it always did; putting
|
|
953
|
-
// it in the real run's summary still hands it to persistPin, so the pin commit carries the
|
|
954
|
-
// added rules and the next upgrade does not read them as a human's stray work.
|
|
955
|
-
if (!dryRun) addWritten('.claude/settings.json');
|
|
956
|
-
summary.settingsDenyAdded = topUp.added;
|
|
957
|
-
summary.notes.push(`.claude/settings.json kept every rule it already had and GAINED ${topUp.added.length} missing deny rule(s) — an instance that took the starter before task 1003966 carried none of them, so its local agent could still read keys and session tokens: ${topUp.added.join(', ')}`);
|
|
958
|
-
log(` ${dryRun ? '[dry-run] would add' : '✓ added'} ${topUp.added.length} missing deny rule(s) to .claude/settings.json — every rule you wrote is kept, the file is re-indented to 2 spaces: ${topUp.added.join(', ')}`);
|
|
959
|
-
} else if (topUp.reason) {
|
|
960
|
-
// The security gap PERSISTS here, so it does not get the same quiet bullet as the
|
|
961
|
-
// all-clear. upgrade.js never iterates summary.notes, so this log line is the only
|
|
962
|
-
// channel that reaches the operator's terminal.
|
|
963
|
-
summary.skippedFiles.push('settings.json');
|
|
964
|
-
summary.settingsDenyUncheckable = topUp.reason;
|
|
965
|
-
summary.notes.push(`.claude/settings.json could not be checked for missing deny rules — ${topUp.reason}. It was left exactly as it is, so if it predates task 1003966 its local agent can still read keys and session tokens; compare its permissions.deny against the starter by hand, or fix the file and upgrade again.`);
|
|
966
|
-
log(` ! .claude/settings.json could NOT be checked for missing deny rules — ${topUp.reason}. Left untouched; its deny half may still be missing.`);
|
|
967
|
-
} else if (!twins.added.length) {
|
|
968
|
-
summary.skippedFiles.push('settings.json');
|
|
969
|
-
log(' • .claude/settings.json already present — left untouched (the instance owns it; it already carries every credential deny rule. The starter\'s shelf rules are not offered here — they guard a workflow, not a secret, and are starter-only: task 1004158).');
|
|
970
|
-
}
|
|
971
|
-
} else {
|
|
972
|
-
if (!dryRun) {
|
|
973
|
-
fs.mkdirSync(destClaude, { recursive: true });
|
|
974
|
-
fs.writeFileSync(settingsDest, renderStarterSettings(toBranding));
|
|
975
|
-
}
|
|
976
|
-
addWritten('.claude/settings.json');
|
|
977
|
-
summary.settings = true;
|
|
978
|
-
summary.notes.push(`.claude/settings.json written from the starter — ${STARTER_COMMANDS.length} blessed command(s) for each of ${STARTER_SHELL_TOOLS.join(' + ')}, permissions only.`);
|
|
979
|
-
log(` ${dryRun ? '[dry-run] would write' : '✓ wrote'} .claude/settings.json (starter: ${STARTER_COMMANDS.length} blessed commands × ${STARTER_SHELL_TOOLS.length} shell tools, no hooks)`);
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
// 3. hooks — topology; copied WITH an identity rebrand (their .js internals carried
|
|
984
|
-
// the founder origin/config-dir). Their core require()s self-resolve at runtime via
|
|
985
|
-
// the copied _core-resolve.js sibling (task 2139) — no path rewriting needed here.
|
|
986
|
-
const hooksRes = copyTreeTransformed(path.join(srcClaude, 'hooks'), path.join(destClaude, 'hooks'), {
|
|
987
|
-
dryRun, overwrite, transform: rebrand, textExt: HOOK_TEXT_EXT, onFile: recordUnder('.claude/hooks'),
|
|
988
|
-
});
|
|
989
|
-
summary.hooks = hooksRes.files;
|
|
990
|
-
for (const rel of hooksRes.skipped || []) summary.skippedFiles.push(`hooks/${rel}`);
|
|
991
|
-
if (!hooksRes.present) {
|
|
992
|
-
summary.notes.push('.claude/hooks not present at the core root (topology, excluded from the package) — provide them from a starter.');
|
|
993
|
-
} else {
|
|
994
|
-
log(` ${dryRun ? '[dry-run] would materialize' : '✓ materialized'} ${hooksRes.files} hook file(s) → .claude/hooks/ (founder identity rebranded)${left((hooksRes.skipped || []).length)}`);
|
|
995
|
-
summary.notes.push('hooks: founder origin/config-dir rebranded to this instance; their internal `require(scripts/gds/…)` paths self-resolve inside the package at runtime via the copied _core-resolve.js sibling (task 2139).');
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
// 3b. scheduled-tasks — the cron routines (System 4 dispatcher, ADR 0078; task 2138). TOPOLOGY
|
|
999
|
-
// like hooks (NOT in the package — PROTECTED_TOPOLOGY_EXCLUDE), so materialized by copy when
|
|
1000
|
-
// present at the core root and a no-op-with-note in a package-only install. Bodies (.md) are
|
|
1001
|
-
// bongosified so a judgment routine's `node scripts/gds/x.js` model-instructions become
|
|
1002
|
-
// `bongos exec …`; the deterministic routines' `.claude/scheduled-tasks/<x>.js` step commands
|
|
1003
|
-
// are NOT matched by bongosify and stay as-is. Companion .js are rebranded but keep their
|
|
1004
|
-
// paths: they resolve core require()s at runtime via the copied _core-resolve.js sibling
|
|
1005
|
-
// (task 2139), and run-routine.js finds the routines under resolveInstanceRoot() post-split.
|
|
1006
|
-
const routinesRes = copyTreeTransformed(path.join(srcClaude, 'scheduled-tasks'), path.join(destClaude, 'scheduled-tasks'), {
|
|
1007
|
-
dryRun, overwrite, transform: (t) => rebrand(bongosify(t)), textExt: HOOK_TEXT_EXT, onFile: recordUnder('.claude/scheduled-tasks'),
|
|
1008
|
-
});
|
|
1009
|
-
summary.scheduledTasks = routinesRes.files;
|
|
1010
|
-
for (const rel of routinesRes.skipped || []) summary.skippedFiles.push(`scheduled-tasks/${rel}`);
|
|
1011
|
-
if (!routinesRes.present) {
|
|
1012
|
-
summary.notes.push('.claude/scheduled-tasks not present at the core root (topology, excluded from the package) — provide them from a starter.');
|
|
1013
|
-
} else {
|
|
1014
|
-
log(` ${dryRun ? '[dry-run] would materialize' : '✓ materialized'} ${routinesRes.files} scheduled-task file(s) → .claude/scheduled-tasks/ (bodies→bongos, founder identity rebranded)${left((routinesRes.skipped || []).length)}`);
|
|
1015
|
-
summary.notes.push('scheduled-tasks: cron routines materialized; run-routine.js resolves them under resolveInstanceRoot() and their companion .js resolve core via the copied _core-resolve.js sibling (task 2138).');
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
// 4. CLAUDE.md — the project-root framing an agent reads every session (task 2104).
|
|
1019
|
-
// Written from the neutral starter template, brand-substituted from THIS instance's
|
|
1020
|
-
// branding. Written only when ABSENT — never clobber a CLAUDE.md the instance has
|
|
1021
|
-
// grown (safe for init, adopt, and upgrade alike; the self-copy guard above already
|
|
1022
|
-
// keeps this from ever touching the core/OTB checkout's own CLAUDE.md).
|
|
1023
|
-
// One narrow exception (task 1004621): the starter's OWN sentences that told the assistant to
|
|
1024
|
-
// type a bare `bongos …` — not on PATH in a project — are swapped for their `npx bongos …` form
|
|
1025
|
-
// where they still read exactly as the starter wrote them (refreshStarterCliLines). Not in
|
|
1026
|
-
// adopt mode, which never touches what the owner already had.
|
|
1027
|
-
const claudeMdPath = path.join(instanceDir, 'CLAUDE.md');
|
|
1028
|
-
if (fs.existsSync(claudeMdPath)) {
|
|
1029
|
-
let refreshed = { changed: 0 };
|
|
1030
|
-
if (overwrite) {
|
|
1031
|
-
try { refreshed = refreshStarterCliLines(fs.readFileSync(claudeMdPath, 'utf8')); } catch { /* unreadable: leave it, as before */ }
|
|
1032
|
-
}
|
|
1033
|
-
if (refreshed.changed) {
|
|
1034
|
-
if (!dryRun) fs.writeFileSync(claudeMdPath, refreshed.text);
|
|
1035
|
-
// Real run only, like the settings top-up: it preserves content, so the upgrade pre-flight's
|
|
1036
|
-
// "materialize overwrites this anyway" waiver must not cover an owner's uncommitted edit.
|
|
1037
|
-
if (!dryRun) addWritten('CLAUDE.md');
|
|
1038
|
-
summary.claudeMdCliLines = refreshed.changed;
|
|
1039
|
-
summary.notes.push(`CLAUDE.md kept as the instance's own, except ${refreshed.changed} unedited starter sentence(s) now say \`npx bongos …\` — the CLI is not on PATH in a project, so a bare \`bongos\` failed with command not found.`);
|
|
1040
|
-
log(` ${dryRun ? '[dry-run] would update' : '✓ updated'} ${refreshed.changed} unedited starter sentence(s) in CLAUDE.md to \`npx bongos …\` (everything else untouched)`);
|
|
1041
|
-
} else {
|
|
1042
|
-
summary.notes.push('CLAUDE.md already present — left untouched (the instance owns it).');
|
|
1043
|
-
}
|
|
1044
|
-
} else {
|
|
1045
|
-
if (!dryRun) {
|
|
1046
|
-
fs.mkdirSync(instanceDir, { recursive: true });
|
|
1047
|
-
fs.writeFileSync(claudeMdPath, renderInstanceClaudeMd(toBranding));
|
|
1048
|
-
}
|
|
1049
|
-
addWritten('CLAUDE.md');
|
|
1050
|
-
summary.claudeMd = true;
|
|
1051
|
-
log(` ${dryRun ? '[dry-run] would write' : '✓ wrote'} CLAUDE.md (starter, brand-substituted for this instance)`);
|
|
1052
|
-
}
|
|
1053
|
-
return summary;
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
// materializeWillRewrite — the instance-relative paths a materialize WOULD rewrite here, changing
|
|
1057
|
-
// nothing. `bongos upgrade` asks before it starts, to decide which dirty paths its clean-tree
|
|
1058
|
-
// pre-flight may waive.
|
|
1059
|
-
//
|
|
1060
|
-
// THE WEDGE THIS EXISTS FOR (task 1004122). The upgrade's materialize step rewrites `.claude/`
|
|
1061
|
-
// from the new core on EVERY bump, so after an upgrade that did not commit it — one from before
|
|
1062
|
-
// task 1003957, or any run without --commit-pin — the instance carries ~40 modified
|
|
1063
|
-
// `.claude/skills/*` files that nobody edited. upgrade.js's clean-tree pre-flight then read them
|
|
1064
|
-
// as a human's uncommitted work and refused, so the instance took exactly one upgrade and stuck:
|
|
1065
|
-
// `test4` (instance 11) failed its Deploy-page upgrade this way, and provision-core-upgrade.js
|
|
1066
|
-
// passes --commit-pin but NOT --force, so the button stayed dead until someone committed by hand.
|
|
1067
|
-
//
|
|
1068
|
-
// Asking materializeClaude what it WOULD write is a real provenance answer, not a path
|
|
1069
|
-
// allow-list: the set is derived from the core actually installed here, and every path in it
|
|
1070
|
-
// is one the materialize step overwrites unconditionally a few seconds later. Whatever those files hold right
|
|
1071
|
-
// now is discarded either way, so refusing on them protects nothing and stops every future
|
|
1072
|
-
// update. A path materialize would NOT touch — an owner's own skill, a dirty migration, a
|
|
1073
|
-
// half-finished edit — is absent from the set and still halts the bump, which is the whole
|
|
1074
|
-
// safety property. Under --commit-pin the same paths come back from that step as persistPin's
|
|
1075
|
-
// artifactPaths and are committed, so the tree ends clean and the next upgrade needs none of this.
|
|
1076
|
-
//
|
|
1077
|
-
// Probed against the core on disk NOW, not the target: the target is not installed yet, and the
|
|
1078
|
-
// two ship the same `.claude/` surface. Fail-soft — a materialize that throws (no core
|
|
1079
|
-
// installed, an unreadable tree) returns nothing and the pre-flight is as strict as it ever was.
|
|
1080
|
-
function materializeWillRewrite({ instanceDir, coreRoot, materialize = materializeClaude }, err = console.error) {
|
|
1081
|
-
try {
|
|
1082
|
-
const root = coreRoot || path.join(instanceDir, 'node_modules', CORE_PACKAGE_NAMES[0]);
|
|
1083
|
-
const sum = materialize({ coreRoot: root, instanceDir, dryRun: true, log: () => {} });
|
|
1084
|
-
return (sum && Array.isArray(sum.writtenPaths)) ? sum.writtenPaths : [];
|
|
1085
|
-
} catch (e) {
|
|
1086
|
-
err(` ! could not preview the .claude/ materialization (${e && e.message ? e.message : e}) — pre-flight will treat every dirty path as a human's work.`);
|
|
1087
|
-
return [];
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
// ---- the dev checkout: module-owned skills materialised INTO the core (task 1003330, ADR 0224) ----
|
|
1092
|
-
// materializeClaude's self-copy guard is right for init/upgrade (instance == core is a no-op),
|
|
1093
|
-
// but Claude Code discovers only .claude/skills/ at the project root, so a builder working IN
|
|
1094
|
-
// the core checkout never sees modules/<key>/skills/. This lands every ENABLED module's skills
|
|
1095
|
-
// there as UNTRACKED, self-ignored dirs: verbatim copies (no bongosify — the checkout runs
|
|
1096
|
-
// `node scripts/gds/…`), a generated .claude/skills/.module-skills.json manifest naming what
|
|
1097
|
-
// was materialised and from where, and a generated .claude/skills/.gitignore covering the
|
|
1098
|
-
// manifest, itself and every materialised dir, so `git status` shows nothing new and nothing
|
|
1099
|
-
// can be committed by accident. The same vendoredSkillGate + SKILL_NAME_RE apply; a name the
|
|
1100
|
-
// core's own tracked .claude/skills/ carries is left to the core. Idempotent: every run first
|
|
1101
|
-
// removes what the last manifest named (so a skill a module stopped declaring does not
|
|
1102
|
-
// linger), then lands the current set; `clean` stops after the removal.
|
|
1103
|
-
// Is `root` the core CHECKOUT — a workbench a builder edits — rather than the core
|
|
1104
|
-
// package installed under a scaffolded instance's node_modules? Only a checkout's own
|
|
1105
|
-
// .claude/skills/ is the directory Claude Code reads for that project, so only there
|
|
1106
|
-
// does materialising the module-owned skills put them in front of anyone; an instance
|
|
1107
|
-
// already received them at ITS root from `bongos init`, and a second copy under
|
|
1108
|
-
// node_modules/@bongos/core would be invisible (task 1003486). Fail-soft by
|
|
1109
|
-
// construction: an unreadable package.json answers "not the core checkout", which is
|
|
1110
|
-
// the conservative no-op rather than a copy into a tree we could not identify.
|
|
1111
|
-
function isCoreCheckoutRoot(root) {
|
|
1112
|
-
try {
|
|
1113
|
-
const abs = path.resolve(root);
|
|
1114
|
-
if (abs.split(/[\\/]+/).includes('node_modules')) return false;
|
|
1115
|
-
return isCorePackageName(JSON.parse(fs.readFileSync(path.join(abs, 'package.json'), 'utf8')).name);
|
|
1116
|
-
} catch (_) {
|
|
1117
|
-
return false;
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
const MODULE_SKILLS_MANIFEST = '.module-skills.json';
|
|
1122
|
-
// The INSTANCE-side provenance record, deliberately a DIFFERENT filename from the
|
|
1123
|
-
// core's (task 1003632). They are different artifacts: MODULE_SKILLS_MANIFEST lists
|
|
1124
|
-
// the untracked copies materializeModuleSkillsIntoCore made inside a core CHECKOUT,
|
|
1125
|
-
// and is asserted never to travel to an instance; this one lists what materializeClaude
|
|
1126
|
-
// landed INTO an instance, and is what step 1c withdraws against. Sharing one name made
|
|
1127
|
-
// the instance's own record look like a core dotfile that had leaked across the boundary.
|
|
1128
|
-
const INSTANCE_SKILLS_MANIFEST = '.instance-skills.json';
|
|
1129
|
-
function readSkillsManifest(skillsDir, file) {
|
|
1130
|
-
const m = readJsonSafe(path.join(skillsDir, file));
|
|
1131
|
-
return m && m.skills && typeof m.skills === 'object' ? m : { skills: {} };
|
|
1132
|
-
}
|
|
1133
|
-
function readModuleSkillsManifest(skillsDir) {
|
|
1134
|
-
return readSkillsManifest(skillsDir, MODULE_SKILLS_MANIFEST);
|
|
1135
|
-
}
|
|
1136
|
-
function readInstanceSkillsManifest(skillsDir) {
|
|
1137
|
-
return readSkillsManifest(skillsDir, INSTANCE_SKILLS_MANIFEST);
|
|
1138
|
-
}
|
|
1139
|
-
function materializeModuleSkillsIntoCore({ coreRoot, dryRun = false, clean = false, log = () => {} }) {
|
|
1140
|
-
const skillsDir = path.join(coreRoot, '.claude', 'skills');
|
|
1141
|
-
const summary = { materialized: [], removed: [], refused: [], excluded: [], keptCore: [], files: 0, notes: [] };
|
|
1142
|
-
const previous = readModuleSkillsManifest(skillsDir);
|
|
1143
|
-
// A dir git tracks is the core's, whatever an older manifest said (a core skill can take
|
|
1144
|
-
// over a name a module once owned); it is never removed or overwritten here.
|
|
1145
|
-
const tracked = (name) => { try { return spawnSync('git', ['-C', coreRoot, 'ls-files', '--error-unmatch', '--', `.claude/skills/${name}`], { encoding: 'utf8' }).status === 0; } catch { return false; } };
|
|
1146
|
-
for (const name of Object.keys(previous.skills)) {
|
|
1147
|
-
const dir = path.join(skillsDir, name);
|
|
1148
|
-
if (!SKILL_NAME_RE.test(name) || !fs.existsSync(dir)) continue;
|
|
1149
|
-
if (tracked(name)) { summary.keptCore.push(name); summary.notes.push(`"${name}" is tracked by git now — the last manifest's copy was not removed; the core's dir is kept.`); continue; }
|
|
1150
|
-
if (!dryRun) fs.rmSync(dir, { recursive: true, force: true });
|
|
1151
|
-
summary.removed.push(name);
|
|
1152
|
-
}
|
|
1153
|
-
if (clean) {
|
|
1154
|
-
for (const f of [MODULE_SKILLS_MANIFEST, '.gitignore']) { const p = path.join(skillsDir, f); if (fs.existsSync(p) && !dryRun) fs.rmSync(p); }
|
|
1155
|
-
log(` ${dryRun ? '[dry-run] would remove' : '✓ removed'} ${summary.removed.length} materialised module skill dir(s), the manifest and .claude/skills/.gitignore`);
|
|
1156
|
-
return summary;
|
|
1157
|
-
}
|
|
1158
|
-
const roster = moduleSkillRoster({ coreRoot, instanceDir: coreRoot });
|
|
1159
|
-
const sources = moduleSkillSources({ roster });
|
|
1160
|
-
for (const r of sources.refused) { summary.refused.push(`${r.name} (${r.module}): ${r.reason}`); log(` ✗ refused module skill "${r.name}" (${r.module}): ${r.reason}`); }
|
|
1161
|
-
const manifest = { _doc: 'GENERATED by `node scripts/gds/claude-materialize.js --module-skills-only` (task 1003330, ADR 0224): the module-owned skills materialised into this core checkout as UNTRACKED copies so Claude Code sees them here. Every dir named below is ignored by the sibling .gitignore and removed by --clean; edit the module\'s skills/<name>/ source, never these copies, and re-run to refresh.', skills: {} };
|
|
1162
|
-
for (const s of sources) {
|
|
1163
|
-
if (!s.enabled) { summary.excluded.push(s.name); continue; }
|
|
1164
|
-
const dest = path.join(skillsDir, s.name);
|
|
1165
|
-
if (fs.existsSync(dest) && (!Object.prototype.hasOwnProperty.call(previous.skills, s.name) || tracked(s.name))) {
|
|
1166
|
-
summary.keptCore.push(s.name);
|
|
1167
|
-
summary.notes.push(`"${s.name}" (${s.module}) already exists under .claude/skills/ and is not a materialised copy — the core's own dir is kept.`);
|
|
1168
|
-
continue;
|
|
1169
|
-
}
|
|
1170
|
-
const r = copyTreeTransformed(s.dir, dest, { dryRun, overwrite: true, transform: (t) => t });
|
|
1171
|
-
summary.files += r.files;
|
|
1172
|
-
summary.materialized.push(s.name);
|
|
1173
|
-
manifest.skills[s.name] = { module: s.module, source: path.relative(coreRoot, s.dir).split(path.sep).join('/'), vendored: s.vendored, files: r.files };
|
|
1174
|
-
}
|
|
1175
|
-
const names = Object.keys(manifest.skills).sort();
|
|
1176
|
-
manifest.skills = Object.fromEntries(names.map((n) => [n, manifest.skills[n]]));
|
|
1177
|
-
const ignore = ['# GENERATED by scripts/gds/claude-materialize.js --module-skills-only (task 1003330): the module-owned skills', '# materialised into this checkout are untracked copies; this file and the manifest ignore themselves. Never commit these.', '/.gitignore', `/${MODULE_SKILLS_MANIFEST}`, ...names.map((n) => `/${n}/`)].join('\n') + '\n';
|
|
1178
|
-
if (!dryRun) {
|
|
1179
|
-
fs.mkdirSync(skillsDir, { recursive: true });
|
|
1180
|
-
fs.writeFileSync(path.join(skillsDir, MODULE_SKILLS_MANIFEST), JSON.stringify(manifest, null, 2) + '\n');
|
|
1181
|
-
fs.writeFileSync(path.join(skillsDir, '.gitignore'), ignore);
|
|
1182
|
-
}
|
|
1183
|
-
log(` ${dryRun ? '[dry-run] would materialize' : '✓ materialized'} ${summary.materialized.length} module-owned skill(s) (${summary.files} file(s)) → .claude/skills/ as untracked copies: ${names.join(', ') || 'none'}`);
|
|
1184
|
-
return summary;
|
|
1185
|
-
}
|
|
1186
|
-
|
|
1187
|
-
// The CLI entry is the dev-checkout path only; init/upgrade call materializeClaude directly.
|
|
1188
|
-
if (require.main === module) {
|
|
1189
|
-
const argv = process.argv.slice(2);
|
|
1190
|
-
if (!argv.includes('--module-skills-only') || argv.includes('--help')) {
|
|
1191
|
-
process.stderr.write('usage: node scripts/gds/claude-materialize.js --module-skills-only [--dry-run] [--clean]\n Lands every enabled module\'s skills (modules/<key>/skills/<name>/) into THIS checkout\'s .claude/skills/ as untracked,\n self-ignored copies so Claude Code sees them here (task 1003330). --clean removes them. The library behind bongos init / upgrade otherwise.\n');
|
|
1192
|
-
process.exit(argv.includes('--help') ? 0 : 2);
|
|
1193
|
-
}
|
|
1194
|
-
const s = materializeModuleSkillsIntoCore({ coreRoot: path.resolve(__dirname, '..', '..'), dryRun: argv.includes('--dry-run'), clean: argv.includes('--clean'), log: (l) => process.stdout.write(l + '\n') });
|
|
1195
|
-
for (const n of s.notes) process.stdout.write(` • ${n}\n`);
|
|
1196
|
-
process.stdout.write(`module skills → .claude/skills/: ${s.materialized.length} materialised (${s.files} file(s)), ${s.removed.length} refreshed or removed, ${s.excluded.length} excluded (module off), ${s.keptCore.length} kept as the core's own, ${s.refused.length} refused\n`);
|
|
1197
|
-
process.exit(s.refused.length ? 1 : 0);
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
module.exports = { skillDescription, descriptionDigest, isRetiredCoreCopy, readRetiredCoreSkills, RETIRED_CORE_SKILLS_FILE, scriptToVerb, bongosify, PROJECT_CLI, topUpNpxAllowTwins, transformSettings, readSettingsTransform, renderStarterSettings, STARTER_ALLOW, copyTreeTransformed, materializeClaude, materializeWillRewrite, materializeModuleSkillsIntoCore, isCoreCheckoutRoot, readModuleSkillsManifest, MODULE_SKILLS_MANIFEST, readInstanceSkillsManifest, INSTANCE_SKILLS_MANIFEST, GDS_INVOCATION_RE, buildRebrandRules, rebrandText, disabledModuleSkills, moduleSkillRoster, moduleSkillSources, vendoredSkillGate, SKILL_NAME_RE, VENDOR_DEFAULT_POLICY };
|
|
7
|
+
require('../bongos/forwarder.js').forward(module, 'claude-materialize.js');
|