@bongos/core 1.19.1075 → 1.19.1077

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 (87) hide show
  1. package/.bongos-core.json +104 -114
  2. package/.claude/skills/blocker-solve/SKILL.md +1 -1
  3. package/README.md +1 -1
  4. package/clients/bongos-client/README.md +1 -1
  5. package/clients/bongos-client/bongos-client.global.js +2 -0
  6. package/clients/bongos-client/index.cjs +2 -0
  7. package/clients/bongos-client/index.d.ts +2 -0
  8. package/clients/bongos-client/index.mjs +2 -0
  9. package/docs/adr/0031-cloud-dev-environments-for-builders.md +1 -1
  10. package/docs/adr/0035-builder-onboarding-three-paths.md +1 -1
  11. package/docs/adr/0044-per-box-live-game-preview.md +1 -1
  12. package/docs/adr/0045-devbox-desktop-app.md +1 -1
  13. package/docs/adr/0046-sandbox-first-review-gate.md +1 -1
  14. package/docs/adr/0052-sandbox-for-everyone-game-only-preview.md +1 -1
  15. package/docs/adr/0053-scoped-dev-box-session.md +1 -1
  16. package/docs/adr/0055-server-mediated-branch-publish.md +1 -1
  17. package/docs/adr/0057-container-cost-ledger.md +1 -1
  18. package/docs/adr/0059-single-approval-remove-devbox-approval-gate.md +1 -1
  19. package/docs/adr/0071-box-confirm-before-destroyed-and-drift-reconcile.md +1 -1
  20. package/docs/adr/0072-bongos-app-mac-signed-first-windows-deferred.md +1 -1
  21. package/docs/adr/0072-dev-box-code-staleness-visibility.md +1 -1
  22. package/docs/adr/0104-trust-gds-api-channel-in-auto-mode.md +1 -1
  23. package/docs/adr/0123-box-idle-sweep-autosave-before-destroy.md +1 -1
  24. package/docs/adr/0144-devbox-rehome-onto-cloudbongos-plane.md +1 -1
  25. package/docs/adr/0145-devbox-app-branding-driven-module.md +1 -1
  26. package/docs/adr/0145-free-hosted-project-tier-isolation-and-domain-separation.md +7 -0
  27. package/docs/adr/0148-task-scoped-box-source-access.md +2 -2
  28. package/docs/adr/0151-governance-permissions-as-atom-ranks-as-roles.md +1 -1
  29. package/docs/adr/0193-pause-task-scoped-box-slices.md +1 -1
  30. package/docs/adr/0277-a-box-is-in-use-only-while-a-human-is-attached.md +1 -1
  31. package/docs/adr/0346-dev-boxes-are-retired.md +69 -0
  32. package/docs/adr/README.md +1 -0
  33. package/docs/api/openapi.json +22 -1
  34. package/docs/api-reference.md +3 -2
  35. package/docs/architecture.md +5 -6
  36. package/docs/branding-contract.md +2 -2
  37. package/docs/canonical-permissions.md +10 -18
  38. package/docs/copy-inventory.md +3 -3
  39. package/docs/copy-registry.json +3 -3
  40. package/docs/design/gate-navigation-direction.md +1 -1
  41. package/docs/design/hall-direction-v2.md +3 -3
  42. package/docs/design/modular-architecture/00-research-report.md +1 -1
  43. package/docs/design/modular-architecture/01-architecture.md +3 -3
  44. package/docs/design/modular-architecture/02-module-map.md +1 -2
  45. package/docs/design/modular-architecture/03-builder-flows.md +22 -20
  46. package/docs/design/modular-architecture/04-module-lifecycle.md +1 -1
  47. package/docs/design/modular-architecture/README.md +4 -2
  48. package/docs/design/reviews/hall-v2/README.md +2 -2
  49. package/docs/design/vanilla-hall-ui-redesign-scope.md +4 -4
  50. package/docs/file-map.md +5 -5
  51. package/docs/handoff-template.md +1 -1
  52. package/docs/module-api-changelog.md +8 -0
  53. package/docs/modules-contract.md +11 -14
  54. package/docs/page-readings.json +63 -63
  55. package/docs/recipes/bongos-cli-release.md +1 -2
  56. package/docs/recipes/multi-builder-merge.md +1 -1
  57. package/docs/recipes/ops-gotchas.md +0 -9
  58. package/docs/recipes/self-host.md +1 -1
  59. package/docs/recipes/windows-builders.md +1 -1
  60. package/migrations/core_258_drop_dev_box_tables.sql +3 -0
  61. package/modules/hall-ui/public/palette.js +143 -3
  62. package/package-lock.json +2 -2
  63. package/package.json +1 -1
  64. package/release-notes.json +28 -0
  65. package/scripts/gds/dev-box-guard.js +165 -0
  66. package/scripts/gds/fitness-lib.js +10 -0
  67. package/scripts/gds/fitness.js +2 -10
  68. package/scripts/gds/run-unit-tests.js +4 -0
  69. package/src/bongos/auth.js +8 -1
  70. package/src/bongos/middleware/rate-limit.js +1 -1
  71. package/src/bongos/module-scope-map.js +1 -1
  72. package/src/bongos/routes/auth.js +271 -73
  73. package/src/module-api.js +1 -1
  74. package/tests/core_258_box_session_claims_db.mjs +180 -0
  75. package/tests/fitness.mjs +89 -0
  76. package/tests/hall_palette.mjs +224 -11
  77. package/tests/hub_cookie_host_only.mjs +279 -0
  78. package/tests/landing_page.mjs +4 -1
  79. package/tests/provisioning_recommendations.mjs +1 -1
  80. package/tests/session_rename_fallback.mjs +19 -11
  81. package/tests/subdomain_auth.mjs +17 -15
  82. package/docs/design/reviews/hall-v2/harbor--archon.webp +0 -0
  83. package/docs/design/reviews/hall-v2/harbor--metic.webp +0 -0
  84. package/docs/design/reviews/hall-v2/harbor--xenos.webp +0 -0
  85. package/docs/design/reviews/hall-v2/pair--archon.webp +0 -0
  86. package/docs/design/reviews/hall-v2/pair--metic.webp +0 -0
  87. package/docs/design/reviews/hall-v2/pair--xenos.webp +0 -0
