@bongos/core 1.17.0 → 1.17.2

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 (230) hide show
  1. package/.bongos-core.json +363 -312
  2. package/.claude/skills/blocker-review/SKILL.md +1 -1
  3. package/.claude/skills/builder-claim/SKILL.md +2 -0
  4. package/.claude/skills/builder-exit/SKILL.md +2 -2
  5. package/.claude/skills/builder-redteam/SKILL.md +3 -3
  6. package/.claude/skills/builder-setup/SKILL.md +2 -2
  7. package/.claude/skills/builder-start/SKILL.md +1 -1
  8. package/.claude/skills/dev/SKILL.md +1 -1
  9. package/.claude/skills/idea-triage/SKILL.md +2 -2
  10. package/.claude/skills/ideate/SKILL.md +1 -1
  11. package/.claude/skills/merge-mode/SKILL.md +1 -1
  12. package/.claude/skills/new-project/SKILL.md +3 -0
  13. package/.claude/skills/paint/SKILL.md +1 -1
  14. package/CLAUDE.md +11 -238
  15. package/GOVERNANCE.md +1 -1
  16. package/README.md +1 -1
  17. package/bin/bongos.js +1 -0
  18. package/clients/bongos-client/README.md +4 -4
  19. package/clients/bongos-client/bongos-client.global.js +14 -1
  20. package/clients/bongos-client/index.cjs +14 -1
  21. package/clients/bongos-client/index.d.ts +19 -2
  22. package/clients/bongos-client/index.mjs +11 -1
  23. package/clients/bongos-client/package.json +1 -1
  24. package/docs/adr/0001-stack-choice-single-vps.md +1 -1
  25. package/docs/adr/0008-google-chat-oauth-user-auth.md +1 -1
  26. package/docs/adr/0019-red-team-bounty-payout-table.md +3 -3
  27. package/docs/adr/0020-security-model-public-stub.md +1 -1
  28. package/docs/adr/0023-kind-multipliers-and-idea-bonus.md +1 -1
  29. package/docs/adr/0024-cloneable-repo-local-first-memory.md +1 -1
  30. package/docs/adr/0026-bfg-memory-hygiene-and-cross-builder-learning.md +4 -4
  31. package/docs/adr/0027-bfg-session-inefficiency-evaluator.md +3 -3
  32. package/docs/adr/0030-builders-hall-live-updates.md +1 -1
  33. package/docs/adr/0031-cloud-dev-environments-for-builders.md +4 -4
  34. package/docs/adr/0032-discord-mirror-of-gds.md +2 -2
  35. package/docs/adr/0034-thetes-graduated-newcomer-rank.md +1 -1
  36. package/docs/adr/0044-mediterranean-palette-replacement.md +1 -1
  37. package/docs/adr/0044-per-box-live-game-preview.md +1 -1
  38. package/docs/adr/0054-session-token-reward-cost-plus.md +10 -10
  39. package/docs/adr/0057-container-cost-ledger.md +3 -3
  40. package/docs/adr/0062-medusa-instance-model-decoupling.md +4 -4
  41. package/docs/adr/0065-agpl-nonprofit-ai-first-governance.md +2 -2
  42. package/docs/adr/0085-remove-default-per-builder-spend-cap.md +1 -1
  43. package/docs/adr/0086-goal-scoped-work-hierarchy.md +1 -1
  44. package/docs/adr/0096-require-reward-before-workable.md +9 -9
  45. package/docs/adr/0097-retroactive-reward-backfill.md +3 -3
  46. package/docs/adr/0100-two-repo-instance-model.md +1 -1
  47. package/docs/adr/0101-goal-hierarchy-phase-5-judge-membership-reward.md +3 -3
  48. package/docs/adr/0103-core-first-extraction-cloud-bongos-trunk.md +3 -3
  49. package/docs/adr/0107-module-upstreaming-contribution-to-core-catalog.md +1 -1
  50. package/docs/adr/0120-pay-on-land-and-builder-owned-rebase-gate.md +6 -6
  51. package/docs/adr/0133-github-app-manifest-onboarding-signin.md +2 -0
  52. package/docs/adr/0134-private-first-npm-distribution.md +20 -6
  53. package/docs/adr/0135-module-upstream-submission-interim-queue.md +34 -0
  54. package/docs/adr/0136-update-channel-subscription-policy.md +51 -0
  55. package/docs/adr/0137-upstream-publish-policy-manual-owner-gated.md +40 -0
  56. package/docs/adr/0138-bundled-module-deps-declared-per-module.md +45 -0
  57. package/docs/adr/README.md +14 -10
  58. package/docs/api/openapi.json +315 -6
  59. package/docs/api-reference.md +10 -5
  60. package/docs/architecture.md +3 -3
  61. package/docs/branding-contract.md +5 -4
  62. package/docs/canonical-permissions.md +1 -1
  63. package/docs/design/vanilla-hall-ui-redesign-scope.md +1 -1
  64. package/docs/file-map.md +20 -19
  65. package/docs/handoff-template.md +2 -2
  66. package/docs/modules-contract.md +8 -1
  67. package/docs/onboarding/diagrams/README.md +7 -7
  68. package/docs/onboarding/drachmae-and-karma.md +18 -18
  69. package/docs/onboarding/primer.md +9 -9
  70. package/docs/recipes/audit-replay.md +2 -2
  71. package/docs/recipes/builder-box-lifecycle.md +2 -2
  72. package/docs/recipes/claude-design-loop.md +1 -1
  73. package/docs/recipes/instance-deploy.md +4 -4
  74. package/docs/recipes/instance-first-run.md +51 -0
  75. package/docs/recipes/ops-gotchas.md +1 -1
  76. package/docs/recipes/packaging-the-core.md +5 -5
  77. package/docs/recipes/private-npm-distribution.md +39 -12
  78. package/docs/recipes/self-host.md +1 -1
  79. package/docs/recipes/staging-environment.md +1 -1
  80. package/docs/recipes/upgrading-the-core.md +63 -8
  81. package/docs/research/cursor-competitive-analysis.md +1 -1
  82. package/docs/research/llm-model-agnostic-and-cheaper-grader.md +1 -1
  83. package/migrations/core_191_module_submissions.sql +45 -0
  84. package/modules/autonomy/CLAUDE.md +11 -45
  85. package/modules/builder-settings/CLAUDE.md +11 -54
  86. package/modules/dev-box/CLAUDE.md +11 -34
  87. package/modules/discord/CLAUDE.md +11 -46
  88. package/modules/discord/module.json +2 -1
  89. package/modules/economy/CLAUDE.md +11 -44
  90. package/modules/economy/achievements.js +9 -1
  91. package/modules/economy/credits.js +10 -1
  92. package/modules/grading/CLAUDE.md +11 -38
  93. package/modules/hall-ui/CLAUDE.md +11 -57
  94. package/modules/hall-ui/public/builders.js +71 -4
  95. package/modules/hall-ui/public/goal-inbox.js +191 -0
  96. package/modules/hall-ui/public/goals-page.js +227 -22
  97. package/modules/hall-ui/public/goals.html +16 -0
  98. package/modules/hall-ui/public/hall-widgets.js +14 -1
  99. package/modules/hall-ui/public/index.html +3 -0
  100. package/modules/hall-ui/public/new-project-wizard.js +6 -4
  101. package/modules/hall-ui/public/style.css +43 -0
  102. package/modules/ideas/CLAUDE.md +11 -33
  103. package/modules/lifecycle/CLAUDE.md +11 -59
  104. package/modules/lifecycle/routes/goals.js +80 -0
  105. package/modules/memory/CLAUDE.md +11 -36
  106. package/modules/onboarding/CLAUDE.md +11 -51
  107. package/modules/provisioning/CLAUDE.md +15 -0
  108. package/modules/provisioning/migrations/provisioning_001_tables.sql +160 -0
  109. package/modules/provisioning/migrations/provisioning_002_standalone_shape.sql +11 -0
  110. package/modules/provisioning/migrations/provisioning_003_github_app_manifest.sql +95 -0
  111. package/modules/provisioning/module.json +17 -0
  112. package/modules/provisioning/onboard-plan.js +37 -0
  113. package/modules/provisioning/provisioning.js +539 -0
  114. package/modules/provisioning/rate-limit.js +35 -0
  115. package/modules/provisioning/routes/provisioning.js +607 -0
  116. package/modules/provisioning/tests/provisioning.mjs +232 -0
  117. package/modules/provisioning/ui/.gitkeep +0 -0
  118. package/modules/security/CLAUDE.md +11 -40
  119. package/modules/security/secret-scrub.js +10 -0
  120. package/modules/sessions/CLAUDE.md +11 -35
  121. package/modules/status-ui/CLAUDE.md +11 -43
  122. package/package-lock.json +2 -2
  123. package/package.json +7 -2
  124. package/public-landing/create.html +58 -12
  125. package/public-landing/index.html +40 -21
  126. package/scripts/discord/README.md +1 -1
  127. package/scripts/gds/CLAUDE.md +11 -140
  128. package/scripts/gds/claim.js +98 -48
  129. package/scripts/gds/claude-materialize.js +174 -20
  130. package/scripts/gds/claude-md-template.js +84 -0
  131. package/scripts/gds/cli-lib.js +112 -2
  132. package/scripts/gds/cutover-codemod.js +241 -0
  133. package/scripts/gds/fitness.js +54 -0
  134. package/scripts/gds/gen-api-client.js +10 -10
  135. package/scripts/gds/init.js +112 -16
  136. package/scripts/gds/lint-infra-exec.js +70 -0
  137. package/scripts/gds/lint-workflow-exec.js +63 -0
  138. package/scripts/gds/migration-namespace.js +1 -1
  139. package/scripts/gds/mirror-lineage-check.js +14 -5
  140. package/scripts/gds/mirror-redact.js +8 -0
  141. package/scripts/gds/module.js +118 -4
  142. package/scripts/gds/npmrc.js +93 -0
  143. package/scripts/gds/onboard.js +17 -24
  144. package/scripts/gds/package-core.js +74 -17
  145. package/scripts/gds/provision.js +102 -17
  146. package/scripts/gds/publish-manifest.js +60 -2
  147. package/scripts/gds/run-routine.js +51 -13
  148. package/scripts/gds/run-unit-tests.js +4 -0
  149. package/scripts/gds/seed-adopt-tasks.js +1 -1
  150. package/scripts/gds/status.js +6 -1
  151. package/scripts/gds/task.js +166 -0
  152. package/scripts/gds/update-channel.js +186 -0
  153. package/scripts/gds/upgrade.js +172 -25
  154. package/src/bongos/CLAUDE.md +11 -60
  155. package/src/bongos/auth.js +24 -0
  156. package/src/bongos/module-submissions.js +56 -0
  157. package/src/bongos/route-rank-check.js +6 -0
  158. package/src/bongos/routes/CLAUDE.md +11 -39
  159. package/src/bongos/routes/auth.js +6 -1
  160. package/src/bongos/routes/modules.js +123 -21
  161. package/src/bongos/serve-internal.js +10 -1
  162. package/src/branding.js +1 -0
  163. package/src/instance-config.js +1 -1
  164. package/src/module-api.js +24 -1
  165. package/src/module-loader/loader.js +36 -4
  166. package/src/module-loader/manifest-schema.js +16 -1
  167. package/tests/branding.mjs +11 -0
  168. package/tests/claim_error_surface.mjs +107 -0
  169. package/tests/claude_materialize.mjs +125 -0
  170. package/tests/consumer_layout_boot.mjs +302 -0
  171. package/tests/cutover_codemod.mjs +184 -0
  172. package/tests/device_flow_start.mjs +96 -0
  173. package/tests/first_run_engine_check.mjs +79 -0
  174. package/tests/goal_membership_requests.mjs +33 -3
  175. package/tests/hook_core_resolve.mjs +125 -0
  176. package/tests/hook_user_agents.mjs +62 -0
  177. package/tests/infra_exec_paths.mjs +104 -0
  178. package/tests/init.mjs +106 -6
  179. package/tests/instance_mismatch_guard.mjs +101 -0
  180. package/tests/mirror_lineage_proof.mjs +14 -0
  181. package/tests/module_cli.mjs +130 -2
  182. package/tests/module_loader.mjs +42 -0
  183. package/tests/module_manifest.mjs +19 -0
  184. package/tests/module_submissions.mjs +135 -0
  185. package/tests/npmrc.mjs +105 -0
  186. package/tests/onboard.mjs +62 -0
  187. package/tests/package_core.mjs +76 -22
  188. package/tests/platform_boot.mjs +5 -2
  189. package/tests/provision.mjs +107 -8
  190. package/tests/provisioning_github_app_routes.mjs +44 -2
  191. package/tests/publish_manifest.mjs +52 -1
  192. package/tests/run_routine.mjs +26 -1
  193. package/tests/run_routine_two_root.mjs +77 -0
  194. package/tests/scrubber_corpus.mjs +17 -0
  195. package/tests/served_paths_shipped.mjs +2 -2
  196. package/tests/task_cli.mjs +99 -0
  197. package/tests/update_channel.mjs +186 -0
  198. package/tests/upgrade.mjs +220 -25
  199. package/tests/workflow_exec_paths.mjs +98 -0
  200. package/docs/design/container-exterior-tiles.md +0 -49
  201. package/docs/design/container-exterior.md +0 -81
  202. package/docs/design/container-interior.md +0 -77
  203. package/docs/design/world-map-scroll.md +0 -41
  204. package/docs/recipes/claude-gemini-bongos-doors.md +0 -155
  205. package/docs/recipes/cloudbongos-staging-gate.md +0 -139
  206. package/docs/recipes/cloudbongos-standup.md +0 -111
  207. package/docs/recipes/parallel-load-results-2026-05-30.md +0 -63
  208. package/docs/recipes/parallel-load-test.md +0 -32
  209. package/docs/recipes/pixel-art-pipeline.md +0 -411
  210. package/docs/recipes/staging-data.md +0 -50
  211. package/migrations/instance/018_pms_v3_planning_seed.sql +0 -131
  212. package/migrations/instance/080_gds_v4_planning_seed.sql +0 -75
  213. package/migrations/instance/110_medusa_planning_seed.sql +0 -70
  214. package/migrations/instance/120_bongos_v1_planning_seed.sql +0 -69
  215. package/migrations/instance/144_bongos_v1_module_system_criterion.sql +0 -26
  216. package/migrations/instance/159_bongos_v1_goal_hierarchy_criterion.sql +0 -29
  217. package/migrations/instance/172_v2_world_planning_seed.sql +0 -163
  218. package/migrations/instance/173_bongos_v1_c7_core_modularized.sql +0 -33
  219. package/migrations/instance/182_gdsv4_bongos_consolidation.sql +0 -132
  220. package/migrations/instance/183_gdsv4_carryover_themed_goals.sql +0 -116
  221. package/migrations/instance/186_bongos_v1_governance_planning_seed.sql +0 -69
  222. package/scripts/gds/art-stage.js +0 -152
  223. package/server.js +0 -212
  224. package/tests/art_key.mjs +0 -121
  225. package/tests/day_cycle.mjs +0 -197
  226. package/tests/snapshot_picker.mjs +0 -233
  227. package/tests/sprite_facing.mjs +0 -35
  228. package/tests/terrain_picker.mjs +0 -298
  229. package/tests/turn_in_place.mjs +0 -280
  230. package/tests/walkability.mjs +0 -188
