@bongos/core 1.17.1 → 1.17.3

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 (233) hide show
  1. package/.bongos-core.json +521 -281
  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/GOVERNANCE.md +1 -1
  15. package/README.md +1 -1
  16. package/clients/bongos-client/README.md +1 -1
  17. package/clients/bongos-client/bongos-client.global.js +2 -0
  18. package/clients/bongos-client/index.cjs +2 -0
  19. package/clients/bongos-client/index.d.ts +4 -2
  20. package/clients/bongos-client/index.mjs +2 -0
  21. package/docs/adr/0001-stack-choice-single-vps.md +1 -1
  22. package/docs/adr/0008-google-chat-oauth-user-auth.md +1 -1
  23. package/docs/adr/0019-red-team-bounty-payout-table.md +3 -3
  24. package/docs/adr/0020-security-model-public-stub.md +1 -1
  25. package/docs/adr/0023-kind-multipliers-and-idea-bonus.md +1 -1
  26. package/docs/adr/0024-cloneable-repo-local-first-memory.md +1 -1
  27. package/docs/adr/0026-bfg-memory-hygiene-and-cross-builder-learning.md +4 -4
  28. package/docs/adr/0027-bfg-session-inefficiency-evaluator.md +3 -3
  29. package/docs/adr/0030-builders-hall-live-updates.md +1 -1
  30. package/docs/adr/0031-cloud-dev-environments-for-builders.md +4 -4
  31. package/docs/adr/0032-discord-mirror-of-gds.md +2 -2
  32. package/docs/adr/0034-thetes-graduated-newcomer-rank.md +1 -1
  33. package/docs/adr/0044-mediterranean-palette-replacement.md +1 -1
  34. package/docs/adr/0044-per-box-live-game-preview.md +1 -1
  35. package/docs/adr/0054-session-token-reward-cost-plus.md +10 -10
  36. package/docs/adr/0057-container-cost-ledger.md +3 -3
  37. package/docs/adr/0062-medusa-instance-model-decoupling.md +4 -4
  38. package/docs/adr/0065-agpl-nonprofit-ai-first-governance.md +2 -2
  39. package/docs/adr/0085-remove-default-per-builder-spend-cap.md +1 -1
  40. package/docs/adr/0086-goal-scoped-work-hierarchy.md +1 -1
  41. package/docs/adr/0096-require-reward-before-workable.md +9 -9
  42. package/docs/adr/0097-retroactive-reward-backfill.md +3 -3
  43. package/docs/adr/0100-two-repo-instance-model.md +1 -1
  44. package/docs/adr/0101-goal-hierarchy-phase-5-judge-membership-reward.md +3 -3
  45. package/docs/adr/0103-core-first-extraction-cloud-bongos-trunk.md +3 -3
  46. package/docs/adr/0107-module-upstreaming-contribution-to-core-catalog.md +1 -1
  47. package/docs/adr/0120-pay-on-land-and-builder-owned-rebase-gate.md +6 -6
  48. package/docs/adr/0136-update-channel-subscription-policy.md +51 -0
  49. package/docs/adr/0137-upstream-publish-policy-manual-owner-gated.md +40 -0
  50. package/docs/adr/0138-bundled-module-deps-declared-per-module.md +45 -0
  51. package/docs/adr/README.md +9 -6
  52. package/docs/api/openapi.json +65 -26
  53. package/docs/api-reference.md +3 -2
  54. package/docs/architecture.md +2 -2
  55. package/docs/branding-contract.md +5 -4
  56. package/docs/canonical-permissions.md +1 -1
  57. package/docs/design/vanilla-hall-ui-redesign-scope.md +1 -1
  58. package/docs/file-map.md +18 -17
  59. package/docs/handoff-template.md +2 -2
  60. package/docs/modules-contract.md +6 -1
  61. package/docs/onboarding/diagrams/README.md +7 -7
  62. package/docs/onboarding/drachmae-and-karma.md +18 -18
  63. package/docs/onboarding/primer.md +9 -9
  64. package/docs/recipes/audit-replay.md +2 -2
  65. package/docs/recipes/builder-box-lifecycle.md +2 -2
  66. package/docs/recipes/claude-design-loop.md +1 -1
  67. package/docs/recipes/ops-gotchas.md +1 -1
  68. package/docs/recipes/private-npm-distribution.md +17 -0
  69. package/docs/recipes/staging-environment.md +1 -1
  70. package/docs/recipes/upgrading-the-core.md +55 -0
  71. package/docs/research/cursor-competitive-analysis.md +1 -1
  72. package/docs/research/llm-model-agnostic-and-cheaper-grader.md +1 -1
  73. package/modules/discord/module.json +2 -1
  74. package/modules/economy/achievements.js +9 -1
  75. package/modules/economy/credits.js +10 -1
  76. package/modules/hall-ui/public/builders.js +137 -620
  77. package/modules/hall-ui/public/goal-inbox.js +232 -0
  78. package/modules/hall-ui/public/goals-page.js +4 -1
  79. package/modules/hall-ui/public/goals.html +8 -0
  80. package/modules/hall-ui/public/hall-kit.js +474 -0
  81. package/modules/hall-ui/public/hall-widgets.js +14 -5
  82. package/modules/hall-ui/public/index.html +3 -0
  83. package/modules/hall-ui/public/instances-panel.js +24 -3
  84. package/modules/hall-ui/public/new-project-wizard.js +7 -5
  85. package/modules/hall-ui/public/style.css +168 -0
  86. package/modules/hall-ui/public/work.css +194 -0
  87. package/modules/hall-ui/public/work.html +46 -374
  88. package/modules/hall-ui/public/work.js +137 -102
  89. package/modules/lifecycle/criterion-suggest.js +80 -0
  90. package/modules/lifecycle/db.js +42 -5
  91. package/modules/lifecycle/routes/goals.js +26 -0
  92. package/modules/lifecycle/routes/tasks.js +21 -0
  93. package/modules/provisioning/CLAUDE.md +15 -0
  94. package/modules/provisioning/migrations/provisioning_001_tables.sql +160 -0
  95. package/modules/provisioning/migrations/provisioning_002_standalone_shape.sql +11 -0
  96. package/modules/provisioning/migrations/provisioning_003_github_app_manifest.sql +95 -0
  97. package/modules/provisioning/module.json +17 -0
  98. package/modules/provisioning/onboard-plan.js +37 -0
  99. package/modules/provisioning/provisioning.js +539 -0
  100. package/modules/provisioning/rate-limit.js +35 -0
  101. package/modules/provisioning/routes/provisioning.js +607 -0
  102. package/modules/provisioning/tests/provisioning.mjs +232 -0
  103. package/modules/provisioning/ui/.gitkeep +0 -0
  104. package/modules/security/secret-scrub.js +10 -0
  105. package/package-lock.json +2 -2
  106. package/package.json +7 -2
  107. package/scripts/discord/README.md +1 -1
  108. package/scripts/gds/claim.js +98 -48
  109. package/scripts/gds/claude-materialize.js +30 -9
  110. package/scripts/gds/cutover-codemod.js +241 -0
  111. package/scripts/gds/fitness.js +54 -0
  112. package/scripts/gds/init.js +59 -3
  113. package/scripts/gds/lint-infra-exec.js +70 -0
  114. package/scripts/gds/lint-workflow-exec.js +63 -0
  115. package/scripts/gds/mirror-lineage-check.js +14 -5
  116. package/scripts/gds/mirror-redact.js +8 -0
  117. package/scripts/gds/onboard.js +4 -0
  118. package/scripts/gds/package-core.js +18 -3
  119. package/scripts/gds/publish-manifest.js +60 -2
  120. package/scripts/gds/run-routine.js +51 -13
  121. package/scripts/gds/run-unit-tests.js +4 -0
  122. package/scripts/gds/update-channel.js +186 -0
  123. package/scripts/gds/upgrade.js +116 -9
  124. package/scripts/hall-preview/README.md +103 -0
  125. package/scripts/hall-preview/fixtures/access-requests.json +1 -0
  126. package/scripts/hall-preview/fixtures/achievements.json +76 -0
  127. package/scripts/hall-preview/fixtures/analytics__builder.json +251 -0
  128. package/scripts/hall-preview/fixtures/audit-log.json +1 -0
  129. package/scripts/hall-preview/fixtures/boxes__cost-ledger.json +1 -0
  130. package/scripts/hall-preview/fixtures/builders__active-claims.json +1 -0
  131. package/scripts/hall-preview/fixtures/builders__directory.json +81 -0
  132. package/scripts/hall-preview/fixtures/builders__roster.json +1 -0
  133. package/scripts/hall-preview/fixtures/goals.json +502 -0
  134. package/scripts/hall-preview/fixtures/goals__25.json +96 -0
  135. package/scripts/hall-preview/fixtures/goals__26.json +67 -0
  136. package/scripts/hall-preview/fixtures/goals__3.json +103 -0
  137. package/scripts/hall-preview/fixtures/goals__35.json +49 -0
  138. package/scripts/hall-preview/fixtures/goals__conflicts.json +154 -0
  139. package/scripts/hall-preview/fixtures/goals__detail.json +96 -0
  140. package/scripts/hall-preview/fixtures/goals__inbox.json +5 -0
  141. package/scripts/hall-preview/fixtures/goals__requests.json +3 -0
  142. package/scripts/hall-preview/fixtures/grades__by-builder.json +1 -0
  143. package/scripts/hall-preview/fixtures/inbox.json +330 -0
  144. package/scripts/hall-preview/fixtures/instance.json +124 -0
  145. package/scripts/hall-preview/fixtures/leaderboard.json +184 -0
  146. package/scripts/hall-preview/fixtures/me.json +476 -0
  147. package/scripts/hall-preview/fixtures/me__recent-ships.json +304 -0
  148. package/scripts/hall-preview/fixtures/override-requests.json +1 -0
  149. package/scripts/hall-preview/fixtures/provisioning__fleet.json +1 -0
  150. package/scripts/hall-preview/fixtures/provisioning__fleet__cost-ledger.json +1 -0
  151. package/scripts/hall-preview/fixtures/provisioning__instances.json +1 -0
  152. package/scripts/hall-preview/fixtures/public__analytics__ecosystem.json +516 -0
  153. package/scripts/hall-preview/fixtures/public__bounty-table.json +37 -0
  154. package/scripts/hall-preview/fixtures/public__cost-summary.json +742 -0
  155. package/scripts/hall-preview/fixtures/public__estimation-drift.json +41 -0
  156. package/scripts/hall-preview/fixtures/public__grades.json +50 -0
  157. package/scripts/hall-preview/fixtures/public__progress.json +124 -0
  158. package/scripts/hall-preview/fixtures/public__recent-shipped.json +426 -0
  159. package/scripts/hall-preview/fixtures/public__repo-health.json +160 -0
  160. package/scripts/hall-preview/fixtures/public__repo-info.json +5 -0
  161. package/scripts/hall-preview/fixtures/security__docs.json +1 -0
  162. package/scripts/hall-preview/fixtures/security__reports.json +1 -0
  163. package/scripts/hall-preview/fixtures/sessions__search.json +1 -0
  164. package/scripts/hall-preview/fixtures/tasks.json +2420 -0
  165. package/scripts/hall-preview/fixtures/tasks__claimable.json +2555 -0
  166. package/scripts/hall-preview/fixtures/tasks__detail.json +111 -0
  167. package/scripts/hall-preview/fixtures/tasks__peer-votes__feed.json +330 -0
  168. package/scripts/hall-preview/fixtures/versions.json +89 -0
  169. package/scripts/hall-preview/refresh-fixtures.js +77 -0
  170. package/scripts/hall-preview/server.js +178 -0
  171. package/scripts/migrate.sh +29 -4
  172. package/src/bongos/auth.js +14 -1
  173. package/src/bongos/optimizer.js +37 -2
  174. package/src/bongos/serve-internal.js +10 -1
  175. package/src/branding.js +1 -0
  176. package/src/module-api.js +12 -1
  177. package/src/module-loader/loader.js +36 -4
  178. package/src/module-loader/manifest-schema.js +16 -1
  179. package/tests/branding.mjs +11 -0
  180. package/tests/claim_error_surface.mjs +107 -0
  181. package/tests/claude_materialize.mjs +20 -0
  182. package/tests/consumer_layout_boot.mjs +302 -0
  183. package/tests/criterion_suggest.mjs +106 -0
  184. package/tests/cutover_codemod.mjs +184 -0
  185. package/tests/device_flow_start.mjs +25 -2
  186. package/tests/hook_core_resolve.mjs +125 -0
  187. package/tests/infra_exec_paths.mjs +104 -0
  188. package/tests/init.mjs +47 -0
  189. package/tests/migrate_root_resolution.mjs +97 -0
  190. package/tests/mirror_lineage_proof.mjs +14 -0
  191. package/tests/module_loader.mjs +42 -0
  192. package/tests/module_manifest.mjs +19 -0
  193. package/tests/onboard.mjs +13 -0
  194. package/tests/package_core.mjs +8 -0
  195. package/tests/provisioning_github_app_routes.mjs +15 -0
  196. package/tests/publish_manifest.mjs +52 -1
  197. package/tests/run_routine.mjs +26 -1
  198. package/tests/run_routine_two_root.mjs +77 -0
  199. package/tests/scrubber_corpus.mjs +17 -0
  200. package/tests/update_channel.mjs +186 -0
  201. package/tests/upgrade.mjs +131 -0
  202. package/tests/workflow_exec_paths.mjs +98 -0
  203. package/docs/design/container-exterior-tiles.md +0 -49
  204. package/docs/design/container-exterior.md +0 -81
  205. package/docs/design/container-interior.md +0 -77
  206. package/docs/design/world-map-scroll.md +0 -41
  207. package/docs/recipes/claude-gemini-bongos-doors.md +0 -155
  208. package/docs/recipes/cloudbongos-staging-gate.md +0 -139
  209. package/docs/recipes/cloudbongos-standup.md +0 -111
  210. package/docs/recipes/parallel-load-results-2026-05-30.md +0 -63
  211. package/docs/recipes/parallel-load-test.md +0 -32
  212. package/docs/recipes/pixel-art-pipeline.md +0 -411
  213. package/docs/recipes/staging-data.md +0 -50
  214. package/migrations/instance/018_pms_v3_planning_seed.sql +0 -131
  215. package/migrations/instance/080_gds_v4_planning_seed.sql +0 -75
  216. package/migrations/instance/110_medusa_planning_seed.sql +0 -70
  217. package/migrations/instance/120_bongos_v1_planning_seed.sql +0 -69
  218. package/migrations/instance/144_bongos_v1_module_system_criterion.sql +0 -26
  219. package/migrations/instance/159_bongos_v1_goal_hierarchy_criterion.sql +0 -29
  220. package/migrations/instance/172_v2_world_planning_seed.sql +0 -163
  221. package/migrations/instance/173_bongos_v1_c7_core_modularized.sql +0 -33
  222. package/migrations/instance/182_gdsv4_bongos_consolidation.sql +0 -132
  223. package/migrations/instance/183_gdsv4_carryover_themed_goals.sql +0 -116
  224. package/migrations/instance/186_bongos_v1_governance_planning_seed.sql +0 -69
  225. package/scripts/gds/art-stage.js +0 -152
  226. package/server.js +0 -212
  227. package/tests/art_key.mjs +0 -121
  228. package/tests/day_cycle.mjs +0 -197
  229. package/tests/snapshot_picker.mjs +0 -233
  230. package/tests/sprite_facing.mjs +0 -35
  231. package/tests/terrain_picker.mjs +0 -298
  232. package/tests/turn_in_place.mjs +0 -280
  233. 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,18 +163,18 @@ 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 |
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
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 |
@@ -187,7 +187,7 @@ 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 |
@@ -205,5 +205,8 @@ This keeps the decision history honest and traceable.
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
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
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 |
208
211
 