@@ -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 |
@@ -95,7 +95,6 @@ graph TD
95
95
  GA[game] --> K
96
96
  AR[art-pipeline] --> K
97
97
  DC[discord] --> K
98
- DB[dev-box] --> K
99
98
  ```
100
99
 
101
100
  | Module | Owns |
@@ -111,6 +110,6 @@ graph TD
111
110
  | autonomy/MAS | conductor dispatch · architect audits · autonomy-gate · scheduled routines |
112
111
  | security | red-team reports · bounty (rank-gated Metic+) |
113
112
  | hall-UI · status-UI | the two web surfaces |
114
- | game · art-pipeline · discord · dev-box | feature modules |
113
+ | game · art-pipeline · discord | feature modules |
115
114
 
116
115
  > **~16 is the target ceiling, not a day-one requirement.** Start coarser; split as the coupling scan + fitness demand. Every one is a real cohesive cluster (the scan proved it), but a small team should be "as modular as the evidence supports, no finer." Merging two modules is cheap; the fitness ratchet makes splitting them safe — you're never locked into the first cut.
@@ -4,26 +4,26 @@ How a person works once the code is in modules. **Nothing you do is blocked —
4
4
 
5
5
  ## The one idea: two kinds of "access"
6
6
 
7
- - **Platform capabilities** — claim, start, ship, file an idea, recall, see your box. These are **kernel endpoints over HTTP, gated only by your rank.** The module structure never touches them. Available everywhere, always.
8
- - **Code-write scope** — which files a *single claimed task* may change. The **only** thing the structure bounds; it lives at the **worktree** level (not you, not your box); escaped by seeding a new task (itself a kernel capability).
7
+ - **Platform capabilities** — claim, start, ship, file an idea, recall. These are **kernel endpoints over HTTP, gated only by your rank.** The module structure never touches them. Available everywhere, always.
8
+ - **Code-write scope** — which files a *single claimed task* may change. The **only** thing the structure bounds; it lives at the **worktree** level (not you, not your checkout); escaped by seeding a new task (itself a kernel capability).
9
9
 
10
- **The wall is around each task's worktree — not around you, and not around your dev box.**
10
+ **The wall is around each task's worktree — not around you, and not around your checkout.**
11
11
 
12
- ## 1. What the dev box has access to
12
+ ## 1. What your checkout has access to
13
13
 
14
- The dev box is your machine — a persistent environment, **not** module-scoped. Scoping happens one level down, per claim.
14
+ Your checkout is your own copy of the project repo on your own machine — a persistent environment, **not** module-scoped. Scoping happens one level down, per claim.
15
15
 
16
16
  | Layer | Scope | Governed by |
17
17
  |---|---|---|
18
- | Dev box (your environment) | full repo, all modules readable, whole CLI, the API, the preview | nothing — it's yours |
18
+ | Your checkout (your machine) | full repo, all modules readable, whole CLI, the API, the preview | nothing — it's yours |
19
19
  | Kernel capabilities (claim/ship/capture/…) | everything the platform can do | **your rank** (server-enforced) — never a module |
20
20
  | A claim's worktree | write = its one module; read = that module + the kernel doorway | the task's **module label** + the ship-time diff check |
21
21
 
22
- ## 2. Flow: open a dev box → ship a task
22
+ ## 2. Flow: open your checkout → ship a task
23
23
 
24
24
  ```mermaid
