@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,728 @@
1
+ // tests/publish_reconciler.mjs
2
+ //
3
+ // Unit tests for the server-owned publish reconciler (task 1134) — the durable
4
+ // cure for the "strands at confirmed" class. A server-mediated publish (ADR 0055)
5
+ // is async; ship.js stops polling after ~9 min, so the confirmed→shipped flip had
6
+ // no driver once the box exited. This module sweeps confirmed tasks on a timer and
7
+ // runs the EXACT shipTask + postShipBroadcast the publish-status route runs.
8
+ //
9
+ // runSweep is pure w.r.t. injected deps (db / githubPush / emit / loggers)
10
+ // — no DB, no network — so this runs in the DB-free unit gate.
11
+ //
12
+ // Run: node tests/publish_reconciler.mjs
13
+
14
+ import { strict as assert } from 'node:assert';
15
+ import { createRequire } from 'node:module';
16
+
17
+ const require = createRequire(import.meta.url);
18
+ const reconciler = require('../modules/lifecycle/publish-reconciler.js');
19
+
20
+ let passed = 0;
21
+ let failed = 0;
22
+ function test(name, fn) {
23
+ Promise.resolve()
24
+ .then(fn)
25
+ .then(() => {
26
+ passed++;
27
+ console.log(` ok ${name}`);
28
+ })
29
+ .catch((err) => {
30
+ failed++;
31
+ console.log(` FAIL ${name}`);
32
+ console.log(` ${err.message}`);
33
+ });
34
+ }
35
+
36
+ // A LANDED status (merged + deploy succeeded). Mirrors getPublishStatus's shape.
37
+ const LANDED = { pr_state: 'closed', merged: true, merge_sha: 'abc1234deadbeef', deploy_status: 'success' };
38
+ const PENDING = { pr_state: 'open', merged: false, merge_sha: null, deploy_status: 'pending' };
39
+ const NONE = { pr_state: 'none', merged: false, merge_sha: null, deploy_status: 'none' };
40
+
41
+ // task 1547 fixtures: sha-shaped published tips scripted on/off main via ancestryBySha.
42
+ const ON_MAIN = 'a'.repeat(40);
43
+ const NOT_ON_MAIN = 'b'.repeat(40);
44
+ // A LANDED status whose matched PR references task `id` in its server-generated body
45
+ // (the no-published-tip fallback path).
46
+ const landedPrFor = (id) => ({ ...LANDED, pr_number: 700 + id, pr_title: `task ${id}: x`, pr_body: `for task ${id}` });
47
+
48
+ // Build an injectable deps bundle with sensible defaults + recording stubs.
49
+ function mkDeps({
50
+ configured = true,
51
+ rows = [],
52
+ statusByBranch = {},
53
+ mergeByBranch = {},
54
+ ancestryBySha = {},
55
+ shipImpl,
56
+ broadcastImpl,
57
+ conflictResolveImpl,
58
+ refreshStaleImpl,
59
+ healAttempts = new Map(),
60
+ } = {}) {
61
+ const calls = { ship: [], broadcast: [], status: [], merge: [], ancestry: [], resolve: [], refresh: [], logs: [], errors: [] };
62
+ const realLandConfirmed = (s) => !!s && s.merged === true && s.deploy_status === 'success';
63
+ // isSafeBranch mirrors github-push's pattern enough for the test (rejects
64
+ // option-like / traversal refs); we use the REAL module so the contract can't drift.
65
+ const githubPush = require('../modules/lifecycle/github-push.js');
66
+ return {
67
+ db: {
68
+ listConfirmedTasksForReconcile: async () => rows,
69
+ shipTask: shipImpl || (async ({ taskId, builderId }) => {
70
+ calls.ship.push({ taskId, builderId });
71
+ return { id: taskId, value_summary: `task ${taskId}`, security_sensitive: false };
72
+ }),
73
+ },
74
+ githubPush: {
75
+ isConfigured: () => configured,
76
+ isSafeBranch: githubPush.isSafeBranch,
77
+ landConfirmed: realLandConfirmed,
78
+ // Active merge driver (task 1162). Default: nothing to merge. A branch listed
79
+ // in mergeByBranch returns its scripted result; an Error value throws (to
80
+ // prove the sweep swallows a merge-driver failure and continues to land-check).
81
+ mergeIfGreen: async ({ branch }) => {
82
+ calls.merge.push(branch);
83
+ const m = mergeByBranch[branch];
84
+ if (m instanceof Error) throw m;
85
+ return m || { merged: false, merged_now: false, reason: 'pending' };
86
+ },
87
+ getPublishStatus: async ({ branch }) => {
88
+ calls.status.push(branch);
89
+ const s = statusByBranch[branch];
90
+ if (s instanceof Error) throw s;
91
+ return s || NONE;
92
+ },
93
+ // task 1313 head_sha land-check. Default: not on main. An Error value throws
94
+ // (to prove a transient compare-API miss is swallowed, leaving it for next sweep).
95
+ isAncestorOfDefaultBranch: async ({ sha }) => {
96
+ calls.ancestry.push(sha);
97
+ const a = ancestryBySha[sha];
98
+ if (a instanceof Error) throw a;
99
+ return !!a;
100
+ },
101
+ // task 1547 per-task land proof. Mirrors the real github-push.landProvenForTask
102
+ // shape but routes its ONE network hop (the ancestry compare) through the mock
103
+ // above so the sweep stays DB/network-free, and reuses the REAL prReferencesTask
104
+ // so that pure check can't drift. publishedSha (the server-pushed tip) is the
105
+ // robust proof; the matched-PR-references-this-task fallback covers a legacy /
106
+ // in-flight row with no recorded tip.
107
+ landProvenForTask: async ({ taskId, publishedSha, status }) => {
108
+ if (publishedSha && /^[0-9a-f]{7,64}$/.test(String(publishedSha))) {
109
+ calls.ancestry.push(publishedSha);
110
+ const a = ancestryBySha[publishedSha];
111
+ if (a instanceof Error) throw a;
112
+ return a
113
+ ? { proven: true, reason: `published tip ${publishedSha.slice(0, 8)} in main` }
114
+ : { proven: false, reason: `published tip ${publishedSha.slice(0, 8)} not in main` };
115
+ }
116
+ return githubPush.prReferencesTask(status, taskId)
117
+ ? { proven: true, reason: `matched PR references task ${taskId}` }
118
+ : { proven: false, reason: `no published tip and matched PR does not reference task ${taskId}` };
119
+ },
120
+ },
121
+ // task.shipped is emitted on the kernel seam now; the discord module's listener
122
+ // posts the broadcast (BV1.R47). Inject `emit` to observe it — the reconciler
123
+ // fires it once per shipped task on the confirmed→shipped transition. A custom
124
+ // broadcastImpl REPLACES the default push (the throwing-broadcast test relies
125
+ // on that to prove the reconcile stands even when the listener throws).
126
+ emit: async (event, task) => {
127
+ if (event !== 'task.shipped') return;
128
+ if (broadcastImpl) return broadcastImpl(task);
129
+ calls.broadcast.push(task.id);
130
+ },
131
+ // task 1385: server-side conflict resolver. Default stub is a no-op so the
132
+ // existing tests (no merge_conflict) never invoke the real module.
133
+ // task 1915: refreshStaleGenerated — the mergeable-but-stale-generated heal.
134
+ // Default records the call and reports no diff (a real failure), so a test that
135
+ // doesn't opt in never healed anything.
136
+ conflictResolve: {
137
+ resolveBranchConflicts: conflictResolveImpl || (async ({ branch }) => {
138
+ calls.resolve.push(branch);
139
+ return { resolved: false, skipped: 'unconfigured' };
140
+ }),
141
+ refreshStaleGenerated: refreshStaleImpl || (async ({ branch }) => {
142
+ calls.refresh.push(branch);
143
+ return { refreshed: false, skipped: 'no_regen_diff' };
144
+ }),
145
+ },
146
+ // task 1915: per-branch treadmill guard, injected so the cap is deterministic and
147
+ // never leaks module state across tests.
148
+ healAttempts,
149
+ log: (m) => calls.logs.push(m),
150
+ error: (m) => calls.errors.push(m),
151
+ _calls: calls,
152
+ _healAttempts: healAttempts,
153
+ };
154
+ }
155
+
156
+ // ---------------------------------------------------------------------------
157
+
158
+ test('no push credential → no-op (skipped: unconfigured), never touches the DB', async () => {
159
+ const deps = mkDeps({ configured: false, rows: [{ task_id: 1, builder_id: 9, worktree_name: 'wt' }] });
160
+ const r = await reconciler.runSweep(deps);
161
+ assert.equal(r.skipped, 'unconfigured');
162
+ assert.equal(r.reconciled, 0);
163
+ assert.equal(deps._calls.status.length, 0, 'must not call GitHub when unconfigured');
164
+ });
165
+
166
+ test('a landed branch → shipTask + broadcast fire, reconciled=1, attributed to the claim holder', async () => {
167
+ const deps = mkDeps({
168
+ rows: [{ task_id: 1096, builder_id: 7, worktree_name: 't1096-helpers', published_head_sha: ON_MAIN }],
169
+ statusByBranch: { 'claude/t1096-helpers': LANDED },
170
+ ancestryBySha: { [ON_MAIN]: true },
171
+ });
172
+ const r = await reconciler.runSweep(deps);
173
+ assert.equal(r.reconciled, 1);
174
+ assert.deepEqual(deps._calls.ship, [{ taskId: 1096, builderId: 7 }]);
175
+ assert.deepEqual(deps._calls.broadcast, [1096]);
176
+ });
177
+
178
+ test('a not-yet-landed branch (open PR / pending deploy) → no ship', async () => {
179
+ const deps = mkDeps({
180
+ rows: [{ task_id: 5, builder_id: 1, worktree_name: 'wt-open' }],
181
+ statusByBranch: { 'claude/wt-open': PENDING },
182
+ });
183
+ const r = await reconciler.runSweep(deps);
184
+ assert.equal(r.reconciled, 0);
185
+ assert.equal(deps._calls.ship.length, 0);
186
+ assert.equal(deps._calls.broadcast.length, 0);
187
+ });
188
+
189
+ test('merged but deploy NOT yet success → no ship (landConfirmed requires both)', async () => {
190
+ const deps = mkDeps({
191
+ rows: [{ task_id: 6, builder_id: 1, worktree_name: 'wt-merged-no-deploy' }],
192
+ statusByBranch: { 'claude/wt-merged-no-deploy': { ...LANDED, deploy_status: 'pending' } },
193
+ });
194
+ const r = await reconciler.runSweep(deps);
195
+ assert.equal(r.reconciled, 0);
196
+ });
197
+
198
+ test('getPublishStatus throws (transient) → swallowed, sweep continues to the next task', async () => {
199
+ const deps = mkDeps({
200
+ rows: [
201
+ { task_id: 1, builder_id: 1, worktree_name: 'wt-bad' },
202
+ { task_id: 2, builder_id: 1, worktree_name: 'wt-good', published_head_sha: ON_MAIN },
203
+ ],
204
+ statusByBranch: {
205
+ 'claude/wt-bad': new Error('GitHub 502'),
206
+ 'claude/wt-good': LANDED,
207
+ },
208
+ ancestryBySha: { [ON_MAIN]: true },
209
+ });
210
+ const r = await reconciler.runSweep(deps);
211
+ assert.equal(r.reconciled, 1, 'the good task still reconciles despite the bad one throwing');
212
+ assert.deepEqual(deps._calls.ship, [{ taskId: 2, builderId: 1 }]);
213
+ });
214
+
215
+ test('shipTask TASK_NOT_CONFIRMED (route/sweep race) → NOT counted as an error, no broadcast', async () => {
216
+ const deps = mkDeps({
217
+ rows: [{ task_id: 3, builder_id: 1, worktree_name: 'wt-raced', published_head_sha: ON_MAIN }],
218
+ statusByBranch: { 'claude/wt-raced': LANDED },
219
+ ancestryBySha: { [ON_MAIN]: true },
220
+ shipImpl: async () => {
221
+ const e = new Error('task not in confirmed state');
222
+ e.code = 'TASK_NOT_CONFIRMED';
223
+ throw e;
224
+ },
225
+ });
226
+ const r = await reconciler.runSweep(deps);
227
+ assert.equal(r.reconciled, 0);
228
+ assert.equal(r.errors, 0, 'an idempotent race is expected, not an error');
229
+ assert.equal(deps._calls.broadcast.length, 0);
230
+ });
231
+
232
+ test('shipTask throws a real error → counted in errors, sweep does not crash', async () => {
233
+ const deps = mkDeps({
234
+ rows: [{ task_id: 4, builder_id: 1, worktree_name: 'wt-dberr', published_head_sha: ON_MAIN }],
235
+ statusByBranch: { 'claude/wt-dberr': LANDED },
236
+ ancestryBySha: { [ON_MAIN]: true },
237
+ shipImpl: async () => { throw new Error('db exploded'); },
238
+ });
239
+ const r = await reconciler.runSweep(deps);
240
+ assert.equal(r.reconciled, 0);
241
+ assert.equal(r.errors, 1);
242
+ });
243
+
244
+ test('a broadcast that throws never undoes the reconcile (still counted shipped)', async () => {
245
+ const deps = mkDeps({
246
+ rows: [{ task_id: 8, builder_id: 2, worktree_name: 'wt-broadcast-fail', published_head_sha: ON_MAIN }],
247
+ statusByBranch: { 'claude/wt-broadcast-fail': LANDED },
248
+ ancestryBySha: { [ON_MAIN]: true },
249
+ broadcastImpl: async () => { throw new Error('discord down'); },
250
+ });
251
+ const r = await reconciler.runSweep(deps);
252
+ assert.equal(r.reconciled, 1, 'the ship stands even if the broadcast throws');
253
+ });
254
+
255
+ test('ambiguous branch (2 confirmed tasks share a worktree_name) → both skipped, no mis-ship', async () => {
256
+ const deps = mkDeps({
257
+ rows: [
258
+ { task_id: 10, builder_id: 1, worktree_name: 'shared-wt' },
259
+ { task_id: 11, builder_id: 1, worktree_name: 'shared-wt' },
260
+ ],
261
+ statusByBranch: { 'claude/shared-wt': LANDED },
262
+ });
263
+ const r = await reconciler.runSweep(deps);
264
+ assert.equal(r.reconciled, 0, 'ambiguous branch must not ship either task');
265
+ assert.equal(deps._calls.ship.length, 0);
266
+ });
267
+
268
+ test('a row with neither worktree_name nor a sha-shaped head_sha is a no-op', async () => {
269
+ const deps = mkDeps({
270
+ rows: [{ task_id: 12, builder_id: 1, worktree_name: null, head_sha: null }],
271
+ });
272
+ const r = await reconciler.runSweep(deps);
273
+ assert.equal(r.reconciled, 0);
274
+ assert.equal(deps._calls.status.length, 0, 'no branch → no PR lookup');
275
+ assert.equal(deps._calls.ancestry.length, 0, 'no sha → no ancestry lookup');
276
+ });
277
+
278
+ // --- task 1547: per-task land proof keyed on the published tip (the strand cure) ---
279
+
280
+ test('PR/branch gone (pr_state none) but published tip on main → ship via ancestry, attributed to claim holder', async () => {
281
+ const deps = mkDeps({
282
+ rows: [{ task_id: 1176, builder_id: 3, worktree_name: 'crazy-haslett-6af2af', published_head_sha: ON_MAIN }],
283
+ statusByBranch: { 'claude/crazy-haslett-6af2af': NONE }, // PR was deleted post-merge
284
+ ancestryBySha: { [ON_MAIN]: true },
285
+ });
286
+ const r = await reconciler.runSweep(deps);
287
+ assert.equal(r.reconciled, 1);
288
+ assert.deepEqual(deps._calls.ship, [{ taskId: 1176, builderId: 3 }]);
289
+ assert.deepEqual(deps._calls.ancestry, [ON_MAIN]);
290
+ });
291
+
292
+ test('no worktree_name at all but published tip on main → ship via ancestry, no branch lookup', async () => {
293
+ const deps = mkDeps({
294
+ rows: [{ task_id: 1273, builder_id: 1, worktree_name: null, published_head_sha: ON_MAIN }],
295
+ ancestryBySha: { [ON_MAIN]: true },
296
+ });
297
+ const r = await reconciler.runSweep(deps);
298
+ assert.equal(r.reconciled, 1);
299
+ assert.equal(deps._calls.status.length, 0, 'no branch to look up');
300
+ assert.deepEqual(deps._calls.ship, [{ taskId: 1273, builderId: 1 }]);
301
+ });
302
+
303
+ test('published tip NOT on main → no ship (genuinely in-flight)', async () => {
304
+ const deps = mkDeps({
305
+ rows: [{ task_id: 50, builder_id: 1, worktree_name: null, published_head_sha: NOT_ON_MAIN }],
306
+ ancestryBySha: { [NOT_ON_MAIN]: false },
307
+ });
308
+ const r = await reconciler.runSweep(deps);
309
+ assert.equal(r.reconciled, 0);
310
+ assert.equal(deps._calls.ship.length, 0);
311
+ });
312
+
313
+ test('merged PR with deploy still pending → wait, do NOT short-circuit via the tip proof', async () => {
314
+ const deps = mkDeps({
315
+ rows: [{ task_id: 51, builder_id: 1, worktree_name: 'wt-deploying', published_head_sha: ON_MAIN }],
316
+ statusByBranch: { 'claude/wt-deploying': { pr_state: 'closed', merged: true, merge_sha: 'cafe1234', deploy_status: 'pending' } },
317
+ ancestryBySha: { [ON_MAIN]: true },
318
+ });
319
+ const r = await reconciler.runSweep(deps);
320
+ assert.equal(r.reconciled, 0, 'a live PR mid-deploy governs — ship only when deploy succeeds');
321
+ assert.equal(deps._calls.ancestry.length, 0, 'the tip proof must not be consulted while a PR is mid-land');
322
+ });
323
+
324
+ test('corrupt published tip ("HEAD") is never sent to the compare API (would false-positive)', async () => {
325
+ const deps = mkDeps({
326
+ rows: [{ task_id: 1199, builder_id: 1, worktree_name: null, published_head_sha: 'HEAD' }],
327
+ ancestryBySha: { HEAD: true }, // even if the API would say yes, we must not ask
328
+ });
329
+ const r = await reconciler.runSweep(deps);
330
+ assert.equal(r.reconciled, 0);
331
+ assert.equal(deps._calls.ancestry.length, 0, 'a non-sha published tip is rejected before the API call');
332
+ });
333
+
334
+ test('ambiguous branch but each task has its own on-main published tip → only the on-main one ships', async () => {
335
+ const deps = mkDeps({
336
+ rows: [
337
+ { task_id: 60, builder_id: 1, worktree_name: 'dup-wt', published_head_sha: ON_MAIN },
338
+ { task_id: 61, builder_id: 2, worktree_name: 'dup-wt', published_head_sha: NOT_ON_MAIN },
339
+ ],
340
+ ancestryBySha: { [ON_MAIN]: true, [NOT_ON_MAIN]: false },
341
+ });
342
+ const r = await reconciler.runSweep(deps);
343
+ assert.equal(r.reconciled, 1, 'only the task whose own tip is on main ships; the branch ambiguity no longer blocks it');
344
+ assert.deepEqual(deps._calls.ship, [{ taskId: 60, builderId: 1 }]);
345
+ assert.equal(deps._calls.status.length, 0, 'ambiguous branch skips the PR path entirely');
346
+ });
347
+
348
+ // --- task 1547: the branch-name-reuse false-ship this fix closes ---
349
+
350
+ test('landConfirmed off a REUSED branch but the published tip is NOT in main → NO ship (the BV1.R04/R05 bug)', async () => {
351
+ // The branch matched an OLDER, already-merged PR (LANDED), but THIS task's own
352
+ // pushed tip never reached main. Pre-fix this false-shipped; now it must not.
353
+ const deps = mkDeps({
354
+ rows: [{ task_id: 1299, builder_id: 95, worktree_name: 'jovial-rosalind-84d6c3', published_head_sha: NOT_ON_MAIN }],
355
+ statusByBranch: { 'claude/jovial-rosalind-84d6c3': LANDED },
356
+ ancestryBySha: { [NOT_ON_MAIN]: false },
357
+ });
358
+ const r = await reconciler.runSweep(deps);
359
+ assert.equal(r.reconciled, 0, 'a stale merged PR on a reused branch must not ship a task whose tip is not on main');
360
+ assert.equal(deps._calls.ship.length, 0);
361
+ });
362
+
363
+ test('landConfirmed, no published tip, matched PR references THIS task → ship (legacy/in-flight fallback)', async () => {
364
+ const deps = mkDeps({
365
+ rows: [{ task_id: 999, builder_id: 1, worktree_name: 'wt-legacy' }], // no published_head_sha
366
+ statusByBranch: { 'claude/wt-legacy': landedPrFor(999) },
367
+ });
368
+ const r = await reconciler.runSweep(deps);
369
+ assert.equal(r.reconciled, 1, 'a legacy land whose own PR references this task still ships');
370
+ assert.deepEqual(deps._calls.ship, [{ taskId: 999, builderId: 1 }]);
371
+ });
372
+
373
+ test('landConfirmed, no published tip, matched PR references a DIFFERENT task → NO ship (branch reuse)', async () => {
374
+ const deps = mkDeps({
375
+ rows: [{ task_id: 1300, builder_id: 95, worktree_name: 'jovial-rosalind-84d6c3' }], // no published_head_sha
376
+ statusByBranch: { 'claude/jovial-rosalind-84d6c3': landedPrFor(1297) }, // the OLD task's PR
377
+ });
378
+ const r = await reconciler.runSweep(deps);
379
+ assert.equal(r.reconciled, 0, 'a reused branch matching another task\'s PR must not ship this task');
380
+ assert.equal(deps._calls.ship.length, 0);
381
+ });
382
+
383
+ test('the tip proof compare-API throws (transient) → swallowed, no ship, next sweep retries', async () => {
384
+ const deps = mkDeps({
385
+ rows: [{ task_id: 70, builder_id: 1, worktree_name: null, published_head_sha: ON_MAIN }],
386
+ ancestryBySha: { [ON_MAIN]: new Error('GitHub 502 on compare') },
387
+ });
388
+ const r = await reconciler.runSweep(deps);
389
+ assert.equal(r.reconciled, 0);
390
+ assert.equal(r.errors, 0, 'a transient ancestry miss is not an error');
391
+ });
392
+
393
+ test('listConfirmedTasksForReconcile failure → skipped: list_failed, no crash', async () => {
394
+ const deps = mkDeps({});
395
+ deps.db.listConfirmedTasksForReconcile = async () => { throw new Error('pool down'); };
396
+ const r = await reconciler.runSweep(deps);
397
+ assert.equal(r.skipped, 'list_failed');
398
+ assert.equal(r.errors, 1);
399
+ });
400
+
401
+ // --- Active merge driver (task 1162) -------------------------------------
402
+
403
+ test('stalled-but-green PR → server merges it (merged_now), counted in summary.merged', async () => {
404
+ const deps = mkDeps({
405
+ rows: [{ task_id: 1093, builder_id: 5, worktree_name: 'romantic-austin-2ea51a' }],
406
+ // not merged yet at land-check (deploy hasn't run) — the merge just fired
407
+ statusByBranch: { 'claude/romantic-austin-2ea51a': PENDING },
408
+ mergeByBranch: { 'claude/romantic-austin-2ea51a': { merged: true, merged_now: true, number: 125 } },
409
+ });
410
+ const r = await reconciler.runSweep(deps);
411
+ assert.equal(r.merged, 1, 'the stalled green PR was server-merged');
412
+ assert.equal(r.reconciled, 0, 'no ship this sweep — deploy not yet success');
413
+ assert.deepEqual(deps._calls.merge, ['claude/romantic-austin-2ea51a']);
414
+ });
415
+
416
+ test('merge driver runs BEFORE the land-check, so a freshly-merged+deployed PR still ships', async () => {
417
+ const deps = mkDeps({
418
+ rows: [{ task_id: 200, builder_id: 1, worktree_name: 'wt-fast', published_head_sha: ON_MAIN }],
419
+ statusByBranch: { 'claude/wt-fast': LANDED }, // already merged + deployed
420
+ ancestryBySha: { [ON_MAIN]: true },
421
+ mergeByBranch: { 'claude/wt-fast': { merged: true, merged_now: false, number: 7 } }, // already merged → no-op
422
+ });
423
+ const r = await reconciler.runSweep(deps);
424
+ assert.equal(r.merged, 0, 'already-merged PR is not re-counted');
425
+ assert.equal(r.reconciled, 1, 'it still ships off the land-check');
426
+ assert.deepEqual(deps._calls.ship, [{ taskId: 200, builderId: 1 }]);
427
+ });
428
+
429
+ test('merge driver throws → swallowed, sweep still proceeds to the land-check', async () => {
430
+ const deps = mkDeps({
431
+ rows: [{ task_id: 201, builder_id: 1, worktree_name: 'wt-mergeboom', published_head_sha: ON_MAIN }],
432
+ statusByBranch: { 'claude/wt-mergeboom': LANDED },
433
+ ancestryBySha: { [ON_MAIN]: true },
434
+ mergeByBranch: { 'claude/wt-mergeboom': new Error('GitHub 500 on merge') },
435
+ });
436
+ const r = await reconciler.runSweep(deps);
437
+ assert.equal(r.merged, 0);
438
+ assert.equal(r.reconciled, 1, 'a merge-driver error never blocks an independent land');
439
+ assert.equal(r.errors, 0, 'a best-effort merge miss is not an error');
440
+ });
441
+
442
+ test('not-green PR → no merge, no ship (merge driver reports but does not force)', async () => {
443
+ const deps = mkDeps({
444
+ rows: [{ task_id: 202, builder_id: 1, worktree_name: 'wt-blocked' }],
445
+ statusByBranch: { 'claude/wt-blocked': PENDING },
446
+ mergeByBranch: { 'claude/wt-blocked': { merged: false, merged_now: false, reason: 'review_required' } },
447
+ });
448
+ const r = await reconciler.runSweep(deps);
449
+ assert.equal(r.merged, 0);
450
+ assert.equal(r.reconciled, 0);
451
+ });
452
+
453
+ // --- task 1366: session-cost reconcile piggybacked on the same sweep --------
454
+
455
+ test('1366 runCostSweep calls db.reconcileSessionCosts and passes its counts through', async () => {
456
+ const calls = [];
457
+ const deps = {
458
+ db: { reconcileSessionCosts: async () => { calls.push('called'); return { scanned: 9, reconciled: 4, totalUsd: 12.5, unknownModels: [] }; } },
459
+ log: () => {},
460
+ error: () => {},
461
+ };
462
+ const r = await reconciler.runCostSweep(deps);
463
+ assert.equal(calls.length, 1, 'reconcileSessionCosts is invoked once');
464
+ assert.equal(r.reconciled, 4);
465
+ assert.equal(r.scanned, 9);
466
+ });
467
+
468
+ test('1366 runCostSweep swallows a reconcile error → skipped:error, never throws', async () => {
469
+ const errors = [];
470
+ const deps = {
471
+ db: { reconcileSessionCosts: async () => { throw new Error('pool down'); } },
472
+ log: () => {},
473
+ error: (m) => errors.push(m),
474
+ };
475
+ const r = await reconciler.runCostSweep(deps);
476
+ assert.equal(r.skipped, 'error', 'a reconcile failure is reported, not thrown');
477
+ assert.equal(errors.length, 1, 'the failure is logged to error');
478
+ });
479
+
480
+ test('1366 cost sweep is independent of the push credential (runs even when unconfigured)', async () => {
481
+ // The confirmed→shipped sweep no-ops without a push credential; the cost sweep
482
+ // is pure DB, so it must NOT inherit that gate. Proven by calling runCostSweep
483
+ // with a deps bundle that carries no githubPush at all.
484
+ let called = false;
485
+ const deps = { db: { reconcileSessionCosts: async () => { called = true; return { scanned: 1, reconciled: 1, totalUsd: 1, unknownModels: [] }; } }, log: () => {}, error: () => {} };
486
+ const r = await reconciler.runCostSweep(deps);
487
+ assert.equal(called, true, 'cost reconcile runs without any push-credential check');
488
+ assert.equal(r.reconciled, 1);
489
+ });
490
+
491
+ test('1366 runCostSweep on a db without the method → skipped:unsupported (older deps bundle)', async () => {
492
+ const r = await reconciler.runCostSweep({ db: {}, log: () => {}, error: () => {} });
493
+ assert.equal(r.skipped, 'unsupported');
494
+ });
495
+
496
+ // --- task 1385: server-side conflict auto-resolve wiring ---
497
+
498
+ test('1385 PR conflicts on generated/index files only → server-resolves it (resolvedConflicts=1, not shipped this sweep)', async () => {
499
+ const deps = mkDeps({
500
+ rows: [{ task_id: 300, builder_id: 4, worktree_name: 'wt-300' }],
501
+ mergeByBranch: { 'claude/wt-300': { merged: false, merged_now: false, number: 300, reason: 'merge_conflict' } },
502
+ conflictResolveImpl: async ({ branch }) => ({ resolved: true, head_sha: 'newsha', branch }),
503
+ });
504
+ const r = await reconciler.runSweep(deps);
505
+ assert.equal(r.resolvedConflicts, 1, 'the conflict was server-resolved');
506
+ assert.equal(r.reconciled, 0, 'it does NOT ship this sweep — checks re-run on the new head, lands next sweep');
507
+ assert.equal(deps._calls.ship.length, 0);
508
+ });
509
+
510
+ test('1385 hand-written conflict → left for a human (resolvedConflicts=0, no error)', async () => {
511
+ const deps = mkDeps({
512
+ rows: [{ task_id: 301, builder_id: 4, worktree_name: 'wt-301' }],
513
+ mergeByBranch: { 'claude/wt-301': { merged: false, merged_now: false, number: 301, reason: 'merge_conflict' } },
514
+ conflictResolveImpl: async () => ({ resolved: false, skipped: 'unresolvable_conflict', conflicted: ['src/bongos/db.js'] }),
515
+ });
516
+ const r = await reconciler.runSweep(deps);
517
+ assert.equal(r.resolvedConflicts, 0);
518
+ assert.equal(r.errors, 0, 'an unresolvable conflict is a clean no-op, not an error');
519
+ });
520
+
521
+ test('1385 only merge_conflict triggers the resolver (a failing_check does NOT)', async () => {
522
+ const seen = [];
523
+ const deps = mkDeps({
524
+ rows: [{ task_id: 302, builder_id: 4, worktree_name: 'wt-302' }],
525
+ mergeByBranch: { 'claude/wt-302': { merged: false, merged_now: false, number: 302, reason: 'failing_check:unit' } },
526
+ conflictResolveImpl: async ({ branch }) => { seen.push(branch); return { resolved: true }; },
527
+ });
528
+ const r = await reconciler.runSweep(deps);
529
+ assert.equal(seen.length, 0, 'the resolver is only called on a true merge conflict');
530
+ assert.equal(r.resolvedConflicts, 0);
531
+ });
532
+
533
+ test('1385 a resolver that throws is swallowed (best-effort) → sweep continues, counted as error-logged not crash', async () => {
534
+ const deps = mkDeps({
535
+ rows: [{ task_id: 303, builder_id: 4, worktree_name: 'wt-303' }],
536
+ mergeByBranch: { 'claude/wt-303': { merged: false, merged_now: false, number: 303, reason: 'merge_conflict' } },
537
+ conflictResolveImpl: async () => { throw new Error('temp clone disk full'); },
538
+ });
539
+ const r = await reconciler.runSweep(deps);
540
+ assert.equal(r.resolvedConflicts, 0);
541
+ assert.ok(deps._calls.errors.some((m) => /conflict-resolve/.test(m)), 'the failure is logged, not thrown');
542
+ });
543
+
544
+ // task 1546 / blocker 47 — observability for unprovable strands. A confirmed task
545
+ // the sweep can't prove landed (no branch + no published tip, or land-not-proven)
546
+ // used to be a silent `continue`. The sweep now counts it (unprovable) and, when it
547
+ // is older than STALE_CONFIRMED_MS, WARN-logs it (staleStrands) so a credited-but-
548
+ // unlanded task surfaces in minutes, not the 66h the blocker-47 strands sat.
549
+ test('1546 old confirmed task with no branch + no published tip → counted unprovable + WARN-logged as a strand', async () => {
550
+ const old = new Date(Date.now() - 66 * 3_600_000).toISOString(); // 66h ago (blocker 47's oldest)
551
+ const deps = mkDeps({
552
+ rows: [{ task_id: 263, builder_id: 94, worktree_name: null, head_sha: null, published_head_sha: null, confirmed_at: old }],
553
+ });
554
+ const r = await reconciler.runSweep(deps);
555
+ assert.equal(r.reconciled, 0, 'nothing landed → not shipped');
556
+ assert.equal(r.unprovable, 1);
557
+ assert.equal(r.staleStrands, 1);
558
+ assert.ok(
559
+ deps._calls.errors.some((m) => /STRAND task 263/.test(m) && /no_branch_no_tip/.test(m)),
560
+ 'a >30min unprovable confirmed task is WARN-logged with its reason'
561
+ );
562
+ });
563
+
564
+ test('1546 a FRESH unprovable confirmed task is counted but NOT yet WARN-logged', async () => {
565
+ const fresh = new Date(Date.now() - 60_000).toISOString(); // 1 min ago
566
+ const deps = mkDeps({
567
+ rows: [{ task_id: 999, builder_id: 1, worktree_name: null, head_sha: null, published_head_sha: null, confirmed_at: fresh }],
568
+ });
569
+ const r = await reconciler.runSweep(deps);
570
+ assert.equal(r.unprovable, 1);
571
+ assert.equal(r.staleStrands, 0, 'within the grace window → no strand WARN yet');
572
+ assert.equal(deps._calls.errors.length, 0);
573
+ });
574
+
575
+ // --- task 1915: speculative regen-heal for the clean-merge-but-stale strand ------
576
+
577
+ // mergeIfGreen shape for a PR GitHub reports MERGEABLE (no conflict) but with a RED
578
+ // check — the shape whose commonest cause is a stale generated index.
579
+ const mergeableRed = (reason, number = 900) => ({
580
+ pr_state: 'open', number, merged: false, merged_now: false, mergeable: 'MERGEABLE', reason,
581
+ });
582
+
583
+ test('1915 couldBeStaleGenerated: MERGEABLE + failing_check / non_required_check_failing → true; other shapes → false', () => {
584
+ const p = reconciler.couldBeStaleGenerated;
585
+ assert.equal(p(mergeableRed('failing_check:unit')), true);
586
+ assert.equal(p(mergeableRed('non_required_check_failing:e2e')), true);
587
+ // a CONFLICTING PR is the resolveBranchConflicts path, never this one
588
+ assert.equal(p({ pr_state: 'open', mergeable: 'CONFLICTING', reason: 'merge_conflict' }), false);
589
+ // pending / computing / review-gated → leave it to settle, not a failure
590
+ assert.equal(p(mergeableRed('mergeability_computing')), false);
591
+ assert.equal(p(mergeableRed('branch_behind_base')), false);
592
+ assert.equal(p(mergeableRed('review_required')), false);
593
+ assert.equal(p({ ...mergeableRed('failing_check:unit'), merged: true }), false);
594
+ assert.equal(p({ ...mergeableRed('failing_check:unit'), pr_state: 'closed' }), false);
595
+ assert.equal(p(null), false);
596
+ });
597
+
598
+ test('1915 mergeable-but-red PR → regen-heal fires on the right branch; refreshedStale=1, NOT shipped this sweep', async () => {
599
+ const healedBranches = [];
600
+ const deps = mkDeps({
601
+ rows: [{ task_id: 400, builder_id: 5, worktree_name: 'wt-stale' }],
602
+ statusByBranch: { 'claude/wt-stale': PENDING }, // still open + pending after the push
603
+ mergeByBranch: { 'claude/wt-stale': mergeableRed('failing_check:unit', 616) },
604
+ refreshStaleImpl: async ({ branch }) => { healedBranches.push(branch); return { refreshed: true, head_sha: 'healed', branch }; },
605
+ });
606
+ const r = await reconciler.runSweep(deps);
607
+ assert.equal(r.refreshedStale, 1, 'the stale-generated PR was regen-healed');
608
+ assert.deepEqual(healedBranches, ['claude/wt-stale'], 'the heal is invoked on exactly this task\'s branch');
609
+ assert.equal(r.reconciled, 0, 'no ship this sweep — checks re-run on the new head, lands next sweep');
610
+ assert.equal(deps._calls.ship.length, 0, 'the heal never ships (no phantom-ship — land still needs the tip proof)');
611
+ });
612
+
613
+ test('1915 mergeable-but-red PR where regen yields NO diff → not healed, logged as a real check failure', async () => {
614
+ const deps = mkDeps({
615
+ rows: [{ task_id: 401, builder_id: 5, worktree_name: 'wt-realfail' }],
616
+ statusByBranch: { 'claude/wt-realfail': PENDING },
617
+ mergeByBranch: { 'claude/wt-realfail': mergeableRed('failing_check:unit') },
618
+ refreshStaleImpl: async () => ({ refreshed: false, skipped: 'no_regen_diff' }),
619
+ });
620
+ const r = await reconciler.runSweep(deps);
621
+ assert.equal(r.refreshedStale, 0);
622
+ assert.equal(r.reconciled, 0);
623
+ assert.ok(
624
+ deps._calls.logs.some((m) => /regeneration produced no diff/.test(m) && /real check failure/.test(m)),
625
+ 'a real (non-staleness) check failure is logged, not silently retried forever'
626
+ );
627
+ });
628
+
629
+ test('1915 a merge_conflict PR does NOT trigger the regen-heal (it routes to resolveBranchConflicts)', async () => {
630
+ const deps = mkDeps({
631
+ rows: [{ task_id: 402, builder_id: 5, worktree_name: 'wt-conf' }],
632
+ mergeByBranch: { 'claude/wt-conf': { merged: false, merged_now: false, number: 402, mergeable: 'CONFLICTING', reason: 'merge_conflict' } },
633
+ conflictResolveImpl: async () => ({ resolved: true, head_sha: 'x' }),
634
+ });
635
+ const r = await reconciler.runSweep(deps);
636
+ assert.equal(deps._calls.refresh.length, 0, 'refreshStaleGenerated is not called for a true merge conflict');
637
+ assert.equal(r.resolvedConflicts, 1, 'the conflict path still runs');
638
+ });
639
+
640
+ test('1915 a regen-heal that throws is swallowed (best-effort) → logged, sweep continues, refreshedStale=0', async () => {
641
+ const deps = mkDeps({
642
+ rows: [{ task_id: 403, builder_id: 5, worktree_name: 'wt-boom' }],
643
+ statusByBranch: { 'claude/wt-boom': PENDING },
644
+ mergeByBranch: { 'claude/wt-boom': mergeableRed('non_required_check_failing:e2e') },
645
+ refreshStaleImpl: async () => { throw new Error('temp clone disk full'); },
646
+ });
647
+ const r = await reconciler.runSweep(deps);
648
+ assert.equal(r.refreshedStale, 0);
649
+ assert.ok(deps._calls.errors.some((m) => /regen-heal/.test(m)), 'the failure is logged, not thrown');
650
+ });
651
+
652
+ test('1915 regen-heal is capped per branch (MAX 3 attempts) so a treadmill cannot loop forever', async () => {
653
+ const healAttempts = new Map();
654
+ let attempted = 0;
655
+ const mk = () => mkDeps({
656
+ rows: [{ task_id: 404, builder_id: 5, worktree_name: 'wt-tread' }],
657
+ statusByBranch: { 'claude/wt-tread': PENDING },
658
+ mergeByBranch: { 'claude/wt-tread': mergeableRed('failing_check:unit') },
659
+ // stays red every sweep → a would-be treadmill; count each real invocation.
660
+ refreshStaleImpl: async () => { attempted++; return { refreshed: false, skipped: 'no_regen_diff' }; },
661
+ healAttempts,
662
+ });
663
+ for (let i = 0; i < 4; i++) {
664
+ const deps = mk();
665
+ await reconciler.runSweep(deps);
666
+ if (i === 3) {
667
+ assert.ok(deps._calls.logs.some((m) => /capped/.test(m)), 'the 4th sweep is capped, and logs it for owner visibility');
668
+ }
669
+ }
670
+ assert.equal(attempted, 3, 'exactly MAX_STALE_HEAL_ATTEMPTS (3) heals were attempted before the cap');
671
+ });
672
+
673
+ test('1915 a TRANSIENT heal skip (clone/fetch/push miss) does NOT burn a cap slot — retried indefinitely', async () => {
674
+ const healAttempts = new Map();
675
+ let calls = 0;
676
+ const mk = () => mkDeps({
677
+ rows: [{ task_id: 406, builder_id: 5, worktree_name: 'wt-flaky' }],
678
+ statusByBranch: { 'claude/wt-flaky': PENDING },
679
+ mergeByBranch: { 'claude/wt-flaky': mergeableRed('failing_check:unit') },
680
+ // an infra miss every sweep — must NOT count toward the cap (only tree-level
681
+ // determinations — refreshed / no_regen_diff — do).
682
+ refreshStaleImpl: async () => { calls++; return { refreshed: false, skipped: 'clone_failed' }; },
683
+ healAttempts,
684
+ });
685
+ for (let i = 0; i < 5; i++) await reconciler.runSweep(mk());
686
+ assert.equal(calls, 5, 'a transient skip is retried on every sweep, never capped');
687
+ assert.equal(healAttempts.get('claude/wt-flaky') || 0, 0, 'no cap slot is burned by an environmental miss');
688
+ });
689
+
690
+ test('1915 the treadmill guard prunes branches that leave the confirmed set (no Map leak)', async () => {
691
+ const healAttempts = new Map();
692
+ // Sweep A: branch X is confirmed + red + healed → its attempt is recorded.
693
+ await reconciler.runSweep(mkDeps({
694
+ rows: [{ task_id: 407, builder_id: 5, worktree_name: 'gone-soon' }],
695
+ statusByBranch: { 'claude/gone-soon': PENDING },
696
+ mergeByBranch: { 'claude/gone-soon': mergeableRed('failing_check:unit') },
697
+ refreshStaleImpl: async () => ({ refreshed: false, skipped: 'no_regen_diff' }),
698
+ healAttempts,
699
+ }));
700
+ assert.equal(healAttempts.get('claude/gone-soon'), 1, 'the attempt was recorded');
701
+ // Sweep B: a DIFFERENT branch is confirmed; X has landed/left the set → pruned.
702
+ await reconciler.runSweep(mkDeps({
703
+ rows: [{ task_id: 408, builder_id: 5, worktree_name: 'still-here' }],
704
+ statusByBranch: { 'claude/still-here': PENDING },
705
+ mergeByBranch: { 'claude/still-here': mergeableRed('failing_check:unit') },
706
+ refreshStaleImpl: async () => ({ refreshed: false, skipped: 'no_regen_diff' }),
707
+ healAttempts,
708
+ }));
709
+ assert.equal(healAttempts.has('claude/gone-soon'), false, 'a branch no longer confirmed is dropped from the guard');
710
+ assert.equal(healAttempts.get('claude/still-here'), 1, 'a still-confirmed branch keeps its count');
711
+ });
712
+
713
+ test('1915 the heal path never runs when the module lacks refreshStaleGenerated (older deps bundle)', async () => {
714
+ const deps = mkDeps({
715
+ rows: [{ task_id: 405, builder_id: 5, worktree_name: 'wt-old' }],
716
+ statusByBranch: { 'claude/wt-old': PENDING },
717
+ mergeByBranch: { 'claude/wt-old': mergeableRed('failing_check:unit') },
718
+ });
719
+ delete deps.conflictResolve.refreshStaleGenerated; // simulate a pre-1915 resolver
720
+ const r = await reconciler.runSweep(deps);
721
+ assert.equal(r.refreshedStale, 0, 'a missing heal fn is a clean no-op, not a crash');
722
+ });
723
+
724
+ // Drain the microtask queue, then report + exit with the right code.
725
+ setTimeout(() => {
726
+ console.log(`\npublish reconciler (task 1134 + 1915) tests: ${passed} passed, ${failed} failed`);
727
+ process.exit(failed > 0 ? 1 : 0);
728
+ }, 100);