@bongos/core 1.19.1072 → 1.19.1074

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 (297) hide show
  1. package/.bongos-core.json +320 -465
  2. package/.claude/skills/feedback/SKILL.md +2 -2
  3. package/clients/bongos-client/README.md +1 -1
  4. package/clients/bongos-client/bongos-client.global.js +4 -60
  5. package/clients/bongos-client/index.cjs +4 -60
  6. package/clients/bongos-client/index.d.ts +5 -90
  7. package/clients/bongos-client/index.mjs +4 -60
  8. package/config/branding.neutral.json +1 -5
  9. package/config/modules.neutral.json +2 -3
  10. package/config/scheduled-routines.json +0 -2
  11. package/docs/adr/0145-free-hosted-project-tier-isolation-and-domain-separation.md +1 -0
  12. package/docs/adr/0285-a-shared-box-holds-about-twelve-projects-per-gb-and-memory-is-the-wall.md +1 -0
  13. package/docs/adr/0323-hosting-is-three-shapes-and-we-are-not-the-landlord.md +1 -1
  14. package/docs/adr/0327-a-cloud-host-runs-on-the-owners-account-and-the-key-is-borrowed.md +1 -1
  15. package/docs/adr/0341-the-page-is-the-unit-of-tweak-mode.md +6 -2
  16. package/docs/adr/0345-we-host-every-projects-hall-and-its-app-deploys-where-the-owner-chooses.md +94 -0
  17. package/docs/adr/README.md +2 -1
  18. package/docs/api/openapi.json +171 -1661
  19. package/docs/api-reference.md +9 -41
  20. package/docs/architecture.md +16 -1
  21. package/docs/branding-contract.md +0 -3
  22. package/docs/copy-inventory.md +454 -479
  23. package/docs/copy-registry.json +746 -978
  24. package/docs/file-map.md +5 -34
  25. package/docs/module-api-changelog.md +4 -0
  26. package/docs/modules-contract.md +13 -1
  27. package/docs/onboarding/diagrams/04-architecture.mmd +11 -22
  28. package/docs/onboarding/diagrams/README.md +3 -3
  29. package/docs/onboarding/diagrams/assertions.json +2 -22
  30. package/docs/onboarding/primer.md +9 -28
  31. package/docs/page-inventory.json +4 -1
  32. package/docs/page-readings.json +1032 -1077
  33. package/docs/recipes/render-pilot.md +29 -10
  34. package/migrations/core_257_module_store_registry.sql +87 -0
  35. package/migrations/core_258_drop_dev_box_tables.sql +55 -0
  36. package/modules/agents/module.json +1 -0
  37. package/modules/autonomy/module.json +1 -0
  38. package/modules/builder-settings/module.json +1 -0
  39. package/modules/builder-settings/render-prefs.js +4 -5
  40. package/modules/copy-desk/docx.js +78 -5
  41. package/modules/copy-desk/module.json +1 -0
  42. package/modules/copy-desk/routes/copy-desk.js +9 -9
  43. package/modules/copy-desk/tests/copy_docx.mjs +107 -1
  44. package/modules/copy-desk/tests/fixtures/word-docx.mjs +30 -0
  45. package/modules/discord/module.json +1 -0
  46. package/modules/economy/module.json +1 -0
  47. package/modules/economy/routes/credits.js +1 -2
  48. package/modules/government/catalog.js +13 -17
  49. package/modules/government/migrations/government_019_retire_box_permissions.sql +33 -0
  50. package/modules/government/module.json +1 -0
  51. package/modules/government/protected-surfaces.json +3 -11
  52. package/modules/government/resolver.js +3 -46
  53. package/modules/government/routes/government.js +0 -2
  54. package/modules/government/session-scopes.js +43 -83
  55. package/modules/government/session-scopes.json +8 -18
  56. package/modules/grading/module.json +1 -0
  57. package/modules/hall-ui/module.json +1 -0
  58. package/modules/hall-ui/public/board-lib.js +2 -2
  59. package/modules/hall-ui/public/builders.js +29 -40
  60. package/modules/hall-ui/public/collab.html +1 -1
  61. package/modules/hall-ui/public/collab.js +1 -1
  62. package/modules/hall-ui/public/diagrams.html +3 -3
  63. package/modules/hall-ui/public/dom-utils.js +1 -1
  64. package/modules/hall-ui/public/gate.js +2 -2
  65. package/modules/hall-ui/public/gate.states.json +1 -1
  66. package/modules/hall-ui/public/hall-render.js +43 -79
  67. package/modules/hall-ui/public/index.html +5 -1
  68. package/modules/hall-ui/public/modules.js +1 -0
  69. package/modules/hall-ui/public/oversight.css +5 -5
  70. package/modules/hall-ui/public/palette.js +0 -11
  71. package/modules/hall-ui/public/primer.js +1 -1
  72. package/modules/hall-ui/public/sessions.html +1 -1
  73. package/modules/hall-ui/public/settings-sessions.js +1 -1
  74. package/modules/hall-ui/public/settings.css +0 -1
  75. package/modules/hall-ui/public/settings.html +4 -33
  76. package/modules/hall-ui/public/settings.js +3 -33
  77. package/modules/hall-ui/public/settings.states.json +2 -2
  78. package/modules/hall-ui/public/studio.html +1 -1
  79. package/modules/hall-ui/public/style.css +10 -13
  80. package/modules/hall-ui/public/task.html +4 -1
  81. package/modules/hall-ui/public/task.js +36 -1
  82. package/modules/hall-ui/public/tweak-editor-lib.js +18 -1
  83. package/modules/hall-ui/public/tweak-editor.css +16 -0
  84. package/modules/hall-ui/public/tweak-editor.html +26 -3
  85. package/modules/hall-ui/public/tweak-editor.js +32 -1
  86. package/modules/hall-ui/public/work.js +1 -1
  87. package/modules/hall-ui/records/tweak-editor.md +1 -0
  88. package/modules/ideas/module.json +1 -0
  89. package/modules/lifecycle/db-claim-reads.js +1 -58
  90. package/modules/lifecycle/db-ship.js +0 -5
  91. package/modules/lifecycle/db.js +0 -4
  92. package/modules/lifecycle/kickoff-checklist.js +0 -4
  93. package/modules/lifecycle/lifecycle.js +0 -8
  94. package/modules/lifecycle/module.json +1 -0
  95. package/modules/lifecycle/routes/tasks.js +5 -7
  96. package/modules/memory/module.json +1 -0
  97. package/modules/npm-release/module.json +1 -0
  98. package/modules/onboarding/module.json +1 -0
  99. package/modules/onboarding/onboarding-state.js +17 -36
  100. package/modules/onboarding/routes/access-requests.js +3 -3
  101. package/modules/platform-identity/module.json +1 -0
  102. package/modules/platform-identity/platform-identity.js +13 -5
  103. package/modules/platform-identity/routes/sso.js +2 -2
  104. package/modules/platform-identity/tests/platform-identity.mjs +17 -3
  105. package/modules/provisioning/module.json +1 -0
  106. package/modules/provisioning/provisioning.js +2 -2
  107. package/modules/provisioning/starter-bundles.js +5 -25
  108. package/modules/public-landing/module.json +1 -0
  109. package/modules/public-landing/public/assets/cosmos.css +1 -1
  110. package/modules/public-landing/public/contact.html +1 -1
  111. package/modules/public-landing/public/privacy.html +1 -1
  112. package/modules/public-landing/public/projects.html +101 -32
  113. package/modules/public-landing/public/projects.probes.json +2 -2
  114. package/modules/public-landing/public/projects.states.json +4 -3
  115. package/modules/public-landing/public/terms.html +1 -1
  116. package/modules/security/module.json +1 -0
  117. package/modules/sessions/module.json +1 -0
  118. package/modules/specialities/module.json +1 -0
  119. package/modules/status-ui/module.json +1 -0
  120. package/modules/ui-design/module.json +1 -0
  121. package/package-lock.json +2 -2
  122. package/package.json +1 -1
  123. package/release-notes.json +84 -0
  124. package/scripts/gds/artifact-format.js +203 -0
  125. package/scripts/gds/audit-authorship.sh +1 -13
  126. package/scripts/gds/claim.js +0 -15
  127. package/scripts/gds/cli-lib.js +8 -8
  128. package/scripts/gds/diagram-facts.js +12 -23
  129. package/scripts/gds/do-api.js +13 -80
  130. package/scripts/gds/doc-cli-guard.js +2 -0
  131. package/scripts/gds/doctor.js +1 -1
  132. package/scripts/gds/feedback-latest.js +139 -9
  133. package/scripts/gds/fitness-checks-identity.js +2 -7
  134. package/scripts/gds/fitness-checks-write-validation.js +4 -0
  135. package/scripts/gds/fitness-ratchets.js +4 -4
  136. package/scripts/gds/fitness.js +10 -10
  137. package/scripts/gds/gen-diagrams.js +49 -71
  138. package/scripts/gds/http-api-client.js +12 -19
  139. package/scripts/gds/init.js +1 -1
  140. package/scripts/gds/lint-infra-exec.js +1 -1
  141. package/scripts/gds/local-preview-lib.js +8 -39
  142. package/scripts/gds/local-preview.js +2 -15
  143. package/scripts/gds/migration-namespace.js +3 -3
  144. package/scripts/gds/module-artifact.js +212 -0
  145. package/scripts/gds/module.js +95 -6
  146. package/scripts/gds/package-core.js +5 -116
  147. package/scripts/gds/provision-config.js +2 -2
  148. package/scripts/gds/provision-net.js +2 -3
  149. package/scripts/gds/provision.js +9 -9
  150. package/scripts/gds/publish-manifest.js +1 -2
  151. package/scripts/gds/regen-instance-docs.js +1 -1
  152. package/scripts/gds/run-unit-tests.js +2 -16
  153. package/scripts/gds/sandbox-stage.js +39 -341
  154. package/scripts/gds/ship-flow.js +6 -6
  155. package/scripts/gds/ship-land.js +3 -4
  156. package/scripts/gds/ship-regen.js +10 -41
  157. package/scripts/gds/ship.js +4 -24
  158. package/scripts/gds/start.js +0 -15
  159. package/scripts/hall-preview/README.md +5 -5
  160. package/scripts/hall-preview/server.js +6 -6
  161. package/scripts/render-diagrams.sh +1 -1
  162. package/src/bongos/api-errors.js +1 -1
  163. package/src/bongos/auth-github.js +2 -3
  164. package/src/bongos/auth.js +51 -126
  165. package/src/bongos/db-kernel.js +2 -3
  166. package/src/bongos/db.js +5 -28
  167. package/src/bongos/module-scope-map.js +14 -29
  168. package/src/bongos/module-store.js +141 -0
  169. package/src/bongos/route-rank-check.js +3 -16
  170. package/src/bongos/routes/auth.js +0 -116
  171. package/src/bongos/routes/builders.js +5 -15
  172. package/src/bongos/routes/instance.js +8 -14
  173. package/src/bongos/routes/me.js +6 -22
  174. package/src/bongos/routes/modules.js +83 -0
  175. package/src/bongos/routes.js +5 -0
  176. package/src/module-api.js +13 -6
  177. package/src/module-loader/catalog.js +3 -0
  178. package/src/module-loader/loader.js +4 -4
  179. package/src/module-loader/manifest-schema.js +15 -7
  180. package/src/module-seams.js +2 -3
  181. package/src/modules.js +42 -14
  182. package/tests/agents_spend_guard.mjs +1 -1
  183. package/tests/api_client.mjs +0 -15
  184. package/tests/auth_page_gate.mjs +10 -10
  185. package/tests/canonical_profile_url.mjs +1 -3
  186. package/tests/claim_action.mjs +4 -1
  187. package/tests/claim_from_task_and_home.mjs +127 -0
  188. package/tests/consumer_layout_boot.mjs +2 -0
  189. package/tests/copy_desk_page_docx.mjs +33 -2
  190. package/tests/core_upgrade_runner.mjs +6 -6
  191. package/tests/deploy_divergence_line.mjs +11 -11
  192. package/tests/diagram_facts_offset.mjs +1 -1
  193. package/tests/do_api.mjs +106 -0
  194. package/tests/feedback_latest.mjs +122 -0
  195. package/tests/fitness.mjs +44 -42
  196. package/tests/gate_approvals.mjs +0 -1
  197. package/tests/go_live.mjs +3 -3
  198. package/tests/government_abuse_matrix.mjs +20 -19
  199. package/tests/government_ownership_scope.mjs +33 -35
  200. package/tests/government_parity.mjs +2 -2
  201. package/tests/government_protected_surfaces.mjs +56 -37
  202. package/tests/government_require_permission.mjs +3 -3
  203. package/tests/government_seed.mjs +37 -4
  204. package/tests/government_session_scope.mjs +92 -366
  205. package/tests/hall_error_envelope.mjs +4 -0
  206. package/tests/hall_landing_boot.mjs +4 -1
  207. package/tests/hall_palette.mjs +1 -16
  208. package/tests/hall_record_world.mjs +6 -0
  209. package/tests/hall_tweak_editor.mjs +52 -1
  210. package/tests/host_topology_skips.mjs +1 -2
  211. package/tests/html_comment_nesting.mjs +137 -0
  212. package/tests/infra_exec_paths.mjs +9 -10
  213. package/tests/init.mjs +4 -5
  214. package/tests/instance_manifest.mjs +18 -25
  215. package/tests/kickoff_checklist.mjs +1 -1
  216. package/tests/lib_sh_resolution.mjs +0 -221
  217. package/tests/local_preview.mjs +0 -12
  218. package/tests/module-scope-map.mjs +9 -9
  219. package/tests/module_catalog.mjs +1 -1
  220. package/tests/module_cli.mjs +15 -15
  221. package/tests/module_contributions.mjs +6 -6
  222. package/tests/module_loader.mjs +6 -6
  223. package/tests/module_manifest.mjs +13 -4
  224. package/tests/module_store_publish.mjs +307 -0
  225. package/tests/module_store_publish_route.mjs +121 -0
  226. package/tests/module_store_registry_migration.mjs +70 -0
  227. package/tests/modules.mjs +56 -26
  228. package/tests/onboarding_route_signals.mjs +21 -31
  229. package/tests/onboarding_state.mjs +35 -49
  230. package/tests/permission_path.mjs +0 -3
  231. package/tests/platform_boot.mjs +1 -2
  232. package/tests/profile_route.mjs +1 -6
  233. package/tests/projects_hub.mjs +5 -5
  234. package/tests/projects_hub_app_step.mjs +138 -0
  235. package/tests/projects_hub_module_picker.mjs +2 -2
  236. package/tests/projects_hub_pre_uat.mjs +4 -5
  237. package/tests/provision.mjs +7 -7
  238. package/tests/provisioning_starter_bundles.mjs +0 -22
  239. package/tests/publish_branch_route.mjs +10 -18
  240. package/tests/publish_manifest.mjs +1 -2
  241. package/tests/rank_tier_single_source.mjs +1 -13
  242. package/tests/repo_map.mjs +3 -4
  243. package/tests/runner_drift.mjs +3 -21
  244. package/tests/sandbox_stage.mjs +57 -390
  245. package/tests/session_rename_fallback.mjs +0 -21
  246. package/tests/ship_error_shape.mjs +1 -1
  247. package/tests/task_visual_slots.mjs +31 -0
  248. package/tests/terms_acceptance.mjs +1 -1
  249. package/tests/upgrade.mjs +4 -4
  250. package/tests/watch_sealed_floor.mjs +0 -1
  251. package/tests/wizard_draft_resume.mjs +2 -2
  252. package/tests/wizard_intent_resume.mjs +21 -10
  253. package/tests/wizard_preselect_why.mjs +18 -18
  254. package/docs/onboarding/browser-terminal-guide.md +0 -73
  255. package/docs/recipes/managed-settings-remote-control.md +0 -416
  256. package/modules/dev-box/CLAUDE.md +0 -15
  257. package/modules/dev-box/box-access.js +0 -623
  258. package/modules/dev-box/box-credential.js +0 -94
  259. package/modules/dev-box/box-onboard.js +0 -486
  260. package/modules/dev-box/boxes.js +0 -1038
  261. package/modules/dev-box/db.js +0 -39
  262. package/modules/dev-box/module.json +0 -19
  263. package/modules/dev-box/routes/box.js +0 -1223
  264. package/scripts/gds/box-auth-check.js +0 -160
  265. package/scripts/gds/box-infra.js +0 -321
  266. package/scripts/gds/box-sync.js +0 -216
  267. package/scripts/gds/box.js +0 -1332
  268. package/scripts/gds/cf-tunnel.js +0 -558
  269. package/scripts/gds/smoke-box.sh +0 -150
  270. package/scripts/gds/tree-preflight.js +0 -241
  271. package/src/bongos/app-pair.js +0 -172
  272. package/tests/app_pair.mjs +0 -168
  273. package/tests/box_access.mjs +0 -578
  274. package/tests/box_auth_check.mjs +0 -114
  275. package/tests/box_code_staleness.mjs +0 -129
  276. package/tests/box_connect_e2e.mjs +0 -196
  277. package/tests/box_cost.mjs +0 -70
  278. package/tests/box_credential.mjs +0 -125
  279. package/tests/box_dns_repoint.mjs +0 -153
  280. package/tests/box_env.mjs +0 -64
  281. package/tests/box_host_keys.mjs +0 -126
  282. package/tests/box_infra_resolve.mjs +0 -246
  283. package/tests/box_onboard.mjs +0 -317
  284. package/tests/box_scope_session.mjs +0 -119
  285. package/tests/box_sweep_docs.mjs +0 -119
  286. package/tests/box_sync.mjs +0 -55
  287. package/tests/box_sync_scope_report.mjs +0 -126
  288. package/tests/box_task_scope.mjs +0 -169
  289. package/tests/box_task_scope_pause.mjs +0 -66
  290. package/tests/box_terminal_ssrf.mjs +0 -96
  291. package/tests/boxes.mjs +0 -1585
  292. package/tests/cf_ruleset_preflight.mjs +0 -142
  293. package/tests/cf_tunnel.mjs +0 -496
  294. package/tests/docs_scrubber_damage.mjs +0 -111
  295. package/tests/module_scope_active_claims.mjs +0 -94
  296. package/tests/ship_api_client_pathspec.mjs +0 -100
  297. package/tests/tree_preflight.mjs +0 -243