25
25
  graph LR
26
- A["Open dev box<br/>(box)"] --> B["/builder-start<br/>lists ALL modules<br/>(kernel)"]
26
+ A["Open your checkout<br/>(local)"] --> B["/builder-start<br/>lists ALL modules<br/>(kernel)"]
27
27
  B --> C["/builder-claim N<br/>a game task<br/>(kernel)"]
28
28
  C --> D["worktree spun:<br/>modules/game + RO kernel<br/>(module-scoped)"]
29
29
  D --> E["agent edits game only<br/>(module-scoped)"]
@@ -31,7 +31,7 @@ graph LR
31
31
  F --> G["live ✓<br/>worktree reaped"]
32
32
  ```
33
33
 
34
- Five of seven steps are kernel/box capabilities; only the worktree + the edits are module-scoped. The only *new* thing is a silent check inside `/builder-ship` (diff ⊆ declared module) that in-scope work never notices.
34
+ Five of seven steps are kernel/local capabilities; only the worktree + the edits are module-scoped. The only *new* thing is a silent check inside `/builder-ship` (diff ⊆ declared module) that in-scope work never notices.
35
35
 
36
36
  ## 3. Flow: claim a task in a different module
37
37
 
@@ -39,14 +39,14 @@ You're never "in" a module — each *claim* is. A second claim just makes a seco
39
39
 
40
40
  ## 4. Flow: see an idea — and seed a cross-module task
41
41
 
42
- Browsing ideas, filing an idea, and **seeding a task for another module** are all kernel operations — they need no access to the other module's code, so they work from anywhere. An agent in a game worktree can't *write* dev-box code, but it can always *file the task* for it (one command), then continue or hand off; a dependency link orders them if needed.
42
+ Browsing ideas, filing an idea, and **seeding a task for another module** are all kernel operations — they need no access to the other module's code, so they work from anywhere. An agent in a game worktree can't *write* discord code, but it can always *file the task* for it (one command), then continue or hand off; a dependency link orders them if needed.
43
43
 
44
44
  ## 5. "Could this block me?" — every worry
45
45
 
46
46
  | Worry | Why it isn't a block |
47
47
  |---|---|
48
48
  | Claim a task in a module I'm not "in"? | You're never "in" a module. Claiming is kernel; each claim makes its own scoped worktree. |
49
- | Does my box only have one module's code? | No — the box has the full repo. Only each per-claim worktree is scoped. |
49
+ | Does my checkout only have one module's code? | No — the checkout has the full repo. Only each per-claim worktree is scoped. |
50
50
  | Agent needs another module mid-task — stuck? | No — it seeds a task for it (kernel op, needs no access to that code); a dep orders them. |
51
51
  | Filing an idea about module X needs X access? | No — capture/inbox is kernel; file from anywhere. |
52
52
  | Is shipping gated by my module? | No — ship is kernel; the only module check is "diff ⊆ module," which passes for normal work. |
@@ -60,7 +60,7 @@ A Claude Code session is **not** welded to one worktree. The session is a **cond
60
60
  graph TD
61
61
  S["long autonomous SESSION = <redacted> repo · full mobility · no module binding"]
62
62
  S --> A["task A (game) → worktree A → its own PR → ship"]
63
- S --> B["task B (dev-box) → worktree B → its own PR → ship"]
63
+ S --> B["task B (discord) → worktree B → its own PR → ship"]
64
64
  S --> C["task C (memory) → worktree C → its own PR → ship"]
65
65
  ```
66
66
 
@@ -69,34 +69,36 @@ graph TD
69
69
 
70
70
  The session has full mobility across modules; only each *task's worker* is module-isolated. This is the orchestrator-worker pattern (ADR 0024), and Bongos already assigns a per-claim worktree.
71
71
 
72
- ## 7. Limiting what the box holds — the jailbreak blast radius
72
+ ## 7. Limiting what a sandbox holds — the jailbreak blast radius
73
73
 
