@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
@@ -303,6 +303,20 @@ summary{min-height:24px;padding:3px 0;}
303
303
  .addrConfirm details .inner{margin-top:6px;}
304
304
  .addrOpt{display:flex;align-items:flex-start;gap:12px;margin-top:14px;font-size:14px;font-weight:400;color:var(--warn);line-height:1.5;cursor:pointer;}
305
305
  .addrOpt input{margin-top:4px;accent-color:var(--accent);}
306
+ /* the app step (task 1004351, ADR 0345): the hall line, then one row per place the app
307
+ can run. A radio per row so the choice is native; "soon" is a row that is shown but
308
+ cannot be picked yet, and says so in words rather than by colour alone. */
309
+ .appHall{font-size:14.5px;font-weight:400;color:var(--ink-soft);line-height:1.5;max-width:62ch;margin:0 0 18px;}
310
+ .appHall b{color:var(--ink);font-weight:500;}
311
+ .appOpts{border:0;padding:0;margin:0 0 14px;border-top:1px solid var(--rule);}
312
+ .appOpts legend{font-family:var(--label-face);font-size:var(--label-size);letter-spacing:var(--label-space);text-transform:uppercase;font-weight:400;color:var(--ink-faint);padding:0;margin:0 0 10px;}
313
+ .appOpt{display:flex;align-items:flex-start;gap:12px;min-height:24px;padding:14px 0;border-bottom:1px solid var(--rule);cursor:pointer;}
314
+ .appOpt input{flex:none;width:18px;height:18px;margin:3px 0 0;accent-color:var(--accent);}
315
+ .appOpt b{display:block;font-family:var(--font-body);font-size:15px;font-weight:500;color:var(--ink);margin-bottom:2px;}
316
+ .appOpt span span{display:block;font-size:14px;font-weight:400;color:var(--ink-soft);line-height:1.5;max-width:62ch;}
317
+ .appOpt.soon{cursor:default;}
318
+ .appOpt.soon b{color:var(--ink-soft);}
319
+ .appOpt .soonTag{display:inline-block;margin-left:8px;padding:0 8px;border:1px solid var(--rule-soft);border-radius:999px;font-size:12px;font-weight:500;line-height:1.6;color:var(--ink-soft);vertical-align:1px;}
306
320
 
307
321
  /* GitHub repo picker (task 1002099): hairline rows, the chosen one marked on
308
322
  the accent; the private badge in the label face */
@@ -893,7 +907,7 @@ summary{min-height:24px;padding:3px 0;}
893
907
  <div id="mMods"><p class="finePrint">Reading the project…</p></div>
894
908
  <details class="finePrint" id="mModsWhat">
895
909
  <summary>What an extra is — and what is always on</summary>
896
- <p>Extras are the optional parts a project can run — a shared dev box, a Discord mirror, and the rest. You picked a set when you created the project, or took the suggested set by skipping that step; this is where you change your mind. Switching one on or off saves straight away and changes nothing that is already running: nothing restarts, and no work is lost either way. The parts every project runs — the platform itself, the way it tracks work, the builders’ hall — were never part of the choice, so they are not listed here and cannot be switched off.</p>
910
+ <p>Extras are the optional parts a project can run — extra AI agents, a Discord mirror, and the rest. You picked a set when you created the project, or took the suggested set by skipping that step; this is where you change your mind. Switching one on or off saves straight away and changes nothing that is already running: nothing restarts, and no work is lost either way. The parts every project runs — the platform itself, the way it tracks work, the builders’ hall — were never part of the choice, so they are not listed here and cannot be switched off.</p>
897
911
  </details>
898
912
  </div>
899
913
 
@@ -1019,7 +1033,8 @@ summary{min-height:24px;padding:3px 0;}
1019
1033
  <li data-step="4"><span class="snum">4</span><span class="slbl">Modules</span></li>
1020
1034
  <li data-step="5"><span class="snum">5</span><span class="slbl">Home</span></li>
1021
1035
  <li data-step="6"><span class="snum">6</span><span class="slbl">Address</span></li>
1022
- <li data-step="7"><span class="snum">7</span><span class="slbl">Create</span></li>
1036
+ <li data-step="7"><span class="snum">7</span><span class="slbl">App</span></li>
1037
+ <li data-step="8"><span class="snum">8</span><span class="slbl">Create</span></li>
1023
1038
  </ol>
1024
1039
 
1025
1040
  <div class="createSplit">
@@ -1301,14 +1316,44 @@ summary{min-height:24px;padding:3px 0;}
1301
1316
  </form>
1302
1317
  </section>
1303
1318
 