@@ -88,6 +88,11 @@
88
88
  const err = new Error(detail);
89
89
  err.status = res.status;
90
90
  err.code = code;
91
+ // task 1003459 — the { status, data } shape claim-action.js's
92
+ // errCode/errDetails/errMessage read. err.code/detail above stay exactly
93
+ // as before for the existing /vote caller (which reads only .status and
94
+ // .message); this is additive.
95
+ err.data = res.data || {};
91
96
  throw err;
92
97
  }
93
98
  return res.data;
@@ -118,10 +123,11 @@
118
123
  // ---- repo info (the clone URL the welcome walkthrough hands a newcomer) ---
119
124
  //
120
125
  // The /builder-* commands live INSIDE the repo (.claude/skills/, shelling out
121
- // to scripts/gds/*.js). Setup now runs on a hosted dev box (#777), so the
122
- // newcomer never clones a repo locally — the old repo-clone walkthrough (and
123
- // the /public/repo-info fetch that fed it) was removed with the setup-first
124
- // redesign. The /public/repo-info surface still exists for other callers.
126
+ // to scripts/gds/*.js). The old repo-clone walkthrough (and the
127
+ // /public/repo-info fetch that fed it) was removed with the setup-first
128
+ // redesign (#777); the welcome panel's clone block now reads the instance's
129
+ // repo coords instead. The /public/repo-info surface still exists for other
130
+ // callers.
125
131
 
