@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,416 @@
1
+ # Recipe - managed-settings SSH + browser-terminal on-ramps
2
+
3
+ > **Task [#599](https://example.com/builders#/task/599) · [ADR 0031](../adr/<redacted>.md) §1.** This is the operator guide for distributing a locked Claude Desktop SSH connection to builders and for serving the browser web-terminal on the box. Read [builder-box-lifecycle.md](builder-box-lifecycle.md) first — this recipe assumes a box is already provisioned and running.
4
+
5
+ > **Chromebook/browser path (ADR 0038 → [ADR 0040](../adr/<redacted>.md), [#760](https://example.com/builders#/task/760) / [#824](https://example.com/builders#/task/824)):** the box serves its own web terminal - `ttyd` bound to localhost, exposed via an outbound-only Cloudflare Tunnel - and the builder runs a NORMAL interactive `claude` inside it from any browser. Because there is a real human at a real browser-backed terminal, `/login`, workspace-trust, and Trusted-Devices enrollment all succeed (the things that made headless `claude rc` unworkable). **ADR 0040 narrows that terminal to a one-time launchpad:** the builder logs in there once, runs the in-session **`/remote-control`** slash command, and then drives the box from the Claude web/mobile app — the terminal is no longer their daily surface. **The SSH path (Mac/Windows) below is unaffected and works.**
6
+
7
+ ---
8
+
9
+ ## The two on-ramps
10
+
11
+ | Builder's device | Path | What this recipe wires |
12
+ |---|---|---|
13
+ | **Mac / Windows** | Claude Desktop → SSH → box | Pre-distributed `managed-settings.json` (locked `sshConfigs`) |
14
+ | **Chromebook / any browser** | Browser -> `ttyd` web terminal over an outbound Cloudflare Tunnel -> box (reached at `GET /box/terminal`) -> log in once, then `/remote-control` -> drive the box from the Claude web/mobile app (ADR 0040) | `box-terminal.service` (ttyd, localhost-only) + `cloudflared.service` (outbound tunnel) + `box-report-terminal` cron |
15
+
16
+ Both paths land the builder on the same box and the same `/workspace`. The choice is which GUI they prefer, not which machine they reach.
17
+
18
+ ---
19
+
20
+ ## Part 0 — the one-command flow ([#685](https://example.com/builders#/task/685), the default)
21
+
22
+ > **This is the path to use now.** Parts 1, 3 and 4 below document the underlying
23
+ > pieces (and the manual fallbacks); [#685](https://example.com/builders#/task/685) collapses the builder's side to a single
24
+ > command and the operator's side to a single command. Nobody has to `scp` a JSON
25
+ > file, paste a public key into `authorized_keys`, or `sudo cp` anything by hand.
26
+
27
+ **The split:**
28
+
29
+ | Who | Runs | What it does |
30
+ |---|---|---|
31
+ | **Builder** (own Mac/Windows) | `/builder-connect` — or, on a bare laptop, the hosted bootstrap (below) | GitHub sign-in → create+register their SSH key → install `managed-settings.json` |
32
+ | **Operator** (control plane) | `node scripts/gds/box.js onboard <login> --apply` | provision the box (bakes the builder's registered key) + print the welcome packet |
33
+
34
+ **Builder side** — guided in Claude Desktop (`/builder-connect`), or paste the hosted bootstrap on a bare laptop:
35
+
36
+ ```bash
37
+ # macOS / Linux
38
+ curl -fsSL https://example.com/api/gds/box/connect.sh | bash
39
+ # Windows (PowerShell)
40
+ irm https://example.com/api/gds/box/connect.ps1 | iex
41
+ # Plain-text guide (no auth): https://example.com/api/gds/box/connect
42
+ ```
43
+
44
+ The bootstrap (`infra/box-connect.sh` / `.ps1`, served by `GET /box/connect.sh|.ps1`)
45
+ is self-contained — only `curl` + `ssh-keygen` (or PowerShell). It device-flow signs
46
+ the builder in, creates `~/.ssh/otb_builder` if absent, registers the **public** key
47
+ (`POST /box/ssh-key`), and downloads + installs `managed-settings.json`
48
+ (`GET /box/managed-settings`) at the OS path. The private key never leaves the machine;
49
+ the token is held only in memory for the two authenticated calls (passed to `curl` via a
50
+ 0600 config file, never on the command line).
51
+
52
+ > **Operator note (staging):** the served script's `GDS_API_BASE` is pinned to
53
+ > `GDS_PUBLIC_ORIGIN` (default `https://example.com`) — the SAME env var the OAuth
54
+ > `redirect_uri` uses — and is **never** derived from a request header, so a spoofed
55
+ > `Host` can't redirect a victim's `curl … | bash`. On staging, set
56
+ > `GDS_PUBLIC_ORIGIN=https://staging.example.com` in the server env (you already do,
57
+ > for OAuth) and the connect scripts target staging automatically.
58
+
59
+ **Operator side:**
60
+
61
+ ```bash
62
+ node scripts/gds/box.js onboard <login> # dry-run: shows the plan + key count
63
+ node scripts/gds/box.js onboard <login> --apply # provision + print the welcome packet
64
+ ```
65
+
66
+ `onboard` refuses if the builder has **no registered SSH key** (the box would have no
67
+ way in) — the canonical order is **builder connects first, then operator onboards**.
68
+ Override with `--allow-no-keys` only if you will re-provision once they register a key.
69
+
70
+ **How the key reaches the box without an operator SSH round-trip:** `box.js` reads the
71
+ builder's registered keys from the DB and **bakes** them into the cloud-init managed
72
+ block at provision (so the first login works before the box has any GDS token). From
73
+ then on, `infra/<redacted>.sh` (a 10-min cron on the box, wired by the
74
+ cloud-init) keeps `authorized_keys` in sync via `GET /box/authorized-keys` — which is
75
+ **gated on the builder's LIVE rank+status** exactly like source access ([#600](https://example.com/builders#/task/600)). A
76
+ demoted/deactivated builder gets a 403 and the cron empties the managed block — instant
77
+ SSH-login revocation — **without touching the operator's own key** (only the lines
78
+ between the `otb-managed` markers are rewritten). The droplet teardown follows via
79
+ `box.js reconcile`.
80
+
81
+ The rest of this recipe is the manual decomposition + fallbacks.
82
+
83
+ ---
84
+
85
+ ## Part 1 — Claude Desktop SSH (Mac / Windows)
86
+
87
+ ### How it works
88
+
89
+ The builder installs Claude Desktop (free; no paid plan needed for the app shell). You pre-distribute a `managed-settings.json` that contains the SSH connection for their box. When they open Claude Desktop → Code → Environment, they see exactly one entry: **"Example Dev Box"** — no configuration required on their end.
90
+
91
+ Claude Desktop SSHes to the box, auto-installs Claude Code on the host (on first connect), and starts a Code session directly in `/workspace`. The builder is ready to work.
92
+
93
+ ### Step 1 — Provision the box
94
+
95
+ ```bash
96
+ node scripts/gds/box.js provision <login> --apply
97
+ ```
98
+
99
+ This creates the DigitalOcean droplet, runs the cloud-init, and registers the box. The builder's hostname is `box-<login>.dev.example.com`.
100
+
101
+ ### Step 2 — Generate the managed-settings.json
102
+
103
+ ```bash
104
+ bash infra/gen-managed-settings.sh <login> > /tmp/<login>-managed-settings.json
105
+ cat /tmp/<login>-managed-settings.json
106
+ ```
107
+
108
+ The output is a small JSON file, e.g.:
109
+
110
+ ```json
111
+ {
112
+ "sshConfigs": [
113
+ {
114
+ "id": "otb-alice",
115
+ "name": "Example Dev Box",
116
+ "sshHost": "root@box-alice.dev.example.com",
117
+ "sshIdentityFile": "~/.ssh/otb_builder",
118
+ "startDirectory": "/workspace"
119
+ }
120
+ ],
121
+ "sshHostAllowlist": ["*.dev.example.com"]
122
+ }
123
+ ```
124
+
125
+ ### Step 3 — Give it to the builder
126
+
127
+ Send them the file and these instructions (copy-paste friendly):
128
+
129
+ > **Mac:** Open Terminal and run:
130
+ > ```bash
131
+ > sudo mkdir -p "/Library/Application Support/ClaudeCode"
132
+ > sudo cp ~/Downloads/<login>-managed-settings.json "/Library/Application Support/ClaudeCode/managed-settings.json"
133
+ > ```
134
+ > Then restart Claude Desktop. You'll see "Example Dev Box" in Code → Environment.
135
+ >
136
+ > **Windows:** Save the file to `C:\Program Files\ClaudeCode\managed-settings.json` (create the folder if it doesn't exist; needs Administrator). Restart Claude Desktop.
137
+
138
+ > ⚠️ **The directory is `ClaudeCode`, not `Claude`.** Claude Code reads managed settings from `/Library/Application Support/ClaudeCode/` (macOS) and `%ProgramFiles%\ClaudeCode\` (Windows). A file under `…/Claude/` or `%ProgramData%\Claude\` is silently ignored and the box never appears in the Environment picker (the [#808](https://example.com/builders#/task/808) onboarding bug). The legacy `%ProgramData%\ClaudeCode\` Windows path was dropped in v2.1.75.
139
+
140
+ ### Step 4 — Builder's SSH key
141
+
142
+ The `managed-settings.json` points to `~/.ssh/otb_builder` as the identity file. The builder needs this key pair generated on their machine, and you need to add the **public key** to the box.
143
+
144
+ **Builder runs (once):**
145
+ ```bash
146
+ ssh-keygen -t ed25519 -f ~/.ssh/otb_builder -C "otb-builder"
147
+ cat ~/.ssh/otb_builder.pub
148
+ ```
149
+
150
+ **Operator adds the public key to the box:**
151
+ ```bash
152
+ ssh root@box-<login>.dev.example.com \
153
+ "echo '<public key here>' >> ~/.ssh/authorized_keys"
154
+ ```
155
+
156
+ Or, if the builder's key is already registered as a DO SSH key, pass it via `BOX_SSH_KEY_IDS` at provision time so it's injected automatically.
157
+
158
+ ### What `sshHostAllowlist` does
159
+
160
+ The `sshHostAllowlist: ["*.dev.example.com"]` entry prevents the builder from using Claude Desktop SSH to connect to arbitrary hosts. Their SSH picker only shows the pre-configured OTB box — they can't misconfigure or wander off it. This is a `managed-settings`-only field; user-level settings cannot override it.
161
+
162
+ ---
163
+
164
+ ## Part 2 - Browser on-ramp: terminal launchpad -> Remote Control (Chromebook / any browser) - ADR 0038 -> [ADR 0040](../adr/<redacted>.md), [#760](https://example.com/builders#/task/760) / [#824](https://example.com/builders#/task/824)
165
+
166
+ ### How it works
167
+
168
+ The box serves its own web terminal. Two systemd units do the work:
169
+
170
+ - **`box-terminal.service`** runs `ttyd` (a web-terminal daemon) bound to `127.0.0.1:7681`, basic-auth protected with a per-box generated password, dropping whoever connects into a shell in `/workspace`. It listens on localhost only - the box opens **no inbound port**.
171
+ - **`cloudflared.service`** (via `infra/cloudflared-run.sh`) runs a Cloudflare Tunnel that makes that localhost terminal reachable from a browser. The tunnel is **outbound-only**: the box dials out to Cloudflare, so nothing has to be opened in the firewall.
172
+
173
+ The builder opens the tunnel URL in any browser, authenticates at the basic-auth prompt, and then runs a **normal interactive `claude`** in the terminal. The first `claude` run prompts a normal browser `/login`; because there is a real human at a real browser-backed terminal, `/login`, workspace-trust, and Trusted-Devices enrollment all succeed - the exact steps that headless `claude rc` could never perform.
174
+
175
+ **The terminal is a one-time launchpad, not the daily surface (ADR 0040).** Once the builder is signed in to that interactive `claude` session, they run the in-session **`/remote-control`** slash command. It prints a pairing link; opening that link drives the box from the Claude web/mobile app. From there the builder lives in the Claude app — the ttyd terminal is just where they logged in and kicked RC off.
176
+
177
+ > ⚠️ **Use the in-session `/remote-control` slash command — NOT the standalone `claude rc` shell command.** The standalone command mis-checks workspace trust ([anthropics/claude-code#35817](https://github.com/anthropics/claude-code/issues/35817)): it reports `Workspace not trusted` even when the directory is trusted, and a plain shell can't accept the trust dialog. Starting RC from *inside* an already-running, already-trusted `claude` session is the working path (verified live 2026-06-07). Closing the terminal window ends the remote session and closes the box — a property of the session lifecycle, stated up front so builders aren't surprised.
178
+
179
+ > **Workspace trust is pre-seeded ([#824](https://example.com/builders#/task/824)).** The cloud-init writes `/root/.claude.json` with `<redacted>` for `/root` + `/workspace`, so the first `claude` launch usually skips the trust dialog entirely. This is **non-load-bearing** (ADR 0040): the seed is best-effort and only written when the file is absent (upstream pre-seeding is flaky, [#9113](https://github.com/anthropics/claude-code/issues/9113)). If it doesn't take, the builder just accepts trust once — the flow works either way.
180
+
181
+ The cloud-init wires both units automatically (and `infra/box-source-fetch.sh` re-installs them on its post-clone bring-up, so a box provisioned before this shipped picks them up on its next refresh). It copies `infra/box-terminal.service` and `infra/cloudflared.service` to `/etc/systemd/system/`, enables them with `systemctl enable --now`, and wires `infra/box-report-terminal.sh` as a 1-minute cron that publishes the terminal URL + credential **up** to the GDS (`POST /box/terminal`) so the builder's self-serve flow can read them back.
182
+
183
+ **Tunnel modes:**
184
+
185
+ - **Quick tunnel (default, zero operator secrets).** `cloudflared` opens a tokenless quick tunnel and gets a random `https://<id>.trycloudflare.com` hostname. Nothing to configure - works out of the box.
186
+ - **Named tunnel (production upgrade, stable hostname).** When `/etc/otb/box.env` carries `BOX_TUNNEL_TOKEN` + `BOX_TERMINAL_HOSTNAME`, `cloudflared` runs a named tunnel instead and the terminal is reachable at a stable `term-<login>.example.com` host. As of [#771](https://example.com/builders#/task/771) the control plane **creates and bakes those automatically** on `box.js provision` (and tears them down on `deprovision`) — see the [named-tunnel automation](#<redacted>) section below.
187
+
188
+ ### Getting onto the terminal (builder self-serve)
189
+
190
+ No SSH and no pairing script - two API calls:
191
+
192
+ ```bash
193
+ # 1. Get a box (provisions or wakes it; see Part 0 / #701):
194
+ POST /api/gds/box/ensure
195
+
196
+ # 2. Poll until the box has reported its terminal up:
197
+ GET /api/gds/box/terminal
198
+ # -> {"url": "https://<id>.trycloudflare.com", "credential": "<redacted>"}
199
+ ```
200
+
201
+ Then:
202
+
203
+ 1. Open the returned `url` in a browser.
204
+ 2. At the browser's basic-auth prompt, enter username **`otb`** and the password (the `credential` value).
205
+ 3. In the terminal, type `claude` and press enter. On first run it walks the normal browser `/login` (workspace trust is pre-seeded, [#824](https://example.com/builders#/task/824), so the trust dialog usually doesn't appear; accept once if it does). You're now in an interactive Claude Code session in `/workspace`.
206
+ 4. Inside that session, run the **`/remote-control`** slash command. It prints a pairing link.
207
+ 5. Open that link to drive the box from the Claude web/mobile app. The terminal was the launchpad — work from the Claude app from here. (Closing the terminal window ends the remote session and closes the box.)
208
+
209
+ ### Service lifecycle
210
+
211
+ | State | What happens |
212
+ |---|---|
213
+ | Box first boots | `box-terminal.service` (ttyd) + `cloudflared.service` start; `box-report-terminal` cron publishes the URL + credential to the GDS within ~1 min |
214
+ | Builder connects (first time) | Opens the tunnel URL, basic-auths as `otb`, runs `claude` (one-time browser `/login`), then `/remote-control` to get a pairing link and drive the box from the Claude app (ADR 0040) |
215
+ | Builder works (each session) | Lives in the Claude web/mobile app via the RC link; the ttyd terminal is only the launchpad they logged in through |
216
+ | Session ends | Builder closes the browser tab; the terminal + tunnel stay up for the next visit |
217
+ | Box is parked (idle-suspend) | Both units stop naturally when the droplet is destroyed; they restart clean on wake and the cron re-publishes a fresh URL |
218
+
219
+
220
+ ### Checking the services
221
+
222
+ ```bash
223
+ # On the box:
224
+ sudo systemctl status box-terminal # the ttyd web terminal
225
+ sudo systemctl status cloudflared # the outbound tunnel
226
+ journalctl -u box-terminal -f # live tail
227
+ journalctl -u cloudflared -f # tunnel logs - quick-tunnel URL appears here
228
+ journalctl -u cloudflared -n 100 # last 100 lines
229
+ sudo systemctl restart box-terminal cloudflared
230
+ ```
231
+
232
+ The quick-tunnel hostname is printed in the `cloudflared` journal; the same value is published to the GDS by the `box-report-terminal` cron (verify with `crontab -l | grep box-report-terminal`).
233
+
234
+ ### Named-tunnel automation (control plane, [#771](https://example.com/builders#/task/771))
235
+
236
+ The named-tunnel upgrade is automated on the control plane (`scripts/gds/box.js` + `src/bongos/cf-tunnel.js`). It is **OPT-IN, default OFF** — leave it off and every box uses the zero-secret quick tunnel.
237
+
238
+ **Turning it on (operator, in the control-plane `box.env` — the same file that holds `DO_API_TOKEN`, NEVER the web tier):**
239
+
240
+ ```bash
241
+ BOX_NAMED_TUNNEL=1
242
+ CLOUDFLARE_API_TOKEN=<token with Account:Argo Tunnel:Edit + Zone:DNS:Edit>
243
+ CLOUDFLARE_ACCOUNT_ID=<the Cloudflare account id>
244
+ # optional (defaults shown):
245
+ CLOUDFLARE_ZONE=example.com # the DNS zone the record lives in
246
+ BOX_TERMINAL_ZONE=example.com # hostname suffix → term-<login>.example.com
247
+ ```
248
+
249
+ This reuses the **same `CLOUDFLARE_API_TOKEN`** as `box-dns-cloudflare.sh` (the [#725](https://example.com/builders#/task/725) `BOX_DNS_HOOK`) — just add the Tunnel scope to it. In the Cloudflare token UI the permission is **Account → Argo Tunnel → Edit** (the older label for the Cloudflare Tunnel / `cfd_tunnel` API; "Cloudflare Tunnel" on newer accounts). Keep the existing **Zone → DNS → Edit**.
250
+
251
+ > ⚠️ **TLS coverage — why the host is at the apex, not `dev.*` ([#771](https://example.com/builders#/task/771)).** The terminal rides a **proxied** tunnel (Cloudflare terminates HTTPS at its edge), so the hostname needs an edge certificate. Free **Universal SSL covers `example.com` and `*.example.com` (one label) but NOT a two-label host** like `term-x.dev.example.com` — a `dev.*` host fails the TLS handshake at the edge (verified live). So `BOX_TERMINAL_ZONE` defaults to the **apex** (`term-<login>.example.com`, one label, covered for free). Only override it to `dev.example.com` if you've bought an **Advanced Certificate** for `*.dev.example.com`. (The SSH A-record path stays on `dev.*` — it's `proxied=false`/direct-IP and needs no edge cert.)
252
+
253
+ **What the lifecycle does when it's on:**
254
+
255
+ | Op | Tunnel action |
256
+ |---|---|
257
+ | `provision` | create-or-reuse a per-builder named tunnel (`otb-term-<login>`), point its ingress at `127.0.0.1:7681`, route a proxied CNAME `term-<login>.example.com → <tunnel-id>.cfargotunnel.com`, fetch the connector token, and **bake** `BOX_TUNNEL_TOKEN` + `BOX_TERMINAL_HOSTNAME` into the box's `/etc/otb/box.env` via cloud-init. The tunnel is created **before** the droplet so its token is present at first boot. |
258
+ | `park` → `wake` | nothing — the tunnel + DNS are IP-independent and durable, and `box.env` rides the snapshot, so the stable hostname survives park/wake with no control-plane call. |
259
+ | `deprovision` (incl. `sweep-dormant` / `reconcile` clawback) | best-effort teardown: delete the CNAME and the tunnel (the droplet is already gone, so connections have dropped). Never blocks the deprovision. |
260
+
261
+ `box.js provision` (dry-run, the default) prints the tunnel plan without touching Cloudflare; pass `--apply` to create it for real. If `BOX_NAMED_TUNNEL=1` but the token/account id are missing, provision **fails loudly** rather than silently falling back.
262
+
263
+ **Per-box manual override (no automation):** you can still set the two values by hand on a single box and restart — `cloudflared-run.sh` detects the token and switches modes:
264
+
265
+ ```bash
266
+ # In /etc/otb/box.env on the box:
267
+ BOX_TUNNEL_TOKEN=<redacted> named-tunnel token>
268
+ BOX_TERMINAL_HOSTNAME=term-<login>.example.com
269
+ sudo systemctl restart cloudflared
270
+ ```
271
+
272
+ ### Verifying the browser on-ramp end-to-end ([#771](https://example.com/builders#/task/771))
273
+
274
+ The build is unit- and smoke-covered, but the loop crosses real hardware + a human at a browser. Run this once per change to `ttyd`/`cloudflared`/the terminal routes. **Operator deps:** a box provision (small DO cost) and, for the named-tunnel leg, the CF token with Tunnel scope.
275
+
276
+ **Leg A — quick tunnel (zero secrets).**
277
+
278
+ 1. Provision a box for a test builder: `node scripts/gds/box.js onboard <login> --apply` (builder must have a registered SSH key, or `--allow-no-keys`). Confirm cloud-init finished: SSH in and `cloud-init status --wait` → `done`; `systemctl is-active box-terminal cloudflared` → `active`.
279
+ 2. Confirm the box published its terminal: `tail /tmp/box-report-terminal.log` should show `terminal access reported`. Then as the builder: `GET /api/gds/box/terminal` (or `/builder-box`) → returns `{ url: https://<id>.trycloudflare.com, credential }`.
280
+ 3. Open the `url` in a browser. Basic-auth as **`otb`** + the `credential`. You should land in a `/workspace` shell.
281
+ 4. In that terminal run `claude`. Complete the browser `/login` (trust is pre-seeded, [#824](https://example.com/builders#/task/824) — accept once if still prompted) and Trusted-Devices enrollment. Confirm an interactive session starts. **This is the leg `claude rc` could never do** ([#745](https://example.com/builders#/task/745)).
282
+ 5. Inside that session, run **`/remote-control`** (the slash command, NOT `claude rc`). Confirm it prints a pairing link; open the link and confirm the Claude web/mobile app drives the box (ADR 0040, verified live 2026-06-07).
283
+ 6. Full Chromebook loop: from a browser-only device, `POST /box/ensure` → poll `GET /box/terminal` → open → `claude` → `/remote-control` → drive from the Claude app. No SSH, no Desktop.
284
+
285
+ **Leg B — named tunnel (stable hostname).**
286
+
287
+ 1. With the CF token (Tunnel + DNS scope) in the control-plane `box.env`, set `BOX_NAMED_TUNNEL=1` + `CLOUDFLARE_ACCOUNT_ID`. Dry-run first: `node scripts/gds/box.js provision <login>` — confirm it prints the `term-<login>.example.com` plan and the CF calls without touching anything.
288
+ 2. `node scripts/gds/box.js provision <login> --apply`. Confirm in the Cloudflare dashboard: a tunnel `otb-term-<login>` exists with one healthy connector, and a proxied CNAME `term-<login>.example.com → <id>.cfargotunnel.com`.
289
+ 3. `GET /box/terminal` returns the stable `https://term-<login>.example.com`. Open it, basic-auth, `claude` — same as Leg A but on the stable host.
290
+ 4. Teardown: `node scripts/gds/box.js deprovision <login> --apply`. Confirm the tunnel **and** the CNAME are gone from the Cloudflare dashboard.
291
+
292
+ ### Gotchas surfaced by hardware verification ([#771](https://example.com/builders#/task/771))
293
+
294
+ - **Packaged ttyd collision (fixed).** The Ubuntu `ttyd` apt package ships its OWN auto-started `ttyd.service` that binds `127.0.0.1:7681` with **no `--credential`** and runs `login`. It both blocks our `box-terminal.service` (the unit crash-loops on `EADDRINUSE`) and — because the tunnel fronts whatever sits on 7681 — would expose an **unauthenticated** terminal. Cloud-init and the `box-source-fetch` post-clone bring-up now `systemctl mask ttyd` so only our basic-auth ttyd binds the port. On a box provisioned before this fix: `sudo systemctl disable --now ttyd && sudo systemctl mask ttyd && sudo systemctl restart box-terminal`.
295
+ - **IPv4-only Cloudflare calls (fixed).** The CF API token is IP-locked to the droplet's IPv4 (least privilege). The droplet also has IPv6 egress; `cf-tunnel.js` pins IPv4 (undici `Agent{connect:{family:4}}`) or every call 401s — mirroring `box-dns-cloudflare.sh`'s `curl -4`.
296
+ - **⚠ Browser-only bootstrap gap (OPEN — follow-up).** The `ttyd`/`cloudflared` systemd units live in the repo (`/workspace/infra/*.service`), so they only start **after** `box-source-fetch` clones — which needs the **builder's GDS token on the box**. A pure Chromebook builder has no SSH and no terminal yet, so there is **no first-boot path to place that token** → the terminal never comes up for them. Today it only works if the token is seeded another way (SSH, or an operator). The fix (a follow-up) is to bring ttyd up at **first boot independent of the clone** — e.g. cloud-init writes the unit inline rather than copying it from the repo. Until then, the browser on-ramp is verified to work *given a token on the box*, not from a truly bare browser-only device.
297
+
298
+ ---
299
+
300
+ ## Part 3 — The box-heartbeat cron
301
+
302
+ The cloud-init also wires `infra/box-heartbeat.sh` as a 5-minute cron job. This pings `/api/gds/box/heartbeat` while the box is in active use (interactive SSH session or CPU load > 0.2). Silence = the idle-suspend sweep ([#598](https://example.com/builders#/task/598)) is free to park the box.
303
+
304
+ Without this cron the idle sweep measures **uptime** instead of **activity** and may park a box someone is actively using. Always verify it's wired:
305
+
306
+ ```bash
307
+ crontab -l | grep box-heartbeat
308
+ ```
309
+
310
+ If missing (pre-[#599](https://example.com/builders#/task/599) box):
311
+ ```bash
312
+ (crontab -l 2>/dev/null; echo "*/5 * * * * /workspace/infra/box-heartbeat.sh >> /tmp/box-heartbeat.log 2>&1") | crontab -
313
+ ```
314
+
315
+ ---
316
+
317
+ ## Part 4 — Rank-gated source access ([#600](https://example.com/builders#/task/600), ADR 0031 §6 / §9.2)
318
+
319
+ The box holds **no baked credential**. Instead it fetches a rank-scoped clone spec
320
+ from the GDS at boot and on a 10-minute cron, via `infra/box-source-fetch.sh`
321
+ (carried onto the box as base64 inside the cloud-init `write_files`). The flow:
322
+
323
+ 1. The box reads the builder's GDS session token (it appears after they authenticate
324
+ Claude Code / run `/builder-reauth` — so the **first clone lands after the builder
325
+ connects**, not at boot).
326
+ 2. It calls `GET /api/gds/box/source-access`. The GDS checks the builder's **live**
327
+ rank + status (ADR 0016 — unforgeable from the box):
328
+ - **403 `SOURCE_ACCESS_REVOKED`** — builder demoted below the floor or deactivated.
329
+ The script cuts the credentialed remote (box-side clawback); `box.js reconcile`
330
+ deprovisions the droplet.
331
+ - **200 `configured:false`** — the server's source credential isn't set yet (see
332
+ env below); the box logs guidance and no-ops.
333
+ - **200 `configured:true`** — returns the scope-appropriate spec + a short-lived
334
+ credential. The box clones/refreshes `/workspace`, **never persisting the token
335
+ in `.git/config`** (clones via a one-shot authenticated URL, then resets the
336
+ remote to the token-less URL).
337
+ 3. **Scope by rank** (`src/bongos/box-access.js`): a **Xenos → `starter`** sparse-checkout
338
+ of the safe surface (`.devcontainer`, `art`, `docs`, `modules/status-ui`,
339
+ `generative-ideas.md` — the §9.2 "first tasks on a scoped surface"); a **Metic+ →
340
+ `full`** clone. Graduation (`box.js reconcile`) rescopes a starter box to full; the
341
+ box re-clones on its next refresh.
342
+
343
+ **Operator: configure the source credential** (in the **prod env**, never the repo —
344
+ ADR 0022). The default provider (`src/bongos/box-credential.js`) is env-backed:
345
+
346
+ ```bash
347
+ # In the prod environment (e.g. the droplet's systemd unit / .env):
348
+ BOX_SOURCE_REPO_URL=https://github.com/<org>/example.git
349
+ BOX_SOURCE_FULL_TOKEN=<redacted> PAT or installation token, contents:read>
350
+ # Optional — make 'starter' a HARD boundary (a physically separate repo that cannot
351
+ # read the crown jewels) instead of the default sparse-checkout defense-in-depth:
352
+ BOX_SOURCE_STARTER_REPO_URL=https://github.com/<org>/example-starter.git
353
+ BOX_SOURCE_STARTER_TOKEN=<token scoped to the starter repo>
354
+ # Optional — advisory token TTL (how often the box re-fetches + re-checks live rank):
355
+ BOX_SOURCE_TOKEN_TTL_SECONDS=3600
356
+ ```
357
+
358
+ > **Honest limit (ADR 0031 §6).** Git cannot sub-path-scope a single private repo and
359
+ > sparse-checkout is client-side, so the default `starter` surface is
360
+ > **defense-in-depth + audit + revocation, not insider-proof DRM**. Set
361
+ > `BOX_SOURCE_STARTER_REPO_URL` for a hard boundary. Every grant/denial is audited to
362
+ > `box_events` (`source_grant` / `source_deny` / `source_revoke` / `source_rescope`).
363
+
364
+ **The clawback (clean offboarding).** Revoking rank or deactivating a builder cuts
365
+ source on two timelines: the **credential layer is instant** (their next
366
+ `/box/source-access` fetch 403s), and the **droplet teardown** follows when the
367
+ control plane runs reconcile:
368
+
369
+ ```bash
370
+ node scripts/gds/box.js reconcile # dry-run: show what would change
371
+ node scripts/gds/box.js reconcile --apply # deprovision below-floor/inactive boxes,
372
+ # rescope graduated ones (run on a schedule)
373
+ ```
374
+
375
+ Verify the source-fetch cron + check progress on the box:
376
+
377
+ ```bash
378
+ crontab -l | grep box-source-fetch
379
+ tail /tmp/box-source-fetch.log
380
+ WORKSPACE=/workspace /usr/local/bin/box-source-fetch.sh # manual run
381
+ ```
382
+
383
+ ---
384
+
385
+ ## Quick reference: full operator flow
386
+
387
+ ```bash
388
+ # 0. One-time: set BOX_SOURCE_REPO_URL + BOX_SOURCE_FULL_TOKEN in the prod env (Part 4)
389
+
390
+ # 1. Provision the box
391
+ node scripts/gds/box.js provision alice --apply
392
+
393
+ # 2. Add the builder's SSH public key to the box
394
+ ssh root@box-alice.dev.example.com "echo '...' >> ~/.ssh/authorized_keys"
395
+
396
+ # 3. Generate and send managed-settings.json (Desktop / SSH path)
397
+ bash infra/gen-managed-settings.sh alice > /tmp/alice-managed-settings.json
398
+ # → email/DM to builder with placement instructions
399
+
400
+ # 4. For thin-device (Chromebook) path: the web terminal is ready automatically
401
+ # (box-terminal.service + cloudflared.service start at boot; box-report-terminal
402
+ # publishes the URL + credential to the GDS within ~1 min)
403
+ # Builder self-serves: POST /api/gds/box/ensure, then poll GET /api/gds/box/terminal
404
+ # -> open the url, basic-auth as user 'otb' with the returned credential, run: claude
405
+ # -> then /remote-control to drive the box from the Claude app (ADR 0040)
406
+
407
+ # 5. When the builder is done for the day, the idle sweep parks the box:
408
+ node scripts/gds/box.js sweep-idle --apply # control plane / prod cron
409
+
410
+ # 6. Source materializes automatically once the builder authenticates on the box
411
+ # (the box-source-fetch cron clones the rank-scoped surface). Nothing to do here.
412
+
413
+ # 7. Offboarding / demotion: the credential is cut on the builder's next fetch;
414
+ # reconcile then deprovisions the box (run on a schedule alongside the sweeps):
415
+ node scripts/gds/box.js reconcile --apply
416
+ ```
@@ -0,0 +1,71 @@
1
+ # Recipe — Builder memory backup + restore drill
2
+
3
+ > **Filed by:** task [#281](https://example.com/builders#/task/281) (V3.R62), GDS-V3 criterion C8 ("memory is local-first, server-canonical on ship"). Depends on the server-side memory store ([#273](https://example.com/builders#/task/273) R54) and the DB backup pipeline ([#412](https://example.com/builders#/task/412) local nightly + [#415](https://example.com/builders#/task/415) weekly offsite). Companion to [`gds-db-backup.md`](gds-db-backup.md); vendor choice in [ADR 0025](../adr/<redacted>.md).
4
+
5
+ ## Key decision — memory is backed up *as part of the full-DB backup*, not separately
6
+
7
+ C8 makes each builder's local memory dir **server-canonical on ship**: `/builder-ship` upserts the builder's memory files into the `builder_memory` Postgres table ([#274](https://example.com/builders#/task/274) R55). Because that table lives in the same `example` database as everything else, **it is already captured by the full-DB backup pipeline** — there is deliberately **no separate `backup-memory.sh`**. A memory-only dump would duplicate what `pg_dump` already writes nightly and ship offsite weekly, and would be a second thing to keep in sync. One backup story, not two (same principle as [ADR 0025](../adr/<redacted>.md)'s retirement of the redundant [#7](https://example.com/builders#/task/7) cron).
8
+
9
+ So builder memory inherits both layers:
10
+
11
+ | Layer | Mechanism | Cadence | Retention |
12
+ |---|---|---|---|
13
+ | Local | `gds-db-backup.timer` → `pg_dump` → `/var/backups/gds/` ([#412](https://example.com/builders#/task/412)) | daily 04:00 UTC | 30 days |
14
+ | Offsite | `gds-db-offsite.timer` → latest dump → DO Space `gds-offsite/` ([#415](https://example.com/builders#/task/415)) | weekly Sun 05:00 UTC | 4 weeks |
15
+
16
+ The `builder_memory` table is in every dump. No extra moving parts.
17
+
18
+ ## The `builder_memory` table
19
+
20
+ ```
21
+ builder_memory(builder_id, path, content, mtime, sha256, byte_len, created_at, updated_at)
22
+ PK (builder_id, path)
23
+ ```
24
+
25
+ Each row is one memory file for one builder. The `sha256` + `byte_len` columns are the integrity fingerprint — which is what lets the restore drill below verify a restore **without ever reading the private `content`** (builder memory is per-builder private + isolated; see [#276](https://example.com/builders#/task/276) R57).
26
+
27
+ ## Restore drill — verify a builder's memory survives a restore
28
+
29
+ Cadence: **quarterly** (alongside the general restore drill in [`gds-db-backup.md`](gds-db-backup.md)). The drill restores the latest dump into a throwaway sandbox DB and confirms a chosen builder's memory rows are byte-identical to production — by fingerprint, so no private content is printed.
30
+
31
+ ```bash
32
+ # 1. Restore the latest local dump into a sandbox DB.
33
+ DUMP=$(ls -1t /var/backups/gds/example-*.sql.gz | head -1)
34
+ sudo -u postgres dropdb --if-exists example_mem_restore_test
35
+ sudo -u postgres createdb example_mem_restore_test
36
+ set -o pipefail
37
+ gunzip -c "$DUMP" | sudo -u postgres psql -q -d example_mem_restore_test
38
+
39
+ # 2. Pick a builder with memory (builder_id=1 here) and compare a
40
+ # privacy-preserving fingerprint: count + md5 over (path, sha256, byte_len).
41
+ # Never selects `content`.
42
+ FP="SELECT builder_id, count(*),
43
+ md5(string_agg(path||':'||sha256||':'||byte_len, ',' ORDER BY path))
44
+ FROM builder_memory WHERE builder_id=1 GROUP BY builder_id;"
45
+ psql -d example -tAc "$FP" # production
46
+ sudo -u postgres psql -d example_mem_restore_test -tAc "$FP" # restored
47
+
48
+ # 3. The two lines must be identical. Then clean up.
49
+ sudo -u postgres dropdb example_mem_restore_test
50
+ ```
51
+
52
+ ### Last run
53
+
54
+ - **2026-05-30** (task [#281](https://example.com/builders#/task/281), claim `#349`): builder 1, **3 files**, prod and restored fingerprints **MATCH** (`…<redacted>`). Restore completed with zero errors.
55
+
56
+ ## Caveat the drill caught — point-in-time vs. the data
57
+
58
+ The first drill run **failed correctly**: the most recent nightly dump (04:02 UTC) predated migration 054 and the memory rows (which synced at 08:47 UTC that day), so the table wasn't in it. Two lessons baked in here:
59
+
60
+ 1. **A dump only contains what existed when it ran.** Memory synced since the last 04:00 UTC nightly is not in any backup until the next nightly; and not *offsite* until the next weekly run. Worst-case memory-loss window on whole-droplet loss is ~1 week (the offsite cadence). Tighten the offsite timer to daily if that ever matters.
61
+ 2. **After a migration that adds/relocates memory data, take a one-shot dump** rather than waiting for the nightly, if you want it backed up immediately:
62
+ ```bash
63
+ sudo systemctl start gds-db-backup.service # fresh local dump now
64
+ sudo systemctl start gds-db-offsite.service # push it offsite now
65
+ ```
66
+
67
+ ## See also
68
+
69
+ - [`gds-db-backup.md`](gds-db-backup.md) — the full backup pipeline, install steps, and the general (non-memory-specific) restore drills.
70
+ - [ADR 0025](../adr/<redacted>.md) — offsite vendor decision.
71
+ - [ADR 0024](../adr/<redacted>.md) — the local-first / server-canonical memory model this backs up.
@@ -0,0 +1,98 @@
1
+ # Recipe — Memory sync conflicts: policy + clobber recovery
2
+
3
+ > **Filed by:** task [#277](https://example.com/builders#/task/277) (V3.R58), GDS-V3 criterion C8. Documents the conflict policy chosen by the R04 spike ([ADR 0024](../adr/<redacted>.md) §3) and implemented across [#274](https://example.com/builders#/task/274) (push), [#275](https://example.com/builders#/task/275) (pull), [#276](https://example.com/builders#/task/276) (isolation). Recovery leans on the backup pipeline from [#281](https://example.com/builders#/task/281) ([`memory-backup.md`](memory-backup.md)).
4
+
5
+ ## The policy in one line
6
+
7
+ **Last-write-wins, per file, server clock authoritative.** No merge, no rejection, no warning.
8
+
9
+ ## How sync works (so the policy makes sense)
10
+
11
+ Memory is **local-first, server-canonical on ship**. There are exactly two sync moments — no background polling, no mid-session sync:
12
+
13
+ | Trigger | Direction | What happens |
14
+ |---|---|---|
15
+ | `/builder-ship` succeeds ([#274](https://example.com/builders#/task/274) R55) | **push** local → server | `POST /api/gds/memory/sync` upserts each local memory file into `builder_memory`. Every file is written unconditionally — the **last push to land wins**. |
16
+ | `SessionStart` / `/builder-start` ([#275](https://example.com/builders#/task/275) R56) | **pull** server → local | client reports its newest local `mtime`; `GET /api/gds/memory/since?mtime=…` returns files the server holds that are **newer**; client writes them over local copies. |
17
+
18
+ The stored `mtime` is the client's reported file mtime and is **advisory** — used only by the pull side's newer-than check. The server's own `updated_at` (trigger-maintained) is the authority for "when did this row actually change." A client cannot win a conflict by forging a future mtime: an unparseable mtime is normalized to `NULL`, and the server clock governs.
19
+
20
+ `builder_id` is the GitHub user, not a session — so "two different builders racing on the same file" is impossible by construction. Every conflict below is **one builder, more than one machine or session**.
21
+
22
+ ## Edge cases
23
+
24
+ ### 1. Same file edited in two parallel sessions (two machines / two worktrees)
25
+
26
+ Builder edits `MEMORY.md` on the desktop and, in a parallel session, on the laptop. Both ship.
27
+
28
+ - Both sessions push. **Whichever push lands at the server second overwrites the first** — the server now holds exactly one version (the later push). No merge is attempted; the earlier push's content is gone from the server.
29
+ - The "losing" machine still has its own local copy until its **next** `SessionStart` pull, which then overwrites it with the server's surviving version. After that pull, both machines agree.
30
+ - **Net:** one version survives end-to-end; the other is lost. Lost-write window ≈ one session boundary. If the lost version mattered, recover it from backup (below).
31
+
32
+ > Practical avoidance: don't run two live sessions editing the same memory file. Memory edits are cheap to redo; the system optimizes for "never half-merge a plausible-but-broken file" over "never lose a keystroke."
33
+
34
+ ### 2. Server has a newer version than local
35
+
36
+ Builder shipped from the laptop yesterday (server now newer), then opens the desktop today.
37
+
38
+ - `SessionStart` pull sees the server's `mtime` is newer than the desktop's local copy and **writes the server version over the local file**. Desktop is now current. This is the intended path — it's how memory "follows you between machines."
39
+ - Risk only arises if the desktop had **unpushed local edits older** (by mtime) than the server's version — those would be overwritten on pull. In normal use local edits are the newest thing, so this is rare; when it bites, recover from backup.
40
+
41
+ ### 3. Local newer than server (the common, non-conflict case)
42
+
43
+ Local edits since the last ship are newer; on next `/builder-ship` they push and become canonical. No conflict. This is the steady state.
44
+
45
+ ## Operator recovery — restore a clobbered file from backup
46
+
47
+ When a builder confirms a real clobber, the lost version is recoverable from any `pg_dump` taken **before** the overwrite (nightly local, 30-day retention; weekly offsite, 4-week — see [`memory-backup.md`](memory-backup.md) / [`gds-db-backup.md`](gds-db-backup.md)). The dump must predate the bad push.
48
+
49
+ ```bash
50
+ # 1. Restore a pre-clobber dump into a sandbox (NON-destructive to prod).
51
+ DUMP=/var/backups/gds/example-<ts-before-the-clobber>.sql.gz
52
+ sudo -u postgres dropdb --if-exists example_recover
53
+ sudo -u postgres createdb example_recover
54
+ gunzip -c "$DUMP" | sudo -u postgres psql -q -d example_recover
55
+
56
+ # 2. Extract the old content to a FILE (never paste content inline — see the
57
+ # warning below). -tA = unaligned, no headers; one file's content out.
58
+ # (Archon-run, on the droplet; this is the one place reading content is OK —
59
+ # it's a deliberate recovery, logged by this recipe's existence.)
60
+ sudo -u postgres psql -d example_recover -tAc \
61
+ "SELECT content FROM builder_memory WHERE builder_id=<id> AND path='<path>';" \
62
+ > /tmp/recovered.txt
63
+
64
+ # 3. Hand the file back to the builder. Two ways:
65
+ # (a) PREFERRED — give them /tmp/recovered.txt; they drop it into their local
66
+ # memory dir and /builder-ship to re-push it. Keeps the builder as the
67
+ # author of their own memory, and the push path recomputes sha256/byte_len.
68
+ # (b) Archon writes it straight into prod IF the builder can't. Load the
69
+ # content from the FILE via a bound parameter — do NOT inline it into the
70
+ # SQL (a naive dollar-quote breaks if the content itself contains the
71
+ # quote tag, and string-pasting risks injection during a high-stress run):
72
+ sudo -u postgres psql -d example \
73
+ -v content="$(cat /tmp/recovered.txt)" \
74
+ -c "INSERT INTO builder_memory (builder_id, path, content, sha256, byte_len)
75
+ VALUES (<id>, '<path>', :'content', encode(sha256(:'content'::bytea),'hex'),
76
+ octet_length(:'content'))
77
+ ON CONFLICT (builder_id, path) DO UPDATE
78
+ SET content=EXCLUDED.content, sha256=EXCLUDED.sha256, byte_len=EXCLUDED.byte_len;"
79
+ # (`:'content'` is psql variable interpolation with proper literal quoting —
80
+ # safe for arbitrary content, and sha256/byte_len are recomputed in-SQL so
81
+ # they can't drift from the restored bytes.)
82
+
83
+ # 4. Clean up the sandbox and the temp file.
84
+ sudo -u postgres dropdb example_recover && rm -f /tmp/recovered.txt
85
+ ```
86
+
87
+ > **Privacy note:** another builder's memory is private ([#276](https://example.com/builders#/task/276) R57 isolation; Archon forensic reads are audit-logged). Recovery is the builder's own file, or an explicitly-authorized Archon action — never a casual cross-builder read. Prefer path (a) so the builder re-pushes their own content.
88
+
89
+ ## Why not something smarter? (rejected alternatives, from ADR 0024 §3)
90
+
91
+ - **Three-way markdown merge** — rejected: a half-merged `MEMORY.md` that *looks* plausible but is structurally broken is worse than a clean lose-one. Revisit in V4 only if real collisions show up in V3.
92
+ - **Optimistic concurrency** (reject stale-base pushes, force pull-first) — rejected: builders would just `--force` around it. Last-write-wins + a backup recovery path is simpler and handles the rare bad case.
93
+
94
+ ## See also
95
+
96
+ - [ADR 0024](../adr/<redacted>.md) §3 — the decision + rejected alternatives.
97
+ - [`memory-backup.md`](memory-backup.md) — backup cadence + the restore drill the recovery above relies on.
98
+ - [`gds-db-backup.md`](gds-db-backup.md) — the underlying dump/offsite pipeline.