1304
- <!-- step 7 · review + create -->
1319
+ <!-- step 7 · where the app runs (task 1004351, ADR 0345). The hall is ours to
1320
+ host, so this step is only about the owner's APP. Render is listed but
1321
+ cannot be picked until the connect flow lands (task 1004352), which
1322
+ removes the "soon" state; "decide later" is the owner's ruling and is
1323
+ always the default, so nothing here can block a Create. -->
1324
+ <section class="panel" id="panel-app" aria-labelledby="app-h">
1325
+ <h1 id="app-h">Where your app will run</h1>
1326
+ <p class="appHall"><b>We host your Builders' hall</b> — the place where the project gets built — at the address you just chose. There is nothing for you to set up.</p>
1327
+ <p class="lede">Your app is the thing the project builds. Choose where it should run, or decide later.</p>
1328
+ <form data-next="8">
1329
+ <fieldset class="appOpts" id="appOpts">
1330
+ <legend>Where your app runs</legend>
1331
+ <label class="appOpt soon" id="appOptRender">
1332
+ <input type="radio" name="appPlatform" value="render" disabled aria-describedby="appRenderWhat">
1333
+ <span><b>Render <span class="soonTag">Coming soon</span></b>
1334
+ <span id="appRenderWhat">We set your app up on your own Render account. You lend us your Render key once, and Render bills you directly.</span></span>
1335
+ </label>
1336
+ <label class="appOpt">
1337
+ <input type="radio" name="appPlatform" value="later" checked>
1338
+ <span><b>Decide later</b>
1339
+ <span>Create the project now. You can choose where your app runs afterwards.</span></span>
1340
+ </label>
1341
+ </fieldset>
1342
+ <div class="nav">
1343
+ <button type="button" class="btn ghost" data-back="6">← Back</button>
1344
+ <button type="submit" class="btn">Next →</button>
1345
+ </div>
1346
+ </form>
1347
+ </section>
1348
+
1349
+ <!-- step 8 · review + create -->
1305
1350
  <section class="panel" id="panel-review" aria-labelledby="rev-h">
1306
1351
  <h1 id="rev-h">Ready to roll</h1>
1307
1352
  <p class="lede">One tap files the request and the platform starts standing your project up — server, database, address. Here's the beat you're about to drop:</p>
1308
1353
  <ul class="review" id="reviewList"></ul>
1309
1354
  <div class="alert" id="createAlert" role="alert"></div>
1310
1355
  <div class="nav">
1311
- <button type="button" class="btn ghost" data-back="6">← Back</button>
1356
+ <button type="button" class="btn ghost" data-back="7">← Back</button>
1312
1357
  <button type="button" class="btn big" id="doCreate">Create my project</button>
1313
1358
  </div>
1314
1359
  <p class="finePrint">This files the request; the control plane does the real standup and nothing touches servers from this page. You'll get the few steps only you can do right after.</p>
@@ -3238,7 +3283,7 @@ summary{min-height:24px;padding:3px 0;}
3238
3283
  reinterpreted — a stale step 4 meant Address under v1 and Home under v3,
3239
3284
  and replaying it would land on the wrong panel with the rail already
3240
3285
  marking the skipped ones done. Bump this key on EVERY renumbering. */
3241
- var DRAFT_KEY = 'cb-create-draft-v4';
3286
+ var DRAFT_KEY = 'cb-create-draft-v5';
3242
3287
  var CREATED_KEY = 'cb-created-instance';
3243
3288
  /* `description` + `teamShape` are the optional About step (task 1002334) —
3244
3289
  both legitimately stay empty, and empty is what the create request omits. */
@@ -3247,7 +3292,7 @@ summary{min-height:24px;padding:3px 0;}
3247
3292
  request omits the field), [] = the owner switched them all off, [...] =
3248
3293
  what they picked. Never seed it with the preselect — that would store an
3249
3294
  answer nobody gave. */
3250
- var state = { step: 0, name: '', projType: null, description: '', teamShape: null, modules: null, mode: 'greenfield', owner: '', ownerTouched: false, repo: '', repoTouched: false, slug: '', slugTouched: false, domain: '', noAddress: false };
3295
+ var state = { step: 0, name: '', projType: null, description: '', teamShape: null, modules: null, mode: 'greenfield', owner: '', ownerTouched: false, repo: '', repoTouched: false, slug: '', slugTouched: false, domain: '', noAddress: false, appPlatform: 'later' };
3251
3296
  try { Object.assign(state, JSON.parse(sessionStorage.getItem(DRAFT_KEY) || '{}')); } catch (e) {}
3252
3297
  var authKnown = false; /* flips true when the boot's /me settles, either way */
3253
3298
 
@@ -3261,7 +3306,7 @@ summary{min-height:24px;padding:3px 0;}
3261
3306
  state.name = handedName.trim().slice(0, 80);
3262
3307
  state.slug = deriveSlug(state.name); state.slugTouched = false;
3263
3308
  state.repo = deriveRepo(state.name); state.repoTouched = false;
3264
- state.step = state.step >= 1 && state.step <= 7 ? state.step : 1;
3309
+ state.step = state.step >= 1 && state.step <= 8 ? state.step : 1;
3265
3310
  try { sessionStorage.setItem(DRAFT_KEY, JSON.stringify(state)); } catch (e) {}
3266
3311
  }
3267
3312
  } catch (e) {}
@@ -3453,18 +3498,18 @@ summary{min-height:24px;padding:3px 0;}
3453
3498
  }
3454
3499
 
3455
3500
  /* ── step navigation ──
3456
- Eight steps since task 1002339: gate 0 · name 1 · type 2 · about 3 ·
3457
- modules 4 · home 5 · address 6 · review 7 · done 8 (the rail shows 1-7;
3458
- done marks it all). About and Modules are the two steps Next can pass with
3501
+ Nine steps since task 1004351: gate 0 · name 1 · type 2 · about 3 ·
3502
+ modules 4 · home 5 · address 6 · app 7 · review 8 · done 9 (the rail shows
3503
+ 1-8; done marks it all). About and Modules are the two steps Next can pass with
3459
3504
  nothing filled in. */
3460
- var panels = { 0: 'panel-gate', 1: 'panel-name', 2: 'panel-type', 3: 'panel-detail', 4: 'panel-modules', 5: 'panel-home', 6: 'panel-address', 7: 'panel-review', 8: 'panel-done' };
3505
+ var panels = { 0: 'panel-gate', 1: 'panel-name', 2: 'panel-type', 3: 'panel-detail', 4: 'panel-modules', 5: 'panel-home', 6: 'panel-address', 7: 'panel-app', 8: 'panel-review', 9: 'panel-done' };
3461
3506
  /* the rail at the done panel (task 1003244): "done" is the Create step
3462
3507
  still running — the marker stays on 5 until the project actually
3463
3508
  answers, and only then does the whole rail read finished. aria-current
3464
3509
  tells a screen reader the same thing. */