126
132
  // ---- rank badge (V3.R16 #240) -------------------------------------------
127
133
  // Three live ranks per ADR 0018: archon > metic > xenos. Missing rank
@@ -386,14 +392,6 @@
386
392
 
387
393
 
388
394
 
389
- // #785: remember which setup config the builder picked (Desktop app vs Claude
390
- // Online) so it survives a re-render / reload / tab switch — renderWelcome used
391
- // to hardcode 'desktop' every time. Device-level (not per-builder): it's "how I
392
- // connect from this machine". Fail-open to 'desktop' (the recommended default).
393
- function writeSetupConfig(v) {
394
- try { window.localStorage.setItem(SETUP_CONFIG_KEY, v === 'online' ? 'online' : 'desktop'); } catch (_) { /* private mode — won't persist, fine */ }
395
- }
396
-
397
395
  // task 2169 (banner budget): exactly one banner panel at a time. The
398
396
  // checklist render runs before the welcome render in the boot pass, so after
399
397
  // the welcome panel's visibility settles we re-evaluate the checklist —
@@ -966,9 +964,13 @@
966
964
  list.innerHTML = rows.map((t) => {
967
965
  const credits = window.OTBBranding?.taskCreditValue?.(t) ?? t.credits_reward;
968
966
  const mins = t.est_minutes ? ` · ~${escapeHtml(String(t.est_minutes))}m` : '';
967
+ // task 1003459 — this row now claims directly (the extracted claim
968
+ // action, task 1003458) rather than only linking to the record and
969
+ // making the builder find the door there.
969
970
  return `<li class="next-up__item">
970
971
  <a class="next-up__title" href="/task/${encodeURIComponent(t.id)}">${escapeHtml(t.title || `task ${t.id}`)}</a>
971
972
  <span class="next-up__meta">#${escapeHtml(String(t.id))}${mins} · ${fmtNum(credits)} ${escapeHtml(cur)} est.</span>
973
+ <button class="task__claim next-up__claim" type="button" data-task-id="${escapeHtml(String(t.id))}" aria-label="Claim task ${escapeHtml(String(t.id))}">Claim</button>
972
974
  </li>`;
973
975
  }).join('');
974
976
  // Name the size of the queue these two came off. Silent when the count is
@@ -1006,24 +1008,20 @@
1006
1008
  // ---- onboarding live-tick poll (task 1444) -------------------------------
1007
1009
  //
1008
1010
  // The onboarding checklist is rendered once from the page-load /me snapshot.
1009
- // But three of its steps clear from LIVE server signals that flip WITHOUT any
1011
+ // But two of its steps clear from LIVE server signals that flip WITHOUT any
1010
1012
  // local action or page reload while the hall sits open:
1011
- // * box_connect — stamped by the box's heartbeat the first time a `claude`
1012
- // process runs on the dev box (builder_boxes.first_connected_at);
1013
- // * cli_setup — stamped when the Bongos CLI is first authenticated on the box;
1013
+ // * cli_setup — stamped when the Bongos CLI is first authenticated;
1014
1014
  // * join_discord — flips on the OAuth link (usually a full redirect, but can