74
- The split lets the box hold **far less**: only the claimed module (read/write) + the kernel's **safe contract** (signatures, read-only) + client plumbing + a scoped token. The kernel **implementation** (auth, rank, ship, grade) never leaves the server.
74
+ *This section was written for the dev box, which has since been retired ([ADR 0346](../../adr/0346-dev-boxes-are-retired.md)). The reasoning holds for any sandboxed environment a session might run in, such as a future cloud session. Today's path, a local checkout, holds the full repo by design (§1).*
75
+
76
+ The split lets a sandbox hold **far less**: only the claimed module (read/write) + the kernel's **safe contract** (signatures, read-only) + client plumbing + a scoped token. The kernel **implementation** (auth, rank, ship, grade) never leaves the server.
75
77
 
76
78
  ```mermaid
77
79
  graph LR
78
- subgraph Box["DEV BOX · one claim (= jailbreak blast radius)"]
80
+ subgraph Sbx["SANDBOX · one claim (= jailbreak blast radius)"]
79
81
  M["modules/&lt;key&gt;/ — read/write"]
80
82
  KC["kernel CONTRACT — signatures + docs only (RO)"]
81
83
  CLI["CLI plumbing (cli-lib)"]
82
84
  TOK["scoped, claim-scoped token (not full-repo)"]
83
85
  end
84
86
  subgraph Server["SERVER · the trusted side"]
85
- KI["KERNEL IMPL — auth · rank · ship · grade<br/>(never on the box)"]
87
+ KI["KERNEL IMPL — auth · rank · ship · grade<br/>(never in the sandbox)"]
86
88
  OM[every other module's source]
87
89
  FR[full repo + history]
88
90
  EN["ENFORCES the rank ladder, live per request (ADR 0016)"]
89
91
  end
90
- Box -->|"privileged ops = HTTP call<br/>(box can't push main)"| Server
92
+ Sbx -->|"privileged ops = HTTP call<br/>(sandbox can't push main)"| Server
91
93
  ```
92
94
 
93
- **The trap to avoid:** reducing what's *on disk* is not reducing *access* — a box holding a full-repo credential re-fetches. The real lever is **scoping the box's credential + fetch to the claimed module** (and module access can be **rank-gated** too, since the server mediates every fetch). The primary boundary always remains the **server-enforced rank ladder**; on-disk minimization is defense-in-depth on top.
95
+ **The trap to avoid:** reducing what's *on disk* is not reducing *access* — a sandbox holding a full-repo credential re-fetches. The real lever is **scoping the sandbox's credential + fetch to the claimed module** (and module access can be **rank-gated** too, since the server mediates every fetch). The primary boundary always remains the **server-enforced rank ladder**; on-disk minimization is defense-in-depth on top.
94
96
 
95
97
  | Approach | Efficiency | Real confidentiality boundary? |
96
98
  |---|---|---|
97
99
  | Sparse-checkout only | ✓ smaller tree | ✗ — `.git` still has everything |
98
- | Partial clone + sparse | ✓✓ | ~ — box can lazily re-fetch with its token |
99
- | **Server-mediated, claim-scoped fetch** | ✓✓ | **✓ — box never holds a full-repo remote or kernel source** |
100
+ | Partial clone + sparse | ✓✓ | ~ — sandbox can lazily re-fetch with its token |
101
+ | **Server-mediated, claim-scoped fetch** | ✓✓ | **✓ — sandbox never holds a full-repo remote or kernel source** |
100
102
  | Per-module repos | ✓✓ | ✓✓ strongest — but contradicts single-repo (ADR 0080 rejected package-modules for v1) |
101
103
 
102
104
  ## 8. Two boundaries that compose (no new friction)