3465
3510
  function paintRail(step) {
3466
- var landed = step === 8 && !!(live && live.instStatus === 'active');
3467
- var cur = step === 8 ? 7 : step;
3511
+ var landed = step === 9 && !!(live && live.instStatus === 'active');
3512
+ var cur = step === 9 ? 8 : step;
3468
3513
  root.querySelectorAll('.steps li').forEach(function (li) {
3469
3514
  var n = Number(li.getAttribute('data-step'));
3470
3515
  var now = !landed && n === cur;
@@ -3475,7 +3520,7 @@ summary{min-height:24px;padding:3px 0;}
3475
3520
  the button role, the tab stop and the data-goto the delegated handler
3476
3521
  below reads. The done panel offers none — the project is filed, and
3477
3522
  there is nothing behind it to change. */
3478
- if (step < 8 && n < cur) {
3523
+ if (step < 9 && n < cur) {
3479
3524
  li.setAttribute('role', 'button');
3480
3525
  li.setAttribute('tabindex', '0');
3481
3526
  li.setAttribute('data-goto', String(n));
@@ -3494,7 +3539,7 @@ summary{min-height:24px;padding:3px 0;}
3494
3539
  paintRail(step);
3495
3540
  saveDraft();
3496
3541
  /* the done step takes the whole card — the bongo pair steps aside */
3497
- root.querySelector('.createSplit').classList.toggle('wizDone', step === 8);
3542
+ root.querySelector('.createSplit').classList.toggle('wizDone', step === 9);
3498
3543
  /* focus moves ONLY on a deliberate step (the hub rule setView already
3499
3544
  applies to this view: never on boot, never on a background settle) */
3500
3545
  if (moveFocus) {
@@ -3510,12 +3555,13 @@ summary{min-height:24px;padding:3px 0;}
3510
3555
  if (step === 5) { syncHome(); if (authKnown) ensureRepoAccess(); }
3511
3556
  /* a resumed draft can land PAST the Home step with the probe never run —
3512
3557
  Create would then file a repo it promised to make but never did */
3513
- else if (step > 5 && step < 8 && authKnown && repoAccess === null) ensureRepoAccess();
3558
+ else if (step > 5 && step < 9 && authKnown && repoAccess === null) ensureRepoAccess();
3514
3559
  /* re-check on every entry, not just on typing: a resumed draft arrives here with
3515
3560
  a handle nobody has asked the server about, and a handle free ten minutes ago
3516
3561
  may not be now (task 1002898 N10) */
3517
3562
  if (step === 6) { checkSlugAvailable(); renderAddrPanel(); }
3518
- if (step === 7) renderReview();
3563
+ if (step === 7) syncAppStep();
3564
+ if (step === 8) renderReview();
3519
3565
  }
3520
3566
 
3521
3567
  /* One delegated pair on the rail, so paintRail can add and drop data-goto
@@ -3709,7 +3755,7 @@ summary{min-height:24px;padding:3px 0;}
3709
3755
  prevent, one screen before Create. */
3710
3756
  function repaintForBundles() {
3711
3757
  if (state.step === 4) renderModules();
3712
- else if (state.step === 7) renderReview();
3758
+ else if (state.step === 8) renderReview();
3713
3759
  }
3714
3760
  /* The row for the declared type, or null before the read lands / for a type
3715
3761
  the table has no row for (including no type at all). */
@@ -3742,8 +3788,8 @@ summary{min-height:24px;padding:3px 0;}
3742
3788
 
3743
3789
  The fallback is the point (task 1003684). `adjustments` is a DELTA: a rule that
3744
3790
  fires without changing anything claims nothing (ADR 0243). So for a type whose
3745
- bundle ALREADY contains what the rule would add — game is [dev-box, discord] and
3746
- the small-team rule adds dev-box — the delta is empty and the owner was shown a
3791
+ bundle ALREADY contains what the rule would add — game is [discord] and the
3792
+ community rule adds discord — the delta is empty and the owner was shown a
3747
3793
  tailored preselect with no reason beside it at all. That is the state ADR 0237
3748
3794
  calls worse than no preselect: one the owner has to audit. Each bundle carries a
3749
3795
  curated summary authored for exactly this, served on every row, and until now
@@ -4201,6 +4247,28 @@ summary{min-height:24px;padding:3px 0;}
4201
4247
  });
4202
4248
 
4203
4249
  /* ── review ── */
4250
+ /* the app step (task 1004351): a native radio group, so the draft only mirrors it.
4251
+ An older draft has no appPlatform, and a value this page does not offer (a
4252
+ platform still marked soon, or one that was removed) reads as 'later' — the
4253
+ review must never name a platform the owner could not actually pick. */
4254
+ function appPlatformChoice() {
4255
+ var want = state.appPlatform;
4256
+ var pick = Array.prototype.filter.call(root.querySelectorAll('#appOpts input[name=appPlatform]'), function (i) {
4257
+ return i.value === want && !i.disabled;
4258
+ })[0];
4259
+ return pick ? pick.value : 'later';
4260
+ }
4261
+ function syncAppStep() {
4262
+ var pick = appPlatformChoice();
4263
+ root.querySelectorAll('#appOpts input[name=appPlatform]').forEach(function (i) { i.checked = i.value === pick; });
4264
+ }
4265
+ function appRow() {
4266
+ return appPlatformChoice() === 'render' ? 'Render, on your own account' : 'Not chosen yet — you can decide later';
4267
+ }
4268
+ var appOptsEl = root.querySelector('#appOpts');
4269
+ if (appOptsEl) appOptsEl.addEventListener('change', function (ev) {
4270
+ if (ev.target && ev.target.name === 'appPlatform' && !ev.target.disabled) { state.appPlatform = ev.target.value; saveDraft(); }
4271
+ });
4204
4272
  function renderReview() {
4205
4273
  /* every road back to this step gets a live button — the create path
4206
4274
  disables it and only the failure branch used to restore it, which
@@ -4227,9 +4295,10 @@ summary{min-height:24px;padding:3px 0;}
4227
4295
  ['Address', resolvedDomain()
4228
4296
  ? '<code>' + esc(resolvedDomain()) + '</code>'
4229
4297
  : '<em style="font-weight:600;color:var(--warn)">none — sign-in stays locked until it has one</em>'],
4230
- /* The wizard creates hosting_shape 'cloud-host' — we stand it up and run it for
4231
- them. Since task 1004182 the stored value IS the owner-facing name (ADR 0323). */
4232
- ['Shape', 'Cloud host — we stand it up and run it for you, on the platform’s current release']
4298
+ /* The wizard creates hosting_shape 'cloud-host', which since ADR 0345 means the
4299
+ HALL is hosted by us; where the owner's APP runs is its own row (task 1004351). */
4300
+ ['Builders\' hall', 'Hosted by us, on the platform’s current release'],
4301
+ ['App', appRow()]
4233
4302
  ];
4234
4303
  $('reviewList').innerHTML = rows.map(function (r) {
4235
4304
  return '<li><span class="k">' + r[0] + '</span><span class="v">' + r[1] + '</span></li>';
@@ -4362,7 +4431,7 @@ summary{min-height:24px;padding:3px 0;}
4362
4431
  sessionStorage.removeItem(DRAFT_KEY);
4363
4432
  } catch (e) {}
4364
4433
  renderDone();
4365
- show(8, true);
4434
+ show(9, true);
4366
4435
  startProgress(data.instance && data.instance.id);
4367
4436
  }).catch(function (err) {
4368
4437
  if (String(err && err.message) === 'signing in') return;
@@ -4935,7 +5004,7 @@ summary{min-height:24px;padding:3px 0;}
4935
5004
  5s tick never clobbers an open dropdown or mid-flight button) */
4936
5005
  if (inst && inst.status !== live.instStatus) {
4937
5006
  live.instStatus = inst.status; renderSteps();
4938
- if (state.step === 8) paintRail(8); /* the rail finishes only when the project answers */
5007
+ if (state.step === 9) paintRail(9); /* the rail finishes only when the project answers */
4939
5008
  }
4940
5009
  var terminal = renderProgress(inst);
4941
5010
  if (!terminal) pollTimer = setTimeout(tick, 5000);
@@ -4975,7 +5044,7 @@ summary{min-height:24px;padding:3px 0;}
4975
5044
  is three-valued and null is its "nothing said" sentinel; leaving the key out
4976
5045
  left it UNDEFINED, which is not null — so pickedModules() reached .slice()
4977
5046
  on it and the second project's Modules step threw. */
4978
- state = { step: 1, name: '', projType: null, description: '', teamShape: null, modules: null, mode: 'greenfield', owner: '', ownerTouched: false, repo: '', repoTouched: false, slug: '', slugTouched: false, domain: '', noAddress: false };
5047
+ state = { step: 1, name: '', projType: null, description: '', teamShape: null, modules: null, mode: 'greenfield', owner: '', ownerTouched: false, repo: '', repoTouched: false, slug: '', slugTouched: false, domain: '', noAddress: false, appPlatform: 'later' };
4979
5048
  $('newName').value = ''; $('f-owner').value = ''; $('f-repo').value = ''; $('f-slug').value = ''; $('f-domain').value = '';
4980
5049
  $('f-noaddr').checked = false; $('f-desc').value = '';
4981
5050
  /* Re-seed the owner from the signed-in account for the next project. */
@@ -5044,17 +5113,17 @@ summary{min-height:24px;padding:3px 0;}
5044
5113
  another project" the only way out.
5045
5114
 
5046
5115
  The reset fires only when there is a SECOND DRAFT to lose, and the draft's own
5047
- step is what says so. A landed create clears DRAFT_KEY — but show(8) then
5116
+ step is what says so. A landed create clears DRAFT_KEY — but show(9) then
5048
5117
  persists the done panel's own position straight back into it, so "is there a
5049
5118
  draft?" is always yes and would have skipped the reset forever, leaving the
5050
- finished project's name sitting in the fresh form. Only steps 1–7 are wizard
5119
+ finished project's name sitting in the fresh form. Only steps 1–8 are wizard
5051
5120
  steps: anything else is the done panel's bookkeeping, not a project someone
5052
5121
  is part-way through typing. */
5053
5122
  function enterCreated(created, focus) {
5054
5123
  if (focus && !resumeIntent) {
5055
5124
  var draft = null;
5056
5125
  try { draft = JSON.parse(sessionStorage.getItem(DRAFT_KEY) || 'null'); } catch (e) {}
5057
- var at = draft && draft.step >= 1 && draft.step <= 7 ? draft.step : 0;
5126
+ var at = draft && draft.step >= 1 && draft.step <= 8 ? draft.step : 0;
5058
5127
  if (!at) { resetForNewProject(); at = 1; }
5059
5128
  paintResumeOffer(created);
5060
5129
  /* step 1's own focus target is the name field, not the heading — the same
@@ -5078,7 +5147,7 @@ summary{min-height:24px;padding:3px 0;}
5078
5147
  manifestState = created.manifest_state; manifestPending = true;
5079
5148
  }
5080
5149
  renderDone();
5081
- show(8, !!focus);
5150
+ show(9, !!focus);
5082
5151
  startProgress(created.id);
5083
5152
  resumePolls();
5084
5153
  }
@@ -5095,7 +5164,7 @@ summary{min-height:24px;padding:3px 0;}
5095
5164
  /* before identity settles, never render past the name step: deeper steps
5096
5165
  carry authenticated side effects (the Home-step repo probe), and onAuth()
5097
5166
  re-enters to the real draft step the moment /me answers */
5098
- var step = authKnown && state.step >= 1 && state.step <= 7 ? state.step : 1;
5167
+ var step = authKnown && state.step >= 1 && state.step <= 8 ? state.step : 1;
5099
5168
  if (step === 1) {
5100
5169
  /* Pre-auth, step 1 is a PLACEHOLDER, not where the visitor is — but show()
5101
5170
  persists whatever step it renders, so it used to overwrite the draft's real
@@ -5104,7 +5173,7 @@ summary{min-height:24px;padding:3px 0;}
5104
5173
  step back after rendering the placeholder, in memory AND in the draft. */
5105
5174
  var resumeStep = state.step;
5106
5175
  show(1, false);
5107
- if (!authKnown && resumeStep >= 1 && resumeStep <= 7) { state.step = resumeStep; saveDraft(); }
5176
+ if (!authKnown && resumeStep >= 1 && resumeStep <= 8) { state.step = resumeStep; saveDraft(); }
5108
5177
  if (focus) $('newName').focus();
5109
5178
  } else {
5110
5179
  show(step, !!focus);
@@ -159,10 +159,10 @@
159
159
  "steps": [["wait",900],["click","[data-disc-ask]"],["wait",200],["fill","#mDiscName","old-lantern"],["wait",100],["click","[data-disc-yes]"],["wait",900]],
160
160
  "expect": {"text":[["#mDisc .addr","This project is being disconnected."],["#mName","old-lantern"]],"hidden":["#mDiscName","[data-disc-ask]"]} },
161
161
  { "name": "the wizard driver (task 1003346): name, type, about, home (fresh; the stub grants repo access, so the new repository is named from the project), address (the handle's verdict), the review as a ledger, then the filing — the done panel with the standup rail and the human steps", "auth": true, "width": 1440, "url": "/projects?view=new",
162
- "steps": [["wait",600],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["click","#panel-modules button[type=submit]"],["wait",400],["click","#panel-home button[type=submit]"],["wait",400],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#panel-address button[type=submit]"],["wait",400],["click","#doCreate"],["wait",1500]],
162
+ "steps": [["wait",600],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["click","#panel-modules button[type=submit]"],["wait",400],["click","#panel-home button[type=submit]"],["wait",400],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#panel-address button[type=submit]"],["wait",400],["click","#panel-app button[type=submit]"],["wait",400],["click","#doCreate"],["wait",1500]],
163
163
  "expect": {"visible":["#panel-done","#liveProgress .prog","#liveProgress .prog .stages li.now","#humanSteps li"],"hidden":["#panel-review","#panel-name"],"text":[["#done-h","The drums are rolling"]],"attr":[["#panel-done","class","panel on"]]} },
164
164
  { "name": "the wizard driver at 390: the rail folds to two rows of three and the walk still reaches the review", "auth": true, "width": 390, "url": "/projects?view=new",
165
- "steps": [["wait",600],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["click","#panel-modules button[type=submit]"],["wait",400],["click","#panel-home button[type=submit]"],["wait",400],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#panel-address button[type=submit]"],["wait",400]],
165
+ "steps": [["wait",600],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["click","#panel-modules button[type=submit]"],["wait",400],["click","#panel-home button[type=submit]"],["wait",400],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#panel-address button[type=submit]"],["wait",400],["click","#panel-app button[type=submit]"],["wait",400]],
166
166
  "expect": {"visible":["#panel-review","#reviewList li","#doCreate"],"hidden":["#panel-address"],"text":[["#rev-h","Ready to roll"]]} }
167
167
  ]
168
168
  }
@@ -36,9 +36,10 @@
36
36
  "in-new-modules-search": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["fill","#modQ","discord"],["wait",200]], "expect": {"visible":["#panel-modules","#modQ"],"value":[["#modQ","discord"]],"count":[["#modCards .tpill",1],["#modCards .tpill[data-mod=\"discord\"]",1]],"text":[["#modFilterNote","Showing 1 of 3. 2 extras are switched on, including any this search is hiding."]]} },
37
37
  "in-new-home": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["click","#panel-modules button[type=submit]"],["wait",400]], "expect": {"visible":["#panel-home"],"hidden":["#panel-detail","#qWrap"]} },
38
38
  "in-new-address": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["click","#panel-modules button[type=submit]"],["wait",400],["click","#panel-home button[type=submit]"],["wait",400]], "expect": {"visible":["#panel-address"],"hidden":["#panel-home","#qWrap"]} },
39
- "in-new-review": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["click","#panel-modules button[type=submit]"],["wait",400],["click","#panel-home button[type=submit]"],["wait",400],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#panel-address button[type=submit]"],["wait",400]], "expect": {"visible":["#panel-review","#reviewList li"],"hidden":["#panel-address","#qWrap"]} },
40
- "in-new-done": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["click","#panel-modules button[type=submit]"],["wait",400],["click","#panel-home button[type=submit]"],["wait",400],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#panel-address button[type=submit]"],["wait",400],["click","#doCreate"],["wait",1500]], "expect": {"visible":["#panel-done","#liveProgress .prog","#humanSteps li"],"hidden":["#panel-review","#qWrap"]} },
41
- "in-new-resume-offer": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["click","#panel-modules button[type=submit]"],["wait",400],["click","#panel-home button[type=submit]"],["wait",400],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#panel-address button[type=submit]"],["wait",400],["click","#doCreate"],["wait",1500],["click","#projTrig"],["wait",350],["click","#menuProjects [data-nav=\"new\"]"],["wait",500]], "expect": {"visible":["#panel-name","#wizResume","#wizResumeGo"],"hidden":["#panel-done"],"text":[["#wizResumeName","Mercury"]]} },
39
+ "in-new-app": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["click","#panel-modules button[type=submit]"],["wait",400],["click","#panel-home button[type=submit]"],["wait",400],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#panel-address button[type=submit]"],["wait",400]], "expect": {"visible":["#panel-app","#appOpts","#appOptRender .soonTag"],"hidden":["#panel-address","#panel-review","#qWrap"]} },
40
+ "in-new-review": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["click","#panel-modules button[type=submit]"],["wait",400],["click","#panel-home button[type=submit]"],["wait",400],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#panel-address button[type=submit]"],["wait",400],["click","#panel-app button[type=submit]"],["wait",400]], "expect": {"visible":["#panel-review","#reviewList li"],"hidden":["#panel-address","#qWrap"]} },
41
+ "in-new-done": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["click","#panel-modules button[type=submit]"],["wait",400],["click","#panel-home button[type=submit]"],["wait",400],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#panel-address button[type=submit]"],["wait",400],["click","#panel-app button[type=submit]"],["wait",400],["click","#doCreate"],["wait",1500]], "expect": {"visible":["#panel-done","#liveProgress .prog","#humanSteps li"],"hidden":["#panel-review","#qWrap"]} },
42
+ "in-new-resume-offer": { "auth": true, "url": "/projects?view=new", "actions": [["wait",600],["fill","#newName","Mercury"],["click","#panel-name button[type=submit]"],["wait",400],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-type button[type=submit]"],["wait",400],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#teamCards .tpill[data-team=\"small-team\"]"],["click","#panel-detail button[type=submit]"],["wait",900],["click","#panel-modules button[type=submit]"],["wait",400],["click","#panel-home button[type=submit]"],["wait",400],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#panel-address button[type=submit]"],["wait",400],["click","#panel-app button[type=submit]"],["wait",400],["click","#doCreate"],["wait",1500],["click","#projTrig"],["wait",350],["click","#menuProjects [data-nav=\"new\"]"],["wait",500]], "expect": {"visible":["#panel-name","#wizResume","#wizResumeGo"],"hidden":["#panel-done"],"text":[["#wizResumeName","Mercury"]]} },
42
43
  "out-map-projects": { "auth": false, "actions": [["click", "#projTrig"], ["wait", 350]], "expect": { "expanded": true, "hidden": ["#menuProjects [data-nav=\"mine\"]"] } },
43
44
  "card": { "auth": true, "actions": [["dispatchClick", "#orbField a.worldOrb[data-origin=\"https://example.com\"]"], ["wait", 900]], "expect": { "dialog": true, "hasClass": [["#projCard", "has-art"]], "visible": ["#cardArt", "#cardFaces", "#cardBuildersFig", "#cardShippedFig", "#cardOpen", "#cardHall"], "text": [["#cardBuilders", "11"], ["#cardShipped", "0"], ["#cardRel", "you build here"], ["#cardRuns", "example.com"], ["#cardFaces .facesMore", "+6"]], "count": [["#cardFaces img", 5]], "href": [["#cardHall", "https://builders.example.com/"]] } },
44
45
  "card-noart": { "auth": true, "actions": [["dispatchClick", "#orbField a.worldOrb[data-origin=\"https://emersonian-circles.cloudbongos.com\"]"], ["wait", 600]], "expect": { "dialog": true, "hasClass": [["#projCard", "has-art", false]], "hidden": ["#cardArt", "#cardFaces", "#cardHall"], "visible": ["#cardBuildersFig", "#cardShippedFig", "#cardOpen"], "text": [["#cardShipped", "30+"], ["#cardRel", "you build here"]] } },
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
6
  <!-- Server-stamped like index.html and projects.html (task 1003251): the {{…}}
7
7
  tokens are filled by landingPage() (src/platform-server.js) from the
8
- instance's own branding, and every <!--apex-only--> region is REMOVED off
8
+ instance's own branding, and every apex-only:start/end region is REMOVED off
9
9
  the hub — a claim about the platform must not ship in a child project's
10
10
  page (task 1002748). The baked values are the NEUTRAL pack's. -->
11
11
  <title>{{productName}} — Terms</title>
@@ -2,6 +2,7 @@
2
2
  "key": "security",
3
3
  "title": "Security (red-team · bounty)",
4
4
  "description": "The red-team / vulnerability-report intake and the bounty payout system (rank-gated Metic+): the /builder-redteam skill files a report, the Archon dashboard adjudicates (confirm/dispute/fix/link-fix), and the env-aware bounty table sets the per-severity drachmae payout. A core-domain module carved out of the GDS core in BV1.R79 (ADR 0093 §1; 02-module-map §5 — security-the-FEATURE, NOT security-the-property, which stays kernel). default-on because every instance can take red-team reports. Registers the `security` kernel PORT the core /public/bounty-table resolves for the payout schedule. Also owns the scan-before-install surface (goal 1000055): the artifact-scan engine (quarantine/manifest/mirror) and the security_tool_scans record — POST Metic+, GET every rank.",
5
+ "version": "1.0.0",
5
6
  "coreVersion": "^1.8.0",
6
7
  "default": true,
7
8
  "maintenance": { "status": "core-maintained" },
@@ -2,6 +2,7 @@
2
2
  "key": "sessions",
3
3
  "title": "Sessions & BFG (session corpus · efficiency eval)",
4
4
  "description": "The session-records corpus + its data plane (POST /sessions upload, the Archon-gated cross-builder /sessions/search + /sessions/:id deep-dive + /sessions/upload-health, the server-side signal that a builder's session uploads have silently stopped), the BFG 'read-the-room' cross-builder scorer (ADR 0026 §6B), and the session-pulse / stale-claim heartbeat helpers. A core-domain module carved out of the GDS core in BV1.R82 (ADR 0093 §1); default-on because every instance records its builders' sessions for the BFG. Like the memory module, sessions registers no port — core never calls back into it: the ship-time digest write is an HTTP POST to the module's own /sessions route, and the only outward dependency is the economy `reward` kernel PORT it resolves (session token reward + sumCreditsForTasks) at upload time.",
5
+ "version": "1.0.0",
5
6
  "coreVersion": "^1.10.0",
6
7
  "default": true,
7
8
  "maintenance": { "status": "core-maintained" },
@@ -2,6 +2,7 @@
2
2
  "key": "specialities",
3
3
  "title": "Role sub-specialities (harnesses)",
4
4
  "description": "Role SUB-SPECIALITIES — a named bundle of knowledge, skills and an interaction contract that sits UNDER a craft (task 1003855; ADR 0296). A craft says how you work (engineer / ideator / artist / ui); a speciality says what you work ON and how a subject-matter expert wants to be engaged inside it. Deliberately a thin layer over three surfaces that already exist — discipline-modes.json for craft->playbook, behavior_prefs.interaction for the per-session contract (a speciality contract rides that SAME GET /me -> Conductor path rather than adding a second one), and the ADR 0083 manifest for declared skills; the only new machinery is the knowledge bundle. Training is two-fold per the owner's 2026-09-17 ruling: documents the builder supplied, plus learnings captured from sessions worked in the speciality (pointing at existing `learnings` rows, never a second corpus). Owned per-builder OR per-project, each carrying its owner's sharing decision (private / project / public) and an explicit sellable flag — the flag records intent only, because ADR 0107 defers the marketplace and there is nothing to list on. default-on: a speciality is how an instance's expertise enters the platform, so it ships like the hall and the status page.",
5
+ "version": "1.0.0",
5
6
  "coreVersion": "^1.19.0",
6
7
  "default": true,
7
8
  "maintenance": { "status": "core-maintained" },
@@ -2,6 +2,7 @@
2
2
  "key": "status-ui",
3
3
  "title": "Status dashboard (\"The Watch\")",
4
4
  "description": "The public build-status dashboard served at status.<apex> (status.example.com) — the live up/down banner, version-progress rollups, cost summary, recent ships, leaderboard, and the ecosystem fingerprint, all polling the read-only /api/bongos/public/* surface every 60s. A WEB-SURFACE core-domain module carved out of the GDS core in BV1.R84 (ADR 0093 §1; 02-module-map §6 — a web surface is first-class). default-on: a Cloud Bongos instance ships its status page like it ships its hall. Registers no port and contributes no routes — it declares a webSurface (host prefix + static dir) the loader hands serve-internal, which serves the module's public/ dir on the matching host exactly as it served public-status/ before. The public read endpoints it renders stay SHARED core in routes/public.js (the hall + the off-box mirror read them too).",
5
+ "version": "1.0.0",
5
6
  "coreVersion": "^1.11.0",
6
7
  "default": true,
7
8
  "maintenance": { "status": "core-maintained" },
@@ -2,6 +2,7 @@
2
2
  "key": "ui-design",
3
3
  "title": "UI design (the design contract, its adapters and sync, the /design playbook, the kit, the skills, the styles)",
4
4
  "description": "The platform capability that lets any builder on any instance create and design good-looking, functional UIs in line with that instance's world (scoped with the owner 2026-08-28; task 1003324, ADR 0197). It ships METHOD and never a world: the neutral design contract of ADR 0081 with its tool adapters (Claude Design, Figma), their sync CLIs and the validator; the /design playbook for ui-discipline work; and the reserved homes for the look-before-you-ship kit (kit/), the vetted UI skills (skills/) and the style library (styles/) the sibling tasks land. The instance's world — its branding pack, config/design-tokens.*, config/design-sources.json and its DESIGN.md — stays in config/ and at the repo root as the host boundary this module reads and never owns (ADR 0062 §7). Cloud Bongos's own front door is this module's first customer, not its owner. default-on because every instance has a face. No routes, no migrations, no port: declaration-only like character-anim, so disabling it withdraws only the skills it contributes and touches no served surface.",
5
+ "version": "1.0.0",
5
6
  "coreVersion": "^1.19.0",
6
7
  "default": true,
7
8
  "maintenance": { "status": "core-maintained" },
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.1072",
3
+ "version": "1.19.1074",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@bongos/core",
9
- "version": "1.19.1072",
9
+ "version": "1.19.1074",
10
10
  "license": "AGPL-3.0-or-later",
11
11
  "dependencies": {
12
12
  "express": "^4.21.2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bongos/core",
3
- "version": "1.19.1072",
3
+ "version": "1.19.1074",
4
4
  "description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "main": "src/platform-server.js",
@@ -7737,5 +7737,89 @@
7737
7737
  "id": "1003801",
7738
7738
  "text": "Decided who tests new module versions first: projects that switch on testing once, and a version nobody tests still reaches everyone after seven days."
7739
7739
  }
7740
+ ],
7741
+ "1.19.1073": [
7742
+ {
7743
+ "id": "1004313",
7744
+ "text": "Tweak Mode is live on cloudbongos.com, and the artist gate is off. Artists can now open the lofi studio, take a whole page, rewrite it (in the studio or in Word), and approve the finished page before it ships. The seven old pe"
7745
+ }
7746
+ ],
7747
+ "1.19.1074": [
7748
+ {
7749
+ "id": "1004361",
7750
+ "text": "Fixed the test that had been blocking every new release of the platform since last evening. A test's sample module was missing the version number that modules now need, so the release step refused to run. With it fixed, the wa"
7751
+ },
7752
+ {
7753
+ "id": "1003895",
7754
+ "text": "The dev box's stored data is removed from the database: its four tables and the leftover dev-box login tokens. A fresh backup was taken first. Nothing else changes for builders."
7755
+ },
7756
+ {
7757
+ "id": "1004351",
7758
+ "text": "New projects now get a step that says we host their Builders Hall and asks where their app should run. Render is shown as coming soon; for now they can decide later."
7759
+ },
7760
+ {
7761
+ "id": "1003894",
7762
+ "text": "The leftover dev-box login tokens can no longer reach anything, and the three dev-box permissions are gone from every rank. Nobody's other permissions change. Sign-in and the rank and permission screens work as before."
7763
+ },
7764
+ {
7765
+ "id": "1004358",
7766
+ "text": "Tweak Mode's before-and-after screenshots can now be attached to a tweak. Every upload was being refused as too large, even though each picture was only about 100 KB, because a general size limit checked the upload before the"
7767
+ },
7768
+ {
7769
+ "id": "1004359",
7770
+ "text": "The Contact, Privacy and Terms pages had a scrap of behind-the-scenes note showing at the very top, above the menu. It came from a hidden note that accidentally closed itself too early. The note is reworded so it stays hidden,"
7771
+ },
7772
+ {
7773
+ "id": "1004311",
7774
+ "text": "The builders' hall no longer mentions dev boxes. Settings loses its Dev box section, the quick-jump menu loses its Dev box entry, and the architecture diagram now shows work running on your own machine. It also fixes a bug on"
7775
+ },
7776
+ {
7777
+ "id": "1004241",
7778
+ "text": "Area 5's task list is now honest: one stale task dropped, 14 rewritten to match the settled decisions, and the two waiting on the credit-economy area put back in backlog."
7779
+ },
7780
+ {
7781
+ "id": "1004354",
7782
+ "text": "A page you download as a Word file, edit in Google Docs and upload back now lands in your draft. Google Docs throws away the hidden details that said which page the file was, so the site used to refuse it as the wrong page. No"
7783
+ },
7784
+ {
7785
+ "id": "1004349",
7786
+ "text": "Decided: we host every project's Builders Hall, and owners choose where their app deploys, starting with Render. Also found and filed a sign-in cookie risk for halls on our addresses."
7787
+ },
7788
+ {
7789
+ "id": "1004356",
7790
+ "text": "The /feedback command works again: Claude Code can load your latest recorded walkthrough and its screenshots."
7791
+ },
7792
+ {
7793
+ "id": "1004142",
7794
+ "text": "A Bongos project now runs on Render, on its owner's own account: it starts, signs in, sets up its database and is backed up by Render, which clears the way to move projects off our server."
7795
+ },
7796
+ {
7797
+ "id": "1003459",
7798
+ "text": "You can now claim a task straight from its own page and from the \"Next up\" list on Home — both used to only tell you to claim it elsewhere. Every claim refusal (rank too low, someone else got there first, etc.) shows the same"
7799
+ },
7800
+ {
7801
+ "id": "1004310",
7802
+ "text": "New builders' setup checklist no longer asks them to connect a cloud dev box, and the sign-in path built for the retired dev box desktop app is gone. The builder guide now describes the one setup that exists: working from a co"
7803
+ },
7804
+ {
7805
+ "id": "1003892",
7806
+ "text": "Removed the dev box feature itself from the platform. Sites that still had it switched on in their settings keep starting normally — they now log a one-line note instead of failing to boot."
7807
+ },
7808
+ {
7809
+ "id": "1004271",
7810
+ "text": "Module authors can now publish a new version of their module to the Bongos module store with one command; the store checks it and keeps it ready for installs."
7811
+ },
7812
+ {
7813
+ "id": "1003893",
7814
+ "text": "Removed the machinery that created, parked and woke builders' cloud dev boxes, plus the scripts that ran on those boxes and the two background jobs that swept them. Nothing a builder uses today changes; the local preview and i"
7815
+ },
7816
+ {
7817
+ "id": "1003812",
7818
+ "text": "The module store now has somewhere to keep its list of modules, each published version, and what each one costs (free included)."
7819
+ },
7820
+ {
7821
+ "id": "1003781",
7822
+ "text": "Every module now has its own version number, shown in the module list and the hall's Modules tab — the first step toward publishing and updating modules through the store."
7823
+ }
7740
7824
  ]
7741
7825
  }