1015
1015
  // also land from another tab).
1016
- // Without a poll, a newcomer who connects their box AFTER opening the hall sees
1016
+ // Without a poll, a newcomer who signs the CLI in AFTER opening the hall sees
1017
1017
  // the step stay unchecked until they manually reload — exactly the bug scootermack
1018
1018
  // hit. "The city watches" only worked on the next full reload. So while any
1019
1019
  // live-signal step is still uncleared, re-fetch /me on an interval and re-render
1020
- // the checklist; stop once they all clear (or the builder graduates). The box
1021
- // panel runs its OWN poll and is never re-mounted here (renderOnboarding touches
1022
- // a different DOM subtree), so this doesn't disturb an in-flight setup.
1020
+ // the checklist; stop once they all clear (or the builder graduates).
1023
1021
  let onboardingPollTimer = null;
1024
1022
  const ONBOARDING_POLL_MS = 15000;
1025
1023
 
1026
- // True while at least one step that clears from a live signal (box/cli/discord)
1024
+ // True while at least one step that clears from a live signal (cli/discord)
1027
1025
  // is still uncleared and the builder hasn't graduated. The pick_disciplines and
1028
1026
  // ship_three steps flip via local action (PATCH re-renders) or shipping, so they
1029
1027
  // don't need a poll — scoping to the live-signal steps bounds polling to the
@@ -1032,7 +1030,7 @@
1032
1030
  if (!onboarding || onboarding.graduated) return false;
1033
1031
  const stages = Array.isArray(onboarding.stages) ? onboarding.stages : [];
1034
1032
  return stages.some((s) =>
1035
- (s.source === 'box' || s.source === 'cli' || s.source === 'discord') && !s.cleared);
1033
+ (s.source === 'cli' || s.source === 'discord') && !s.cleared);
1036
1034
  }
1037
1035
 
1038
1036
  function stopOnboardingPoll() {
@@ -1129,8 +1127,8 @@
1129
1127
  // carries the builder's own state directly so this is a render-only call.
1130
1128
  renderOnboarding(me.onboarding || null, me.discord);
1131
1129
  // task 1444: keep the checklist live — re-fetch /me on an interval while a
1132
- // box/cli/discord step is still uncleared, so it ticks itself without a manual
1133
- // reload the moment the dev box connects (or the CLI/Discord links).
1130
+ // cli/discord step is still uncleared, so it ticks itself without a manual
1131
+ // reload the moment the CLI or Discord links.
1134
1132
  scheduleOnboardingPoll(me.onboarding || null);
1135
1133
  renderRecentGrades(me.grades?.recent || []);
1136
1134
  renderRollingNote(me.grades?.rolling || null);
@@ -1276,20 +1274,6 @@
1276
1274
  // Both new steps (join_discord, cli_setup) auto-detect server-side.
1277
1275
  });
1278
1276
 
1279
- // #777: setup-config toggle in the welcome panel. Flips which config pane
1280
- // (Desktop app vs Claude Online) is shown — pure client-side, no round-trip.
1281
- $('#welcome-body')?.addEventListener('click', (e) => {
1282
- const tab = e.target.closest('.setup__tab[data-config]');
1283
- if (!tab) return;
1284
- const setup = tab.closest('.setup');
1285
- if (!setup) return;
1286
- setup.dataset.config = tab.dataset.config;
1287
- setup.querySelectorAll('.setup__tab').forEach((t) => {
1288
- t.setAttribute('aria-selected', String(t === tab));
1289
- });
1290
- writeSetupConfig(tab.dataset.config); // #785: remember the choice
1291
- });
1292
-
1293
1277
  // Welcome panel minimize toggle (replaces full dismiss).
