@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,911 @@
1
+ // src/bongos/db.js — the GDS core db RESIDUE after the lifecycle carve (BV1.R86 /
2
+ // ADR 0093 §3). The build state machine (tasks·claims·versions·done-when·ship)
3
+ // graduated to modules/lifecycle/db.js; what remains here is the non-lifecycle
4
+ // residue the kernel + core read routes still own:
5
+ // • builder IDENTITY + admission (upsertBuilder, seatFirstAdminIfUnclaimed,
6
+ // getBuilderByGithubId, hasInvitedAccessRequest, linkAnthropicAccount,
7
+ // updateBuilderDisciplines) — auth.js imports these; they CANNOT live in a
8
+ // module (auth.js is kernel and may not require a module).
9
+ // • RANK + status MANAGEMENT (setBuilderRank/_applyRankChangeTx/RANKS,
10
+ // getLatestRankChangeForBuilder, deactivate/reactivateBuilder) — Archon-driven
11
+ // identity ops consumed by routes/builders.js, NOT the task lifecycle.
12
+ // • AUTH sessions (builder_sessions: createSession/lookupSession/revoke*/
13
+ // hasCliSession/SESSION_TTL_MS) — the token store auth.js drives.
14
+ // • TWIN / social reads (Discord link flow, karma feed, audit-log read, the
15
+ // grade-trend builderRollingAvgGrade the sessions BFG also consumes) + the
16
+ // security_docs store (the kernel security-PROPERTY plane, routes/security.js).
17
+ // • The art-pipeline Gemini-key leak (api.getBuilderGeminiKeyRow/…).
18
+ // db-kernel.js (identity/audit/rank/withTx) stays the bounded kernel slice this
19
+ // re-exports through, exactly as before (ADR 0091 §2). Pure SQL plumbing;
20
+ // routing/auth lives elsewhere.
21
+ //
22
+ // sealSessionLog + _applyRankChangeTx (+ RANKS / singleRungPromotionError) + the
23
+ // gradePassCount fragment are DELIBERATELY duplicated with modules/lifecycle/db.js
24
+ // (ADR 0091 §2 boundary-forced duplication): the same close-row / rank-change /
25
+ // grade-count SQL runs on both sides of the kernel↔module line — keep in sync.
26
+
27
+ const { pool } = require('./pool');
28
+ // Module seam (ADR 0083 / BV1.R43). The rank/status-change paths EMIT
29
+ // `builder.box-reconcile-needed` AFTER COMMIT (best-effort) so the dev-box module
30
+ // can reconcile a droplet a demotion/graduation implies — never a direct require
31
+ // of the module.
32
+ const seams = require('../module-seams');
33
+
34
+ // Kernel db slice (BV1.R69 / ADR 0091 §2): builder IDENTITY (getBuilderById),
35
+ // the AUDIT log (insertAuditLog), the RANK ladder (LIVE_RANK_LADDER), and the
36
+ // transaction primitive (withTx) live in the bounded ./db-kernel slice the
37
+ // published doorway resolves through. Re-exported below so every caller is
38
+ // byte-identical; db-kernel depends only on ./pool, never ./db (one-way).
39
+ const {
40
+ withTx, getBuilderById, listActiveBuilders, insertAuditLog, LIVE_RANK_LADDER,
41
+ // Auth/identity/admission + the rank vocabulary carved to db-kernel (ADR 0102,
42
+ // finishing ADR 0091 §1). Re-exported below so db.js's other importers + its own
43
+ // internal uses (setBuilderRank's RANKS.indexOf, etc.) stay byte-identical.
44
+ RANKS, SESSION_TTL_MS, upsertBuilder, seatFirstAdminIfUnclaimed,
45
+ getBuilderByGithubId, hasInvitedAccessRequest, createSession, lookupSession,
46
+ } = require('./db-kernel');
47
+
48
+ // gradePassCount removed with builderRollingAvgGrade (its only core user) — that
49
+ // grade-TREND read carved to modules/grading/db.js (ADR 0102), with this one-line
50
+ // fragment inlined there. The modules/lifecycle/db.js twin of it is unaffected.
51
+
52
+ // The shared `bounds`/`days` DAY_SERIES_CTE for the costSummary day-series
53
+ // queries moved with costSummary into modules/economy/cost.js (BV1.R77 / ADR
54
+ // 0093 §§1-2) — its only two callers left the monolith.
55
+
56
+ // Seal a session_logs row inside an open transaction (ended_at is NOT NULL in
57
+ // the schema, so a "sealed" log = the closing row). `outcome` stays a PARAMETER
58
+ // — resolveClaim passes a variable ('shipped'/'partial'/'abandoned'), the two
59
+ // release paths pass the literal 'abandoned' (audit §2B db-tx).
60
+
61
+ async function sealSessionLog(client, { builderId, taskId, claimId, startedAt, outcome, notesMd }) {
62
+ await client.query(
63
+ `INSERT INTO session_logs (builder_id, task_id, claim_id, started_at, ended_at, outcome, notes_md)
64
+ VALUES ($1, $2, $3, $4, now(), $5, $6)`,
65
+ [builderId, taskId, claimId, startedAt, outcome, notesMd]
66
+ );
67
+ }
68
+
69
+ // The builder on the most-recent claim for a task (the worker who did the
70
+ // work). Returns null when the task has no claim on record at all — each caller
71
+ // supplies its OWN fallback (confirmer / requester / grade-caller) at the call
72
+ // site, so that per-site drift is preserved (audit §2B db-deep, #538/#661).
73
+
74
+ // upsertBuilder — carved to ./db-kernel (ADR 0102). Imported + re-exported above.
75
+
76
+ // First-admin bootstrap (R62 / task 1201, ADR 0062). Replaces migration 023's
77
+ // hard-coded founding-Archon literal: a fresh install seats its CONFIGURED
78
+ // firstAdmin login as Archon, in code, at that account's first enrollment. The
79
+ // guard is atomic and conservative — it elevates the row ONLY while NO Archon
80
+ // exists yet, so it can never be used to escalate later (once an owner exists,
81
+ // every call is a no-op) and it is race-safe under concurrent enrollment. Login
82
+ // match is case-insensitive. Returns true iff this call seated the Archon.
83
+
84
+ // seatFirstAdminIfUnclaimed — carved to ./db-kernel (ADR 0102). Re-exported above.
85
+
86
+ // getBuilderById — the canonical builder-identity read — moved to ./db-kernel
87
+ // (BV1.R69 / ADR 0091 §2: identity is a kernel primitive). Imported +
88
+ // re-exported at the top of this file, so all callers are unchanged.
89
+
90
+ // V3.R10 (#235), criterion C3: store the Anthropic account a builder attested to
91
+ // during /builder-setup. `email` is what the builder confirmed; `userId` is the
92
+ // accountUuid Claude Code reported from ~/.claude.json oauthAccount. It is kept
93
+ // as optional cosmetic attribution only — NOT an auth boundary; the
94
+ // X-Anthropic-User identity pin was removed (task 1039 / idea 258).
95
+ // Idempotent: re-linking (e.g. re-running setup, or a builder switching machines)
96
+ // just overwrites the stored pair. Returns the updated identity columns.
97
+
98
+ async function linkAnthropicAccount(builderId, { email, userId }) {
99
+ const { rows } = await pool.query(
100
+ `UPDATE builders
101
+ SET anthropic_email = $2, anthropic_user_id = $3
102
+ WHERE id = $1
103
+ RETURNING id, anthropic_email, anthropic_user_id`,
104
+ [builderId, email ?? null, userId ?? null]
105
+ );
106
+ return rows[0] ?? null;
107
+ }
108
+
109
+ // getBuilderCostStatus() + autonomousApiSpendMtd() carved into
110
+ // modules/economy/cost.js (BV1.R77 / ADR 0093 §1-2). Core resolves them via the
111
+ // `reward` kernel port (me.js cost status; autonomy-gate.js reads them as a CLI).
112
+
113
+ // recordAutonomyRun() + lastAutonomyHead() (the autonomy_runs slice) carved into
114
+ // modules/autonomy/db.js (BV1.R83 / ADR 0093 §1). The MAS autonomy gate
115
+ // (scripts/gds/autonomy-gate.js, a CLI) reads them directly from the module; core
116
+ // never calls them. The autonomy_runs TABLE (migration 126) stays in core
117
+ // migrations/ (the shared-schema additive rule).
118
+
119
+ // setBuilderMonthlyBudget() carved into modules/economy/cost.js (BV1.R77 / ADR
120
+ // 0093 §1-2). routes/builders.js resolves it via the `reward` kernel port.
121
+
122
+ // setBuilderBoxBlocked + its box_blocked UPDATE RELOCATED to modules/dev-box/db.js
123
+ // (BV1.R68 / ADR 0091 §3): box-blocked is cleanly dev-box-owned — the module is
124
+ // its only writer AND reader (core never reads box_blocked) — so the query left
125
+ // the core monolith with the doorway re-export when the slice pattern landed.
126
+
127
+ // Approval-gated entry (2026-05-30). The web hall sign-in no longer auto-creates
128
+ // an account for any GitHub user — a first-time visitor must be approved first
129
+ // (an Archon marks their access_request 'invited'). These three small lookups
130
+ // back that gate (used in auth.js completeWebFlow and the access-request form).
131
+
132
+ // Does a builder row already exist for this stable GitHub numeric id? Returns a
133
+ // minimal row or null. github_id is the stable key (login can change).
134
+
135
+ // getBuilderByGithubId — carved to ./db-kernel (ADR 0102). Re-exported above.
136
+
137
+ // Has an Archon approved this login (an access_requests row at status='invited',
138
+ // case-insensitive)? This is the approval signal that lets a first-time web
139
+ // sign-in through — and that the form uses to say "you're already approved".
140
+
141
+ // hasInvitedAccessRequest — carved to ./db-kernel (ADR 0102). Re-exported above.
142
+
143
+ // Replace a builder's preferred_disciplines (migrations 027 + 086). Input is
144
+ // deduped, order-normalized, and validated against the disciplines THIS INSTANCE
145
+ // offers — core (engineer, ideator) plus any enabled feature module's disciplines
146
+ // (the art-pipeline module adds 'artist'), resolved via src/modules.js (R59 /
147
+ // task 1198). The DB CHECK still enforces the full known enum
148
+ // (engineer|artist|ideator) as a backstop; this is the instance-aware
149
+ // friendly-error layer, so a vanilla instance with the art pipeline off rejects
150
+ // 'artist' instead of silently storing an unofferable discipline. Returns the
151
+ // updated builder row, or throws { code: 'invalid_discipline', bad } if any
152
+ // element is not offered by this instance.
153
+
154
+ async function updateBuilderDisciplines(builderId, disciplines) {
155
+ const { enabledDisciplines } = require('../modules');
156
+ const offered = enabledDisciplines();
157
+ const list = Array.isArray(disciplines) ? disciplines : [];
158
+ const bad = list.filter((d) => !offered.includes(d));
159
+ if (bad.length) {
160
+ const err = new Error(`invalid discipline(s): ${bad.join(', ')}`);
161
+ err.code = 'invalid_discipline';
162
+ err.bad = bad;
163
+ throw err;
164
+ }
165
+ const normalized = offered.filter((d) => list.includes(d));
166
+ const { rows } = await pool.query(
167
+ `UPDATE builders
168
+ SET preferred_disciplines = $2
169
+ WHERE id = $1
170
+ RETURNING id, github_id, github_login, display_name, avatar_url, total_credits, karma, created_at, rank, preferred_disciplines`,
171
+ [builderId, normalized]
172
+ );
173
+ return rows[0] ?? null;
174
+ }
175
+
176
+ // The builder-PREFS db slice — the five per-builder preference jsonb columns on
177
+ // `builders` (skill_model_prefs / sound_prefs / behavior_prefs / event_sound_prefs)
178
+ // — was carved into modules/builder-settings/db.js (BV1.R80 / ADR 0093 §1). Core
179
+ // no longer reads/writes them: the `/me/*-prefs` routes moved to the module, and
180
+ // the `GET /me` aggregator resolves the `builder-settings` kernel port for the
181
+ // wandering/render/needs slices instead of importing those helpers directly.
182
+
183
+ // ---- per-builder Gemini key, encrypted at rest (migration 122 / task 1013) ----
184
+ //
185
+ // The plaintext key NEVER touches the DB — the caller encrypts it with
186
+ // src/bongos/secret-box.js (master key in server env only) and passes the opaque
187
+ // blob + the last-4 chars for masked display. These three helpers are the only
188
+ // readers/writers of the gemini_key_* columns.
189
+
190
+ // Set/replace the builder's own key. `enc` is the secret-box blob; `last4` is the
191
+ // plaintext's last 4 chars (for "…ABCD" display — not a secret). Returns the
192
+ // masked metadata, never the blob.
193
+
194
+ // setBuilderGeminiKey / clearBuilderGeminiKey / getBuilderGeminiKeyRow RELOCATED to
195
+ // modules/art-pipeline/db.js (ADR 0102) — the art module owns the gemini_key_*
196
+ // credential store + registers the 'art.getBuilderGeminiKeyRow' port; core me.js
197
+ // resolves that port (degrades to a no-key shape on a vanilla instance).
198
+
199
+ // Remove the builder's own key (back to "not set"). Returns { set: false }.
200
+
201
+
202
+ // Read the raw row for the builder's own key: { enc, last4, set_at }. `enc` is the
203
+ // still-encrypted blob — the caller decrypts with secret-box when it needs the
204
+ // plaintext (only the own-scoped /me/art-key delivery does). Returns
205
+ // { enc: null, ... } when no key is set.
206
+
207
+
208
+ // leaderboard() carved into modules/economy/credits.js (BV1.R77 / ADR 0093 §1-2).
209
+ // Core read routes resolve it via the `reward` kernel port.
210
+
211
+ // The full reserved rank ladder (matches the CHECK enum in migration 023).
212
+ // LIVE in V3: 'archon' (top), 'metic' (Archon-approved working rank — full
213
+ // claim/ship + triage/blocker/planning/priority; task #360 / ADR 0018),
214
+ // 'thetes' (the GRADUATED-newcomer rank — added in #692 / ADR 0034: claims the
215
+ // whole general queue but NO scope-shaping/trust powers; a Xenos auto-graduates
216
+ // here after THETES_GRADUATION_THRESHOLD successfully SHIPPED tasks), and 'xenos' (the
217
+ // sandboxed entry rank new builders default to since migration 029 — claims
218
+ // ONLY newcomer_friendly tasks). The rest stay reserved so future ranks never
219
+ // need a schema change. The DB CHECK is the backstop — this set lets the API
220
+ // give a clean 400 instead of leaking a constraint-violation 500.
221
+ //
222
+ // ORDER IS LOAD-BEARING: setBuilderRank uses RANKS.indexOf to decide
223
+ // promotion-vs-demotion (lower index = higher rank). So the live ladder must
224
+ // read archon > metic > thetes > xenos — thetes sits BETWEEN metic and xenos.
225
+
226
+ // RANKS — carved to ./db-kernel (ADR 0102); imported + re-exported above. Order is
227
+ // load-bearing (setBuilderRank's RANKS.indexOf below) and stays TWINNED with
228
+ // modules/lifecycle/db.js.
229
+
230
+ // THETES auto-graduation (#692 / ADR 0034; trigger corrected in #704). A Xenos
231
+ // who has this many SUCCESSFULLY SHIPPED tasks (tasks.status='shipped',
232
+ // attributed via tasks.shipped_by) is promoted xenos→thetes the moment the Nth
233
+ // ship lands. The signal is SHIPPED, not confirmed — a task only counts once it
234
+ // is merged + deployed, per the Archon rule "after 3 tasks are successfully
235
+ // shipped." Pure decision helper is exported so tests/rank_gate.mjs can exercise
236
+ // the threshold without a DB.
237
+
238
+ function singleRungPromotionError(oldRank, newRank) {
239
+ const a = REQUIRES_RANK_TIER[oldRank];
240
+ const b = REQUIRES_RANK_TIER[newRank];
241
+ if (!a || !b) return null; // one side is off the live ladder — not our gate
242
+ if (b <= a) return null; // demotion or lateral — unconstrained here
243
+ if (b - a === 1) return null; // exactly one rung up — allowed
244
+ return {
245
+ code: 'MULTI_RUNG_PROMOTION',
246
+ from: oldRank,
247
+ to: newRank,
248
+ next_rung: LIVE_RANK_LADDER[a], // rank at tier a+1 (ladder is 0-based)
249
+ };
250
+ }
251
+
252
+ // disambiguateWorktreeName — V3.R51 (#270). Two simultaneously-ACTIVE claims
253
+ // must never share a worktree_name: `.claude/worktrees/<name>` is a filesystem
254
+ // path, and two live builders pointing at the same one would stomp each other.
255
+ // This is NOT a refusal (unlike ALREADY_CLAIMED / TOUCHES_CONFLICT) — we
256
+ // silently append a numeric suffix and let the claim succeed, returning the
257
+ // disambiguated name so the caller knows what they actually got.
258
+ //
259
+ // `taken` is the set of worktree_names held by currently-ACTIVE claims only
260
+ // (released_at IS NULL). A name freed by a resolved/shipped claim is freely
261
+ // reusable WITHOUT a suffix — this is load-bearing for the overnight builder,
262
+ // which reuses ONE worktree_name across sequential tasks (it ships, freeing the
263
+ // claim, before claiming the next). Keying off historical claims would break it.
264
+ //
265
+ // Suffix scheme: "name" → "name-2" → "name-3" … (first collision becomes -2,
266
+ // matching git-worktree / file-manager conventions). A null/empty desired name
267
+ // has nothing to collide on, so it's returned unchanged. Pure + exported so
268
+ // tests can exercise it without a DB; claimTask calls it inside the txn.
269
+
270
+ async function _applyRankChangeTx(client, { builderId, newRank, actorBuilderId, reasonNote = null, enforceSingleRungPromotion = false }) {
271
+ const { rows } = await client.query(
272
+ `SELECT id, rank, status FROM builders WHERE id = $1 FOR UPDATE`,
273
+ [builderId]
274
+ );
275
+ const target = rows[0];
276
+ if (!target) throw { code: 'BUILDER_NOT_FOUND' };
277
+ const oldRank = target.rank;
278
+ if (oldRank === newRank) throw { code: 'RANK_UNCHANGED', rank: oldRank };
279
+
280
+ // #707 — manual promotions advance ONE live rung at a time. Checked here
281
+ // (atomic, under the FOR UPDATE lock) but only when the caller opts in; the
282
+ // automatic xenos→thetes graduation (always +1) does not.
283
+ if (enforceSingleRungPromotion) {
284
+ const rungErr = singleRungPromotionError(oldRank, newRank);
285
+ if (rungErr) throw rungErr;
286
+ }
287
+
288
+ const { rows: updated } = await client.query(
289
+ `UPDATE builders SET rank = $2 WHERE id = $1
290
+ RETURNING id, github_id, github_login, display_name, avatar_url, total_credits, created_at, rank`,
291
+ [builderId, newRank]
292
+ );
293
+
294
+ // V3.R28 / #249 — ceremony delta. Promotion (moving UP the ladder = lower
295
+ // index in RANKS) earns +5; demotion is audit-only (0).
296
+ const oldIdx = RANKS.indexOf(oldRank);
297
+ const newIdx = RANKS.indexOf(newRank);
298
+ const isPromotion = oldIdx !== -1 && newIdx !== -1 && newIdx < oldIdx;
299
+ const isDemotion = oldIdx !== -1 && newIdx !== -1 && newIdx > oldIdx;
300
+ const delta = isPromotion ? 5 : 0;
301
+ // reason is the join key for downstream pickup; the human-readable text stays
302
+ // in `description`. The "by builder#N" clause is load-bearing — the rank-change
303
+ // greeting parser (getLatestRankChangeForBuilder) matches on it — so an
304
+ // automatic promotion (#692) keeps it (actor = the builder themselves) and
305
+ // APPENDS the "auto-graduation: …" note rather than replacing it.
306
+ const description = reasonNote
307
+ ? `rank_change: ${oldRank}→${newRank} by builder#${actorBuilderId} (${reasonNote})`
308
+ : `rank_change: ${oldRank}→${newRank} by builder#${actorBuilderId}`;
309
+ await client.query(
310
+ `INSERT INTO credit_log (builder_id, task_id, delta, reason, description)
311
+ VALUES ($1, NULL, $2, 'rank_change', $3)`,
312
+ [builderId, delta, description]
313
+ );
314
+
315
+ // V3.R38 / #259 — DEMOTION hook for criterion C7 (rank-change-near-instant).
316
+ // Revoke every active session in the same transaction so the demoted builder's
317
+ // CLI tokens stop working on their next API call. Combined with requireBuilder
318
+ // re-reading rank from the DB per request (ADR 0016), this is belt-and-braces.
319
+ // Promotion never revokes — we don't log someone out for getting a raise.
320
+ let demotionRevoked = 0;
321
+ if (isDemotion) {
322
+ const { rowCount } = await client.query(
323
+ `UPDATE builder_sessions
324
+ SET revoked_at = now()
325
+ WHERE builder_id = $1 AND revoked_at IS NULL`,
326
+ [builderId]
327
+ );
328
+ demotionRevoked = rowCount;
329
+ }
330
+
331
+ return {
332
+ builder: updated[0],
333
+ previous_rank: oldRank,
334
+ status: target.status,
335
+ sessions_revoked: demotionRevoked,
336
+ direction: isPromotion ? 'promotion' : isDemotion ? 'demotion' : 'lateral',
337
+ credit_delta: delta,
338
+ };
339
+ }
340
+
341
+
342
+ async function setBuilderRank({ builderId, newRank, actorBuilderId }) {
343
+ const result = await withTx(async (client) => {
344
+ return _applyRankChangeTx(client, { builderId, newRank, actorBuilderId, enforceSingleRungPromotion: true });
345
+ });
346
+ // Source-access clawback (ADR 0031 §6 / #600). Post-commit, own connection,
347
+ // never throws — records the box reconcile this rank change implies (a demotion
348
+ // below the floor → deprovision; a graduation up → rescope). The CREDENTIAL
349
+ // layer is already cut off live on the next /box/source-access fetch; this
350
+ // just signals + audits the slower droplet-level reconcile.
351
+ await seams.emitAsync('builder.box-reconcile-needed', {
352
+ builderId, rank: newRank, status: result.status, actor: `rank-change:builder#${actorBuilderId}`,
353
+ });
354
+ return {
355
+ builder: result.builder,
356
+ previous_rank: result.previous_rank,
357
+ sessions_revoked: result.sessions_revoked,
358
+ direction: result.direction,
359
+ credit_delta: result.credit_delta,
360
+ };
361
+ }
362
+
363
+ // maybeAutoGraduateToThetes — #692 / ADR 0034 (trigger corrected #704). Call
364
+ // INSIDE the SHIP transaction (shipTask) AFTER the task flips to 'shipped',
365
+ // passing the task's attributed builder (tasks.shipped_by). If that builder is a
366
+ // Xenos who now has THETES_GRADUATION_THRESHOLD successfully SHIPPED tasks,
367
+ // promote them xenos→thetes atomically with the ship and return the rank-change
368
+ // result (so the caller fires the post-commit box reconcile). Returns null when
369
+ // no graduation happened. Idempotent: rank-guarded (only a current Xenos
370
+ // graduates) and counts SHIPPED tasks by attribution, so it fires exactly once
371
+ // per builder. The actor is the builder themselves — a system-driven promotion.
372
+
373
+ async function getLatestRankChangeForBuilder(builderId) {
374
+ // Match both schemas:
375
+ // post-R28: reason = 'rank_change'
376
+ // pre-R28: reason LIKE 'rank_change:%'
377
+ const { rows } = await pool.query(
378
+ `SELECT id, builder_id, delta, reason, description, recorded_at
379
+ FROM credit_log
380
+ WHERE builder_id = $1
381
+ AND (reason = 'rank_change' OR reason LIKE 'rank_change:%')
382
+ ORDER BY id DESC
383
+ LIMIT 1`,
384
+ [builderId]
385
+ );
386
+ const row = rows[0];
387
+ if (!row) return null;
388
+ // The "rank_change: <old>→<new> by builder#<actor>" string lives in
389
+ // `description` (post-R28) or `reason` (pre-R28).
390
+ const text = row.description || row.reason || '';
391
+ // Tolerant parser — fall back to nulls if anything's off.
392
+ const m = text.match(/rank_change:\s*([a-z]+)\s*→\s*([a-z]+)\s*by builder#(\d+)/i);
393
+ const oldRank = m ? m[1] : null;
394
+ const newRank = m ? m[2] : null;
395
+ const actorId = m ? Number(m[3]) : null;
396
+ // Direction by ladder index — same definition as setBuilderRank itself.
397
+ let direction = null;
398
+ if (oldRank && newRank) {
399
+ const oi = RANKS.indexOf(oldRank);
400
+ const ni = RANKS.indexOf(newRank);
401
+ if (oi !== -1 && ni !== -1) {
402
+ direction = ni < oi ? 'promotion' : ni > oi ? 'demotion' : 'lateral';
403
+ }
404
+ }
405
+ return {
406
+ id: row.id,
407
+ builder_id: row.builder_id,
408
+ old_rank: oldRank,
409
+ new_rank: newRank,
410
+ actor_builder_id: actorId,
411
+ delta: row.delta,
412
+ direction,
413
+ recorded_at: row.recorded_at,
414
+ };
415
+ }
416
+
417
+ // Graceful builder exit (V3.R88 #307). Deactivating a builder is reversible
418
+ // and lossless: drachmae (credits) + credit_log, shipped tasks, and historical
419
+ // session_logs all stay. What changes: status → inactive (blocks new claims via
420
+ // claimTask's guard), rank → 'xenos' (sandboxed tier), active claims released
421
+ // cleanly with a final 'abandoned' session_log sealing each, and the tasks
422
+ // returned to 'ready' for someone else. Reactivation flips status back; rank
423
+ // is NOT auto-restored (an Archon re-promotes deliberately via PATCH
424
+ // /builders/:id/rank). Memory archival is local-first and handled by the
425
+ // /builder-exit skill — the server never holds another builder's local memory
426
+ // (the server-side memory store is criterion #54's job, not this task's).
427
+
428
+ async function deactivateBuilder({ builderId, reason, actorBuilderId }) {
429
+ const { updated, activeClaims } = await withTx(async (client) => {
430
+ const { rows } = await client.query(
431
+ `SELECT id, rank, status FROM builders WHERE id = $1 FOR UPDATE`,
432
+ [builderId]
433
+ );
434
+ const target = rows[0];
435
+ if (!target) throw { code: 'BUILDER_NOT_FOUND' };
436
+ if (target.status === 'inactive') throw { code: 'ALREADY_INACTIVE' };
437
+
438
+ // Release every active claim, seal each with a final session_log, and
439
+ // return the task to 'ready' so the work isn't stranded.
440
+ const { rows: activeClaims } = await client.query(
441
+ `SELECT id AS claim_id, task_id, claimed_at FROM claims
442
+ WHERE builder_id = $1 AND released_at IS NULL FOR UPDATE`,
443
+ [builderId]
444
+ );
445
+ for (const c of activeClaims) {
446
+ await client.query(
447
+ `UPDATE claims SET released_at = now(), outcome = 'abandoned' WHERE id = $1`,
448
+ [c.claim_id]
449
+ );
450
+ // Only bounce the task back to 'ready' if it's still mid-flight.
451
+ await client.query(
452
+ `UPDATE tasks SET status = 'ready' WHERE id = $1 AND status = 'active'`,
453
+ [c.task_id]
454
+ );
455
+ // Seal an outstanding session_log (ended_at is NOT NULL in the schema,
456
+ // so "sealing" = writing the closing abandoned-on-exit row).
457
+ await sealSessionLog(client, {
458
+ builderId, taskId: c.task_id, claimId: c.claim_id, startedAt: c.claimed_at,
459
+ outcome: 'abandoned',
460
+ notesMd: `Claim released on builder exit (graceful deactivation by builder#${actorBuilderId}).`,
461
+ });
462
+ }
463
+
464
+ const { rows: updated } = await client.query(
465
+ `UPDATE builders
466
+ SET status = 'inactive', deactivated_at = now(),
467
+ deactivated_reason = $2, reactivated_at = NULL, rank = 'xenos'
468
+ WHERE id = $1
469
+ RETURNING id, github_id, github_login, display_name, avatar_url,
470
+ total_credits, created_at, rank, status,
471
+ deactivated_at, reactivated_at, deactivated_reason`,
472
+ [builderId, reason ?? null]
473
+ );
474
+ // Interim audit (→ audit_log when R36 lands). delta=0 = no-op for credits.
475
+ await client.query(
476
+ `INSERT INTO credit_log (builder_id, task_id, delta, reason)
477
+ VALUES ($1, NULL, 0, $2)`,
478
+ [builderId, `builder_exit: deactivated by builder#${actorBuilderId} (rank ${target.rank}→xenos)`]
479
+ );
480
+ // SECURITY (#871): revoke EVERY live session for the offboarded builder, in
481
+ // the same transaction. Before this, deactivateBuilder set status='inactive'
482
+ // + rank='xenos' via direct SQL (not setBuilderRank, which is the only path
483
+ // that revokes on demotion), so a deactivated/offboarded builder kept working
484
+ // CLI bearer tokens (which don't expire) and could still reach the API. This
485
+ // is the server-side teardown that pairs with the requireBuilder status gate;
486
+ // a genuine return requires re-auth (correct — they were offboarded).
487
+ await client.query(
488
+ `UPDATE builder_sessions SET revoked_at = now()
489
+ WHERE builder_id = $1 AND revoked_at IS NULL`,
490
+ [builderId]
491
+ );
492
+ return { updated, activeClaims };
493
+ });
494
+ // Source-access clawback (ADR 0031 §6 / #600): a deactivated builder loses
495
+ // their box → loses source. Post-commit, own connection, never throws. The
496
+ // builder is now status='inactive' (rank forced to xenos above), so the
497
+ // reconcile resolves to 'deprovision'. Their next /box/source-access fetch is
498
+ // already 403'd (inactive) — this signals the droplet teardown for `box.js
499
+ // reconcile` / the dormant sweep.
500
+ await seams.emitAsync('builder.box-reconcile-needed', {
501
+ builderId, rank: 'xenos', status: 'inactive', actor: `builder-exit:builder#${actorBuilderId}`,
502
+ });
503
+ return {
504
+ builder: updated[0],
505
+ claims_released: activeClaims.map((c) => c.task_id),
506
+ logs_sealed: activeClaims.length,
507
+ };
508
+ }
509
+
510
+
511
+ async function reactivateBuilder({ builderId, actorBuilderId }) {
512
+ return withTx(async (client) => {
513
+ const { rows } = await client.query(
514
+ `SELECT id, status FROM builders WHERE id = $1 FOR UPDATE`,
515
+ [builderId]
516
+ );
517
+ const target = rows[0];
518
+ if (!target) throw { code: 'BUILDER_NOT_FOUND' };
519
+ if (target.status !== 'inactive') throw { code: 'NOT_INACTIVE', status: target.status };
520
+
521
+ const { rows: updated } = await client.query(
522
+ `UPDATE builders
523
+ SET status = 'active', reactivated_at = now()
524
+ WHERE id = $1
525
+ RETURNING id, github_id, github_login, display_name, avatar_url,
526
+ total_credits, created_at, rank, status,
527
+ deactivated_at, reactivated_at, deactivated_reason`,
528
+ [builderId]
529
+ );
530
+ // Rank is intentionally left at whatever it is (xenos after a deactivation):
531
+ // an Archon re-promotes deliberately via PATCH /builders/:id/rank.
532
+ await client.query(
533
+ `INSERT INTO credit_log (builder_id, task_id, delta, reason)
534
+ VALUES ($1, NULL, 0, $2)`,
535
+ [builderId, `builder_exit: reactivated by builder#${actorBuilderId} (rank stays ${updated[0].rank})`]
536
+ );
537
+ return { builder: updated[0] };
538
+ });
539
+ }
540
+
541
+ // -------------------------------------------------------------------------
542
+ // Sessions (auth tokens)
543
+ // -------------------------------------------------------------------------
544
+ //
545
+ // V3.R38 / task #259 — short-lived sessions with refresh-on-use.
546
+ // V3.R90 / task #400 (2026-05-29) — TTL widened from 1h to 24h.
547
+ //
548
+ // * Every NEW session (CLI or web) defaults to a 24-hour TTL. The caller may
549
+ // still pass an explicit expiresAt to override (web flow uses 30 days for
550
+ // the cookie's max-age, but the SERVER-SIDE row still uses 24h + roll-on-use
551
+ // so a logged-out browser tab in someone's history can't be replayed weeks
552
+ // later).
553
+ // * Every successful lookupSession bumps BOTH last_used_at AND expires_at to
554
+ // NOW() + 24h. This is the "refresh-on-use" half: an actively-used session
555
+ // stays valid; an idle session expires after 24h. The bump is fire-and-
556
+ // forget — it's an optimization for the next request, not a precondition
557
+ // for THIS request, so we don't add request latency by awaiting it.
558
+ // * Migration 035 backfilled all pre-existing rows with a 24h grace runway
559
+ // so deploying the V3.R38 change didn't kick the supervisor / mid-flow
560
+ // builders. With the V3.R90 TTL = 24h, the refresh window matches that
561
+ // grace formula exactly — no further migration needed.
562
+ // * The 1h value originally backstopped C7 (rank-change-near-instant), but
563
+ // setBuilderRank already calls revokeAllSessionsForBuilder on every
564
+ // demotion (see below), so the TTL is no longer load-bearing for C7. Its
565
+ // remaining job is idle-session hygiene under C9 (security baseline).
566
+ // 24h still kills idle sessions overnight; an active builder no longer
567
+ // gets kicked out over lunch.
568
+
569
+ // Session TTL on refresh / creation, in milliseconds. Centralized so the
570
+ // migration's grace formula, the test suite, and the code agree on one number.
571
+
572
+ // SESSION_TTL_MS — carved to ./db-kernel (ADR 0102); imported + re-exported above.
573
+
574
+
575
+ // createSession — carved to ./db-kernel (ADR 0102). Re-exported above.
576
+
577
+ // Has this builder ever authenticated the GDS CLI? (#777) True once they've run
578
+ // /builder-setup (or the box-connect bootstrap) — both mint a source='cli'
579
+ // session via the device flow. Revoked/expired sessions still count (rows are
580
+ // marked, never deleted — see revokeAllSessionsForBuilder), so this is a durable
581
+ // "the CLI was signed in at least once" signal. Drives the onboarding checklist's
582
+ // "Run /builder-setup" step (auto-ticks; no manual mark) — purely a display
583
+ // signal, never gates graduation.
584
+
585
+ async function hasCliSession(builderId) {
586
+ if (!Number.isFinite(Number(builderId))) return false;
587
+ const { rows } = await pool.query(
588
+ `SELECT EXISTS (
589
+ SELECT 1 FROM builder_sessions WHERE builder_id = $1 AND source = 'cli'
590
+ ) AS has`,
591
+ [builderId]
592
+ );
593
+ return rows[0] ? rows[0].has === true : false;
594
+ }
595
+
596
+
597
+ // lookupSession — carved to ./db-kernel (ADR 0102). Re-exported above.
598
+
599
+
600
+ async function revokeSession(token) {
601
+ await pool.query(
602
+ `UPDATE builder_sessions SET revoked_at = now() WHERE token = $1 AND revoked_at IS NULL`,
603
+ [token]
604
+ );
605
+ }
606
+
607
+ // revokeSessionById — V3.R38 / #259. Kill ONE session by primary key. Returns
608
+ // the number of rows revoked (0 if id didn't exist or was already revoked, 1
609
+ // otherwise). Used by POST /api/gds/auth/revoke (Archon-only).
610
+
611
+ async function revokeSessionById(sessionId) {
612
+ const { rowCount } = await pool.query(
613
+ `UPDATE builder_sessions
614
+ SET revoked_at = now()
615
+ WHERE id = $1 AND revoked_at IS NULL`,
616
+ [sessionId]
617
+ );
618
+ return rowCount;
619
+ }
620
+
621
+ // revokeAllSessionsForBuilder — V3.R38 / #259. Kill EVERY non-revoked session
622
+ // for a single builder. Returns the count of sessions revoked. Used by:
623
+ // * POST /api/gds/auth/revoke-all (Archon-only direct call)
624
+ // * setBuilderRank when newRank < oldRank (rank-change-near-instant per C7)
625
+
626
+ async function revokeAllSessionsForBuilder(builderId) {
627
+ const { rowCount } = await pool.query(
628
+ `UPDATE builder_sessions
629
+ SET revoked_at = now()
630
+ WHERE builder_id = $1 AND revoked_at IS NULL`,
631
+ [builderId]
632
+ );
633
+ return rowCount;
634
+ }
635
+
636
+ // -------------------------------------------------------------------------
637
+ // Versions
638
+ // -------------------------------------------------------------------------
639
+
640
+
641
+ async function recentKarmaForBuilder(builderId, limit = 10) {
642
+ const n = Math.min(Math.max(Number(limit) || 10, 1), 500);
643
+ const { rows } = await pool.query(
644
+ `SELECT k.id, k.delta, k.reason, k.recorded_at,
645
+ k.granted_by,
646
+ gb.github_login AS granted_by_login,
647
+ gb.display_name AS granted_by_display_name
648
+ FROM karma_log k
649
+ LEFT JOIN builders gb ON gb.id = k.granted_by
650
+ WHERE k.builder_id = $1
651
+ ORDER BY k.recorded_at DESC, k.id DESC
652
+ LIMIT $2`,
653
+ [builderId, n]
654
+ );
655
+ return rows;
656
+ }
657
+
658
+ // V3.R26 (#246): rolling 30-day karma delta for this builder. Powers the
659
+ // "karma trend" stat on the /builders profile card — the done-when "30-day
660
+ // delta" criterion. Returns a plain integer (0 when no karma_log rows fall in
661
+ // the window) so the UI can render it directly without null-handling. Cheap
662
+ // single-aggregate query; safe to call alongside the karma feed.
663
+
664
+ async function karmaDelta30d(builderId) {
665
+ const { rows } = await pool.query(
666
+ `SELECT COALESCE(SUM(delta), 0)::int AS delta_30d
667
+ FROM karma_log
668
+ WHERE builder_id = $1
669
+ AND recorded_at >= now() - interval '30 days'`,
670
+ [builderId]
671
+ );
672
+ return rows[0]?.delta_30d ?? 0;
673
+ }
674
+
675
+ // -------------------------------------------------------------------------
676
+ // Discord foundation (Phase 3 F1, ADR 0033)
677
+ // -------------------------------------------------------------------------
678
+ // Account links are 1:1 both ways and exist only because a builder PERSONALLY
679
+ // linked their Discord (F2's UI-first OAuth) — the bot never invents a mapping.
680
+ // Every write the bot later triggers re-checks the linked builder's LIVE rank
681
+ // (ADR 0033 §1). Applause is the cosmetic tier: open to anyone, never karma.
682
+
683
+ // Link a Discord user to a builder. Idempotent for the SAME builder (re-link
684
+ // updates discord_user_id). Returns { ok:true, link } on success, or
685
+ // { ok:false, error:'discord_taken' } if that Discord id is already linked to a
686
+ // DIFFERENT builder (UNIQUE(discord_user_id)) — surfaced so F2's route answers
687
+ // cleanly instead of 500-ing.
688
+
689
+ async function linkDiscord({ builderId, discordUserId }) {
690
+ try {
691
+ const { rows } = await pool.query(
692
+ `INSERT INTO discord_links (builder_id, discord_user_id)
693
+ VALUES ($1, $2)
694
+ ON CONFLICT (builder_id)
695
+ DO UPDATE SET discord_user_id = EXCLUDED.discord_user_id, linked_at = now()
696
+ RETURNING builder_id, discord_user_id, linked_at`,
697
+ [builderId, discordUserId]
698
+ );
699
+ return { ok: true, link: rows[0] };
700
+ } catch (err) {
701
+ if (err.code === '23505') return { ok: false, error: 'discord_taken' }; // unique_violation
702
+ throw err;
703
+ }
704
+ }
705
+
706
+ // Remove a builder's Discord link. Returns true if a row was deleted.
707
+
708
+ async function unlinkDiscord(builderId) {
709
+ const { rowCount } = await pool.query(
710
+ `DELETE FROM discord_links WHERE builder_id = $1`,
711
+ [builderId]
712
+ );
713
+ return rowCount > 0;
714
+ }
715
+
716
+ // The Discord link for a builder (so the hall can show "linked as ..." + an
717
+ // Unlink affordance), or null.
718
+
719
+ async function getDiscordLink(builderId) {
720
+ const { rows } = await pool.query(
721
+ `SELECT builder_id, discord_user_id, linked_at FROM discord_links WHERE builder_id = $1`,
722
+ [builderId]
723
+ );
724
+ return rows[0] || null;
725
+ }
726
+
727
+ // Record one cosmetic applause (a Discord user reacted on a shipped task).
728
+ // NEVER writes karma_log — that separation is load-bearing (ADR 0033 §3).
729
+ // Re-reacting is a harmless no-op. Returns { counted } — true if new, false if
730
+ // this user had already applauded this task.
731
+
732
+ async function recordApplause({ targetTaskId, discordUserId }) {
733
+ const { rowCount } = await pool.query(
734
+ `INSERT INTO discord_applause (target_task_id, discord_user_id)
735
+ VALUES ($1, $2)
736
+ ON CONFLICT (target_task_id, discord_user_id) DO NOTHING`,
737
+ [targetTaskId, discordUserId]
738
+ );
739
+ return { counted: rowCount > 0 };
740
+ }
741
+
742
+
743
+ // -------------------------------------------------------------------------
744
+ // Task grades (PMS-V2 task 197)
745
+ // -------------------------------------------------------------------------
746
+
747
+ // Last N grades for tasks shipped by this builder (passed=true OR false —
748
+ // the failed grades are interesting too).
749
+ //
750
+ // V3.R18 (#209): rubric_scores + signals.issues are now part of the response
751
+ // so /me can surface the v2 subagent's failure detail (functional_fidelity vs
752
+ // code_quality + the issues array) without a follow-up call.
753
+
754
+ // builderRollingAvgGrade RELOCATED to modules/grading/db.js (ADR 0102) — the
755
+ // grade-TREND read behind the 'grade.builderRollingAvgGrade' port (core me.js +
756
+ // the sessions BFG resolve it; degrades to a zero-grade shape when grading is off).
757
+
758
+ // Per-builder grade breakdown over the last `days` days. Powers the MARKS
759
+ // section of the Archon-only /watch page (#726) — "who is passing / failing
760
+ // the grader". One row per builder who has at least one graded ship in the
761
+ // window, joined through tasks.shipped_by. avg_score 0–10, pass_rate 0–1.
762
+
763
+ async function listAuditLog({ limit = 100, offset = 0, builderId, method, surface } = {}) {
764
+ const where = [];
765
+ const params = [];
766
+ if (builderId) {
767
+ params.push(builderId);
768
+ where.push(`builder_id = $${params.length}`);
769
+ }
770
+ if (method) {
771
+ params.push(method);
772
+ where.push(`method = $${params.length}`);
773
+ }
774
+ if (surface) {
775
+ if (surface === 'none') {
776
+ where.push(`surface IS NULL`);
777
+ } else {
778
+ params.push(surface);
779
+ where.push(`surface = $${params.length}`);
780
+ }
781
+ }
782
+ const whereSql = where.length ? `WHERE ${where.join(' AND ')}` : '';
783
+ params.push(limit);
784
+ const limitParam = `$${params.length}`;
785
+ params.push(offset);
786
+ const offsetParam = `$${params.length}`;
787
+ const { rows } = await pool.query(
788
+ `SELECT id, builder_id, route, method, request_body_redacted,
789
+ response_status, ip, user_agent, surface, recorded_at
790
+ FROM audit_log
791
+ ${whereSql}
792
+ ORDER BY recorded_at DESC, id DESC
793
+ LIMIT ${limitParam} OFFSET ${offsetParam}`,
794
+ params
795
+ );
796
+ return rows;
797
+ }
798
+
799
+ // -------------------------------------------------------------------------
800
+ // Session records (BFG session-inefficiency evaluator — 6D.1/6D.2, ADR 0027)
801
+ // CARVED into modules/sessions/db.js (BV1.R82 / ADR 0093 §1): the
802
+ // session_records data plane (upsertSessionRecord[WithReward], searchSessions,
803
+ // summarizeSessions, getSessionById, listSessionsByBuilder, filterTaskIdsClaimedBy,
804
+ // the order/limit/offset helpers + the shared filter clause) is now module-owned.
805
+ // upsertSessionRecordWithReward resolves the economy `reward` kernel port inside
806
+ // its own withTx; no core file calls these (the ship-time digest write is an HTTP
807
+ // POST to the module's /sessions route). sumCreditsForTasks() left for
808
+ // modules/economy/ at BV1.R77.
809
+ // -------------------------------------------------------------------------
810
+
811
+ // ---- 6D.6: grade-attempt log (ADR 0027) ----------------------------------
812
+
813
+ // logGradeAttempt — append one grade ATTEMPT to grade_attempts (migration 064).
814
+ // task_grades is upsert-unique (latest grade only), so this is the ONLY record
815
+ // of re-grade thrash. BEST-EFFORT: it swallows its own errors and returns a
816
+ // boolean — callers (db.applyGrade, post-commit) can never be broken by it. The
817
+ // queryFn seam lets the unit test inject a throwing/recording stub (mirrors the
818
+ // audit middleware's insertFn pattern).
819
+
820
+ async function upsertSecurityDoc({ slug, title, contentMd }) {
821
+ const { rows } = await pool.query(
822
+ `INSERT INTO security_docs (slug, title, content_md)
823
+ VALUES ($1, $2, $3)
824
+ ON CONFLICT (slug) DO UPDATE
825
+ SET title = EXCLUDED.title,
826
+ content_md = EXCLUDED.content_md,
827
+ updated_at = now()
828
+ RETURNING id, slug, title, content_md, created_at, updated_at`,
829
+ [slug, title, contentMd]
830
+ );
831
+ return rows[0];
832
+ }
833
+
834
+ // Fetch one doc (with content) by slug. Returns the row or null.
835
+
836
+ async function getSecurityDoc(slug) {
837
+ const { rows } = await pool.query(
838
+ `SELECT id, slug, title, content_md, created_at, updated_at
839
+ FROM security_docs WHERE slug = $1`,
840
+ [slug]
841
+ );
842
+ return rows[0] ?? null;
843
+ }
844
+
845
+ // List doc METADATA — slug, title, updated_at, and the content size in chars
846
+ // (char_length) — but NOT the content itself, so the list view never ships the
847
+ // exploit bodies. Newest-updated first.
848
+
849
+ async function listSecurityDocs() {
850
+ const { rows } = await pool.query(
851
+ `SELECT slug, title, updated_at, char_length(content_md) AS bytes
852
+ FROM security_docs
853
+ ORDER BY updated_at DESC, slug ASC`
854
+ );
855
+ return rows;
856
+ }
857
+
858
+ // ---------- server-side merge lease (task 585 / idea 124) ----------
859
+ //
860
+ // merge-lock.js serializes main-mutating merges within ONE machine (a filesystem lock). When
861
+ // builders ship from DIFFERENT physical machines — each with its own checkout of main — a file
862
+ // lock can't see across machines. This is the cross-machine counterpart: a TTL'd advisory lease
863
+ // keyed on the merge target (default 'main'), handed out by the GDS API at merge time. Plain SQL,
864
+ // NOT a session-scoped pg_advisory_lock (a pooled connection can't hold one across a builder's
865
+ // local merge); a dead holder's lease auto-reclaims once expires_at passes. See
866
+ // docs/recipes/multi-builder-merge.md and merge-lock.js (the intra-machine tier) — and
867
+ // merge-lock.withServerMergeLease(), the composition helper a multi-machine ship wraps around it.
868
+
869
+ // Atomically acquire OR renew the lease. Returns { acquired, holder, expires_at }; acquired=false
870
+ // (with the current holder/expiry) means another holder owns an unexpired lease.
871
+ // SECURITY (for the future route that wraps this): `holder` MUST be set server-side from the
872
+ // authenticated builder's identity, never a client-supplied value — otherwise a builder could
873
+ // forge a lease under another builder's name (or release theirs). holder is intentionally free
874
+ // text (a machine/session label), not an FK, so the route owns that binding.
875
+
876
+ module.exports = {
877
+ withTx,
878
+ upsertBuilder,
879
+ seatFirstAdminIfUnclaimed,
880
+ getBuilderById,
881
+ listActiveBuilders,
882
+ linkAnthropicAccount,
883
+ getBuilderByGithubId,
884
+ hasInvitedAccessRequest,
885
+ updateBuilderDisciplines,
886
+ RANKS,
887
+ setBuilderRank,
888
+ getLatestRankChangeForBuilder,
889
+ deactivateBuilder,
890
+ reactivateBuilder,
891
+ createSession,
892
+ lookupSession,
893
+ revokeSession,
894
+ revokeSessionById,
895
+ revokeAllSessionsForBuilder,
896
+ hasCliSession,
897
+ SESSION_TTL_MS,
898
+ LIVE_RANK_LADDER,
899
+ singleRungPromotionError,
900
+ recentKarmaForBuilder,
901
+ karmaDelta30d,
902
+ insertAuditLog,
903
+ listAuditLog,
904
+ linkDiscord,
905
+ unlinkDiscord,
906
+ getDiscordLink,
907
+ recordApplause,
908
+ upsertSecurityDoc,
909
+ getSecurityDoc,
910
+ listSecurityDocs,
911
+ };