@bongos/core 1.24.29 → 1.24.31

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 (113) hide show
  1. package/.bongos-core.json +198 -108
  2. package/clients/bongos-client/README.md +1 -1
  3. package/clients/bongos-client/bongos-client.global.js +12 -0
  4. package/clients/bongos-client/index.cjs +12 -0
  5. package/clients/bongos-client/index.d.ts +12 -0
  6. package/clients/bongos-client/index.mjs +12 -0
  7. package/docs/api/openapi.json +174 -1
  8. package/docs/api-reference.md +12 -2
  9. package/docs/copy-inventory.md +226 -224
  10. package/docs/copy-registry.json +583 -549
  11. package/docs/module-api-changelog.md +2 -0
  12. package/docs/page-inventory.json +18 -37
  13. package/docs/page-readings.json +306 -361
  14. package/modules/copy-desk/module.json +1 -1
  15. package/modules/copy-desk/routes/copy-desk-studio.js +103 -0
  16. package/modules/copy-desk/tests/copy_no_cms.mjs +2 -2
  17. package/modules/government/db.js +29 -0
  18. package/modules/government/docket.js +61 -4
  19. package/modules/government/routes/government.js +2 -0
  20. package/modules/hall-ui/public/ai-studio.html +1 -1
  21. package/modules/hall-ui/public/atlas.html +1 -1
  22. package/modules/hall-ui/public/blockers.html +1 -1
  23. package/modules/hall-ui/public/board-room.html +1 -1
  24. package/modules/hall-ui/public/builders.js +3 -79
  25. package/modules/hall-ui/public/city.html +1 -1
  26. package/modules/hall-ui/public/collab.html +1 -1
  27. package/modules/hall-ui/public/commands.html +1 -1
  28. package/modules/hall-ui/public/copy-desk.html +1 -1
  29. package/modules/hall-ui/public/craft-mode.js +1 -1
  30. package/modules/hall-ui/public/deploy.html +1 -1
  31. package/modules/hall-ui/public/diagrams.html +1 -1
  32. package/modules/hall-ui/public/drachmae.html +1 -1
  33. package/modules/hall-ui/public/fleet.html +1 -1
  34. package/modules/hall-ui/public/gate.html +1 -1
  35. package/modules/hall-ui/public/goal-map.html +1 -1
  36. package/modules/hall-ui/public/goals.html +1 -1
  37. package/modules/hall-ui/public/government.html +1 -1
  38. package/modules/hall-ui/public/hall-render.js +68 -167
  39. package/modules/hall-ui/public/hall-widgets.js +4 -45
  40. package/modules/hall-ui/public/home-city-draw.js +583 -0
  41. package/modules/hall-ui/public/home-city.css +102 -0
  42. package/modules/hall-ui/public/home-city.js +339 -0
  43. package/modules/hall-ui/public/home-gallery.css +129 -0
  44. package/modules/hall-ui/public/home-gallery.js +349 -0
  45. package/modules/hall-ui/public/home-studio.css +72 -0
  46. package/modules/hall-ui/public/home-studio.js +203 -0
  47. package/modules/hall-ui/public/idea.html +1 -1
  48. package/modules/hall-ui/public/ideas.html +1 -1
  49. package/modules/hall-ui/public/index.html +9 -7
  50. package/modules/hall-ui/public/index.states.json +73 -8
  51. package/modules/hall-ui/public/market-watch-item.html +1 -1
  52. package/modules/hall-ui/public/market-watch-rules.html +1 -1
  53. package/modules/hall-ui/public/market-watch-settings.js +6 -1
  54. package/modules/hall-ui/public/market-watch.html +141 -54
  55. package/modules/hall-ui/public/market-watch.js +54 -0
  56. package/modules/hall-ui/public/market-watch.states.json +2 -1
  57. package/modules/hall-ui/public/modules.html +1 -1
  58. package/modules/hall-ui/public/my-agents.html +1 -1
  59. package/modules/hall-ui/public/primer.html +1 -1
  60. package/modules/hall-ui/public/profile.html +1 -1
  61. package/modules/hall-ui/public/project-settings.html +1 -1
  62. package/modules/hall-ui/public/ranks.html +1 -1
  63. package/modules/hall-ui/public/roadmap.html +1 -1
  64. package/modules/hall-ui/public/roster.html +1 -1
  65. package/modules/hall-ui/public/sessions.html +1 -1
  66. package/modules/hall-ui/public/settings.html +1 -1
  67. package/modules/hall-ui/public/shell.js +2 -3
  68. package/modules/hall-ui/public/street.html +1 -1
  69. package/modules/hall-ui/public/studio.html +9 -1
  70. package/modules/hall-ui/public/style.css +74 -27
  71. package/modules/hall-ui/public/task.html +1 -1
  72. package/modules/hall-ui/public/thinking.html +1 -1
  73. package/modules/hall-ui/public/tweak-editor.html +1 -1
  74. package/modules/hall-ui/public/watch.html +1 -1
  75. package/modules/hall-ui/public/work.html +1 -1
  76. package/modules/hall-ui/records/home-city.md +189 -0
  77. package/modules/hall-ui/records/loader.md +1 -1
  78. package/modules/hall-ui/records/market-watch-settings.md +16 -3
  79. package/modules/hall-ui/records/market-watch.md +3 -1
  80. package/modules/lifecycle/home-city.js +388 -0
  81. package/modules/lifecycle/home-gallery.js +320 -0
  82. package/modules/lifecycle/migrations/lifecycle_020_work_appreciations.sql +36 -0
  83. package/modules/lifecycle/module.json +2 -0
  84. package/modules/lifecycle/routes/home-city.js +29 -0
  85. package/modules/lifecycle/routes/home-gallery.js +37 -0
  86. package/modules/market-watch/routes/settings.js +1 -1
  87. package/package-lock.json +2 -2
  88. package/package.json +1 -1
  89. package/release-notes.json +38 -0
  90. package/scripts/bongos/leak-scan-allowlist.js +8 -0
  91. package/scripts/hall-preview/README.md +1 -0
  92. package/scripts/hall-preview/server.js +10 -0
  93. package/src/bongos/serve-internal.js +17 -3
  94. package/src/module-api.js +1 -1
  95. package/tests/claim_from_task_and_home.mjs +8 -43
  96. package/tests/hall_board_world.mjs +10 -12
  97. package/tests/hall_builders_page_pass.mjs +18 -27
  98. package/tests/hall_home_ships_bounded.mjs +4 -3
  99. package/tests/hall_loading.mjs +1 -1
  100. package/tests/hall_nav.mjs +11 -4
  101. package/tests/hall_page_gate_map.mjs +7 -4
  102. package/tests/home_bounded_reads.mjs +16 -31
  103. package/tests/home_city.mjs +580 -0
  104. package/tests/home_city_widget.mjs +260 -0
  105. package/tests/home_gallery.mjs +255 -0
  106. package/tests/home_gallery_widget.mjs +220 -0
  107. package/tests/home_studio.mjs +169 -0
  108. package/tests/home_studio_widget.mjs +157 -0
  109. package/tests/leaderboard_roles.mjs +3 -2
  110. package/tests/market_watch_pages.mjs +162 -0
  111. package/tests/nav_permission_atoms.mjs +2 -2
  112. package/modules/hall-ui/public/market-watch-settings.html +0 -115
  113. package/modules/hall-ui/public/market-watch-settings.states.json +0 -14