1294
1278
  $('#welcome-minimize')?.addEventListener('click', () => {
1295
1279
  const scroll = $('#welcome-scroll');
@@ -1302,6 +1286,11 @@
1302
1286
  // V3.R25 (#245): delegated click handler for the peer-acclaim vote buttons.
1303
1287
  $('#acclaim-feed')?.addEventListener('click', onAcclaimClick);
1304
1288
 
1289
+ // task 1003459 — the Claim button on each Next-up row; the action + the
1290
+ // delegated listener live in hall-render.js (builders.js is at the
1291
+ // 1,500-line ratchet, hall-ui/CLAUDE.md's "growth goes in the lib/renderer").
1292
+ wireNextUpClaim();
1293
+
1305
1294
  $('#f-ships-window')?.addEventListener('change', onShipsFilterChange);
1306
1295
  $('#f-ships-version')?.addEventListener('change', onShipsFilterChange);
1307
1296
  $('#f-ships-sort')?.addEventListener('change', renderRecentShips);
@@ -1416,8 +1405,8 @@
1416
1405
  // reads what this page holds NOW rather than what it held at boot. Everything
1417
1406
  // else is stable for the life of the page. This call sits AFTER every
1418
1407
  // declaration it passes — moving it earlier is a temporal-dead-zone crash.
1419
- const { SETUP_CONFIG_KEY, acclaimEvidenceHtml, analyticsState, lbState, mountHallWidgets, renderCurveBody, renderGreeting, renderLanding, renderNav, renderOnboarding, renderProfile, renderRecentShips, renderWelcomeCore, shipState, shipsPager, welcomeDismissalKey } = window.OTBHallRender({
1420
- API, RANK_ORDER, api, brandWorld, curLabel, emptyRow, fmtDate, mins, normalizeRank, pct, postJSON, rankLabel, rankWeight, signClasses, toast, usd,
1408
+ const { acclaimEvidenceHtml, analyticsState, lbState, mountHallWidgets, renderCurveBody, renderGreeting, renderLanding, renderNav, renderOnboarding, renderProfile, renderRecentShips, renderWelcomeCore, shipState, shipsPager, welcomeDismissalKey, wireNextUpClaim } = window.OTBHallRender({
1409
+ API, RANK_ORDER, api, brandWorld, curLabel, emptyRow, fmtDate, loadNextUp, mins, normalizeRank, pct, postJSON, rankLabel, rankWeight, signClasses, toast, usd,
1421
1410
  get instanceRepo() { return instanceRepo; },
1422
1411
  get lastClaimableCount() { return lastClaimableCount; },
1423
1412
  get lastCostState() { return lastCostState; },
@@ -38,7 +38,7 @@
38
38
  <!-- The glass figure strip task 1003942 promised and did not build, and
39
39
  the artist's verdict (task 1004041) asked for by name: three calm
40
40
  numbers a person meets BEFORE any age pill. The shell's .stat-row,
41
- the same band Harbor, Gate and the copy desk open on; collab.js
41
+ the same band Gate and the copy desk open on; collab.js
42
42
  fills it from the two reads it already makes. -->
43
43
  <div class="stat-row ov-summary cb-figs" id="cb-figs" aria-label="Where the asks stand"></div>
44
44
 
@@ -425,7 +425,7 @@
425
425
  // grader's narc worker caught the omission and the artist named what it cost:
426
426
  // with no numbers to open on, the first thing a person meets is the wall of
427
427
  // age pills, which is why the two findings were one defect seen twice. So the
428
- // strip is the shell's .stat-row, the same glass band Harbor, Gate and the
428
+ // strip is the shell's .stat-row, the same glass band Gate and the
429
429
  // copy desk open on, and it is drawn BEFORE the blocks in the markup.
430
430
  //
431
431
  // The figures repeat what the block heads count, and that is the point rather
@@ -71,10 +71,10 @@
71
71
 
72
72
  <section class="scroll" aria-labelledby="d4-h">
73
73
  <h2 id="d4-h" class="scroll__h">4 · The complete architecture</h2>
74
- <p class="scroll__lede">Where your work runs and how it reaches production, in one diagram. Your <strong>device</strong> is only the screen; the <strong>dev box</strong> holds the worker, the code, and your local memory; the <strong>server</strong> (the droplet) is both the authority and production; <strong>GitHub</strong> holds the repo. Follow the numbered path to see how a credential-less box gets its work to prod. This is the largest diagram — <em>drag to pan, scroll to zoom, or open it fullscreen</em>.</p>
74
+ <p class="scroll__lede">Where your work runs and how it reaches production, in one diagram. <strong>Your machine</strong> holds the worker, the code, and your local memory; the <strong>server</strong> is both the authority and production; <strong>GitHub</strong> holds the repo. Follow the numbered path to see how your work gets to prod. This is the largest diagram — <em>drag to pan, scroll to zoom, or open it fullscreen</em>.</p>
75
75
  <figure class="diagram">
76
- <img src="diagrams/04-architecture.png" alt="The complete architecture: your device (screen only), the dev box (worker, code, and local memory), the server droplet (authority and production, with Postgres, the server-side memory store, and the push credential), and GitHub (branch-protected main + Actions). Numbered edges show the box-to-production ship flow; the per-builder memory layer syncs between the box and the server.">
77
- <figcaption>Device · dev box · memory · server (authority + prod) · GitHub — and the full box→production ship flow.</figcaption>
76
+ <img src="diagrams/04-architecture.png" alt="The complete architecture: your machine (the worker, the code, and local memory), the server (authority and production, with Postgres, the server-side memory store, and the push credential), and GitHub (branch-protected main). Numbered edges show how a change travels from your machine to production; the per-builder memory layer syncs between your machine and the server.">
77
+ <figcaption>Your machine · memory · server (authority + prod) · GitHub — and the full path from your machine to production.</figcaption>
78
78
  </figure>
79
79
  </section>
80
80
 
@@ -95,7 +95,7 @@
95
95
  }
96
96
 
97
97
  // Feature-module gate (R60, task 1199 / ADR 0062 §4). serve-internal.js injects
98
- // window.__MODULES__ = { enabled: { game, 'art-pipeline', discord, 'dev-box' }, … }
98
+ // window.__MODULES__ = { enabled: { game, 'art-pipeline', discord, … }, … }
99
99
  // synchronously (the same path as window.__BRANDING__), so hall/status pages can
100
100
  // hide an off module's UI. Defaults to TRUE when the global or key is missing, so
101
101
  // a stale cache / fetch hiccup degrades to showing the full UI, never silently
@@ -7,7 +7,7 @@
7
7
  // classifier the CI runs), and an Approve button that records the owner's seal
8
8
  // (a server-set gate-owner-approved status) and re-runs the check so the PR merges.
9
9
  //
10
- // Like The Watch + The Harbor, this reads /api/bongos/me to show a Sealed notice for
10
+ // Like The Watch, this reads /api/bongos/me to show a Sealed notice for
11
11
  // non-Archons — DEFENCE IN DEPTH only. GET /gate-approvals + POST
12
12
  // /gate-approvals/:pr/approve are ALSO archon-gated server-side (ADR 0016), and
13
13
  // the page itself is gated by server.js requireGovernmentPage. On 401 → web sign-in.
@@ -25,7 +25,7 @@
25
25
  const rankLabel = (rank) => window.OTB.rankLabel(rank, { empty: '' });
26
26
  const toast = (msg) => window.OTB.toast(msg);
27
27
 
28
- // ---- fetch helpers (mirror harbor.js / watch.js) -------------------------
28
+ // ---- fetch helpers (mirror watch.js) -------------------------------------
29
29
 
30
30
  async function fetchJson(path) {
31
31
  const res = await api.request('GET', `${API}${path}`);
@@ -1,5 +1,5 @@
1
1
  {
2
- "_": "Gate — the access-request queue behind requireGovernmentPage. Same confirm-modal component as harbor, which is why the two had guessed two different z-indexes for it. Written with the re-skin (task 1003307) so this page is MEASURED at three widths in both modes rather than looked at once.",
2
+ "_": "Gate — the access-request queue behind requireGovernmentPage. Its confirm modal once had a second user, and the two had guessed two different z-indexes for it. Written with the re-skin (task 1003307) so this page is MEASURED at three widths in both modes rather than looked at once.",
3
3
  "page": "/builders/gate",
4
4
  "surface": "hall-ui",
5
5
  "stub": {
@@ -22,7 +22,7 @@
22
22
  'use strict';
23
23
 
24
24
  window.OTBHallRender = function createHallRender(ctx) {
25
- const { API, RANK_ORDER, api, brandWorld, curLabel, emptyRow, fmtDate, mins, normalizeRank, pct, postJSON, rankLabel, rankWeight, signClasses, toast, usd } = ctx;
25
+ const { API, RANK_ORDER, api, brandWorld, curLabel, emptyRow, fmtDate, loadNextUp, mins, normalizeRank, pct, postJSON, rankLabel, rankWeight, signClasses, toast, usd } = ctx;
26
26
  const { escapeHtml, $, fmtNum, moduleOn } = window.OTB;
27
27
 
28
28
  const RANK_UNLOCKS = {
@@ -768,13 +768,6 @@
768
768
  return null;
769
769
  }
770
770
  }
771
- const SETUP_CONFIG_KEY = 'builders:setup-config';
772
- function readSetupConfig() {
773
- try {
774
- const v = window.localStorage.getItem(SETUP_CONFIG_KEY);
775
- return v === 'online' ? 'online' : 'desktop';
776
- } catch (_) { return 'desktop'; }
777
- }
778
771
  function renderWelcomeCore(builder, onboarding) {
779
772
  const scroll = $('#welcome-scroll');
780
773
  const body = $('#welcome-body');
@@ -802,78 +795,24 @@
802
795
  const rankBadge = renderRankBadge(normalizeRank(builder.rank), { tip: true });
803
796
  const greeting = `Welcome, ${escapeHtml(builder.display_name || builder.github_login || 'builder')}.`;
804
797
 
805
- // #777: the welcome panel now shows ONLY setup — a two-config selector that
806
- // gets a zero-technical newcomer from "signed into the hall" to a working
807
- // `claude` session on their dev box. Both paths reach the SAME hosted dev
808
- // box (Xenos are box-only, ADR 0035): the Desktop app connects over an
809
- // automated SSH link (/builder-connect — no keys to copy), and Claude Online
810
- // is the in-browser ttyd terminal (ADR 0038 — no install, no SSH). Steps are
811
- // short, scannable, and plain-spoken (theme stays in the headings). The
812
- // "what to do next" arc lives in the Path checklist below — not here.
813
- // #785: restore the builder's last-chosen config (persisted in localStorage)
814
- // so a re-render / reload / tab switch doesn't snap back to Desktop.
815
- const setupCfg = readSetupConfig();
816
- // R60 (task 1199): the hosted dev-box onboarding below is the `dev-box`
817
- // feature module's UI. A vanilla Cloud Bongos instance has dev-box OFF, so
818
- // there is no box to host — show the bring-your-own-machine path instead.
819
- // OTB (dev-box ON) renders the existing flow verbatim, so prod is unchanged.
820
- const devBoxOn = moduleOn('dev-box');
798
+ // #777: the welcome panel shows ONLY setup — the steps that get a newcomer
799
+ // from "signed into the hall" to a working `claude` session on their own
800
+ // machine. The "what to do next" arc lives in the Path checklist below — not
801
+ // here.
821
802
  // The #support pointer assumes the Discord module; drop it when discord is off.
822
803
  const supportFoot = moduleOn('discord')
823
804
  ? `Stuck on any step? <a href="${API}/auth/discord/start">Join our Discord</a> and ask in <strong>#support</strong>.`
824
805
  : `Stuck on any step? See the project's README and docs.`;
825
- const setupPanes = devBoxOn ? `
826
- <p class="setup__intro">Your work runs on a dev box we host for you — there's almost nothing to install. Choose how to connect:</p>
827
- <div class="setup__toggle" role="tablist" aria-label="Choose a setup">
828
- <button type="button" class="setup__tab setup__tab--desktop" data-config="desktop" role="tab" aria-selected="${setupCfg === 'desktop'}">Claude Desktop app <span class="setup__tab-tag setup__tab-tag--rec">recommended</span></button>
829
- <button type="button" class="setup__tab setup__tab--online" data-config="online" role="tab" aria-selected="${setupCfg === 'online'}">Claude Online <span class="setup__tab-tag">browser only</span></button>
830
- </div>
831
-
832
- <div class="setup__pane setup__pane--desktop">
833
- <ol class="setup__steps">
834
- <li><strong>Download the Dev Box app:</strong>
835
- <a href="/downloads/devbox/mac-arm64">Mac</a> ·
836
- <a href="/downloads/devbox/mac-x64">Mac (Intel)</a> ·
837
- <a href="/downloads/devbox/win-x64">Windows</a> ·
838
- <a href="/downloads/devbox/win-arm64">Windows (ARM)</a>.
839
- <span class="setup__hint">First open: your computer warns about an unknown developer — that's
840
- expected (we haven't bought the signing certificates yet; the app is ours). Mac: System Settings
841
- → Privacy &amp; Security → “Open Anyway”. Windows: “More info” → “Run anyway”.</span></li>
842
- <li><strong>Sign in from the app.</strong> It opens this hall in your browser — click one
843
- <em>Approve</em> button and you're in. No terminal, nothing to paste.</li>
844
- <li><strong>Flip the switch.</strong> Your dev box builds itself in a minute or two and the app
845
- chimes when it's ready. It lives in the menu bar on Mac and the system tray on Windows, and it
846
- wires up Claude Desktop for you along the way.</li>
847
- <li><strong><a href="https://claude.com/download" target="_blank" rel="noopener noreferrer">Download Claude</a></strong>
848
- for Mac or Windows, sign in with your <a href="https://claude.com" target="_blank" rel="noopener noreferrer">Claude</a>
849
- account, then open <strong>Code → Environment → “${brandWorld()} Dev Box”</strong>. You're inside —
850
- build from <code>/workspace</code>.</li>
851
- </ol>
852
- </div>
853
-
854
- <div class="setup__pane setup__pane--online">
855
- <ol class="setup__steps">
856
- <li><strong>Create your <a href="https://claude.com" target="_blank" rel="noopener noreferrer">Claude</a> account.</strong></li>
857
- <li><strong>Open your online environment.</strong> This is the environment you will build in — no SSH, nothing to install.</li>
858
- <li><strong>Sign in when Claude prompts you.</strong> Claude starts automatically when you open the terminal.
859
- <span class="setup__hint">To paste the sign-in code: <strong>Ctrl+Shift+V</strong> or right-click — plain Ctrl+V will not paste here. Claude takes over the terminal with its own interface once you're signed in. This guide stays open in its own tab. If Claude didn't start automatically, type <code>claude</code> and press Enter.</span></li>
860
- <li><strong>Then drive it however you like:</strong>
861
- <span class="setup__hint"><strong>Remote control (recommended)</strong> — type <code>/remote-control</code> for a link that runs this session in Claude's own web/app interface, the same UI you'd use on a computer. <strong>Or just stay in the online terminal</strong> and build right here in the browser — no remote control needed. Either way, reopening the online terminal later resumes your session right where you left it (closing the tab keeps it running).</span></li>
862
- </ol>
863
- </div>
864
- ` : `
806
+ const setupSteps = `
865
807
  <p class="setup__intro">Build from your own machine — clone the repository, run the platform locally, and sign in from the terminal.</p>
866
- <div class="setup__pane">
867
- <ol class="setup__steps">
868
- <li><strong>Clone the repository</strong> and install dependencies (<code>npm install</code>).</li>
869
- <li><strong><a href="https://claude.com/download" target="_blank" rel="noopener noreferrer">Download Claude</a></strong> (or use the Claude Code CLI) and open the project.</li>
870
- <li><strong>Run <code>/builder-setup</code></strong> to authenticate this machine, then <code>/builder-start</code> to claim your first task.</li>
871
- </ol>
872
- </div>
808
+ <ol class="setup__steps">
809
+ <li><strong>Clone the repository</strong> and install dependencies (<code>npm install</code>).</li>
810
+ <li><strong><a href="https://claude.com/download" target="_blank" rel="noopener noreferrer">Download Claude</a></strong> (or use the Claude Code CLI) and open the project.</li>
811
+ <li><strong>Run <code>/builder-setup</code></strong> to authenticate this machine, then <code>/builder-start</code> to claim your first task.</li>
812
+ </ol>
873
813
  `;
874
- // task 469: a "Set up your machine / get the code" door, available in BOTH
875
- // the hosted dev-box flow and the bring-your-own-machine flow. The flows
876
- // above get you a session running; this section answers the separate
814
+ // task 469: a "Set up your machine / get the code" door. The steps above
815
+ // get you a session running; this section answers the separate
877
816
  // question a first-timer always has — "where does the code come from, and
878
817
  // how do I get it onto my own laptop?". It's the hall mirror of the primer's
879
818
  // "Step 0 — get the project onto your machine". Collapsed by default so it
@@ -901,8 +840,8 @@
901
840
  </details>`;
902
841
  body.innerHTML = `
903
842
  <div class="welcome__lede">${greeting} Your standing is ${rankBadge}.</div>
904
- <div class="setup" data-config="${setupCfg}">
905
- ${setupPanes}
843
+ <div class="setup">
844
+ ${setupSteps}
906
845
  ${getCode}
907
846
  <p class="setup__foot">${supportFoot}</p>
908
847
  </div>
@@ -944,7 +883,7 @@
944
883
 
945
884
  // task 470: a static, INFORMATIONAL lead-in step that sits AHEAD of the
946
885
  // data-driven steps — the genuine first action into the city is "obtain the
947
- // repo" (clone it, or open the hosted dev box where it's already cloned).
886
+ // repo" (clone it onto your machine).
948
887
  // It mirrors onboarding-state.js PRE_AUTH_STEP. It is NOT one of the tracked
949
888
  // checklist steps (it carries no engine stage, never gates graduation, and
950
889
  // isn't counted in the "N of M steps cleared" status line) — it just makes
@@ -955,7 +894,7 @@
955
894
  <span class="onboarding-item__mark" aria-hidden="true">›</span>
956
895
  <div class="onboarding-item__body">
957
896
  <p class="onboarding-item__label">First — obtain the repo</p>
958
- <p class="onboarding-item__hint">Clone the project to your machine, or open your hosted dev box (where it is already cloned). The build commands live inside the repo, so this comes first. The remaining steps below are tracked automatically.</p>
897
+ <p class="onboarding-item__hint">Clone the project to your machine. The build commands live inside the repo, so this comes first. The remaining steps below are tracked automatically.</p>
959
898
  </div>
960
899
  </li>`;
961
900
 
@@ -1335,6 +1274,31 @@
1335
1274
  return idx === -1 ? null : { place: idx + 1, total: ranked.length };
1336
1275
  }
1337
1276
 
1338
- return { SETUP_CONFIG_KEY, acclaimEvidenceHtml, analyticsState, lbState, mountHallWidgets, renderCurveBody, renderGreeting, renderLanding, renderNav, renderOnboarding, renderProfile, renderRecentShips, renderWelcomeCore, shipState, shipsPager, welcomeDismissalKey };
1277
+ // task 1003459 — the Claim button on each Home "Next up" row, through the
1278
+ // hall's ONE claim action (task 1003458) rather than a third hand-rolled
1279
+ // POST /claims. Lives here, not builders.js, because that file is at the
1280
+ // 1,500-line ratchet (hall-ui/CLAUDE.md: "growth in the page half has to be
1281
+ // paid for; new pure helper → the lib/renderer"). refresh re-fetches the
1282
+ // two-row slice so a claimed task drops out of it immediately.
1283
+ function wireNextUpClaim() {
1284
+ const claimAction = window.OTBClaimAction.makeClaimAction({ postJSON, toast, API, refresh: loadNextUp });
1285
+ $('#home-next-list')?.addEventListener('click', (e) => {
1286
+ const btn = e.target.closest('.next-up__claim');
1287
+ if (!btn || btn.disabled) return;
1288
+ const taskId = btn.dataset.taskId;
1289
+ btn.disabled = true;
1290
+ btn.textContent = '…';
1291
+ claimAction.claim(taskId).then((out) => {
1292
+ // A redirect to sign-in is already navigating away; re-enabling here
1293
+ // would just invite a click that can't land.
1294
+ if (!out.ok && !out.redirected) {
1295
+ btn.disabled = false;
1296
+ btn.textContent = 'Claim';
1297
+ }
1298
+ });
1299
+ });
1300
+ }
1301
+
1302
+ return { acclaimEvidenceHtml, analyticsState, lbState, mountHallWidgets, renderCurveBody, renderGreeting, renderLanding, renderNav, renderOnboarding, renderProfile, renderRecentShips, renderWelcomeCore, shipState, shipsPager, welcomeDismissalKey, wireNextUpClaim };
1339
1303
  };
1340
1304
  })();
@@ -135,7 +135,11 @@
135
135
  window.OTBProfileNudge; goal-inbox.js's mount() calls it once it has
136
136
  created the #attention-profile div, so load order is not load-bearing. -->
137
137
  <script src="/builders/profile-nudge.js?v=2026-08-25-profile-nudge" defer></script>
138
- <script src="/builders/builders.js?v=2026-06-27-r75" defer></script>
138
+ <!-- task 1003459: the hall's ONE claim/release action (task 1003458) — the
139
+ Home "Next up" row's Claim button consumes it rather than a second
140
+ hand-rolled POST /claims. Loaded BEFORE builders.js, which wires it. -->
141
+ <script src="/builders/claim-action.js?v=2026-09-26-claimaction1" defer></script>
142
+ <script src="/builders/builders.js?v=2026-09-28-nextupclaim" defer></script>
139
143
  <script src="/builders/copy-on-click.js?v=2026-06-01-copy-1" defer></script>
140
144
  </body>
141
145
  </html>
@@ -104,6 +104,7 @@
104
104
  const lines = [];
105
105
  const line = (k, v) => { if (v) lines.push(`<li><span class="ov-key ov-key--faint">${escapeHtml(k)}</span><span class="ov-lines__v">${v}</span></li>`); };
106
106
  line('key', `<span class="ov-mono">${escapeHtml(m.key)}</span>`);
107
+ if (m.version) line('version', `<span class="ov-mono">${escapeHtml(String(m.version))}</span>`);
107
108
  if (m.coreVersion) line('needs core', `<span class="ov-mono">${escapeHtml(String(m.coreVersion))}</span>`);
108
109
  const c = m.contributes || {};
109
110
  for (const kind of Object.keys(c)) {
@@ -1,6 +1,6 @@
1
1
  /* oversight.css — the oversight family's archetype (task 1003469, goal
2
2
  1000081): what an oversight ROW is in the chrome world, and the pieces the
3
- four pages (government, watch, harbor, gate) share around it — the figure
3
+ pages (government, watch, gate) share around it — the figure
4
4
  band inside a panel, the group head, the inline form, the grant toggle, the
5
5
  confirm modal. The third family sheet after record.css and room.css: a page
6
6
  sheet holds only what one page has and the others do not. The collaboration
@@ -15,8 +15,8 @@
15
15
  /* ---- the figure band, inside a panel ---------------------------------------
16
16
  The record family's band (.rec-figs), restated for this family: hairline
17
17
  columns, the figure in the display face at 300, the label above it. A glass
18
- .stat-row is the TOP-of-page strip (Watch's attention row, Harbor and Gate's
19
- summaries); this is the figure row a panel carries under its own heading. */
18
+ .stat-row is the TOP-of-page strip (Watch's attention row, Gate's
19
+ summary); this is the figure row a panel carries under its own heading. */
20
20
  .ov-figs {
21
21
  display: grid;
22
22
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
@@ -210,7 +210,7 @@ a.fact-chip:hover { color: var(--accent-ink); border-color: var(--accent-ink); t
210
210
  .gov-held-note { font-size: 12.5px; color: var(--ok); white-space: nowrap; }
211
211
 
212
212
  /* Detail lines under a row: a reason per line (the gate's holds), or a key and
213
- a value (the harbor's make and cost). Hairlines between, none on the first. */
213
+ a value. Hairlines between, none on the first. */
214
214
  .ov-lines { list-style: none; margin: 10px 0 0; padding: 0; max-width: 72ch; }
215
215
  .ov-lines li { display: flex; gap: 12px; align-items: baseline; padding: 6px 0; border-top: var(--line) solid var(--rule-soft); font-size: 13px; line-height: 1.45; color: var(--ink-soft); }
216
216
  .ov-lines li:first-child { border-top: 0; padding-top: 0; }
@@ -336,7 +336,7 @@ a.fact-chip:hover { color: var(--accent-ink); border-color: var(--accent-ink); t
336
336
  .ov-foot a { display: inline-block; color: var(--accent-ink); min-height: 24px; min-width: 24px; padding: 3px 4px; margin: -3px -4px; line-height: 18px; }
337
337
 
338
338
  /* ---- the confirm modal ----------------------------------------------------------
339
- Harbor and Gate share one confirm dialog. A --bg-card panel closed by one rule
339
+ Gate's confirm dialog. A --bg-card panel closed by one rule
340
340
  hairline and no shadow (the hub's project card is the reference), on the
341
341
  shell's --z-modal layer, over a scrim mixed from the ink. */
342
342
  .ov-modal-bg {
@@ -56,9 +56,6 @@
56
56
  { parent: 'Settings', gate: 'shell-user', items: [
57
57
  { label: 'Account', href: '/settings#account' },
58
58
  { label: 'Access', href: '/settings#access' },
59
- // settings.js builds this panel only when the dev-box module is on, so the
60
- // jump must carry the same condition or it lands on a panel that isn't there.
61
- { label: 'Dev box', href: '/settings#devbox', module: 'dev-box' },
62
59
  { label: 'Extensions', href: '/settings#extensions' },
63
60
  { label: 'Preferences', href: '/settings#preferences' },
64
61
  { label: 'Sound', href: '/settings#sound' },
@@ -92,13 +89,6 @@
92
89
  var el = document.getElementById(id);
93
90
  return !!(el && !el.hidden);
94
91
  }
95
- // Same contract as shell.js moduleOn: an unknown key is treated as ON, so a
96
- // core instance that publishes no module map keeps every destination.
97
- function moduleOn(name) {
98
- var m = window.__MODULES__;
99
- if (!m || !m.enabled || !(name in m.enabled)) return true;
100
- return m.enabled[name] === true;
101
- }
102
92
 
103
93
  // Pages, straight from the rendered sidebar. Skips the external API-docs link's
104
94
  // target rewrite by reading the href attribute as authored.
@@ -128,7 +118,6 @@
128
118
  SECTIONS.forEach(function (s) {
129
119
  if (!visible(s.gate)) return;
130
120
  s.items.forEach(function (it) {
131
- if (it.module && !moduleOn(it.module)) return;
132
121
  out.push({ label: it.label, group: s.parent, href: it.href });
133
122
  });
134
123
  });
@@ -45,7 +45,7 @@
45
45
  { match: 'claim → ship lifecycle', src: '/builders/diagrams/01-task-lifecycle.png', alt: 'The full task lifecycle from backlog through shipped' },
46
46
  { match: 'rank ladder', src: '/builders/diagrams/02-rank-ladder.png', alt: 'The rank ladder — the ranks a builder can hold and how to rise' },
47
47
  { match: 'drachmae and karma', src: '/builders/diagrams/03-drachmae-karma.png', alt: 'How the reward currency and karma differ — pay for shipped work vs. reputation signals' },
48
- { match: 'get set up', src: '/builders/diagrams/04-architecture.png', alt: 'The complete architecture: your device is just the screen, the dev box holds the worker, the code, and your local memory, the droplet is the authority and production, GitHub holds the repo — and how code travels from the box to prod' },
48
+ { match: 'get set up', src: '/builders/diagrams/04-architecture.png', alt: 'The complete architecture: your machine holds the worker, the code, and your local memory, the server is the authority and production, GitHub holds the repo — and how code travels from your machine to prod' },
49
49
  ];
50
50
 
51
51
  // -----------------------------------------------------------------------
@@ -42,7 +42,7 @@
42
42
  </section>
43
43
 
44
44
  <!-- Totals — the shell's glass strip at the top of the page (the way
45
- Watch, Harbor and Gate carry theirs), not a strip inside a panel. -->
45
+ Watch and Gate carry theirs), not a strip inside a panel. -->
46
46
  <section class="ov-summary" id="stats-scroll" aria-labelledby="stats-h" hidden>
47
47
  <h2 id="stats-h" class="sr-only">Totals</h2>
48
48
  <div class="stat-row" id="stats-body"></div>
@@ -24,7 +24,7 @@
24
24
 
25
25
  // The words a person recognises, not the column value. `source` is the same
26
26
  // three-value set the session-scope registry declares.
27
- const SOURCE_LABELS = { cli: 'Terminal', web: 'Browser', box: 'Dev box' };
27
+ const SOURCE_LABELS = { cli: 'Terminal', web: 'Browser' };
28
28
  const sourceLabel = (s) => SOURCE_LABELS[s] || 'Session';
29
29
 
30
30
  // "3 minutes ago" beats a timestamp for the one question this panel exists to
@@ -22,7 +22,6 @@
22
22
  reveal logic in settings.js is unchanged. */
23
23
  .settings-groups > [data-group] { display: none; }
24
24
  .settings-groups[data-active="account"] > [data-group="account"],
25
- .settings-groups[data-active="devbox"] > [data-group="devbox"],
26
25
  .settings-groups[data-active="access"] > [data-group="access"],
27
26
  .settings-groups[data-active="preferences"] > [data-group="preferences"],
28
27
  .settings-groups[data-active="sound"] > [data-group="sound"],
@@ -4,7 +4,7 @@
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
6
  <title>Settings — {{worldName}}</title>
7
- <meta name="description" content="Your preferences — connections, dev box, access keys, skill voices, and sounds.">
7
+ <meta name="description" content="Your preferences — connections, access keys, skill voices, and sounds.">
8
8
  <link rel="icon" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><text x='16' y='24' font-size='24' text-anchor='middle' font-family='sans-serif'>⌂</text></svg>">
9
9
  <link rel="preconnect" href="https://fonts.googleapis.com">
10
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -38,14 +38,14 @@
38
38
  grouped layout: full-width, ungrouped. -->
39
39
  <section class="scroll gate" id="gate-scroll" aria-labelledby="gate-h" hidden>
40
40
  <h2 id="gate-h" class="gate__h">Not signed in</h2>
41
- <p class="gate__lede" id="gate-body">You're not signed in yet. Sign in to manage your connections, your keys, your dev box and the way the hall behaves.</p>
41
+ <p class="gate__lede" id="gate-body">You're not signed in yet. Sign in to manage your connections, your keys and the way the hall behaves.</p>
42
42
  <div class="row-end"><a class="pbtn pbtn--save" href="/api/bongos/auth/web/start">Sign in</a></div>
43
43
  </section>
44
44
 
45
45
  <!-- Grouped layout (task 1723 → kit, task 2172): the sections sit in six
46
46
  groups behind a left sub-nav rail built by OTBKit.makeSectionRail
47
47
  (switch mode). settings.js wires the rail + per-panel anchor deep
48
- links (/settings#cli, /settings#dev-box, …); only the active group's
48
+ links (/settings#cli, /settings#voices, …); only the active group's
49
49
  sections display. -->
50
50
  <div class="settings-layout" id="settings-layout">
51
51
  <nav class="section-rail" id="settings-rail" aria-label="Settings sections"></nav>
@@ -162,7 +162,7 @@
162
162
  <h2 id="sessions-h" class="scroll__h">Active sessions</h2>
163
163
  <p class="scroll__lede">
164
164
  Every place you are currently signed in — this browser, your terminal,
165
- any dev box. A session refreshes for another 24 hours each time it is
165
+ any other machine. A session refreshes for another 24 hours each time it is
166
166
  used, so one you have forgotten about can stay alive indefinitely. If a
167
167
  token has leaked, end it here.
168
168
  </p>
@@ -193,35 +193,6 @@
193
193
  <p class="section-note">Stored encrypted; never shown again after saving — only its last four digits.</p>
194
194
  </section>
195
195
 
196
- <!-- ============ group: devbox ============ -->
197
-
198
- <!-- DEV BOX APP — the desktop switch (#904, ADR 0044). Static download
199
- links; the /downloads/devbox/* redirects resolve to the current
200
- release (config/devbox-app.json). -->
201
- <section class="scroll" id="boxapp-scroll" aria-labelledby="boxapp-h" data-group="devbox" hidden>
202
- <h2 id="boxapp-h" class="scroll__h">Dev box app</h2>
203
- <p class="scroll__lede">
204
- A small app for your menu bar (Mac) or system tray (Windows): one
205
- switch to start and stop your dev box, with a chime when it's ready.
206
- It signs in with browser clicks and sets up Claude Desktop for you —
207
- no terminal at all.
208
- </p>
209
- <div class="settings-card">
210
- <a class="settings-btn" href="/downloads/devbox/mac-arm64">Download for Mac</a>
211
- <a class="settings-btn" href="/downloads/devbox/win-x64">Download for Windows</a>
212
- </div>
213
- <p class="panel-hint">Intel Mac? <a href="/downloads/devbox/mac-x64">This one</a>.
214
- ARM Windows (Surface, Snapdragon, Parallels)? <a href="/downloads/devbox/win-arm64">This one</a>.
215
- <!-- #924: latest-release courtesy line; populated from /downloads/devbox/version -->
216
- <span id="boxapp-latest" hidden></span></p>
217
- <p class="section-note">
218
- First open: your computer warns about an unknown developer — expected
219
- (we haven't bought the signing certificates yet; the app is ours).
220
- Mac: System Settings → Privacy &amp; Security → “Open Anyway”.
221
- Windows: “More info” → “Run anyway”.
222
- </p>
223
- </section>
224
-
225
196
  <!-- ============ group: preferences ============ -->
226
197
 
227
198
  <!-- INTERACTION PROFILE — how replies are pitched for you (task 2010,