@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,78 @@
1
+ # Multi-builder merge safety — audit + serialization model
2
+
3
+ > **Deploy-mode note (current state).** This recipe documents the **`laptop`** merge path (operator merges `main` + SSHes the droplet). Since the 2026-06-13 cutover `config/deploy.json` is **`mode: ci`** — the merge + deploy run **server-side** (PR auto-merge + `.github/workflows/deploy-prod.yml`), and credential-less dev boxes ship via server-mediated publish ([ADR 0055](../adr/<redacted>.md)). The local-`main`-worktree + merge-lock model below applies only if `deploy.json` is reverted to `mode: laptop`.
4
+
5
+ > **Task:** V3.R50 / [#269](https://example.com/builders#/task/269) (criterion **C6 — parallel-safe-under-load**).
6
+ > **Question it answers:** when N>1 builders ship and merge concurrently, where do `ship.js` and `/merge-mode` assume "I am the only builder," and what serializes the shared state so they don't collide?
7
+
8
+ This recipe is the audit deliverable for [#269](https://example.com/builders#/task/269). It enumerates every shared-state surface in the merge/ship path, marks which assume serialized access, names every git operation that could race, and documents the mutex that now covers them.
9
+
10
+ ---
11
+
12
+ ## TL;DR
13
+
14
+ - **Claim side is already deterministic.** `claimTask()` runs in a single transaction with `SELECT … FOR UPDATE` on the task row, a touches-overlap check, and the `uniq_active_claim_per_task` partial unique index. A lost race surfaces as `ALREADY_CLAIMED` (Postgres `23505`), never as corruption. No change needed.
15
+ - **Merge side is the risk, and it has ONE shared resource:** the single `main` worktree (`REPO_ROOT`) on the build machine. Every ship's auto-merge and every `/merge-mode` run checks out `main`, fetches, merges, pushes, and deploys *there*.
16
+ - **[#462](https://example.com/builders#/task/462) (criterion C4)** added a lockfile so two concurrent **ships** couldn't collide — but the lock lived *inside* `ship.js`, so `/merge-mode` (which mutates the same tree by hand) never took it. That left two races open: **ship-vs-merge-mode** and **merge-mode-vs-merge-mode**.
17
+ - **[#269](https://example.com/builders#/task/269) (this task)** extracts the lock into [`src/bongos/merge-lock.js`](../../src/bongos/merge-lock.js) and has **both** surfaces acquire the **same** mutex. `/merge-mode` takes it via the [`scripts/gds/merge-lock.js`](../../scripts/gds/merge-lock.js) CLI before it touches `main`, and releases it after deploy.
18
+
19
+ ---
20
+
21
+ ## The shared-state surfaces
22
+
23
+ | Surface | Shared across builders? | Serialized by | Notes |
24
+ |---|---|---|---|
25
+ | **`main` worktree** (`REPO_ROOT`): checkout, `git fetch`, `git merge`, `git push origin main`, post-merge smoke, `~/deploy.sh` | **Yes — the single hot resource.** One checkout, one HEAD. | **`merge-lock` mutex** (`.git/otb-automerge.lock`) — held by `ship.js` auto-merge AND `/merge-mode`. | This is the surface [#269](https://example.com/builders#/task/269) closes end-to-end. |
26
+ | **`claims` table** (claim/release) | Yes | Postgres txn + `uniq_active_claim_per_task` unique index + touches-overlap check (`db.js claimTask`) | Deterministic. `ALREADY_CLAIMED` / `TOUCHES_CONFLICT` are clean refusals, not corruption. |
27
+ | **`creator_session_id` on claims** | Yes | `CLAIM_SESSION_MISMATCH` (migration 013) | Only the session that created a claim may ship/release it — prevents cross-session interference. |
28
+ | **`worktree_name` uniqueness** | Yes | Server-side disambiguation in `claimTask` (V3.R51 / [#270](https://example.com/builders#/task/270)) | Two claims with the same worktree name → second gets a suffix. |
29
+ | **`migration_counter`** (migration number allocation) | Yes | `UPDATE … RETURNING` inside the claim txn | Atomic; each claim that signals `migrations/` gets a distinct number. |
30
+ | **Feature worktree** (`.claude/worktrees/<name>`) | No — per-builder | n/a | Each builder's feature branch work is isolated. The collision only appears at merge time, on `main`. |
31
+ | **`origin/main` on GitHub** | Yes | `git push origin main` is atomic server-side; a stale push is rejected (non-fast-forward) | The local mutex makes the local merge serialized so the push is fast-forward; a rejected push bails the ship to `confirmed`. |
32
+ | **The droplet deploy** (`ssh … ~/deploy.sh`) | Yes | Runs *inside* the merge-lock critical section | Two deploys can't overlap because each holds the mutex through merge→push→deploy. |
33
+
34
+ ---
35
+
36
+ ## Every place the merge path assumed "I am the only builder"
37
+
38
+ 1. **`ship.js autoMerge()` — `git merge --ff-only origin/main` on `REPO_ROOT`.**
39
+ If another session left `main` mid-merge or moved it, this failed and bailed with the misleading *"main is ahead of origin somehow."* — **Fixed in [#462](https://example.com/builders#/task/462)** with the in-`ship.js` lock + `mainWorktreeBusy()` guard (refuses to mutate `REPO_ROOT` when `MERGE_HEAD` exists or the tree is dirty).
40
+
41
+ 2. **`/merge-mode` — `git checkout main; git pull; git merge …` on `REPO_ROOT`, with no lock.** ← **the gap [#269](https://example.com/builders#/task/269) closes.**
42
+ `/merge-mode` mutated the exact same worktree `ship.js` does, but never acquired [#462](https://example.com/builders#/task/462)'s lock (the lock was a private function inside `ship.js`). A ship auto-merging while an operator ran `/merge-mode` could interleave checkouts/merges on one HEAD. **Fixed in [#269](https://example.com/builders#/task/269):** `/merge-mode` now runs `node scripts/gds/merge-lock.js acquire` before Step 2 and `release` in Step 5c.
43
+
44
+ 3. **macOS Finder/iCloud `* 2` duplicate refs.**
45
+ Both surfaces clean these before fetching (`cleanupMacFinderDupRefs` / `find .git -name "* 2" -delete`). Not a concurrency bug, but a shared-filesystem hazard worth listing — it broke every auto-merge on 2026-05-10.
46
+
47
+ ---
48
+
49
+ ## The mutex, precisely
50
+
51
+ [`src/bongos/merge-lock.js`](../../src/bongos/merge-lock.js) is a portable, advisory file lock at `<REPO_ROOT>/.git/otb-automerge.lock`. **Not `flock(2)`** — ships run on macOS over an iCloud-synced filesystem where `flock` is unreliable, and the manual `/merge-mode` holder is a short-lived CLI process with no long-lived owner.
52
+
53
+ Lockfile format (3 lines): `pid` · `epoch-ms timestamp` · `mode` (`auto` | `manual`).
54
+
55
+ | | `auto` (a ship — process stays alive through its merge) | `manual` (`/merge-mode` via the CLI — no long-lived owner) |
56
+ |---|---|---|
57
+ | Recorded pid | `process.pid` of the ship | `0` (the CLI process exits immediately) |
58
+ | Reclaimed when | holder pid is dead **OR** stamp older than `AUTO_STALE_MS` (10 min) | stamp older than `MANUAL_STALE_MS` (30 min) — **time only** |
59
+ | Released by | the owning ship process (pid match), in a `finally` | whoever runs `merge-lock.js release` (any process, since mode=manual) |
60
+
61
+ A ship that can't get the lock within 30s bails cleanly to `confirmed` (the task is safe; `/merge-mode` lands it later). An operator who sees `acquire` exit `3` is told to wait — never to force past a live holder. The two stale windows differ on purpose: an automated ship that crashes should free up fast (10 min), while a human resolving conflicts mid-merge gets a generous 30 min before the lock is presumed abandoned.
62
+
63
+ Behavior is pinned by [`tests/merge_lock.mjs`](../../tests/merge_lock.mjs) (auto-vs-auto wait, dead-pid + time-based reclaim, manual-window survival, owner-guarded release, two-line legacy-lockfile back-compat).
64
+
65
+ ---
66
+
67
+ ## Known residual limitation (filed, not blocking C6)
68
+
69
+ **The mutex is machine-local.** `.git/otb-automerge.lock` serializes everything that mutates the *one* `main` worktree on the *one* build machine. Today that is correct and complete: all ships and merges run from worktrees under the single shared checkout on Lars's Mac. If a future version lets builders ship from *different physical machines* against *different* checkouts of `main`, a filesystem lock won't serialize them — that needs a server-side lease (e.g. an advisory lock row / `pg_advisory_lock` keyed on `main`, handed out by the API at merge time). Captured as an idea for GDS-V4; out of scope for C6, which targets parallel safety on the current single-machine, multi-session model.
70
+
71
+ ---
72
+
73
+ ## Related
74
+
75
+ - [ADR 0024](../adr/<redacted>.md) — multi-agent system (the reason N>1 builders exist).
76
+ - [#462](https://example.com/builders#/task/462) — the C4 auto-merge lock this task generalizes.
77
+ - [#270](https://example.com/builders#/task/270) (V3.R51) — server-side worktree-name uniqueness (a sibling parallel-safety fix).
78
+ - [#272](https://example.com/builders#/task/272) — the parallel-load smoke test that *exercises* this serialization under 5 simulated builders (the other open C6 task). Its **DB rank is R53** (the DB is king); the original planning-seed cross-ref text called it "R54", but the live rank renumbering settled it at R53/[#272](https://example.com/builders#/task/272).
@@ -0,0 +1,212 @@
1
+ ---
2
+ track: internal
3
+ scope: shared-infra (production droplet, Caddy, Postgres, deploy chain) — touches both tracks but the *recipes themselves* are builder-facing
4
+ ---
5
+
6
+ # Ops gotchas — read before deploying or touching infra
7
+
8
+ Things we've already paid for once. Don't pay again.
9
+
10
+ Organized by topic, not chronology. New entries go in the matching section; create a new section for a new topic.
11
+
12
+ ---
13
+
14
+ ## PostgreSQL
15
+
16
+ ### `pg` defaults to TCP localhost, not the Unix socket
17
+
18
+ - **Symptom:** `new Pool()` with no `host` fails with `SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string`. The Node process appears to start, but every database call silently fails (or noisily fails depending on where it happens).
19
+ - **Root cause:** The `pg` library defaults to TCP `localhost`. With Postgres configured for **peer authentication** (matching the OS user to the DB user), TCP doesn't qualify — TCP requires a password, peer auth only works over the Unix socket. So `pg` tries TCP, Postgres demands a password, no password is provided, SASL bombs.
20
+ - **Fix:** Pass the socket directory explicitly:
21
+ ```js
22
+ new Pool({ host: '/var/run/postgresql' })
23
+ ```
24
+ (Or set `PGHOST=/var/run/postgresql` in the environment.) That directory is the Debian/Ubuntu default Postgres socket location; on other distros it may differ.
25
+ - **Why it bites:** The `pg` library's defaults assume a standard TCP+password setup, which is the most common configuration but not the cheapest one for a single-machine deploy. Peer auth is more secure and frictionless once you know the socket path. The error message points at SASL, not at the host setting, which buries the real cause.
26
+ - **Where this lives in the codebase:** [`src/db.js`](../../src/db.js) has the explicit socket host.
27
+
28
+ ---
29
+
30
+ ## Colyseus
31
+
32
+ ### Server/client version skew between 0.16 and 0.17
33
+
34
+ - **Symptom:** `npm install colyseus` picks the latest 0.17.x server, but `colyseus.js` (the browser client) is still 0.16.x. Install fails with an `eresolve` peer-dependency error on `@colyseus/schema` because 0.17 wants schema v4 and 0.16 wants schema v3.
35
+ - **Root cause:** Colyseus releases server-side first; the browser client lags by several months. The two must be on the same major.minor.
36
+ - **Fix:** Pin all four to the same major.minor in `package.json`:
37
+ ```json
38
+ "colyseus": "^0.16",
39
+ "@colyseus/ws-transport": "^0.16",
40
+ "@colyseus/schema": "^3",
41
+ "colyseus.js": "^0.16"
42
+ ```
43
+ - **Why it bites:** `npm install <pkg>` pulls the latest version unless told otherwise, and there's no warning that the matching client doesn't exist yet. `colyseus.js` 0.17 will eventually ship — when it does, the pins can be lifted in lockstep.
44
+
45
+ ### Colyseus 0.16 ignores `static maxClients`
46
+
47
+ - **Symptom:** Setting `maxClients` as a static class field on a Room subclass (the documented pattern in some online examples) has no effect. The room accepts unlimited clients.
48
+ - **Fix:** Set `this.maxClients = N` inside `onCreate()`. It is an instance property, not a static one, in 0.16.
49
+ - **Why it bites:** The docs and examples drift between Colyseus versions. The older static-field pattern is still findable on the web.
50
+
51
+ ---
52
+
53
+ ## Caddy + Cloudflare
54
+
55
+ ### Let's Encrypt auto-renewal silently breaks under Cloudflare proxy (resolved)
56
+
57
+ - **Symptom:** Caddy obtained the initial cert fine, then failed to renew at the 90-day mark — site went down.
58
+ - **Root cause:** With Cloudflare proxy ON (orange cloud), CF intercepts port 80 at the edge and Caddy never sees the HTTP-01 challenge from Let's Encrypt. Renewal silently fails.
59
+ - **Fix (already in place):** Replaced Let's Encrypt with a Cloudflare Origin Certificate (15-year cert at `/etc/caddy/origin.crt` + `.key`, explicit `tls` directive in Caddyfile). Eliminates the auto-renewal dependency for the CF↔origin leg. See [ADR 0003](../adr/<redacted>.md).
60
+ - **Why it bites:** The failure mode is silent for ~89 days, then catastrophic. Easy to think the site is "set and forget" when it is actually approaching a cliff.
61
+
62
+ ### Deploying configs to `/etc/caddy/` requires staging through `~/`
63
+
64
+ - **Symptom:** `scp` directly to `/etc/caddy/Caddyfile` fails with permission denied because `lars` doesn't own `/etc/caddy/`.
65
+ - **Fix:** `scp` to `~/staging/Caddyfile` first, then `sudo mv ~/staging/Caddyfile /etc/caddy/Caddyfile && sudo systemctl reload caddy`. Same pattern for the systemd unit at `/etc/systemd/system/example.service`.
66
+ - **Why it bites:** The deploy script handles this for normal app code, but config files in `/etc/` need the staging step. Easy to forget when you haven't touched infra in a while.
67
+
68
+ ### Cloudflare hides real client IPs from the origin
69
+
70
+ - **Symptom:** Caddy logs show Cloudflare IPs (162.158.x.x, 172.69.x.x, etc.) instead of real visitor IPs.
71
+ - **Fix when needed:** Wire `trusted_proxies cloudflare` into the Caddyfile so Caddy honors `X-Forwarded-For` / `CF-Connecting-IP`. CF maintains the IP-range list — the directive auto-pulls it.
72
+ - **Why it bites:** Not yet biting (we're not rate-limiting or doing abuse detection). It will bite the moment we try to identify a single misbehaving client. Documented here so when that day comes the fix is one line.
73
+
74
+ ---
75
+
76
+ ## SSH + droplet
77
+
78
+ ### Don't `apt-get upgrade` in a plain SSH session
79
+
80
+ - **Symptom:** Mid-upgrade, sshd restarts (because openssh-server was in the upgrade set). The SSH session drops, leaving the upgrade half-run and the operator locked out until they can reach the DigitalOcean web console.
81
+ - **Recovery (already once):** Power-cycle from DO web console, log back in, verify the upgrade completed. It usually has — apt is good at finishing what it started — but this is luck not design.
82
+ - **Fix going forward:** Skip routine `apt-get upgrade` entirely. Let `unattended-upgrades` handle security patches in the background — it's already enabled. If a manual upgrade is genuinely needed, wrap it in `tmux` or `screen` so it survives the session drop.
83
+ - **Why it bites:** sshd is the lifeline. Anything that touches it from inside an SSH session is dangerous.
84
+
85
+ ### SSH is key-only, root login disabled
86
+
87
+ - **Reminder, not a gotcha:** `PermitRootLogin no`, `PasswordAuthentication no` in `/etc/ssh/sshd_config`. Only `lars` can log in, and only with the registered ed25519 key. If the key is ever lost, recovery is via DigitalOcean's web console (or by attaching the volume to a recovery droplet).
88
+
89
+ ### SSH silently times out — fail2ban banned your IP
90
+
91
+ - **Symptom:** `ssh lars@REDACTED_IP` hangs and times out. `ping REDACTED_IP` works. `curl https://example.com/healthz` returns 200. Only port 22 from your specific public IP is dead. Looks identical to a firewall outage.
92
+ - **Root cause:** fail2ban (running on the droplet, watches `/var/log/auth.log`) saw N auth failures from your IP inside the rolling window and inserted an iptables `DROP` rule. Default policy in this distro: 5 failures in 10 minutes triggers a 10-minute ban. The drop is silent — no RST, no Mac-side log, no obvious error — which is why diagnosis is slow the first time.
93
+ - **Immediate fix:** DigitalOcean web console (it bypasses port 22 because it doesn't go through SSH at all). Log into the droplet via the console, then:
94
+ ```bash
95
+ sudo fail2ban-client status sshd # confirm the IP is in the Banned list
96
+ sudo fail2ban-client unban <your-public-IP>
97
+ ```
98
+ Then verify from the Mac: `ssh -o ConnectTimeout=5 lars@REDACTED_IP "uptime"` should respond in <1s.
99
+ - **Permanent fix:** add your IP to `/etc/fail2ban/jail.local`'s `ignoreip` list and reload fail2ban. `jail.local` overrides the package's `jail.conf` so apt upgrades won't trample the whitelist. Example file:
100
+ ```ini
101
+ [DEFAULT]
102
+ ignoreip = 127.0.0.1/8 ::1 <your-public-IP>
103
+ bantime = 10m
104
+ findtime = 10m
105
+ maxretry = 5
106
+
107
+ [sshd]
108
+ enabled = true
109
+ ```
110
+ Then `sudo systemctl reload fail2ban`. Confirm with `sudo fail2ban-client status sshd | grep -i ignor` — the IP should appear in the Ignored list.
111
+ - **Why it bites:** the failure mode is silent. There's no log on the Mac side, no log from the operating shell, and the symptom is indistinguishable from "port 22 is closed" or "the droplet is down." You only realize it's fail2ban after the DO console reveals the iptables DROP. First-time diagnosis is ~20 minutes; once you know the signature it's 30 seconds.
112
+ - **For new builders:** most builders (Metic and below) don't need direct droplet SSH — they work through the public API. The whitelist is primarily an Archon-comfort item. Don't reflexively add every new builder's IP; only add IPs for people who actually deploy.
113
+
114
+ ---
115
+
116
+ ## GitHub OAuth (web flow)
117
+
118
+ ### Authorized callback URL must include the full /api/gds path
119
+
120
+ - **Symptom:** Visitor clicks "Sign in with GitHub" on /builders, GitHub renders its red "Be careful!" warning page or returns `?error=redirect_uri_mismatch`, and the visitor never lands back on the hall.
121
+ - **Root cause:** The GitHub OAuth app's **Authorization callback URL** field must match exactly what the server tells GitHub. Our server sends `${publicOrigin}/api/gds/auth/web/callback` — easy to misconfigure as just `https://example.com/` or `/auth/callback` when registering a fresh OAuth app.
122
+ - **Fix:** In github.com → Settings → Developer settings → OAuth Apps → (the Off the Boats app) → **Authorization callback URL**, set:
123
+ ```
124
+ https://example.com/api/gds/auth/web/callback
125
+ ```
126
+ No trailing slash, full path. If staging gets provisioned ([#260](https://example.com/builders#/task/260)) it will need a second OAuth app or the same app with multiple callback URLs (GitHub now supports up to 10).
127
+ - **Where this lives in the codebase:** [`src/bongos/routes/auth.js`](../../src/bongos/routes/auth.js) — `/auth/web/start` computes `redirectUri` from `publicOrigin(req)` and the `/auth/web/callback` route reads back to it. As of [#371](https://example.com/builders#/task/371) the error branches render a styled HTML page (with a retry link) instead of `text/plain`, so the visitor at least sees something coherent.
128
+ - **Why it bites:** GitHub's warning page is intentionally scary and doesn't tell you *which* URL it expected; the only diagnostic is the `error=redirect_uri_mismatch` query param on the redirect back, which our server now surfaces in the styled error page.
129
+
130
+ ---
131
+
132
+ ## Mac / local dev
133
+
134
+ ### TextEdit defaults to RTF and silently corrupts plain-text files
135
+
136
+ - **Symptom:** Saved a Cloudflare Origin Cert to `~/Desktop/origin.crt` from TextEdit. The file ended up wrapped in RTF formatting codes (and TextEdit added `.rtf` to the filename).
137
+ - **Fix:** `textutil -convert txt -output X.crt X.crt.rtf` strips the RTF wrapper and writes plain PEM.
138
+ - **Going forward:** When editing certs, keys, configs, or any plain-text file on this Mac, either Format → Make Plain Text in TextEdit first, or use VS Code (plain text by default), or use `nano`/`vim` from the terminal.
139
+ - **Why it bites:** TextEdit's default makes sense for word-processing but is hostile to anything that needs to be byte-exact.
140
+
141
+ ### `.env.local` is auto-provisioned into new worktrees (don't `cp` it by hand)
142
+
143
+ - **Behavior (V3.R59 [#278](https://example.com/builders#/task/278)):** `.env.local` is gitignored, so `git worktree add` does not carry it over. The `SessionStart` hook [`.claude/hooks/session-start.js`](../../.claude/hooks/session-start.js) copies it from the main checkout into the worktree on first session — no manual `cp` from a sibling needed.
144
+ - **If the main checkout has no `.env.local`:** the hook tells you to run `/builder-setup`.
145
+ - **The Google AI Studio key is separate:** it resolves from `~/.config/otb/env`, which already survives worktree churn — see [`art/pipeline/gen_api.py`](../../art/pipeline/gen_api.py).
146
+ - **All hooks run via `node`, not `bash` ([#671](https://example.com/builders#/task/671)):** `SessionStart`, `UserPromptSubmit`, and `Stop` run identically on Windows/macOS/Linux. `session-start.js` chains the env-copy + onboarding + rank-change greeting + memory pull that the old `sync-env-local.sh` shell chain ran.
147
+
148
+ ---
149
+
150
+ ## GDS build pipeline
151
+
152
+ ### Two deterministic routines run as in-process server timers, not external cron
153
+
154
+ - **What:** `peer-vote-tally` (weekly) runs inside the always-on Node process via the autonomy module's poller `modules/autonomy/pollers/routine-timers.js` (ADR 0078 amendment, task 1382; carved into `modules/autonomy/` at BV1.R83) — no `claude -p`, no external cron, no token. The loader's `startModulePollers` starts it (on the game/droplet boot only); it reaches `tallyPeerVotes` through the doorway. It's a no-op anywhere the DB is unreachable (builder machines), so it only does work on the prod droplet.
155
+ - **Disable / move it out-of-process:** set `ROUTINE_TIMERS_DISABLED=1` in `/etc/example/web-source.env` and restart. Also set it on any **second** always-on instance that shares the `example` DB so the tally can't double-fold (the `FOR UPDATE OF pv` row lock is the hard guard if you forget).
156
+ - **Run it manually now:** `node scripts/gds/run-routine.js peer-vote-tally` (the dispatcher front door still works). The cadence is boot-anchored ("~90s after boot, then weekly"), not a wall-clock Monday job — frequent deploys re-anchor it, which is harmless (the tally is idempotent).
157
+
158
+ ### A ship was graded FAIL but the work is genuinely good (grader false-negative)
159
+
160
+ - **Symptom:** `/builder-ship` runs the subagent grader and it hard-FAILs with blockers that are *factually wrong* — e.g. "No PNG committed" / "no evidence the review ran" / "empty diff — no files changed" — even though the work is committed on the branch and passed its own review. The task is stuck at `completed` with 0 credits, and the builder is below Archon so every fix route (`PATCH touches`, `POST /confirm`, override-decide) is gated.
161
+ - **Root cause (one known class, fixed):** the grader read a `null` baseline because the task had empty `touches[]`, so it diffed against nothing and "saw" zero files. Fixed in [#536](https://example.com/builders#/task/536) — the grader baseline is now derived from `git merge-base` independent of `touches[]`. If you hit a *different* false-negative class, treat the below as the general escape hatch.
162
+ - **The process (canonical — works at any rank):**
163
+ 1. The **stuck builder** (any rank, incl. Xenos) files an override request — this is the one builder-rank-available escape hatch:
164
+ `POST /api/gds/tasks/:id/override-request` with `{ "rationale": "<≥20 chars: why the grade is wrong>" }`.
165
+ This is *not* routing around the trust boundary — Xenos are allowed to file; only the decision is privileged.
166
+ 2. An **Archon** reviews the open queue (`GET /api/gds/override-requests?status=open`) and decides:
167
+ `POST /api/gds/override-requests/:id/decide` with `{ "decision": "approve", "note": "..." }`.
168
+ 3. On approve, the task flips `completed → confirmed` and **both the credit AND the ship attribution (`shipped_by`) land with the original requester**, never the approving Archon ([#538](https://example.com/builders#/task/538)). The whole exchange is permanently audited in `task_override_requests` (requester, decider, rationale, decision note, timestamps).
169
+ - **Do NOT** use `POST /tasks/:id/confirm` to unstick *another* builder's task — it credits + attributes to the *caller* (the Archon), not the original builder. `/confirm` is for the shipping builder's own `--skip-grade` path. The override-request → approve flow is the correct tool when the work was someone else's.
170
+ - **Why it bites:** the grader defaults to fail (by design — it's adversarial), so a false-negative looks identical to a real rejection. The fix is a documented, audited human-in-the-loop appeal, not a grader bypass — and the appeal pays the right person.
171
+
172
+ ---
173
+
174
+ ## Status page + monitoring
175
+
176
+ ### Cloudflare 522 with the whole site dark — the droplet itself is down (often billing)
177
+
178
+ - **Symptom:** `example.com` shows Cloudflare **522 (connection timed out)** and the status page is dark too. From your machine, `ping` + `ssh` (port 22) + `curl https://…` (443) **all time out** — not "connection refused" — yet `dig example.com` still returns Cloudflare IPs and status.digitalocean.com is green.
179
+ - **Root cause:** the droplet is powered off / hung / firewalled — **not** an app crash. A *timeout* (black-hole) on every port means packets are dropped, the signature of the box being down or network-blocked; *refused* would mean the box is up but the service isn't listening. On 2026-06-03 the cause was a **failed DigitalOcean payment** — DO powers off droplets when a charge fails.
180
+ - **Fix:** every lever is in the **DigitalOcean web panel** (SSH is dead and we keep no `doctl`/API token locally): check for a billing banner, check the droplet's power state, then Power → Turn on / Power Cycle. The recovery console bypasses SSH entirely. Confirm with `ssh … uptime` (a fresh boot) once it answers; systemd auto-starts caddy/node/postgres. Prevent recurrence with a **backup payment method + balance alerts** on DO.
181
+ - **Why it bites:** a billing power-off looks identical to a crash or a firewall block, and the status page can't tell you which — it's served by the same droplet (see next entry).
182
+
183
+ ### Your status page must not share fate with the product (and cannot measure itself)
184
+
185
+ - **Symptom:** the site is down for hours, but The Watch still shows 100% / "standing".
186
+ - **Root cause:** `status.example.com` is served by the same Node process on the same droplet as the game, and the in-process poller (`src/bongos/uptime-poller.js`) probes `127.0.0.1`. When the droplet dies, the page dies with it and the poller writes **zero rows** — the gap renders as green. A monitor that lives inside the monitored thing cannot witness its own death.
187
+ - **Fix:** measure availability from **outside** (the external GitHub-Actions prober — `.github/workflows/status-probe.yml`, task [#565](https://example.com/builders#/task/565)) and host the status page **off-box** (follow-up [#566](https://example.com/builders#/task/566)). See [ADR 0029](../adr/<redacted>.md) + GDS learning `#35`.
188
+ - **Why it bites:** a status page that lies is worse than none — it actively reassures you while the product is on fire.
189
+
190
+ ### The live status page is NOT served by the droplet — editing the status surface + deploying does nothing
191
+
192
+ > **Path note (BV1.R84):** the status surface moved from `public-status/` to `modules/status-ui/public/` (carved to the `status-ui` web-surface module). Everything below applies at the new path; `scripts/status-mirror-sync.js` was re-pointed. **Open follow-up:** `.github/workflows/sync-status-mirror.yml` still triggers on `public-status/**` and must be re-pointed at `modules/status-ui/public/**` by an owner/Archon (the GitHub App can't push `.github/workflows/*`, learning 107) — until then the auto-sync won't fire and you must run the script by hand.
193
+
194
+ - **Symptom:** you change `modules/status-ui/public/`, deploy to the droplet, the origin serves the new page (verified via `curl` on the box), but `status.example.com` keeps showing the old version. Purging Cloudflare doesn't help.
195
+ - **Root cause:** the off-box move (ADR 0029) repointed `status.example.com` DNS at **GitHub Pages from the separate repo `example-owner/example-status`** (served by Fastly — headers say `server: GitHub.com`, `via: varnish`, **no `cf-*` headers** → Cloudflare isn't even in the path). The droplet still serves `modules/status-ui/public/` as a same-origin fallback, but the public DNS goes to Pages. There was no sync, so droplet edits never reached the live page.
196
+ - **Fix:** publish to the mirror with `node scripts/status-mirror-sync.js --repo-dir <mirror-checkout> --push` — or (once the workflow trigger is re-pointed, see the path note above) let `.github/workflows/sync-status-mirror.yml` do it on push (needs the `STATUS_MIRROR_TOKEN` repo secret). `status.js`/`style.css`/`cursors/` are byte-identical copies (the one off-box difference, the API base, is injected via `window.STATUS_API_BASE` in the mirror's `index.html`); the sync injects the off-box banner + API-base script into `index.html` at fixed anchors and **throws if an anchor is missing** rather than mis-publishing. GitHub Pages purges its own Fastly cache on deploy, so the live page updates ~1 min after the Pages build goes green (`gh api repos/example-owner/example-status/pages/builds/latest`). ([#737](https://example.com/builders#/task/737))
197
+ - **Why it bites:** the origin looks correct at every layer you can `curl` from the box, so you chase a phantom cache on the wrong CDN. The tell is the response headers — `server: GitHub.com` + Fastly, not `cloudflare`.
198
+
199
+ ---
200
+
201
+ ## Dev box
202
+
203
+ ### `bypassPermissions` "still not available" even though the box was provisioned for it (task 2022)
204
+
205
+ - **Symptom:** you reconnect to the browser terminal (or SSH) on a dev box and `claude` still stops for permission prompts, even though tasks [#1251](https://example.com/builders#/task/1251) and [#1314](https://example.com/builders#/task/1314) default every box to `bypassPermissions`.
206
+ - **Root cause:** `otb-box-launch.sh` (behind `box-terminal.service`) only ever runs `claude` once — the first time it creates the tmux `otb` session. Every later connect just reattaches to that **same running process**. The `defaultMode=bypassPermissions` setting is written into `~/.claude/settings.json` by `box-source-fetch.sh`'s cron, on its own `*/10` schedule (and, on an already-provisioned box, only after that box's baked copy of the script has self-updated to even contain the fix). If the `otb` tmux session got created before that write landed — an older box, or a fresh box whose very first connect raced the first cron tick — `claude` started once in normal `auto` mode and is stuck there for the life of the box; reconnecting never re-launches it, so the fix never takes effect even once the setting is correct on disk. (Flagged as an open follow-up in [ADR 0104](../adr/<redacted>.md).)
207
+ - **Fix:** `otb-box-launch.sh` now asserts `defaultMode=bypassPermissions` itself, synchronously, right before it creates a **new** `otb` tmux session — so a fresh session never depends on cron timing. This prevents the race going forward but does **not** repair a box whose `otb` session is already running in the wrong mode: for that, from an SSH/browser-terminal shell run `tmux kill-session -t otb` then reconnect (the launcher creates a fresh session and picks up the corrected setting immediately). Killing the session only drops the terminal pane — it does not touch `/workspace` or in-flight git state.
208
+ - **Why it bites:** every layer *looks* fixed — `~/.claude/settings.json` has the right value, `IS_SANDBOX=1` is set — because you're inspecting the box's filesystem, not the already-running process that never re-read it.
209
+
210
+ ## When to add a new entry here
211
+
212
+ Anytime you spend more than ~10 minutes diagnosing something that turned out to have a non-obvious cause, add a section. Include symptom, root cause, fix, and why-it-bites. The cost of a 5-minute write-up is much less than the cost of the next session re-discovering the same thing.
@@ -0,0 +1,53 @@
1
+ # Recipe — running the autonomous overnight builder ("session polling")
2
+
3
+ > Added under GDS-V3 task [#358](https://example.com/builders#/task/358). The routine itself is `.claude/scheduled-tasks/overnight-builder/SKILL.md`; this page is the operator's runbook. Archon-only.
4
+
5
+ ## What it does
6
+
7
+ Starts one session that works the GDS queue **by priority, on its own**. It claims the highest-priority safe task, works it in a fresh sub-agent, ships it, then re-polls the claimable list — the promote-on-ship DB trigger (migration 020) self-feeds the queue, so as soon as one task ships the next unblocked one is waiting. It loops until nothing claimable remains, the time budget runs out, or the cost cap is hit.
8
+
9
+ It only ever touches tasks the GDS marks safe to run unattended (`automation_tag = 'overnight-safe'`, `manual_degree <= 2`, unblocked). Nothing broken reaches `main`: the quality grader gates credits and the auto-merge re-runs smoke tests and bails (parking the task) on any conflict or failure.
10
+
11
+ ## Start it (serial — the proven path)
12
+
13
+ 1. **Keep the Mac awake.** Deploys run from your machine, so it must stay on. In a terminal:
14
+ ```bash
15
+ caffeinate -i &
16
+ ```
17
+ `caffeinate` is a built-in macOS command that stops the Mac from sleeping; `-i` prevents idle sleep until you kill it (`kill %1` or just close the terminal in the morning). Nothing to install.
18
+ 2. **Open a Claude Code session** in the repo and launch the routine, e.g.:
19
+ > "Run the overnight-builder routine. Serial, 6-hour budget, stop at $40."
20
+ 3. It checks you're **Archon** (refuses otherwise), then loops. Walk away.
21
+
22
+ ## Go parallel (advanced — opt in only with credit headroom)
23
+
24
+ Parallel runs several tasks at once in **separate isolated worktrees**. It gets more done but spends Claude credits several times faster and has more ways to get stuck unattended. Only use it when you know you have the credit headroom for the night.
25
+
26
+ > "Run overnight-builder, **parallel 3**, 6-hour budget, stop at $80."
27
+
28
+ The runner only fills parallel slots with tasks explicitly flagged **`parallel_safe = true`** (and, as always, with non-overlapping file footprints). Flag a task parallel-safe at creation (`parallel_safe: true` in `POST /api/gds/tasks`) or after the fact:
29
+
30
+ ```bash
31
+ TOKEN=$(node -e "console.log(require(require('os').homedir()+'/.config/otb/pms-session.json').token)")
32
+ curl -sS -X PATCH -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
33
+ -d '{"parallel_safe": true}' https://example.com/api/gds/tasks/<id>
34
+ ```
35
+
36
+ In parallel mode each worker stops at `confirmed` (credits land) and the runner lands the merges **one at a time** — concurrent merges to `main` are never allowed.
37
+
38
+ ## Reading the morning report
39
+
40
+ The end-of-run report buckets everything; the only things needing you are:
41
+
42
+ - **Parked — needs merge** (`confirmed`): a ship passed quality review but hasn't landed yet. The server reconciler sweeps these to `shipped` on its own within ~5 min — re-check the report before acting. Only if one is *still* parked after that does it need **`/merge-mode`** by hand (a conflict the server couldn't auto-resolve).
43
+ - **Parked — needs grade review** (`completed`): the quality grader failed or flaked (it flakes ~1 in 3). Eyeball the change; if it's good, manually confirm it (`POST /api/gds/tasks/:id/confirm`, archon-only).
44
+ - **Released with feedback**: the runner couldn't finish these and put them back in the queue with a note (a captured learning) explaining why — so the next builder, you or it, doesn't start from zero. Nothing to do unless you want to unblock them.
45
+
46
+ Everything under **Shipped** is already merged and deployed.
47
+
48
+ ## Gotchas
49
+
50
+ - **It's archon-only** by policy (only `archon` and `thetes` ranks are live; claim/ship are open to any builder at the API, so the rank check lives in the routine). When middle ranks go live, widen the gate there.
51
+ - **No more `--expand-touches` / drift scanner (task 879).** ship.js no longer scans for files outside the declared touches[] or offers to expand it — a wrong up-front prediction isn't ship-blocking; `git merge` at land time is the authoritative collision detector. (Older notes referenced `--expand-touches auto`; that flag is gone.)
52
+ - **`.env.local` doesn't propagate to fresh worktrees** — if a parallel worker's task hits the Google API (art pipeline), copy it in first. See `docs/recipes/pixel-art-pipeline.md`.
53
+ - **Start serial first.** Prove a clean single-task loop before trusting a parallel night.
@@ -0,0 +1,49 @@
1
+ # Recipe — packaging the Cloud Bongos core as a pinned, installable artifact
2
+
3
+ > Implements [ADR 0100 §1](../adr/<redacted>.md) (the two-repo instance model). This is **R84**, the first step of the `R84 → R85 → R86` spine: package the core → stand a downstream instance up on a pinned core → make `bongos upgrade` a real update channel. Tooling: [`scripts/gds/package-core.js`](../../scripts/gds/package-core.js) (`bongos package-core`).
4
+ >
5
+ > **Real installable npm package ([ADR 0108](../adr/<redacted>.md) §2, task 1882/W2, shipped):** the artifact is `package/`-rooted (the npm convention `npm install ./x.tgz` requires) and carries a synthesized `package.json` — `name: "@cloudbongos/core"`, `version` = `CORE_VERSION`, `main: "src/platform-server.js"`, `exports` for the default entry (`buildPlatformApp`) plus `./serve-internal` (`mountInternalSurfaces`) and `./module-api`, `bin: "bongos"` — and a **pruned** `package-lock.json` (express + pg's own transitive closure only, resolved offline from the source lockfile — no colyseus/phaser/sharp/discord.js). Both files are synthesized fresh, never copied verbatim from the source repo's game-heavy `package.json`. `resolveCoreRoot()`/`resolveInstanceRoot()` ([`src/instance-config.js`](../../src/instance-config.js), W1/task 1881) are what a consumer's own code routes through once installed.
6
+
7
+ ## What the artifact is
8
+
9
+ A Cloud Bongos *instance* can be its **own repository** that installs a **pinned version** of the Cloud Bongos **core** — the portable methodology + platform + neutral branding — and layers its own content, branding, and modules on top. "The core" is not re-defined here: it is exactly the subtree [`isPublishable()`](../../scripts/gds/publish-manifest.js) already defines ([ADR 0098](../adr/<redacted>.md)).
10
+
11
+ `bongos package-core` produces three things in `dist/` (git-ignored — the artifact is a build product, not committed):
12
+
13
+ | Output | What it is |
14
+ |---|---|
15
+ | `cloudbongos-core-<version>.tgz` | the installable unit — a gzip'd tar of the redacted core tree, rooted at `package/` (the npm convention `npm install ./x.tgz` requires), carrying a synthesized `@cloudbongos/core` `package.json` + pruned `package-lock.json` (task 1882) |
16
+ | `cloudbongos-core-<version>.manifest.json` | the **pin** — version, source commit, per-file hashes, and the tree hash a consumer verifies against |
17
+ | `cloudbongos-core-<version>/` | the same redacted tree unpacked, for inspection |
18
+
19
+ The version is the **platform version** — `CORE_VERSION` from [`src/module-api.js`](../../src/module-api.js), the same coordinate the module loader and `bongos upgrade` compare against ([#1203](https://example.com/builders#/task/1203)). That shared coordinate is what keeps the spine coherent: a module pinned to `^core_contract` is guaranteed to load against the packaged core.
20
+
21
+ Every file is **redacted** through the same fail-closed pipeline the public mirror uses ([ADR 0099](../adr/<redacted>.md)): instance literals + public IPs are stripped, a secret backstop runs, and if *any* residual leak survives the packager **produces nothing** (`dist/` is never touched). So a downstream repo never inherits the source instance's identity or secrets — it gets a neutral core.
22
+
23
+ ## Produce it
24
+
25
+ ```sh
26
+ bongos package-core # from HEAD, version = platform CORE_VERSION
27
+ bongos package-core --ref origin/main --version 1.13.0
28
+ node scripts/gds/package-core.js --droplet-ip <ip> # add the prod IP as an exact gate literal
29
+ ```
30
+
31
+ `--ref` chooses the source commit (default `HEAD`), `--out-dir` the output dir (default `dist`), `--version` overrides the stamped version. `stdout` carries a one-line JSON pin (`{ core_version, source_commit, tree_sha256, tarball }`) for CI/scripts to capture; human detail goes to `stderr`.
32
+
33
+ If the no-leak gate fails, it names the file + the residual literal. Fix the redaction rules ([`scripts/gds/mirror-redact.js`](../../scripts/gds/mirror-redact.js)) or the manifest exclusions ([`scripts/gds/publish-manifest.js`](../../scripts/gds/publish-manifest.js)) and re-run — do not weaken the gate to force a pass.
34
+
35
+ ## Consume + pin it (the R85 side)
36
+
37
+ A downstream instance repo:
38
+
39
+ 1. **Installs** the `.tgz` — `npm install ./cloudbongos-core-<version>.tgz` (or a fetched-in-CI path) — which lands it at `node_modules/@cloudbongos/core/`, a directory the consumer does not hand-edit.
40
+ 2. **Pins** by recording `core_version` + `source_commit` + `tree_sha256` from the manifest.
41
+ 3. **Verifies** the install by recomputing `tree_sha256` from the unpacked tree — for each core file, `sha256(content)` with a canonical mode (`0000644`/`0000755`), then `sha256` over the sorted `"<path> <mode> <filesha>"` lines. It must equal the manifest's `tree_sha256`. The tree hash is **compression-independent**, so it is a stable pin even though `.tgz` bytes are an implementation detail (`tarball.sha256` separately verifies the exact download).
42
+
43
+ The manifest's `files[]` carries the same `{ path, mode, sha256 }` triples, so the pin also recomputes from the manifest alone — the two must agree.
44
+
45
+ ## Boundaries + relation to the mirror
46
+
47
+ - **Not the public mirror.** The delayed, redacted, ~6-month-lagged public mirror ([ADR 0099](../adr/<redacted>.md)) is the open-source surface. This artifact is a *current*, versioned unit for **dependency consumption** by a sister repo — no lag. Both reuse the same `isPublishable()` selection and the same redaction; `package-core.js` imports the mirror's `redactBlob` so the redaction logic is defined once.
48
+ - **Per-repo GDS.** Each instance runs its own database, tasks, builders, and credits ([ADR 0100 §3](../adr/<redacted>.md)). Packaging the core moves *code*, never work-tracking state.
49
+ - **The single-checkout instance model is not deprecated** — it stays the cheaper shape for a quick reskin (cloudbongos.com). Two-repo is the destination for a project that wants to be its own thing and pull core updates on its own schedule.
@@ -0,0 +1,63 @@
1
+ # Parallel-load test results — 2026-05-30 ([#272](https://example.com/builders#/task/272), criterion C6)
2
+
3
+ > **Harness:** [`tests/parallel-load.mjs`](../../tests/parallel-load.mjs) · **Procedure:** [parallel-load-test.md](parallel-load-test.md) · **Target:** seeded staging ([#262](https://example.com/builders#/task/262)) at `http://127.0.0.1:3001` on the droplet (direct, bypassing Cloudflare).
4
+
5
+ This is the live run that closes **[#272](https://example.com/builders#/task/272) (V3.R53)** and satisfies criterion **C6 — parallel-safe-under-load**. It exercises the deterministic claim concurrency audited in [#269](https://example.com/builders#/task/269) (the `claimTask()` transaction + `uniq_active_claim_per_task` index) against a real running server under concurrent load.
6
+
7
+ ## Bottom line
8
+
9
+ **Across both runs: ZERO `server_error` (5xx), ZERO races, ZERO anomalies.** Every claim resolved to exactly one of: `success`, `collision` (409 — exactly-one-wins), or `throttled` (429 — the rate limiter cleanly shedding excess writes). Staging's journal logged **0** 5xx responses over the full window. C6's bar — "all claims succeed or 409 cleanly; no 500s, no race conditions" — holds, with the added finding that excess write load is shed cleanly via 429 rather than ever degrading into a race or crash.
10
+
11
+ ## Run A — sustained 30-minute run (the [#272](https://example.com/builders#/task/272) acceptance run)
12
+
13
+ `--workers 5 --duration 1800 --work-ms 150` (natural claim→work→release→repeat loop across distinct tasks):
14
+
15
+ | metric | value |
16
+ |---|---|
17
+ | wall | 1800.1s (30 min) |
18
+ | claim attempts | 144 |
19
+ | success | 13 |
20
+ | collision (409, exactly-one-wins) | 8 (5.6%) |
21
+ | throttled (429) | 123 |
22
+ | **server_error (5xx)** | **0** |
23
+ | client_error / other | 0 / 0 |
24
+ | anomalies | 0 |
25
+ | staging 5xx in journal | 0 |
26
+
27
+ The system stayed healthy (`/healthz` 200) for the entire 30 minutes with no degradation. Low attempt volume is expected: the per-IP rate limiter (below) caps writes, and releases that get throttled leave tasks `active`, draining the claimable pool — so workers spend most cycles idling on an empty queue rather than hammering. That's the system behaving correctly under its own backpressure.
28
+
29
+ ## Run B — high-intensity contention burst (forces collisions)
30
+
31
+ `--workers 5 --duration 25 --work-ms 100 --contend` (all 5 workers race the SAME task — the canonical "two builders, one task" case):
32
+
33
+ | metric | value |
34
+ |---|---|
35
+ | claim attempts | 2733 |
36
+ | success | 8 |
37
+ | collision (409, exactly-one-wins) | 17 |
38
+ | throttled (429) | 2708 |
39
+ | **server_error (5xx)** | **0** |
40
+ | anomalies | 0 |
41
+
42
+ This is the direct demonstration of the C6 invariant: when multiple workers race the same task row, **exactly one wins and the rest get a clean 409 `ALREADY_CLAIMED`** — never two winners, never a 5xx.
43
+
44
+ ## The rate limiter (a relevant, healthy finding)
45
+
46
+ `src/bongos/middleware/rate-limit.js` enforces **30 writes / 60s per-IP** and **60 writes / 60s per-session** on write methods (GET is unlimited). Because all simulated workers run from the droplet's single IP, the per-IP limit binds first, so most write attempts under load return **429** (`throttled` above). For a parallel-safety test this is a *positive* result: under sustained overload the server sheds excess writes cleanly (429 + `Retry-After`) instead of racing or 500ing. To exercise the claim logic at higher volume in a future run, raise the limit on staging or distribute workers across IPs.
47
+
48
+ ## Harness fixes made while running this (committed under [#272](https://example.com/builders#/task/272))
49
+
50
+ Running against the real server surfaced live-path bugs the self-test (mock) couldn't:
51
+
52
+ - **claimable parsing:** the harness read `.data.tasks`, but `GET /tasks/claimable` returns `{ claimable: [...] }` → it saw 0 tasks and never claimed. Fixed to read `.claimable` (with `.tasks` fallback).
53
+ - **429 classification:** 429 was bucketed as `other` / flagged as a release anomaly. Added a dedicated `throttled` outcome (clean) so the report and the pass/fail conclusion are accurate.
54
+ - **`--contend` mode:** added so workers can be pointed at one task to demonstrate exactly-one-wins collisions on demand (Run B).
55
+
56
+ ## Reproduce
57
+
58
+ ```bash
59
+ # On the droplet (staging seeded per #262, service running, alphanumeric token minted):
60
+ cd /home/lars/example-staging
61
+ BASE_URL=http://127.0.0.1:3001 TOKEN=<redacted> node tests/parallel-load.mjs --workers 5 --duration 1800 --work-ms 150
62
+ # add --contend to force same-task collisions
63
+ ```
@@ -0,0 +1,32 @@
1
+ # Parallel-load test — exercising claim concurrency under N builders
2
+
3
+ > **Harness:** [`tests/parallel-load.mjs`](../../tests/parallel-load.mjs) (built under prep task [#472](https://example.com/builders#/task/472)).
4
+ > **Live run:** criterion **C6** task **[#272](https://example.com/builders#/task/272)** (V3.R53) — a 30-min, 5-builder run against **staging**, gated on **[#262](https://example.com/builders#/task/262)** (staging data seeding).
5
+
6
+ The harness spawns N concurrent simulated "builder" loops that hammer the GDS claim lifecycle (claim → simulated work → release → repeat) and classifies every claim outcome into `success` / `collision` (clean 409/refusal) / `server_error` (the anomaly we hunt) / `client_error` / `other`. It validates the deterministic claim concurrency C6 requires — the same `claimTask()` transaction + `uniq_active_claim_per_task` index audited in [multi-builder-merge.md](multi-builder-merge.md).
7
+
8
+ ## Self-test (CI-safe, no network)
9
+
10
+ ```bash
11
+ node tests/parallel-load.mjs # defaults: 5 workers, 60s
12
+ node tests/parallel-load.mjs --workers 5 --duration 3 --work-ms 50
13
+ ```
14
+
15
+ With no `BASE_URL`, the harness drives an **in-process mock server** whose claim semantics mirror the DB (one active claim per task; touches-overlap → conflict). The board deliberately has two tasks sharing a path so collisions are *forced*, then asserts: ≥1 success, ≥1 collision, **zero** server_error, no invariant violation, and that attempts == sum of classes. Exit 0 = harness accounting proven correct. This runs in CI without a droplet.
16
+
17
+ ## Live run against staging ([#272](https://example.com/builders#/task/272) — once [#262](https://example.com/builders#/task/262) has seeded staging)
18
+
19
+ ```bash
20
+ # Get builder tokens (one or more simulated builders share the load).
21
+ # NEVER point this at production — it mutates real claim/task state. The
22
+ # harness refuses a prod example.com host unless you pass --i-know.
23
+ BASE_URL=https://staging.example.com \
24
+ TOKENS=$tokA,$tokB,$tokC,$tokD,$tokE \
25
+ node tests/parallel-load.mjs --workers 5 --duration 1800
26
+ ```
27
+
28
+ `#272` acceptance: run 30 min (`--duration 1800`); **every claim resolves to `success` or a clean `collision` — zero `server_error`, no races**; the report's throughput + collision-rate are the deliverable. A single anomaly (any 5xx, thrown error, or invariant violation) exits 1 and fails the run.
29
+
30
+ ## Why the split (prep [#472](https://example.com/builders#/task/472) vs live [#272](https://example.com/builders#/task/272))
31
+
32
+ `#272`'s done-when explicitly requires a seeded staging environment, which `#262` (backlog) provides. Rather than block the runnable harness behind infra, [#472](https://example.com/builders#/task/472) built + self-validated the harness now; [#272](https://example.com/builders#/task/272) stays the live-staging run. When [#262](https://example.com/builders#/task/262) ships, point the harness at staging per above to close [#272](https://example.com/builders#/task/272) and satisfy C6.