209
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`.)
@@ -4589,6 +4589,58 @@
4589
4589
  ]
4590
4590
  }
4591
4591
  },
4592
+ "/goals/{id}/suggest-criteria": {
4593
+ "get": {
4594
+ "operationId": "get_goals_id_suggest_criteria",
4595
+ "tags": [
4596
+ "goals"
4597
+ ],
4598
+ "summary": "GET /goals/:id/suggest-criteria",
4599
+ "description": "GET /goals/:id/suggest-criteria?title=&description=&limit= — task 2165. Rank THIS goal's unsatisfied criteria by lexical overlap with a candidate task, so a create flow can SUGGEST which done-when criterion to link (the author confirms/overrides — nothing is auto-linked). Read-only + advisory; rank: any-builder (same as GET /goals/:id).\n\n**Rank:** `any-builder` — Any authenticated builder (row-level ownership enforced in-handler).",
4600
+ "x-rank": "any-builder",
4601
+ "x-source": "modules/lifecycle/routes/goals.js",
4602
+ "parameters": [
4603
+ {
4604
+ "name": "id",
4605
+ "in": "path",
4606
+ "required": true,
4607
+ "schema": {
4608
+ "type": "string"
4609
+ },
4610
+ "description": "Path parameter `id`."
4611
+ }
4612
+ ],
4613
+ "responses": {
4614
+ "200": {
4615
+ "description": "Success.",
4616
+ "content": {
4617
+ "application/json": {
4618
+ "schema": {
4619
+ "$ref": "#/components/schemas/GetGoalsIdSuggestCriteriaResponse"
4620
+ }
4621
+ }
4622
+ }
4623
+ },
4624
+ "400": {
4625
+ "$ref": "#/components/responses/BadRequest"
4626
+ },
4627
+ "401": {
4628
+ "$ref": "#/components/responses/Unauthorized"
4629
+ },
4630
+ "403": {
4631
+ "$ref": "#/components/responses/Forbidden"
4632
+ },
4633
+ "404": {
4634
+ "$ref": "#/components/responses/NotFound"
4635
+ }
4636
+ },
4637
+ "security": [
4638
+ {
4639
+ "builderSession": []
4640
+ }
4641
+ ]
4642
+ }
4643
+ },
4592
4644
  "/goals/{id}/tasks": {
4593
4645
  "post": {
4594
4646
  "operationId": "post_goals_id_tasks",
@@ -8464,14 +8516,7 @@
8464
8516
  },
8465
8517
  "responses": {
8466
8518
  "200": {
8467
- "description": "Success.",
8468
- "content": {
8469
- "application/json": {
8470
- "schema": {
8471
- "$ref": "#/components/schemas/PostTasksResponse"
8472
- }
8473
- }
8474
- }
8519
+ "description": "Success."
8475
8520
  },
8476
8521
  "400": {
8477
8522
  "$ref": "#/components/responses/ValidationFailed"
@@ -10497,6 +10542,17 @@
10497
10542
  "dependencies"
10498
10543
  ]
10499
10544
  },
10545
+ "GetGoalsIdSuggestCriteriaResponse": {
10546
+ "type": "object",
10547
+ "properties": {
10548
+ "goal_id": {},
10549
+ "suggestions": {}
10550
+ },
10551
+ "required": [
10552
+ "goal_id",
10553
+ "suggestions"
10554
+ ]
10555
+ },
10500
10556
  "GetGoalsResponse": {
10501
10557
  "type": "object",
10502
10558
  "properties": {
@@ -13752,23 +13808,6 @@
13752
13808
  ],
13753
13809
  "additionalProperties": false
13754
13810
  },
13755
- "PostTasksResponse": {
13756
- "type": "object",
13757
- "properties": {
13758
- "task": {},
13759
- "needs_migration": {},
13760
- "criteria": {},
13761
- "idempotent": {
13762
- "type": "boolean"
13763
- },
13764
- "credits_reward": {}
13765
- },
13766
- "required": [
13767
- "task",
13768
- "needs_migration",
13769
- "criteria"
13770
- ]
13771
- },
13772
13811
  "PostVersionsIdDoneWhenRequest": {
13773
13812
  "type": "object",
13774
13813
  "properties": {
@@ -14021,7 +14060,7 @@
14021
14060
  "description": "A required dependency/feature is not configured or is temporarily down."
14022
14061
  }
14023
14062
  },
14024
- "x-endpoint-count": 229,
14063
+ "x-endpoint-count": 230,
14025
14064
  "x-schema-count": 250,
14026
14065
  "x-undocumented-bodies": 8,
14027
14066
  "x-response-schemas": 170,
@@ -2,7 +2,7 @@
2
2
 
3
3
  # GDS API reference
4
4
 
5
- > **Generated from the live route files** — the route file is authoritative. 229 endpoints across 38 route files.
5
+ > **Generated from the live route files** — the route file is authoritative. 230 endpoints across 38 route files.
6
6
  > Machine-readable spec: [`docs/api/openapi.json`](api/openapi.json) (OpenAPI 3.1). Rendered docs site: **`/docs`** (e.g. `cloudbongos.com/docs`).
7
7
 
8
8
  Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>.md)): `public` < `any-builder` < `metic+archon` < `archon`.
@@ -181,7 +181,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
181
181
  | GET | `/api/bongos/gate-approvals` | `archon` | — | GET /gate-approvals — open PRs awaiting owner approval (gate-review red), with the verdict + per-file reasons + changed files + diff link. |
182
182
  | POST | `/api/bongos/gate-approvals/:pr/approve` | `archon` | — | POST /gate-approvals/:pr/approve — record owner approval for a stuck gate PR and re-run the gate-review check so it clears. |
183
183
 
184
- ## `goals` (23)
184
+ ## `goals` (24)
185
185
 
186
186
  | Method | Path | Rank | Body | Description |
187
187
  |---|---|---|---|---|
@@ -203,6 +203,7 @@ Base path: `/api/bongos`. Ranks (enforced server-side, [ADR 0016](adr/<redacted>
203
203
  | POST | `/api/bongos/goals/:id/requests/:reqId/respond` | `any-builder` | `action` | POST /goals/:id/requests/:reqId/respond { action: approve\|deny } — an owner\| manager\|Archon resolves a pending join-request (task 1952). |
204
204
  | POST | `/api/bongos/goals/:id/requests/:reqId/withdraw` | `any-builder` | — | POST /goals/:id/requests/:reqId/withdraw — the requester cancels their OWN pending join-request (task 1953): the symmetric self-served mi… |
205
205
  | POST | `/api/bongos/goals/:id/scope` | `metic+archon` | `add` | POST /goals/:id/scope — "ask to widen": add module(s) to a goal's scope_modules (ADR 0086 §4 / BV1.R64). |
206
+ | GET | `/api/bongos/goals/:id/suggest-criteria` | `any-builder` | — | GET /goals/:id/suggest-criteria?title=&description=&limit= — task 2165. |
206
207
  | POST | `/api/bongos/goals/:id/tasks` | `any-builder` | `title`, `description`, `touches`, `est_minutes`, `priority`, `kind`, `discipline`, `value_summary`, `parent_task_id` | POST /goals/:id/tasks — bounded task authoring within a goal's scope (BV1.R60 / ADR 0086 §3). |
207
208
  | POST | `/api/bongos/goals/:id/transfer` | `any-builder` | `builder_id` | POST /goals/:id/transfer — hand the goal to a new owner (task 1735). |
208
209
  | PATCH | `/api/bongos/goals/:id/visibility` | `any-builder` | `visibility` | PATCH /goals/:id/visibility — make a goal public\|private (task 1952 / ADR 0112). |
@@ -93,7 +93,7 @@ builders(id, github_id UNIQUE, github_login, display_name, avatar_url, total_cre
93
93
  gemini_key_enc, gemini_key_last4, gemini_key_set_at) -- mig 122: per-builder Gemini key, AES-256-GCM at rest (ADR 0073); master key BUILDER_SECRET_KEY in server env only
94
94
  rank text NOT NULL DEFAULT 'xenos' (mig 023; default flipped to xenos in mig 029)
95
95
  CHECK IN 16-value ladder; LIVE: archon|metic|xenos (three-rank model, #360/ADR 0018)
96
- karma integer NOT NULL DEFAULT 0 (mig 040) -- good-citizenship track alongside drachmae
96
+ karma integer NOT NULL DEFAULT 0 (mig 040) -- good-citizenship track alongside example
97
97
  (=total_credits); append-only karma_log + AFTER INSERT trigger keep it in sync
98
98
  status text DEFAULT 'active' (mig 025) -- 'active'|'inactive'; a deactivated builder can't claim (#307)
99
99
  system_role text NULL (mig 065) -- NULL for every human; 'bfg' = the BFG service principal
@@ -168,7 +168,7 @@ task_grades(id, task_id UNIQUE, score NUMERIC(3,1), passed bool, threshold NUMER
168
168
  grade_attempts(id, task_id, builder_id?, passed bool, score NUMERIC(3,1), attempted_at)
169
169
  -- mig 064 (6D.6, ADR 0027): APPEND-ONLY, one row per grade run, so
170
170
  -- re-grade thrash is countable (task_grades keeps only the latest)
171
- session_records(id, session_id UNIQUE, builder_id, task_ids bigint[], drachmae_earned,
171
+ session_records(id, session_id UNIQUE, builder_id, task_ids bigint[], example_earned,
172
172
  total_tokens, duration_seconds, started_at, ended_at, uploaded_at,
173
173
  detail jsonb, metrics jsonb) -- mig 062 (6D.1, ADR 0027): per-shipped-session
174
174
  -- secret-scrubbed digest (per-turn metadata + short snippets); idx on
@@ -19,7 +19,7 @@ env override → instance config (config/branding.json) → neutral star
19
19
 
20
20
  | Path | Meaning |
21
21
  |---|---|
22
- | `identity.productName` | The product name (e.g. "Off the Boats"). **Required.** |
22
+ | `identity.productName` | The product name (e.g. "Example"). **Required.** |
23
23
  | `identity.worldName` | The in-world / civilization name rendered at runtime (e.g. "Example"). **Required.** |
24
24
  | `identity.company` | `{ name, site }` of the operating company (may be empty). |
25
25
  | `llmProjectName` | The project name injected into grader / architect / onboarding **LLM prompts**, so a non-OTB instance is graded against its own identity. **Required.** |
@@ -27,13 +27,14 @@ env override → instance config (config/branding.json) → neutral star
27
27
  | `domains.buildersOrigin` / `statusOrigin` | Hall + status origins. **These three (`publicOrigin`/`buildersOrigin`/`statusOrigin`) are the docs-discovery contract** ([ADR 0114](adr/<redacted>.md)): the hall is the canonical doc-reading surface, `/docs` on `publicOrigin` renders the API reference, the status page is the outage fallback. `GET <publicOrigin>/api/bongos` re-advertises them (`hall`/`status`/`public`) so an agent resolves the surfaces with no hard-coded host. |
28
28
  | `domains.cookieDomain` | Session cookie domain (`""` = host-only — the safe default; never widen to a parent domain by accident). |
29
29
  | `domains.oauthOrigin` | Canonical sign-in origin. |
30
+ | `domains.provisioningOrigin` | **Optional.** Control-plane front-door origin the [provisioning module](../../modules/provisioning/CLAUDE.md) uses to build a new customer's GitHub-App `redirect_url`. Set it when the control plane co-hosts a game whose `publicOrigin` is the game's own domain (OTB = customer 0) so the customer's App carries the PLATFORM brand (e.g. `https://get.cloudbongos.com`), not the game's. **Falls back to `publicOrigin` when unset** — an instance whose `publicOrigin` is already the platform needs no override. Env-overridable: `<PREFIX>_PROVISIONING_ORIGIN`. ([#2101](https://example.com/builders#/task/2101)) |
30
31
  | `domains.devBoxBase` | Apex zone the **proxied** browser-terminal + sandbox hosts ride (`term-<login>.<devBoxBase>`, `sandbox-<login>.<devBoxBase>`). Must be a one-label-under-apex zone so free edge TLS (`*.<apex>`) covers it — a two-label host fails edge TLS (the [#771](https://example.com/builders#/task/771) lesson). Empty ⇒ no managed boxes. |
31
32
  | `domains.sshBoxBase` | Zone for the **legacy direct-IP SSH** box host (`box-<login>.<sshBoxBase>`, unproxied). Deliberately distinct from `devBoxBase` (one proxied/edge-TLS, one direct-IP). |
32
33
  | `domains.sandboxPrefix` / `termPrefix` | Subdomain prefixes for the sandbox-preview + browser-terminal hosts. |
33
34
  | `repo` | `{ owner, name }` GitHub binding. |
34
35
  | `db.database` | DB name the GDS pool connects to when neither `DATABASE_URL` nor `PGHOST`/`PGDATABASE` is set (`src/bongos/pool.js`, ADR 0062 §5). `null` in the neutral starter = **fail loud** rather than silently target a host DB. |
35
- | `currency` | `{ label, symbol }` — the reward unit label (e.g. "drachmae"). Display only. |
36
- | `reward` | `{ marginPct, usdPeg }` — the per-instance reward POLICY the economy module reads ([ADR 0054](adr/<redacted>.md), task 2009): the cost-plus margin percent (default `20`) and the drachmae-per-USD peg (default `1`). A committed, code-reviewed change — not a live UI knob. Omit ⇒ code defaults (20% margin, 1:1 peg). |
36
+ | `currency` | `{ label, symbol }` — the reward unit label (e.g. "example"). Display only. |
37
+ | `reward` | `{ marginPct, usdPeg }` — the per-instance reward POLICY the economy module reads ([ADR 0054](adr/<redacted>.md), task 2009): the cost-plus margin percent (default `20`) and the example-per-USD peg (default `1`). A committed, code-reviewed change — not a live UI knob. Omit ⇒ code defaults (20% margin, 1:1 peg). |
37
38
  | `models` | `{ main, subagentDefault, subagentRoutine }` — the per-instance subagent model-allocation DEFAULT the builder-settings module reads (task 2011): the tier for the main session, subagent-default work, and routine plumbing (tiers: `haiku`/`sonnet`/`opus`/`fable`). A per-builder override resolves over this. Omit ⇒ code defaults (`opus`/`opus`/`haiku`). |
38
39
  | `tracks` | The configurable version-track set (replaces the hardcoded `product\|internal`). |
39
40
  | `theme` | `{ palette, mode }` — palette file ref + theme mode. |
@@ -59,7 +60,7 @@ The browser never sees the full pack — only the **client-safe projection** `cl
59
60
  - **On-box (hall + status served from the droplet):** injected synchronously by `mountInternalSurfaces` (`src/bongos/serve-internal.js` → `injectBrandingGlobal`) into the page `<head>` as **`window.__BRANDING__`** (the strings) **plus theme markup** (`themeMarkup` → a `:root` palette/font-var override `<style>`, the web-font `<link>`s, and the favicon `<link>`). The `<style>` lands after the page's own stylesheet so the pack wins. No fetch, no flash-of-default.
60
61
  - **Off-box (the GitHub-Pages status page):** read cross-origin from **`GET /api/gds/public/branding`**.
61
62
 
62
- R56 seeded the projection with the configurable **currency label** (`public-builders/brand-apply.js` fills `[data-currency-label]` / `[data-currency-tmpl]` markup + `window.OTBBranding.currencyLabel()`). R57 widens it to the **LOOK** — `theme.ui` (palette + fonts + favicon; note this is the WEB theme, distinct from the server-only `theme.palette` game pixel-art path) — and the **rank display-label map** (`window.OTB.rankLabel()` reads `rankLabels`; the rank ENUM stays Greek by decision, only the label is presentation). The remaining archaic **page copy + identity strings** (titles, ledes, "washed ashore" flavor) are tracked as the R57 copy-pack follow-up.
63
+ R56 seeded the projection with the configurable **currency label** (`public-builders/brand-apply.js` fills `[data-currency-label]` / `[data-currency-tmpl]` markup + `window.OTBBranding.currencyLabel()`). R57 widens it to the **LOOK** — `theme.ui` (palette + fonts + favicon; note this is the WEB theme, distinct from the server-only `theme.palette` game pixel-art path) — and the **rank display-label map** (`window.OTB.rankLabel()` reads `rankLabels`; the rank ENUM stays Greek by decision, only the label is presentation). The remaining themed **page copy + identity strings** (titles, ledes, world-flavor copy) are tracked as the R57 copy-pack follow-up.
63
64
 
64
65
  ## Branding a new instance
65
66
 
@@ -86,7 +86,7 @@ forming the ordered claim-gate tier **`xenos` (1) < `thetes` (2) < `metic` (3) <
86
86
  `db.claimTask` / `claimTasksBatch`, returns `rank_too_low_for_task`). Cannot triage, resolve
87
87
  blockers, or run planning/priority sessions. This is also the tier a deactivated/offboarded builder
88
88
  is dropped to by `/builder-exit` (migration `025`); for them `status='inactive'` additionally blocks
89
- *all* claims. Either way, drachmae / credit history / shipped-task attribution are preserved.
89
+ *all* claims. Either way, example / credit history / shipped-task attribution are preserved.
90
90
 
91
91
  Everything else on the citizen ladder (`strategos`…`zeugitai`), the divine tiers, and the other
92
92
  sub-citizen tiers (`periokoi`/`doulos`/`helot`) stay **reserved but unwired** — promoting anyone to
@@ -227,7 +227,7 @@ Not layout, but it rides along. Most of this already flows through the brand pac
227
227
  | "The Builders' Hall" · "chronicles of the city" epigraph | "Builders" · no epigraph | brand pack + markup |
228
228
  | "scroll" (section) | card / panel | markup + CSS class |
229
229
  | "Thy Standing in the City" | Standing / Profile | markup |
230
- | drachmae | credits (`currency-label`) | brand pack (already) |
230
+ | example | credits (`currency-label`) | brand pack (already) |
231
231
  | Honours / laurels | Achievements | markup |
232
232
  | "Works Wrought by Thy Hand" | Your work | markup |
233
233
  | "Marks of the Inspector" | Reviews / quality marks | markup |
package/docs/file-map.md CHANGED
@@ -364,23 +364,24 @@ tests/
364
364
  <!-- BEGIN GENERATED FILE-MAP .claude/scheduled-tasks/ (scripts/gds/gen-file-map.js — do not hand-edit; notes live in docs/file-map.notes.json) -->
365
365
  ```
366
366
  .claude/scheduled-tasks/
367
- ├── bfg/SKILL.md ← (MAS Phase 6, ADR 0026) BFG hygiene + read-the-room + steward routine: doc-vs-reality checks, memory hygiene, cross-builder learning. Read-mostly.
368
- ├── bfg-session-eval/SKILL.md ← (6D.3, ADR 0027) BFG session-inefficiency evaluator: search the session corpus, deep-dive wasteful sessions (ceremony-vs-work + footguns), file systemic findings. Read-only.
369
- ├── box-dormant-reclaim/SKILL.md ← (#598/ADR 0031) daily: deprovision dev boxes parked past the dormant threshold (pings the builder). Drives `box.js sweep-dormant --apply`. Control-plane only.
370
- ├── box-idle-suspend/SKILL.md ← (#598/ADR 0031) every 15 min: snapshot-and-park dev boxes idle past the idle threshold. Drives `box.js sweep-idle --apply`. Control-plane only.
371
- ├── dep-audit-nightly/SKILL.md ← autonomous nightly dependency-vulnerability scan on the droplet (`scripts/security/dep-audit.js --report-mode=nightly`) across npm + the devbox app
372
- ├── diagram-drift/SKILL.md ← belt-and-braces backstop for the onboarding diagrams — all five auto-regenerate on deploy, so this only flags any residual staleness
373
- ├── idea-triage-nightly/SKILL.md ← nightly autonomous walk of the idea_inbox; promotes high-confidence bugs/cleanups, discards obvious noise, defers ambiguous ideas
374
- ├── main-audit/SKILL.md ← (SEC #863 / ADR 0043) nightly post-push audit of `main` — flags commits where a sub-Metic builder edited a permission-sensitive surface
375
- ├── newcomer-floor/SKILL.md ← deterministic on-claim replenisher for the three evergreen newcomer chores (engineer/artist/ideator) — no cron; restocks when one is claimed (task 1168)
376
- ├── newcomer-generator/SKILL.md ← keep the newcomer_friendly task queue populated (C1) — deterministic generator tops the queue back up to its floor
377
- ├── overnight-builder/SKILL.md ← (#358) autonomous overnight session-runner: claims the highest-priority autonomous-fit task, works it in a fresh sub-agent, ships, re-polls. Archon-only. Runbook: docs/recipes/overnight-builder.md
378
- ├── overnight-code-review/SKILL.md ← nightly read-only code review; routes each finding into the idea_inbox (one row per finding; title prefix `[review YYYY-MM-DD]`)
379
- ├── peer-vote-tally/SKILL.md ← (V3.R25 / #245, C2) weekly tally of builder-on-builder peer votes into karma; folds votes ≥7 days old into karma_log
380
- ├── repo-simplify-sweep/SKILL.md ← weekly autonomous repo-cleanliness janitor: runs repo-metrics, files dead-code findings to the idea_inbox, auto-fixes the narrow safe class (unused vars/imports)
381
- ├── security-review-weekly/SKILL.md ← (V3.R69 / #288) autonomous weekly security-state review — surfaces stale vulnerability_reports + other stale-security signals
382
- ├── skill-usage-review/SKILL.md ← nightly skill-usage feedback loop: aggregates 24h of skill invocations, detects friction (over-invocation, errors), files findings
383
- └── stale-claim-release/SKILL.md ← auto-release GDS claims whose session_pulses heartbeat went silent ≥ GDS_STALE_CLAIM_HOURS (default 6h); runs every 15 min on the droplet
367
+ ├── bfg/SKILL.md ← (MAS Phase 6, ADR 0026) BFG hygiene + read-the-room + steward routine: doc-vs-reality checks, memory hygiene, cross-builder learning. Read-mostly.
368
+ ├── bfg-session-eval/SKILL.md ← (6D.3, ADR 0027) BFG session-inefficiency evaluator: search the session corpus, deep-dive wasteful sessions (ceremony-vs-work + footguns), file systemic findings. Read-only.
369
+ ├── box-dormant-reclaim/SKILL.md ← (#598/ADR 0031) daily: deprovision dev boxes parked past the dormant threshold (pings the builder). Drives `box.js sweep-dormant --apply`. Control-plane only.
370
+ ├── box-idle-suspend/SKILL.md ← (#598/ADR 0031) every 15 min: snapshot-and-park dev boxes idle past the idle threshold. Drives `box.js sweep-idle --apply`. Control-plane only.
371
+ ├── core-update-subscription/SKILL.md ← (task 2150 / ADR 0136) daily: patch-only auto-upgrade of subscribed consumer instances (config/update-subscriptions.json) via `bongos upgrade --registry` with auto-rollback. Deterministic; opt-in + autonomy-gated (default OFF). Control-plane only.
372
+ ├── dep-audit-nightly/SKILL.md ← autonomous nightly dependency-vulnerability scan on the droplet (`scripts/security/dep-audit.js --report-mode=nightly`) across npm + the devbox app
373
+ ├── diagram-drift/SKILL.md ← belt-and-braces backstop for the onboarding diagrams — all five auto-regenerate on deploy, so this only flags any residual staleness
374
+ ├── idea-triage-nightly/SKILL.md ← nightly autonomous walk of the idea_inbox; promotes high-confidence bugs/cleanups, discards obvious noise, defers ambiguous ideas
375
+ ├── main-audit/SKILL.md ← (SEC #863 / ADR 0043) nightly post-push audit of `main` — flags commits where a sub-Metic builder edited a permission-sensitive surface
376
+ ├── newcomer-floor/SKILL.md ← deterministic on-claim replenisher for the three evergreen newcomer chores (engineer/artist/ideator) — no cron; restocks when one is claimed (task 1168)
377
+ ├── newcomer-generator/SKILL.md ← keep the newcomer_friendly task queue populated (C1) — deterministic generator tops the queue back up to its floor
378
+ ├── overnight-builder/SKILL.md ← (#358) autonomous overnight session-runner: claims the highest-priority autonomous-fit task, works it in a fresh sub-agent, ships, re-polls. Archon-only. Runbook: docs/recipes/overnight-builder.md
379
+ ├── overnight-code-review/SKILL.md ← nightly read-only code review; routes each finding into the idea_inbox (one row per finding; title prefix `[review YYYY-MM-DD]`)
380
+ ├── peer-vote-tally/SKILL.md ← (V3.R25 / #245, C2) weekly tally of builder-on-builder peer votes into karma; folds votes ≥7 days old into karma_log
381
+ ├── repo-simplify-sweep/SKILL.md ← weekly autonomous repo-cleanliness janitor: runs repo-metrics, files dead-code findings to the idea_inbox, auto-fixes the narrow safe class (unused vars/imports)
382
+ ├── security-review-weekly/SKILL.md ← (V3.R69 / #288) autonomous weekly security-state review — surfaces stale vulnerability_reports + other stale-security signals
383
+ ├── skill-usage-review/SKILL.md ← nightly skill-usage feedback loop: aggregates 24h of skill invocations, detects friction (over-invocation, errors), files findings
384
+ └── stale-claim-release/SKILL.md ← auto-release GDS claims whose session_pulses heartbeat went silent ≥ GDS_STALE_CLAIM_HOURS (default 6h); runs every 15 min on the droplet
384
385
  ```
385
386
  <!-- END GENERATED FILE-MAP .claude/scheduled-tasks/ -->
386
387
 
@@ -65,9 +65,9 @@ If even one of these is false, the claim is `[verified-smoke]` or `[implemented-
65
65
 
66
66
  ### Diagram backstop (task [#357](https://example.com/builders#/task/357); conceptual diagrams auto-generated [#436](https://example.com/builders#/task/436))
67
67
 
68
- If your change touched anything the onboarding diagrams describe — the **rank enum or which ranks are wired** (`requireRank`, `builders.rank` default, exit/assign paths), the **task-status set**, the **versions** (id/track/status), or the **complete-architecture** (the ADR 0024 memory chain + the dev-box → production ship flow) **/ drachmae-karma** models (which now flip per the **shipped** status of their backing tasks) — then before shipping:
68
+ If your change touched anything the onboarding diagrams describe — the **rank enum or which ranks are wired** (`requireRank`, `builders.rank` default, exit/assign paths), the **task-status set**, the **versions** (id/track/status), or the **complete-architecture** (the ADR 0024 memory chain + the dev-box → production ship flow) **/ example-karma** models (which now flip per the **shipped** status of their backing tasks) — then before shipping:
69
69
 
70
- - **All five diagrams are auto-generated** by `scripts/gds/gen-diagrams.js` — run it (`node scripts/gds/gen-diagrams.js`) and confirm the result looks right; **do not hand-edit any `.mmd`**. The mechanical three (`01-task-lifecycle`, `02-rank-ladder`, `05-versioning`) regenerate from migrations + the public version API. The conceptual two (`03-drachmae-karma`, `04-architecture`) regenerate from the **authenticated** `/tasks/:id` status of their backing tasks (and 03's seeded-achievement count); if no session is present the generator skips them cleanly. Rendering produces both `.svg` (the pannable viewer asset) and `.png` (fallback).
70
+ - **All five diagrams are auto-generated** by `scripts/gds/gen-diagrams.js` — run it (`node scripts/gds/gen-diagrams.js`) and confirm the result looks right; **do not hand-edit any `.mmd`**. The mechanical three (`01-task-lifecycle`, `02-rank-ladder`, `05-versioning`) regenerate from migrations + the public version API. The conceptual two (`03-example-karma`, `04-architecture`) regenerate from the **authenticated** `/tasks/:id` status of their backing tasks (and 03's seeded-achievement count); if no session is present the generator skips them cleanly. Rendering produces both `.svg` (the pannable viewer asset) and `.png` (fallback).
71
71
  - To change a diagram's **layout or wording**, edit the matching template function in `gen-diagrams.js` — not the `.mmd`. `assertions.json` is rebuilt by the generator in lockstep, so you don't hand-maintain it.
72
72
 
73
73
  The `diagram-drift` routine is a belt-and-braces backstop (it should find nothing once the generator has run), but the point is not to rely on it — running `gen-diagrams.js` is part of the change.
@@ -95,12 +95,17 @@ Every module must have a `module.json` at its root (`modules/<key>/module.json`)
95
95
  },
96
96
  "provides": ["box.hasEverConnected"], // OPTIONAL. Seam PORTS this module registers a provider for.
97
97
  "consumes": [], // OPTIONAL. Seam ports this module resolves (required caps).
98
- "prerequisites": { "modules": [] } // OPTIONAL. Other modules that must be enabled first.
98
+ "prerequisites": { "modules": [] }, // OPTIONAL. Other modules that must be enabled first.
99
+ "dependencies": { "discord.js": "^14.26.4" } // OPTIONAL. External npm deps this module needs at runtime.
99
100
  }
100
101
  ```
101
102
 
102
103
  An unknown key throws at validate time — typos fail loud (top-level attribution fields have no closed allowlist; only `contributes` sub-keys do).
103
104
 
105
+ ### `dependencies` — a module's own npm deps ([ADR 0138](adr/<redacted>.md))
106
+
107
+ `@bongos/core` ships lean — its synthesized `package.json` declares only `express` + `pg` ([ADR 0108](adr/<redacted>.md)). A bundled module that needs an external npm package at runtime (e.g. `discord` → `discord.js`) declares it in its own `module.json` `dependencies` (`{ "<npm-name>": "<semver-range>" }`, schema-validated). **Core does not carry it**, so the *consumer* must — greenfield `bongos init` composes the ENABLED modules' declared deps into the instance `package.json` (`enabledModuleDeps` → `buildInstancePackageJson`; an explicit pre-existing pin wins, `@bongos/core` is always set), and the R89 cutover preserves the monolith's existing dependency closure. If a module needs a dep and neither declares it nor is it in the consumer's closure, an instance that enables the module crashes at boot — so **declare it here**.
108
+
104
109
  **Attribution (`author`/`origin`/`license`/`maintainer`) is portable metadata, not a cross-GDS link** — each repo runs its own GDS with its own builder identities ([ADR 0100](adr/<redacted>.md) §3), so credit travels *with the module* rather than through a foreign key ([ADR 0107](adr/<redacted>.md) §2). `bongos module new` stamps all four as TODO placeholders (license defaults to `AGPL-3.0`) so a module carries its authorship from the day it's scaffolded, not bolted on later at upstream-submit time.
105
110
 
106
111
  **`bongos module check <key> [--sign-off "Name <email>"]`** ([ADR 0107](adr/<redacted>.md) §4) is the submit-time pre-check a module must clear before it can be upstreamed. It reuses (never re-types) the public-mirror publish denylist (`scripts/gds/publish-manifest.js`'s `matchesDeny`) to reject content that cannot ship under AGPL (game content, pixel art, copyrighted reference material) — deliberately the DENY half only, since a brand-new module is never on the publish ALLOWLIST until it's accepted into core (§6). It also requires `module.json`'s `license` to be AGPL-3.0 (inbound = outbound). On a pass, `--sign-off` records a lightweight DCO-style affirmation (own work, licensed AGPL-3.0 — never a copyright-assignment CLA) to `modules/<key>/.upstream-signoff.json`.
@@ -11,7 +11,7 @@ Five flowcharts that explain the Game Development System (GDS) to a new builder
11
11
  | Diagram | What drives its state |
12
12
  |---|---|
13
13
  | `01-task-lifecycle` · `02-rank-ladder` · `05-versioning` (**mechanical**) | The task-status set + rank enum/wiring (read from `migrations/` + `src/bongos/`) and the live version set (production API). No auth needed — always regenerate. |
14
- | `03-drachmae-karma` · `04-architecture` (**conceptual**) | Each feature-piece is **LIVE iff its backing GDS task is `shipped`**, plus 03's "N seeded" count from the achievements seed in `migrations/`. These read the **authenticated** `/tasks/:id` status, so when no GDS session is available (headless run, no creds) the generator **skips** 03/04 and leaves them untouched rather than emit wrong data. (04's device/box/server/GitHub *topology* is structural; only its LIVE/PLANNED markers — the memory chain + the box→prod ship-flow legs — are task-gated.) |
14
+ | `03-example-karma` · `04-architecture` (**conceptual**) | Each feature-piece is **LIVE iff its backing GDS task is `shipped`**, plus 03's "N seeded" count from the achievements seed in `migrations/`. These read the **authenticated** `/tasks/:id` status, so when no GDS session is available (headless run, no creds) the generator **skips** 03/04 and leaves them untouched rather than emit wrong data. (04's device/box/server/GitHub *topology* is structural; only its LIVE/PLANNED markers — the memory chain + the box→prod ship-flow legs — are task-gated.) |
15
15
 
16
16
  The mechanical diagrams regenerate **on every deploy** (`ship.js` / `/merge-mode` run `gen-diagrams.js` before deploying; a changed diagram is committed and shipped automatically). The conceptual diagrams regenerate the same way whenever a session is present (the deploy host has one). The `diagram-drift` routine remains as a belt-and-braces backstop. So `/builders/diagrams` is never more than one deploy behind the live architecture.
17
17
 
@@ -28,7 +28,7 @@ The GDS is mid-build. These diagrams deliberately distinguish **what exists toda
28
28
  ## The five diagrams
29
29
 
30
30
  ### 1. Task lifecycle — backlog → shipped
31
- How a task moves from creation to production, and the exact edge where **credits/drachmae are awarded** (`completed → confirmed`, *not* at ship).
31
+ How a task moves from creation to production, and the exact edge where **credits/example are awarded** (`completed → confirmed`, *not* at ship).
32
32
 
33
33
  ![Task lifecycle](01-task-lifecycle.png)
34
34
 
@@ -41,12 +41,12 @@ The 16-value reserved rank enum (migration 023) in three Greek bands, which rank
41
41
 
42
42
  Source: [`02-rank-ladder.mmd`](02-rank-ladder.mmd)
43
43
 
44
- ### 3. Drachmae & karma — sourcing and spending
45
- Where each comes from and where each goes. Key facts: **drachmae = credits** (same thing, in-world name), they are **equity, not a spendable currency**, and the **primary source is now a cost-plus reward on each shipped session** — `round(true_cost × 1.20)` ([ADR 0054](../../adr/<redacted>.md)) — alongside per-task `credits_reward × kind multiplier` ([ADR 0023](../../adr/<redacted>.md)), achievements, and the (rate-card-live) security bounty. Karma is a separate peer-trust signal that does **not** gate rank promotions; its LIVE/PLANNED state tracks its backing tasks (R25/R32/R26). The full write-up is [`docs/onboarding/drachmae-and-karma.md`](../drachmae-and-karma.md).
44
+ ### 3. Example & karma — sourcing and spending
45
+ Where each comes from and where each goes. Key facts: **example = credits** (same thing, in-world name), they are **equity, not a spendable currency**, and the **primary source is now a cost-plus reward on each shipped session** — `round(true_cost × 1.20)` ([ADR 0054](../../adr/<redacted>.md)) — alongside per-task `credits_reward × kind multiplier` ([ADR 0023](../../adr/<redacted>.md)), achievements, and the (rate-card-live) security bounty. Karma is a separate peer-trust signal that does **not** gate rank promotions; its LIVE/PLANNED state tracks its backing tasks (R25/R32/R26). The full write-up is [`docs/onboarding/example-and-karma.md`](../example-and-karma.md).
46
46
 
47
- ![Drachmae and karma](03-drachmae-karma.png)
47
+ ![Example and karma](03-example-karma.png)
48
48
 
49
- Source: [`03-drachmae-karma.mmd`](03-drachmae-karma.mmd)
49
+ Source: [`03-example-karma.mmd`](03-example-karma.mmd)
50
50
 
51
51
  ### 4. The complete architecture — where your work runs and how code reaches production
52
52
  One map of the whole system, merging the old "server ↔ repo ↔ memory" three-layer view with the dev-box → production ship flow. The four places Claude Code splits across — your **device** (screen only) · the **dev box** (the worker, the code, *and* your local memory dir) · the **server/droplet** (authority *and* production: Postgres, the server-side memory store, the push credential) · **GitHub** (branch-protected main + Actions) — plus two flows woven through it: the **per-builder memory layer** (ADR 0024 — local ↔ server, sync-on-ship / pull-on-start) and the **box → prod ship path** (a credential-less box re-auths and uploads its branch as a git bundle; the server pushes it with a GitHub App credential; the PR auto-merges and GitHub Actions deploys — no droplet key on any box). Every feature-piece + flow edge is LIVE/solid iff its backing task is `shipped`. Backing tasks: memory chain [#273](https://example.com/builders#/task/273)–[#276](https://example.com/builders#/task/276); dev box [#904](https://example.com/builders#/task/904)/[#774](https://example.com/builders#/task/774)/[#897](https://example.com/builders#/task/897)/[#919](https://example.com/builders#/task/919); box→prod [#1025](https://example.com/builders#/task/1025)/[#859](https://example.com/builders#/task/859)/[#1028](https://example.com/builders#/task/1028)/[#1027](https://example.com/builders#/task/1027) (all shipped → the map reads all-LIVE today). See [ADR 0024](../../adr/<redacted>.md) (cloneable memory), [ADR 0055](../../adr/<redacted>.md) (server-mediated publish), [ADR 0053](../../adr/0053-scoped-dev-box-session.md) (scoped box token), [ADR 0042](../../adr/<redacted>.md) (CI self-deploy), [ADR 0016](../../adr/<redacted>.md) (trust boundary).
@@ -78,7 +78,7 @@ Two mechanisms keep these honest as the system changes (added under [#356](https
78
78
  node .claude/scheduled-tasks/diagram-drift/check.js --file-idea
79
79
  ```
80
80
 
81
- `assertions.json` is the machine-readable record of what these diagrams claim about the live system (rank enum + wired ranks, task-status set, live versions, and the conceptual `architecture` + `drachmae_karma` piece→task slices). It is **rebuilt by `gen-diagrams.js` in lockstep with the diagrams**, so you no longer hand-maintain it; it stays as the drift checker's reference.
81
+ `assertions.json` is the machine-readable record of what these diagrams claim about the live system (rank enum + wired ranks, task-status set, live versions, and the conceptual `architecture` + `example_karma` piece→task slices). It is **rebuilt by `gen-diagrams.js` in lockstep with the diagrams**, so you no longer hand-maintain it; it stays as the drift checker's reference.
82
82
 
83
83
  ## Regenerating the diagrams by hand
84
84