@@ -126,7 +126,6 @@
126
126
  settings: '<circle cx="9" cy="9" r="2.5"/><path d="M9 2.5v2m0 9v2M2.5 9h2m9 0h2M4.4 4.4l1.4 1.4m6.4 6.4 1.4 1.4m0-9.2-1.4 1.4M5.8 12.2l-1.4 1.4"/>',
127
127
  deploy: '<path d="M9 12V3M5.5 6.5 9 3l3.5 3.5M3 12.5v2a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1v-2"/>',
128
128
  fleet: '<path d="M4 2.5h10v13l-1.7-1-1.6 1-1.7-1-1.7 1-1.6-1-1.7 1v-13Z"/><path d="M6.5 6h5M6.5 9h5M6.5 12h3"/>',
129
- fuel: '<path d="M3 13a6 6 0 1 1 12 0"/><path d="M9 13l3-4"/>',
130
129
  permissions: '<circle cx="6" cy="12" r="3.5"/><path d="M8.5 9.5 15 3M12.5 5.5l2 2M10.5 7.5l1.5 1.5"/>',
131
130
  // The governor city: a pediment over columns, the Governing mode's own glyph.
132
131
  city: '<path d="M2.5 7 9 3l6.5 4M4 7.5v6.5M7 7.5v6.5M11 7.5v6.5M14 7.5v6.5M2.5 15.5h13"/>',
@@ -389,8 +388,8 @@
389
388
  // of `provisioning.fleet.manage`, the atom its page and its one read check (the
390
389
  // Deploy precedent above); dropped where the provisioning module is not enabled.
391
390
  { id: 'fleet', label: 'Fleet costs', icon: 'fleet', href: '/fleet', gate: 'government', module: 'provisioning', position: true },
392
- // task 1004938: owner-only Market Watch settings; 'archon' mirrors its routes (cosmetic, ADR 0016).
393
- { id: 'market-watch-settings', label: 'Market Watch', icon: 'fuel', href: '/market-watch-settings', gate: 'archon', module: 'market-watch', position: true },
391
+ // task 1005045: the owner's Market Watch settings (task 1004938) are an owner-only tab on
392
+ // /market-watch now, so the sidebar says "Market Watch" once (owner decision 2026-11-03).
394
393
  // BV1.R113: the roles-and-permissions tab (ADR 0151). The one genuinely
395
394
  // Archon-only item the 'government' gate comment anticipated — cosmetic
396
395
  // only. The wall is the `government.manage` atom checked on each of the
@@ -231,7 +231,7 @@
231
231
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
232
232
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
233
233
  <script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
234
- <script src="/builders/shell.js?v=2026-11-03-update-pill"></script>
234
+ <script src="/builders/shell.js?v=2026-11-04-one-market-watch"></script>
235
235
  <script src="/builders/palette.js" defer></script>
236
236
  <script src="/builders/gov-living.js?v=2026-10-09-positions1"></script>
237
237
  <script src="/builders/gov-feeds.js?v=2026-10-09-living3"></script>
@@ -15,6 +15,8 @@
15
15
  <link rel="stylesheet" href="/builders/style.css?v=2026-07-02-shell1">
16
16
  <link rel="stylesheet" href="/builders/studio.css?v=2026-10-09-day">
17
17
  <link rel="stylesheet" href="/builders/approval-queue.css?v=2026-09-29-aqfix">
18
+ <link rel="stylesheet" href="/builders/home-gallery.css?v=2026-11-04-studio">
19
+ <link rel="stylesheet" href="/builders/home-studio.css?v=2026-11-04-studio">
18
20
  </head>
19
21
  <!-- THE STUDIO HOME (task 1003971 / BV2.TW16, goal 1000095; ADR 0341 D2, D5,
20
22
  D8 and D11). docs/design/mocks/tweak-mode/Main.dc.html is the master design:
@@ -208,6 +210,10 @@
208
210
  </div>
209
211
  </div>
210
212
  </main>
213
+ <!-- task 1005061: the studio's five shelves (home-studio.js), under the room, in the
214
+ gallery's colours: the easel, pages waiting, words to tune, pinned works and
215
+ your works. -->
216
+ <section class="hs-page" id="studio-shelves" aria-labelledby="hs-h"></section>
211
217
 
212
218
  <footer class="app-foot" id="app-foot"></footer>