@@ -86,7 +86,7 @@ This keeps the decision history honest and traceable.
86
86
  | 0020 | [Security model — public stub (full ADR is server-side)](<redacted>.md) | GDS / security |
87
87
  | 0021 | [Per-builder skill model preferences + audit](<redacted>.md) | GDS / cost discipline |
88
88
  | 0022 | [Secrets policy — what counts, where it lives, how rotation works](0022-secrets-policy.md) | infra / security |
89
- | 0023 | [Kind multipliers + staged idea bonus](<redacted>.md) | GDS / drachmae economy |
89
+ | 0023 | [Kind multipliers + staged idea bonus](<redacted>.md) | GDS / example economy |
90
90
  | 0024-a | [Cloneable repo + local-first memory with server-canonical sync](<redacted>.md) | GDS / per-builder memory |
91
91
  | 0024-b | [Multi-Agent System (MAS) architecture](<redacted>.md) | GDS / MAS |
92
92
  | 0025-a | [Offsite backup vendor: DigitalOcean Spaces](<redacted>.md) | infra / backup |
@@ -120,7 +120,7 @@ This keeps the decision history honest and traceable.
120
120
  | 0051 | [Full session transcripts in the BFG corpus (with transcript-grade scrubbing)](<redacted>.md) | GDS / BFG |
121
121
  | 0052 | [Sandbox for everyone: a game-only preview entrypoint + the game in the starter clone](<redacted>.md) | GDS / dev boxes |