@@ -8,7 +8,7 @@ The one-way rule forbids a module importing another. But the **lifecycle** (whic
8
8
 
9
9
  - **Ports** (a *required, single-provider* capability): the economy module registers a `reward` provider; at ship, the lifecycle asks the kernel to resolve `reward` and calls it. **Economy owns the formula *and* the ledger**; the lifecycle only supplies the session and delivers the result.
10
10
  - **Events** (an *optional* reaction): the lifecycle emits `task.shipped`; the discord module reacts if it cares.
11
- - **Contributions** (an *accumulating extension point*): zero-or-more modules each add a piece to a named point and the kernel hands the whole set to a core consumer — how a module adds its own slice to a shared core surface without core hardcoding it. The `profile.fields` point lets dev-box/discord/art add their slice to the `GET /me` payload (and its browser twin, `window.OTB.contributeSettingsPanel`, adds a Settings panel) instead of those being baked into `routes/me.js` + `settings.js` (BV1.R42 / task 1411 — the strangler prerequisite for those three moves; game has no such coupling). Add-only: a contribution may introduce keys, never overwrite a core one.
11
+ - **Contributions** (an *accumulating extension point*): zero-or-more modules each add a piece to a named point and the kernel hands the whole set to a core consumer — how a module adds its own slice to a shared core surface without core hardcoding it. The `profile.fields` point lets discord/art add their slice to the `GET /me` payload (and its browser twin, `window.OTB.contributeSettingsPanel`, adds a Settings panel) instead of those being baked into `routes/me.js` + `settings.js` (BV1.R42 / task 1411 — the strangler prerequisite for those moves; game has no such coupling). Add-only: a contribution may introduce keys, never overwrite a core one.
12
12
 
13
13
  ```mermaid
14
14
  graph LR
@@ -4,17 +4,19 @@ Five reports from the **2026-06-21 modular-architecture design session**, filed
4
4
 
5
5
  > **Status: pre-red-team draft.** These are research/design reports, not a decision record. A formal numbered ADR follows once they've been red-teamed. Filed under `docs/design/` (not `docs/adr/`) on purpose — the ADR numbering is in flux (0079→0081 collisions), so the number is assigned later on an up-to-date worktree.
6
6
 
7
+ > **Since filing:** the dev box module that these reports use as their first example was retired on 2026-09-28 ([ADR 0346](../../adr/0346-dev-boxes-are-retired.md)). Where a report still names it (the code-size table, the import-graph findings, the migration plan), that is the tree as it stood at filing.
8
+
7
9
  | # | Doc | What it answers |
8
10
  |---|-----|-----------------|
9
11
  | 00 | [Research report](00-research-report.md) | Industry best practice on packaging, plugins, theming, and AI-agent scoping (cited) |
10
12
  | 01 | [Architecture](01-architecture.md) | The concrete core+modules design; why not a rewrite; the migration path |
11
13
  | 02 | [Module map](02-module-map.md) | Where the ~95k LOC live; how finely to cut the core; the decided roster |
12
- | 03 | [Builder flows](03-builder-flows.md) | What the dev box can access; why the structure never blocks a builder |
14
+ | 03 | [Builder flows](03-builder-flows.md) | What a builder's checkout can access; why the structure never blocks a builder |
13
15
  | 04 | [Module lifecycle & maintenance](04-module-lifecycle.md) | How modules interact (seams) and stay healthy as code grows |
14
16
 
15
17
  ## The decided model (one paragraph)
16
18
 
17
- A small **kernel** (auth, rank, db-pool, the loader, the seam registry, trust primitives, config/identity, analytics, the trusted publish path) plus **~16 modules** (lifecycle, economy, grading, memory, onboarding, ideas, builder-settings, sessions/BFG, autonomy/MAS, security, hall-UI, status-UI + game/art-pipeline/discord/dev-box). Modules **never import each other** — they interact through **kernel-mediated seams** (ports + events). Boundaries are held by **CI fitness functions** so the structure can't rot as it grows. It stays **single-package, single-process, no-bundler** — modularity is a separate axis from packaging/runtime/build. It is built via an incremental **strangler migration**, not a ground-up rewrite.
19
+ A small **kernel** (auth, rank, db-pool, the loader, the seam registry, trust primitives, config/identity, analytics, the trusted publish path) plus **~16 modules** (lifecycle, economy, grading, memory, onboarding, ideas, builder-settings, sessions/BFG, autonomy/MAS, security, hall-UI, status-UI + game/art-pipeline/discord). Modules **never import each other** — they interact through **kernel-mediated seams** (ports + events). Boundaries are held by **CI fitness functions** so the structure can't rot as it grows. It stays **single-package, single-process, no-bundler** — modularity is a separate axis from packaging/runtime/build. It is built via an incremental **strangler migration**, not a ground-up rewrite.
18
20
 
19
21
  ## How the boundaries were drawn
20
22
 
@@ -19,6 +19,8 @@ The 26 pages that carry a `*.states.json` (`modules/hall-ui/public/`), each rend
19
19
 
20
20
  Sheets: `<page>--<rank>.webp`, one per page-lane — dark rows above light, 1440 → 390 → 320 left to right, one tile per state. (The atlas sheets are from the second run, with `atlas.json` generated.)
21
21
 
22
+ The `harbor` and `pair` sheets were deleted when those two pages were removed with the dev box ([ADR 0346](../../../adr/0346-dev-boxes-are-retired.md)). The counts and lists below are as walked on 2026-09-02, with both pages in them.
23
+
22
24
  ## Page × rank
23
25
 
24
26
  | page | xenos | metic | archon |
@@ -31,13 +33,11 @@ Sheets: `<page>--<rank>.webp`, one per page-lane — dark rows above light, 1440
31
33
  | gate | 12 · refused (metic+) | 12 · clean | 18 · clean |
32
34
  | goals | 20 · clean | 20 · clean | 30 · clean |
33
35
  | government | 20 · refused (permissions view is archon) | 20 · refused (same) | 30 · clean |
34
- | harbor | 12 · refused (metic+) | 12 · clean | 18 · clean |
35
36
  | idea | 8 · clean | 8 · clean | 12 · clean |
36
37
  | ideas | 8 · clean | 8 · clean | 12 · clean |
37
38
  | index | 16 · clean | 16 · clean | 24 · clean |
38
39
  | modules | 20 · clean | 20 · clean | 30 · clean |
39
40
  | not-ready | 8 · clean | 8 · clean | 12 · clean |
40
- | pair | 8 · clean | 8 · clean | 12 · clean |
41
41
  | people | 12 · clean | 12 · clean | 18 · clean |
42
42
  | primer | 12 · harness (sign-in redirect) | 12 · harness | 18 · harness |
43
43
  | profile | 20 · **defect 1003497** (signed-out links) | 20 · **defect 1003497** | 30 · **defect 1003497** |
@@ -38,7 +38,7 @@ The current hall is **one long single-column page** (`index.html`, `<main>` capp
38
38
 
39
39
  The eleven core widgets (from `hall-widgets.js`, by mount order): **Welcome, Path (onboarding), Standing (profile), Honours (8 laurels), Karma, Acclaim, Works (ships), Marks (grades), Curve (analytics), Bounty (red-team rewards), Roll (leaderboard)** — plus a **Goals** widget (`goals.js`).
40
40
 
41
- Separate full pages behind header links: **Work Board, Primer, Diagrams, Repo Atlas, Ranks, Settings, Pair**, plus Archon-only **Watch, Harbor, Gate**.
41
+ Separate full pages behind header links: **Work Board, Primer, Diagrams, Repo Atlas, Ranks, Settings**, plus Archon-only **Watch, Gate**.
42
42
 
43
43
  The data and the registry seam stay. The redesign changes the **frame** the widgets live in.
44
44
 
@@ -99,7 +99,7 @@ Seven primary destinations plus a gated Admin group. Today's eleven scrolls coll
99
99
  | **Leaderboard** | Roll of the Foremost | Table view | signed-in |
100
100
  | **Docs** | Primer, Diagrams/maps, Repo Atlas | Doc pages + TOC | signed-in |
101
101
  | **Settings** | Settings (all panels) | Sub-nav + panels | signed-in |
102
- | **Admin ▾** | Watch, Harbor, Gate | Grouped, collapsed | **Archon only** |
102
+ | **Admin ▾** | Watch, Gate | Grouped, collapsed | **Archon only** |
103
103
 
104
104
  > Rank/permission gating is **unchanged** — Xenos still don't see Work until graduation; Admin only unhides at `rank=archon`. The redesign moves *where* those links render (into the sidebar), not *whether* they gate.
105
105
 
@@ -152,7 +152,7 @@ Kept close to today's three-section structure (in-progress, claimable, history),
152
152
 
153
153
  ## 7. Surface · Settings — grouped panels
154
154
 
155
- Settings has the most sections today (~15: connections, dev box, box app, craft, display name, wandering, render, art key, CLI, voices, sounds, event sounds…). It gets its own left sub-nav so each group is a focused panel.
155
+ Settings has the most sections today (~13: connections, craft, display name, wandering, render, art key, CLI, voices, sounds, event sounds…). It gets its own left sub-nav so each group is a focused panel.
156
156
 
157
157
  | Component | Type | Placement | Size |
158
158
  |---|---|---|---|
@@ -251,7 +251,7 @@ Not layout, but it rides along. Most of this already flows through the brand pac
251
251
  - Neutral default voice
252
252
 
253
253
  **Deferred**
254
- - Archon pages — Watch, Harbor, Gate (inherit shell only; internal layout unchanged)
254
+ - Archon pages — Watch, Gate (inherit shell only; internal layout unchanged)
255
255
  - Rank-name copy decision
256
256
  - Public apex landing page (separate surface)
257
257
 
package/docs/file-map.md CHANGED
@@ -94,7 +94,7 @@
94
94
  │ ├── <redacted>.sql ← /builder-exit: deactivated builders drop to 'xenos'
95
95
  │ ├── <redacted>.sql ← builders.preferred_disciplines column (enum renamed by mig 086)
96
96
  │ ├── 029_rank_three_live.sql ← #360/ADR 0018: rank default thetes→xenos + tasks.xenos_claimable (three-rank model live)
97
- │ ├── 067_builder_boxes.sql ← #598/ADR 0031: builder_boxes (per-builder dev box lifecycle state) + box_events ledger
97
+ │ ├── 067_builder_boxes.sql ← #598/ADR 0031: the per-builder dev box lifecycle tables; dropped by core_258 (ADR 0346)
98
98
  │ └── <redacted>.sql ← task 615: rename disciplines engineering→engineer, creative→artist|ideator; swaps both CHECK constraints + backfills tasks.discipline & builders.preferred_disciplines
99
99
  ├── modules/ ← self-contained optional feature modules (ADR 0083 / docs/modules-contract.md). Each `modules/<key>/` is a full vertical slice — routes, migrations, skills, seam registrations — reached only through src/module-api.js. The loader discovers them at boot; no core file changes to add one.
100
100
  │ ├── game/ ← the playable Example world — Phaser client, Colyseus rooms (WorldRoom/QueueRoom), world/terrain model, game DB tables, static assets. Moved BV1.R49 (task 1418). CLAUDE.md, module.json, routes/game.js, rooms/, world/, public/, migrations/.
@@ -149,7 +149,7 @@
149
149
  │ ├── gen-file-map.js ← ADR 0066 ([#1276](https://example.com/builders#/task/1276)): generates the `.claude/skills/` + `.claude/scheduled-tasks/` sections of docs/file-map.md from disk; per-entry notes come from docs/file-map.notes.json; `--check` fails on drift OR a skill/routine with no note (CI gate via fitness.js); regenerated on deploy by ship.js regenerateFileMap()
150
150
  │ ├── spike-task-map.js ← (task 1003282, goal 1000072) the task-network-map spike harness: builds a ~1,357-task graph across a swept dependency density, lays it out for real (<redacted> + Barnes-Hut), counts what decides readability (isolated nodes, components, distinguishable marks / overplot, crossings, ink budget, payload) and renders PNGs with a hand-rolled encoder. Zero deps, no DB. `--from <tasks.json>` measures the REAL corpus instead of the model. Verdict: docs/research/task-network-map-readability.md
151
151
  │ ├── fitness.js ← Path C (ADR 0062 §9, [#1225](https://example.com/builders#/task/1225)): architecture fitness functions — core↔host import boundary (zero grandfathered exceptions as of R52/#1191), CLAUDE.md budget + nested-doc presence (ADR 0061), no route bypasses rank checks (reuses route-rank-check), repo-map freshness. Enforced in CI via tests/fitness.mjs (the `unit` gate). `node scripts/gds/fitness.js`
152
- │ ├── ship.js ← resolve claim as shipped, award credits (`/builder-ship`); also uploads a secret-scrubbed session digest to the corpus (6D.1, ADR 0027); on a dev box runs the sandbox-first review gate before resolving (#927, ADR 0046)
152
+ │ ├── ship.js ← resolve claim as shipped, award credits (`/builder-ship`); also uploads a secret-scrubbed session digest to the corpus (6D.1, ADR 0027); runs the sandbox-first review gate before resolving when the checkout has a local game preview (#927, ADR 0046)
153
153
  │ ├── ship-visual.js ← the OPTIONAL `--visual <image> [--visual-alt "…"]` leg of a ship (task 1003109): screens the file BEFORE the claim resolves (bad input costs no claim), uploads it AFTER (a failed picture never fails a ship)
154
154
  │ ├── package-core.js ← package the core as a versioned, installable artifact + pin manifest (`bongos package-core`; R84, ADR 0100 §1, [#1688](https://example.com/builders#/task/1688)): isPublishable() selection + mirror redaction + fail-closed no-leak gate → dist/bongos-core-<version>.{tgz,manifest.json}; version = src/module-api CORE_VERSION. Recipe: docs/recipes/packaging-the-core.md
155
155
  │ ├── release-notes.js ← what each core release brought in (task 1004218): generated at pack time from the ref's HISTORY into the package's release-notes.json (exact per-release ranges, 1 MiB bound; package-core redacts its prose like a doc), read back by the upgrade runner for a from→to range; home of the one merge-summary parser
@@ -208,7 +208,7 @@
208
208
  │ │ ├── catalog.js ← the browsable module catalog model (ADR 0167 / ADR 0107 §2/§3): `source` (which TREE ships it — core package vs instance, read off the loader's discovery root) + resolved author/origin `credit` with an `inferred` flag. The ONE builder behind both `GET /api/bongos/modules` and `bongos module list --catalog`, so the hall + CLI can't drift.
209
209
  │ │ └── semver.js ← minimal semver `satisfies(version, range)` used by the loader (no npm dep).
210
210
  │ ├── platform-server.js ← BONGOS-ONLY entrypoint (ADR 0062 R51, task 1190): boots Express + the shared internal surface (API + hall + status) with NO game in the process; the inverse of preview-server.js. `node src/platform-server.js`
211
- │ ├── preview-server.js ← GAME-ONLY entrypoint for the per-box sandbox (ADR 0052): Phaser/Colyseus + tiles, NO /api/bongos
211
+ │ ├── preview-server.js ← GAME-ONLY entrypoint for the local preview that `/builder-stage` runs (ADR 0052): Phaser/Colyseus + tiles, NO /api/bongos
212
212
  │ ├── seats.js ← in-process seat counter + EventEmitter
213
213
  │ ├── rooms/
214
214
  │ │ ├── WorldRoom.js ← singleton room: move + interact + identity
@@ -221,8 +221,8 @@
221
221
  │ │ ├── routes.js ← thin mounter — imports each routes/* sub-router + every enabled module's routes and stitches them behind kernel-composed auth
222
222
  │ │ ├── api-prefix.js ← API_PREFIX ('/api/bongos') + LEGACY_API_PREFIXES ('/api/gds' permanent alias) + API_VERSION
223
223
  │ │ ├── api-path-404.js ← recognize Bongos-API-shaped paths that missed the mount → JSON 404 + corrective hint (server.js catch-all; V4.R14, [#952](https://example.com/builders#/task/952))
224
- │ │ ├── serve-internal.js ← (ADR 0062 R51, task 1190) the SHARED internal web surface: mountInternalSurfaces(app) wires /healthz + /version + /api/bongos + the Dev Box downloads + the status & builders hosts; called by BOTH server.js (game boot) and platform-server.js (Bongos-only) so the two never drift. Also injects clientBranding() as window.__BRANDING__ into the served hall/status HTML
225
- │ │ ├── routes/ ← one file per KERNEL feature so parallel branches stop colliding on routes.js — the domain routes (tasks/claims/versions/cost/leaderboard/memory/learnings/box/inbox/blockers/search/gate-approvals/discord/…) graduated with their domains into `modules/<key>/routes/`, reached only through the loader
224
+ │ │ ├── serve-internal.js ← (ADR 0062 R51, task 1190) the SHARED internal web surface: mountInternalSurfaces(app) wires /healthz + /version + /api/bongos + the `bongos` CLI downloads + the status & builders hosts; called by BOTH server.js (game boot) and platform-server.js (Bongos-only) so the two never drift. Also injects clientBranding() as window.__BRANDING__ into the served hall/status HTML
225
+ │ │ ├── routes/ ← one file per KERNEL feature so parallel branches stop colliding on routes.js — the domain routes (tasks/claims/versions/cost/leaderboard/memory/learnings/inbox/blockers/search/gate-approvals/discord/…) graduated with their domains into `modules/<key>/routes/`, reached only through the loader
226
226
  │ │ │ ├── _helpers.js ← validateOrRespond, parseId, LIMITS, asyncHandler, publicOrigin, corsPublicGet, parseCookie
227
227
  │ │ │ ├── healthz.js, auth.js, me.js, builders.js, instance.js
228
228
  │ │ │ ├── my-sessions.js ← GET /me/sessions + POST /me/sessions/revoke{,-all} — the OWN-scoped session self-service (task 1003341, ADR 0206): see and kill your own sessions without an Archon. Kept apart from auth.js's admin-gated cross-builder pair so the no-caller-named-owner rule holds over a WHOLE file (tests/own_session_revoke.mjs)
@@ -65,7 +65,7 @@ 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) **/ example-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 machine → production ship flow) **/ example-karma** models (which now flip per the **shipped** status of their backing tasks) — then before shipping:
69
69
 
70
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.
@@ -2637,5 +2637,13 @@ is load-bearing: the script throws rather than guess if it is missing, and
2637
2637
  landed since 1.19.1073 with no explicit bump. run 36510198162. (task 1002620)
2638
2638
  1.19.1075 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2639
2639
  landed since 1.19.1074 with no explicit bump. run 36512197709. (task 1002620)
2640
+ (note, no bump) — auth.allowBoxScope is now a deprecated no-op (task 1003894).
2641
+ The narrowing session scope it opted a route into, and the three box.*
2642
+ permissions, were removed with the dev box (ADR 0346). The export is kept so
2643
+ the doorway loses nothing inside 1.x; it goes at the next MAJOR.
2644
+ 1.19.1076 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2645
+ landed since 1.19.1075 with no explicit bump. run 36523068301. (task 1002620)
2646
+ 1.19.1077 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
2647
+ landed since 1.19.1076 with no explicit bump. run 36558431394. (task 1002620)
2640
2648
  ---------------------------------------------------------------------------
2641
2649
  ```