213
219
  </div>
@@ -219,7 +225,7 @@
219
225
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
220
226
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
221
227
  <script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
222
- <script src="/builders/shell.js?v=2026-11-03-update-pill"></script>
228
+ <script src="/builders/shell.js?v=2026-11-04-one-market-watch"></script>
223
229
  <script src="/builders/palette.js" defer></script>
224
230
  <!-- The kit, for its ONE renderer: the full-size ship-time visual figure
225
231
  (task 1003829), which the older reviews still show. -->
@@ -236,5 +242,7 @@
236
242
  <script src="/builders/studio-lib.js?v=2026-10-09-day"></script>
237
243
  <script src="/builders/ai-studio-lib.js?v=2026-10-29-ais1"></script>
238
244
  <script src="/builders/studio.js?v=2026-10-09-day"></script>
245
+ <script src="/builders/home-gallery.js?v=2026-11-04-studio"></script>
246
+ <script src="/builders/home-studio.js?v=2026-11-04-studio"></script>
239
247
  </body>
240
248
  </html>
@@ -3339,8 +3339,53 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
3339
3339
 
3340
3340
  /* ---------- landing (signed-out) ---------- */
3341
3341
 
3342
- .landing { max-width: var(--measure); }
3343
- .landing__lede { font-size: 14px; color: var(--ink-soft); }
3342
+ /* The signed-out page is a sign-in screen, not the hall: html[data-door="out"]
3343
+ (hall-render.js markSignedOut) drops the rail, the top bar, the foot and the
3344
+ page head, and centres one card in the window. The h1 stays in the markup for
3345
+ screen readers (one-header-main-h1), visually hidden. */
3346
+ html[data-door="out"] .app-sidebar,
3347
+ html[data-door="out"] .app-scrim,
3348
+ html[data-door="out"] .app-topbar,
3349
+ html[data-door="out"] .app-foot,
3350
+ html[data-door="out"] #welcome-reopen { display: none; }
3351
+ html[data-door="out"] .app-body { margin-left: 0; }
3352
+ /* body in the selector outranks Home's own body[data-page="home"] .page-head--hall. */
3353
+ html[data-door="out"] body .page-head {
3354
+ position: absolute;
3355
+ width: 1px; height: 1px;
3356
+ overflow: hidden;
3357
+ clip: rect(0 0 0 0);
3358
+ margin: 0; padding: 0;
3359
+ }
3360
+ html[data-door="out"] .app-content {
3361
+ min-height: 100vh;
3362
+ display: flex;
3363
+ align-items: center;
3364
+ justify-content: center;
3365
+ padding: 40px 16px;
3366
+ }
3367
+ html[data-door="out"] #hall-main { width: 100%; }
3368
+
3369
+ .landing {
3370
+ width: 100%;
3371
+ max-width: 400px;
3372
+ margin: 0 auto;
3373
+ padding: 40px 32px 28px;
3374
+ border-radius: var(--radius);
3375
+ background: var(--bg-card);
3376
+ text-align: center;
3377
+ }
3378
+ .landing__logo { display: block; width: 56px; height: 56px; margin: 0 auto 18px; overflow: visible; }
3379
+ .landing__ring { stroke: var(--ink); }
3380
+ .landing__planet { fill: var(--ink); }
3381
+ .landing__title {
3382
+ margin: 0 0 28px;
3383
+ font-family: var(--font-display);
3384
+ font-size: 26px;
3385
+ font-weight: 300;
3386
+ letter-spacing: -0.025em;
3387
+ color: var(--ink);
3388
+ }
3344
3389
  /* A link inside landing prose is still a control: 3px of vertical padding is
3345
3390
  what clears the 24px floor in a line that has no rhythm of its own
3346
3391
  (DESIGN.md §The footer applies the same rule to its links). */
@@ -3355,6 +3400,7 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
3355
3400
  display: inline-flex;
3356
3401
  align-items: center;
3357
3402
  justify-content: center;
3403
+ gap: 10px;
3358
3404
  min-height: 46px;
3359
3405
  padding: 0 22px;
3360
3406
  border-radius: var(--radius-pill);
@@ -3367,16 +3413,33 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
3367
3413
  cursor: pointer;
3368
3414
  }
3369
3415
  .landing__btn:hover { background: var(--accent-lift); text-decoration: none; color: var(--accent-on); }
3416
+ .landing__btn--block { display: flex; width: 100%; }
3417
+ .landing__gh { flex-shrink: 0; }
3418
+ .landing__btn--quiet {
3419
+ background: transparent;
3420
+ color: var(--ink);
3421
+ box-shadow: inset 0 0 0 1px var(--border-strong);
3422
+ }
3423
+ .landing__btn--quiet:hover { background: var(--surface-2); color: var(--ink); }
3370
3424
  .landing__note { font-size: 12.5px; color: var(--ink-faint); }
3371
3425
  .landing__error { color: var(--danger); }
3372
3426
  .landing__error-h { color: var(--danger); margin: 0 0 4px; font-size: 14px; }