122
122
  | 0053 | [Scoped, short-lived dev-box session + apex-cookie strip at the tunnel (SR#2/#11)](0053-scoped-dev-box-session.md) | GDS / dev boxes + security |
123
- | 0054 | [Flat cost-plus session token reward (drachmae as equity): reward = round(true_cost_usd × 1.20 × 100), server-priced from per-model tokens, idempotent per session_id](<redacted>.md) | GDS / economy |
123
+ | 0054 | [Flat cost-plus session token reward (example as equity): reward = round(true_cost_usd × 1.20 × 100), server-priced from per-model tokens, idempotent per session_id](<redacted>.md) | GDS / economy |
124
124
  | 0055 | [Server-mediated branch publish (the dev box holds no GitHub credential): box uploads a thin bundle, the GDS pushes + opens the PR + auto-merges with a server-side PAT](<redacted>.md) | GDS / dev boxes + ship pipeline |
125
125
  | 0056 | [Version-control the prod deploy script as a reviewable mirror (`scripts/deploy/deploy-prod.sh`), and retry the post-restart `/healthz` so a slow service bind no longer false-fails a successful deploy](<redacted>.md) | GDS / deploy pipeline |
126
126
  | 0057 | [Approve new members and first dev boxes from Discord: two Archon-only channels where a 👍/👎 fires the existing admit (`access_requests`) / first-box (`box_intents`) approve action, re-checked against the reactor's live rank](<redacted>.md) _(box half superseded by ADR 0059)_ | GDS / Discord + onboarding |
@@ -163,22 +163,22 @@ This keeps the decision history honest and traceable.
163
163
  | 0094 | [Repo Atlas — a self-drawing map of the codebase (idea [#457](https://example.com/builders#/idea/457)): a Builders' Hall page rendering an isometric, hover-connective, click-for-detail map in two views — CONTEXT LAYER (the always-loaded root `CLAUDE.md` + its budget gauge vs the on-demand nested guides, the docs library, the DB as live state, broken-link drift) and MODULE TRUTH (the real modules carved into `modules/<key>/` with clean boundaries vs the ~26k-line `src/bongos` core blob + the `db.js` monolith vs the planned-but-still-fused ghosts). Data = one generated `public-builders/atlas.json` from `scripts/gds/gen-atlas.js`, PURE file-reads, reusing the existing truth sources (`module-scope-map` MOVED-vs-FUSED, `fitness.js` boundary scan for clean-vs-violation + kernel leaks, `docs-entropy` stale links, the `CLAUDE.md` budget). Regenerated SERVER-SIDE on every deploy (a `deploy-prod.sh` step, the world-snapshot precedent) — never on the shipping builder's machine; gitignored build artifact; page degrades gracefully pre-generation; styled in the Cloud Bongos brand, gated to any signed-in builder, built to port to Cloud Bongos. Owner decision 2026-06-27. Follow-up task [#1641](https://example.com/builders#/task/1641) migrates the repo-map/session-index/file-map generators onto the same server-side trigger (diagrams excepted: headless browser + auth).](<redacted>.md) | Cloud Bongos / docs |
164
164
  | 0095-a | [Borrowed memory, retrieval & collision concepts from claude-mem (Apache-2.0) and graphify (MIT) — after evaluating both Claude-Code tools and rejecting either wholesale (Python stack / local-daemon+Chroma architecture / no rank-scoping / open-core+memecoin governance), adopt eight stack-agnostic CONCEPTS, reimplemented in-stack with no new dependency or service ("borrow concepts, not tools"): from graphify — symbol-level collision detection (path-prefix→symbol/dependency overlap in `path-match.js`, the forecast-accuracy lever ADR 0049 left open), an AST/tree-sitter repo-map upgrade via the ADR 0063 `extractFile()` seam (polyglot + symbol resolution + a dependency graph that also feeds the ADR 0094 atlas truer edges), and forward-facing "why" extraction (`# WHY:`/ADR rationale into recall + auto-injected on file open); from claude-mem (1–5) — progressive-disclosure recall with token-cost visibility (~10× fewer tokens/query, mechanism-agnostic), a hook graceful-degradation policy (infra-fail→exit 0, code-bug→exit 2), a memory-usefulness feedback loop, a `<private>` content-exclusion marker, and windowed content-hash dedup. Deliberately does NOT decide grep vs. a semantic/embedding layer — a companion owner-authored ADR owns that, and every item here composes with whichever it picks. Declines lifting either codebase, the Chroma/uv dependency, and automatic-capture-as-default (folded into the BFG as suggestion-only).](<redacted>.md) | GDS / memory + retrieval |
165
165
  | 0095-b | [Cross-agent context management — adopt docstrings now (meaning written into version-controlled source is the zero-cost, zero-drift core of BOTH grep and semantic findability — no separate index to pay for or keep fresh); record as DEFERRED future-decision content the `AGENTS.md` cross-tool adapter layer (one canonical instructions file + thin per-tool pointers), the greppability / Grep-Test naming conventions, the `AIDEV-NOTE` anchor-comment convention (guarded by a fitness check so it can't rot), a semantic / embeddings layer (local model + embedded store + incremental git-hook reindex, run alongside grep — never instead), and a per-project "retrieval & agent profile" chosen at init that provisions the adapter set. Preserves the cross-agent research (agents navigate by grep not embeddings; Anthropic + Sourcegraph dropped embedding indexes, Cursor only augments grep with them). The portability frame is the ADR 0062 / 0081 core↔host swappable-adapter pattern applied to the agent surface; corroborates ADR 0060's deferred-embeddings gate. One accepted decision; everything else is framing for a future GDS-V4 / Cloud Bongos planning session. Follow-on task 1654 tracks the docstring rollout.](<redacted>.md) | Cloud Bongos / context + retrieval |
166
- | 0096 | [Require a `credits_reward` (drachmae) value before a task is workable — closes the hole where `credits_reward NOT NULL DEFAULT 0` (migration 003) let a task be promoted→claimed→shipped while paying 0 drachmae. Enforces a present, positive reward at THREE points: the promote route (`POST /tasks/:id/promote` refuses an unrewarded flip to `ready` with an actionable `REWARD_REQUIRED` 409 that SUGGESTS a value from kind/est), the auto-promote predicate (`task_is_fully_unblocked`, migration 177 — adds `(reward_gate_exempt OR credits_reward>0)` so a deps-shipped task with no reward stays `backlog`), and a claim backstop (`db.claimTask` mirrors the `DEPS_NOT_SHIPPED` second-line-of-defence). GRANDFATHERS the ~57 already-`ready` zero-reward tasks via a `tasks.reward_gate_exempt` flag set true for every task at/past `ready` at migration time — no currently-claimable task becomes unclaimable, no `ready` task is retro-demoted (the predicate change is forward-only: triggers never re-evaluate a `ready` row). Keeps `credits_reward` AUTHOR-SET (ADR 0023 anti-gaming): suggests, never auto-applies; setting it stays `PATCH /tasks/:id`. Coordinates with the backfill task (<redacted>, task 1672) to value the grandfathered rows.](<redacted>.md) | GDS / economy + lifecycle |
166
+ | 0096 | [Require a `credits_reward` (example) value before a task is workable — closes the hole where `credits_reward NOT NULL DEFAULT 0` (migration 003) let a task be promoted→claimed→shipped while paying 0 example. Enforces a present, positive reward at THREE points: the promote route (`POST /tasks/:id/promote` refuses an unrewarded flip to `ready` with an actionable `REWARD_REQUIRED` 409 that SUGGESTS a value from kind/est), the auto-promote predicate (`task_is_fully_unblocked`, migration 177 — adds `(reward_gate_exempt OR credits_reward>0)` so a deps-shipped task with no reward stays `backlog`), and a claim backstop (`db.claimTask` mirrors the `DEPS_NOT_SHIPPED` second-line-of-defence). GRANDFATHERS the ~57 already-`ready` zero-reward tasks via a `tasks.reward_gate_exempt` flag set true for every task at/past `ready` at migration time — no currently-claimable task becomes unclaimable, no `ready` task is retro-demoted (the predicate change is forward-only: triggers never re-evaluate a `ready` row). Keeps `credits_reward` AUTHOR-SET (ADR 0023 anti-gaming): suggests, never auto-applies; setting it stays `PATCH /tasks/:id`. Coordinates with the backfill task (<redacted>, task 1672) to value the grandfathered rows.](<redacted>.md) | GDS / economy + lifecycle |
167
167
  | 0097 | [One active claim per session + a claim binds to a dedicated worktree (task 1642) — closes the commingled-ship hole: a single Claude Code session works one git worktree which owns one branch, so claiming a 2nd task from the same worktree lands both tasks' commits on one branch and `/builder-ship` (which publishes the whole branch) drags the unfinished task's work out under the first's ship. The only prior guard (`gateNewcomerClaim`) was Xenos-only, builder-scoped, and fail-OPEN. Adds a SESSION-scoped (keyed on `creator_session_id`, not builder — preserves the many-sessions-per-builder norm), ALL-rank, FAIL-CLOSED block at `POST /claims` (`409 session_already_has_active_claim` naming the in-flight task). NULL-session web claims (`bind_session=false`) are skipped so claim-in-browser/ship-from-any-terminal still works. The decision is a pure exported fn (`shouldRefuseSessionClaim`, DB-free unit-tested); the route middleware is thin. DB defence-in-depth: partial unique index `uniq_active_claim_per_session ON claims(creator_session_id) WHERE released_at IS NULL AND creator_session_id IS NOT NULL` (migration 180 — the real `released_at` convention, NOT the spec's nonexistent `status` column; heals any current violation before CREATE so deploy can't break). Part B: the builder-claim skill default flow now claims into a dedicated worktree (`EnterWorktree task-N`). AMENDS ADR 0049 — adds the within-session invariant 0049 left implicit; the cross-claim split contract is untouched.](<redacted>.md) | GDS / lifecycle |
168
168
  | 0098 | [The Cloud Bongos public-mirror publish boundary as an executable manifest (`scripts/gds/publish-manifest.js`, `isPublishable()`) — makes ADR 0065 §4's prose boundary something R72 (the delayed redacted export) consumes and R73 (the no-leak proof) asserts against. Default-deny: an allowlist (portable core + platform + neutral branding + sanitized methodology docs) gated by a hard denylist that IMPORTS and partitions the three trust inventories — `PROTECTED_GLOBS` is NOT a denylist, only its topology subset (infra/deploy/CI/local-gate-hooks) is excluded; the rank/permission/ship machinery publishes AS the open-source methodology. Excludes the game + all art (the art subtree carries the ripped Pokémon FireRed reference corpus — an independent copyright reason) + instance identity/config/history + secrets. A unit test cross-checks the partition against the live `PROTECTED_GLOBS` so the carve-out can't silently drift (the gate-review "no allow-by-omission" doctrine applied to publishing). Defers the customer-0 brand pack + desktop-client source to R72/owner (excluded by default until then). No migration — a file-glob boundary has no DB state.](<redacted>.md) | Cloud Bongos / open-source governance |
169
169
  | 0099 | [The time-delayed, redacted public-mirror export pipeline (R72, task 1211) — the file-level work ADR 0098 deferred: `scripts/public-mirror-export.js` picks the newest commit ≥180 days old (a lagged SNAPSHOT, not a history replay), partitions its tree through `isPublishable()` (ADR 0098 — the ONLY allow-list), redacts every published file (`scripts/gds/mirror-redact.js`: domain/subdomains → example.com, repo/db/world/company token → example, owner login+aliases → example-owner, public IPv4 **and** IPv6 → REDACTED_IP with localhost/RFC-1918/RFC-5737/link-local/ULA kept) THEN the ADR-0022 secret scrubber (extracted to `modules/security/secret-scrub.js` so it's CI-safe to require without ship.js's heavy deps; ship.js re-exports it). FAIL-CLOSED + atomic: all redaction in memory, a no-leak gate over every blob, and only a fully-clean set touches the mirror FS. Two invariants carry it: (1) SELF-LEAK — the redactor is itself published so it holds NO instance literal, deriving them at runtime from the excluded `config/branding.json`; (2) the no-leak DETECTOR is STRICTER THAN + DECOUPLED FROM redaction — `findLeaks` scans raw literal SUBSTRINGS + IPv4/v6 floors, not the bounded redaction regexes, because a shared word-bounded rule silently missed `example-owner` inside a regex-literal string AND blinded the gate to its own miss. Droplet IP + owner-name aliases are sourced from env in the EXCLUDED workflow yaml. Transport reuses the ADR-0029/[#741](https://example.com/builders#/task/741) scoped-deploy-key push; scheduled weekly; DORMANT no-op until history is 180d old (~2026-11), keeping the mirror empty until R73 lands + the owner flips it public. `.mirror-provenance.json` is the lineage anchor R73 ([#1212](https://example.com/builders#/task/1212)) reuses.](<redacted>.md) | Cloud Bongos / open-source governance |
170
170
  | 0100 | [Two-repo instance model — a project consumes Cloud Bongos as a versioned platform dependency (resolves the R77 decision gate, task [#1607](https://example.com/builders#/task/1607)). Chooses the PHYSICAL repo topology [ADR 0062](<redacted>.md) §10 left open: an instance may be its OWN repo installing a pinned core (the `isPublishable()` subtree, [ADR 0098](<redacted>.md)) + layering its own content/branding/modules — not only a second process on one checkout (cloudbongos.com stays a supported, cheaper reskin shape). SEQUENCED + Mercury-driven: build the smallest slice to stand Mercury up as customer 2 on a PINNED core, then let its first core bump define the update channel (`bongos upgrade` is a stub today, [#1203](https://example.com/builders#/task/1203)) — don't design the channel up front; Example is NOT split (stays the single-checkout reference instance, free core updates) until a separate later call. GDS topology = PER-REPO (each project its own DB/tasks/builders/versions; a shared GDS is rejected — it re-couples what the split exists to separate). The generated mirror ([ADR 0065](<redacted>.md) §4 / [ADR 0099](<redacted>.md)) is RETAINED now, retired CONDITIONALLY once the core is physically extracted (then the core repo becomes the canonical public artifact); AGPL + governance + 6-month delay unaffected by topology. Trades free instant updates for a permanent per-project upgrade step + a bigger op footprint, weighed against the $5k budget. Seeds GDS-V4 R84→R85→R86.](<redacted>.md) | Cloud Bongos / architecture |
171
- | 0101 | [Goal hierarchy Phase 5 — the deferred ADR 0086 non-decisions, recorded with a security review (BV1.R65, task 1519): (1) an ADVISORY-FIRST relevance / anti-hack judge at goal-task create/claim that reuses the ADR 0024 grader subagent harness, flags for a Metic to review, and NEVER hard-blocks a newcomer (the deterministic scope + protected-path + auto-rank-floor gates stay the only hard walls; a fallible LLM as a hard gate would re-introduce the bottleneck ADR 0086 removed + open a gaming/DoS surface); (2) sub-Metic membership inside PROTECTED-scope goals — a genuine widening of the ADR 0043 hard floor, made purely-additive + fail-closed: an Archon grants a tightly-scoped, audit-logged membership and the ship-time gates (pre-push / grader pre-pass / gate-review / main-audit) become GOAL-AWARE on the REAL diff (allow a sub-Metic protected-path hit only if a live Archon-granted goal membership enumerates exactly that path, else the 0043 floor bites unchanged); ships LAST behind Part 1 + an owner Gate sign-off (ADR 0058) + a red-team pass; (3) the goal-reward model — leaning KARMA (not drachmae: real money, tight budget) + CONTRIBUTION-WEIGHTED (not membership-flat: anti-squatting; reuse the shipped-task attribution + BFG signals, ADR 0027) on goal ACHIEVEMENT, with any monetary component + the exact curve owner-gated at build time. Design + security review only; NO enforcement code. Child cluster P5.1 (judge) / P5.2 (goal-aware gates + 0043 amendment) / P5.3 (reward) filed backlog.](<redacted>.md) | GDS / permissions + economy |
171
+ | 0101 | [Goal hierarchy Phase 5 — the deferred ADR 0086 non-decisions, recorded with a security review (BV1.R65, task 1519): (1) an ADVISORY-FIRST relevance / anti-hack judge at goal-task create/claim that reuses the ADR 0024 grader subagent harness, flags for a Metic to review, and NEVER hard-blocks a newcomer (the deterministic scope + protected-path + auto-rank-floor gates stay the only hard walls; a fallible LLM as a hard gate would re-introduce the bottleneck ADR 0086 removed + open a gaming/DoS surface); (2) sub-Metic membership inside PROTECTED-scope goals — a genuine widening of the ADR 0043 hard floor, made purely-additive + fail-closed: an Archon grants a tightly-scoped, audit-logged membership and the ship-time gates (pre-push / grader pre-pass / gate-review / main-audit) become GOAL-AWARE on the REAL diff (allow a sub-Metic protected-path hit only if a live Archon-granted goal membership enumerates exactly that path, else the 0043 floor bites unchanged); ships LAST behind Part 1 + an owner Gate sign-off (ADR 0058) + a red-team pass; (3) the goal-reward model — leaning KARMA (not example: real money, tight budget) + CONTRIBUTION-WEIGHTED (not membership-flat: anti-squatting; reuse the shipped-task attribution + BFG signals, ADR 0027) on goal ACHIEVEMENT, with any monetary component + the exact curve owner-gated at build time. Design + security review only; NO enforcement code. Child cluster P5.1 (judge) / P5.2 (goal-aware gates + 0043 amendment) / P5.3 (reward) filed backlog.](<redacted>.md) | GDS / permissions + economy |
172
172
  | 0102 | [Finish bounding the kernel — flip fitness Check 12 ("kernel imports no domain") from a WARN-mode ratchet to a HARD gate by clearing all 7 tracked kernel→domain leaks (task [#1707](https://example.com/builders#/task/1707)). (1) `llm-cache.js` + `llm-pricing.js` reclassified as kernel-adjacent infra (pure/injected cost primitives, same category as the pg pool + `path-match.js` — added to `KERNEL_IMPORT_ALLOWLIST`, NOT a new module core would depend on anyway); (2) the identity/auth/admission cluster (`upsertBuilder`/`seatFirstAdminIfUnclaimed`/`getBuilderByGithubId`/`hasInvitedAccessRequest`/`createSession`/`lookupSession`/`SESSION_TTL_MS`/`RANKS`) carved from the `db.js` residue into `db-kernel.js` — `auth.js` (a KERNEL_FILE) resolves them there, `db.js` re-exports for its other callers, the `RANKS` twin now pairs with lifecycle; (3) the doorway's remaining domain re-exports pushed behind ports — Gemini-key storage → art-pipeline, `builderRollingAvgGrade` → the `grade` port; (4) `<redacted>` flipped to `violations` + `hardFail` at zero. Lands incrementally, each verified vs `fitness.js` + the unit suite + a live vanilla `docker compose up` (auth still 401s clean). Supersedes the ADR 0091 §1/§3 + 0093 WARN-mode deferral of the llm-infra carve.](<redacted>.md) | GDS / architecture |
173
173
  | 0103 | [Consolidate the two parallel internal versions — GDS-V4 (frozen) folds into BONGOS-V1, now the single go-forward Cloud Bongos PLATFORM version (renamed "Cloud Bongos — platform (V1)", status `building`); its still-relevant open work carries forward. The Bongos DESKTOP APP becomes its own GOAL under BONGOS-V1 (mascot, branded download + auto-update, the cloudbongos.com landing page, feedback capture, the absorbed Dev Box switch — [ADR 0087](<redacted>.md)); the code carve `bongos-app/` → `modules/bongos-app/` is tracked under it. Prunes 19 superseded tasks (the C1 semantic-search/embeddings arm — retired by [ADR 0095](<redacted>.md)'s grep-over-embeddings decision; old V3-era grader tasks superseded by [ADR 0089](<redacted>.md); the T-NNN task-ref migration), moves 2 misfiled game-art tasks to product V2, and severs the 758→753 dependency edge so 758 stays claimable. Executed as reversible data migration `182` (only status/version/goal/edge mutations; in-flight `confirmed`/`active` tasks stay in GDS-V4 to land). `/status` now defaults to BONGOS-V1. Surfaced + fixed a 12-day silent DB-backup outage first (task [#1711](https://example.com/builders#/task/1711)).](<redacted>.md) | Cloud Bongos / methodology |
174
174
  | 0104 | [Trust the GDS API channel in Claude Code AUTO mode — pre-allow `Bash(node scripts/gds/api.js:*)` in the project `.claude/settings.json`. Completes task [#1051](https://example.com/builders#/task/1051)'s narrow named-script allow-list (from the task-[#1027](https://example.com/builders#/task/1027) nightmare): every autonomous GDS op without a dedicated script — idea-triage promote, create-task, blocker-resolve, criterion ratify, goal create, cost, security reports — rides the GENERIC `api.js` caller, which was never allow-listed, so auto mode's classifier hard-denied the whole autonomous GDS write surface as "[External System Writes] … beyond the user's request" (it only worked under the box's task-[#1251](https://example.com/builders#/task/1251) `bypassPermissions`). Safe because the GDS SERVER enforces `builders.rank` per-request ([ADR 0016](<redacted>.md)) — the classifier was never the gate; the rule grants nothing beyond the caller's rank, and `api.js` can only reach `/api/gds/*`. Scope-discipline stays in the per-builder `wandering` knob. Locked by `tests/box_ship_permissions.mjs`.](<redacted>.md) | harness permissions / dev box |
175
175
  | 0105 | [Instance/product seed data out of the core migration path — OTB scope-truth (`versions`/`goals`/`done_when_criteria`) embedded in ~16 core migrations crash-looped a vanilla self-host on a fresh DB (FK violations) or polluted it with OTB's versions/goals; task [#1264](https://example.com/builders#/task/1264) patched only the two crashers (172/173 `DO`-block guards). Structural fix (task [#1704](https://example.com/builders#/task/1704)): the 10 PURE seed files move to a declared `migrations/instance/` dir; `scripts/migrate.sh` applies instance seeds only for the OWNING instance and DEFAULTS OFF (opt-in `GDS_APPLY_INSTANCE_SEEDS=1`; hard-off under the now-revived `MEDUSA_GDS_ONLY`), so a vanilla OR branded self-host never inherits them. Both dirs merge-sort by basename so the global numeric order is preserved (018 before 019) and an OTB from-scratch replay is byte-identical (5 versions / 11 goals / 43 criteria). The unavoidable seed blocks in the mixed files 003/006 guard in place on the `app.seed_instance_data` GUC (achievements + the generic `bfg`/`discord_bot` system principals kept). A `selfhost-boot.yml` CI gate (authored; landing gated on blocker 52 — the App can't merge `.github/workflows/*`) boots a fresh `postgres:16` and asserts a clean vanilla boot with zero OTB rows, closing the C9-style un-gated-proof gap. Verified against a throwaway DB both ways.](<redacted>.md) | Cloud Bongos / architecture |
176
176
  | 0106 | [Goal owner/manager authority — refines ADR 0086's membership roles into a fixed hierarchy (task [#1735](https://example.com/builders#/task/1735)): the goal OWNER is `goals.created_by` (a column, not a role row — set at create, moved only by the new owner-only `POST /goals/:id/transfer`; the new owner must be Metic+); MANAGER is the `goal_members.role='lead'` value (rendered "manager" in the hall), owner-equivalent EXCEPT demotion (owner-only) and transfer; the owner's row is never demotable (`owner_role_fixed`), enforced in the pure ordered gate (`authorizeMemberRoleChange`, the authorizeGoalTaskCreate precedent) AND atomically inside the UPDATE (`setGoalMemberRole`). Creators backfill as leads via module migration `<redacted>` — deliberately NO earliest-member fallback (fail-closed; ownerless migration-160 system goals stay Archon-run). No goal delete — archive unchanged. Replaces the task's original leads-as-equals "never below one lead" invariant with the simpler fixed-owner model.](<redacted>.md) | GDS / goal hierarchy |
177
- | 0107 | [Module upstreaming — instances contribute modules into the shared core catalog (task [#1766](https://example.com/builders#/task/1766)). The REVERSE of the ADR 0100/0103 distribution arrow: an instance (Example, Mercury) builds a feature module and submits it for approval to be merged INTO the shared Cloud Bongos core, credited to author + origin project; accepted modules land in core `modules/<key>/` **default-off**, added to the `isPublishable()` allowlist, and every instance may opt in. Decisions: (1) platform-native `bongos module submit` → a rank-gated core review queue (NOT instance write-access to core; fork-and-PR is a fallback); (2) attribution is PORTABLE METADATA — `module.json` gains `author`/`origin`/`license`/`maintainer` (a record, not a cross-GDS foreign key, since each repo has its own identities per [ADR 0100](<redacted>.md) §3); (3) reward = CREDIT NOW, money later (drachmae/cross-instance payout deferred to a separate economics call); (4) AGPL-IN with a DCO-style sign-off, NO CLA ([ADR 0065](<redacted>.md)), `isPublishable()` pre-check at submit rejects un-AGPL-able content (game/art/copyright); (5) SECURITY REVIEW is a hard accept-gate — a contributed module runs in-process in every enabling instance, no sandbox yet; (6) default-off + the publish-allowlist add IS the accept action; (7) maintenance/deprecation policy for orphaned modules (coreVersion compat). Sequenced: manifest fields + module-owned test discovery in core CI + submit-time pre-check buildable NOW; the submit→review→accept→catalog pipeline depends on R88 (extract core, [#1727](https://example.com/builders#/task/1727)) + R85 (Mercury, [#1689](https://example.com/builders#/task/1689)). Renames away from the taken "contribution seam" term (that is the in-process UI hook).](<redacted>.md) | Cloud Bongos / architecture |
178
- | 0108 | [Instance composition topology — CONFIGURABLE-ROOT: the core is consumed as a versioned npm dependency (task [#1870](https://example.com/builders#/task/1870), BV1.R115). Resolves the composition MECHANISM that [ADR 0062](<redacted>.md) §10 / [ADR 0100](<redacted>.md) §1 / [ADR 0103](<redacted>.md) §2 each left open (they are mechanism-neutral — "installs a pinned core + layers on top"; 0103's R88 record deferred "the topology/instance paths the scaffold populates on `init`"). A 2026-07-03 owner review chose configurable-root over the earlier clone-and-layer draft, weighting SCALABILITY over least-resistance: upgrades = O(1)-per-instance version bump (not O(instances×drift) merges); the boundary is enforced by the PACKAGE (can't rot under many agents) not convention+CI; a dependency forces a real core API; instance repos stay small; "root is a parameter" is the precondition for multi-instance/hosted. Decisions: (1) core installed as `@cloudbongos/core`, host content resolved via an injected instance-root — two resolvers `resolveInstanceRoot()`/`resolveCoreRoot()` in the existing `src/instance-config.js`, defaulting to repo-root TODAY (byte-identical) and flipping `resolveCoreRoot()` to `node_modules` when packaged, no further per-site edits; the two directions are OPPOSITE (config→instance-root; the `infra/` installers `serve-internal` serves→core-root); (2) `package-core` emits a real `package/`-rooted npm package (`main`→platform-server, `bin`→bongos, deps pruned to express/pg/undici), `isPublishable()` stays the single core definition; (3) `.claude/` is MATERIALIZED into the instance by `bongos init`/`upgrade` (Claude Code reads it from the project root, never node_modules) + the ~30 skills/hooks rewritten `node scripts/gds/…`→`bongos …` (skills already ship in-core; hooks+settings are already "topology"); (4) `bongos upgrade` (R86) is an npm version bump, deploy flips `git reset --hard`→`npm ci` (Docker/`platform-server`/`selfhost-boot` already model it); (5) cross-repo migration numbering gets a namespacing + lineage discipline (two repos both adding `NNN_*.sql` collide on the shared `schema_migrations` stem key); (6) land Mercury-first — step-1 resolvers now (zero-change), package+`.claude` prove on greenfield R85, Example splits last (R89) with the trust-boundary path sites + the two-root guardrail fix (fitness.js/gen-repo-map/gen-file-map all hardcode REPO_ROOT) behind a security review. Runtime-library half is SMALL/de-risked (~8–11 readers; entrypoint seam `mountInternalSurfaces`/`buildPlatformApp`, two-roots loader, single-sourced partition already exist); the real work is delivery+ops (§3/§4/§5) — the accepted "more pain now". Clone-and-layer/submodule/monorepo rejected. Informs R85 ([#1689](https://example.com/builders#/task/1689)), R86 ([#1690](https://example.com/builders#/task/1690)), R89 ([#1728](https://example.com/builders#/task/1728)). Docs amended (not superseded): file-map, architecture, packaging-the-core + self-host recipes, ADR 0105, modules-contract; cross-refs in 0062/0100/0103/0098/branding-contract/CLAUDE.md. No migration, no new criterion; goal 26.](<redacted>.md) | Cloud Bongos / architecture |
177
+ | 0107 | [Module upstreaming — instances contribute modules into the shared core catalog (task [#1766](https://example.com/builders#/task/1766)). The REVERSE of the ADR 0100/0103 distribution arrow: an instance (Example, Mercury) builds a feature module and submits it for approval to be merged INTO the shared Cloud Bongos core, credited to author + origin project; accepted modules land in core `modules/<key>/` **default-off**, added to the `isPublishable()` allowlist, and every instance may opt in. Decisions: (1) platform-native `bongos module submit` → a rank-gated core review queue (NOT instance write-access to core; fork-and-PR is a fallback); (2) attribution is PORTABLE METADATA — `module.json` gains `author`/`origin`/`license`/`maintainer` (a record, not a cross-GDS foreign key, since each repo has its own identities per [ADR 0100](<redacted>.md) §3); (3) reward = CREDIT NOW, money later (example/cross-instance payout deferred to a separate economics call); (4) AGPL-IN with a DCO-style sign-off, NO CLA ([ADR 0065](<redacted>.md)), `isPublishable()` pre-check at submit rejects un-AGPL-able content (game/art/copyright); (5) SECURITY REVIEW is a hard accept-gate — a contributed module runs in-process in every enabling instance, no sandbox yet; (6) default-off + the publish-allowlist add IS the accept action; (7) maintenance/deprecation policy for orphaned modules (coreVersion compat). Sequenced: manifest fields + module-owned test discovery in core CI + submit-time pre-check buildable NOW; the submit→review→accept→catalog pipeline depends on R88 (extract core, [#1727](https://example.com/builders#/task/1727)) + R85 (Mercury, [#1689](https://example.com/builders#/task/1689)). Renames away from the taken "contribution seam" term (that is the in-process UI hook).](<redacted>.md) | Cloud Bongos / architecture |
178
+ | 0108 | [Instance composition topology — CONFIGURABLE-ROOT: the core is consumed as a versioned npm dependency (task [#1870](https://example.com/builders#/task/1870), BV1.R115). Resolves the composition MECHANISM that [ADR 0062](<redacted>.md) §10 / [ADR 0100](<redacted>.md) §1 / [ADR 0103](<redacted>.md) §2 each left open (they are mechanism-neutral — "installs a pinned core + layers on top"; 0103's R88 record deferred "the topology/instance paths the scaffold populates on `init`"). A 2026-07-03 owner review chose configurable-root over the earlier clone-and-layer draft, weighting SCALABILITY over least-resistance: upgrades = O(1)-per-instance version bump (not O(instances×drift) merges); the boundary is enforced by the PACKAGE (can't rot under many agents) not convention+CI; a dependency forces a real core API; instance repos stay small; "root is a parameter" is the precondition for multi-instance/hosted. Decisions: (1) core installed as `@bongos/core`, host content resolved via an injected instance-root — two resolvers `resolveInstanceRoot()`/`resolveCoreRoot()` in the existing `src/instance-config.js`, defaulting to repo-root TODAY (byte-identical) and flipping `resolveCoreRoot()` to `node_modules` when packaged, no further per-site edits; the two directions are OPPOSITE (config→instance-root; the `infra/` installers `serve-internal` serves→core-root); (2) `package-core` emits a real `package/`-rooted npm package (`main`→platform-server, `bin`→bongos, deps pruned to express/pg/undici), `isPublishable()` stays the single core definition; (3) `.claude/` is MATERIALIZED into the instance by `bongos init`/`upgrade` (Claude Code reads it from the project root, never node_modules) + the ~30 skills/hooks rewritten `node scripts/gds/…`→`bongos …` (skills already ship in-core; hooks+settings are already "topology"); (4) `bongos upgrade` (R86) is an npm version bump, deploy flips `git reset --hard`→`npm ci` (Docker/`platform-server`/`selfhost-boot` already model it); (5) cross-repo migration numbering gets a namespacing + lineage discipline (two repos both adding `NNN_*.sql` collide on the shared `schema_migrations` stem key); (6) land Mercury-first — step-1 resolvers now (zero-change), package+`.claude` prove on greenfield R85, Example splits last (R89) with the trust-boundary path sites + the two-root guardrail fix (fitness.js/gen-repo-map/gen-file-map all hardcode REPO_ROOT) behind a security review. Runtime-library half is SMALL/de-risked (~8–11 readers; entrypoint seam `mountInternalSurfaces`/`buildPlatformApp`, two-roots loader, single-sourced partition already exist); the real work is delivery+ops (§3/§4/§5) — the accepted "more pain now". Clone-and-layer/submodule/monorepo rejected. Informs R85 ([#1689](https://example.com/builders#/task/1689)), R86 ([#1690](https://example.com/builders#/task/1690)), R89 ([#1728](https://example.com/builders#/task/1728)). Docs amended (not superseded): file-map, architecture, packaging-the-core + self-host recipes, ADR 0105, modules-contract; cross-refs in 0062/0100/0103/0098/branding-contract/CLAUDE.md. No migration, no new criterion; goal 26.](<redacted>.md) | Cloud Bongos / architecture |
179
179
  | 0109 | [The GDS API is self-describing — a standards-compliant **OpenAPI 3.1** spec generated from the live route files + a hosted `/docs` site (task [#1918](https://example.com/builders#/task/1918), BONGOS-V1, Part A of the API-docs + `/api/gds`→`/api/bongos` rename). Replaces the hand-maintained, drifted `docs/routes-permissions.md` with `scripts/gds/gen-api-docs.js`, which reuses the SAME `route-rank-check.js` introspection the ship-time rank gate ([ADR 0016](<redacted>.md)) uses — so the docs enumerate exactly the routes the server mounts and cannot drift (the [ADR 0063](<redacted>.md) generate-and-`--check` pattern). Emits `docs/api/openapi.json` (each op carries its rank in `x-rank` + a `security` ref, path params, and best-effort request-body fields from the `validateOrRespond` schema; undocumented bodies are counted) + a generated `docs/api-reference.md`. A vendored Redoc bundle renders it at `/docs` on every instance's apex (`cloudbongos.com/docs` canonical), served from the SHARED `mountInternalSurfaces` so a self-hosted instance is self-documenting for free; `GET /api/gds` returns a machine-discovery index and the 404 hint names `/docs`. Introduces the single `src/bongos/api-prefix.js` prefix constant that Part B flips to `/api/bongos`. Freshness enforced by `gen-api-docs --check` in `fitness.js` + ship-time regen; full standard lint via `npm run docs:api:lint` (`@redocly/cli`, off the critical path). Rejected: annotation-based/hand-written specs (drift), CDN renderer (self-host convention/air-gap), redocly as a hard CI dep (lean project).](<redacted>.md) | GDS / API docs |
180
180
  | 0110 | [Move whole-file generated navigation docs off the git graph (task [#1926](https://example.com/builders#/task/1926), BONGOS-V1, goal 24 build-pipeline-integrity). `docs/repo-map.md` (ADR 0063) + `docs/session-log-index.md` (ADR 0062 §8) were regenerated + **committed on every ship**, so parallel builder branches collided on them constantly (the [ADR 0082](<redacted>.md) reactive heal only cleans up after the fact). Applies the blessed `gen-atlas.js`/`atlas.json` precedent ([ADR 0094](<redacted>.md)): **gitignore** both whole files + regenerate them SERVER-SIDE at deploy (`deploy-prod.sh`, LOUD on failure → goal-24 `gcarry-pipe-loud`) and at `box-source-fetch` — a file not in git can never appear in a branch diff, so the conflict class is gone AT THE SOURCE. Both generators are DUAL-DUTY (each also refreshes a tracked block — the nested `CLAUDE.md` symbol blocks / the `CLAUDE.md` §13 snippet), so the CI freshness gate is SPLIT: `gen-*.js --check-block` (tracked block, still HARD) vs `--check-whole` (the gitignored file, no longer gated) — the adversarial-review fatal flaw was that the old single `--check` bundled both, so a naive relax would silently drop the block gate. `ship.js` drops the gitignored paths from its `git add` (an explicit `git add <ignored>` aborts the commit). Reactive heal (`git-merge-regen`, `.gitattributes`, ADR 0082 resolver) KEPT unchanged as a transition backstop; trust boundary untouched (no bot commits to main; no `.github/workflows/` change). Deferred to follow-ups: the OpenAPI spec (external consumers → bounded regen bot) + diagram renders (headless Chromium). Accepts: whole files fresh only post-deploy, not at merge.](<redacted>.md) | Build pipeline / generated artifacts |
181
- | 0111 | [Instance hosting + domains as a Cloud Bongos module — spec of the new **`provisioning`** module boundary + the **self-host vs managed** split (task [#1485](https://example.com/builders#/task/1485), BONGOS-V1 goal 26; consolidates owner ideas [#345](https://example.com/builders#/idea/345) + [#303](https://example.com/builders#/idea/303)). Standing up a Cloud Bongos instance still leaves an irreducibly-manual infra checklist (`bongos init` files it as kickoff tasks); this ADR specs the module that automates it. **Distinct from [ADR 0092](<redacted>.md)'s `hosting`** (that brokers compute/storage *workloads*; this provisions an *instance's own* server/DB/domain/DNS/TLS) — takes the free key `provisioning` to avoid the collision. Decisions: (1) a portable `default:false` `provisioning` module owns only the web-tier request/state surface (`provisioning_instances`/`_intents`/`_events`, own+Archon rank-gated routes, a `provisioning.instanceState` port) — it holds **no** cloud tokens; (2) the web tier only **enqueues intents**, a new control-plane CLI `scripts/gds/provision.js` (sibling of `box.js`, sole token-holder, systemd-timer-drained, idempotent/dry-run-default) executes them — the [ADR 0031](<redacted>.md)/[ADR 0016](<redacted>.md) box precedent, with the DO+Cloudflare clients extracted to a shared control-plane location so `box.js`+`provision.js` reuse them without a module→module import; (3) provisioning composes the [`cloudbongos-standup.md`](../recipes/cloudbongos-standup.md) runbook (server co-tenant-or-droplet → DB → migrate → env → service → DNS → TLS → Caddy), with GitHub-OAuth-app + first-sign-in demarcated as guided/manual; (4) **bring-your-own-domain first** (registrar-API purchase deferred) + **Caddy on-demand ACME TLS** for new hosts (removes the manual Cloudflare Origin-Cert leg; existing apexes keep theirs); (5) **self-host and managed run the identical `@cloudbongos/core` artifact** ([ADR 0108](<redacted>.md)) — the only differences are *whose* credentials the control plane holds and *who* operates it; managed = self-host + <redacted> infra + a central fleet control plane driving the same `bongos upgrade` channel, AGPL unchanged ([ADR 0065](<redacted>.md) §2, no open-core); (6) cheapest-first cost DNA (co-tenant $0 → dedicated droplet only when justified; snapshot-park idle; billing deferred); (7) self-host arm buildable now on the shipped configurable-root substrate, managed arm gated on R85 Mercury ([#1689](https://example.com/builders#/task/1689)) + R86 upgrade channel ([#1690](https://example.com/builders#/task/1690)). Seeds 8 follow-up tasks via `scripts/gds/seed-provisioning-tasks.js`.](<redacted>.md) | Cloud Bongos / architecture |
181
+ | 0111 | [Instance hosting + domains as a Cloud Bongos module — spec of the new **`provisioning`** module boundary + the **self-host vs managed** split (task [#1485](https://example.com/builders#/task/1485), BONGOS-V1 goal 26; consolidates owner ideas [#345](https://example.com/builders#/idea/345) + [#303](https://example.com/builders#/idea/303)). Standing up a Cloud Bongos instance still leaves an irreducibly-manual infra checklist (`bongos init` files it as kickoff tasks); this ADR specs the module that automates it. **Distinct from [ADR 0092](<redacted>.md)'s `hosting`** (that brokers compute/storage *workloads*; this provisions an *instance's own* server/DB/domain/DNS/TLS) — takes the free key `provisioning` to avoid the collision. Decisions: (1) a portable `default:false` `provisioning` module owns only the web-tier request/state surface (`provisioning_instances`/`_intents`/`_events`, own+Archon rank-gated routes, a `provisioning.instanceState` port) — it holds **no** cloud tokens; (2) the web tier only **enqueues intents**, a new control-plane CLI `scripts/gds/provision.js` (sibling of `box.js`, sole token-holder, systemd-timer-drained, idempotent/dry-run-default) executes them — the [ADR 0031](<redacted>.md)/[ADR 0016](<redacted>.md) box precedent, with the DO+Cloudflare clients extracted to a shared control-plane location so `box.js`+`provision.js` reuse them without a module→module import; (3) provisioning composes the [`cloudbongos-standup.md`](../recipes/cloudbongos-standup.md) runbook (server co-tenant-or-droplet → DB → migrate → env → service → DNS → TLS → Caddy), with GitHub-OAuth-app + first-sign-in demarcated as guided/manual; (4) **bring-your-own-domain first** (registrar-API purchase deferred) + **Caddy on-demand ACME TLS** for new hosts (removes the manual Cloudflare Origin-Cert leg; existing apexes keep theirs); (5) **self-host and managed run the identical `@bongos/core` artifact** ([ADR 0108](<redacted>.md)) — the only differences are *whose* credentials the control plane holds and *who* operates it; managed = self-host + <redacted> infra + a central fleet control plane driving the same `bongos upgrade` channel, AGPL unchanged ([ADR 0065](<redacted>.md) §2, no open-core); (6) cheapest-first cost DNA (co-tenant $0 → dedicated droplet only when justified; snapshot-park idle; billing deferred); (7) self-host arm buildable now on the shipped configurable-root substrate, managed arm gated on R85 Mercury ([#1689](https://example.com/builders#/task/1689)) + R86 upgrade channel ([#1690](https://example.com/builders#/task/1690)). Seeds 8 follow-up tasks via `scripts/gds/seed-provisioning-tasks.js`.](<redacted>.md) | Cloud Bongos / architecture |
182
182
  | 0112 | [Private goals — a `visibility` flag (`public` default \| `private`) + a two-sided `goal_membership_requests` queue (task [#1951](https://example.com/builders#/task/1951), BONGOS-V1). A goal manager can make a goal **private**; on a private goal non-members can't self-join — they are **invited** (a consented, pending row the invitee accepts from their inbox — distinct from the immediate `POST /goals/:id/members` add, kept byte-identical) or they **request** to join, approved by the goal's owner/manager/Archon (the [ADR 0106](<redacted>.md) `authorizeGoalManagement` wall reused wholesale). Both directions are one `goal_membership_requests` table keyed by `kind ∈ {invite, request}`, `status ∈ {pending, accepted, rejected, cancelled}`, with a **partial-unique `(goal_id, builder_id) WHERE status='pending'`** (the `access_requests` precedent — one open ask per person+goal). `GET /goals/inbox` returns each builder's actionable slice — invitations to them + join-requests on goals they own/manage + their own outstanding requests — powering a **home-page inbox**. **Private = join-gated, not hidden** (owner decision): a private goal still shows its title + progress; true concealment would need its own ADR. Purely additive (default `public` = today's open-join, unchanged) + revertible; ships in four phases (schema/db → routes → goals-page UI → home inbox). Rejected: fully-hidden goals (large filter surface for the stated intent), invite-as-force-add (owner asked for accept-from-inbox), two separate tables (shared lifecycle + mutual-exclusion index), requests on public goals (redundant — just join).](<redacted>.md) | GDS / goal hierarchy |
183
183
  | 0113 | [Per-builder art sandbox (task [#885](https://example.com/builders#/task/885)): descope to the sprite/animation Studio only. Task 885's 8-part breakdown (walkable offline preview, static sandbox server + systemd unit, `cf-tunnel.js` multi-ingress, box-provisioning wiring, reset-to-main script, retire staging) went stale on two axes: (1) Parts A1/B were already shipped, one day after 885 was filed, under [ADR 0044](<redacted>.md) (real degraded-DB game server at `sandbox-<login>.example.com` over the existing box tunnel) + [ADR 0052](<redacted>.md) (game-only entry, every rank) — a better design than the static-file/offline-mode one 885 proposed; (2) the touches\[\] paths point at pre-carve locations (`public/game/...`, `src/bongos/cf-tunnel.js`, `src/bongos/routes/box.js`) that moved to `modules/game/...`/`scripts/gds/cf-tunnel.js`/`modules/dev-box/...` under the ADR 0083/0093 module carve. Part C (retire staging) also contradicts the standing 2026-05-29 defer-not-delete decision in `docs/recipes/staging-environment.md`. Keeps only the Studio — a sprite/animation reviewer at `/studio`, layered onto the *existing* sandbox as a static page under `modules/game/public/` (the `/art` gallery precedent in `src/preview-server.js`; no new server/tunnel/unit) that auto-discovers sprites from `manifest.json` and extracts the right-facing mirror logic from `Player.js` into a shared `spriteFacing.js` — filed as one new child task instead of re-minting the stale 8.](<redacted>.md) | Builder experience / dev box |
184
184
  | 0114 | [Instance docs-discovery contract — pins how an agent locates its doc surfaces from config alone, with no hard-coded host. Three layers: (1) `config/branding.json` `domains.{publicOrigin,buildersOrigin,statusOrigin}` is the source of truth — the hall is the canonical doc-reading surface, `/docs` on `publicOrigin` renders the API reference, the status page is the off-box outage fallback; (2) `GET <publicOrigin>/api/bongos` (the machine-discovery index, + permanent `/api/gds` alias) is the zero-config entry point and now re-advertises `hall`/`status`/`public` from `branding().domains` so a second instance bootstraps its surfaces from a single unauthenticated call; (3) a resolution order for agents. Formalizes existing keys (no new required field); CLAUDE.md's preamble references it instead of hand-waving one config key.](<redacted>.md) | Portability / docs-discovery |
@@ -187,11 +187,11 @@ This keeps the decision history honest and traceable.
187
187
  | 0117 | [API versioning + deprecation policy — the policy (R05) for goal 36's `api-versioning` criterion (task [#1992](https://example.com/builders#/task/1992), BONGOS-V1). The API (212 endpoints at `/api/bongos` + permanent `/api/gds` alias) had no version marker, no breaking-change definition, no deprecation window — any change could silently break a self-hoster/shipped Dev Box binary/status dashboard. Decision: (1) an explicit path segment `/api/bongos/v1/…` is the **contract** version, distinct from `info.version` (the package semver); (2) today's unversioned paths become **permanent aliases pinned to v1** — the load-bearing rule is *an unversioned path never silently jumps major versions*, so when v2 mounts at `/v2/` the alias stays on v1 and breaking changes reach only opted-in callers; (3) breaking = remove/rename/retype a field/endpoint/error-code, new required field, tightened validation, narrowed auth, changed default — non-breaking = additive fields/endpoints/optional-params + new error codes *within an existing ADR-0116 category*; (4) a superseded version lives **≥180 days** with RFC 8594 `Deprecation`/`Sunset` headers, the unversioned alias exempt (permanent); (5) the version is discoverable via OpenAPI `servers` + `x-api-version` + the machine-discovery index + `/docs`. **Policy only** — R06 ([#1993](https://example.com/builders#/task/1993)) mounts `/v1` + aliases the unversioned paths (day-one no-op). Rejected: header-based versioning (invisible in URL, un-curl-able), semver-in-path (too fine), reusing the package semver (conflates build with contract), sunsetting the unversioned alias (breaks un-updatable binaries).](<redacted>.md) | API contract / goal 36 |
188
188
  | 0118 | [API contract source-of-truth: code-first, schema-as-data — the spike (R07) for goal 36 (task [#1994](https://example.com/builders#/task/1994), BONGOS-V1). Decision: STAY code-first; the per-route `validate()` schema object (already structured data: type/required/enum/length caps in `_helpers.js`) is the SINGLE source — the OpenAPI spec, runtime validation, and the typed client are all DERIVED from it, none hand-authored. `gen-api-docs.js` already generates the spec from route source (ADR 0109) but shallowly (212 endpoints; 76 write ops with a requestBody, 24 without; `components.schemas` empty); enrich `extractBody()` to emit full typed schemas from the validate() rules. One schema, three consumers (spec + validation + client) = single-source WITHIN code-first, no drift. Refines R08 (enrich generator → generate+publish client), R09 (migrate callers — also repairs the R04 flat-error reads), R10 (external on-ramp), R11 (reject unknown fields + query params, same schema), R12 (build check: write route ⇒ spec-bound schema). Rejected: schema-first (rewrite the whole 212-endpoint route layer), hand-maintained spec (drift, per ADR 0109), framework swap to Fastify/tRPC (too invasive).](<redacted>.md) | API contract / goal 36 |
189
189
  | 0119 | [API pagination contract — the contract (R13) for goal 36's `api-pagination` criterion (task [#2000](https://example.com/builders#/task/2000), BONGOS-V1). Three styles coexisted (limit-only, limit+offset, none) and some public lists (leaderboard, blockers, versions) returned everything (unbounded = cost/DoS surface). Decision: ONE convention — `?limit=&offset=` through a shared `parsePagination(req,{defaultLimit,maxLimit})` helper in `_helpers.js`: limit default 50 / hard-cap 200 (so no list is unbounded), offset default 0, bad/oversized values CLAMPED not rejected (list reads stay forgiving — the strict counterpart is write-validation R11). Response convention `{ items, page:{ limit, offset, total? } }` via `pageMeta()`. Chose limit/offset over cursor (already the in-use style, no opaque-token/stable-sort infra, trivial to curl; cursor left as a per-endpoint escape hatch for churning lists). Opt-in/non-breaking today; R14 ([#2001](https://example.com/builders#/task/2001)) adopts it across every list + caps the unbounded public lists. Rejected: cursor-as-default (disproportionate), page-number (awkward), leaving lists unbounded (the problem), 400-on-bad-limit (a read should be forgiving).](0119-api-pagination-contract.md) | API contract / goal 36 |
190
- | 0120 | [Pay drachmae on land (not on confirm) + a builder-owned rebase gate (task [#2035](https://example.com/builders#/task/2035), BONGOS-V1). Credits were awarded at the `confirmed` transition — before the code is on `main` — so stranded/never-pushed work paid out with no consequence, and the builder (the only one who can rebase it) had no reason to. Decision: (1) move BOTH the per-task credit AND the cost-plus session reward to the `shipped` (merged-to-`main`) transition; (2) the publish-reconciler flags a confirmed task `needs_rebase` (attributed to the claim holder) once auto-land is exhausted — merge conflict, failing required check vs current `main`, or no pushed branch; (3) a `needs_rebase` task blocks that builder's NEW claims (`REBASE_REQUIRED`) but not their existing/in-flight ones; (4) a one-time migration claws back the `task.confirmed` credits on the current confirmed backlog and re-gates it. Happy path unaffected (a clean PR auto-lands in minutes and pays then); the teeth bite only on stranding. Rejected: gate-only (stranded work still paid), soft-warn (ignorable), grandfather the backlog (leaves today's stranded-and-paid state), per-task-credit-only (owner chose fullest alignment).](<redacted>.md) | economy + lifecycle |
190
+ | 0120 | [Pay example on land (not on confirm) + a builder-owned rebase gate (task [#2035](https://example.com/builders#/task/2035), BONGOS-V1). Credits were awarded at the `confirmed` transition — before the code is on `main` — so stranded/never-pushed work paid out with no consequence, and the builder (the only one who can rebase it) had no reason to. Decision: (1) move BOTH the per-task credit AND the cost-plus session reward to the `shipped` (merged-to-`main`) transition; (2) the publish-reconciler flags a confirmed task `needs_rebase` (attributed to the claim holder) once auto-land is exhausted — merge conflict, failing required check vs current `main`, or no pushed branch; (3) a `needs_rebase` task blocks that builder's NEW claims (`REBASE_REQUIRED`) but not their existing/in-flight ones; (4) a one-time migration claws back the `task.confirmed` credits on the current confirmed backlog and re-gates it. Happy path unaffected (a clean PR auto-lands in minutes and pays then); the teeth bite only on stranding. Rejected: gate-only (stranded work still paid), soft-warn (ignorable), grandfather the backlog (leaves today's stranded-and-paid state), per-task-credit-only (owner chose fullest alignment).](<redacted>.md) | economy + lifecycle |
191
191
  | 0117 | [API versioning + deprecation policy — the policy (R05) for goal 36's `api-versioning` criterion (task [#1992](https://example.com/builders#/task/1992), BONGOS-V1). The API (212 endpoints at `/api/bongos` + permanent `/api/gds` alias) had no version marker, no breaking-change definition, no deprecation window — any change could silently break a self-hoster/shipped Dev Box binary/status dashboard. Decision: (1) an explicit path segment `/api/bongos/v1/…` is the **contract** version, distinct from `info.version` (the package semver); (2) today's unversioned paths become **permanent aliases pinned to v1** — the load-bearing rule is *an unversioned path never silently jumps major versions*, so when v2 mounts at `/v2/` the alias stays on v1 and breaking changes reach only opted-in callers; (3) breaking = remove/rename/retype a field/endpoint/error-code, new required field, tightened validation, narrowed auth, changed default — non-breaking = additive fields/endpoints/optional-params + new error codes *within an existing ADR-0116 category*; (4) a superseded version lives **≥180 days** with RFC 8594 `Deprecation`/`Sunset` headers, the unversioned alias exempt (permanent); (5) the version is discoverable via OpenAPI `servers` + `x-api-version` + the machine-discovery index + `/docs`. **Policy only** — R06 ([#1993](https://example.com/builders#/task/1993)) mounts `/v1` + aliases the unversioned paths (day-one no-op). Rejected: header-based versioning (invisible in URL, un-curl-able), semver-in-path (too fine), reusing the package semver (conflates build with contract), sunsetting the unversioned alias (breaks un-updatable binaries).](<redacted>.md) | API contract / goal 36 |
192
192
  | 0116 | [API error envelope + code taxonomy — the contract (R01) for goal 36's `api-error-envelope` criterion (task [#1988](https://example.com/builders#/task/1988), BONGOS-V1). An audit found **352 distinct `error:'…'` string literals** returned across 400/401/403/404/409/413/422/429/500/502/503 in ~4 different response shapes — a caller cannot write one error-handling path. Decision: **one envelope everywhere** — `{error:{code,message,details?}}` — where the specific `code` slug is **preserved** (a caller keying on `task_not_found` keeps working) and the 352 codes **collapse by category, not by discard**. A kernel registry `src/bongos/api-errors.js` defines ~12 canonical categories (each with a default HTTP status + `retriable` flag) and a pure/total `classify(code)` — an `OVERRIDES` table for the ~90 exceptions (auth codes, preconditions-as-conflicts, `*_too_large`) plus a suffix/prefix heuristic for the long tail (`*_failed`→internal, `*_not_found`→404, `bad_*`/`*_required`→400, `already_*`/`*_taken`→409, `*_unconfigured`→503); an unknown/future code falls back to `internal` (500). Ships the `ApiError` carrier + `envelope()` formatter + `statusForCode(code,override)` (a site keeps its current status; the sweep changes shape, not status). **Contract-only — nothing imports it yet, zero behaviour change.** R02 ([#1989](https://example.com/builders#/task/1989)) wires the middleware + `res.fail()`; R03 ([#1990](https://example.com/builders#/task/1990)) fails the build on a new hand-rolled flat error; R04 ([#1991](https://example.com/builders#/task/1991)) sweeps the ~219 handlers behind that gate. Rejected: flat `{error,message}` (today's mess, no room to grow), numeric codes (opaque), collapsing to 12 codes only (loses signal, breaks callers), per-module registries (defeats "one shape").](<redacted>.md) | API contract / goal 36 |
193
193
  | 0122 | [Onboarding diagram renders: untracked + rendered at deploy from a host-provisioned Chrome (task [#2027](https://example.com/builders#/task/2027), BONGOS-V1) — completes the diagram half [ADR 0110](<redacted>.md) deferred. The `.svg`/`.png` renders were committed on every render-capable ship and kept colliding on parallel branches; ADR 0110 deferred them because `mermaid-cli`/puppeteer downloads its own Chromium on first run (a multi-minute fetch that stalls the 2 GB droplet). Decision: provision Google Chrome once on the host; `render-diagrams.sh` auto-detects an installed browser (or honors `PUPPETEER_EXECUTABLE_PATH`) and sets `PUPPETEER_SKIP_DOWNLOAD` so it never fetches (falls back to the download only on a dev laptop), passing a committed `puppeteer-config.json` with `--no-sandbox` (Ubuntu 24.04 restricts unprivileged user namespaces) and pinning `mermaid-cli@11`; deploy-prod.sh + box-source-fetch render from the tracked `.mmd` (LOUD `::ERROR::`, best-effort); `git rm --cached` + gitignore the `*.svg`/`*.png` (the `.mmd` + `assertions.json` stay tracked, so the nightly diagram-drift cron is unaffected); ship runs `gen-diagrams --no-render`. Verified rendering all 5 diagrams on the prod droplet before landing. Rejected: on-deploy Chromium download (the droplet stall), snap chromium (flaky headless), keep-tracked + strengthen the ADR 0082 resolver (hides the collision).](<redacted>.md) | internal / ADR 0110 |
194
- | 0121 | [Greenfield vs. brownfield onboarding — scope `bongos init --adopt` (task [#1986](https://example.com/builders#/task/1986), BONGOS-V1, goal 35's `adopt-existing-repo` criterion). Today the creation flow is greenfield-only: `scripts/gds/init.js` opens *"stand up a NEW instance"*, refuses to run where `config/branding.json` exists (`--force` overwrites), and seeds a synthetic `"V1 — Prove the loop"`; it inspects nothing about an existing tree. Decision: TWO explicit modes over goal 35's one canonical step sequence (task 1981), branching at exactly the SCAFFOLD leg — greenfield (`bongos init`, today) vs brownfield (`bongos init --adopt`); every other leg (provision, OAuth, verify, brand) identical, so the CLI (1982) + hall wizard (1983) forms inherit adopt for free. `--adopt` must: (1) LAYER not clobber — add the pinned `@cloudbongos/core` dep + lean `config/` + `.claude/` additively, merge-or-report on pre-existing files, never reuse the `--force`-overwrites path; (2) reflect REAL state — capture the repo's actual version/goal instead of the synthetic V1, import the existing backlog (GitHub issues / TODO / roadmap) into GDS tasks; (3) DETECT the existing stack + layout so modules / repo-map / fitness-boundary fit; (4) a CONFLICT PRE-FLIGHT report (migration namespace, fitness boundary, protected-path / rank gates, existing CI), `--dry-run` default, gated behind an accept step. Scope-only — no adopt code ships; seeds a 5-task dependency-wired breakdown. Rejected: overloading `--force` to merge (footgun), a separate `bongos adopt` command (leg duplication / drift), auto-import with no pre-flight, building adopt-mode now (1986 is scope-only).](<redacted>.md) | Cloud Bongos / onboarding |
194
+ | 0121 | [Greenfield vs. brownfield onboarding — scope `bongos init --adopt` (task [#1986](https://example.com/builders#/task/1986), BONGOS-V1, goal 35's `adopt-existing-repo` criterion). Today the creation flow is greenfield-only: `scripts/gds/init.js` opens *"stand up a NEW instance"*, refuses to run where `config/branding.json` exists (`--force` overwrites), and seeds a synthetic `"V1 — Prove the loop"`; it inspects nothing about an existing tree. Decision: TWO explicit modes over goal 35's one canonical step sequence (task 1981), branching at exactly the SCAFFOLD leg — greenfield (`bongos init`, today) vs brownfield (`bongos init --adopt`); every other leg (provision, OAuth, verify, brand) identical, so the CLI (1982) + hall wizard (1983) forms inherit adopt for free. `--adopt` must: (1) LAYER not clobber — add the pinned `@bongos/core` dep + lean `config/` + `.claude/` additively, merge-or-report on pre-existing files, never reuse the `--force`-overwrites path; (2) reflect REAL state — capture the repo's actual version/goal instead of the synthetic V1, import the existing backlog (GitHub issues / TODO / roadmap) into GDS tasks; (3) DETECT the existing stack + layout so modules / repo-map / fitness-boundary fit; (4) a CONFLICT PRE-FLIGHT report (migration namespace, fitness boundary, protected-path / rank gates, existing CI), `--dry-run` default, gated behind an accept step. Scope-only — no adopt code ships; seeds a 5-task dependency-wired breakdown. Rejected: overloading `--force` to merge (footgun), a separate `bongos adopt` command (leg duplication / drift), auto-import with no pre-flight, building adopt-mode now (1986 is scope-only).](<redacted>.md) | Cloud Bongos / onboarding |
195
195
  | 0123 | [Idle-swept dev boxes lose uncommitted work: an on-box autosave-push, not a VM snapshot (task [#837](https://example.com/builders#/task/837) SPIKE). `box.js`'s idle sweep hard-deletes the droplet once a box reads idle — nothing on that path checks git status, and park's snapshot was deliberately removed from the automated path for cost. Decision: a new on-box cron (sibling to `box-heartbeat.sh`) that, when `/workspace` is dirty, commits + pushes to the box's own `claude/<name>` claim branch using the same one-shot-credentialed-then-scrubbed pattern `box-source-fetch.sh` already uses for fetch — bounding loss to the autosave interval (~5 min) instead of unbounded. Open dependency: confirm/mint a push-scoped box credential (today's `BOX_SOURCE_FULL_TOKEN` is fetch-only by convention). Rejected: reintroducing snapshot-before-destroy (the exact cost the team removed), a control-plane git-status check before sweep (needs new box-exec capability, would pin dirty boxes active forever), relying on `/builder-end`'s manual dirty-check alone (doesn't fire on the automatic sweep path at all). Scope-only — no autosave code ships; seeds a follow-up implementation task.](<redacted>.md) | internal / dev-box |
196
196
  | 0124 | [Typed API response bodies — follow-up to ADR 0118 for goal 36's `api-client-sdk` (task [#2061](https://example.com/builders#/task/2061), from idea 519, BONGOS-V1). Task 2050 typed every request body but success RESPONSES stayed the `ApiResponse` (`= any`) alias — routes declare no response schema. Decision: infer the success shape STATICALLY from each route's inline `res.json({ … })` object literal (reusing the request extractor's `captureBalanced`/`splitTopLevel` machinery; never executes a route) → a `<OperationId>Response` component on the `200` `content`, and the client returns `Promise<ThatShape>`. Only KEYS are provable (values type `unknown` unless trivially safe — a boolean literal, or the ADR-0119 `pageMeta()` `page` block → a shared `PageInfo`). Degrade-gracefully: a bare value (`res.json(row)`), a top-level spread, an empty `{}`, or a computed key keeps `ApiResponse` — we only ever narrow `any`, never mistype. 162/221 endpoints now typed; runtime JS unchanged (only `openapi.json` + `index.d.ts`). Rejected: a per-route `responseSchema` export (duplicates the `res.json` truth + 200-file churn, anti-code-first), executing routes to observe responses (breaks the zero-execution contract), tracing variables to type values (brittle data-flow analysis), `additionalProperties:false` on responses (a false compile error if an unparsed branch adds a key).](<redacted>.md) | API contract / goal 36 |
197
197
  | 0125 | [The control plane scaffolds + pushes a standalone instance's repo (task [#2055](https://example.com/builders#/task/2055), BONGOS-V1, goal 35's `project-creation-flow`). `provision.js` used to THROW if a standalone instance's repo wasn't already hand-cloned at `/srv/cloudbongos/<slug>` — a manual dead-end between `bongos init` and provision. Decision: the provisioning runner SCAFFOLDS the repo itself (`scaffoldStandaloneRepo`) before the existing code-sync/db/service steps: clone the empty `target_ref` (forcing branch `main` on the unborn HEAD) → build the core tarball (`package-core.js`) → materialize `config/` + `.claude/` + a `file:`-pinned `package.json` + lockfile via `bongos init --vendor-core` (task 2053, `--no-seed`) → commit + push (with a `node_modules`-excluding `.gitignore`; vendored tarball + lockfile stay tracked). Idempotent (skips once `package.json` exists) + dry-run-safe (injected `exec`/`writeFile`). Git transport reuses the existing `github-deploy` SSH alias (no secret in any command) — the one operational grant is that the control plane's deploy key gets WRITE on each instance repo (per-repo, like the platform repo). `deploy-instance.sh` already existed at `scripts/deploy/` (ADR 0108 §4 / task 1884; the task description predated it) — it's the ongoing consumer deploy, not the first-time scaffold; no `infra/` duplicate created. Rejected: a control-plane PAT/App-token over HTTPS (token-leak risk in the URL + a new broad secret class — a GitHub App is the scalable follow-up), keeping the "clone it yourself first" throw (the dead-end itself), scaffolding from a template fork (a template repo to maintain vs `--vendor-core`'s single-source tree).](<redacted>.md) | Cloud Bongos / onboarding |
@@ -203,6 +203,10 @@ This keeps the decision history honest and traceable.
203
203
  | 0131 | [Rank-scoped skill visibility — feasibility spike (task [#1650](https://example.com/builders#/task/1650)). Wanted: a session lists only the skills the builder's rank can use, via a SessionStart hook filtering the skill menu — pure UX declutter (the server rank gate + each skill's early self-check still enforce). Finding: Claude Code hooks CANNOT filter/hide/rewrite the skill listing — SessionStart offers only `additionalContext` (inject text) + `reloadSkills` (add-only), no hook subtracts a skill, and hooks can't mutate settings at runtime. A HARD menu hide needs a pre-launch step (the launcher that already fetches rank) writing per-builder `skillOverrides:"off"` into `.claude/settings.local.json` before `claude` starts (misses plugin skills; workspace-trust-gated). Recommendation: don't build the heavy launcher change for a cosmetic gain; if some declutter is wanted now, use the existing hook's `additionalContext` as a soft nudge; keep the server gate + self-checks. Owner to decide.](<redacted>.md) | dx / skills |
204
204
  | 0132 | [Migrate the co-hosting fleet to the control plane over an SSH DB tunnel (task [#2071](https://example.com/builders#/task/2071), BONGOS-V1, goal 26; extends ADR 0130, completes 2065 / blocker 64). Stripping the co-hosting box's tokens proved NOT a switch-flip: it runs FIVE token-consuming timers (the 4 `box.js` dev-box lifecycle sweeps + `provision-intent-runner`), each reading its queue from the box's LOCAL `example` Postgres (firewalled to localhost) — so a control-plane runner can't reach the queues, and ADR 0130 moved only box-step execution, not queue reading. Also `box.js` was never migrated. Decision: a persistent SSH tunnel (control-plane `127.0.0.1:5433` → co-hosting `127.0.0.1:5432`, `infra/cohost-db-tunnel.service`) + all five runners re-homed as `cohost-*` control-plane variants reading the example queues via `DATABASE_URL` through the tunnel (no public Postgres exposure), calling DO/CF with the control-plane tokens; provisioning remote-execs box steps per ADR 0130. DB auth: a scram password on the EXISTING `lars` role (identical privileges the runners already use; reachable only via `127.0.0.1`), stored only in chmod-600 `/etc/cloudbongos/cohost-fleet.env`. `box.js` unchanged (pure DO/CF API + Discord/DNS-hook execs, all on the control plane). `cohost-provision-intent-runner.*` supersedes 2065's `provision-intent-runner-cloudbongos.*`. Rejected: exposing Postgres over the VPC (opens a TCP surface + `pg_hba`/cred work; droplets not guaranteed same-VPC); a token-signing broker on the co-hosting box (leaves tokens' blast radius there — opposite of the goal); moving the queue tables to the cloudbongos DB (the OTB web tier can't reach it either — firewall symmetry). Units ship additive + not-enabled, self-healed install-only. Activation (SSH trust · DB password · tunnel · enable `cohost-*` + disable co-hosting timers same window · verify via drift-reconcile · bake · owner token rotate+strip · drop rollback DB) is a sequenced operator-op.](<redacted>.md) | infra / Cloud Bongos |
205
205
  | 0133 | [One-click GitHub sign-in for onboarding via the GitHub App Manifest flow (task [#2080](https://example.com/builders#/task/2080), BONGOS-V1, goal 35 / criterion 165). The last onboarding friction was wiring GitHub sign-in — the owner had to hand-create an OAuth App + paste a client secret, unscriptable because GitHub has NO create-OAuth-App API. Decision: use GitHub's App **Manifest** flow. The signed-in owner clicks one pre-filled link; GitHub creates the App and returns a temporary `code`; the control-plane runner (`provision.js`, sole token-holder) exchanges it for `client_id`/`client_secret`, writes them to `/etc/<slug>/web.env` (the `oauth-secret.js` path), restarts, and verifies `/healthz` auth_configured — the secret never touches the browser, chat, or web tier. Spans the trust boundary: web tier mints a one-time `state` + stores a `provisioning_oauth_manifests` row + a PUBLIC callback stores GitHub's code (`state` is the auth); the control-plane runner drains `code_received` rows on its existing timer tick (gated on instance=active). Sign-in code unchanged — a GitHub App's user token hits the same `GET /user`; GitHub ignores the extra `scope` for Apps. Back-compat: existing OAuth-app instances untouched; manifest is the new default, manual path kept as fallback. All three onboarding surfaces (hall wizard one-click button, `bongos onboard`, `/new-project`) updated in lockstep.](<redacted>.md) | onboarding / auth |
206
- | 0134 | [Private-first npm distribution for the core + client (task [#2089](https://example.com/builders#/task/2089), BONGOS-V1, goal 35 / criterion 165; refines [#2025](https://example.com/builders#/task/2025), builds on ADR 0108). Owner wants the npm/CLI onboarding commands ready but private pre-launch, choosing paid private npm over free GitHub Packages. npm rule forces the shape: unscoped names are always public, only SCOPED packages can be private (paid plan) — so the private form stays scoped `@cloudbongos/core` + `@cloudbongos/client` (zero rename; org already owned). Decision: publish both as scoped PRIVATE packages now via `publishConfig:{access:"restricted"}` baked into the synthesized core `package.json` (`package-core.js buildPackageJson`) + the generated client `package.json` (`gen-api-client.js`); `package-core.js --publish` dry-runs by default, real publish needs `--publish --live` + owner `npm login` (tooling holds no token). Consumers auth via env-fed `.npmrc` `_authToken=<redacted> Vendored-tarball install (task 2053) stays the working default; provision/init registry auto-pull is a follow-up. Going public at launch is one flag (`npm access public`) or task 2025's unscoped vanity `cloudbongos` — 2025 becomes the go-public step, not superseded. The daily `bongos` command is name-independent throughout. Runbook: docs/recipes/private-npm-distribution.md.](<redacted>.md) | distribution / npm |
206
+ | 0134 | [Private-first npm distribution for the core + client (task [#2089](https://example.com/builders#/task/2089), BONGOS-V1, goal 35 / criterion 165; refines [#2025](https://example.com/builders#/task/2025), builds on ADR 0108). Owner wants the npm/CLI onboarding commands ready but private pre-launch, choosing paid private npm over free GitHub Packages. npm rule forces the shape: unscoped names are always public, only SCOPED packages can be private (paid plan) — so the private form stays scoped `@bongos/core` + `@bongos/client` (zero rename; org already owned). Decision: publish both as scoped PRIVATE packages now via `publishConfig:{access:"restricted"}` baked into the synthesized core `package.json` (`package-core.js buildPackageJson`) + the generated client `package.json` (`gen-api-client.js`); `package-core.js --publish` dry-runs by default, real publish needs `--publish --live` + owner `npm login` (tooling holds no token). Consumers auth via env-fed `.npmrc` `_authToken=<redacted> Vendored-tarball install (task 2053) stays the working default; provision/init registry auto-pull is a follow-up. Going public at launch is one flag (`npm access public`) or task 2025's unscoped vanity `cloudbongos` — 2025 becomes the go-public step, not superseded. The daily `bongos` command is name-independent throughout. Runbook: docs/recipes/private-npm-distribution.md.](<redacted>.md) | distribution / npm |
207
+ | 0135 | [Module upstream submission: the review queue lives in the submitting instance's own DB, interim (task [#1770](https://example.com/builders#/task/1770), BONGOS-V1, builds on ADR 0107). ADR 0107 §1 says `bongos module submit` files a packaged module into a rank-gated review queue "on the core" — but the extracted core (`github.com/example-owner/cloud-bongos`) is a private GIT REPO, not a running service (no HTTP API), and per ADR 0100 §3 each project runs its OWN GDS DB, so there is no shared cross-repo queue to file into; R85 (the forcing-function second consumer) was also abandoned. Decision: the queue is a table (`module_submissions`, migration `<redacted>.sql`) in THIS instance's own Bongos DB. `bongos module submit <key>` and the hall's submit button both call the SAME route, `POST /modules/:key/submit` (metic+archon), which re-runs the ADR 0107 §4 pre-check against its OWN on-disk copy (authoritative — a local CLI pass is a courtesy) and refuses without a sign-off; `GET /modules/submissions` lists the queue for task 1771 (core-side review & accept, still backlog) to read from. Rejected: a live call to a not-yet-built core endpoint (guesses at 1771's contract); a GitHub Issue/PR against the private core repo (loses the structured queue, no standing credential); a dry-run-only local-file client mirroring do-api.js (a worse queue than a DB table this instance already operates). Forward-compatible: when a real core endpoint exists, filing becomes a network hop with no change to the CLI/UI contract.](<redacted>.md) | modules / upstreaming |
208
+ | 0136 | [Update-channel subscription policy (task [#2150](https://example.com/builders#/task/2150), BONGOS-V1, goal 26; completes the update-consumption workstream on ADR 0100 §2 + ADR 0134 + task 2149). Answers "how do projects subscribe to regular @bongos/core updates?" with the owner-chosen policy: **patch-only by default, health-gated with auto-rollback, opt-in, autonomy-gated.** Per-instance `update_channel` = `pinned` (never) / `patch` (higher z within x.y — DEFAULT) / `minor` (higher y within the major); a MAJOR is never automatic, prereleases never auto-targeted — the pure math is `scripts/gds/update-channel.js` (`resolveChannelTarget`), unit-tested in `tests/update_channel.mjs`. The registry (npm view, ADR 0134) is the "what's newest" source. A new `mode:deterministic` instance-wide routine `core-update-subscription` reads the opt-in roster `config/update-subscriptions.json` (ships EMPTY) and runs `bongos upgrade --to <v> --registry` per subscribed instance with auto-rollback ON (task 2149). Triple-gated: autonomy flag OFF by default (ADR 0115) + empty roster + health-gated. Upstream auto-publish (whether main merges auto-publish a patch) is deliberately SPLIT to its own follow-up task, so goal 26 closes on the consumption half; the subscription just consumes whatever the owner publishes. Scope is local same-host instances; multi-host fleet orchestration is the deferred fleet-control-plane epic (task 1948). Rejected: a `provisioning_instances` DB column (presumes the still-unbuilt fleet-registry schema; a config manifest is migration-free + ADR-0115-shaped), minor-by-default (less conservative), deciding auto-publish here (orthogonal, would block consumption).](<redacted>.md) | distribution / updates |
209
+ | 0137 | [Upstream publish policy: `@bongos/core` patches are published MANUALLY (owner-gated), NOT auto-published on merge (task [#2158](https://example.com/builders#/task/2158), BONGOS-V1, goal 26; the SUPPLY half split out of ADR 0136 §5 / task 2150, builds on ADR 0134). Owner chose manual over auto. Decision: the owner runs `package-core.js --publish --live` to cut a release (optional `core-v<version>` git tag as the auditable marker — triggers no CI); `CORE_VERSION` (src/module-api.js) is bumped by hand in-task with a changelog line (provenance stays in git, not a release-tool side effect); NO npm write-token at rest (preserves ADR 0134 tokenless tooling — owner auths at publish time; only the read token exists); the no-leak/mirror-redact gate is already fail-closed inside `package-core.js`, so `--publish` cannot upload a leaking artifact. The ADR 0136 subscription consumes whatever is published; freshness is owner-paced by design. Rejected: auto-publish-on-merge (needs a standing npm write-token as a CI secret — reverses the tokenless posture for little gain at low, deliberate release volume). Revisit as a tag-triggered CI publish when the managed-fleet epic (task 1948) makes the manual step a real bottleneck. Ritual: docs/recipes/private-npm-distribution.md "Cutting a core release".](<redacted>.md) | distribution / npm |
210
+ | 0138 | [A core-bundled module's external npm deps are declared per-module; the consumer composes them, core stays lean (task [#2160](https://example.com/builders#/task/2160), BONGOS-V1, goal 26; R89 cutover rehearsal finding F2, builds on ADR 0108 + ADR 0083). The discord module ships inside `@bongos/core` but `package-core.js` declares only express+pg, so a consumer that enables discord crashed at boot on missing `discord.js` (the only such case; discord is `default:false`). Owner chose lean-core over hoisting. Decision: core deps stay express+pg; a bundled module declares its own npm deps in `module.json` `dependencies` (schema-validated in `manifest-schema.js`; discord declares `discord.js`); greenfield `bongos init` composes the ENABLED modules' deps into the instance package.json (`enabledModuleDeps`→`buildInstancePackageJson`, existing pin wins, core always set); the R89 cutover preserves the monolith's existing closure ∪ core. Rejected: hoisting `discord.js` into core `optionalDependencies` (installs for EVERY consumer though discord is opt-in — cuts against ADR 0108 lean-core); `peerDependencies` (optional peers aren't auto-installed → crash remains; required peers = hoisting-with-warnings).](<redacted>.md) | modules / distribution |
207
211
 
208
212
  > ⚠️ **Numbering collision (known):** two ADRs share `0008`. The numbers were assigned in parallel sessions before the lock could be enforced. The files are kept under their existing filenames to preserve git history, but the table disambiguates them as `0008-a` / `0008-b`. New ADRs should resume at `0040` to avoid further collisions. (`0024` is also a real on-disk duplicate: the cloneable-repo/local-first-memory ADR and the multi-agent-system-architecture ADR were both numbered `0024` in parallel; both keep their filenames, disambiguated as `0024-a` / `0024-b` like `0008`. Likewise `0025` ended up with two on-disk files — the offsite-backup ADR and the structured-criterion↔task-link ADR — both kept under their existing filenames and disambiguated as `0025-a` / `0025-b`; separately, the BFG ADR had also claimed `0025` on 2026-05-30 and yielded to `0026`. A third happened 2026-06-06: `0036` was claimed in parallel by the builders-subdomain ADR ([#726](https://example.com/builders#/task/726)) and this Discord-channels ADR ([#727](https://example.com/builders#/task/727)); the Discord-channels ADR yielded to `0037`. A fourth landed 2026-06-10: `0044` was claimed in parallel by the palette-replacement ADR and the per-box game-preview ADR ([#897](https://example.com/builders#/task/897)); both keep their filenames, disambiguated as `0044-a` / `0044-b` like `0008`. A fifth was caught pre-land 2026-06-13: `0050` was claimed in parallel by the device-flow-admission ADR ([#1000](https://example.com/builders#/task/1000)) and the sandbox-for-everyone ADR ([#1001](https://example.com/builders#/task/1001)); the latter yielded to `0052` before merging, so there is no `0050` duplicate. A sixth was caught pre-land 2026-06-21: the tool-agnostic-design-layer ADR ([#1375](https://example.com/builders#/task/1375)) first collided at `0079` with the value-gated-autonomous-engagement ADR, then at `0080` with the llm-cache-api-transport ADR (both part of the 0075–0080 LLM-cost-reduction series, landed on `main` in parallel); it yielded to `0081` before merging, so there is no `0079`/`0080` design-layer duplicate. A seventh landed 2026-06-23: `0084` was claimed in parallel by the auto-derived-per-task-rank-floor ADR and the remove-default-spend-cap ADR (task 1499); the rank-floor ADR landed on `main` first, so the spend-cap ADR yielded to `0085`, leaving no `0084` duplicate. An eighth landed 2026-06-27: `0095` was claimed in parallel by the borrowed-memory-and-retrieval-concepts ADR (PR #459, landed first) and the cross-agent-context-management ADR ([#1651](https://example.com/builders#/task/1651), PR #460); both keep their filenames, disambiguated as `0095-a` / `0095-b` like `0008`. These two are companions — `0095-a` adopts the memory/retrieval concepts and explicitly defers the grep-vs-semantic question to `0095-b`.)