@bongos/core 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1142) hide show
  1. package/.bongos-core.json +5727 -0
  2. package/.claude/skills/blocker-review/SKILL.md +91 -0
  3. package/.claude/skills/blocker-solve/SKILL.md +96 -0
  4. package/.claude/skills/builder-backup/SKILL.md +54 -0
  5. package/.claude/skills/builder-box/SKILL.md +45 -0
  6. package/.claude/skills/builder-claim/SKILL.md +76 -0
  7. package/.claude/skills/builder-connect/SKILL.md +59 -0
  8. package/.claude/skills/builder-cost/SKILL.md +47 -0
  9. package/.claude/skills/builder-end/SKILL.md +81 -0
  10. package/.claude/skills/builder-exit/SKILL.md +88 -0
  11. package/.claude/skills/builder-key/SKILL.md +40 -0
  12. package/.claude/skills/builder-reauth/SKILL.md +50 -0
  13. package/.claude/skills/builder-redteam/SKILL.md +109 -0
  14. package/.claude/skills/builder-release/SKILL.md +41 -0
  15. package/.claude/skills/builder-setup/SKILL.md +62 -0
  16. package/.claude/skills/builder-ship/SKILL.md +79 -0
  17. package/.claude/skills/builder-stage/SKILL.md +51 -0
  18. package/.claude/skills/builder-start/SKILL.md +46 -0
  19. package/.claude/skills/close-box/SKILL.md +43 -0
  20. package/.claude/skills/design-sync/SKILL.md +69 -0
  21. package/.claude/skills/dev/SKILL.md +49 -0
  22. package/.claude/skills/feedback/SKILL.md +32 -0
  23. package/.claude/skills/figma-design-sync/SKILL.md +74 -0
  24. package/.claude/skills/goal-review/SKILL.md +89 -0
  25. package/.claude/skills/idea-triage/SKILL.md +144 -0
  26. package/.claude/skills/ideate/SKILL.md +82 -0
  27. package/.claude/skills/merge-mode/SKILL.md +169 -0
  28. package/.claude/skills/new-project/SKILL.md +108 -0
  29. package/.claude/skills/otb-character-review/SKILL.md +71 -0
  30. package/.claude/skills/otb-design-review/SKILL.md +47 -0
  31. package/.claude/skills/otb-feedback-capture/SKILL.md +45 -0
  32. package/.claude/skills/otb-figma-sync/SKILL.md +54 -0
  33. package/.claude/skills/otb-tile-generate/SKILL.md +45 -0
  34. package/.claude/skills/paint/SKILL.md +70 -0
  35. package/.claude/skills/planning-session/SKILL.md +299 -0
  36. package/.claude/skills/priority-session/SKILL.md +134 -0
  37. package/.claude/skills/read-session-export/SKILL.md +58 -0
  38. package/.claude/skills/recall/SKILL.md +52 -0
  39. package/.claude/skills/session-handoff/SKILL.md +46 -0
  40. package/.claude/skills/status/SKILL.md +33 -0
  41. package/.devcontainer/Dockerfile +69 -0
  42. package/.devcontainer/README.md +73 -0
  43. package/.devcontainer/devcontainer-lock.json +19 -0
  44. package/.devcontainer/devcontainer.json +93 -0
  45. package/.devcontainer/healthcheck.sh +84 -0
  46. package/.devcontainer/init-firewall.sh +198 -0
  47. package/.devcontainer/post-create.sh +153 -0
  48. package/.dockerignore +36 -0
  49. package/.env.local.example +32 -0
  50. package/.gitattributes +83 -0
  51. package/.gitignore +91 -0
  52. package/CLAUDE.md +242 -0
  53. package/CODE_OF_CONDUCT.md +46 -0
  54. package/CONTRIBUTING.md +51 -0
  55. package/Dockerfile +46 -0
  56. package/GOVERNANCE.md +44 -0
  57. package/LICENSE +661 -0
  58. package/README.md +88 -0
  59. package/bin/bongos.js +222 -0
  60. package/clients/bongos-client/README.md +48 -0
  61. package/clients/bongos-client/bongos-client.global.js +617 -0
  62. package/clients/bongos-client/examples/hello-world.mjs +62 -0
  63. package/clients/bongos-client/index.cjs +619 -0
  64. package/clients/bongos-client/index.d.ts +793 -0
  65. package/clients/bongos-client/index.mjs +614 -0
  66. package/clients/bongos-client/package.json +32 -0
  67. package/config/branding.neutral.json +60 -0
  68. package/config/design-tokens.neutral.json +51 -0
  69. package/config/design-tokens.schema.json +96 -0
  70. package/config/modules.neutral.json +9 -0
  71. package/docker-compose.yml +52 -0
  72. package/docker-entrypoint.sh +30 -0
  73. package/docs/adr/0001-stack-choice-single-vps.md +45 -0
  74. package/docs/adr/0002-digitalocean-over-hetzner.md +27 -0
  75. package/docs/adr/0003-cloudflare-origin-cert-over-letsencrypt.md +35 -0
  76. package/docs/adr/0004-amazonprimea-name-and-trademark-acceptance.md +45 -0
  77. package/docs/adr/0005-invisible-other-players-in-v1.md +37 -0
  78. package/docs/adr/0006-singleton-worldroom-plus-queueroom.md +30 -0
  79. package/docs/adr/0007-persistent-identity-via-localstorage-uuid.md +31 -0
  80. package/docs/adr/0008-family-based-tile-generation.md +86 -0
  81. package/docs/adr/0008-google-chat-oauth-user-auth.md +37 -0
  82. package/docs/adr/0009-autotile-architecture.md +181 -0
  83. package/docs/adr/0010-pms-architecture.md +70 -0
  84. package/docs/adr/0011-terrain-id-rendering-model.md +174 -0
  85. package/docs/adr/0012-ground-object-cell-split.md +208 -0
  86. package/docs/adr/0013-paths-as-object-overlays-with-autotile-dispatch.md +158 -0
  87. package/docs/adr/0014-families-canonical-over-vocabulary.md +103 -0
  88. package/docs/adr/0015-task-dependencies-and-auto-promotion.md +125 -0
  89. package/docs/adr/0016-trust-boundary-server-enforced-permissions.md +132 -0
  90. package/docs/adr/0017-code-simplification-and-repo-cleanliness.md +74 -0
  91. package/docs/adr/0018-three-rank-model-goes-live.md +97 -0
  92. package/docs/adr/0019-red-team-bounty-payout-table.md +52 -0
  93. package/docs/adr/0020-security-model-public-stub.md +70 -0
  94. package/docs/adr/0021-per-builder-skill-model-preferences.md +99 -0
  95. package/docs/adr/0022-secrets-policy.md +124 -0
  96. package/docs/adr/0023-kind-multipliers-and-idea-bonus.md +118 -0
  97. package/docs/adr/0024-cloneable-repo-local-first-memory.md +277 -0
  98. package/docs/adr/0024-multi-agent-system-architecture.md +125 -0
  99. package/docs/adr/0025-offsite-backup-vendor-digitalocean-spaces.md +59 -0
  100. package/docs/adr/0025-structured-criterion-task-link.md +44 -0
  101. package/docs/adr/0026-bfg-memory-hygiene-and-cross-builder-learning.md +117 -0
  102. package/docs/adr/0027-bfg-session-inefficiency-evaluator.md +170 -0
  103. package/docs/adr/0028-honest-llm-spend-accounting.md +109 -0
  104. package/docs/adr/0029-status-page-outage-resilience.md +59 -0
  105. package/docs/adr/0030-builders-hall-live-updates.md +59 -0
  106. package/docs/adr/0031-cloud-dev-environments-for-builders.md +222 -0
  107. package/docs/adr/0032-discord-mirror-of-gds.md +50 -0
  108. package/docs/adr/0033-discord-bot-service-principal.md +82 -0
  109. package/docs/adr/0034-thetes-graduated-newcomer-rank.md +53 -0
  110. package/docs/adr/0035-builder-onboarding-three-paths.md +128 -0
  111. package/docs/adr/0036-builders-subdomain-and-ui-reorg.md +40 -0
  112. package/docs/adr/0037-discord-channel-management.md +51 -0
  113. package/docs/adr/0038-chromebook-ttyd-cloudflare-tunnel.md +111 -0
  114. package/docs/adr/0039-setup-first-onboarding-ux.md +49 -0
  115. package/docs/adr/0040-remote-control-default-browser-onramp.md +47 -0
  116. package/docs/adr/0041-temporary-grader-bypass-killswitch.md +40 -0
  117. package/docs/adr/0042-builder-self-deploy-ci-auto-merge.md +82 -0
  118. package/docs/adr/0043-git-ssh-trust-boundary-and-rank-floor-on-permission-paths.md +74 -0
  119. package/docs/adr/0044-mediterranean-palette-replacement.md +73 -0
  120. package/docs/adr/0044-per-box-live-game-preview.md +57 -0
  121. package/docs/adr/0045-devbox-desktop-app.md +133 -0
  122. package/docs/adr/0046-sandbox-first-review-gate.md +72 -0
  123. package/docs/adr/0047-discord-bugs-intake-anti-abuse.md +36 -0
  124. package/docs/adr/0048-works-in-progress-ia-split.md +32 -0
  125. package/docs/adr/0049-split-parallel-safety-contract.md +46 -0
  126. package/docs/adr/0050-device-flow-admission-invite-gated-by-default.md +43 -0
  127. package/docs/adr/0051-full-session-transcript-corpus.md +57 -0
  128. package/docs/adr/0052-sandbox-for-everyone-game-only-preview.md +70 -0
  129. package/docs/adr/0053-scoped-dev-box-session.md +55 -0
  130. package/docs/adr/0054-session-token-reward-cost-plus.md +63 -0
  131. package/docs/adr/0055-server-mediated-branch-publish.md +47 -0
  132. package/docs/adr/0056-prod-deploy-script-mirror-and-healthcheck-retry.md +62 -0
  133. package/docs/adr/0057-container-cost-ledger.md +28 -0
  134. package/docs/adr/0057-discord-archon-approval-channels.md +64 -0
  135. package/docs/adr/0058-automatic-gate-surface-gatekeeper.md +64 -0
  136. package/docs/adr/0059-single-approval-remove-devbox-approval-gate.md +37 -0
  137. package/docs/adr/0060-gds-retrieval-layer.md +97 -0
  138. package/docs/adr/0061-context-layer-decomposition.md +61 -0
  139. package/docs/adr/0062-medusa-instance-model-decoupling.md +107 -0
  140. package/docs/adr/0063-generated-repo-map-symbol-skeleton.md +44 -0
  141. package/docs/adr/0064-rename-medusa-to-cloud-bongos.md +49 -0
  142. package/docs/adr/0065-agpl-nonprofit-ai-first-governance.md +69 -0
  143. package/docs/adr/0066-generated-file-map-sections.md +51 -0
  144. package/docs/adr/0067-session-start-fast-forward-pull.md +43 -0
  145. package/docs/adr/0068-shared-art-key-for-newcomers.md +38 -0
  146. package/docs/adr/0069-hall-live-channel-sse-decouple.md +35 -0
  147. package/docs/adr/0070-deterministic-session-card-delivery.md +44 -0
  148. package/docs/adr/0071-box-confirm-before-destroyed-and-drift-reconcile.md +59 -0
  149. package/docs/adr/0072-bongos-app-mac-signed-first-windows-deferred.md +35 -0
  150. package/docs/adr/0072-dev-box-code-staleness-visibility.md +39 -0
  151. package/docs/adr/0073-builder-needs-signal-and-byok-gemini-key.md +64 -0
  152. package/docs/adr/0073-secrets-scan-exclude-uri-detector.md +37 -0
  153. package/docs/adr/0074-memory-map-stays-light.md +32 -0
  154. package/docs/adr/0075-per-system-cost-attribution.md +37 -0
  155. package/docs/adr/0076-in-session-deterministic-compaction.md +58 -0
  156. package/docs/adr/0077-content-addressed-llm-cache.md +32 -0
  157. package/docs/adr/0078-deterministic-first-cron.md +48 -0
  158. package/docs/adr/0079-value-gated-autonomous-engagement.md +39 -0
  159. package/docs/adr/0080-llm-cache-api-transport-and-trust-model.md +46 -0
  160. package/docs/adr/0081-tool-agnostic-design-layer.md +62 -0
  161. package/docs/adr/0082-productized-key-storage-provisioning.md +32 -0
  162. package/docs/adr/0082-server-side-merge-conflict-auto-resolution.md +55 -0
  163. package/docs/adr/0083-modular-architecture-strangler-build-plan.md +143 -0
  164. package/docs/adr/0084-auto-derived-per-task-rank-floor.md +86 -0
  165. package/docs/adr/0085-remove-default-per-builder-spend-cap.md +39 -0
  166. package/docs/adr/0086-goal-scoped-work-hierarchy.md +123 -0
  167. package/docs/adr/0087-bongos-app-architecture-and-handoff-contract.md +49 -0
  168. package/docs/adr/0087-compete-on-governance-not-tooling-cursor.md +65 -0
  169. package/docs/adr/0088-consistent-character-generative-animation.md +169 -0
  170. package/docs/adr/0089-modular-multi-model-adversarial-grader.md +179 -0
  171. package/docs/adr/0090-metic-task-authoring.md +73 -0
  172. package/docs/adr/0091-bounding-the-kernel-and-db-carve.md +106 -0
  173. package/docs/adr/0092-hosting-module-and-on-prem-target.md +117 -0
  174. package/docs/adr/0093-tranche-2-core-carve-sequence.md +72 -0
  175. package/docs/adr/0094-repo-atlas-self-drawing-codebase-map.md +49 -0
  176. package/docs/adr/0095-borrowed-memory-and-retrieval-concepts.md +65 -0
  177. package/docs/adr/0095-cross-agent-context-management.md +58 -0
  178. package/docs/adr/0096-require-reward-before-workable.md +209 -0
  179. package/docs/adr/0097-one-active-claim-per-session-and-worktree-binding.md +46 -0
  180. package/docs/adr/0097-retroactive-reward-backfill.md +124 -0
  181. package/docs/adr/0098-public-mirror-publish-manifest.md +92 -0
  182. package/docs/adr/0099-delayed-redacted-mirror-export.md +55 -0
  183. package/docs/adr/0100-two-repo-instance-model.md +60 -0
  184. package/docs/adr/0101-goal-hierarchy-phase-5-judge-membership-reward.md +90 -0
  185. package/docs/adr/0102-finish-bounding-the-kernel.md +36 -0
  186. package/docs/adr/0103-core-first-extraction-cloud-bongos-trunk.md +70 -0
  187. package/docs/adr/0103-gdsv4-bongos-consolidation.md +28 -0
  188. package/docs/adr/0104-trust-gds-api-channel-in-auto-mode.md +42 -0
  189. package/docs/adr/0105-instance-seed-migrations-out-of-core.md +47 -0
  190. package/docs/adr/0106-goal-owner-manager-authority.md +84 -0
  191. package/docs/adr/0107-module-upstreaming-contribution-to-core-catalog.md +83 -0
  192. package/docs/adr/0108-instance-composition-configurable-root.md +87 -0
  193. package/docs/adr/0109-self-describing-openapi-and-hosted-docs.md +44 -0
  194. package/docs/adr/0110-untrack-whole-file-generated-nav-docs.md +49 -0
  195. package/docs/adr/0111-instance-hosting-provisioning-module.md +135 -0
  196. package/docs/adr/0112-private-goals-invitations-join-requests.md +72 -0
  197. package/docs/adr/0113-sandbox-studio-descope-superseded-by-0044-0052.md +41 -0
  198. package/docs/adr/0114-instance-docs-discovery-contract.md +32 -0
  199. package/docs/adr/0115-scheduled-routines-portability.md +31 -0
  200. package/docs/adr/0116-api-error-envelope-and-code-taxonomy.md +62 -0
  201. package/docs/adr/0117-api-versioning-and-deprecation-policy.md +50 -0
  202. package/docs/adr/0118-api-contract-source-of-truth-code-first.md +47 -0
  203. package/docs/adr/0119-api-pagination-contract.md +34 -0
  204. package/docs/adr/0120-pay-on-land-and-builder-owned-rebase-gate.md +108 -0
  205. package/docs/adr/0121-greenfield-vs-brownfield-onboarding-adopt-existing-repo.md +97 -0
  206. package/docs/adr/0122-onboarding-diagram-renders-deploy-rendered-off-git.md +43 -0
  207. package/docs/adr/0123-box-idle-sweep-autosave-before-destroy.md +36 -0
  208. package/docs/adr/0124-typed-api-response-bodies.md +37 -0
  209. package/docs/adr/0125-control-plane-scaffolds-standalone-instance-repo.md +36 -0
  210. package/docs/adr/0126-dedicated-cloudbongos-control-plane-droplet.md +30 -0
  211. package/docs/adr/0127-cross-box-fleet-observability.md +64 -0
  212. package/docs/adr/0128-provisioning-runner-privilege-and-db-auth-model.md +46 -0
  213. package/docs/adr/0129-cloudbongos-control-plane-pull-deploy.md +34 -0
  214. package/docs/adr/0130-provision-remote-exec-over-ssh.md +61 -0
  215. package/docs/adr/0131-rank-scoped-skill-visibility.md +47 -0
  216. package/docs/adr/0132-cohost-fleet-control-plane-migration.md +54 -0
  217. package/docs/adr/0133-github-app-manifest-onboarding-signin.md +42 -0
  218. package/docs/adr/0134-private-first-npm-distribution.md +38 -0
  219. package/docs/adr/README.md +208 -0
  220. package/docs/api/openapi.json +13720 -0
  221. package/docs/api-reference.md +437 -0
  222. package/docs/architecture.md +244 -0
  223. package/docs/branding-contract.md +66 -0
  224. package/docs/branding-fill-prompt.md +25 -0
  225. package/docs/canonical-permissions.md +241 -0
  226. package/docs/design/container-exterior-tiles.md +49 -0
  227. package/docs/design/container-exterior.md +81 -0
  228. package/docs/design/container-interior.md +77 -0
  229. package/docs/design/modular-architecture/00-research-report.md +107 -0
  230. package/docs/design/modular-architecture/01-architecture.md +125 -0
  231. package/docs/design/modular-architecture/02-module-map.md +116 -0
  232. package/docs/design/modular-architecture/03-builder-flows.md +104 -0
  233. package/docs/design/modular-architecture/04-module-lifecycle.md +62 -0
  234. package/docs/design/modular-architecture/README.md +27 -0
  235. package/docs/design/vanilla-hall-ui-redesign-scope.md +284 -0
  236. package/docs/design/world-map-scroll.md +41 -0
  237. package/docs/design-contract.md +320 -0
  238. package/docs/file-map.md +418 -0
  239. package/docs/handoff-template.md +92 -0
  240. package/docs/modules-contract.md +293 -0
  241. package/docs/onboarding/browser-terminal-guide.md +73 -0
  242. package/docs/onboarding/diagrams/01-task-lifecycle.mmd +28 -0
  243. package/docs/onboarding/diagrams/02-rank-ladder.mmd +54 -0
  244. package/docs/onboarding/diagrams/03-drachmae-karma.mmd +37 -0
  245. package/docs/onboarding/diagrams/04-architecture.mmd +51 -0
  246. package/docs/onboarding/diagrams/05-versioning.mmd +29 -0
  247. package/docs/onboarding/diagrams/README.md +94 -0
  248. package/docs/onboarding/diagrams/assertions.json +170 -0
  249. package/docs/onboarding/diagrams/puppeteer-config.json +1 -0
  250. package/docs/onboarding/diagrams/render-config.json +9 -0
  251. package/docs/onboarding/drachmae-and-karma.md +178 -0
  252. package/docs/onboarding/primer.md +202 -0
  253. package/docs/project-context.template.md +67 -0
  254. package/docs/recipes/README.md +35 -0
  255. package/docs/recipes/audit-replay.md +100 -0
  256. package/docs/recipes/bongos-cli-release.md +66 -0
  257. package/docs/recipes/builder-box-lifecycle.md +152 -0
  258. package/docs/recipes/claude-design-loop.md +143 -0
  259. package/docs/recipes/claude-gemini-bongos-doors.md +155 -0
  260. package/docs/recipes/cloudbongos-staging-gate.md +139 -0
  261. package/docs/recipes/cloudbongos-standup.md +111 -0
  262. package/docs/recipes/devbox-app-release.md +93 -0
  263. package/docs/recipes/devbox-app-windows-test.md +128 -0
  264. package/docs/recipes/failed-ship-recovery-proof.md +102 -0
  265. package/docs/recipes/figma-design-loop.md +129 -0
  266. package/docs/recipes/gds-db-backup.md +255 -0
  267. package/docs/recipes/instance-deploy.md +37 -0
  268. package/docs/recipes/managed-settings-remote-control.md +416 -0
  269. package/docs/recipes/memory-backup.md +71 -0
  270. package/docs/recipes/memory-sync-conflicts.md +98 -0
  271. package/docs/recipes/multi-builder-merge.md +78 -0
  272. package/docs/recipes/ops-gotchas.md +212 -0
  273. package/docs/recipes/overnight-builder.md +53 -0
  274. package/docs/recipes/packaging-the-core.md +49 -0
  275. package/docs/recipes/parallel-load-results-2026-05-30.md +63 -0
  276. package/docs/recipes/parallel-load-test.md +32 -0
  277. package/docs/recipes/pixel-art-pipeline.md +411 -0
  278. package/docs/recipes/private-npm-distribution.md +79 -0
  279. package/docs/recipes/search-index-ingestion.md +67 -0
  280. package/docs/recipes/self-host.md +60 -0
  281. package/docs/recipes/ship-and-regrade.md +72 -0
  282. package/docs/recipes/staging-data.md +50 -0
  283. package/docs/recipes/staging-environment.md +215 -0
  284. package/docs/recipes/upgrading-the-core.md +58 -0
  285. package/docs/research/cursor-competitive-analysis.md +255 -0
  286. package/docs/research/llm-model-agnostic-and-cheaper-grader.md +227 -0
  287. package/migrations/003_pms.sql +284 -0
  288. package/migrations/004_pms_cost_idempotency.sql +13 -0
  289. package/migrations/005_pms_smoke_filter.sql +44 -0
  290. package/migrations/006_pms_v2.sql +378 -0
  291. package/migrations/007_pms_v2_hierarchy_trigger.sql +59 -0
  292. package/migrations/008_pms_v2_migration_allocator.sql +27 -0
  293. package/migrations/009_pms_v2_blockers_table.sql +68 -0
  294. package/migrations/010_uptime.sql +29 -0
  295. package/migrations/011_backfill_v2_v3_done_when.sql +20 -0
  296. package/migrations/012_pms_v2_task_lifecycle_states.sql +82 -0
  297. package/migrations/013_claim_locking.sql +22 -0
  298. package/migrations/014_pms_task_discipline.sql +86 -0
  299. package/migrations/015_pms_estimation_calibration.sql +140 -0
  300. package/migrations/016_pms_task_grades.sql +60 -0
  301. package/migrations/017_version_progress_exclude_abandoned.sql +49 -0
  302. package/migrations/019_rename_pms_v3_to_gds_v3.sql +65 -0
  303. package/migrations/020_task_dependencies.sql +99 -0
  304. package/migrations/021_v3_renumber_and_deps.sql +224 -0
  305. package/migrations/022_v3_reconcile_dep_gated_status.sql +41 -0
  306. package/migrations/023_pms_rank.sql +30 -0
  307. package/migrations/025_builder_exit_status.sql +15 -0
  308. package/migrations/027_builders_preferred_disciplines.sql +46 -0
  309. package/migrations/028_tasks_parallel_safe.sql +71 -0
  310. package/migrations/029_rank_three_live.sql +32 -0
  311. package/migrations/030_vulnerability_reports.sql +61 -0
  312. package/migrations/031_reward_simplification.sql +57 -0
  313. package/migrations/032_repo_health_snapshots.sql +56 -0
  314. package/migrations/033_audit_log.sql +64 -0
  315. package/migrations/034_lifecycle_breakdown_leaf_only.sql +62 -0
  316. package/migrations/035_auth_token_hygiene.sql +66 -0
  317. package/migrations/037_builder_skill_model_prefs.sql +44 -0
  318. package/migrations/038_task_override_requests.sql +51 -0
  319. package/migrations/039_newcomer_friendly_column.sql +124 -0
  320. package/migrations/040_builder_karma.sql +58 -0
  321. package/migrations/041_kind_multipliers_and_idea_bonus.sql +42 -0
  322. package/migrations/042_criterion_proposal_workflow.sql +78 -0
  323. package/migrations/043_builder_onboarding_observability.sql +66 -0
  324. package/migrations/044_tasks_requires_rank.sql +97 -0
  325. package/migrations/045_builder_onboarding_state.sql +147 -0
  326. package/migrations/046_cost_log_builder_attribution.sql +42 -0
  327. package/migrations/054_builder_memory.sql +108 -0
  328. package/migrations/055_task_criteria.sql +90 -0
  329. package/migrations/058_peer_votes.sql +41 -0
  330. package/migrations/059_onboarding_pick_disciplines.sql +59 -0
  331. package/migrations/060_access_requests.sql +46 -0
  332. package/migrations/061_backfill_override_ship_attribution.sql +29 -0
  333. package/migrations/062_session_records.sql +34 -0
  334. package/migrations/063_session_records_tool_errors_idx.sql +11 -0
  335. package/migrations/064_grade_attempts.sql +18 -0
  336. package/migrations/065_bfg_principal.sql +58 -0
  337. package/migrations/066_live_notify_triggers.sql +69 -0
  338. package/migrations/067_builder_boxes.sql +117 -0
  339. package/migrations/067_discord_bot_foundation.sql +69 -0
  340. package/migrations/068_thetes_requires_rank.sql +27 -0
  341. package/migrations/069_builder_ssh_keys.sql +66 -0
  342. package/migrations/070_box_intents.sql +101 -0
  343. package/migrations/071_box_first_provision_approval.sql +46 -0
  344. package/migrations/072_onboarding_ship_three_remove_primer.sql +80 -0
  345. package/migrations/073_box_terminal_access.sql +46 -0
  346. package/migrations/075_builder_sound_prefs.sql +28 -0
  347. package/migrations/078_box_claude_active.sql +22 -0
  348. package/migrations/079_box_first_connected_at.sql +20 -0
  349. package/migrations/081_tasks_needs_migration.sql +34 -0
  350. package/migrations/084_tasks_security_sensitive.sql +24 -0
  351. package/migrations/085_security_engagement_docs.sql +34 -0
  352. package/migrations/086_rename_disciplines.sql +125 -0
  353. package/migrations/088_builders_anthropic_link.sql +28 -0
  354. package/migrations/089_builders_monthly_budget.sql +19 -0
  355. package/migrations/090_box_scoped_sessions.sql +38 -0
  356. package/migrations/091_session_token_reward.sql +44 -0
  357. package/migrations/093_tasks_sandbox_review.sql +22 -0
  358. package/migrations/102_remove_box_first_provision_approval.sql +58 -0
  359. package/migrations/103_search_chunks.sql +90 -0
  360. package/migrations/104_builder_box_blocked.sql +34 -0
  361. package/migrations/105_box_host_keys.sql +35 -0
  362. package/migrations/111_medusa_customer0_framing.sql +35 -0
  363. package/migrations/112_drop_track_check.sql +25 -0
  364. package/migrations/113_merge_lease.sql +16 -0
  365. package/migrations/114_cloudbongos_rename_live_strings.sql +32 -0
  366. package/migrations/118_currency_label_decoupling.sql +23 -0
  367. package/migrations/119_builder_behavior_prefs.sql +31 -0
  368. package/migrations/121_box_code_version.sql +37 -0
  369. package/migrations/122_builder_gemini_key.sql +30 -0
  370. package/migrations/123_cost_log_tiers.sql +33 -0
  371. package/migrations/124_cost_baseline.sql +45 -0
  372. package/migrations/125_llm_cache.sql +54 -0
  373. package/migrations/126_autonomy_runs.sql +33 -0
  374. package/migrations/143_cost_calibration.sql +63 -0
  375. package/migrations/145_backfill_task_requires_rank.sql +84 -0
  376. package/migrations/160_goal_tier.sql +88 -0
  377. package/migrations/163_polymorphic_dependencies.sql +187 -0
  378. package/migrations/164_event_sound_prefs.sql +20 -0
  379. package/migrations/165_task_module_key.sql +15 -0
  380. package/migrations/171_claims_published_head_sha.sql +24 -0
  381. package/migrations/174_close_orphaned_claims_on_terminal_tasks.sql +30 -0
  382. package/migrations/175_task_grades_diff_hash.sql +9 -0
  383. package/migrations/176_promotion_respects_open_blockers.sql +58 -0
  384. package/migrations/176_ui_discipline.sql +40 -0
  385. package/migrations/177_require_reward_before_workable.sql +76 -0
  386. package/migrations/178_reward_gate_auto_assign_revert_autopromote.sql +61 -0
  387. package/migrations/179_search_chunk_usefulness.sql +33 -0
  388. package/migrations/180_one_active_claim_per_session.sql +54 -0
  389. package/migrations/181_cost_log_skill_name.sql +33 -0
  390. package/migrations/184_claim_release_requested.sql +25 -0
  391. package/migrations/185_module_upstreaming_goal_wiring.sql +59 -0
  392. package/migrations/187_goal_sort_order.sql +30 -0
  393. package/migrations/187_tasks_kind_check_add_verify.sql +21 -0
  394. package/migrations/README.md +88 -0
  395. package/migrations/core_188_goal_visibility_and_membership_requests.sql +71 -0
  396. package/migrations/core_189_core_upgrades_ledger.sql +37 -0
  397. package/migrations/core_189_credit_log_task_id_index.sql +19 -0
  398. package/migrations/core_190_rebuild_claimable_task_views.sql +71 -0
  399. package/migrations/instance/018_pms_v3_planning_seed.sql +131 -0
  400. package/migrations/instance/080_gds_v4_planning_seed.sql +75 -0
  401. package/migrations/instance/110_medusa_planning_seed.sql +70 -0
  402. package/migrations/instance/120_bongos_v1_planning_seed.sql +69 -0
  403. package/migrations/instance/144_bongos_v1_module_system_criterion.sql +26 -0
  404. package/migrations/instance/159_bongos_v1_goal_hierarchy_criterion.sql +29 -0
  405. package/migrations/instance/172_v2_world_planning_seed.sql +163 -0
  406. package/migrations/instance/173_bongos_v1_c7_core_modularized.sql +33 -0
  407. package/migrations/instance/182_gdsv4_bongos_consolidation.sql +132 -0
  408. package/migrations/instance/183_gdsv4_carryover_themed_goals.sql +116 -0
  409. package/migrations/instance/186_bongos_v1_governance_planning_seed.sql +69 -0
  410. package/modules/autonomy/CLAUDE.md +49 -0
  411. package/modules/autonomy/db.js +50 -0
  412. package/modules/autonomy/module.json +13 -0
  413. package/modules/autonomy/pollers/routine-timers.js +146 -0
  414. package/modules/autonomy/routes/autonomy.js +37 -0
  415. package/modules/builder-settings/CLAUDE.md +58 -0
  416. package/modules/builder-settings/builder-needs.js +115 -0
  417. package/modules/builder-settings/db.js +168 -0
  418. package/modules/builder-settings/display-name.js +84 -0
  419. package/modules/builder-settings/event-sound-prefs.js +169 -0
  420. package/modules/builder-settings/interaction-prefs.js +201 -0
  421. package/modules/builder-settings/model-alloc-prefs.js +147 -0
  422. package/modules/builder-settings/module.json +10 -0
  423. package/modules/builder-settings/render-prefs.js +103 -0
  424. package/modules/builder-settings/routes/settings.js +417 -0
  425. package/modules/builder-settings/settings.js +52 -0
  426. package/modules/builder-settings/skill-prefs.js +196 -0
  427. package/modules/builder-settings/sound-prefs.js +178 -0
  428. package/modules/builder-settings/wandering-prefs.js +282 -0
  429. package/modules/dev-box/CLAUDE.md +38 -0
  430. package/modules/dev-box/box-access.js +275 -0
  431. package/modules/dev-box/box-credential.js +94 -0
  432. package/modules/dev-box/box-onboard.js +486 -0
  433. package/modules/dev-box/boxes.js +842 -0
  434. package/modules/dev-box/db.js +39 -0
  435. package/modules/dev-box/module.json +14 -0
  436. package/modules/dev-box/routes/box.js +977 -0
  437. package/modules/discord/CLAUDE.md +50 -0
  438. package/modules/discord/auth.js +54 -0
  439. package/modules/discord/bug-attachments.js +210 -0
  440. package/modules/discord/db.js +96 -0
  441. package/modules/discord/discord-approvals.js +145 -0
  442. package/modules/discord/discord-audit.js +29 -0
  443. package/modules/discord/discord-bot.js +545 -0
  444. package/modules/discord/discord-bugs.js +257 -0
  445. package/modules/discord/discord-channels.js +412 -0
  446. package/modules/discord/discord-inbound.js +147 -0
  447. package/modules/discord/discord-message-buffer.js +54 -0
  448. package/modules/discord/discord-reaction.js +186 -0
  449. package/modules/discord/discord-role-sync.js +318 -0
  450. package/modules/discord/module.json +14 -0
  451. package/modules/discord/pollers/discord-bot.js +19 -0
  452. package/modules/discord/routes/bug-attachments.js +44 -0
  453. package/modules/discord/routes/discord.js +102 -0
  454. package/modules/discord/ship-broadcast.js +78 -0
  455. package/modules/discord/webhook.js +74 -0
  456. package/modules/economy/CLAUDE.md +48 -0
  457. package/modules/economy/achievements.js +594 -0
  458. package/modules/economy/cost-classify.js +331 -0
  459. package/modules/economy/cost-summary-shape.js +90 -0
  460. package/modules/economy/cost.js +438 -0
  461. package/modules/economy/credits.js +430 -0
  462. package/modules/economy/migrations/economy_001_fix_gds_shipper_description.sql +91 -0
  463. package/modules/economy/module.json +10 -0
  464. package/modules/economy/reward.js +61 -0
  465. package/modules/economy/routes/cost.js +97 -0
  466. package/modules/economy/routes/leaderboard.js +26 -0
  467. package/modules/economy/routes/reward.js +42 -0
  468. package/modules/economy/streak.js +285 -0
  469. package/modules/grading/CLAUDE.md +42 -0
  470. package/modules/grading/db.js +39 -0
  471. package/modules/grading/grader-rubric.json +151 -0
  472. package/modules/grading/grader-workers/efficiency.js +213 -0
  473. package/modules/grading/grader-workers/extract-json.js +80 -0
  474. package/modules/grading/grader-workers/fence.js +100 -0
  475. package/modules/grading/grader-workers/hacker.js +239 -0
  476. package/modules/grading/grader-workers/index.js +183 -0
  477. package/modules/grading/grader-workers/narc.js +207 -0
  478. package/modules/grading/grader-workers/quality.js +198 -0
  479. package/modules/grading/grader-workers/rubric.js +20 -0
  480. package/modules/grading/grader-workers/worker-prompt.js +89 -0
  481. package/modules/grading/grader-workers/worker-verdict.js +50 -0
  482. package/modules/grading/grader.js +1790 -0
  483. package/modules/grading/module.json +12 -0
  484. package/modules/grading/routes/grade.js +51 -0
  485. package/modules/hall-ui/CLAUDE.md +61 -0
  486. package/modules/hall-ui/module.json +14 -0
  487. package/modules/hall-ui/public/atlas.html +180 -0
  488. package/modules/hall-ui/public/atlas.js +336 -0
  489. package/modules/hall-ui/public/box-panel.js +423 -0
  490. package/modules/hall-ui/public/brand-apply.js +117 -0
  491. package/modules/hall-ui/public/builders.js +3028 -0
  492. package/modules/hall-ui/public/chime.wav +0 -0
  493. package/modules/hall-ui/public/copy-on-click.js +174 -0
  494. package/modules/hall-ui/public/cursors/arrow.png +0 -0
  495. package/modules/hall-ui/public/cursors/hand-pointer.png +0 -0
  496. package/modules/hall-ui/public/cursors/magnifier-out.png +0 -0
  497. package/modules/hall-ui/public/cursors/magnifier.png +0 -0
  498. package/modules/hall-ui/public/diagram-viewer.css +125 -0
  499. package/modules/hall-ui/public/diagram-viewer.js +330 -0
  500. package/modules/hall-ui/public/diagrams.html +113 -0
  501. package/modules/hall-ui/public/dom-utils.js +212 -0
  502. package/modules/hall-ui/public/drachmae.html +68 -0
  503. package/modules/hall-ui/public/drachmae.js +136 -0
  504. package/modules/hall-ui/public/gate.html +143 -0
  505. package/modules/hall-ui/public/gate.js +228 -0
  506. package/modules/hall-ui/public/goals-page.js +1297 -0
  507. package/modules/hall-ui/public/goals.html +376 -0
  508. package/modules/hall-ui/public/goals.js +119 -0
  509. package/modules/hall-ui/public/hall-widgets.js +189 -0
  510. package/modules/hall-ui/public/harbor.html +167 -0
  511. package/modules/hall-ui/public/harbor.js +335 -0
  512. package/modules/hall-ui/public/index.html +116 -0
  513. package/modules/hall-ui/public/instances-panel.js +172 -0
  514. package/modules/hall-ui/public/md-reader.js +234 -0
  515. package/modules/hall-ui/public/modules.html +119 -0
  516. package/modules/hall-ui/public/modules.js +154 -0
  517. package/modules/hall-ui/public/new-project-wizard.js +186 -0
  518. package/modules/hall-ui/public/not-ready.html +48 -0
  519. package/modules/hall-ui/public/pair.html +119 -0
  520. package/modules/hall-ui/public/pair.js +132 -0
  521. package/modules/hall-ui/public/primer.css +404 -0
  522. package/modules/hall-ui/public/primer.html +85 -0
  523. package/modules/hall-ui/public/primer.js +641 -0
  524. package/modules/hall-ui/public/profile.html +85 -0
  525. package/modules/hall-ui/public/profile.js +236 -0
  526. package/modules/hall-ui/public/ranks.html +69 -0
  527. package/modules/hall-ui/public/ranks.js +206 -0
  528. package/modules/hall-ui/public/roadmap.html +209 -0
  529. package/modules/hall-ui/public/roadmap.js +375 -0
  530. package/modules/hall-ui/public/sessions.html +92 -0
  531. package/modules/hall-ui/public/sessions.js +222 -0
  532. package/modules/hall-ui/public/settings.html +640 -0
  533. package/modules/hall-ui/public/settings.js +1219 -0
  534. package/modules/hall-ui/public/shell.js +495 -0
  535. package/modules/hall-ui/public/style.css +1748 -0
  536. package/modules/hall-ui/public/task-detail.js +253 -0
  537. package/modules/hall-ui/public/task.html +83 -0
  538. package/modules/hall-ui/public/task.js +326 -0
  539. package/modules/hall-ui/public/watch.html +333 -0
  540. package/modules/hall-ui/public/watch.js +859 -0
  541. package/modules/hall-ui/public/work.html +469 -0
  542. package/modules/hall-ui/public/work.js +1292 -0
  543. package/modules/ideas/CLAUDE.md +37 -0
  544. package/modules/ideas/blockers.js +100 -0
  545. package/modules/ideas/inbox.js +459 -0
  546. package/modules/ideas/module.json +10 -0
  547. package/modules/ideas/routes/blockers.js +120 -0
  548. package/modules/ideas/routes/inbox.js +230 -0
  549. package/modules/lifecycle/CLAUDE.md +63 -0
  550. package/modules/lifecycle/conflict-resolve.js +436 -0
  551. package/modules/lifecycle/db.js +4970 -0
  552. package/modules/lifecycle/done-when.js +355 -0
  553. package/modules/lifecycle/github-push.js +969 -0
  554. package/modules/lifecycle/goal-conflicts.js +133 -0
  555. package/modules/lifecycle/hierarchy.js +104 -0
  556. package/modules/lifecycle/lifecycle.js +58 -0
  557. package/modules/lifecycle/merge-lock.js +261 -0
  558. package/modules/lifecycle/migrations/lifecycle_001_goal_first_leads.sql +28 -0
  559. package/modules/lifecycle/migrations/lifecycle_002_backfill_orphan_task_goals.sql +36 -0
  560. package/modules/lifecycle/module.json +13 -0
  561. package/modules/lifecycle/pollers/publish-reconciler.js +20 -0
  562. package/modules/lifecycle/publish-reconciler.js +418 -0
  563. package/modules/lifecycle/routes/analytics.js +63 -0
  564. package/modules/lifecycle/routes/claims.js +506 -0
  565. package/modules/lifecycle/routes/dependencies.js +82 -0
  566. package/modules/lifecycle/routes/done-when.js +136 -0
  567. package/modules/lifecycle/routes/gate-approvals.js +197 -0
  568. package/modules/lifecycle/routes/goals.js +1419 -0
  569. package/modules/lifecycle/routes/lifecycle.js +43 -0
  570. package/modules/lifecycle/routes/tasks.js +1703 -0
  571. package/modules/lifecycle/routes/versions.js +128 -0
  572. package/modules/lifecycle/ship-card.js +505 -0
  573. package/modules/lifecycle/ship-preflight.js +225 -0
  574. package/modules/lifecycle/task-classifier.js +512 -0
  575. package/modules/lifecycle/version-close.js +106 -0
  576. package/modules/memory/CLAUDE.md +40 -0
  577. package/modules/memory/learnings.js +275 -0
  578. package/modules/memory/memory.js +572 -0
  579. package/modules/memory/module.json +12 -0
  580. package/modules/memory/routes/learnings.js +90 -0
  581. package/modules/memory/routes/memory.js +916 -0
  582. package/modules/memory/routes/search.js +188 -0
  583. package/modules/memory/search-chunker.js +252 -0
  584. package/modules/memory/search.js +320 -0
  585. package/modules/onboarding/CLAUDE.md +55 -0
  586. package/modules/onboarding/approval-broadcast.js +59 -0
  587. package/modules/onboarding/db.js +54 -0
  588. package/modules/onboarding/module.json +10 -0
  589. package/modules/onboarding/newcomer-restock.js +212 -0
  590. package/modules/onboarding/onboarding-state.js +532 -0
  591. package/modules/onboarding/onboarding.js +508 -0
  592. package/modules/onboarding/port.js +63 -0
  593. package/modules/onboarding/routes/access-requests.js +208 -0
  594. package/modules/onboarding/routes/onboarding.js +54 -0
  595. package/modules/security/CLAUDE.md +44 -0
  596. package/modules/security/module.json +10 -0
  597. package/modules/security/routes/reports.js +251 -0
  598. package/modules/security/secret-scrub.js +201 -0
  599. package/modules/security/security.js +294 -0
  600. package/modules/sessions/CLAUDE.md +39 -0
  601. package/modules/sessions/bfg.js +357 -0
  602. package/modules/sessions/db.js +326 -0
  603. package/modules/sessions/module.json +10 -0
  604. package/modules/sessions/pulse.js +149 -0
  605. package/modules/sessions/routes/sessions.js +331 -0
  606. package/modules/status-ui/CLAUDE.md +47 -0
  607. package/modules/status-ui/module.json +14 -0
  608. package/modules/status-ui/public/README.md +29 -0
  609. package/modules/status-ui/public/cursors/arrow.png +0 -0
  610. package/modules/status-ui/public/cursors/hand-pointer.png +0 -0
  611. package/modules/status-ui/public/index.html +363 -0
  612. package/modules/status-ui/public/snapshots/.gitkeep +0 -0
  613. package/modules/status-ui/public/status.js +1375 -0
  614. package/modules/status-ui/public/style.css +1342 -0
  615. package/package-lock.json +975 -0
  616. package/package.json +28 -0
  617. package/public-docs/index.html +35 -0
  618. package/public-docs/redoc.standalone.js +1838 -0
  619. package/public-docs/redoc.standalone.js.LICENSE.txt +102 -0
  620. package/public-landing/buddha.png +0 -0
  621. package/public-landing/create.html +868 -0
  622. package/public-landing/index.html +168 -0
  623. package/scripts/bongos-mcp.js +28 -0
  624. package/scripts/cron/style_guide_audit.sh +134 -0
  625. package/scripts/discord/README.md +52 -0
  626. package/scripts/discord/lib.js +80 -0
  627. package/scripts/discord/post.js +51 -0
  628. package/scripts/gds/CLAUDE.md +144 -0
  629. package/scripts/gds/abandon.js +58 -0
  630. package/scripts/gds/adopt-detect.js +123 -0
  631. package/scripts/gds/adopt-import.js +111 -0
  632. package/scripts/gds/adopt-preflight.js +121 -0
  633. package/scripts/gds/api.js +78 -0
  634. package/scripts/gds/architect-audit.js +288 -0
  635. package/scripts/gds/art-stage.js +152 -0
  636. package/scripts/gds/audit-authorship.sh +243 -0
  637. package/scripts/gds/audit-deps.js +121 -0
  638. package/scripts/gds/audit-exports.js +128 -0
  639. package/scripts/gds/audit-replay.sh +161 -0
  640. package/scripts/gds/audit-ships.js +251 -0
  641. package/scripts/gds/autonomy-gate.js +135 -0
  642. package/scripts/gds/backfill-cost.js +165 -0
  643. package/scripts/gds/backfill-sessions.js +351 -0
  644. package/scripts/gds/backfill-task-rewards.js +408 -0
  645. package/scripts/gds/backup.js +94 -0
  646. package/scripts/gds/bfg-principal-token.js +65 -0
  647. package/scripts/gds/box-auth-check.js +160 -0
  648. package/scripts/gds/box-connect-lib.js +453 -0
  649. package/scripts/gds/box.js +1258 -0
  650. package/scripts/gds/build-bongos.js +94 -0
  651. package/scripts/gds/capture.js +123 -0
  652. package/scripts/gds/cf-tunnel.js +419 -0
  653. package/scripts/gds/ci-grade.js +82 -0
  654. package/scripts/gds/claim-recall.js +112 -0
  655. package/scripts/gds/claim.js +333 -0
  656. package/scripts/gds/classify-discipline.js +153 -0
  657. package/scripts/gds/claude-materialize.js +176 -0
  658. package/scripts/gds/cleanup-orphans.js +74 -0
  659. package/scripts/gds/cli-lib.js +518 -0
  660. package/scripts/gds/code.js +101 -0
  661. package/scripts/gds/codemod-rename-src-gds.js +145 -0
  662. package/scripts/gds/conductor-dispatch.js +426 -0
  663. package/scripts/gds/context-pack.js +228 -0
  664. package/scripts/gds/coreB-carve-proof.sh +716 -0
  665. package/scripts/gds/cost.js +47 -0
  666. package/scripts/gds/db-backup-nightly.sh +160 -0
  667. package/scripts/gds/db-backup-offsite.sh +152 -0
  668. package/scripts/gds/demote.js +40 -0
  669. package/scripts/gds/design-sync.js +62 -0
  670. package/scripts/gds/diagnose-achievements.js +118 -0
  671. package/scripts/gds/diagram-facts.js +319 -0
  672. package/scripts/gds/discipline-modes.json +25 -0
  673. package/scripts/gds/discord-channels.js +66 -0
  674. package/scripts/gds/do-api.js +176 -0
  675. package/scripts/gds/docs-entropy.js +403 -0
  676. package/scripts/gds/doctor.js +389 -0
  677. package/scripts/gds/feedback-latest.js +94 -0
  678. package/scripts/gds/fetch-art-key.js +106 -0
  679. package/scripts/gds/fetch-sound-prefs.js +88 -0
  680. package/scripts/gds/figma-design-sync.js +61 -0
  681. package/scripts/gds/fitness.js +1446 -0
  682. package/scripts/gds/gate-review.js +322 -0
  683. package/scripts/gds/gating.js +325 -0
  684. package/scripts/gds/gds-db-backup.service +24 -0
  685. package/scripts/gds/gds-db-backup.timer +20 -0
  686. package/scripts/gds/gds-db-offsite.service +29 -0
  687. package/scripts/gds/gds-db-offsite.timer +18 -0
  688. package/scripts/gds/gen-api-client.js +508 -0
  689. package/scripts/gds/gen-api-docs.js +1037 -0
  690. package/scripts/gds/gen-atlas.js +366 -0
  691. package/scripts/gds/gen-diagrams.js +608 -0
  692. package/scripts/gds/gen-file-map.js +196 -0
  693. package/scripts/gds/gen-repo-map.js +519 -0
  694. package/scripts/gds/gen-session-index.js +210 -0
  695. package/scripts/gds/git-merge-regen.js +147 -0
  696. package/scripts/gds/grade-smoke.js +205 -0
  697. package/scripts/gds/hooks/pre-push.js +169 -0
  698. package/scripts/gds/http-api-client.js +88 -0
  699. package/scripts/gds/init.js +903 -0
  700. package/scripts/gds/install-git-hooks.js +114 -0
  701. package/scripts/gds/key-card.js +213 -0
  702. package/scripts/gds/key-status.js +126 -0
  703. package/scripts/gds/land-watch.js +168 -0
  704. package/scripts/gds/learning-capture.js +145 -0
  705. package/scripts/gds/lib.sh +44 -0
  706. package/scripts/gds/linkify-refs.js +473 -0
  707. package/scripts/gds/local-preview-lib.js +159 -0
  708. package/scripts/gds/local-preview.js +95 -0
  709. package/scripts/gds/login.js +225 -0
  710. package/scripts/gds/main-audit.js +279 -0
  711. package/scripts/gds/me.js +88 -0
  712. package/scripts/gds/memory-map.js +174 -0
  713. package/scripts/gds/merge-lock.js +71 -0
  714. package/scripts/gds/migration-namespace.js +200 -0
  715. package/scripts/gds/mirror-lineage-check.js +319 -0
  716. package/scripts/gds/mirror-redact.js +305 -0
  717. package/scripts/gds/module.js +482 -0
  718. package/scripts/gds/newcomer-floor.config.json +13 -0
  719. package/scripts/gds/newcomer-floor.js +415 -0
  720. package/scripts/gds/newcomer-floor.templates.json +86 -0
  721. package/scripts/gds/newcomer-floor.test.js +235 -0
  722. package/scripts/gds/next-number.js +163 -0
  723. package/scripts/gds/oauth-secret.js +197 -0
  724. package/scripts/gds/onboard.js +217 -0
  725. package/scripts/gds/onboarding-analyze.js +226 -0
  726. package/scripts/gds/onboarding-config.js +178 -0
  727. package/scripts/gds/onboarding-ship.js +92 -0
  728. package/scripts/gds/package-core.js +684 -0
  729. package/scripts/gds/paste-token.js +131 -0
  730. package/scripts/gds/portability-smoke-art.sh +85 -0
  731. package/scripts/gds/portability-smoke-memory.sh +147 -0
  732. package/scripts/gds/provision.js +1324 -0
  733. package/scripts/gds/publish-manifest.js +307 -0
  734. package/scripts/gds/pulse.js +309 -0
  735. package/scripts/gds/push-main.js +45 -0
  736. package/scripts/gds/read-session-export.js +359 -0
  737. package/scripts/gds/reauth.js +149 -0
  738. package/scripts/gds/recall.js +135 -0
  739. package/scripts/gds/release.js +71 -0
  740. package/scripts/gds/render-ideas.js +173 -0
  741. package/scripts/gds/repo-metrics.js +363 -0
  742. package/scripts/gds/resolve-skill-model.js +57 -0
  743. package/scripts/gds/run-routine.js +197 -0
  744. package/scripts/gds/run-unit-tests.js +178 -0
  745. package/scripts/gds/sandbox-stage.js +653 -0
  746. package/scripts/gds/search-ingest-db.js +209 -0
  747. package/scripts/gds/search-ingest-md.js +225 -0
  748. package/scripts/gds/security-baseline-check.sh +180 -0
  749. package/scripts/gds/seed-adopt-tasks.js +75 -0
  750. package/scripts/gds/seed-api-contract-goal-tasks.js +141 -0
  751. package/scripts/gds/seed-bongos-app-tasks.js +294 -0
  752. package/scripts/gds/seed-bongos-coreB-tranche1-tasks.js +81 -0
  753. package/scripts/gds/seed-bongos-coreB-tranche2-tasks.js +100 -0
  754. package/scripts/gds/seed-bongos-goal-hierarchy-tasks.js +307 -0
  755. package/scripts/gds/seed-bongos-module-system-tasks.js +346 -0
  756. package/scripts/gds/seed-bongos-tasks.js +214 -0
  757. package/scripts/gds/seed-gds-v4-tasks.js +624 -0
  758. package/scripts/gds/seed-governance-tasks.js +340 -0
  759. package/scripts/gds/seed-medusa-tasks.js +440 -0
  760. package/scripts/gds/seed-module-upstreaming.js +219 -0
  761. package/scripts/gds/seed-productization-tasks.js +235 -0
  762. package/scripts/gds/seed-provisioning-tasks.js +83 -0
  763. package/scripts/gds/seed-staging.sh +104 -0
  764. package/scripts/gds/seed-v2-world-tasks.js +283 -0
  765. package/scripts/gds/seed-v3-tasks.js +1981 -0
  766. package/scripts/gds/session-cost.js +393 -0
  767. package/scripts/gds/session-digest.js +179 -0
  768. package/scripts/gds/session-eval.js +576 -0
  769. package/scripts/gds/session.js +404 -0
  770. package/scripts/gds/setup.js +504 -0
  771. package/scripts/gds/shell.js +100 -0
  772. package/scripts/gds/ship.js +3618 -0
  773. package/scripts/gds/smoke-batch-claim.sh +213 -0
  774. package/scripts/gds/smoke-batch-release.sh +296 -0
  775. package/scripts/gds/smoke-box.sh +150 -0
  776. package/scripts/gds/smoke-claim-consistency.sh +212 -0
  777. package/scripts/gds/smoke-dependencies.sh +84 -0
  778. package/scripts/gds/smoke-gds.js +125 -0
  779. package/scripts/gds/smoke-write.sh +168 -0
  780. package/scripts/gds/start.js +782 -0
  781. package/scripts/gds/status.js +365 -0
  782. package/scripts/gds/triage.js +366 -0
  783. package/scripts/gds/upgrade.js +421 -0
  784. package/scripts/gds/validate-design.js +254 -0
  785. package/scripts/gds/version-close.js +549 -0
  786. package/scripts/migrate.sh +183 -0
  787. package/scripts/migrate_cost_ledger.sh +178 -0
  788. package/scripts/public-mirror-export.js +291 -0
  789. package/scripts/render-diagrams.sh +88 -0
  790. package/scripts/security/dep-audit.js +276 -0
  791. package/scripts/setup-builder.js +274 -0
  792. package/scripts/setup-builder.sh +28 -0
  793. package/scripts/snapshots/backfill-history.mjs +292 -0
  794. package/scripts/snapshots/maybe-render-on-deploy.sh +66 -0
  795. package/scripts/snapshots/render-pre-art-eras.mjs +329 -0
  796. package/scripts/snapshots/render-world.mjs +322 -0
  797. package/scripts/status-mirror-sync.js +192 -0
  798. package/scripts/status-probe.mjs +185 -0
  799. package/server.js +212 -0
  800. package/src/asset-version.js +71 -0
  801. package/src/bongos/CLAUDE.md +64 -0
  802. package/src/bongos/api-errors.js +281 -0
  803. package/src/bongos/api-path-404.js +67 -0
  804. package/src/bongos/api-prefix.js +38 -0
  805. package/src/bongos/app-pair.js +172 -0
  806. package/src/bongos/auth.js +979 -0
  807. package/src/bongos/cascade-dispatch.js +123 -0
  808. package/src/bongos/db-kernel.js +252 -0
  809. package/src/bongos/db.js +911 -0
  810. package/src/bongos/goal-scope-check.js +120 -0
  811. package/src/bongos/hierarchy-config.js +189 -0
  812. package/src/bongos/live-channel.js +145 -0
  813. package/src/bongos/llm-cache.js +260 -0
  814. package/src/bongos/llm-pricing.js +220 -0
  815. package/src/bongos/metrics.js +286 -0
  816. package/src/bongos/middleware/audit.js +274 -0
  817. package/src/bongos/middleware/error-envelope.js +93 -0
  818. package/src/bongos/middleware/rate-limit.js +195 -0
  819. package/src/bongos/module-scope-map.js +271 -0
  820. package/src/bongos/optimizer.js +166 -0
  821. package/src/bongos/path-match.js +47 -0
  822. package/src/bongos/permission-path-check.js +248 -0
  823. package/src/bongos/pool.js +55 -0
  824. package/src/bongos/repo-info.js +91 -0
  825. package/src/bongos/route-rank-check.js +420 -0
  826. package/src/bongos/routes/CLAUDE.md +43 -0
  827. package/src/bongos/routes/_helpers.js +369 -0
  828. package/src/bongos/routes/audit-log.js +59 -0
  829. package/src/bongos/routes/auth.js +755 -0
  830. package/src/bongos/routes/backup.js +104 -0
  831. package/src/bongos/routes/builders.js +526 -0
  832. package/src/bongos/routes/healthz.js +16 -0
  833. package/src/bongos/routes/instance.js +129 -0
  834. package/src/bongos/routes/live.js +125 -0
  835. package/src/bongos/routes/llm-cache.js +119 -0
  836. package/src/bongos/routes/me.js +380 -0
  837. package/src/bongos/routes/modules.js +131 -0
  838. package/src/bongos/routes/optimizer.js +54 -0
  839. package/src/bongos/routes/public.js +476 -0
  840. package/src/bongos/routes/security.js +207 -0
  841. package/src/bongos/routes.js +166 -0
  842. package/src/bongos/secret-box.js +177 -0
  843. package/src/bongos/sensitive-surfaces.js +30 -0
  844. package/src/bongos/serve-internal.js +889 -0
  845. package/src/bongos/uptime-poller.js +90 -0
  846. package/src/bongos-downloads.js +70 -0
  847. package/src/branding.js +182 -0
  848. package/src/build-info.js +77 -0
  849. package/src/devbox-downloads.js +67 -0
  850. package/src/instance-config.js +200 -0
  851. package/src/module-api.js +366 -0
  852. package/src/module-loader/loader.js +268 -0
  853. package/src/module-loader/manifest-schema.js +140 -0
  854. package/src/module-loader/provenance.js +28 -0
  855. package/src/module-loader/semver.js +100 -0
  856. package/src/module-seams.js +291 -0
  857. package/src/modules.js +254 -0
  858. package/src/platform-server.js +135 -0
  859. package/src/ui/adapters/claude-design/index.js +333 -0
  860. package/src/ui/adapters/figma/index.js +328 -0
  861. package/tests/abandon_task.mjs +138 -0
  862. package/tests/achievements_reconcile.mjs +167 -0
  863. package/tests/adopt_detect.mjs +141 -0
  864. package/tests/adopt_import.mjs +132 -0
  865. package/tests/adopt_preflight.mjs +105 -0
  866. package/tests/anti_grid.mjs +89 -0
  867. package/tests/api_client.mjs +231 -0
  868. package/tests/api_docs.mjs +283 -0
  869. package/tests/api_error_envelope_buildcheck.mjs +56 -0
  870. package/tests/api_error_envelope_middleware.mjs +99 -0
  871. package/tests/api_error_registry.mjs +108 -0
  872. package/tests/api_pagination_contract.mjs +51 -0
  873. package/tests/api_path_404.mjs +96 -0
  874. package/tests/app_pair.mjs +168 -0
  875. package/tests/architect.mjs +140 -0
  876. package/tests/art_key.mjs +121 -0
  877. package/tests/art_stage.mjs +121 -0
  878. package/tests/asset_version.mjs +94 -0
  879. package/tests/atlas.mjs +69 -0
  880. package/tests/audit_deps.mjs +74 -0
  881. package/tests/audit_middleware.mjs +385 -0
  882. package/tests/auth_admission_gate.mjs +164 -0
  883. package/tests/auth_anthropic_identity.mjs +95 -0
  884. package/tests/auth_duplicate_cookie.mjs +56 -0
  885. package/tests/auth_error_brand.mjs +77 -0
  886. package/tests/auth_flow_slice1.mjs +223 -0
  887. package/tests/auth_inactive_builder.mjs +94 -0
  888. package/tests/auth_page_gate.mjs +92 -0
  889. package/tests/auth_session_ttl.mjs +155 -0
  890. package/tests/autonomous_fit_protected_paths.mjs +115 -0
  891. package/tests/autonomy_gate.mjs +85 -0
  892. package/tests/autotile_variants.mjs +256 -0
  893. package/tests/autotile_xverify.mjs +133 -0
  894. package/tests/backfill_sessions.mjs +101 -0
  895. package/tests/backfill_task_rewards.mjs +152 -0
  896. package/tests/backup_cli.mjs +104 -0
  897. package/tests/bfg.mjs +327 -0
  898. package/tests/bfg_write.mjs +423 -0
  899. package/tests/bongos_box_connect.mjs +89 -0
  900. package/tests/bongos_dispatch.mjs +74 -0
  901. package/tests/bongos_downloads.mjs +118 -0
  902. package/tests/bongos_login.mjs +34 -0
  903. package/tests/box_access.mjs +186 -0
  904. package/tests/box_auth_check.mjs +114 -0
  905. package/tests/box_code_staleness.mjs +116 -0
  906. package/tests/box_connect_e2e.mjs +196 -0
  907. package/tests/box_cost.mjs +70 -0
  908. package/tests/box_dns_repoint.mjs +151 -0
  909. package/tests/box_host_keys.mjs +102 -0
  910. package/tests/box_onboard.mjs +317 -0
  911. package/tests/box_scope_session.mjs +115 -0
  912. package/tests/box_ship_permissions.mjs +71 -0
  913. package/tests/box_terminal_ssrf.mjs +90 -0
  914. package/tests/boxes.mjs +1255 -0
  915. package/tests/branding.mjs +88 -0
  916. package/tests/bug_attachments.mjs +189 -0
  917. package/tests/build_info.mjs +88 -0
  918. package/tests/builder_needs.mjs +99 -0
  919. package/tests/cap_newcomer_tasks.mjs +114 -0
  920. package/tests/cascade-dispatch.mjs +95 -0
  921. package/tests/cf_tunnel.mjs +459 -0
  922. package/tests/claim_recall.mjs +150 -0
  923. package/tests/claims_bind_session.mjs +47 -0
  924. package/tests/claude_materialize.mjs +148 -0
  925. package/tests/cli_box_scope.mjs +52 -0
  926. package/tests/cli_lib_formatters.mjs +87 -0
  927. package/tests/cli_token_reissue.mjs +147 -0
  928. package/tests/client_bundle_route.mjs +47 -0
  929. package/tests/cloud_bongos_pack.mjs +85 -0
  930. package/tests/conductor.mjs +496 -0
  931. package/tests/confirm_attribution.mjs +156 -0
  932. package/tests/conflict_resolve.mjs +462 -0
  933. package/tests/context_pack.mjs +240 -0
  934. package/tests/cost.mjs +94 -0
  935. package/tests/cost_audit.mjs +122 -0
  936. package/tests/cost_budget_status.mjs +78 -0
  937. package/tests/cost_reconcile.mjs +102 -0
  938. package/tests/cost_summary_shape.mjs +94 -0
  939. package/tests/credit_grant.mjs +376 -0
  940. package/tests/criterion_progress.mjs +220 -0
  941. package/tests/criterion_proposal.mjs +109 -0
  942. package/tests/criterion_ref_parse.mjs +53 -0
  943. package/tests/currency_label.mjs +119 -0
  944. package/tests/day_cycle.mjs +197 -0
  945. package/tests/dependencies_migration.mjs +77 -0
  946. package/tests/dependencies_polymorphic.mjs +212 -0
  947. package/tests/deploy_instance.mjs +78 -0
  948. package/tests/devbox_downloads.mjs +122 -0
  949. package/tests/diff_derived_signals.mjs +115 -0
  950. package/tests/discord_approvals.mjs +174 -0
  951. package/tests/discord_autojoin.mjs +158 -0
  952. package/tests/discord_bot.mjs +94 -0
  953. package/tests/discord_bugs.mjs +297 -0
  954. package/tests/discord_channels.mjs +337 -0
  955. package/tests/discord_foundation.mjs +76 -0
  956. package/tests/discord_inbound.mjs +190 -0
  957. package/tests/discord_message_buffer.mjs +87 -0
  958. package/tests/discord_oauth.mjs +55 -0
  959. package/tests/discord_reaction.mjs +170 -0
  960. package/tests/discord_role_sync.mjs +151 -0
  961. package/tests/display_name.mjs +123 -0
  962. package/tests/dns_preflight.mjs +74 -0
  963. package/tests/event_sound_prefs.mjs +194 -0
  964. package/tests/eviction_policy.mjs +279 -0
  965. package/tests/figma_adapter.mjs +199 -0
  966. package/tests/file_map.mjs +91 -0
  967. package/tests/first_admin_bootstrap.mjs +40 -0
  968. package/tests/fitness.mjs +435 -0
  969. package/tests/fitness_two_root.mjs +104 -0
  970. package/tests/fixtures/session-506-digest.json +34 -0
  971. package/tests/gate_approvals.mjs +451 -0
  972. package/tests/gate_review.mjs +152 -0
  973. package/tests/git_merge_regen.mjs +151 -0
  974. package/tests/github_push_ancestry.mjs +119 -0
  975. package/tests/github_push_land_proof.mjs +127 -0
  976. package/tests/github_push_merge_driver.mjs +175 -0
  977. package/tests/goal_abuse_matrix.mjs +187 -0
  978. package/tests/goal_achievement.mjs +146 -0
  979. package/tests/goal_conflicts.mjs +305 -0
  980. package/tests/goal_dependencies_read.mjs +73 -0
  981. package/tests/goal_member_roles.mjs +420 -0
  982. package/tests/goal_membership_requests.mjs +332 -0
  983. package/tests/goal_routes.mjs +203 -0
  984. package/tests/goal_scope_check.mjs +167 -0
  985. package/tests/goal_tier.mjs +312 -0
  986. package/tests/goal_wall_proof.mjs +112 -0
  987. package/tests/grade_attempts.mjs +73 -0
  988. package/tests/grade_attribution.mjs +117 -0
  989. package/tests/grade_diff_hash.mjs +191 -0
  990. package/tests/grade_server_authoritative.mjs +305 -0
  991. package/tests/grade_unavailable_display.mjs +66 -0
  992. package/tests/grader.mjs +1960 -0
  993. package/tests/grader_bypass.mjs +57 -0
  994. package/tests/grader_panel.mjs +252 -0
  995. package/tests/grader_prompt_fencing.mjs +192 -0
  996. package/tests/helpers.mjs +52 -0
  997. package/tests/hierarchy-config.mjs +81 -0
  998. package/tests/init.mjs +463 -0
  999. package/tests/instance_config.mjs +76 -0
  1000. package/tests/instance_manifest.mjs +110 -0
  1001. package/tests/interaction_prefs.mjs +72 -0
  1002. package/tests/key-card.mjs +110 -0
  1003. package/tests/key-status.mjs +45 -0
  1004. package/tests/land_watch.mjs +115 -0
  1005. package/tests/lifecycle-card.mjs +145 -0
  1006. package/tests/lifecycle_breakdown_view.mjs +236 -0
  1007. package/tests/linkify_refs.mjs +264 -0
  1008. package/tests/live_channel.mjs +128 -0
  1009. package/tests/live_sse.mjs +122 -0
  1010. package/tests/llm-cache-route.mjs +110 -0
  1011. package/tests/llm-cache.mjs +140 -0
  1012. package/tests/llm-pricing.mjs +152 -0
  1013. package/tests/local_preview.mjs +136 -0
  1014. package/tests/main_audit.mjs +137 -0
  1015. package/tests/memory_isolation.mjs +431 -0
  1016. package/tests/memory_map.mjs +107 -0
  1017. package/tests/memory_pull.mjs +429 -0
  1018. package/tests/merge_lease.mjs +100 -0
  1019. package/tests/merge_lock.mjs +312 -0
  1020. package/tests/metrics.mjs +147 -0
  1021. package/tests/migration_allocation.mjs +146 -0
  1022. package/tests/migration_namespace.mjs +185 -0
  1023. package/tests/migrations_fresh_replay_guard.mjs +38 -0
  1024. package/tests/mirror_lineage_fulltree.mjs +45 -0
  1025. package/tests/mirror_lineage_proof.mjs +72 -0
  1026. package/tests/mirror_redact.mjs +193 -0
  1027. package/tests/model_alloc_prefs.mjs +63 -0
  1028. package/tests/module-scope-map.mjs +88 -0
  1029. package/tests/module_api.mjs +110 -0
  1030. package/tests/module_cli.mjs +292 -0
  1031. package/tests/module_contributions.mjs +148 -0
  1032. package/tests/module_loader.mjs +286 -0
  1033. package/tests/module_manifest.mjs +194 -0
  1034. package/tests/module_owned_tests.mjs +105 -0
  1035. package/tests/module_provenance.mjs +34 -0
  1036. package/tests/module_route_rank.mjs +147 -0
  1037. package/tests/module_seams.mjs +68 -0
  1038. package/tests/modules.mjs +156 -0
  1039. package/tests/modules_route.mjs +38 -0
  1040. package/tests/newcomer_floor.mjs +17 -0
  1041. package/tests/newcomer_restock.mjs +80 -0
  1042. package/tests/next_number.mjs +154 -0
  1043. package/tests/oauth_secret.mjs +60 -0
  1044. package/tests/onboard.mjs +70 -0
  1045. package/tests/onboarding_gate.mjs +267 -0
  1046. package/tests/onboarding_observability.mjs +344 -0
  1047. package/tests/onboarding_route_signals.mjs +175 -0
  1048. package/tests/onboarding_state.mjs +346 -0
  1049. package/tests/one_active_claim_per_session.mjs +111 -0
  1050. package/tests/orphaned_claim_ship.mjs +135 -0
  1051. package/tests/override_attribution.mjs +142 -0
  1052. package/tests/override_request_ownership.mjs +235 -0
  1053. package/tests/package_core.mjs +435 -0
  1054. package/tests/parallel-load.mjs +402 -0
  1055. package/tests/path_match.mjs +62 -0
  1056. package/tests/permission_path.mjs +151 -0
  1057. package/tests/platform_boot.mjs +167 -0
  1058. package/tests/pre_compact.mjs +60 -0
  1059. package/tests/preview_server.mjs +127 -0
  1060. package/tests/profile_route.mjs +197 -0
  1061. package/tests/provision.mjs +805 -0
  1062. package/tests/provisioning_github_app_routes.mjs +98 -0
  1063. package/tests/public_mirror_export.mjs +124 -0
  1064. package/tests/public_task_resolver.mjs +112 -0
  1065. package/tests/publish_branch_route.mjs +422 -0
  1066. package/tests/publish_manifest.mjs +184 -0
  1067. package/tests/publish_reconciler.mjs +728 -0
  1068. package/tests/rank_gate.mjs +463 -0
  1069. package/tests/rate_limit_public.mjs +217 -0
  1070. package/tests/read_session_export.mjs +89 -0
  1071. package/tests/recall_cli.mjs +82 -0
  1072. package/tests/recall_hints.mjs +119 -0
  1073. package/tests/recent_shipped_window.mjs +80 -0
  1074. package/tests/regrade_eligibility.mjs +202 -0
  1075. package/tests/render_prefs.mjs +122 -0
  1076. package/tests/repo_map.mjs +92 -0
  1077. package/tests/reward_gate.mjs +284 -0
  1078. package/tests/route_rank_check.mjs +243 -0
  1079. package/tests/route_validation.mjs +490 -0
  1080. package/tests/routine_timers.mjs +72 -0
  1081. package/tests/rubric_fixtures.mjs +140 -0
  1082. package/tests/run_routine.mjs +69 -0
  1083. package/tests/sandbox_stage.mjs +582 -0
  1084. package/tests/scrubber_corpus.mjs +257 -0
  1085. package/tests/search_chunker.mjs +209 -0
  1086. package/tests/search_ingest.mjs +96 -0
  1087. package/tests/search_ingest_db.mjs +88 -0
  1088. package/tests/search_isolation.mjs +204 -0
  1089. package/tests/search_route.mjs +95 -0
  1090. package/tests/secret_box.mjs +189 -0
  1091. package/tests/security_docs.mjs +186 -0
  1092. package/tests/security_route.mjs +108 -0
  1093. package/tests/served_paths_shipped.mjs +118 -0
  1094. package/tests/session-cards.mjs +142 -0
  1095. package/tests/session_506_regression.mjs +69 -0
  1096. package/tests/session_caps.mjs +238 -0
  1097. package/tests/session_cost.mjs +133 -0
  1098. package/tests/session_digest.mjs +73 -0
  1099. package/tests/session_eval.mjs +386 -0
  1100. package/tests/session_index.mjs +105 -0
  1101. package/tests/session_records.mjs +369 -0
  1102. package/tests/session_search.mjs +78 -0
  1103. package/tests/session_start_freshness.mjs +123 -0
  1104. package/tests/setup_smoke.mjs +154 -0
  1105. package/tests/ship_autolinkify.mjs +60 -0
  1106. package/tests/ship_automerge_injection.mjs +174 -0
  1107. package/tests/ship_broadcast_routing.mjs +125 -0
  1108. package/tests/ship_broadcast_server.mjs +175 -0
  1109. package/tests/ship_card.mjs +280 -0
  1110. package/tests/ship_ci_deploy.mjs +374 -0
  1111. package/tests/ship_preflight.mjs +368 -0
  1112. package/tests/ship_premerge.mjs +75 -0
  1113. package/tests/ship_resume.mjs +129 -0
  1114. package/tests/ship_upload_skip.mjs +89 -0
  1115. package/tests/ship_zero_commit.mjs +60 -0
  1116. package/tests/single_host_hall.mjs +98 -0
  1117. package/tests/skill_prefs.mjs +150 -0
  1118. package/tests/smoke_preflight.mjs +66 -0
  1119. package/tests/snapshot_picker.mjs +233 -0
  1120. package/tests/sound_prefs.mjs +198 -0
  1121. package/tests/sprite_facing.mjs +35 -0
  1122. package/tests/status-probe.mjs +89 -0
  1123. package/tests/status_backfill.mjs +94 -0
  1124. package/tests/stop_refcheck.mjs +127 -0
  1125. package/tests/streak.mjs +175 -0
  1126. package/tests/subdomain_auth.mjs +58 -0
  1127. package/tests/task_classifier_vocab.mjs +41 -0
  1128. package/tests/task_create_idempotency.mjs +96 -0
  1129. package/tests/task_goal_link.mjs +93 -0
  1130. package/tests/task_ownership_gate.mjs +125 -0
  1131. package/tests/terrain_picker.mjs +298 -0
  1132. package/tests/touches_overlap.mjs +75 -0
  1133. package/tests/triage_development.mjs +140 -0
  1134. package/tests/turn_in_place.mjs +280 -0
  1135. package/tests/upgrade.mjs +357 -0
  1136. package/tests/verify_task_guard.mjs +64 -0
  1137. package/tests/version_close.mjs +76 -0
  1138. package/tests/versions_route.mjs +93 -0
  1139. package/tests/walkability.mjs +188 -0
  1140. package/tests/wandering_prefs.mjs +176 -0
  1141. package/tests/worktree_disambiguation.mjs +105 -0
  1142. package/tests/worktree_guard.mjs +90 -0