3373
- .landing__request {
3374
- border: 0;
3375
- border-radius: var(--radius);
3376
- background: var(--surface-2);
3377
- padding: 18px 20px;
3378
- margin: 16px 0;
3427
+ .landing__door { margin: 18px 0 0; font-size: 13px; color: var(--ink-soft); }
3428
+ /* apply mode: the request form folds under the sign-in button. */
3429
+ .landing__disclosure { margin-top: 18px; }
3430
+ .landing__summary {
3431
+ display: inline-flex;
3432
+ align-items: center;
3433
+ min-height: 24px;
3434
+ list-style: none;
3435
+ cursor: pointer;
3436
+ font-size: 13px;
3437
+ color: var(--ink-soft);
3379
3438
  }
3439
+ .landing__summary::-webkit-details-marker { display: none; }
3440
+ .landing__summary:hover { color: var(--ink); }
3441
+ .landing__disclosure[open] .landing__summary { color: var(--ink); }
3442
+ .landing__request { margin-top: 14px; text-align: left; }
3380
3443
  .landing__request-h { margin: 0 0 6px; font-family: var(--font-display); font-size: 18px; font-weight: 300; letter-spacing: -0.025em; }
3381
3444
  .landing__request-lede { margin: 0 0 12px; font-size: 13px; color: var(--ink-soft); }
3382
3445
  .landing__request-lede--soft { color: var(--ink-faint); }
@@ -3386,28 +3449,12 @@ main [id] { scroll-margin-top: calc(var(--topbar-h) + 16px); }
3386
3449
  .landing__req-mark { color: var(--danger); }
3387
3450
  .landing__opt { color: var(--ink-faint); font-weight: 400; }
3388
3451
  .landing__form-hint { font-size: 12.5px; color: var(--ink-faint); margin: 0; }
3389
- .landing__btn--request { align-self: flex-start; }
3390
3452
  .landing__request-status { font-size: 13px; margin: 0; color: var(--ok); }
3391
3453
  .landing__request-status[data-kind="err"] { color: var(--danger); }
3392
- /* The returning builder's door, rendered only on the `apply` landing (task
3393
- 1002851). Same panel as the request block and the same button geometry, so
3394
- signing in reads as a real control rather than a footnote — but a quiet
3395
- fill, because the request path is what most of this page's traffic needs. */
3396
- .landing__returning {
3397
- border: 0;
3398
- border-radius: var(--radius);
3399
- background: var(--surface-2);
3400
- padding: 18px 20px;
3401
- margin: 16px 0;
3402
- }
3403
- .landing__returning .landing__cta { margin: 0; }
3404
- .landing__btn--quiet {
3405
- background: transparent;
3406
- color: var(--ink);
3407
- box-shadow: inset 0 0 0 1px var(--border-strong);
3454
+ .landing__signin-note { margin: 22px 0 0; font-size: 12px; color: var(--ink-faint); }
3455
+ @media (max-width: 480px) {
3456
+ .landing { padding: 28px 20px 22px; }
3408
3457
  }
3409
- .landing__btn--quiet:hover { background: var(--surface-2); color: var(--ink); }
3410
- .landing__signin-note { font-size: 13px; color: var(--ink-soft); }
3411
3458
 
3412
3459
  /* ---------- goals ---------- */
3413
3460
 
@@ -59,7 +59,7 @@
59
59
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
60
60
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
61
61
  <script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
62
- <script src="/builders/shell.js?v=2026-11-03-update-pill"></script>
62
+ <script src="/builders/shell.js?v=2026-11-04-one-market-watch"></script>
63
63
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
64
64
  <script src="/builders/palette.js" defer></script>
65
65
  <!-- task-detail.js still owns the #/idea/N and #/blocker/N deep-link overlay
@@ -141,7 +141,7 @@
141
141
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
142
142
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
143
143
  <script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
144
- <script src="/builders/shell.js?v=2026-11-03-update-pill"></script>
144
+ <script src="/builders/shell.js?v=2026-11-04-one-market-watch"></script>
145
145
  <script src="/builders/palette.js" defer></script>
146
146
 
147
147
  <script src="/builders/idea-objects.js?v=2026-09-27-split"></script>
@@ -145,7 +145,7 @@
145
145
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
146
146
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
147
147
  <script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
148
- <script src="/builders/shell.js?v=2026-11-03-update-pill"></script>
148
+ <script src="/builders/shell.js?v=2026-11-04-one-market-watch"></script>
149
149
  <script src="/builders/palette.js" defer></script>
150
150
  <script src="/builders/brand-holes.js?v=2026-09-29-aqfix"></script>
151
151
  <script src="/builders/tweak-editor-lib.js?v=2026-09-29-tw27"></script>
@@ -168,7 +168,7 @@
168
168
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
169
169
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
170
170
  <script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
171
- <script src="/builders/shell.js?v=2026-11-03-update-pill"></script>
171
+ <script src="/builders/shell.js?v=2026-11-04-one-market-watch"></script>
172
172
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
173
173
  <script src="/builders/palette.js" defer></script>
174
174
  <!-- shared component kit (window.OTBKit) — tabs, ledger, pager (task 2166). -->
@@ -174,7 +174,7 @@
174
174
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
175
175
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
176
176
  <script src="/builders/craft-mode.js?v=2026-10-30-market-watch"></script>
177
- <script src="/builders/shell.js?v=2026-11-03-update-pill"></script>
177
+ <script src="/builders/shell.js?v=2026-11-04-one-market-watch"></script>
178
178
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
179
179
  <script src="/builders/palette.js" defer></script>
180
180
  <!-- task 1004727: the ONE karma vote control every task/idea list renders -->
@@ -0,0 +1,189 @@
1
+ # The project city — Home's body becomes one scene: towers, a ladder of builders, a time slider (task 1005054)
2
+
3
+ The owner's Home redesign of 2026-11-03, agreed over fourteen mock rounds; the approved mock is
4
+ [`docs/design/mocks/hall/home/v14.html`](../../../docs/design/mocks/hall/home/v14.html) (v2 to v13 beside it
5
+ are the rounds, each with its own header comment on what changed and why). The brief in the owner's words:
6
+ "I don't want to reach, I want to see and feel", and the UI "subtle and free from overuse of text".
7
+
8
+ **What people see** (agreed before drawing, round 6): who is involved, the speed of builds as a time slider,
9
+ what is waiting on them, what is being built now, then spend, health and just shipped as small things. Not on
10
+ Home: how close the version is to done, what is ready to go live, work to pick up. The same page for everyone.
11
+
12
+ - **The scene** (`home-city-draw.js`, pure; the city's own iso palette from `city-draw.js`): one tower per
13
+ working area (the open, non-maintenance goals of the version being built), as tall as what has shipped
14
+ there; artist and ui work clads it in glass from the ground up; one hairline per floor. The sites worked in
15
+ the selected week carry a crane lifting a slab, scaffolding round the floor going up, that floor lit, and the
16
+ face of who built there (a robot face when an Autobongos runner is working it). That week's ideas are lights
17
+ in the sky, the week before's dimmer; one that became work drops a dotted line to its tower. A salmon dot
18
+ with a count sits on each tower where something waits on the viewer, on the latest week only.
19
+ - **The ladder** beside the city: a small face and one thin line per builder, length = their week's total,
20
+ split into art · build · ideas · govern, each piece marked with the hall's own craft icon (`craft-mode.js`
21
+ `iconHtml`, never a second copy) and its count. Ranked by the total, the top seven, and the viewer appended
22
+ when they fall below. No rank numbers, no names, no tabs: the words are on hover. One colour, not four: four
23
+ craft colours from this pack fail the dataviz validator's normal-vision floor (v11's note).
24
+ - **The slider** under the scene, with play: every part redraws for the week it is on. Play steps a week at a
25
+ time on a timer and stops on now — state, never animation, so no motion lives in JavaScript. The ladder's
26
+ rows slide and a crane's slab lifts in CSS; the hall's reduced-motion rule stops both.
27
+ - **Placement.** The widget is `home-city` in the `home-stats` zone (budget 1), which the stats strip held.
28
+
29
+ **Left Home:** the stats strip and version tab (`home-stats`, and the `/public/progress` read that only fed the
30
+ tab), the Goals card (`goals.js` is no longer loaded by `index.html`), and Your work — Next up with its claim
31
+ button and `GET /tasks/claimable?limit=5`, and the Recently shipped table (`home-recent`). `claim-action.js` left
32
+ `index.html` with the claim button. **Kept:** the conditional welcome, setup, genesis and founding banners, the
33
+ Standing chip (its Shipped figure now comes straight from the ships payload, `shipState`, not a DOM tile), and
34
+ the Needs-your-attention inbox below the city, because it holds actions with no other home (join requests,
35
+ invitations, triage). The `/me/recent-ships?limit=5` read stays: it feeds the chip and Accomplishments.
36
+
37
+ **The data** is ONE bounded read, `GET /home/city?weeks=10` (`modules/lifecycle/home-city.js`, any signed-in
38
+ builder): counts grouped by week in SQL, so the payload grows with areas, builders and weeks, never with the
39
+ corpus; `tests/home_city.mjs` proves every query is bounded and selects no prose. Four things it is honest about:
40
+
41
+ - **Art** is economy's credits-by-craft rule: `artist` and `ui` disciplines. Page tweaks file under each version's
42
+ artist-review goal, so that tower is mostly glass.
43
+ - **An agent is a site fact, never a person.** Autobongos runs under its builder's account; a site whose task an
44
+ `autonomy_runner_heartbeat` row is working (seen in the last 15 minutes) is drawn with the robot face and named
45
+ "<builder>'s agent". `people[].agent` is always false from the server.
46
+ - **"Waits on you" is the docket's own routing (task 1005056):** the government port's `yoursByGoal(viewer)`
47
+ routes the docket's goal-shaped matters (blockers, criteria awaiting sign-off, goal join requests) with
48
+ `modules/government/routing.js` and counts, per area, those routed to the viewer — so a seated Lead, a board
49
+ member or an access holder sees their own dots, not only an Archon. With government off, an older government
50
+ without the method, or seats it could not read, the server falls back to open blockers whose stored ask waits
51
+ on `owner` (or carry none), shown only to an Archon.
52
+ - Government and autonomy are optional modules: their tables are probed with `to_regclass` first and left out
53
+ when absent, so a project with either switched off still gets its city.
54
+
55
+ **Verifying:** the hall-preview harness serves `fixtures/home__city.json` (hand-shaped from the approved mock, ids
56
+ from the other fixtures); `tests/home_city_widget.mjs` runs the real widget in a browser (one read, the slider
57
+ redraws, play stops on now, a refused read leaves no empty plate, no sideways scroll at 390); the kit stub does
58
+ not serve the read, so `index.states.json` ignores it and its renders show the city hidden, as for a visitor.
59
+
60
+ ## v16 — one city for every craft (task 1005058)
61
+
62
+ The owner's round of 2026-11-04 ([`v16-building.html`](../../../docs/design/mocks/hall/home/v16-building.html),
63
+ with `v16-city.js` and `v16-frame.js`; the v15 and v16 rounds for the other crafts sit beside it). Step 1 of 4:
64
+ the builder's Home. Steps 2–4 (the ideator's sky, the artist's gallery, the studio) are tasks 1005059–1005061.
65
+
66
+ - **The civic core is the Governor City's own.** The nine institutions stand on the plaza at the centre, drawn by
67
+ `city-draw.js` (`GovCity.isoInstitution` at `GovCity.CIVIC_SLOTS`, its `isoTheme` palette), which Home now loads
68
+ ahead of `home-city-draw.js`; the drawing takes it as `opts.gov` and is never handed a copy. Without it the city
69
+ still draws, minus its core.
70
+ - **The working areas stand on a ring of sixteen plots** (`RING`) around the plaza, tallest first into the plots
71
+ farthest back (smallest x + y), so no tower hides the core; the art museum and its garden (after the Cleveland
72
+ Museum of Art: the marble block and portico, the atrium between granite wings, the Fine Arts Garden and lagoon)
73
+ stand on the front edge. A test holds every plot clear of the plaza, the museum and each other.
74
+ - **Districts are doors, one hover each.** The core is one link to the street (`GovCity.STREET_HREF`); the museum
75
+ and the band of stars are craft doors (`data-craft-door`, `OTBCraftMode.choose`); a building links to its goal
76
+ (`/goals#/goal/N`). On the builder's Home the core and the museum are faded (`.hc-quiet`) so the new buildings
77
+ lead; `opts.focus` keeps a craft's own district in colour for the Homes still to come.
78
+ - **The ideas are a thin band of stars high above the city**, apart from it — a hint at the sky, not part of it.
79
+ - **Time is live.** The slider opens at **Live** (a pulsing dot) and takes any value (`step="any"`); the drawing
80
+ accepts a fractional week (`doneAt` adds that part of the next week), so moving the slider or the quiet player
81
+ (rewind, play/pause, fast forward) **glides** the city through every week in between — the owner asked for a
82
+ rewind, not a jump. A date pill rides the handle; *Back to live* returns.
83
+ - **The one motion driven from script.** The glide is a `requestAnimationFrame` loop that redraws the city at a
84
+ fractional week — a deliberate exception to the hall's "motion stays CSS" rule, at the owner's request. It is
85
+ gated on `prefers-reduced-motion` before it starts: with reduced motion nothing animates and every control jumps
86
+ straight to its destination (`tests/home_city_widget.mjs` pins both).
87
+
88
+ ## v16 step 2 — the ideator's sky (task 1005059)
89
+
90
+ The mock is [`v16-ideating.html`](../../../docs/design/mocks/hall/home/v16-ideating.html). While the craft is
91
+ **Ideating** (`OTBCraftMode.current()`, redrawn on `otb:craft`) the same widget, from the same one read, draws
92
+ `home-city-draw.js` `skySvg` instead of the city. Every other craft keeps the builder's city untouched.
93
+
94
+ - **The skyline is the city.** `skylineOf` turns every building `citySvg` stands into a silhouette at the
95
+ same screen x (a box from (x0,y0) to (x1,y1) spans `P(x0,y1)` to `P(x1,y0)` in the city's own frame) and
96
+ the same height: each tower is its plinth plus what it has built by the slider's week, a civic building is
97
+ `GovCity.ROOF` at the core's scale, and the museum is its marble block and atrium. A test holds each
98
+ silhouette to its tower's drawn faces.
99
+ - **Nearer covers farther, outlines included.** The silhouettes are drawn back to front, each fill followed
100
+ by its own outline, so a nearer building hides the outline behind it. Over them lies one hit link per
101
+ silhouette, also back to front, so the nearest building takes the pointer. Hovering or focusing any link
102
+ in a group outlines the whole group (CSS `:has()` in `home-city.css`; no script). Each group is one door
103
+ with one keyboard stop: **Building** opens `/goals`, **Government** opens `GovCity.STREET_HREF`, and
104
+ **Art** switches to Artistry (`data-craft-door`). A low building still offers a 30-unit band to point at.
105
+ - **The ideas.** An idea's area is the goal of the work it became, else the goal its filer aimed it at
106
+ (`suggested_goal_id`) when that goal is an area of this version. Each area with ideas gets a constellation,
107
+ and the rest go in the *Not placed yet* field. Star size is net votes. A salmon ring, only at Live, marks a
108
+ new idea (these two weeks) that is open, in no area, not the viewer's, and not yet voted on by them. In the
109
+ week an idea became work it falls into its tower; after that it lights a window there. The moon is the
110
+ version, its phase what the areas have shipped over every task under them (`version.tasks`).
111
+ - **The ladder** ranks the week's ideators: ideas filed, idea votes cast, and ideas of theirs that became work.
112
+ - **The read stays one and bounded.** `GET /home/city` adds these fields to the ideas list it already sent
113
+ (still newest first, at most 120 rows), plus idea votes per builder per week and a per-area task count.
114
+ The `ideas_votes` table is probed first, so a project with the ideas module off answers without votes.
115
+
116
+ ## The gallery — the artist's Home (task 1005060)
117
+
118
+ Step 3 of 4, the owner's round of 2026-11-04 ([`v16-artistry.html`](../../../docs/design/mocks/hall/home/v16-artistry.html), v16b):
119
+ "not about quality but about appreciation". In Artistry, Home is a seat on a bench in the city's art museum, facing a
120
+ quiet wall; the museum's `data-craft-door="artistry"` leads here.
121
+
122
+ - **One section, two Homes.** It is not a hall widget of its own (Home's stats zone holds one): `home-city.js`
123
+ attaches `home-gallery.js` beside the city and, on `otb:craft`, shows the gallery in Artistry (`.hc--gallery`) and
124
+ the city otherwise. The builder's Home is unchanged and never asks for the wall.
125
+ - **What a work is.** A shipped `artist`/`ui` task (or a page tweak round) that carries a picture: a round hangs its
126
+ own desktop AFTER renders (light and dark), any other ship its ship-time visual. The artist is `shipped_by`, the
127
+ line on the label its value summary. A picture whose file is gone is not hung. Read by `GET /home/gallery`
128
+ (`modules/lifecycle/home-gallery.js`, at most 60 works, Most popular or Latest ordered in SQL); a security-sensitive
129
+ task, or one under a private goal the viewer cannot read, never hangs.
130
+ - **Appreciation, never a grade.** One heart per builder per work (`lifecycle_work_appreciations`, lifecycle_020,
131
+ primary key `(task_id, builder_id)`), given and taken back with `PUT /home/gallery/:id/heart { on }`. The count
132
+ shows only in the credit line and orders Most popular; no rank or leaderboard reads it. The heart never changes size.
133
+ - **The label is the museum's.** Small, at the work's foot; a click opens it closer (`transform`, so the wall does not
134
+ re-flow) with the value summary and the credit line. The signature (a first name, an initial and the year, in a
135
+ handwriting stack the hall already has on the machine, no web font) sits on the wall under it, beside the heart.
136
+ - **Full screen** (the button or F) is the art, a caption, the signature and the heart; Escape leaves. Where the
137
+ browser refuses the Fullscreen API it falls back to a fixed layer.
138
+ - **Wayfinding:** "The full gallery" hangs every work at once, salon-style (a click sits you in front of one);
139
+ "Your studio" goes to `/studio` until step 4 (task 1005061) builds the studio behind the gallery.
140
+ - **Colour** is the hall's tokens mixed; the frame and shadows are black with alpha. Motion is CSS only.
141
+ - Pinned in `tests/home_gallery.mjs` (the read, the heart, the label words) and `tests/home_gallery_widget.mjs` (the
142
+ real widget: the walk, the zoom, the heart, Latest, full screen, the salon, phone width, the craft switch). The
143
+ harness answers with `scripts/hall-preview/fixtures/home__gallery.json` (sample names, the project's real works);
144
+ `HALL_PREVIEW_VISUALS=<dir>` serves real renders.
145
+
146
+ ## The studio — behind the gallery (task 1005061)
147
+
148
+ Step 4 of 4 ([`v16-studio.html`](../../../docs/design/mocks/hall/home/v16-studio.html)): "then you are in your studio,
149
+ where you are at peace and can think best." The studio is the hall's **`/studio`** page: the sidebar's Studio and the
150
+ gallery's **Your studio** door both lead there. Its five shelves (`home-studio.js`, mounted into
151
+ `#studio-shelves`) sit under the page's illustrated room, which keeps its tally, the tweak flow, the approvals and the
152
+ AI door; the shelves wear the gallery's wall, lit from a north window: "Quiet. Nothing here is due." No ranks, no
153
+ leaderboard.
154
+
155
+ - **On your easel** — the page round you hold (the Tweak/CopyWrite Flow's `resume`), with "Pick up where you left off"
156
+ into the tweak editor; with none, "Nothing on your easel" and the page the flow would recommend next. The picture is
157
+ that page's newest work on the wall (`GET /home/studio/works?page=`), else a quiet empty frame.
158
+ - **Waiting for new inspiration** — pages whose words changed since an artist last designed them (the flow's `changed`
159
+ tier, drift from the page readings), most changed lines first, four shown and the rest counted.
160
+ - **Words to tune** — the three newest open copy-desk flags, as text, linking to the copy desk.
161
+ - **Pinned from the gallery** — the works you hearted, newest heart first (a heart on the bench pins a work here).
162
+ - **Your works in the collection** — the works you signed, most appreciated first, with their heart counts.
163
+ - **Back into the gallery:** "The bench" is `/`, "The full gallery" `/?gallery=all`, and each work `/?work=<id>`, which
164
+ the gallery reads once on arrival (`landing`) to open its salon or sit you in front of that work, then puts the
165
+ address back.
166
+ - **Two bounded reads:** `GET /copy-desk/studio` (`modules/copy-desk/routes/copy-desk-studio.js`, composed by
167
+ `page-status.js` `composeNext`, so it cannot disagree with the room's own tweak flow) and `GET /home/studio/works`
168
+ (`modules/lifecycle/home-gallery.js`, the wall's own WHERE, six a shelf). Without the copy desk its shelves say so and
169
+ the works still hang. A link from a shelf row goes only to the tweak editor or the copy desk.
170
+ - **Not built, said rather than invented:** the mock's "The style library →" (the style library is files in
171
+ `modules/ui-design/styles/`, with no hall page to link) and the easel's line about the owner's notes on a round (notes
172
+ on a page round are stored nowhere the studio can read).
173
+ - **Open for the owner:** whether the shelves should one day replace the illustrated room above them (its Resume and the
174
+ easel now say the same thing twice).
175
+ - Pinned in `tests/home_studio.mjs` and `tests/home_studio_widget.mjs` (real browser, empty states included); harness
176
+ fixtures `copy-desk__studio.json` and `home__studio__works.json`.
177
+
178
+ ## Private areas
179
+
180
+ A private goal the viewer is neither a member of nor an Archon over still stands as a tower (its counts are structure), but the server sends no title for it or for the ideas tied to it; the drawing labels them "A private area" and "A private idea" (ADR 0112, as the goal map and the sky apply it). Pinned in `tests/home_city.mjs`.
181
+
182
+ ## Sign-off
183
+
184
+ The owner chose v14 from fourteen mock rounds, approved the before and after review sheet (1280 dark and light, 390 dark) on 2026-11-02, and said "Yes, ship it".
185
+
186
+ **Step 2, the ideator's sky (task 1005059).** The owner approved the four-step v16 plan on 2026-11-04 and asked
187
+ for each step to land; the step's shots (Ideating at 1440 and 390, dark and light; the three hovers; the
188
+ builder's Home unchanged) went to the owner after landing, and the visual review holds the deploy, never the
189
+ land (ADR 0241). Their OK of those shots is recorded here when given — not before.
@@ -15,7 +15,7 @@ shapes breathing 0.4 to 1 and back over 0.8s, in the place the content will land
15
15
  rewrites IN PLACE (atlas's caption, sessions' status line, the goal dependency ledes, the profile's
16
16
  activity placeholder) keeps its plain words, because the class would stay on the finished sentence.
17
17
  - **Pages that are blank while they wait get a page loader that puts itself away.** The sealed/body
18
- pages (board-room, deploy, fleet, gate, government, market-watch-settings, project-settings,
18
+ pages (board-room, deploy, fleet, gate, government, project-settings,
19
19
  sessions) open their `<main>` on `.hall-loading--wait`, which shows only while every section after
20
20
  it is `[hidden]`. Home and Watch, whose zones and panes are always present, use
21
21
  `.hall-loading--zones`: it shows while no showing zone has a showing child. Both are `:has()`
@@ -1,11 +1,24 @@
1
- # Market Watch settings, at /market-watch-settings (task 1004938)
1
+ # Market Watch settings, the owner's Settings tab on /market-watch (task 1004938; a tab since task 1005045)
2
+
3
+ **Since task 1005045 (owner decision 2026-11-03, idea 1001310) this is a tab, not a page.** The sidebar showed "Market Watch" twice — the page and these settings — so the settings page is gone and its markup is the `#mw-panel-settings` panel in `market-watch.html`. What that move settled:
4
+
5
+ - **Only the owner gets the strip.** `market-watch.js` adopts the shell's one `/me` read (`window.__hallReads`, no second request); for an archon it builds two kit tabs (`watch`, `settings`, `hash: true`) and calls `OTBMarketWatchSettings.load()`. Anyone else gets no tab strip at all, and their page never asks for the settings. An unreadable `/me` is not an owner. Cosmetic only: the four routes below are still the wall (ADR 0016).
6
+ - **`market-watch-settings.js` no longer boots itself** — it exports `load` and waits to be called. `market-watch-settings.css` rides along on the page.
7
+ - **The old URL lands on the tab:** `/market-watch-settings` (apex and subdomain, with or without `.html`) 302s to `/market-watch#settings` in `serve-internal.js` (`RETIRED_MW_SETTINGS_RE`), before any page gate. The tab ids are the contract.
8
+ - **Where the module is off there is no tab:** the page shows its quiet off line and asks nothing, so there is nothing to set. A watch that fails to READ keeps the tab: the settings are their own read, and a broken watch must not lock the owner out of its switch and key.
9
+ - **The link to the rules** sits at the foot of the tab, as it does under the desk's streak.
10
+ - **The tab opens on the page loader** (`.hall-loading--wait`, records/loader.md): every section after it starts hidden, so an owner landing on `#settings` sees "Loading…" until the read draws a section, never a blank panel.
11
+ - **Governing mode lost its Market Watch entry.** The settings were in the Governing mode's list; the Market Watch page is not (`tests/craft_mode_nav.mjs` pins Governing as the shortest list), so in that mode the owner reaches the tab from another mode, the palette, or the URL.
12
+
13
+ What the page settled before the move still holds:
14
+
2
15
 
3
16
  **The owner's fuel gauge for Market Watch (goal 1000137), built to `docs/design/mocks/market-watch/settings.html`, option B.** One panel: the gauge (spend this month against the monthly AI cap, with a faint arc for what the next run will use), the on/off pill, the cap slider, the cadence chips (weekly, every 2 weeks, monthly), the strip of recent runs, and the project's Anthropic key. Five things it settled:
4
17
 
5
- - **The routes are the wall, not the page.** `GET`/`PATCH /market-watch/settings` and `PUT`/`DELETE /market-watch/settings/key` are owner-only: the `project.settings.manage` atom, then an in-route owner-seat (Archon) check (modules/market-watch/routes/settings.js). The shell joins `SIGNEDIN_BUILDERS_PAGE_RE` and holds no data; a 403 draws the owner-only panel and a 404 (module off, so its routes are not mounted) the "turn the module on" panel. The nav item sits in Government, `archon`, `module: 'market-watch'`.
18
+ - **The routes are the wall, not the page.** `GET`/`PATCH /market-watch/settings` and `PUT`/`DELETE /market-watch/settings/key` are owner-only: the `project.settings.manage` atom, then an in-route owner-seat (Archon) check (modules/market-watch/routes/settings.js). A 403 draws the owner-only panel and a 404 (module off, so its routes are not mounted) the "turn the module on" panel.
6
19
  - **The key is write-only.** The page learns `key_set` and nothing else, not the last four. The field is emptied before the request goes out; Clear asks twice by turning into its own question.
7
20
  - **The page redraws from the server's answer.** Every write returns the whole view, so the gauge never shows a value the server did not store.
8
21
  - **The strip is the run ledger, oldest left.** A ran run shows the names it watched; a skipped one is a hatched dash, with its reason in the cell's label and the legend (`cap reached`, `switched off`, `no key`, …); the dashed tile is the next run and the two after it are empty. When the watch is off the future tiles go. The seed run never shows. At 620px and below the dates stack day over month, or nine tiles overflow at 390px.
9
22
  - **Mockup colours were not kept.** The ring, chips and tiles use the hall's `--accent`, `--accent-tint`, `--accent-text`, `--rule*` and `--ok-weak`; the mock's own fonts were dropped for the pack's.
10
23
 
11
- Fixture: `scripts/hall-preview/fixtures/market-watch__settings.json` (the mockup's month). Tests: `tests/market_watch_settings.mjs` (403s for a Metic and a Xenos on all four routes, switching off stops the next run against `run.js`'s own gate, the key never in a response).
24
+ Fixture: `scripts/hall-preview/fixtures/market-watch__settings.json` (the mockup's month). Tests: `tests/market_watch_pages.mjs` (SETTINGS TAB: who gets the tab, the panel's controls, the redirect), `tests/market_watch_settings.mjs` (403s for a Metic and a Xenos on all four routes, switching off stops the next run against `run.js`'s own gate, the key never in a response).
@@ -30,8 +30,10 @@ its known facts, and the sortable case file (found, run, type, takeaway, confide
30
30
  item, a score or an entry. The direction of a move comes from the item on the server, never the client.
31
31
  - **Pin and "read" are the viewer's own** (localStorage `mw-pins`, `mw-read`): conveniences, not the
32
32
  record. Pinned items list under the scouts.
33
- - **"sweep now" is not here.** A manual run spends the project's AI budget, so it is the settings page's
33
+ - **"sweep now" is not here.** A manual run spends the project's AI budget, so it is the settings'
34
34
  (task 1004938) to offer with the cap beside it.
35
+ - **The owner's settings are a tab here** (task 1005045): an archon viewer gets a `watch` / `settings`
36
+ strip, everyone else none. See `records/market-watch-settings.md`.
35
37
  - **Off is quiet.** Where the default-off module is not enabled the nav item is dropped, the page shows
36
38
  one line pointing at Modules, and it asks the server nothing; a 404 from unmounted routes reads the same.
37
39