@bongos/core 1.19.1075 → 1.19.1076

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 (72) hide show
  1. package/.bongos-core.json +85 -100
  2. package/.claude/skills/blocker-solve/SKILL.md +1 -1
  3. package/README.md +1 -1
  4. package/docs/adr/0031-cloud-dev-environments-for-builders.md +1 -1
  5. package/docs/adr/0035-builder-onboarding-three-paths.md +1 -1
  6. package/docs/adr/0044-per-box-live-game-preview.md +1 -1
  7. package/docs/adr/0045-devbox-desktop-app.md +1 -1
  8. package/docs/adr/0046-sandbox-first-review-gate.md +1 -1
  9. package/docs/adr/0052-sandbox-for-everyone-game-only-preview.md +1 -1
  10. package/docs/adr/0053-scoped-dev-box-session.md +1 -1
  11. package/docs/adr/0055-server-mediated-branch-publish.md +1 -1
  12. package/docs/adr/0057-container-cost-ledger.md +1 -1
  13. package/docs/adr/0059-single-approval-remove-devbox-approval-gate.md +1 -1
  14. package/docs/adr/0071-box-confirm-before-destroyed-and-drift-reconcile.md +1 -1
  15. package/docs/adr/0072-bongos-app-mac-signed-first-windows-deferred.md +1 -1
  16. package/docs/adr/0072-dev-box-code-staleness-visibility.md +1 -1
  17. package/docs/adr/0104-trust-gds-api-channel-in-auto-mode.md +1 -1
  18. package/docs/adr/0123-box-idle-sweep-autosave-before-destroy.md +1 -1
  19. package/docs/adr/0144-devbox-rehome-onto-cloudbongos-plane.md +1 -1
  20. package/docs/adr/0145-devbox-app-branding-driven-module.md +1 -1
  21. package/docs/adr/0148-task-scoped-box-source-access.md +2 -2
  22. package/docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md +1 -1
  23. package/docs/adr/0193-pause-task-scoped-box-slices.md +1 -1
  24. package/docs/adr/0277-a-box-is-in-use-only-while-a-human-is-attached.md +1 -1
  25. package/docs/adr/0346-dev-boxes-are-retired.md +69 -0
  26. package/docs/adr/README.md +1 -0
  27. package/docs/architecture.md +5 -6
  28. package/docs/branding-contract.md +2 -2
  29. package/docs/canonical-permissions.md +10 -18
  30. package/docs/copy-inventory.md +3 -3
  31. package/docs/copy-registry.json +3 -3
  32. package/docs/design/gate-navigation-direction.md +1 -1
  33. package/docs/design/hall-direction-v2.md +3 -3
  34. package/docs/design/modular-architecture/00-research-report.md +1 -1
  35. package/docs/design/modular-architecture/01-architecture.md +3 -3
  36. package/docs/design/modular-architecture/02-module-map.md +1 -2
  37. package/docs/design/modular-architecture/03-builder-flows.md +22 -20
  38. package/docs/design/modular-architecture/04-module-lifecycle.md +1 -1
  39. package/docs/design/modular-architecture/README.md +4 -2
  40. package/docs/design/reviews/hall-v2/README.md +2 -2
  41. package/docs/design/vanilla-hall-ui-redesign-scope.md +4 -4
  42. package/docs/file-map.md +5 -5
  43. package/docs/handoff-template.md +1 -1
  44. package/docs/module-api-changelog.md +6 -0
  45. package/docs/modules-contract.md +11 -14
  46. package/docs/page-readings.json +63 -63
  47. package/docs/recipes/bongos-cli-release.md +1 -2
  48. package/docs/recipes/multi-builder-merge.md +1 -1
  49. package/docs/recipes/ops-gotchas.md +0 -9
  50. package/docs/recipes/self-host.md +1 -1
  51. package/docs/recipes/windows-builders.md +1 -1
  52. package/migrations/core_258_drop_dev_box_tables.sql +3 -0
  53. package/modules/hall-ui/public/palette.js +143 -3
  54. package/package-lock.json +2 -2
  55. package/package.json +1 -1
  56. package/release-notes.json +22 -0
  57. package/scripts/gds/dev-box-guard.js +165 -0
  58. package/scripts/gds/fitness-lib.js +10 -0
  59. package/scripts/gds/fitness.js +2 -10
  60. package/scripts/gds/run-unit-tests.js +4 -0
  61. package/src/bongos/module-scope-map.js +1 -1
  62. package/src/module-api.js +1 -1
  63. package/tests/core_258_box_session_claims_db.mjs +180 -0
  64. package/tests/fitness.mjs +89 -0
  65. package/tests/hall_palette.mjs +224 -11
  66. package/tests/provisioning_recommendations.mjs +1 -1
  67. package/docs/design/reviews/hall-v2/harbor--archon.webp +0 -0
  68. package/docs/design/reviews/hall-v2/harbor--metic.webp +0 -0
  69. package/docs/design/reviews/hall-v2/harbor--xenos.webp +0 -0
  70. package/docs/design/reviews/hall-v2/pair--archon.webp +0 -0
  71. package/docs/design/reviews/hall-v2/pair--metic.webp +0 -0
  72. package/docs/design/reviews/hall-v2/pair--xenos.webp +0 -0
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Date:** 2026-06-11
4
4
  **Context:** GDS-V3, task [#927](https://example.com/builders#/task/927). Builds directly on [ADR 0044](0044-per-box-live-game-preview.md) (the per-box live game preview / "sandbox") and the three-state ship lifecycle in `scripts/gds/ship.js` (Phase 5). Companion to [ADR 0031](0031-cloud-dev-environments-for-builders.md) (dev boxes) and [ADR 0016](0016-trust-boundary-server-enforced-permissions.md) (the gate is a workflow aid, not an authority surface).
5
- **Status:** Accepted.
5
+ **Status:** Superseded in part by [ADR 0346](0346-dev-boxes-are-retired.md) (the dev-box half; the local sandbox review survives). Was: Accepted.
6
6
  **Track:** `internal` (dev-system / builder experience).
7
7
 
8
8
  ## Problem
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Date:** 2026-06-13
4
4
  **Context:** GDS-V3, task [#1001](https://example.com/builders#/task/1001) (clone-scope + ungate) and task [#1002](https://example.com/builders#/task/1002) (hardware-verify). Builds on [ADR 0044](0044-per-box-live-game-preview.md) (the per-box live game preview / "sandbox") and [ADR 0031](0031-cloud-dev-environments-for-builders.md) (cloud dev boxes + rank-scoped source). Companion to [ADR 0046](0046-sandbox-first-review-gate.md) (sandbox-first review) and [ADR 0016](0016-trust-boundary-server-enforced-permissions.md) (authority is server-enforced — source visibility grants nothing). **Reverses the full-clone gate from task [#903](https://example.com/builders#/task/903).** Decision by Lars, 2026-06-13.
5
- **Status:** Accepted. Mechanism implemented under task [#1001](https://example.com/builders#/task/1001) (game-only entry `src/preview-server.js` + shared `registerGameRooms()` helper, `STARTER_SPARSE_PATHS` widened by `src/world`/`src/rooms`/`public`, `box-game-preview.service` repointed at the game-only entry, `box-source-fetch.sh` ungated); **hardware-verified under task [#1002](https://example.com/builders#/task/1002) (2026-06-14)** — a fresh **Xenos starter-scope** box (`LarsCode`) served the playable game over the public tunnel at `sandbox-<login>.example.com` (HTTP 200, Phaser client + `/game/*` assets) while **(b)** `/api/gds/*` returned 404 through that host (game-only entry does not mount the internal API) and **(c)** `migrations/` was absent on the box (the game paths `src/world`/`src/rooms`/`public` were present). Box deprovisioned after the run.
5
+ **Status:** Superseded in part by [ADR 0346](0346-dev-boxes-are-retired.md) (the per-box half; the local game-only preview survives). Was: Accepted. Mechanism implemented under task [#1001](https://example.com/builders#/task/1001) (game-only entry `src/preview-server.js` + shared `registerGameRooms()` helper, `STARTER_SPARSE_PATHS` widened by `src/world`/`src/rooms`/`public`, `box-game-preview.service` repointed at the game-only entry, `box-source-fetch.sh` ungated); **hardware-verified under task [#1002](https://example.com/builders#/task/1002) (2026-06-14)** — a fresh **Xenos starter-scope** box (`LarsCode`) served the playable game over the public tunnel at `sandbox-<login>.example.com` (HTTP 200, Phaser client + `/game/*` assets) while **(b)** `/api/gds/*` returned 404 through that host (game-only entry does not mount the internal API) and **(c)** `migrations/` was absent on the box (the game paths `src/world`/`src/rooms`/`public` were present). Box deprovisioned after the run.
6
6
  **Track:** `internal` (dev boxes / builder experience).
7
7
 
8
8
  ## Problem
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Date:** 2026-06-13
4
4
  **Context:** GDS, security reports SR[#2](https://example.com/builders#/task/2) (HIGH) + SR[#11](https://example.com/builders#/task/11) (HIGH) from the 2026-06-08 server audit ([#870](https://example.com/builders#/task/870)); task [#919](https://example.com/builders#/task/919). Owner decision 2026-06-09: do the proper redesign, not the interim named-tunnel disable. Governed by the trust-boundary rule in [ADR 0016](0016-trust-boundary-server-enforced-permissions.md) and the box subsystem in [ADR 0031](0031-cloud-dev-environments-for-builders.md) / [ADR 0038](0038-chromebook-ttyd-cloudflare-tunnel.md) / [ADR 0044](0044-per-box-live-game-preview.md).
5
- **Status:** Accepted.
5
+ **Status:** Superseded by [ADR 0346](0346-dev-boxes-are-retired.md) — the dev box was removed (goal 1000120). Was: Accepted.
6
6
  **Track:** `internal` (development system / builder dev boxes + access control).
7
7
 
8
8
  ## Problem
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Date:** 2026-06-13
4
4
  **Context:** GDS, task [#1025](https://example.com/builders#/task/1025). A live "can I publish from a dev box?" test failed even after CI self-deploy ([#859](https://example.com/builders#/task/859) / [ADR 0042](0042-builder-self-deploy-ci-auto-merge.md)) went live. Sits at the intersection of [ADR 0042](0042-builder-self-deploy-ci-auto-merge.md) (ci deploy mode), [ADR 0053](0053-scoped-dev-box-session.md) (box-scoped session, [#919](https://example.com/builders#/task/919)), and the box on-ramp ([ADR 0038](0038-chromebook-ttyd-cloudflare-tunnel.md) browser-only builders, [ADR 0044](0044-per-box-live-game-preview.md), [ADR 0046](0046-sandbox-first-review-gate.md) sandbox-first ship gate / [#927](https://example.com/builders#/task/927), which expects `/builder-ship` to run *on* a box). Governed by the trust boundary in [ADR 0016](0016-trust-boundary-server-enforced-permissions.md).
5
- **Status:** Accepted.
5
+ **Status:** Superseded in part by [ADR 0346](0346-dev-boxes-are-retired.md) (the dev box as its reason — the publish mechanism SURVIVES and now serves any checkout with no push credential). Was: Accepted.
6
6
  **Track:** `internal` (development system / builder dev boxes + ship pipeline).
7
7
 
8
8
  ## Problem
@@ -1,7 +1,7 @@
1
1
  # ADR 0057 — Per-builder container cost ledger (org-funded → self-fund tracking)
2
2
 
3
3
  **Date:** 2026-06-15
4
- **Status:** Accepted
4
+ **Status:** Superseded by [ADR 0346](0346-dev-boxes-are-retired.md) — the dev box was removed (goal 1000120). Was: Accepted
5
5
  **Track:** `internal` (dev-system / cost oversight).
6
6
  **Context:** GDS-V3, task [#602](https://example.com/builders#/task/602), criterion C-cost. Implements the ledger half of ADR 0031 §5 (cost passthrough). Companion to [ADR 0031](0031-cloud-dev-environments-for-builders.md) (the dev box) and the early-stage billing policy ("tracked, not settled" — both example earnings and container costs are recorded but not actually paid/charged yet).
7
7
 
@@ -1,6 +1,6 @@
1
1
  # ADR 0059 — Single approval: remove the dev-box (first-box) Archon approval gate
2
2
 
3
- - **Status:** Accepted
3
+ - **Status:** Superseded by [ADR 0346](0346-dev-boxes-are-retired.md) — the dev box was removed (goal 1000120). Was: Accepted
4
4
  - **Date:** 2026-06-16
5
5
  - **Track:** internal
6
6
  - **Supersedes:** [ADR 0035](0035-builder-onboarding-three-paths.md) §2 (the first-box Archon approval gate, [#717](https://example.com/builders#/task/717) / migration 071) and the **box half** of [ADR 0057](0057-discord-archon-approval-channels.md) (the `#box-approvals` channel + the box-intent approve/deny wiring)
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Date:** 2026-06-20
4
4
  **Context:** GDS / dev boxes, task [#1289](https://example.com/builders#/task/1289). Builds on [ADR 0031](0031-cloud-dev-environments-for-builders.md) (cloud dev environments) and [ADR 0053](0053-scoped-dev-box-session.md) (scoped dev-box session). Touches `scripts/gds/box.js`, `src/bongos/boxes.js`, `src/bongos/do-api.js`, `infra/box-drift-reconcile.{service,timer}`.
5
- **Status:** Accepted.
5
+ **Status:** Superseded by [ADR 0346](0346-dev-boxes-are-retired.md) — the dev box was removed (goal 1000120). Was: Accepted.
6
6
  **Track:** `internal` (development system / builder dev boxes).
7
7
 
8
8
  ## Problem — the "zombie" box
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Date:** 2026-06-20
4
4
  **Context:** Bongos App `BONGOS-V1` / criterion C1 (signed-installable), task [#1296](https://example.com/builders#/task/1296) (`BV1.R01`). Builds on [ADR 0045](0045-devbox-desktop-app.md) (the Dev Box desktop app) and [ADR 0004](0004-example-name-and-trademark-acceptance.md) (brand discipline). The bongos app forks the Dev Box app's Electron shell ([#1298](https://example.com/builders#/task/1298) `BV1.R03`), so it inherits that app's signing machinery; this ADR pins which parts it inherits now and which it defers.
5
- **Status:** Accepted.
5
+ **Status:** Superseded in part by [ADR 0346](0346-dev-boxes-are-retired.md) (absorbing the Dev Box app, which was deleted). Was: Accepted.
6
6
  **Track:** `internal` (development system → the Cloud Bongos desktop app line; bongos succeeds the GDS after GDS-V4).
7
7
 
8
8
  ## Problem — an unsigned mic + screen app reads as hostile
@@ -1,6 +1,6 @@
1
1
  # ADR 0072 — Dev-box code-staleness: make it visible, never auto-reset
2
2
 
3
- - **Status:** Accepted
3
+ - **Status:** Superseded by [ADR 0346](0346-dev-boxes-are-retired.md) — the dev box was removed (goal 1000120). Was: Accepted
4
4
  - **Date:** 2026-06-20
5
5
  - **Track:** internal
6
6
  - **Builds on:** [ADR 0031](0031-cloud-dev-environments-for-builders.md) (per-builder dev boxes), the `box-source-fetch.sh` self-update machinery ([#600](https://example.com/builders#/task/600), [#985](https://example.com/builders#/task/985)), and task [#1187](https://example.com/builders#/task/1187) (the box host-key reporter — the report-up cron pattern this mirrors)
@@ -21,7 +21,7 @@ Two prior decisions were supposed to prevent this and don't fully:
21
21
 
22
22
  ## Decision
23
23
 
24
- **Pre-allow the generic GDS API channel.** Add `Bash(node scripts/gds/api.js:*)` to the project `.claude/settings.json` `permissions.allow`. It ships in the repo, so it reaches the box, laptops, and **every permission mode** at once, and it is locked against silent regression by [`tests/box_ship_permissions.mjs`](../../tests/box_ship_permissions.mjs).
24
+ **Pre-allow the generic GDS API channel.** Add `Bash(node scripts/gds/api.js:*)` to the project `.claude/settings.json` `permissions.allow`. It ships in the repo, so it reaches the box, laptops, and **every permission mode** at once, and it is locked against silent regression by [`tests/box_ship_permissions.mjs`](../../tests/cli_allowlist_permissions.mjs).
25
25
 
26
26
  The owner chose **"trust the whole channel"** over a narrower "reads + a few specific write paths" split — the split is brittle (breaks when a skill uses a slightly different path or flag order) and buys only illusory least-privilege, because the server already gates every write by rank.
27
27
 
@@ -1,6 +1,6 @@
1
1
  # ADR 0123 — Idle-swept dev boxes lose uncommitted work: an on-box autosave-push, not a VM snapshot
2
2
 
3
- - **Status:** Accepted (the approach + rejected alternatives are decided; the cron script + operator credential wiring are task-pending — see §Consequences for the seeded follow-up). **No autosave code ships in this ADR — it is a SPIKE.**
3
+ - **Status:** Superseded by [ADR 0346](0346-dev-boxes-are-retired.md) — the dev box was removed (goal 1000120). Was: Accepted (the approach + rejected alternatives are decided; the cron script + operator credential wiring are task-pending — see §Consequences for the seeded follow-up). **No autosave code ships in this ADR — it is a SPIKE.**
4
4
  - **Date:** 2026-07-05
5
5
  - **Track:** internal (dev-box lifecycle)
6
6
  - **Task:** [#837](https://example.com/builders#/task/837) — "SPIKE: don't lose uncommitted work when a dev box is reclaimed (idle sweep deprovisions, no snapshot)."
@@ -1,6 +1,6 @@
1
1
  # 0144 — Re-home the dev-box fleet onto the cloudbongos.com plane (native runners, local DB, isolated fleet tag)
2
2
 
3
- - **Status:** Accepted — Phases 1–3 built in task 1002239. **Phase 4 part (a) (stop legacy `cohost-box-*` runners) done in task 1002248** (2026-07-15); part (b) (disable dev-box on example.com) flagged to owner — not reachable from the cloudbongos control plane.
3
+ - **Status:** Superseded by [ADR 0346](0346-dev-boxes-are-retired.md) — the dev box was removed (goal 1000120). Was: Accepted — Phases 1–3 built in task 1002239. **Phase 4 part (a) (stop legacy `cohost-box-*` runners) done in task 1002248** (2026-07-15); part (b) (disable dev-box on example.com) flagged to owner — not reachable from the cloudbongos control plane.
4
4
  - **Date:** 2026-07-15
5
5
  - **Deciders:** Lars (owner/Archon) chose "re-home properly, not a legacy band-aid" + pre-approved box spend; Claude designed + executed autonomously.
6
6
  - **Task:** [#1002239](https://cloudbongos.com/builders#/task/1002239) · supersedes stale incident [#1002031](https://cloudbongos.com/builders#/task/1002031) · **Goal:** 1000025 (builder experience — hall, dev box, skills).
@@ -1,6 +1,6 @@
1
1
  # 0145 — The Dev Box app becomes a branding-driven module (one source, per-instance builds)
2
2
 
3
- - **Status:** Accepted — Phase 1 built in task [#1002255](https://cloudbongos.com/builders#/task/1002255). Downloads (1002257), CI + releases repo + signing (1002258), and end-to-end verify (1002256) follow.
3
+ - **Status:** Superseded by [ADR 0346](0346-dev-boxes-are-retired.md) — the dev box was removed (goal 1000120). Was: Accepted — Phase 1 built in task [#1002255](https://cloudbongos.com/builders#/task/1002255). Downloads (1002257), CI + releases repo + signing (1002258), and end-to-end verify (1002256) follow.
4
4
  - **Date:** 2026-07-15
5
5
  - **Deciders:** Lars (owner) — "re-set up the dev box app so it's properly installable for cloudbongos; the design should not be linked to a specific project but to the Cloud Bongos design; it should live on cloudbongos and be maintained there as a module, and Example should borrow it."
6
6
  - **Extends:** ADR 0045 (the Dev Box desktop app), ADR 0072 (app signing posture), ADR 0083 (module system), ADR 0004/0062 (brand discipline — no hardcoded host identity), [branding contract](../branding-contract.md).
@@ -1,9 +1,9 @@
1
1
  # 0148 — Task-scoped box source access (rank-scope → claim-scope)
2
2
 
3
- - **Status:** Accepted (spike R90 / task 1002378 — the architecture pass for goal 1000051). Confirms the build shape of R92–R95.
3
+ - **Status:** Superseded by [ADR 0346](0346-dev-boxes-are-retired.md) — the dev box was removed (goal 1000120). Was: Accepted (spike R90 / task 1002378 — the architecture pass for goal 1000051). Confirms the build shape of R92–R95.
4
4
  - **Date:** 2026-07-18
5
5
  - **Deciders:** Lars (owner) — "claim a task → the box pulls only that module's code, on a base Bongos instance; the GitHub token stays on the server." Corrected the earlier "bring-your-own-GitHub" framing.
6
- - **Extends:** ADR 0031 §6 (box source-access, task 600), ADR 0086 (goals + `scope_modules` scope wall), ADR 0093 (the `lifecycle` port), ADR 0052 (sandbox-for-everyone starter scope). Spec: [`docs/specs/<redacted>.md`](../specs/<redacted>.md).
6
+ - **Extends:** ADR 0031 §6 (box source-access, task 600), ADR 0086 (goals + `scope_modules` scope wall), ADR 0093 (the `lifecycle` port), ADR 0052 (sandbox-for-everyone starter scope). Spec: `docs/specs/<redacted>.md` (deleted with the dev box by task 1003898; read it in git history).
7
7
 
8
8
  ## Context
9
9
 
@@ -1,6 +1,6 @@
1
1
  # 0151 — Governance: permissions as the atom, ranks as seeded roles
2
2
 
3
- - **Status:** Accepted
3
+ - **Status:** Superseded in part by [ADR 0346](0346-dev-boxes-are-retired.md) (§3 — the narrowing session scope was removed; the declared-source rule survives). Was: Accepted
4
4
  - **Date:** 2026-07-24
5
5
  - **Deciders:** Lars (owner / Archon), Claude
6
6
  - **Track:** `internal` (GDS / methodology — a Cloud Bongos platform capability)
@@ -1,6 +1,6 @@
1
1
  # 0193 — Pause task-scoped box slices: a box serves its rank scope (the full repo for Metic+)
2
2
 
3
- - **Status:** Accepted
3
+ - **Status:** Superseded by [ADR 0346](0346-dev-boxes-are-retired.md) — the dev box was removed (goal 1000120). Was: Accepted
4
4
  - **Date:** 2026-08-25
5
5
  - **Tasks:** [#1003285](https://cloudbongos.com/builders#/task/1003285) (the pause), from the owner's 2026-08-25 dev-box efficiency review; the review's other findings are [#1003286](https://cloudbongos.com/builders#/task/1003286)–[#1003291](https://cloudbongos.com/builders#/task/1003291) and shipped [#1003253](https://cloudbongos.com/builders#/task/1003253).
6
6
  - **Pauses, does not repeal:** [ADR 0148](0148-task-scoped-box-source-access.md) / goal 1000051 — the claim-driven slice. The machinery stays; the default flips.
@@ -1,6 +1,6 @@
1
1
  # ADR 0277 — A box is "in use" only while a human is attached, and the claim expires
2
2
 
3
- - **Status:** accepted
3
+ - **Status:** Superseded by [ADR 0346](0346-dev-boxes-are-retired.md) — the dev box was removed (goal 1000120). Was: accepted
4
4
  - **Date:** 2026-09-10
5
5
  - **Task:** [1003507](https://cloudbongos.com/builders#/task/1003507) (goal 1000095 — *Working area 6*, criterion `wa6-role-experience`)
6
6
  - **Supersedes the "never touch a box with a claude process" rule** in [ADR 0031](0031-cloud-dev-environments-for-builders.md) §5(a); the park/preserve guarantee of tasks 1002726/1002727 is unchanged and is what makes this safe.
@@ -0,0 +1,69 @@
1
+ # ADR 0346 — Dev boxes are retired; a builder builds from their own checkout
2
+
3
+ - **Status:** accepted
4
+ - **Date:** 2026-09-28
5
+ - **Task:** [task 1003898](https://cloudbongos.com/builders#/task/1003898) (goal 1000120 — Dev-box removal)
6
+ - **Deciders:** Lars (Archon) decided the removal and its three rulings on 2026-09-13. Claude carried out the removal and wrote the record.
7
+ - **Supersedes:** [0031](0031-cloud-dev-environments-for-builders.md) · [0044](0044-per-box-live-game-preview.md) · [0045](0045-devbox-desktop-app.md) · [0053](0053-scoped-dev-box-session.md) · [0057](0057-container-cost-ledger.md) · [0059](0059-single-approval-remove-devbox-approval-gate.md) · [0071](0071-box-confirm-before-destroyed-and-drift-reconcile.md) · [0072 (code staleness)](0072-dev-box-code-staleness-visibility.md) · [0123](0123-box-idle-sweep-autosave-before-destroy.md) · [0144](0144-devbox-rehome-onto-cloudbongos-plane.md) · [0145 (desktop-app branding)](0145-devbox-app-branding-driven-module.md) · [0148](0148-task-scoped-box-source-access.md) · [0193](0193-pause-task-scoped-box-slices.md) · [0277](0277-a-box-is-in-use-only-while-a-human-is-attached.md)
8
+ - **Supersedes in part:** [0035](0035-builder-onboarding-three-paths.md) (the DO-box path) · [0046](0046-sandbox-first-review-gate.md) (the box half) · [0052](0052-sandbox-for-everyone-game-only-preview.md) (the box half) · [0055](0055-server-mediated-branch-publish.md) (the box as its reason; the mechanism survives) · [0072 (Bongos app)](0072-bongos-app-mac-signed-first-windows-deferred.md) (absorbing the Dev Box app) · [0151](0151-governance-permissions-as-atom-ranks-as-roles.md) §3 (the narrowing session scope)
9
+
10
+ ## Context
11
+
12
+ ADR 0031 gave every builder a hosted cloud machine, the **dev box**: a DigitalOcean droplet built from `.devcontainer/`, switched on and off by a desktop app (0045), reached over SSH or a browser terminal, holding a box-scoped session (0053) and a task-scoped sparse checkout (0148), swept when idle (0123), and landing its work through the server because it held no push credential (0055). It grew to roughly 22,000 lines, and about a third of it lived in the core rather than in `modules/dev-box/`.
13
+
14
+ By 2026-09-13 it had no users. The fleet was cold: 0 live droplets, 4 destroyed, 1 parked. `/downloads/devbox/*` already answered 404, because cloudbongos.com had no `config/devbox-app.json`. Every live builder builds from a checkout of the project repo on their own machine. The owner decided to remove it outright rather than keep maintaining it.
15
+
16
+ ## Decision
17
+
18
+ We removed the dev box and everything that existed only for it. What a builder does instead is the path that already worked for everyone: **clone the project repo, sign the CLI in with `/builder-setup`, and build locally** (`/builder-stage` for a local preview). A cloud replacement, such as Claude's own cloud sessions working from a clone, is separate later work and is deliberately not designed here.
19
+
20
+ **The owner's three rulings (2026-09-13):**
21
+
22
+ 1. **Drop the box's stored data now.** The historic box compute spend is not worth preserving as box state.
23
+ 2. **Delete `.devcontainer/`** with the rest. It was the box as code; a later cloud plan defines its own environment.
24
+ 3. **Remove `bongos box`, `bongos shell` and `bongos code` entirely**, including their Metic-only `--local` modes.
25
+
26
+ **What was removed** (goal 1000120, one linear chain, each link leaving `main` green):
27
+
28
+ | Task | Removed |
29
+ |---|---|
30
+ | [1003889](https://cloudbongos.com/builders#/task/1003889) | the three CLI verbs |
31
+ | [1003890](https://cloudbongos.com/builders#/task/1003890) | the Harbor page, the box panel and the pair page |
32
+ | [1003891](https://cloudbongos.com/builders#/task/1003891) | the Electron desktop app, its CI workflow and download route |
33
+ | [1003896](https://cloudbongos.com/builders#/task/1003896) | `.devcontainer/` |
34
+ | [1003893](https://cloudbongos.com/builders#/task/1003893) | the box control-plane and bring-up scripts (`scripts/gds/box*`, `infra/box-*`), with the last box recipe |
35
+ | [1003892](https://cloudbongos.com/builders#/task/1003892) | `modules/dev-box/` and its registrations |
36
+ | [1004310](https://cloudbongos.com/builders#/task/1004310) | desktop-app pairing, the onboarding box step, and box fields in the core API |
37
+ | [1004311](https://cloudbongos.com/builders#/task/1004311) | the hall's box surfaces, preview fixtures, and the DEV BOX subgraph of the architecture diagram |
38
+ | [1003894](https://cloudbongos.com/builders#/task/1003894) | the box session scope and `box.source.full` / `box.fleet.manage` / `box.manage.own` (migration `government_019`) |
39
+ | [1003895](https://cloudbongos.com/builders#/task/1003895) | `builder_boxes`, `box_events`, `box_intents`, `builder_ssh_keys` and the `'box'` session source (migration `core_258`) |
40
+ | [1003897](https://cloudbongos.com/builders#/task/1003897) | the residual mentions in code, tests and fixtures |
41
+ | [1003899](https://cloudbongos.com/builders#/task/1003899) | (the fitness check that keeps it out) |
42
+
43
+ **Kept on purpose.** These were born for the box and are now load-bearing for everyone:
44
+
45
+ - **Server-mediated publish** (0055: `modules/lifecycle/github-push.js`, `publish-reconciler.js`, `POST /tasks/:id/publish-branch`, `ship-land.js`'s `ciLandServer`). It serves any checkout with no GitHub push credential. Only its reason changed.
46
+ - **`src/bongos-downloads.js`**, the `bongos` CLI binary downloads (the Dev Box app's own downloads were removed).
47
+ - **`src/bongos/secret-box.js`**, the AES secret store. It is unrelated to dev boxes despite the name.
48
+ - **`scripts/gds/do-api.js`**, which instance provisioning still uses.
49
+ - **The session-source registry** (`modules/government/session-scopes.json`). Its narrowing form had no user left and was removed (task 1003894). Its fail-closed rule, that a session whose source the registry does not declare is refused on every route and page, is what kept the leftover box tokens out until `core_258` deleted them.
50
+
51
+ **Deliberate retirement guards.** These still name the box, and that is correct:
52
+
53
+ - `RETIRED_MODULE_KEYS` in `src/modules.js`: an instance whose config still says `"dev-box": true` boots with a one-line warning instead of failing.
54
+ - `allowBoxScope` stays on the module doorway as a no-op until the next MAJOR. Removing an export is a MAJOR, and modules declare `^1`.
55
+ - `config/devbox-app.json` stays in the publish manifest's instance-exclude list, because instance repos still carry the file.
56
+
57
+ ## Alternatives considered
58
+
59
+ - **Keep the module, switched off.** Rejected: a third of it lived in the core (auth, migrations, the ship path, the hall), so "off" still cost maintenance and review attention on every change near it, for zero users.
60
+ - **Replace it with a cloud-session product in the same goal.** Rejected by the owner: the replacement is its own design question, and coupling it would have held the removal hostage to it.
61
+ - **One big deletion.** Rejected in the 2026-09-27 re-scope: each link deletes its own tests and regenerates its own artifacts, so `main` stays green at every step and any one link can be reverted alone.
62
+ - **Drop the four `builders.box_blocked*` columns with the tables.** Deferred to [task 1004360](https://cloudbongos.com/builders#/task/1004360). A deploy migrates while the previous server is still up, and a failed upgrade rolls back code but never schema. Every previous core reads those columns in `getBuilderById`.
63
+
64
+ ## Consequences
65
+
66
+ - A builder's only setup is a local checkout. The hall's welcome panel, the primer and the architecture diagram now describe that path. The welcome panel's own-machine steps had been hidden by a stylesheet rule written for the box's Desktop/Online toggle; they now show.
67
+ - Nothing user-facing regressed: the fleet was cold and the downloads already 404'd.
68
+ - Owner follow-ups outside the code: reclaim or verify absent the DigitalOcean and Cloudflare resources (task [1003887](https://cloudbongos.com/builders#/task/1003887), blocker 1000159, including the one parked droplet snapshot). Remove `"dev-box"` from each instance repo's `config/modules.json` and `config/devbox-app.json` when convenient; the retirement guard makes both harmless meanwhile.
69
+ - The historical ADRs above keep their bodies; each carries a status line pointing here.
@@ -437,3 +437,4 @@ This keeps the decision history honest and traceable.
437
437
  | 0343 | [**A module's score is a security gate, then an average of parts every buyer can see** ([task 1003790](https://cloudbongos.com/builders#/task/1003790), goal 1000091 — working area 5, owner Will). No module score existed; the floor, ranking and cap all derive from this one. **D1:** five parts, each 0–100 per version — Security and Tests day one; Install, Reliability (from real installs) and Tester feedback later. **D2 (owner):** failing Security means not listed, never averaged in. **D3 (owner):** overall = unweighted average of the other parts that have data; a missing part is left out, not zero. **D4 (owner):** every part's score is shown to buyers beside the overall, so they can pick the module strongest where they care (tasks 1003798/1003799). **D5:** a version without real-world data is labelled "New". **D6:** price is never an input; the Metic+ override/delist sits on top and is audited. Rejected: security in the average, day-one weights, a single number, missing-as-zero.](0343-a-module-score-is-a-security-gate-then-an-average-of-visible-parts.md) | modules / store / quality |
438
438
  | 0344 | [**A tester is a project that opts in once; an untested version reaches everyone after seven days** ([task 1003801](https://cloudbongos.com/builders#/task/1003801), goal 1000091 — working area 5, owner Will). Settles "willing user" for criterion `wa5-staged-rollout`. **D1 (owner):** a project's own admin switches on "tester" once and gets tester versions of every module it has, with a per-module "general only" override; never on by default; a builder cannot opt in someone else's project. **D2:** first releases and updates alike go to testers first. **D3 (owner):** a version moves to general after seven days if it still passes the security gate and tests, tested or not; the promotion gate may promote earlier or hold on evidence, never forever. **D4:** testers pay the normal price; any tester discount is area 8's call, named not decided. **D5:** tester installs, errors and crashes feed the score (ADR 0343). Rejected: per-module-only opt-in, one all-or-nothing switch, waiting for a tester, releasing at once.](0344-a-tester-is-a-project-that-opts-in-once.md) | modules / store / rollout |
439
439
  | 0345 | [**We host every project's hall, and its app deploys where the owner chooses** ([task 1004349](https://cloudbongos.com/builders#/task/1004349), goal 1000106 — working area 1, owner Lars). Reverses ADR 0323 §2 and the hall half of ADR 0327. **D1 (owner):** every project's Builders Hall runs on our shared server; `cloud-host` now means "hosted by us". **D2 (owner):** the hall's address is ours or the owner's own domain. **D3 (owner):** the setup wizard asks where the APP deploys; Render only at launch; choosing it creates the app on the owner's own Render account with ADR 0327's borrowed key. **D4 (owner):** "decide later" is allowed. **D5 (owner):** no project is moved. **D6 (measured):** ADR 0145 Finding 1 is live — the hub cookie is `Domain=.cloudbongos.com` and a hall loads modules from its own repo — so our-address halls need task 1004357; an owner domain is safe. **D7 (measured):** at the ceiling the create route refuses `box_full` up front, and the resize is not a prerequisite. Task 1004184 re-scoped, task 1004185 on hold.](0345-we-host-every-projects-hall-and-its-app-deploys-where-the-owner-chooses.md) | hosting / provisioning / security |
440
+ | 0346 | [**Dev boxes are retired; a builder builds from their own checkout** ([task 1003898](https://cloudbongos.com/builders#/task/1003898), goal 1000120 — owner Lars). Records the whole removal, link by link, the owner's three rulings of 2026-09-13 (drop the data, delete `.devcontainer/`, remove `bongos box`/`shell`/`code`), what was kept on purpose (server-mediated publish, the CLI downloads, `secret-box`, `do-api`, the declared-source rule), and the retirement guards that still name the box. Supersedes 0031, 0044, 0045, 0053, 0057, 0059, 0071, 0072 (code staleness), 0123, 0144, 0145 (desktop-app branding), 0148, 0193, 0277; supersedes in part 0035, 0046, 0052, 0055, 0072 (Bongos app), 0151 §3.](0346-dev-boxes-are-retired.md) | builder environment / removal |
@@ -11,7 +11,7 @@
11
11
 
12
12
  - **Domain:** `example.com` — registered at Cloudflare Registrar. DNS A records (apex + `www`) point to the droplet at `REDACTED_IP`. Cloudflare proxy is **ON (orange cloud)**. CF terminates TLS at the edge; the **Cloudflare Origin Certificate** handles the CF↔origin leg (valid through 2041-05-04). A `status` subdomain is added at PMS-V1 deploy time (see `docs/pms-v1-deploy.md` (instance-side)) with the same proxy/cert posture; Origin Cert needs `*.example.com` SAN. Real client IPs come in via `CF-Connecting-IP` / `X-Forwarded-For`, wired into Caddy's `trusted_proxies static` (the Cloudflare IP ranges) in the `infra/Caddyfile` global options block.
13
13
  - **Production droplet (co-hosting box):** DigitalOcean, hostname `example`, IPv4 `REDACTED_IP`, IPv6 `REDACTED_IP`. NYC3, Premium Intel 2 GB / 1 vCPU / 60 GB NVMe. Ubuntu 24.04 LTS. ~$14/mo. Hosts the OTB game + co-hosted project instances (`emersonian-circles.`, `staging.`).
14
- - **Cloud Bongos control-plane droplet (NEW 2026-07-05, [ADR 0126](adr/0126-dedicated-cloudbongos-control-plane-droplet.md), task [#2063](https://example.com/builders#/task/2063)):** DigitalOcean, hostname `cloudbongos`, IPv4 `REDACTED_IP`, NYC3, `s-1vcpu-2gb` (2 GB / 1 vCPU), Ubuntu 24.04, ~$12/mo, tag `cloudbongos-control`. Runs **cloudbongos.com + `builders.` + `status.`** (`src/platform-server.js`, Cloud Bongos brand, port 3002, own `cloudbongos` DB, checkout `/home/lars/cloudbongos-instance`, the root subscribed to the nightly core-patch sweep) and is the **sole token-holding control plane** — a SECOND root, `/home/lars/cloudbongos`, survives only to vendor `infra/` (the box cloud-init the core package does not ship, ADR 0150); it is not subscribed, so nothing may resolve core code from it (task 1002738, [ADR 0144](adr/0144-devbox-rehome-onto-cloudbongos-plane.md) follow-up 5) — `/etc/cloudbongos/box.env` holds the account-wide Cloudflare token (IP-locked to this box) + the DigitalOcean token; this is where `provision.js` provisions instance subdomains. **Structurally separate SSH** (own `cloudbongos_ed25519` key). IPv6 egress disabled so the IPv4-locked CF token can't be spuriously rejected. cloudbongos.com was previously a co-tenant on the co-hosting box; that unit was decommissioned at cutover. **Follow-ups:** deploy automation (task [#2064](https://example.com/builders#/task/2064)) + fully stripping cloud tokens off the co-hosting box (task [#2065](https://example.com/builders#/task/2065)).
14
+ - **Cloud Bongos control-plane droplet (NEW 2026-07-05, [ADR 0126](adr/0126-dedicated-cloudbongos-control-plane-droplet.md), task [#2063](https://example.com/builders#/task/2063)):** DigitalOcean, hostname `cloudbongos`, IPv4 `REDACTED_IP`, NYC3, `s-1vcpu-2gb` (2 GB / 1 vCPU), Ubuntu 24.04, ~$12/mo, tag `cloudbongos-control`. Runs **cloudbongos.com + `builders.` + `status.`** (`src/platform-server.js`, Cloud Bongos brand, port 3002, own `cloudbongos` DB, checkout `/home/lars/cloudbongos-instance`, the root subscribed to the nightly core-patch sweep) and is the **sole token-holding control plane** — a SECOND root, `/home/lars/cloudbongos`, is left over from the retired dev-box bring-up, which vendored `infra/` from it ([ADR 0346](adr/0346-dev-boxes-are-retired.md)); it is not subscribed, so nothing may resolve core code from it (task 1002738) — `/etc/cloudbongos/box.env` holds the account-wide Cloudflare token (IP-locked to this box) + the DigitalOcean token; this is where `provision.js` provisions instance subdomains. **Structurally separate SSH** (own `cloudbongos_ed25519` key). IPv6 egress disabled so the IPv4-locked CF token can't be spuriously rejected. cloudbongos.com was previously a co-tenant on the co-hosting box; that unit was decommissioned at cutover. **Follow-ups:** deploy automation (task [#2064](https://example.com/builders#/task/2064)) + fully stripping cloud tokens off the co-hosting box (task [#2065](https://example.com/builders#/task/2065)).
15
15
  - **Where projects run ([ADR 0345](adr/0345-we-host-every-projects-hall-and-its-app-deploys-where-the-owner-chooses.md), 2026-09-28):** every project's **Builders Hall** is hosted by us on the shared control-plane box (`hosting_shape='cloud-host'`, labelled "hosted by us"), at one of our addresses or the owner's own domain. The project's **app** deploys wherever its owner chooses; the setup wizard offers Render first, creating the app on the owner's own Render account with a borrowed, never-stored key (ADR 0327 §2). ADR 0323's plan to move the halls to Render is reversed. Halls at our addresses receive the hub cookie until task 1004357 ships.
16
16
  - **Server stack:** Node.js 22 LTS · PostgreSQL 16 · Caddy 2.11.2. `example.service` (systemd) runs `node server.js` as user `lars` on `127.0.0.1:3000`; restart-on-failure.
17
17
  - **Hardening:** `lars` user with passwordless sudo; SSH key-only (root login disabled, password auth disabled); ufw allows 22/80/443; fail2ban active; unattended-upgrades enabled; timezone `America/New_York`.
@@ -35,7 +35,6 @@ The product is organized as a small kernel (`src/`) + **19 modules** under `modu
35
35
  - **The loader** (`src/module-loader/loader.js`) — discovers `modules/*/module.json` at boot, validates manifests, checks `coreVersion` compatibility, and mounts each enabled module's routes behind kernel-composed auth. No core file changes to add or remove a module.
36
36
  - **Enablement** — `config/modules.json` (instance config) or `<PREFIX>_MODULE_<KEY>=1` (env override). Vanilla = all off.
37
37
  - **Feature modules** (optional — off on a vanilla instance, enabled per-instance via `config/modules.json`):
38
- - `dev-box` — per-builder cloud dev environments; ports: `box.hasEverConnected`
39
38
  - `game` — Phaser client + Colyseus rooms + world/terrain; ports: `game.staticRoot`, `game.registerRooms`, `game.precreateWorldRoom`
40
39
  - `discord` — ship broadcast + inbound bot + role-sync; port: `discord.isLinked`
41
40
  - `art-pipeline` — pixel-art generation + artist discipline; port: `art.sharedKeyConfigured`
@@ -67,7 +66,7 @@ The product is organized as a small kernel (`src/`) + **19 modules** under `modu
67
66
  **Code & deploy:**
68
67
 
69
68
  - **Code repo:** [github.com/example-owner/example](https://github.com/example-owner/example) — **private**. Clone URL: `git@github.com:example-owner/example.git`. Default branch: `main`. GitHub user: `example-owner`.
70
- - **Deploy:** two modes, selected by `config/deploy.json` `mode` (env `<PREFIX>_DEPLOY_MODE` overrides — `BONGOS_DEPLOY_MODE` on a vanilla instance; the legacy `OTB_DEPLOY_MODE` is still read), currently **`ci`** (flipped from `laptop` 2026-06-13, [#859](https://example.com/builders#/task/859)) — see [ADR 0042](adr/0042-builder-self-deploy-ci-auto-merge.md). **`laptop`** (legacy): `git push origin main` from the Mac → `ssh lars@REDACTED_IP ~/deploy.sh`. The droplet has a read-only deploy key at `~/.ssh/github_deploy` registered on the repo. `~/deploy.sh` does: `git fetch + reset --hard origin/main` → `npm ci --omit=dev` if `package-lock.json` changed → `./scripts/migrate.sh` → `sudo systemctl restart example` → `curl /healthz` smoke (**retried up to 15× @ 1s** — `systemctl` reports "active" before the Node process binds the port, so a single curl raced the bind and false-failed healthy deploys: [ADR 0056](adr/0056-prod-deploy-script-mirror-and-healthcheck-retry.md) / [#1026](https://example.com/builders#/task/1026)). Droplet checkout: `/home/lars/example/`. `~/deploy.sh` is hand-maintained on the droplet but now has a byte-faithful, reviewable repo mirror at `scripts/deploy/deploy-prod.sh` (instance-side) — **not** auto-installed (the ci deploy key is forced-command-locked, ADR 0042/0043; reinstall by hand on change: `scp scripts/deploy/deploy-prod.sh lars@…:deploy.sh`). **`ci`** (current, armed via [#679](https://example.com/builders#/task/679)): no builder box holds the droplet key — `ship.js` opens a PR + enables GitHub auto-merge, and `.github/workflows/deploy-prod.yml` (instance-side) runs the same `~/deploy.sh` from Actions on merge to `main`. Cutover preconditions (incl. a server-recorded **CI grade-gate**) are in ADR 0042.
69
+ - **Deploy:** two modes, selected by `config/deploy.json` `mode` (env `<PREFIX>_DEPLOY_MODE` overrides — `BONGOS_DEPLOY_MODE` on a vanilla instance; the legacy `OTB_DEPLOY_MODE` is still read), currently **`ci`** (flipped from `laptop` 2026-06-13, [#859](https://example.com/builders#/task/859)) — see [ADR 0042](adr/0042-builder-self-deploy-ci-auto-merge.md). **`laptop`** (legacy): `git push origin main` from the Mac → `ssh lars@REDACTED_IP ~/deploy.sh`. The droplet has a read-only deploy key at `~/.ssh/github_deploy` registered on the repo. `~/deploy.sh` does: `git fetch + reset --hard origin/main` → `npm ci --omit=dev` if `package-lock.json` changed → `./scripts/migrate.sh` → `sudo systemctl restart example` → `curl /healthz` smoke (**retried up to 15× @ 1s** — `systemctl` reports "active" before the Node process binds the port, so a single curl raced the bind and false-failed healthy deploys: [ADR 0056](adr/0056-prod-deploy-script-mirror-and-healthcheck-retry.md) / [#1026](https://example.com/builders#/task/1026)). Droplet checkout: `/home/lars/example/`. `~/deploy.sh` is hand-maintained on the droplet but now has a byte-faithful, reviewable repo mirror at `scripts/deploy/deploy-prod.sh` (instance-side) — **not** auto-installed (the ci deploy key is forced-command-locked, ADR 0042/0043; reinstall by hand on change: `scp scripts/deploy/deploy-prod.sh lars@…:deploy.sh`). **`ci`** (current, armed via [#679](https://example.com/builders#/task/679)): no builder machine holds the droplet key — `ship.js` opens a PR + enables GitHub auto-merge, and `.github/workflows/deploy-prod.yml` (instance-side) runs the same `~/deploy.sh` from Actions on merge to `main`. Cutover preconditions (incl. a server-recorded **CI grade-gate**) are in ADR 0042.
71
70
  - **Post-merge branch cleanup (standard practice):** Every feature branch that lands on main via `--no-ff` merge gets deleted on origin once the deploy succeeds. The merge commit itself preserves the branch's history in main, so the named ref isn't carrying any signal — keeping it just clutters GitHub's branch list and tricks the UI into offering empty PRs against zero-diff branches. The auto-merge in [`scripts/gds/ship.js`](../scripts/gds/ship.js) does this automatically after `~/deploy.sh` returns 0; the manual [`/merge-mode`](../.claude/skills/merge-mode/SKILL.md) flow follows the same step 5b. Local refs and worktree directories stay — only the origin branch and the local tracking ref (cleaned on next `git fetch --prune`) go.
72
71
  - **Local dev machine:** Lars's MacBook Air (Apple Silicon, macOS Sequoia). Tooling installed via Homebrew at `/opt/homebrew/`. Node v26.0.0 locally; `package.json` declares `"engines": { "node": ">=22" }`. Single ed25519 SSH key (`~/.ssh/id_ed25519`) authenticates to GitHub and droplet.
73
72
  - **Smoke tests:** lightweight scripts in `/tmp/colyseus-*-smoketest.js` verify joinOrCreate, move protocol, interact, identity, queue. Run any after deploy with `node /tmp/colyseus-<name>-smoketest.js`.
@@ -238,7 +237,7 @@ Bongos views: `claimable_tasks` (rebuilt in 006 to use SELECT t.*; rebuilt again
238
237
 
239
238
  **Bongos API (`/api/bongos/*`, mounted in the same Node process):**
240
239
 
241
- - **Canonical path is `/api/bongos` (task 1919); `/api/gds` is a PERMANENT alias.** The router + the discovery index are dual-mounted at both by `serve-internal.js`, driven by the single `src/bongos/api-prefix.js` constant (`API_PREFIX` + `LEGACY_API_PREFIXES`). The legacy `/api/gds` alias never goes away — shipped Dev Box binaries, the cached status mirror, and live boxes call it. **Exception:** the GitHub OAuth callback stays pinned to `/api/gds/auth/web/callback` (registered on the OAuth app; `src/bongos/routes/auth.js`). Not yet flipped (still ride the permanent alias): `src/**` internal callers + the deeper internal names (folders, `GDS_*` env, `gds_session` cookie) — the deferred internal-rename pass.
240
+ - **Canonical path is `/api/bongos` (task 1919); `/api/gds` is a PERMANENT alias.** The router + the discovery index are dual-mounted at both by `serve-internal.js`, driven by the single `src/bongos/api-prefix.js` constant (`API_PREFIX` + `LEGACY_API_PREFIXES`). The legacy `/api/gds` alias never goes away — shipped older CLI binaries, the cached status mirror, and older instances call it. **Exception:** the GitHub OAuth callback stays pinned to `/api/gds/auth/web/callback` (registered on the OAuth app; `src/bongos/routes/auth.js`). Not yet flipped (still ride the permanent alias): `src/**` internal callers + the deeper internal names (folders, `GDS_*` env, `gds_session` cookie) — the deferred internal-rename pass.
242
241
  - **Self-describing (task 1918, [ADR 0109](adr/0109-self-describing-openapi-and-hosted-docs.md)).** The whole surface is documented in the standard **OpenAPI 3.1** format at [`docs/api/openapi.json`](api/openapi.json), **generated from the live route files** by `scripts/gds/gen-api-docs.js` (reusing the same `route-rank-check.js` introspection the ship-time rank gate uses — so it can't drift; a fitness `--check` + ship-time regen enforce freshness). A rendered docs site (vendored Redoc) is served at **`/docs`** on the apex of every instance (`cloudbongos.com/docs` canonical); `GET /api/bongos` returns a machine-discovery index pointing at it. The generated [`docs/api-reference.md`](api-reference.md) supersedes the old hand-maintained `routes-permissions.md`. The mount prefix is the single `src/bongos/api-prefix.js` constant.
243
242
 
244
243
  - Auth: `POST /auth/device/start`, `/poll` (CLI Device Flow); `GET /auth/web/start`, `/web/callback` (browser); `POST /auth/logout`.
@@ -246,9 +245,9 @@ Bongos views: `claimable_tasks` (rebuilt in 006 to use SELECT t.*; rebuilt again
246
245
  - Authenticated CLI/web: `GET /me` (returns `rank`), `GET /versions[/progress]`, `GET /tasks[?version=&status=&kind=&discipline=]`, `GET /tasks/claimable[?version=&discipline=]`, `GET /tasks/:id`, `POST /tasks` (accepts `discipline` + `criterion_ids`; **metic+** — [ADR 0090](adr/0090-metic-task-authoring.md)), `PATCH /tasks/:id` (supports `parent_task_id`, `kind`, `discipline`, `goal_id` — (re)assign the task's goal; must be a goal in the task's own version, task 1763; **metic+**), `POST /tasks/:id/promote` (**metic+**), `POST /claims`, `POST /claims/:id/resolve`, `POST /cost`.
247
246
  - Criterion rollup + task↔criterion links ([ADR 0025](adr/0025-structured-criterion-task-link.md), [#435](https://example.com/builders#/task/435)/[#438](https://example.com/builders#/task/438)): `GET /versions/:id/progress` rolls up each done-when criterion → its gating tasks (via `task_criteria`) → live status counts + the not-yet-shipped `remaining[]` + `unattributed_tasks` (the read behind the `/status` skill, in `src/bongos/done-when.js criterionProgress`). The link CRUD mirrors the dependency endpoints: `GET /tasks/:id/criteria`, `POST /tasks/:id/criteria` (**metic+** — [ADR 0090](adr/0090-metic-task-authoring.md)) and `DELETE /tasks/:id/criteria/:criterionId` (**metic+**). A criterion ref is a numeric `done_when_criteria.id`, a positional `"Cn"` token, or a `criterion_id` slug, resolved against the task's version (`POST /tasks` links at create time so `/status` counts the task with no backfill).
248
247
  - Module store publish (ADR 0338 D1, task 1004271): `POST /store/modules/:key/versions` (`requireBuilder` + `requirePermission('module.submit')`, Metic floor). The body is the raw gzip tarball `bongos module publish` builds (own `express.raw` parser, 5 MB cap; 16 MB / 2000 files unpacked). `scripts/gds/module-artifact.js` re-verifies every hash and the publish gate, then `src/bongos/module-store.js` keeps the file under `var/module-store/` and inserts the `store_module_versions` row in one transaction. The first publish makes the caller the author; later versions are author-only, newer than the last and never overwritten; a delisted key takes none.
249
- - Server-mediated branch publish (ADR 0055 / [#1025](https://example.com/builders#/task/1025) — lets a dev box with no GitHub push credential ship). Owner-gated like ship: `POST /tasks/:id/publish-branch` (`requireBuilder` + `gateTaskOwnership`, **NOT** `allowBoxScope` → a box-scoped session is `403 box_scope`, so the builder must `/builder-reauth` first; own 32 MB json parser for the base64 thin-bundle body, 20 MB decoded cap; the server pushes the branch + opens the PR + auto-merges with a server-side push credential — a **GitHub App** installation token (short-lived, repo-scoped; preferred, [ADR 0055](adr/0055-server-mediated-branch-publish.md) update / task 1028) or the `GITHUB_PUSH_TOKEN` PAT fallback; `503 push_unconfigured` when neither is set; `400 tip_mismatch` if the bundle tip ≠ the claimed `head_sha`) and `GET /tasks/:id/publish-status?branch=…` (polls PR + deploy-prod state derived live from GitHub). `branch` is optional: without it the server finds the task's own PR by its `task <id>: …` title, and the answer names the `branch` it used and its `branch_source` (`query` / `task_pr`, or `null` with a `branch_hint` when there is no such PR) — never a `400` (task 1003764). When the PR is still open it also carries `merge_driver`, whose `reason` says why it has not merged; on a red PR `failing_tests` names the failing unit tests (read from the `unit-report` commit status the `unit` workflow posts) and `checks_unreadable: true` says the check list is blind because the App lacks `Checks: read` — so an empty `checks[]` is never read as "nothing failed" (task 1003988, ADR 0301). Because the server's credential is the PR's AUTHOR, publish also **assigns the PR to the task's claim holder** and names them in the body (`modules/lifecycle/pr-assign.js`, task 1003991) — best-effort: the 201 carries `pr_assignee` (the login, or `null` when GitHub would not assign it) and a failed assignment never fails the publish. `ship.js` uses these in `ci` mode only when `pushVia()` resolves to server (a box, or `<PREFIX>_PUSH_VIA_SERVER=1`); a laptop with `gh` keeps the local push path unchanged. Implementation in `src/bongos/github-push.js`.
248
+ - Server-mediated branch publish (ADR 0055 / [#1025](https://example.com/builders#/task/1025) — lets a checkout with no GitHub push credential ship). Owner-gated like ship: `POST /tasks/:id/publish-branch` (`requireBuilder` + `gateTaskOwnership`; own 32 MB json parser for the base64 thin-bundle body, 20 MB decoded cap; the server pushes the branch + opens the PR + auto-merges with a server-side push credential — a **GitHub App** installation token (short-lived, repo-scoped; preferred, [ADR 0055](adr/0055-server-mediated-branch-publish.md) update / task 1028) or the `GITHUB_PUSH_TOKEN` PAT fallback; `503 push_unconfigured` when neither is set; `400 tip_mismatch` if the bundle tip ≠ the claimed `head_sha`) and `GET /tasks/:id/publish-status?branch=…` (polls PR + deploy-prod state derived live from GitHub). `branch` is optional: without it the server finds the task's own PR by its `task <id>: …` title, and the answer names the `branch` it used and its `branch_source` (`query` / `task_pr`, or `null` with a `branch_hint` when there is no such PR) — never a `400` (task 1003764). When the PR is still open it also carries `merge_driver`, whose `reason` says why it has not merged; on a red PR `failing_tests` names the failing unit tests (read from the `unit-report` commit status the `unit` workflow posts) and `checks_unreadable: true` says the check list is blind because the App lacks `Checks: read` — so an empty `checks[]` is never read as "nothing failed" (task 1003988, ADR 0301). Because the server's credential is the PR's AUTHOR, publish also **assigns the PR to the task's claim holder** and names them in the body (`modules/lifecycle/pr-assign.js`, task 1003991) — best-effort: the 201 carries `pr_assignee` (the login, or `null` when GitHub would not assign it) and a failed assignment never fails the publish. `ship.js` uses these in `ci` mode only when `pushVia()` resolves to server (no authenticated `gh` on the machine, or `<PREFIX>_PUSH_VIA_SERVER=1`); a machine with `gh` keeps the local push path unchanged. Implementation in `src/bongos/github-push.js`.
250
249
  - Archon monitoring reads backing the `/watch` page (ADR 0036): `GET /builders/roster`, `GET /grades/by-builder[?days=N]` (**archon-only**, [#726](https://example.com/builders#/task/726) — per-builder grade breakdown for the MARKS section; the project-wide aggregate stays public at `/public/grades`), `GET /audit-log`, `GET /override-requests`, `GET /access-requests`, `GET /security/reports`. Personal-prefs writes backing `/settings`: `GET/PATCH /me/skill-prefs`, `PATCH /me/disciplines`.
251
- - Per-builder "needs" + own Gemini key ([ADR 0073](adr/0073-builder-needs-signal-and-byok-gemini-key.md), [#1013](https://example.com/builders#/task/1013)): `GET /me` now also carries `needs` ({items, action_needed_count} — the consistent "the system needs an input from you" signal; `modules/builder-settings/builder-needs.js` is the SSOT — carved out in BV1.R80, resolved by `GET /me` via the `builder-settings` kernel port — rendered by the hall Standing card + the CLI `printNeedsNudge`). The own-key (pragmatic BYOK) endpoints, all own-scoped: `GET /me/art-key/own` (masked meta — last4 only), `PUT /me/art-key/own` (validate-on-save via a Google list-models call → encrypt with `src/bongos/secret-box.js` → store; `503 storage_not_configured` until `BUILDER_SECRET_KEY` is set, `422 invalid_key` on a bad key), `DELETE /me/art-key/own`. The existing `GET /me/art-key` (shared-key box-sync delivery) is extended to also deliver the decrypted own key, which `scripts/gds/fetch-art-key.js` syncs into the local `gemini_api_key` slot (own key wins in the `gen_api.py` cascade).
250
+ - Per-builder "needs" + own Gemini key ([ADR 0073](adr/0073-builder-needs-signal-and-byok-gemini-key.md), [#1013](https://example.com/builders#/task/1013)): `GET /me` now also carries `needs` ({items, action_needed_count} — the consistent "the system needs an input from you" signal; `modules/builder-settings/builder-needs.js` is the SSOT — carved out in BV1.R80, resolved by `GET /me` via the `builder-settings` kernel port — rendered by the hall Standing card + the CLI `printNeedsNudge`). The own-key (pragmatic BYOK) endpoints, all own-scoped: `GET /me/art-key/own` (masked meta — last4 only), `PUT /me/art-key/own` (validate-on-save via a Google list-models call → encrypt with `src/bongos/secret-box.js` → store; `503 storage_not_configured` until `BUILDER_SECRET_KEY` is set, `422 invalid_key` on a bad key), `DELETE /me/art-key/own`. The existing `GET /me/art-key` (shared-key delivery) is extended to also deliver the decrypted own key, which `scripts/gds/fetch-art-key.js` syncs into the local `gemini_api_key` slot (own key wins in the `gen_api.py` cascade).
252
251
  - Builder memory (ADR 0024 cloneable memory + ADR 0026 BFG). Self-scoped (owner is always `req.builder.id`, never input): `POST /memory/sync` (push own memory; own 64 MB parser, vs the global 64 KB), `GET /memory/files`, `GET /memory/file`, `DELETE /memory/file` (the BFG delete affordance, 6C.2). Cross-builder (input-owner) endpoints — all privileged + audit-logged fail-closed: `GET /memory/builders/:id/files`+`/file` (**archon forensic** read), `GET /memory/bfg/builders/:id/files`+`/file` (**BFG-principal only**, 6B.1 read), and the one cross-builder WRITE `POST /memory/builders/:id/bfg-write` (**BFG-principal only**, kill-switched `BFG_WRITE_ENABLED` default-OFF, namespaced `bfg/`, attributed `author: BFG`, write+audit in one tx — dreams + transparent corrections, 6C.1/6C.2).
253
252
  - Session corpus (BFG evaluator — 6D, ADR 0027): `POST /sessions` (upload own session digest; own **4 MB** json parser — capped, vs the global 64 KB — and the digest is per-turn metadata + short scrubbed snippets, never raw transcript content), `GET /sessions/mine` (self-serve), `GET /sessions/search` (cross-builder, **archon-gated** — the BFG-principal stand-in; the principal now exists (6C.1) and the *memory* cross-reads moved to it (6B.1), but these *session* reads still use the archon stand-in pending a retrofit, + audit_log row per read), `GET /sessions/:id` (own self-serve; cross-builder needs archon + audit; non-owner → 404).
254
253
  - Public (no auth, `Cache-Control: max-age=60`): `/public/versions`, `/public/progress`, `/public/cost-summary`, `/public/recent-shipped`, `/public/leaderboard`, `/public/grades[?days=N]`, `/public/tasks/:id` ([#604](https://example.com/builders#/task/604) — single-task resolver for `#NNN` doc deep-links; `title`/`value_summary`/`visual_url` returned **only** for `shipped`|`confirmed` work and withheld for in-flight tasks so unshipped/security task names can't leak; the status dashboard renders it at `#/task/:id`), `/public/ref-ids` ([#653](https://example.com/builders#/task/653) — `{tasks:[ids]}`, ids only, token-free; the doc-ref linkifier + its CI gate consult it to decide which bare `#NNN` are real task refs). These power `status.example.com`.
@@ -29,7 +29,7 @@ env override → instance config (config/branding.json) → neutral star
29
29
  | `domains.cookieDomain` | Session cookie domain (`""` = host-only — the safe default; never widen to a parent domain by accident). |
30
30
  | `domains.oauthOrigin` | Canonical sign-in origin. |
31
31
  | `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)) |
32
- | `domains.instanceBase` | Apex zone new projects get their **auto-assigned** address under (`<slug>.<instanceBase>`, task 1002704 — every project's hall reachable day one; `no_address: true` on the create call opts out). Same one-label-under-apex/edge-TLS constraint as `devBoxBase`. Deliberately NOT derived from `publicOrigin` (on a co-hosting control plane that is the game's domain). Empty ⇒ no auto-assign — creates are domainless unless the caller brings a domain. |
32
+ | `domains.instanceBase` | Apex zone new projects get their **auto-assigned** address under (`<slug>.<instanceBase>`, task 1002704 — every project's hall reachable day one; `no_address: true` on the create call opts out). One label under the apex only, so the edge wildcard certificate covers it. Deliberately NOT derived from `publicOrigin` (on a co-hosting control plane that is the game's domain). Empty ⇒ no auto-assign — creates are domainless unless the caller brings a domain. |
33
33
  | `repo` | `{ owner, name }` GitHub binding. |
34
34
  | `db.database` | DB name Bongos 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
35
  | `currency` | `{ label, symbol }` — the reward unit label (e.g. "example"). Display only. |
@@ -41,7 +41,7 @@ env override → instance config (config/branding.json) → neutral star
41
41
  | `landing.postLogin` | Where a successful web sign-in lands when it carried no explicit `?return=` / same-apex `Referer` (`src/bongos/routes/auth.js` `postLoginLanding`). **Portable default `/builders`** — the hall always exists. A platform-home instance points this at its OWN front door so a visitor who signs in from there returns there instead of being auto-redirected into the hall (cloudbongos.com → `/gate/`, the orbs). Validated through the same open-redirect allowlist as `?return=` (a misconfigured value falls back to `/builders`). Env-overridable: `<PREFIX>_POST_LOGIN_LANDING`. (task [#1002240](https://cloudbongos.com/builders#/task/1002240)) |
42
42
  | `envPrefix` | Env-var namespace for overrides (`BONGOS` for vanilla, `OTB`, …). Legacy `CLOUDBONGOS_`, `OTB_`, `GDS_` and `PMS_` spellings still resolve, with one deprecation warning per name, until core 1.21 (task 1003703). |
43
43
 
44
- **Not here:** feature-module on/off flags (game, art, discord, dev-box) are a sibling config owned by R54 (task [#1193](https://example.com/builders#/task/1193)).
44
+ **Not here:** feature-module on/off flags (game, art, discord) are a sibling config owned by R54 (task [#1193](https://example.com/builders#/task/1193)).
45
45
 
46
46
  ## Using it
47
47
 
@@ -222,12 +222,11 @@ or missing ranks fail closed.
222
222
  of its grants (ADR 0034); `archon` and the divine tiers above it do.
223
223
 
224
224
  **[ADR 0157](adr/0157-archon-is-rank-and-identity-only.md) added the whole operational block here** —
225
- 20 permissions that had been Archon-gated only by ADR 0016's fail-closed default, never by a decision:
226
- the government/monitoring **pages** (`/watch`, `/harbor`, `/gate` — `page.view.government`) and
225
+ 20 permissions (19 today: the dev-box fleet one went with the box, [ADR 0346](adr/0346-dev-boxes-are-retired.md)) that had been Archon-gated only by ADR 0016's fail-closed default, never by a decision:
226
+ the government/monitoring **pages** (`/watch`, `/gate` — `page.view.government`) and
227
227
  `GET /api/bongos/sessions/search` (whose own `/sessions` page had no server gate at all until
228
228
  task 1002710 put it behind `page.view.government` alongside its three group-mates); the
229
- **dev-box + provisioning fleets** (`GET /boxes[/cost-ledger]`,
230
- `POST /boxes/:b/close`, `PATCH .../block`, `GET /provisioning/fleet[/cost-ledger]`,
229
+ **provisioning fleet** (`GET /provisioning/fleet[/cost-ledger]`,
231
230
  `POST .../force-teardown`); **security adjudication** (`GET /security/reports`,
232
231
  `POST /security/reports/:id/{confirm,dispute,fix,link-fix}`, `/security/docs` CRUD);
233
232
  `GET /api/bongos/audit-log`; the **roster reads** (`GET /builders/roster`, `/grades/by-builder`,
@@ -276,22 +275,15 @@ nothing set it, so every task sat at the `'xenos'` default and the claim gate ab
276
275
  still at the `'xenos'` default to `metic` where sensitive (raise-only, idempotent).
277
276
  - The builders-hall card shows a rank pill when a task's floor is above `xenos`.
278
277
 
279
- ### Source access is rank-gated too (ADR 0031 §9.2, ADR 0035 §1)
278
+ ### Source access (ADR 0035 §1)
280
279
 
281
- Authority over *the code itself* rides the same ladder, enforced server-side from the live DB rank
282
- (never from anything the builder's machine can write):
280
+ Reading the code is not rank-gated today; what a builder can LAND is (next section):
283
281
 
284
- - **Local clone onto your own disk = Metic and up.** Below Metic (`xenos`, `thetes`), there is **no
285
- permanent local copy** — the collaborator-invite path is a Metic+ affordance. New builders work
286
- inside the org-controlled cloud box, where access is revocable and audited.
287
- - **Box source is scoped by rank** (`boxScopeForRank`, decided live inside `GET /api/bongos/box/source-access`):
288
- `xenos`/`thetes` get a sparse `starter` surface; `metic`/`archon` get `full`. A demotion cuts a box
289
- off on its very next fetch (instant credential-layer revocation; the droplet teardown is the slower
290
- control-plane half via `box.js reconcile`).
291
-
292
- > **Rollout note (ADR 0035 §4):** until the box lane is verified end-to-end on real hardware, the
293
- > collaborator-invite/local-clone path stays open to all admitted ranks as the interim on-ramp — the
294
- > Metic+ tightening lands once the box gives newcomers a working alternative. Never leave zero working paths.
282
+ - **A local clone onto your own disk is how every builder works**, and the collaborator-invite /
283
+ local-clone path is open to every admitted rank. `source.clone.local` still names the Metic+ floor
284
+ ADR 0035 planned, but that tightening was to land once a cloud box gave newcomers another way in;
285
+ the box is retired ([ADR 0346](adr/0346-dev-boxes-are-retired.md)), so it does not land as designed.
286
+ What bounds a checkout is what it can land, as the next section describes.
295
287
 
296
288
  ### Git and SSH are OUTSIDE the HTTP boundary — covered by a separate rank floor (ADR 0043, SEC [#863](https://example.com/builders#/task/863))
297
289
 
@@ -589,7 +589,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
589
589
  | `9f9424a5100b` | certain | Join our Discord | `modules/hall-ui/public/hall-render.js:804` |
590
590
  | `7ee76a958445` | certain | Join requests | `modules/hall-ui/public/goals-render.js:1411` |
591
591
  | `b7ab5922126b` | certain | Join-requests to approve | `modules/hall-ui/public/goal-inbox.js:154` |
592
- | `d305f0df6f25` | certain | Jump to | `modules/hall-ui/public/palette.js:216` |
592
+ | `d305f0df6f25` | certain | Jump to | `modules/hall-ui/public/palette.js:351` |
593
593
  | `01176c156112` | certain | Jump to a goal or a thought | `modules/hall-ui/public/goal-map.html:75` |
594
594
  | `01176c156112` | certain | Jump to a goal or a thought | `modules/hall-ui/public/thinking.html:92` |
595
595
  | `2bfc5a50ce88` | certain | Jump to a page or record | `modules/hall-ui/public/shell.js:485` |
@@ -696,7 +696,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
696
696
  | `abc64639b134` | certain | No goals seeded yet. | `modules/hall-ui/public/roadmap.js:205` |
697
697
  | `139ec3636c22` | certain | No introductions right now. One appears here when a pairing round runs. | `modules/hall-ui/public/collab.html:99` |
698
698
  | `3b9823dd4579` | certain | No maintenance declared — nobody is on the hook for this module as the core advances. | `modules/hall-ui/public/modules.js:92` |
699
- | `64a4281934d1` | certain | No match. Try a page name, or an id like | `modules/hall-ui/public/palette.js:172` |
699
+ | `64a4281934d1` | certain | No match. Try a page name, or an id like | `modules/hall-ui/public/palette.js:307` |
700
700
  | `f52552a6afcd` | certain | No notes were packed for this version. | `modules/hall-ui/public/settings-software-update.js:102` |
701
701
  | `4f89817b92e5` | certain | No onboarding steps recorded yet. | `modules/hall-ui/public/hall-render.js:880` |
702
702
  | `421ae031594e` | certain | No open goals in this version | `modules/hall-ui/public/task.js:589` |
@@ -1443,7 +1443,7 @@ Identical copy within one surface. Sometimes right (a repeated button), sometime
1443
1443
  | `af3a8e0fe6a8` | certain | open your goals | `modules/hall-ui/public/goal-inbox.js:158` |
1444
1444
  | `9a803563c948` | certain | open {…} | `modules/hall-ui/public/approval-queue.js:156` |
1445
1445
  | `4f279d68175f` | certain | open, on the Security tab | `modules/hall-ui/public/watch.html:47` |
1446
- | `7b85e6494596` | certain | opens a new tab | `modules/hall-ui/public/palette.js:180` |
1446
+ | `7b85e6494596` | certain | opens a new tab | `modules/hall-ui/public/palette.js:315` |
1447
1447
  | `c38db02adb61` | certain | or above | `modules/hall-ui/public/government.js:564` |
1448
1448
  | `271de72308a4` | certain | pages tweaked | `modules/hall-ui/public/studio.html:83` |
1449
1449
  | `884948925fcb` | certain | paste command | `modules/hall-ui/public/settings.js:914` |
@@ -6727,7 +6727,7 @@
6727
6727
  "surface": "builders-hall",
6728
6728
  "text": "Jump to",
6729
6729
  "file": "modules/hall-ui/public/palette.js",
6730
- "line": 216,
6730
+ "line": 351,
6731
6731
  "origin": "js-markup",
6732
6732
  "confidence": "certain"
6733
6733
  },
@@ -7690,7 +7690,7 @@
7690
7690
  "surface": "builders-hall",
7691
7691
  "text": "No match. Try a page name, or an id like",
7692
7692
  "file": "modules/hall-ui/public/palette.js",
7693
- "line": 172,
7693
+ "line": 307,
7694
7694
  "origin": "js-markup",
7695
7695
  "confidence": "certain"
7696
7696
  },
@@ -14413,7 +14413,7 @@
14413
14413
  "surface": "builders-hall",
14414
14414
  "text": "opens a new tab",
14415
14415
  "file": "modules/hall-ui/public/palette.js",
14416
- "line": 180,
14416
+ "line": 315,
14417
14417
  "origin": "js-markup",
14418
14418
  "confidence": "certain"
14419
14419
  },
@@ -62,7 +62,7 @@ the apex redirects straight past it into the walled gate.
62
62
  `src/platform-server.js:115-121`, conditional only on `isApexHost(req)` and the gate file existing,
63
63
  with no session check and no query bypass.
64
64
 
65
- **The live Caddyfile is not mirrored in this repo** (`infra/` holds only `box-*.sh`); ADR 0152 gives
65
+ **The live Caddyfile is not mirrored in this repo** (`infra/` held only `box-*.sh` and has since been removed with the dev box); ADR 0152 gives
66
66
  the intended shape as prose and marks the lock *"optional pre-launch"*, and several references to
67
67
  `infra/Caddyfile` elsewhere in the tree are dead. Treat the host config as the source of truth.
68
68
 
@@ -28,7 +28,7 @@ Five pages carry the whole hall, and every other page inherits from one of them:
28
28
  | **board** (`index.html` + `work.html`) | the home view and the work board: the densest surface in the hall |
29
29
  | **task** (`task.html`) | one record read end to end; `idea` and `ideas` inherit |
30
30
  | **reading** (`primer.html`) | long markdown with a table of contents; Ranks, Economy, Diagrams, Repo Atlas and Modules inherit |
31
- | **goals** (`goals.html`) | the governance lists; Government, Modules, Watch, Harbor, Gate, Sessions, People and the rest inherit |
31
+ | **goals** (`goals.html`) | the governance lists; Government, Modules, Watch, Gate, Sessions, People and the rest inherit |
32
32
  | **settings** (`settings.html` + `profile.html`) | every form, switch, secret field and status line in the hall |
33
33
 
34
34
  ---
@@ -125,11 +125,11 @@ Five things were reconciled **between** the archetypes, since the builders ran i
125
125
 
126
126
  **A fixture rule the round had to learn, flagged by the grader's security worker.** The settings mocks compose the
127
127
  CLI re-issue flow, which means they have to show a token in a `<pre>`, and they were seeded with a realistic
128
- 64-character hex string beside the real paste command, plus the live dev box's actual `ssh <account>@<ip>` line.
128
+ 64-character hex string beside the real paste command, plus a hosted machine's actual `ssh <account>@<ip>` line.
129
129
  Neither belonged in a committed artifact: the hex was invented (verified against this machine's real session files,
130
130
  so nothing needed rotating) but a credential-shaped literal is treated as a secret regardless of intent and would
131
131
  trip every future scanner, and the SSH host and account are real internal topology that no public API justifies.
132
- Both are now unmistakable placeholders. **The rule for any mock that composes a secret or a connection string: the
132
+ Both were made unmistakable placeholders (the SSH line has since left the mocks with the retired dev-box settings group). **The rule for any mock that composes a secret or a connection string: the
133
133
  fixture must be self-evidently fake at a glance while keeping the real string's LENGTH and SHAPE**, because the
134
134
  length is the composition problem being solved. "Real data, invent nothing" governs ledger figures; it does not
135
135
  extend to credentials or infrastructure.
@@ -77,7 +77,7 @@ The "boundary rots back together" problem is universal; the cure is **architectu
77
77
  - 📄 **Dependency-graph-scoped context** (`nx affected` / `turbo --filter`; [Nx AI agent skills](https://nx.dev/blog/nx-ai-agent-skills) exposes the project graph to agents).
78
78
  - 📄 **Ticket↔component mapping is established**: Jira/Linear "Components", conventional-commit scopes, CODEOWNERS, `nx affected --files`.
79
79
 
80
- 🔧 **The synthesis:** `touches[]` is a file-path list (the lowest-altitude form). The industry moves the unit of affinity *up* from files to components/packages. Once modules are first-class, a task should declare **module affinity**; the agent loads only that module + the core API (small context, higher quality), parallel-safety becomes module-disjointness (cleaner than path overlap), and drift detection becomes semantic ("you said dev-box, you touched game"). *(Refined later: see [02](02-module-map.md)/[04](04-module-lifecycle.md) — in a fully modular world the file-path `touches[]` retires entirely in favor of the module label.)*
80
+ 🔧 **The synthesis:** `touches[]` is a file-path list (the lowest-altitude form). The industry moves the unit of affinity *up* from files to components/packages. Once modules are first-class, a task should declare **module affinity**; the agent loads only that module + the core API (small context, higher quality), parallel-safety becomes module-disjointness (cleaner than path overlap), and drift detection becomes semantic ("you said discord, you touched game"). *(Refined later: see [02](02-module-map.md)/[04](04-module-lifecycle.md) — in a fully modular world the file-path `touches[]` retires entirely in favor of the module label.)*
81
81
 
82
82
  ## 7. Thread 6 — How companies manage AI-assisted dev at scale
83
83
 
@@ -38,7 +38,7 @@ The whole product becomes **core + modules**. A module is a **vertical slice** (
38
38
  graph TD
39
39
  subgraph Modules["Modules (each a vertical slice: routes · db · ui · skills · manifest)"]
40
40
  G[game]
41
- D[dev-box]
41
+ D[provisioning]
42
42
  DC[discord]
43
43
  Y["your module<br/>(no fork!)"]
44
44
  end
@@ -94,7 +94,7 @@ graph LR
94
94
  R1["long dark window — nothing ships —<br/>re-deriving the SAME core (auth, tasks, grading, ~111 migrations)"] --> R2["risky big-bang cutover ⚠"]
95
95
  end
96
96
  subgraph ST["Strangler migration (recommended)"]
97
- S1[loader] --> S2[dev-box→module] --> S3["discord · art"] --> S4[game] --> S5["carve core + task→module"] --> S6[theming]
97
+ S1[loader] --> S2[first module→module] --> S3["discord · art"] --> S4[game] --> S5["carve core + task→module"] --> S6[theming]
98
98
  end
99
99
  ```
100
100
 
@@ -110,7 +110,7 @@ Each phase ships independently, guarded by the fitness functions; easiest/most-i
110
110
  |---|---|---|
111
111
  | 0 | Draw the doorway | define `core/module-api.js` + teach `fitness.js` the one-way rule (mostly exists) |
112
112
  | 1 | Build the loader | discover `modules/*/module.json`, validate, compose routes behind auth, apply module migrations, start/stop pollers |
113
- | 2 | Move dev-box first | most self-contained + half flag-gated; the template every other move copies; prove OTB behaves identically |
113
+ | 2 | Move the most self-contained module first | the template every other move copies; prove OTB behaves identically (the original pick, dev-box, has since been retired, ADR 0346) |
114
114
  | 3 | Move discord, then art-pipeline | same recipe |
115
115
  | 4 | Move game (the hard one) | Colyseus rooms + world tables + `public/`; "realtime capability" seam |
116
116
  | 5 | Carve the core + rewire the task model | split `db.js` per-module; add `task.module`; **retire `touches[]`**; extend fitness to verify diff-in-module |