@@ -0,0 +1,903 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ //
4
+ // scripts/gds/init.js — `bongos init`: scaffold a NEW Cloud Bongos instance.
5
+ //
6
+ // GDS-V4 · V4.R65 · task 1204 (ADR 0062 §7). The self-serve replacement for the
7
+ // hand-written 35–83 KB seed-*.js-per-version pattern. It:
8
+ // 1. gathers a spec (interactive interview, or --from <spec.json>),
9
+ // 2. writes the instance config — config/branding.json + config/modules.json
10
+ // (lean OVERRIDES; config/*.neutral.json fills the rest, src/branding.js),
11
+ // 3. seeds the first version + its done-when goal via POST /api/gds/versions
12
+ // (the primitive added in this same task), then files the starter task and
13
+ // the human-only KICKOFF steps as real, tracked tasks via POST /tasks,
14
+ // 4. points the owner at docs/branding-fill-prompt.md for the LOOK (a locked
15
+ // project rule: an owner brands with their OWN LLM — init never generates
16
+ // branding) and prints the remaining manual steps.
17
+ //
18
+ // It deliberately does NOT try to make launch one command: a fresh instance
19
+ // needs irreducibly-manual owner steps (a GitHub OAuth app, first sign-in).
20
+ // init's value is that it writes what it can AND turns the rest into a claimable,
21
+ // tracked checklist so nothing is silently skipped.
22
+ //
23
+ // Infra arm (ADR 0111 §3, task 1946): when the owner opts into production hosting,
24
+ // the interview's infra answers (hosting shape, bring-your-own domain, credential
25
+ // ref, tier) become a real provisioning REQUEST — a POST to the provisioning
26
+ // module's /provisioning/instances, which enqueues a provision intent the
27
+ // control-plane runner drains — instead of only a manual "production topology"
28
+ // task. OAuth-app creation + first sign-in stay guided/manual (no clean API). If
29
+ // the target instance doesn't have the provisioning module enabled, init falls
30
+ // back to filing the manual task (nothing is silently dropped).
31
+ //
32
+ // Safety: refuses to overwrite an existing config/branding.json unless --force
33
+ // (so running it inside an already-configured instance — e.g. OTB — can't
34
+ // clobber it). Use --dry-run to preview every file + API call without doing any.
35
+ //
36
+ // --adopt (brownfield, ADR 0121): the greenfield body above assumes a blank slate —
37
+ // it refuses where config/branding.json exists, and --force OVERWRITES. `--adopt` is
38
+ // the opposite: it LAYERS Cloud Bongos onto an EXISTING repo (app code, git history,
39
+ // a package.json). It writes the lean config only where absent, adds the pinned
40
+ // @cloudbongos/core dependency to the owner's package.json without touching any other
41
+ // field, and materializes .claude/ ADDITIVELY — for any pre-existing file it
42
+ // MERGES-or-LEAVES-AND-REPORTS, it NEVER overwrites, and it does not reuse the --force
43
+ // path. It deliberately does NOT seed a synthetic "V1 — Prove the loop": capturing the
44
+ // repo's real version/goal + importing its backlog is a later real-state step, and the
45
+ // full conflict pre-flight is a later step too — this file lands the mode skeleton +
46
+ // additive config layering (task 2042). Every other onboarding leg is identical.
47
+ //
48
+ // Usage:
49
+ // bongos init interactive interview (greenfield — a NEW instance)
50
+ // bongos init --adopt LAYER onto an existing repo (brownfield; never clobbers).
51
+ // Runs a conflict PRE-FLIGHT + accept-gate: nothing writes
52
+ // until you confirm (interactive y/N) or pass --accept.
53
+ // bongos init --adopt --accept apply the adopt without the interactive prompt (CI / non-interactive)
54
+ // bongos init --from spec.json non-interactive (CI / the C8 self-build proof)
55
+ // bongos init --dry-run print the plan; write nothing, call nothing
56
+ // bongos init --dir <path> target dir for the config files (default: cwd)
57
+ // bongos init --no-seed write config only; skip the version/task seeding
58
+ // bongos init --force overwrite existing config files (greenfield only; ignored by --adopt)
59
+ // bongos init --vendor-core <tgz> greenfield only: vendor the @cloudbongos/core .tgz + pin
60
+ // package.json to file:vendor/… + generate package-lock.json,
61
+ // so the scaffold is `npm ci`-installable (ADR 0108 gap 1/4).
62
+ // Without it the scaffold pins the caret range (unresolvable
63
+ // on npm today) — a local/dev scaffold you resolve another way.
64
+
65
+ const fs = require('node:fs');
66
+ const path = require('node:path');
67
+ const readline = require('node:readline');
68
+ const { apiCall, arg, hasFlag } = require('./cli-lib');
69
+ const { DEFAULT_HIERARCHY } = require('../../src/bongos/hierarchy-config');
70
+ const { resolveCoreRoot } = require('../../src/instance-config'); // ADR 0108 §1: where the core package lives
71
+ const { materializeClaude } = require('./claude-materialize'); // ADR 0108 §3 (W3): copy .claude/ into the instance
72
+ const { detectStack, formatStackSummary } = require('./adopt-detect'); // ADR 0121 §Decision 4 (task 2043): inspect an existing repo before layering
73
+ const { resolveBacklogTasks, DEFAULT_MAX: BACKLOG_MAX } = require('./adopt-import'); // ADR 0121 §Decision 3 (task 2044): import an existing backlog
74
+ const { preflightAdopt, formatPreflight } = require('./adopt-preflight'); // ADR 0121 §Decision 5 (task 2045): the accept-gated conflict pre-flight
75
+
76
+ const KNOWN_MODULES = ['game', 'art-pipeline', 'discord', 'dev-box'];
77
+
78
+ // The provisioning hosting shapes — a small mirror of modules/provisioning's
79
+ // HOSTING_SHAPES. init deliberately does NOT import the (optional) provisioning
80
+ // module: it stays self-contained and lets the server be the authority on a
81
+ // request (POST /provisioning/instances validates slug/shape, and returns 404 when
82
+ // the module isn't enabled on the target instance — init then falls back to filing
83
+ // the manual production-topology task). ADR 0111 §3.
84
+ const HOSTING_SHAPES = ['co-tenant', 'dedicated', 'standalone'];
85
+
86
+ // The Cloud Bongos core npm package an instance pins as a dependency (ADR 0108).
87
+ // `bongos init --adopt` LAYERS this onto an existing repo's package.json; `bongos
88
+ // upgrade` later re-pins it to a vendored `file:` tarball. Named so the adopt
89
+ // layering and the upgrade re-pin agree on the dependency name.
90
+ const CORE_PKG = '@cloudbongos/core';
91
+
92
+ const isObj = (v) => v && typeof v === 'object' && !Array.isArray(v);
93
+
94
+ // The version RANGE `--adopt` writes for the core dep: a caret over the running
95
+ // core's CORE_VERSION — the declared intent. The CONCRETE artifact (a registry
96
+ // install, or the vendored `file:` tarball a `bongos upgrade` pins) is resolved by
97
+ // provisioning / upgrade per ADR 0108, not by init. Falls back to a safe floor if
98
+ // module-api can't be resolved (e.g. a partial checkout).
99
+ function coreDepRange() {
100
+ let v;
101
+ try { v = require('../../src/module-api').CORE_VERSION; } catch { v = null; }
102
+ return `^${v || '1.0.0'}`;
103
+ }
104
+
105
+ // The running core's bare version (no caret) — for deriving the vendored tarball name
106
+ // when `--vendor-core`'s tarball is non-canonically named. Fail-soft like coreDepRange().
107
+ function coreVersionSafe() {
108
+ try { return require('../../src/module-api').CORE_VERSION; } catch { return null; }
109
+ }
110
+
111
+ // The npm scripts a STANDALONE greenfield instance runs. They MIRROR how the control
112
+ // plane runs a standalone instance (scripts/gds/provision.js): `start` = the systemd
113
+ // ExecStart (`node <core>/src/platform-server.js`), `migrate` = standaloneMigrateCmd
114
+ // (`bash <core>/scripts/migrate.sh`). Keeping them identical means `npm start` /
115
+ // `npm run migrate` on the instance behave like production, and `bongos upgrade`'s
116
+ // `npm run migrate` step resolves to the core's migrate.sh (ADR 0108).
117
+ const INSTANCE_CORE_PKG_DIR = 'node_modules/@cloudbongos/core';
118
+ const INSTANCE_START_SCRIPT = `node ${INSTANCE_CORE_PKG_DIR}/src/platform-server.js`;
119
+ const INSTANCE_MIGRATE_SCRIPT = `bash ${INSTANCE_CORE_PKG_DIR}/scripts/migrate.sh`;
120
+
121
+ // PURE (exported for tests) — build/augment the greenfield instance package.json so a
122
+ // fresh instance is `npm ci`-installable and runnable (ADR 0108 greenfield gap 1/4,
123
+ // task 2053): the @cloudbongos/core dependency (the `file:` tarball pin when a tarball is
124
+ // vendored, else the declared caret range — the CARET RESOLVES NOWHERE on npm, which is
125
+ // exactly why the vendored path pins `file:`) plus the start/migrate npm scripts a
126
+ // standalone instance runs. Preserves any pre-existing fields + scripts (fills only what
127
+ // is missing); greenfield OWNS the core dep, so it is always (re)set to `coreDep`. Never
128
+ // spawns npm — generating the lockfile is a separate imperative step in main().
129
+ function buildInstancePackageJson(existing, { name = 'cloudbongos-instance', coreDep } = {}) {
130
+ const dep = coreDep || coreDepRange();
131
+ const pkg = isObj(existing) ? { ...existing } : {};
132
+ if (!pkg.name) pkg.name = name;
133
+ if (pkg.private === undefined) pkg.private = true;
134
+ pkg.scripts = { ...(isObj(pkg.scripts) ? pkg.scripts : {}) };
135
+ if (!pkg.scripts.start) pkg.scripts.start = INSTANCE_START_SCRIPT;
136
+ if (!pkg.scripts.migrate) pkg.scripts.migrate = INSTANCE_MIGRATE_SCRIPT;
137
+ pkg.dependencies = { ...(isObj(pkg.dependencies) ? pkg.dependencies : {}), [CORE_PKG]: dep };
138
+ return pkg;
139
+ }
140
+
141
+ // ---------------------------------------------------------------------------
142
+ // Pure builders (exported for tests — no I/O, no network)
143
+ // ---------------------------------------------------------------------------
144
+
145
+ // A url-safe slug for a criterion_id derived from a short label.
146
+ function slugify(s, fallback = 'goal') {
147
+ const out = String(s || '')
148
+ .toLowerCase()
149
+ .replace(/[^a-z0-9]+/g, '-')
150
+ .replace(/^-+|-+$/g, '')
151
+ .slice(0, 48);
152
+ return out || fallback;
153
+ }
154
+
155
+ // The DNS/db-safe instance slug a provisioning request carries — derived from an
156
+ // explicit spec.provisioning.slug or the product name, lowercased/dashed, then
157
+ // clamped to the module's 2–40-char rule (the server validates it too). Pure.
158
+ function provisioningSlug(spec) {
159
+ const p = (spec && spec.provisioning) || {};
160
+ const base = p.slug || (spec && spec.identity && spec.identity.productName) || '';
161
+ return slugify(base, 'instance').slice(0, 40).replace(/-+$/, '');
162
+ }
163
+
164
+ // The POST /api/gds/provisioning/instances body built from the interview's infra
165
+ // answers — or null when the owner didn't opt into provisioning (no spec.provisioning
166
+ // block). THE ADR 0111 §3 ARM: infra answers become a real provisioning REQUEST (a
167
+ // provisioning_intents row the control-plane runner drains) instead of only a manual
168
+ // runbook task. Pure — no I/O; the caller POSTs it. Shape defaults to the cheapest
169
+ // co-tenant ($0) per the budget DNA (ADR 0111 §6).
170
+ function provisioningRequest(spec) {
171
+ const p = spec && spec.provisioning;
172
+ if (!isObj(p)) return null;
173
+ const shape = HOSTING_SHAPES.includes(p.shape) ? p.shape : 'co-tenant';
174
+ const body = { slug: provisioningSlug(spec), hosting_shape: shape };
175
+ if (p.domain) body.domain = String(p.domain).trim();
176
+ if (p.targetRef) body.target_ref = String(p.targetRef).trim();
177
+ if (p.tier) body.tier = String(p.tier).trim();
178
+ return body;
179
+ }
180
+
181
+ // The one kickoff step the provisioning module AUTOMATES (ADR 0111 §3): standing up
182
+ // production hosting/TLS/DNS/managed-DB. Kept as a named builder so init can either
183
+ // FILE it (no provisioning requested, or the request couldn't be enqueued) or OMIT
184
+ // it (a request went in — the control-plane runner covers this leg).
185
+ function productionTopologyKickoff() {
186
+ return {
187
+ title: 'Production topology: TLS, real origins, managed Postgres',
188
+ kind: 'infra',
189
+ description: 'For a real (non-localhost) launch: front the instance with TLS (Caddy/Cloudflare/nginx), point ' +
190
+ 'publicOrigin/buildersOrigin/statusOrigin at the real domain (the OAuth callback depends on this), and move off the bundled container DB volume to managed/backed-up Postgres.',
191
+ };
192
+ }
193
+
194
+ // The lean instance branding.json: ONLY the fields the owner supplied. Everything
195
+ // else (theme, copy, rank labels, box subdomain pattern) resolves from
196
+ // config/branding.neutral.json via src/branding.js. Writing less keeps an
197
+ // instance's overrides legible and lets vanilla defaults flow through.
198
+ function buildBrandingConfig(spec) {
199
+ const id = spec.identity || {};
200
+ const productName = id.productName;
201
+ const origin = (spec.domains && spec.domains.publicOrigin) || 'http://localhost:3000';
202
+ const branding = {
203
+ _note: `${productName} — instance brand pack (overrides over config/branding.neutral.json). ` +
204
+ 'Authored by `bongos init`. Fill the LOOK (palette/fonts/wordmark) with your own LLM via docs/branding-fill-prompt.md.',
205
+ identity: {
206
+ productName,
207
+ worldName: id.worldName || productName,
208
+ company: { name: (id.company && id.company.name) || '', site: (id.company && id.company.site) || '' },
209
+ },
210
+ llmProjectName: productName,
211
+ domains: {
212
+ publicOrigin: origin,
213
+ buildersOrigin: origin,
214
+ statusOrigin: origin,
215
+ oauthOrigin: origin,
216
+ },
217
+ repo: { owner: spec.repo.owner, name: spec.repo.name },
218
+ firstAdmin: spec.firstAdmin,
219
+ currency: { label: (spec.currency && spec.currency.label) || 'credits', symbol: (spec.currency && spec.currency.symbol) || '' },
220
+ envPrefix: spec.envPrefix || 'CLOUDBONGOS',
221
+ };
222
+ if (spec.tagline) branding.copy = { tagline: spec.tagline };
223
+ return branding;
224
+ }
225
+
226
+ // modules.json — every known module, explicit boolean. Default OFF (vanilla).
227
+ function buildModulesConfig(spec) {
228
+ const on = new Set(Array.isArray(spec.modules) ? spec.modules : []);
229
+ const modules = {};
230
+ for (const m of KNOWN_MODULES) modules[m] = on.has(m);
231
+ return { modules };
232
+ }
233
+
234
+ // hierarchy.json — the work-tier preset (ADR 0086 §1). The six-tier default with
235
+ // the instance's optional overrides applied: spec.hierarchy.labels ({tierKey:
236
+ // label}), spec.hierarchy.enabled ({tierKey: bool}), spec.hierarchy.roles
237
+ // ({scope/membership/criteria: tierKey}). Most instances keep the canonical six
238
+ // tiers, so this writes them explicitly (self-documenting), resolved over the
239
+ // baked DEFAULT_HIERARCHY by src/bongos/hierarchy-config.js at load.
240
+ function buildHierarchyConfig(spec) {
241
+ const h = isObj(spec.hierarchy) ? spec.hierarchy : {};
242
+ const labels = isObj(h.labels) ? h.labels : {};
243
+ const enabled = isObj(h.enabled) ? h.enabled : {};
244
+ const tiers = DEFAULT_HIERARCHY.tiers.map((t) => ({
245
+ key: t.key,
246
+ label: typeof labels[t.key] === 'string' && labels[t.key].trim() ? labels[t.key].trim() : t.label,
247
+ enabled: typeof enabled[t.key] === 'boolean' ? enabled[t.key] : t.enabled,
248
+ }));
249
+ const roles = { ...DEFAULT_HIERARCHY.roles, ...(isObj(h.roles) ? h.roles : {}) };
250
+ const productName = (spec.identity && spec.identity.productName) || 'Instance';
251
+ return {
252
+ _note: `${productName} — work-hierarchy tiers (ADR 0086 §1): per-tier label/enabled + roles ` +
253
+ '(which tier carries scope_modules / members / done-when criteria), resolved over the six-tier ' +
254
+ 'default in src/bongos/hierarchy-config.js. Authored by `bongos init`.',
255
+ tiers,
256
+ roles,
257
+ };
258
+ }
259
+
260
+ // PURE — layer the pinned core dependency into a parsed package.json (ADR 0121
261
+ // §Decision 2 / task 2042). NEVER clobbers: if `@cloudbongos/core` is already a dep
262
+ // (in dependencies OR devDependencies) it returns the object untouched with
263
+ // action:'present'; if there is no package.json at all it MINTS a minimal one
264
+ // (action:'created'); otherwise it ADDS the dep, preserving every existing field and
265
+ // key order (action:'added'). The `--force`-overwrite path is never involved. The
266
+ // caller only writes the file for 'added'/'created' — 'present' stays byte-untouched.
267
+ function mergeCoreDependency(pkg, { corePkg = CORE_PKG, coreRange, name = 'cloudbongos-instance' } = {}) {
268
+ const range = coreRange || coreDepRange();
269
+ if (!isObj(pkg)) {
270
+ return { pkg: { name, private: true, dependencies: { [corePkg]: range } }, action: 'created' };
271
+ }
272
+ const already = (isObj(pkg.dependencies) && pkg.dependencies[corePkg]) ||
273
+ (isObj(pkg.devDependencies) && pkg.devDependencies[corePkg]);
274
+ if (already) return { pkg, action: 'present' };
275
+ // Spread keeps the original key order — `dependencies` stays where it was (or is
276
+ // appended if absent). We add exactly one key; we never reorder or drop theirs.
277
+ const next = { ...pkg, dependencies: { ...(isObj(pkg.dependencies) ? pkg.dependencies : {}), [corePkg]: range } };
278
+ return { pkg: next, action: 'added' };
279
+ }
280
+
281
+ // The kickoff checklist, as tasks. These are the steps init CANNOT do for you —
282
+ // the human-only setup a fresh instance needs to actually launch (grounded in
283
+ // the onboarding/deploy surfaces; see the task 1204 mapping pass). Each becomes
284
+ // a real, claimable task so it's tracked, never silently skipped. Per-module
285
+ // prerequisites are appended only for the modules the owner enabled.
286
+ function kickoffTasks(spec) {
287
+ const origin = (spec.domains && spec.domains.publicOrigin) || 'http://localhost:3000';
288
+ const tasks = [
289
+ {
290
+ title: 'Register a GitHub OAuth app and set its credentials',
291
+ kind: 'infra',
292
+ description: 'Auth is the hard prerequisite for every sign-in — without it the server returns 503 ' +
293
+ 'auth_not_configured and nobody (including you) can log in. Create a GitHub OAuth app, set ' +
294
+ `<ENVPREFIX>_GITHUB_CLIENT_ID/SECRET, tick "Enable Device Flow" (a separate save), and set the callback URL to ${origin}/api/gds/auth/web/callback.`,
295
+ },
296
+ {
297
+ title: `Sign in once as ${spec.firstAdmin} to seat the founding owner`,
298
+ kind: 'infra',
299
+ description: `A fresh database has no owner. Signing in as the configured firstAdmin (${spec.firstAdmin}) ` +
300
+ 'the first time auto-seats that account as the founding Archon (owner). Config alone does nothing — you must actually sign in.',
301
+ },
302
+ {
303
+ title: 'Confirm the GitHub repo binding and deploy mode',
304
+ kind: 'infra',
305
+ description: `This instance ships work to ${spec.repo.owner}/${spec.repo.name}. Confirm the git remote / repo binding ` +
306
+ 'and pick deploy mode in config/deploy.json (ci = server-mediated PR auto-merge, or laptop). A wrong/absent repo binding lets a task grade but never merge.',
307
+ },
308
+ {
309
+ title: 'Set the admission posture and invite the first builders',
310
+ kind: 'infra',
311
+ description: 'Enrollment is invite-only by default. Beyond you, no one can join until you approve an access request ' +
312
+ 'or set <ENVPREFIX>_OPEN_XENOS_ENROLLMENT=1. Decide who can join and invite/approve the first builders.',
313
+ },
314
+ {
315
+ title: 'Arm the merge gate before a second builder joins (ci deploy mode)',
316
+ kind: 'infra',
317
+ description: 'For a shared instance on ci deploy mode, enable branch protection on main + required checks ' +
318
+ '(unit / secret-scan / gate-review) + CODEOWNERS, so untrusted builders cannot push straight to production. Skippable for a solo/local instance.',
319
+ },
320
+ ];
321
+ // Production topology is either AUTOMATED (the owner opted into provisioning — the
322
+ // control-plane runner stands up TLS/DNS/managed-DB) or a tracked manual step.
323
+ // Keep it in its infra slot, before the look step, when it's still manual. (ADR 0111 §3)
324
+ if (!provisioningRequest(spec)) tasks.push(productionTopologyKickoff());
325
+ tasks.push({
326
+ title: 'Fill the instance look with your own LLM',
327
+ kind: 'ideator',
328
+ description: 'init wrote a lean config/branding.json and left the LOOK to you (a locked project rule: brand with your ' +
329
+ 'own LLM, not a generator). Hand docs/branding-fill-prompt.md to your AI to design a palette/fonts/wordmark, or keep the vanilla look.',
330
+ });
331
+ const enabled = new Set(Array.isArray(spec.modules) ? spec.modules : []);
332
+ if (enabled.has('art-pipeline')) {
333
+ tasks.push({ title: 'Provide a Google Gemini API key for the art pipeline', kind: 'infra',
334
+ description: 'The art-pipeline module needs a Google AI Studio (Gemini) key (GOOGLE_AI_STUDIO_KEY, a shared key, or per-builder keys) or it cannot generate art.' });
335
+ }
336
+ if (enabled.has('discord')) {
337
+ tasks.push({ title: 'Provide Discord bot token + webhooks', kind: 'infra',
338
+ description: 'The discord module needs a bot token + webhook URLs + DISCORD_BOT_ENABLED=true. Note: outbound/link surfaces fire on credentials even if the module flag is later turned off.' });
339
+ }
340
+ if (enabled.has('dev-box')) {
341
+ tasks.push({ title: 'Provide a DigitalOcean API token for dev boxes', kind: 'infra',
342
+ description: 'The dev-box module needs a DigitalOcean API token (and optionally Cloudflare) on the operator control plane before any builder box can be provisioned.' });
343
+ }
344
+ return tasks;
345
+ }
346
+
347
+ // Normalize a raw spec (from --from or the interview) to canonical shape +
348
+ // defaults. Pure.
349
+ function normalizeSpec(raw = {}) {
350
+ const spec = { ...raw };
351
+ spec.identity = spec.identity || {};
352
+ spec.repo = spec.repo || {};
353
+ spec.version = spec.version || {};
354
+ spec.modules = Array.isArray(spec.modules) ? spec.modules.filter((m) => KNOWN_MODULES.includes(m)) : [];
355
+ if (!spec.version.status) spec.version.status = 'building';
356
+ // Provisioning (ADR 0111 §3) — a block ⇒ the owner opted in. Coerce the shape to a
357
+ // known value (default the cheapest co-tenant) and trim the free-text refs; drop the
358
+ // block entirely when absent so provisioningRequest() reads it as "not requested".
359
+ if (isObj(spec.provisioning)) {
360
+ const p = spec.provisioning;
361
+ spec.provisioning = {
362
+ shape: HOSTING_SHAPES.includes(p.shape) ? p.shape : 'co-tenant',
363
+ ...(p.slug ? { slug: String(p.slug).trim() } : {}),
364
+ ...(p.domain ? { domain: String(p.domain).trim() } : {}),
365
+ ...(p.targetRef ? { targetRef: String(p.targetRef).trim() } : {}),
366
+ ...(p.tier ? { tier: String(p.tier).trim() } : {}),
367
+ };
368
+ } else {
369
+ delete spec.provisioning;
370
+ }
371
+ return spec;
372
+ }
373
+
374
+ // Validate a normalized spec → array of human-readable error strings ([] = ok).
375
+ // Version fields are required whenever init will SEED — greenfield always, and
376
+ // `--adopt` too (task 2044: adopt reflects the repo's REAL current version/goal, not
377
+ // a synthetic V1). Only `--adopt --no-seed` (layering-only, the task-2042 skeleton
378
+ // behavior) skips them, since it files nothing.
379
+ function validateSpec(spec, { adopt = false, noSeed = false } = {}) {
380
+ const errs = [];
381
+ if (!spec.identity || !spec.identity.productName) errs.push('identity.productName is required');
382
+ if (!spec.repo || !spec.repo.owner || !spec.repo.name) errs.push('repo.owner and repo.name are required');
383
+ if (!spec.firstAdmin) errs.push('firstAdmin (the founding owner GitHub login) is required');
384
+ const seeds = !(adopt && noSeed);
385
+ if (seeds) {
386
+ const noun = adopt ? 'your current version/milestone' : 'the first version';
387
+ if (!spec.version || !spec.version.id) errs.push(`version.id is required (e.g. "V1") — ${noun}`);
388
+ if (!spec.version || !spec.version.name) errs.push('version.name is required');
389
+ if (!spec.version || !spec.version.done_when) errs.push(`version.done_when is required (what "done" means for ${noun})`);
390
+ }
391
+ for (const m of spec.modules || []) {
392
+ if (!KNOWN_MODULES.includes(m)) errs.push(`unknown module "${m}" (known: ${KNOWN_MODULES.join(', ')})`);
393
+ }
394
+ if (spec.provisioning) {
395
+ if (!HOSTING_SHAPES.includes(spec.provisioning.shape)) {
396
+ errs.push(`provisioning.shape must be one of: ${HOSTING_SHAPES.join(', ')}`);
397
+ }
398
+ if (provisioningSlug(spec).length < 2) {
399
+ errs.push('provisioning: could not derive a valid instance slug (need ≥2 chars of [a-z0-9-]) — set identity.productName or provisioning.slug');
400
+ }
401
+ }
402
+ return errs;
403
+ }
404
+
405
+ // Build the POST /api/gds/versions body from the spec (pure). The first version's
406
+ // done_when goal becomes both the version blurb and one done-when criterion, so
407
+ // /status has a finish line to roll up from day one.
408
+ function versionPayload(spec) {
409
+ const v = spec.version;
410
+ return {
411
+ id: v.id,
412
+ name: v.name,
413
+ status: v.status || 'building',
414
+ done_when: v.done_when,
415
+ criteria: [{ criterion_id: v.criterion_id ? slugify(v.criterion_id) : 'first-goal', criterion_md: v.done_when }],
416
+ };
417
+ }
418
+
419
+ // ---------------------------------------------------------------------------
420
+ // Interview (interactive)
421
+ // ---------------------------------------------------------------------------
422
+
423
+ function ask(rl, question, def) {
424
+ const suffix = def ? ` [${def}]` : '';
425
+ return new Promise((resolve) => rl.question(`${question}${suffix}\n> `, (a) => resolve((a || '').trim() || def || '')));
426
+ }
427
+
428
+ async function interview({ adopt = false } = {}) {
429
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
430
+ try {
431
+ console.log(adopt
432
+ ? "\nLet's adopt Cloud Bongos onto your existing repo.\n (layering only — pre-existing files are left untouched, never overwritten)\n"
433
+ : "\nLet's stand up a new Cloud Bongos instance.\n");
434
+ const productName = await ask(rl, 'Project name?');
435
+ const tagline = await ask(rl, 'One-line tagline? (optional)');
436
+ const repoRaw = await ask(rl, 'GitHub repo the work lands in? (owner/name)');
437
+ const firstAdmin = await ask(rl, 'First owner (GitHub login)?');
438
+ const currency = await ask(rl, 'Name for the reward currency?', 'credits');
439
+ const publicOrigin = await ask(rl, 'Where will it run?', 'http://localhost:3000');
440
+
441
+ const modules = [];
442
+ console.log('\nFeature modules (all off = plain build platform):');
443
+ for (const m of KNOWN_MODULES) {
444
+ const yn = (await ask(rl, ` Enable "${m}"? (y/N)`, 'N')).toLowerCase();
445
+ if (yn === 'y' || yn === 'yes') modules.push(m);
446
+ }
447
+
448
+ // The version + goal. Greenfield seeds a SYNTHETIC first version; --adopt reflects
449
+ // the repo's REAL current version/milestone + open goal (ADR 0121 §Decision 3 /
450
+ // task 2044) — same questions, real-state framing, no "Prove the loop" default.
451
+ console.log(adopt ? '\nYour CURRENT version / milestone (adopt reflects real state):' : '\nYour first version:');
452
+ const versionId = await ask(rl, ' Version id?', adopt ? '' : 'V1');
453
+ const versionName = await ask(rl, ' Version name?', adopt ? '' : `${versionId} — Prove the loop`);
454
+ const doneWhen = await ask(rl, adopt ? ' What is the current goal — what does "done" mean right now?' : ` What does "done" mean for ${versionName}?`,
455
+ adopt ? '' : 'A task goes claim → grade → ship, with credits, on this instance.');
456
+ // Greenfield asks for one optional starter; --adopt IMPORTS the existing backlog
457
+ // (GitHub issues / a local TODO·ROADMAP·BACKLOG file) at seed time, so instead it
458
+ // just offers to point at a backlog file when auto-detection might miss it.
459
+ const starter = adopt ? '' : await ask(rl, ' First starter task to claim? (optional)');
460
+ const backlogFile = adopt ? await ask(rl, ' Path to a backlog file to import? (optional — blank = auto-detect TODO/ROADMAP/BACKLOG or GitHub issues)') : '';
461
+
462
+ // Production hosting (ADR 0111 §3) — opt-in. When the owner answers these infra
463
+ // questions, init files a real provisioning REQUEST via the API (not just a manual
464
+ // runbook task). Default N: most inits are localhost/dev and shouldn't queue infra.
465
+ console.log('\nProduction hosting (optional — needs the provisioning module + control-plane credentials):');
466
+ let provisioning;
467
+ const wantProv = (await ask(rl, ' Provision production hosting now? (y/N)', 'N')).toLowerCase();
468
+ if (wantProv === 'y' || wantProv === 'yes') {
469
+ const shape = (await ask(rl, ' Hosting shape? (co-tenant = share an existing box, $0 / dedicated = its own droplet / standalone = its own repo + pinned @cloudbongos/core, ADR 0108)', 'co-tenant')).toLowerCase();
470
+ const domain = await ask(rl, ' Domain you own — bring-your-own (blank = none yet)?');
471
+ const targetRef = await ask(rl, ' Target credential ref? (which control-plane creds the runner should use; optional)');
472
+ let tier = '';
473
+ if (shape === 'dedicated') tier = await ask(rl, ' Droplet tier? (e.g. s-1vcpu-2gb; optional)');
474
+ provisioning = {
475
+ shape: HOSTING_SHAPES.includes(shape) ? shape : 'co-tenant',
476
+ domain: domain || undefined,
477
+ targetRef: targetRef || undefined,
478
+ tier: tier || undefined,
479
+ };
480
+ }
481
+
482
+ const [owner, name] = repoRaw.includes('/') ? repoRaw.split('/') : [repoRaw, ''];
483
+ const spec = {
484
+ identity: { productName },
485
+ tagline: tagline || undefined,
486
+ repo: { owner, name },
487
+ firstAdmin,
488
+ currency: { label: currency },
489
+ domains: { publicOrigin },
490
+ modules,
491
+ };
492
+ spec.version = { id: versionId, name: versionName, done_when: doneWhen };
493
+ if (starter) spec.starterTasks = [{ title: starter, kind: 'unclassified' }];
494
+ if (backlogFile) spec.backlogFile = backlogFile;
495
+ if (provisioning) spec.provisioning = provisioning;
496
+ return spec;
497
+ } finally {
498
+ rl.close();
499
+ }
500
+ }
501
+
502
+ // ---------------------------------------------------------------------------
503
+ // Write + seed
504
+ // ---------------------------------------------------------------------------
505
+
506
+ function writeConfigs(spec, { dir, force, dryRun, coreDep, log = console.log }) {
507
+ const configDir = path.join(dir, 'config');
508
+ const brandingPath = path.join(configDir, 'branding.json');
509
+ const modulesPath = path.join(configDir, 'modules.json');
510
+ const hierarchyPath = path.join(configDir, 'hierarchy.json');
511
+ const pkgPath = path.join(dir, 'package.json');
512
+ const branding = buildBrandingConfig(spec);
513
+ const modules = buildModulesConfig(spec);
514
+ const hierarchy = buildHierarchyConfig(spec);
515
+ // Greenfield OWNS package.json (ADR 0108 gap 1/4, task 2053): mint it — or augment one
516
+ // from a prior --force run — so the scaffold is `npm ci`-installable + runnable. Augment,
517
+ // never blind-overwrite, so a re-run keeps any hand-added fields/scripts.
518
+ const pkgName = slugify((spec.identity && spec.identity.productName) || '', 'cloudbongos-instance');
519
+ let existingPkg = null;
520
+ if (fs.existsSync(pkgPath)) { try { existingPkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); } catch { existingPkg = null; } }
521
+ const pkg = buildInstancePackageJson(existingPkg, { name: pkgName, coreDep });
522
+ const pinNote = pkg.dependencies[CORE_PKG];
523
+
524
+ if (dryRun) {
525
+ log(`\n[dry-run] would write ${brandingPath}:`);
526
+ log(JSON.stringify(branding, null, 2));
527
+ log(`\n[dry-run] would write ${modulesPath}:`);
528
+ log(JSON.stringify(modules, null, 2));
529
+ log(`\n[dry-run] would write ${hierarchyPath}:`);
530
+ log(JSON.stringify(hierarchy, null, 2));
531
+ log(`\n[dry-run] would write ${pkgPath} (pins ${CORE_PKG} → ${pinNote}):`);
532
+ log(JSON.stringify(pkg, null, 2));
533
+ return { brandingPath, modulesPath, hierarchyPath, pkgPath, wrote: false };
534
+ }
535
+ if (fs.existsSync(brandingPath) && !force) {
536
+ throw new Error(`${brandingPath} already exists — refusing to overwrite. Use --force to replace, or run init in a fresh --dir.`);
537
+ }
538
+ fs.mkdirSync(configDir, { recursive: true });
539
+ fs.writeFileSync(brandingPath, JSON.stringify(branding, null, 2) + '\n');
540
+ fs.writeFileSync(modulesPath, JSON.stringify(modules, null, 2) + '\n');
541
+ fs.writeFileSync(hierarchyPath, JSON.stringify(hierarchy, null, 2) + '\n');
542
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
543
+ log(` ✓ wrote ${path.relative(dir, brandingPath)}`);
544
+ log(` ✓ wrote ${path.relative(dir, modulesPath)}`);
545
+ log(` ✓ wrote ${path.relative(dir, hierarchyPath)}`);
546
+ log(` ✓ wrote ${path.relative(dir, pkgPath)} (pins ${CORE_PKG} → ${pinNote})`);
547
+ return { brandingPath, modulesPath, hierarchyPath, pkgPath, wrote: true };
548
+ }
549
+
550
+ // `--adopt` config layering (ADR 0121 §Decision 2 / task 2042). The additive
551
+ // sibling of writeConfigs: it does NOT refuse where config/branding.json exists and
552
+ // it NEVER overwrites. For each lean config file it WRITES only when absent, and
553
+ // LEAVES-AND-REPORTS when present. The greenfield writeConfigs — with its --force
554
+ // overwrite — is deliberately not reused: a brownfield repo is exactly where an
555
+ // overwrite is expensive. Returns { wrote:[names], left:[names] }.
556
+ function layerConfigs(spec, { dir, dryRun, log = console.log }) {
557
+ const configDir = path.join(dir, 'config');
558
+ const targets = [
559
+ ['branding.json', buildBrandingConfig(spec)],
560
+ ['modules.json', buildModulesConfig(spec)],
561
+ ['hierarchy.json', buildHierarchyConfig(spec)],
562
+ ];
563
+ const wrote = [];
564
+ const left = [];
565
+ for (const [name, content] of targets) {
566
+ const p = path.join(configDir, name);
567
+ if (fs.existsSync(p)) {
568
+ left.push(name);
569
+ log(` • config/${name} already present — left untouched (adopt never overwrites).`);
570
+ continue;
571
+ }
572
+ wrote.push(name);
573
+ if (dryRun) { log(` [dry-run] would write config/${name}`); continue; }
574
+ fs.mkdirSync(configDir, { recursive: true });
575
+ fs.writeFileSync(p, JSON.stringify(content, null, 2) + '\n');
576
+ log(` ✓ wrote config/${name}`);
577
+ }
578
+ return { wrote, left };
579
+ }
580
+
581
+ // `--adopt` package.json layering (ADR 0121 §Decision 2 / task 2042): add the
582
+ // pinned @cloudbongos/core dependency to the owner's EXISTING package.json without
583
+ // touching any other field, or MINT a minimal one when the repo has none. When the
584
+ // dep is already present the file is left byte-untouched (no reserialize). An
585
+ // unparseable package.json is left alone with a report — adopt never risks
586
+ // corrupting a file it can't safely rewrite. Returns { action, path }.
587
+ function layerPackageJson(spec, { dir, dryRun, log = console.log, coreRange = coreDepRange() } = {}) {
588
+ const p = path.join(dir, 'package.json');
589
+ let existing = null;
590
+ if (fs.existsSync(p)) {
591
+ try { existing = JSON.parse(fs.readFileSync(p, 'utf8')); }
592
+ catch (e) {
593
+ log(` • package.json exists but is not valid JSON (${e.message}) — left untouched; add "${CORE_PKG}": "${coreRange}" to its dependencies by hand.`);
594
+ return { action: 'unparseable', path: p };
595
+ }
596
+ }
597
+ const name = slugify((spec.identity && spec.identity.productName) || '', 'cloudbongos-instance');
598
+ const { pkg, action } = mergeCoreDependency(existing, { coreRange, name });
599
+ if (action === 'present') {
600
+ log(` • ${CORE_PKG} already a dependency — package.json left untouched.`);
601
+ return { action, path: p };
602
+ }
603
+ const verb = action === 'created' ? 'create package.json pinning' : 'add';
604
+ const tail = action === 'added' ? ' to dependencies (existing fields preserved)' : '';
605
+ if (dryRun) { log(` [dry-run] would ${verb} ${CORE_PKG}@${coreRange}${tail}`); return { action, path: p }; }
606
+ fs.writeFileSync(p, JSON.stringify(pkg, null, 2) + '\n');
607
+ log(` ✓ ${action === 'created' ? 'created package.json pinning' : 'added'} ${CORE_PKG}@${coreRange}${tail}`);
608
+ return { action, path: p };
609
+ }
610
+
611
+ async function seedViaApi(spec, { dryRun, log = console.log, api = apiCall } = {}) {
612
+ const vp = versionPayload(spec);
613
+ const starters = Array.isArray(spec.starterTasks) ? spec.starterTasks : [];
614
+ const kickoff = kickoffTasks(spec);
615
+ const pr = provisioningRequest(spec); // ADR 0111 §3 — null unless the owner opted in
616
+
617
+ if (dryRun) {
618
+ log(`\n[dry-run] would POST /api/gds/versions:`);
619
+ log(JSON.stringify(vp, null, 2));
620
+ log(`\n[dry-run] would create ${starters.length} starter + ${kickoff.length} kickoff task(s) under ${vp.id}.`);
621
+ if (pr) {
622
+ log(`\n[dry-run] would POST /api/gds/provisioning/instances:`);
623
+ log(JSON.stringify(pr, null, 2));
624
+ log(` (queues a 'provision' intent; the control-plane runner stands up hosting — ADR 0111 §2/§3.`);
625
+ log(` production-topology is left OFF the kickoff list since it's now automated.)`);
626
+ }
627
+ return { seeded: false };
628
+ }
629
+
630
+ // 1. version + first goal
631
+ const vres = await api('POST', '/api/gds/versions', vp);
632
+ if (!vres.ok && vres.status !== 409) {
633
+ throw new Error(`POST /versions failed (${vres.status}): ${JSON.stringify(vres.data)}`);
634
+ }
635
+ if (vres.status === 409) log(` • version ${vp.id} already exists — continuing.`);
636
+ else log(` ✓ created version ${vp.id} + 1 done-when goal`);
637
+ const criterionId = vp.criteria[0].criterion_id;
638
+
639
+ // A tracked kickoff/starter task (status ready, engineer discipline). Returns true on success.
640
+ const postTask = async (t, extra = {}) => {
641
+ const res = await api('POST', '/api/gds/tasks', {
642
+ version_id: vp.id, title: t.title, description: t.description || '', status: 'ready',
643
+ kind: t.kind || 'infra', discipline: 'engineer', source: 'bongos-init', ...extra,
644
+ });
645
+ return res.ok;
646
+ };
647
+
648
+ // 2. starter task(s) — linked to the first goal so /status rolls them up
649
+ let created = 0;
650
+ for (const t of starters) {
651
+ if (await postTask(t, { kind: t.kind || 'unclassified', discipline: undefined, criterion_ids: [criterionId] })) created++;
652
+ }
653
+ // 3. kickoff steps as tracked tasks
654
+ for (const t of kickoff) {
655
+ if (await postTask(t)) created++;
656
+ }
657
+
658
+ // 4. Provisioning arm (ADR 0111 §3): the infra answers become a real provisioning
659
+ // REQUEST, not just a manual runbook task. kickoffTasks already omitted the
660
+ // production-topology step when pr is set — so if the request can't be enqueued
661
+ // (module not enabled on the target instance → 404, or a transient failure), we
662
+ // re-file that manual step here so the leg is never silently dropped.
663
+ let provisioned = false;
664
+ if (pr) {
665
+ const pres = await api('POST', '/api/gds/provisioning/instances', pr);
666
+ if (pres.ok) {
667
+ provisioned = true;
668
+ const inst = (pres.data && pres.data.instance) || {};
669
+ const cost = Number(inst.cost_estimate_usd || 0);
670
+ log(` ✓ requested provisioning of instance "${pr.slug}" (${pr.hosting_shape}${pr.domain ? `, ${pr.domain}` : ''})` +
671
+ `${cost ? ` — est. $${cost}/mo` : ''} — a provision intent is queued for the control-plane runner`);
672
+ } else {
673
+ const why = pres.status === 404
674
+ ? 'the provisioning module is not enabled on this instance'
675
+ : `the provisioning request failed (${pres.status}: ${JSON.stringify(pres.data)})`;
676
+ log(` • ${why} — filing the manual production-topology task instead`);
677
+ if (await postTask(productionTopologyKickoff())) created++;
678
+ }
679
+ }
680
+
681
+ const kickoffLabel = provisioned ? `${kickoff.length} kickoff + provisioning request` : `${kickoff.length} kickoff`;
682
+ log(` ✓ filed ${created} task(s) (${starters.length} starter + ${kickoffLabel})`);
683
+ return { seeded: true, created, provisioned };
684
+ }
685
+
686
+ // ---------------------------------------------------------------------------
687
+ // adopt (brownfield) — LAYER onto an existing repo (ADR 0121 / task 2042)
688
+ // ---------------------------------------------------------------------------
689
+
690
+ // Interactive accept-gate for the pre-flight (ADR 0121 §Decision 5). Default No, so a
691
+ // bare Enter never writes. Only reached when there are no BLOCKING findings (those hard-
692
+ // stop before the prompt). Split out for testability (injectable input/output).
693
+ function confirmProceed({ input = process.stdin, output = process.stdout } = {}) {
694
+ const rl = readline.createInterface({ input, output });
695
+ return new Promise((resolve) => rl.question('\nProceed with layering + seeding onto this repo? (y/N) ', (a) => { rl.close(); resolve(/^y(es)?$/i.test((a || '').trim())); }));
696
+ }
697
+
698
+ // The brownfield sibling of main()'s greenfield body: LAYER Cloud Bongos onto an
699
+ // EXISTING repo without clobbering, then reflect its REAL state. It (1) detects the
700
+ // stack (task 2043), (2) runs an accept-gated conflict PRE-FLIGHT (task 2045) — nothing
701
+ // is written until the owner accepts — then, on accept, (3) writes the lean config where
702
+ // absent + adds the pinned core dep + copies .claude/ ADDITIVELY (task 2042) and (4)
703
+ // seeds the repo's REAL version/goal + IMPORTS its existing backlog (task 2044), NOT a
704
+ // synthetic "V1 — Prove the loop". `--dry-run` previews everything and writes nothing;
705
+ // `--no-seed` layers without seeding. Returns a process exit code.
706
+ async function runAdopt(spec, { dir, dryRun, noSeed = false, accept = false, log = console.log }) {
707
+ log(`\nAdopting Cloud Bongos onto the existing repo at "${dir}"${dryRun ? ' (dry run — nothing will be written or created)' : ''}:`);
708
+ log(' Layering — pre-existing files are left untouched; nothing is overwritten.');
709
+
710
+ // Inspect the tree BEFORE writing anything (ADR 0121 §Decision 4 / task 2043) so
711
+ // layering fits what is already here.
712
+ const stack = detectStack({ dir });
713
+ log('\nDetected stack + layout:');
714
+ for (const line of formatStackSummary(stack)) log(` • ${line}`);
715
+
716
+ // Conflict PRE-FLIGHT (ADR 0121 §Decision 5 / task 2045): report the blast radius, then
717
+ // gate the writes on the owner's acceptance. --dry-run previews without writing, so it
718
+ // needs no gate; a real run proceeds only on --accept or an interactive yes.
719
+ const report = preflightAdopt({ dir, stack });
720
+ log('\nConflict pre-flight (nothing is written until you accept):');
721
+ for (const line of formatPreflight(report)) log(line);
722
+ log(` → ${report.counts.blocking} blocking · ${report.counts.warning} warning · ${report.counts.info} ok`);
723
+ if (!dryRun) {
724
+ // A BLOCKING finding (e.g. a migration that WILL collide) is a hard stop — it can't
725
+ // be waved through with --accept; the owner must resolve it and re-run.
726
+ if (report.hasBlocking) {
727
+ log(`\n✗ ${report.counts.blocking} BLOCKING conflict(s) above — resolve them, then re-run. Nothing was written.`);
728
+ return 2;
729
+ }
730
+ const proceed = accept || (process.stdin.isTTY ? await confirmProceed() : false);
731
+ if (!proceed) {
732
+ log('\nPre-flight only — nothing was written. Re-run with --accept (or confirm interactively) to apply.');
733
+ return 0;
734
+ }
735
+ }
736
+
737
+ const cfg = layerConfigs(spec, { dir, dryRun, log });
738
+ const pkg = layerPackageJson(spec, { dir, dryRun, log });
739
+
740
+ log('\nMaterializing the .claude/ methodology surface (additive — existing files left untouched):');
741
+ const claude = materializeClaude({ coreRoot: resolveCoreRoot(), instanceDir: dir, dryRun, overwrite: false, log });
742
+
743
+ // Reflect REAL state (ADR 0121 §Decision 3 / task 2044): import the existing backlog,
744
+ // then seed the repo's REAL version/goal + the imported tasks + the (identical) human-
745
+ // only kickoff steps via the same seedViaApi greenfield uses — so the ledger starts
746
+ // truthful, not empty. `--no-seed` layers only (the task-2042 skeleton behavior).
747
+ let backlog = { source: 'none', tasks: [], truncated: false };
748
+ if (!noSeed) {
749
+ const githubToken = process.env.GITHUB_TOKEN || process.env.GH_TOKEN || null;
750
+ backlog = await resolveBacklogTasks({ dir, repo: spec.repo, githubToken, backlogFile: spec.backlogFile, onWarn: (m) => log(` • ${m}`) });
751
+ // Imported tasks ride in as starterTasks so seedViaApi links them to the goal's criterion.
752
+ if (backlog.tasks.length) spec.starterTasks = [...(spec.starterTasks || []), ...backlog.tasks];
753
+ const importNote = backlog.tasks.length
754
+ ? `${backlog.tasks.length} imported task(s) from ${backlog.source}${backlog.truncated ? ` (capped at ${BACKLOG_MAX})` : ''}`
755
+ : 'no backlog found (capture tasks later)';
756
+ log(`\nReflecting real state — seeding version "${spec.version && spec.version.id}" + goal + ${importNote}:`);
757
+ await seedViaApi(spec, { dryRun, log });
758
+ } else {
759
+ log('\n (--no-seed: layered config only; skipped real-state seeding)');
760
+ }
761
+
762
+ const leftFiles = cfg.left.length
763
+ + (Array.isArray(claude.skippedFiles) ? claude.skippedFiles.length : 0)
764
+ + (pkg.action === 'present' || pkg.action === 'unparseable' ? 1 : 0);
765
+
766
+ log(`\n${dryRun ? 'Dry run complete — re-run without --dry-run (and --accept) to apply.' : 'Adopted.'} Next:`);
767
+ if (report.counts.warning > 0) log(` • ${report.counts.warning} pre-flight warning(s) above — reconcile them (esp. migrations / CI check names) as you settle in.`);
768
+ if (leftFiles > 0) log(` • ${leftFiles} pre-existing file(s) were left untouched — reconcile them against what a fresh instance ships.`);
769
+ log(' • fill the look: hand docs/branding-fill-prompt.md to your own LLM (or keep your existing branding).');
770
+ log(` • sign in as ${spec.firstAdmin} to seat yourself as the founding owner.`);
771
+ return 0;
772
+ }
773
+
774
+ // ---------------------------------------------------------------------------
775
+ // main
776
+ // ---------------------------------------------------------------------------
777
+
778
+ async function main(argv) {
779
+ const args = argv.slice(2);
780
+ const fromPath = arg('--from', args);
781
+ const dir = path.resolve(arg('--dir', args) || process.cwd());
782
+ const dryRun = hasFlag('--dry-run', args);
783
+ const force = hasFlag('--force', args);
784
+ const noSeed = hasFlag('--no-seed', args);
785
+ const adopt = hasFlag('--adopt', args); // brownfield: LAYER onto an existing repo (ADR 0121)
786
+ const accept = hasFlag('--accept', args) || hasFlag('--yes', args) || hasFlag('-y', args); // adopt pre-flight accept-gate (§Decision 5)
787
+ const vendorCore = arg('--vendor-core', args); // greenfield: vendor + file:-pin a core .tgz, then generate the lockfile (ADR 0108 gap 1/4, task 2053)
788
+
789
+ if (adopt && force) {
790
+ console.error('init: --force is a greenfield-only overwrite; --adopt never overwrites, so --force is ignored.');
791
+ }
792
+
793
+ let raw;
794
+ if (fromPath) {
795
+ try {
796
+ raw = JSON.parse(fs.readFileSync(path.resolve(fromPath), 'utf8'));
797
+ } catch (e) {
798
+ console.error(`init: could not read spec ${fromPath}: ${e.message}`);
799
+ return 1;
800
+ }
801
+ } else {
802
+ raw = await interview({ adopt });
803
+ }
804
+
805
+ const spec = normalizeSpec(raw);
806
+ const errs = validateSpec(spec, { adopt, noSeed });
807
+ if (errs.length) {
808
+ console.error('\ninit: the spec is incomplete:');
809
+ for (const e of errs) console.error(` • ${e}`);
810
+ return 1;
811
+ }
812
+
813
+ // Brownfield (ADR 0121): a distinct LAYER + real-state path — never the greenfield
814
+ // scaffold/overwrite below. Its own report + next-steps live in runAdopt.
815
+ if (adopt) return await runAdopt(spec, { dir, dryRun, noSeed, accept });
816
+
817
+ // Greenfield core-dep resolution (ADR 0108 gap 1/4, task 2053). With --vendor-core, pin
818
+ // package.json to the vendored `file:` tarball (the caret range resolves NOWHERE on npm,
819
+ // so a caret-only scaffold can't `npm ci`); the tarball is copied + the lockfile generated
820
+ // just below. Without it, the scaffold carries the declared caret (a local/dev scaffold the
821
+ // owner resolves another way). Reuses the bongos-upgrade vendoring + install steps.
822
+ const upgrade = require('./upgrade');
823
+ let coreDep = null; // null → writeConfigs writes the caret range
824
+ let vendorPlan = null;
825
+ if (vendorCore) {
826
+ const tgz = path.resolve(vendorCore);
827
+ if (!fs.existsSync(tgz)) {
828
+ console.error(`init: --vendor-core tarball not found: ${tgz}`);
829
+ return 1;
830
+ }
831
+ const version = upgrade.versionFromTgzPath(tgz) || coreVersionSafe();
832
+ if (!version) {
833
+ console.error(`init: could not derive the core version from ${path.basename(tgz)} — expected a tarball named ${upgrade.ARTIFACT}-<version>.tgz (produced by \`node scripts/gds/package-core.js\`).`);
834
+ return 1;
835
+ }
836
+ const vendorRel = path.join('vendor', `${upgrade.ARTIFACT}-${version}.tgz`);
837
+ coreDep = `file:${vendorRel}`;
838
+ vendorPlan = { tgz, version, vendorRel };
839
+ }
840
+
841
+ console.log(`\nScaffolding "${spec.identity.productName}"${dryRun ? ' (dry run — nothing will be written or created)' : ''}:`);
842
+ writeConfigs(spec, { dir, force, dryRun, coreDep });
843
+
844
+ // Vendor the pinned @cloudbongos/core tarball + generate the lockfile so the scaffold is
845
+ // `npm ci --omit=dev`-installable by the provisioner (ADR 0108 gap 1/4, task 2053). The
846
+ // `npm install` here is the ONLY heavy step — it CREATES package-lock.json from the file:
847
+ // tarball; the provisioner later runs `npm ci` against that committed lockfile.
848
+ if (vendorPlan) {
849
+ if (dryRun) {
850
+ console.log(`\n[dry-run] would vendor ${vendorPlan.tgz} → ${vendorPlan.vendorRel} and run \`npm install\` to generate package-lock.json`);
851
+ } else {
852
+ console.log('\nVendoring the pinned @cloudbongos/core + generating the lockfile:');
853
+ upgrade.vendorTarball({ instanceDir: dir, fromTgz: vendorPlan.tgz, targetVersion: vendorPlan.version });
854
+ console.log(` ✓ vendored ${vendorPlan.vendorRel}`);
855
+ const inst = upgrade.npmInstall(dir);
856
+ if (!inst.ok) {
857
+ console.error(` ! npm install failed (${inst.reason || 'exit ' + inst.code}) — package-lock.json not generated; run \`npm install\` in ${dir} by hand before provisioning.`);
858
+ } else {
859
+ console.log(' ✓ npm install → package-lock.json generated (node_modules/@cloudbongos/core installed)');
860
+ }
861
+ }
862
+ }
863
+
864
+ // Materialize the .claude/ methodology surface (ADR 0108 §3 / W3): Claude Code reads skills +
865
+ // hooks + settings.json from the project root, never node_modules, so init copies them from the
866
+ // core package into the instance and rewrites `node scripts/gds/<x>.js` → the `bongos` bin.
867
+ // A no-op when the instance dir IS the core checkout (self-copy guard).
868
+ console.log('\nMaterializing the .claude/ methodology surface:');
869
+ materializeClaude({ coreRoot: resolveCoreRoot(), instanceDir: dir, dryRun, log: console.log });
870
+
871
+ let seedResult = {};
872
+ if (!noSeed) seedResult = (await seedViaApi(spec, { dryRun })) || {};
873
+ else console.log(' (--no-seed: skipped version/task seeding)');
874
+
875
+ console.log(`\n${dryRun ? 'Dry run complete.' : 'Done.'} Next:`);
876
+ console.log(' • fill the look: hand docs/branding-fill-prompt.md to your own LLM');
877
+ console.log(` • sign in as ${spec.firstAdmin} to become the owner, then run \`bongos start\` to see the kickoff tasks`);
878
+ console.log(' • work through the kickoff tasks the way you would any task: claim → ship');
879
+ if (seedResult.provisioned) {
880
+ console.log(` • the control-plane runner (\`bongos provision run-intents --apply\`) will stand up your hosting — watch it in the hall's Instances panel`);
881
+ } else if (provisioningRequest(spec) && !dryRun) {
882
+ console.log(' • provisioning wasn\'t enqueued (module off / request failed) — the manual production-topology task is in your queue');
883
+ }
884
+ return 0;
885
+ }
886
+
887
+ module.exports = {
888
+ buildBrandingConfig, buildModulesConfig, buildHierarchyConfig, kickoffTasks, normalizeSpec,
889
+ validateSpec, versionPayload, slugify, writeConfigs, seedViaApi, interview, main,
890
+ provisioningSlug, provisioningRequest, productionTopologyKickoff,
891
+ // --adopt (brownfield layering, ADR 0121 / task 2042)
892
+ mergeCoreDependency, coreDepRange, layerConfigs, layerPackageJson, runAdopt,
893
+ KNOWN_MODULES, HOSTING_SHAPES, CORE_PKG,
894
+ // greenfield installability (ADR 0108 gap 1/4, task 2053)
895
+ buildInstancePackageJson, coreVersionSafe, INSTANCE_START_SCRIPT, INSTANCE_MIGRATE_SCRIPT,
896
+ };
897
+
898
+ if (require.main === module) {
899
+ main(process.argv).then((code) => process.exit(code)).catch((err) => {
900
+ console.error(`init: ${err.message}`);
901
+ process.exit(1);
902
+ });
903
+ }