@bongos/core 1.21.113 → 1.21.115

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 (265) hide show
  1. package/.bongos-core.json +608 -188
  2. package/.claude/skills/ask-for-help/SKILL.md +1 -1
  3. package/.claude/skills/bongos-feedback/SKILL.md +1 -1
  4. package/.claude/skills/builder-sequence/SKILL.md +1 -1
  5. package/.claude/skills/builder-ship/SKILL.md +1 -0
  6. package/GOVERNMENT.md +128 -11
  7. package/clients/bongos-client/README.md +1 -1
  8. package/clients/bongos-client/bongos-client.global.js +28 -0
  9. package/clients/bongos-client/index.cjs +28 -0
  10. package/clients/bongos-client/index.d.ts +45 -2
  11. package/clients/bongos-client/index.mjs +28 -0
  12. package/docs/adr/0372-an-ask-is-stored-per-docket-matter-and-the-server-refuses-slop.md +33 -0
  13. package/docs/adr/0373-an-ai-session-files-a-blocker-with-an-ask.md +31 -0
  14. package/docs/adr/0374-a-building-lead-is-a-held-position-appointed-by-a-people-matter.md +30 -0
  15. package/docs/adr/0375-who-may-build-without-a-vote-comes-from-the-form-of-government.md +38 -0
  16. package/docs/adr/0376-every-ask-is-routed-to-a-real-seat-on-the-server.md +30 -0
  17. package/docs/adr/0377-governance-is-a-held-position-read-on-me.md +24 -0
  18. package/docs/adr/0378-a-leads-build-outs-are-rows-built-at-once-or-by-a-passed-vote.md +33 -0
  19. package/docs/adr/0379-the-treasury-is-pots-per-goal-a-reserve-and-borrowing-over-real-spend.md +32 -0
  20. package/docs/adr/0380-a-strictness-preset-is-a-bundle-of-laws-switched-by-one-laws-vote.md +26 -0
  21. package/docs/adr/README.md +10 -1
  22. package/docs/api/openapi.json +989 -87
  23. package/docs/api-reference.md +18 -4
  24. package/docs/copy-inventory.md +709 -626
  25. package/docs/copy-registry.json +1673 -858
  26. package/docs/file-map.md +2 -1
  27. package/docs/module-api-changelog.md +4 -0
  28. package/docs/packs/engineer.md +2 -1
  29. package/docs/page-inventory.json +91 -6
  30. package/docs/page-readings.json +4875 -4748
  31. package/modules/builder-settings/law-locks.js +202 -0
  32. package/modules/builder-settings/routes/settings.js +66 -6
  33. package/modules/builder-settings/settings.js +7 -0
  34. package/modules/discord/ship-broadcast.js +22 -13
  35. package/modules/government/asks-db.js +54 -0
  36. package/modules/government/asks.js +269 -0
  37. package/modules/government/board-idea-reads.js +68 -0
  38. package/modules/government/board.js +21 -57
  39. package/modules/government/build-rights.js +148 -0
  40. package/modules/government/buildouts.js +160 -0
  41. package/modules/government/counts.js +81 -0
  42. package/modules/government/db.js +242 -0
  43. package/modules/government/decision-board.js +234 -8
  44. package/modules/government/decision-rules.js +2 -0
  45. package/modules/government/docket.js +114 -6
  46. package/modules/government/law-board.js +131 -0
  47. package/modules/government/laws.js +241 -0
  48. package/modules/government/leads.js +170 -0
  49. package/modules/government/migrations/government_027_laws.sql +143 -0
  50. package/modules/government/migrations/government_028_asks.sql +57 -0
  51. package/modules/government/migrations/government_029_leads.sql +135 -0
  52. package/modules/government/migrations/government_030_buildouts.sql +111 -0
  53. package/modules/government/migrations/government_031_treasury.sql +107 -0
  54. package/modules/government/module.json +2 -1
  55. package/modules/government/pollers/treasury-borrow.js +62 -0
  56. package/modules/government/positions.js +107 -0
  57. package/modules/government/presets.js +149 -0
  58. package/modules/government/routes/government.js +425 -2
  59. package/modules/government/routing.js +154 -0
  60. package/modules/government/treasury-db.js +166 -0
  61. package/modules/government/treasury.js +241 -0
  62. package/modules/hall-ui/public/atlas.html +2 -2
  63. package/modules/hall-ui/public/blockers.html +2 -2
  64. package/modules/hall-ui/public/board-room.html +2 -2
  65. package/modules/hall-ui/public/board-room.js +2 -0
  66. package/modules/hall-ui/public/city-draw.js +604 -11
  67. package/modules/hall-ui/public/city.css +157 -1
  68. package/modules/hall-ui/public/city.html +37 -7
  69. package/modules/hall-ui/public/city.js +441 -21
  70. package/modules/hall-ui/public/city.states.json +110 -5
  71. package/modules/hall-ui/public/collab.html +2 -2
  72. package/modules/hall-ui/public/commands.html +2 -2
  73. package/modules/hall-ui/public/copy-desk.html +2 -2
  74. package/modules/hall-ui/public/craft-mode.js +112 -29
  75. package/modules/hall-ui/public/deploy.html +2 -2
  76. package/modules/hall-ui/public/diagram-viewer.css +12 -0
  77. package/modules/hall-ui/public/diagram-viewer.js +4 -0
  78. package/modules/hall-ui/public/diagrams.html +2 -2
  79. package/modules/hall-ui/public/drachmae.html +2 -2
  80. package/modules/hall-ui/public/fleet.html +2 -2
  81. package/modules/hall-ui/public/gate.html +2 -2
  82. package/modules/hall-ui/public/goal-map.html +2 -2
  83. package/modules/hall-ui/public/goals.html +2 -2
  84. package/modules/hall-ui/public/gov-feeds.js +141 -0
  85. package/modules/hall-ui/public/gov-living.js +1002 -0
  86. package/modules/hall-ui/public/gov-positions.js +97 -0
  87. package/modules/hall-ui/public/government.html +2 -2
  88. package/modules/hall-ui/public/hall-render.js +3 -0
  89. package/modules/hall-ui/public/idea.html +2 -2
  90. package/modules/hall-ui/public/ideas.html +2 -2
  91. package/modules/hall-ui/public/index.html +3 -3
  92. package/modules/hall-ui/public/modules.html +2 -2
  93. package/modules/hall-ui/public/my-agents.css +334 -0
  94. package/modules/hall-ui/public/my-agents.html +72 -0
  95. package/modules/hall-ui/public/my-agents.js +603 -0
  96. package/modules/hall-ui/public/my-agents.states.json +37 -0
  97. package/modules/hall-ui/public/primer.html +2 -2
  98. package/modules/hall-ui/public/profile-connections.js +40 -28
  99. package/modules/hall-ui/public/profile.html +2 -2
  100. package/modules/hall-ui/public/project-settings.html +2 -2
  101. package/modules/hall-ui/public/ranks.html +2 -2
  102. package/modules/hall-ui/public/roadmap.html +2 -2
  103. package/modules/hall-ui/public/room.css +8 -0
  104. package/modules/hall-ui/public/roster.html +2 -2
  105. package/modules/hall-ui/public/sessions.html +2 -2
  106. package/modules/hall-ui/public/settings.html +2 -2
  107. package/modules/hall-ui/public/shell.js +116 -16
  108. package/modules/hall-ui/public/street-card.js +18 -1
  109. package/modules/hall-ui/public/street-deck.css +299 -0
  110. package/modules/hall-ui/public/street-deck.js +1145 -0
  111. package/modules/hall-ui/public/street-depth.js +712 -0
  112. package/modules/hall-ui/public/street-desk.js +5 -2
  113. package/modules/hall-ui/public/street-draw.js +109 -16
  114. package/modules/hall-ui/public/street-inside.js +137 -22
  115. package/modules/hall-ui/public/street-office.js +705 -0
  116. package/modules/hall-ui/public/street.css +161 -11
  117. package/modules/hall-ui/public/street.html +41 -11
  118. package/modules/hall-ui/public/street.js +78 -66
  119. package/modules/hall-ui/public/street.states.json +129 -21
  120. package/modules/hall-ui/public/studio.html +2 -2
  121. package/modules/hall-ui/public/style.css +5 -1
  122. package/modules/hall-ui/public/task.html +2 -2
  123. package/modules/hall-ui/public/thinking.html +2 -2
  124. package/modules/hall-ui/public/tweak-editor.html +2 -2
  125. package/modules/hall-ui/public/watch.html +2 -2
  126. package/modules/hall-ui/public/watch.js +14 -1
  127. package/modules/hall-ui/public/work.html +2 -2
  128. package/modules/hall-ui/records/living-city.md +57 -0
  129. package/modules/hall-ui/records/my-agents.md +21 -0
  130. package/modules/hall-ui/records/oversight-family.md +1 -0
  131. package/modules/hall-ui/records/profile-connections.md +10 -0
  132. package/modules/hall-ui/records/reading-rooms.md +2 -0
  133. package/modules/ideas/routes/blockers.js +92 -3
  134. package/modules/lifecycle/module.json +2 -1
  135. package/modules/lifecycle/moving.js +17 -1
  136. package/modules/lifecycle/routes/moving.js +6 -0
  137. package/modules/lifecycle/routes/project-settings.js +23 -0
  138. package/modules/onboarding/approval-broadcast.js +8 -0
  139. package/modules/onboarding/routes/access-requests.js +16 -6
  140. package/modules/platform-identity/connections.js +13 -2
  141. package/modules/platform-identity/routes/connections.js +7 -1
  142. package/modules/public-landing/public/account-private.states.json +2 -2
  143. package/modules/public-landing/public/account.html +65 -5
  144. package/modules/public-landing/public/account.states.json +3 -3
  145. package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.jpg.json +1 -1
  146. package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.webp +0 -0
  147. package/modules/public-landing/public/assets/world/r2-bongos-chrome-b.webp.json +13 -0
  148. package/modules/public-landing/public/assets/world/r2-chrome-blob-one.jpg.json +1 -1
  149. package/modules/public-landing/public/assets/world/r2-chrome-blob-one.webp +0 -0
  150. package/modules/public-landing/public/assets/world/r2-chrome-blob-one.webp.json +13 -0
  151. package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.jpg.json +1 -1
  152. package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.webp +0 -0
  153. package/modules/public-landing/public/assets/world/r2-chrome-blobs-set.webp.json +13 -0
  154. package/modules/public-landing/public/assets/world.css +4 -4
  155. package/modules/public-landing/public/connections-empty.states.json +14 -0
  156. package/modules/public-landing/public/connections-inactive.states.json +14 -0
  157. package/modules/public-landing/public/connections.html +450 -0
  158. package/modules/public-landing/public/connections.probes.json +414 -0
  159. package/modules/public-landing/public/connections.states.json +17 -0
  160. package/modules/public-landing/public/contact.html +2 -2
  161. package/modules/public-landing/public/guild.html +2 -2
  162. package/modules/public-landing/public/index.html +2 -2
  163. package/modules/public-landing/public/invitations.html +2 -2
  164. package/modules/public-landing/public/privacy.html +2 -2
  165. package/modules/public-landing/public/projects-hall-live.states.json +0 -5
  166. package/modules/public-landing/public/projects.html +169 -6
  167. package/modules/public-landing/public/projects.probes.json +10 -6
  168. package/modules/public-landing/public/projects.states.json +13 -13
  169. package/modules/public-landing/public/terms.html +2 -2
  170. package/modules/ui-design/kit/fixtures/connections-empty.json +12 -0
  171. package/modules/ui-design/kit/fixtures/connections-inactive.json +7 -0
  172. package/modules/ui-design/kit/fixtures/connections.json +22 -0
  173. package/modules/ui-design/kit/serve.js +95 -0
  174. package/package-lock.json +2 -2
  175. package/package.json +1 -1
  176. package/release-notes.json +128 -0
  177. package/scripts/discord/README.md +8 -5
  178. package/scripts/discord/post.js +12 -1
  179. package/scripts/gds/artifact-audit.js +20 -3
  180. package/scripts/gds/ask.js +164 -0
  181. package/scripts/gds/autobongos-verify.js +21 -2
  182. package/scripts/gds/government-walk.js +638 -4
  183. package/scripts/gds/pulse.js +9 -6
  184. package/scripts/gds/ship-escalation.js +22 -3
  185. package/scripts/gds/ship-finish.js +5 -4
  186. package/scripts/gds/ship-merge-gate.js +18 -6
  187. package/scripts/hall-preview/README.md +41 -1
  188. package/scripts/hall-preview/pref-writes.js +140 -0
  189. package/scripts/hall-preview/refresh-fixtures.js +101 -7
  190. package/scripts/hall-preview/scrub-identity.js +366 -7
  191. package/scripts/hall-preview/server.js +27 -1
  192. package/scripts/render-diagrams.sh +4 -2
  193. package/src/bongos/auth-idp.js +6 -1
  194. package/src/bongos/project-settings.js +41 -0
  195. package/src/bongos/route-rank-check.js +27 -0
  196. package/src/bongos/routes/me.js +68 -7
  197. package/src/bongos/serve-internal.js +5 -1
  198. package/src/module-api.js +7 -1
  199. package/src/platform-server.js +10 -0
  200. package/tests/application_lifecycle.mjs +47 -5
  201. package/tests/conductor_main_e2e.mjs +21 -0
  202. package/tests/connections_api.mjs +18 -0
  203. package/tests/craft_mode_nav.mjs +5 -3
  204. package/tests/craft_mode_tallies.mjs +52 -16
  205. package/tests/discord_approvals.mjs +11 -0
  206. package/tests/discord_channels.mjs +20 -0
  207. package/tests/fixtures/gov-seated.mjs +64 -0
  208. package/tests/fixtures/government-ask-cards.json +1284 -0
  209. package/tests/government_act_alone_buildings.mjs +1 -0
  210. package/tests/government_agent_asks.mjs +322 -0
  211. package/tests/government_asks.mjs +408 -0
  212. package/tests/government_build_rights.mjs +253 -0
  213. package/tests/government_buildouts.mjs +382 -0
  214. package/tests/government_counts.mjs +143 -0
  215. package/tests/government_decision_rules.mjs +5 -1
  216. package/tests/government_laws.mjs +488 -0
  217. package/tests/government_laws_session.mjs +321 -0
  218. package/tests/government_leads.mjs +375 -0
  219. package/tests/government_positions.mjs +127 -0
  220. package/tests/government_presets.mjs +215 -0
  221. package/tests/government_routes.mjs +8 -1
  222. package/tests/government_routing.mjs +118 -0
  223. package/tests/government_seed.mjs +5 -0
  224. package/tests/government_treasury.mjs +394 -0
  225. package/tests/governor_docket.mjs +26 -2
  226. package/tests/hall_buildouts.mjs +208 -0
  227. package/tests/hall_city.mjs +14 -6
  228. package/tests/hall_city_living.mjs +617 -0
  229. package/tests/hall_gov_counts.mjs +336 -0
  230. package/tests/hall_gov_living.mjs +636 -0
  231. package/tests/hall_gov_real_site.mjs +655 -0
  232. package/tests/hall_matter_card.mjs +6 -1
  233. package/tests/hall_my_agents.mjs +481 -0
  234. package/tests/hall_nav.mjs +107 -4
  235. package/tests/hall_page_gate_map.mjs +4 -0
  236. package/tests/hall_preview_governor_fixtures.mjs +30 -3
  237. package/tests/hall_preview_scrub.mjs +59 -1
  238. package/tests/hall_preview_security.mjs +169 -0
  239. package/tests/hall_reading_world.mjs +44 -0
  240. package/tests/hall_roster_world.mjs +6 -2
  241. package/tests/hall_street.mjs +18 -2
  242. package/tests/hall_street_amend.mjs +1 -1
  243. package/tests/hall_street_deck.mjs +609 -0
  244. package/tests/hall_street_depth.mjs +559 -0
  245. package/tests/hall_street_desk.mjs +1 -1
  246. package/tests/hall_street_inside.mjs +29 -5
  247. package/tests/hall_tweak_editor.mjs +4 -1
  248. package/tests/hub_account_page.mjs +94 -3
  249. package/tests/hub_connections_page.mjs +507 -0
  250. package/tests/hub_invite_badge.mjs +1 -1
  251. package/tests/idp_device_exchange.mjs +18 -0
  252. package/tests/landing_legal_pages.mjs +8 -5
  253. package/tests/landing_page.mjs +23 -4
  254. package/tests/nav_permission_atoms.mjs +4 -1
  255. package/tests/profile_connections_ui.mjs +88 -25
  256. package/tests/projects_hub.mjs +15 -0
  257. package/tests/projects_hub_pre_uat.mjs +4 -2
  258. package/tests/render_check.mjs +2 -2
  259. package/tests/ship_broadcast_routing.mjs +57 -16
  260. package/tests/ship_broadcast_server.mjs +40 -7
  261. package/tests/ship_merge_gate.mjs +19 -0
  262. package/tests/ui_design_kit.mjs +2 -2
  263. package/tests/watch_applications_queue.mjs +23 -0
  264. package/tests/wizard_physics.mjs +1 -1
  265. package/tests/wizard_physics_more.mjs +133 -0
@@ -0,0 +1,97 @@
1
+ // modules/hall-ui/public/gov-positions.js — GOVERNING IS A POSITION, not a picked
2
+ // craft (owner ruling 2026-10-09; task 1004685 drew it, task 1004713 made it real).
3
+ //
4
+ // WHAT THIS IS. You pick a craft, but you HOLD a seat in the government or you
5
+ // don't. positionsFor() answers one question for the viewer: which seats do you
6
+ // hold? The shell hides the governing surfaces from a builder who holds none, and
7
+ // craft-mode.js names the Governing mode by the first seat ("Planning Lead").
8
+ //
9
+ // positionsFor({ me, as })
10
+ // → { known, viewer_id, rank, as, sim_rank, positions[], title, has_position, _sources }
11
+ //
12
+ // THE ANSWER IS THE SERVER'S. GET /me carries `positions` — the seats resolved
13
+ // server-side, per request, uncached (modules/government/positions.js: the owner
14
+ // seat, a Lead in office, a seat on a building's sitting, the board under the
15
+ // constitution in force). This file only reads that block; it re-derives nothing
16
+ // from rank, craft, the constitution or the prototype overlay, so it can never
17
+ // disagree with the server. A /me with no `positions` block (the module is off,
18
+ // or a read failed) is UNKNOWN (`known: false`), and every caller keeps today's
19
+ // nav: an unknown is never "none".
20
+ //
21
+ // COSMETIC NAV ONLY. Page gates stay server-side (serve-internal.js + auth.js),
22
+ // and nothing here can open a page the server would refuse.
23
+ //
24
+ // `as: 'nobody'` looks at the hall as a builder who holds no seat (the shell
25
+ // reads it from ?as=nobody, see shell.js). It can only TAKE AWAY: the stand-in
26
+ // holds no seat and a rank no higher than thetes (a xenos stays a xenos), so it
27
+ // can never widen what a viewer sees.
28
+ //
29
+ // PURE. No DOM, no fetch, no clock (tests/hall_my_agents.mjs holds it to that).
30
+
31
+ (function (root) {
32
+ 'use strict';
33
+
34
+ const R = 'real';
35
+ const D = 'derived';
36
+
37
+ const BUILDING_NAMES = Object.freeze({
38
+ charter: 'Charter', rules: 'Rules', disputes: 'Disputes', people: 'People', planning: 'Planning',
39
+ automation: 'Automation', review: 'Review', release: 'Release', treasury: 'Treasury',
40
+ });
41
+ // The kinds the server names (positions.js KINDS), in the order it sorts them.
42
+ const KINDS = Object.freeze(['lead', 'owner', 'seat', 'board']);
43
+ const NOBODY_ID = 'as:nobody';
44
+ const AS_VALUES = Object.freeze(['nobody']);
45
+
46
+ const str = (v) => (v == null ? '' : String(v));
47
+ const obj = (v) => (v && typeof v === 'object' && !Array.isArray(v) ? v : null);
48
+ const arr = (v) => (Array.isArray(v) ? v : []);
49
+
50
+ // The ?as= value the hall honours, or null.
51
+ function asValue(v) { return AS_VALUES.indexOf(str(v).toLowerCase()) >= 0 ? str(v).toLowerCase() : null; }
52
+
53
+ // The stand-in rank for `as: nobody`: thetes, but a xenos (or no rank) stays a
54
+ // xenos. Every gate below thetes is the same for thetes and any member rank, so
55
+ // this only ever takes away.
56
+ function nobodyRank(rank) {
57
+ const r = str(rank).toLowerCase();
58
+ return !r || r === 'xenos' ? 'xenos' : 'thetes';
59
+ }
60
+
61
+ // One seat as the server sent it, or null when it is not one the server names.
62
+ function seatOf(p) {
63
+ const s = obj(p);
64
+ if (!s || KINDS.indexOf(s.kind) < 0 || !s.title) return null;
65
+ return { kind: s.kind, seat: str(s.seat), building: s.building == null ? null : str(s.building), title: str(s.title), source: R };
66
+ }
67
+
68
+ function positionsFor(input) {
69
+ const o = obj(input) || {};
70
+ const me = obj(o.me);
71
+ const builder = me ? (obj(me.builder) || me) : null;
72
+ const as = asValue(o.as);
73
+ const realRank = builder && builder.rank ? String(builder.rank).toLowerCase() : null;
74
+ const rank = as === 'nobody' ? nobodyRank(realRank) : realRank;
75
+ const id = as === 'nobody' ? NOBODY_ID : (builder && builder.id != null ? String(builder.id) : null);
76
+ const sent = me ? obj(me.positions) : null;
77
+ // KNOWN ONLY WITH THE SERVER'S ANSWER (or the stand-in, which holds nothing).
78
+ const known = !!builder && (as === 'nobody' || (!!sent && Array.isArray(sent.held)));
79
+ const positions = known && as !== 'nobody' ? arr(sent.held).map(seatOf).filter(Boolean) : [];
80
+ return {
81
+ known,
82
+ viewer_id: id,
83
+ rank,
84
+ as,
85
+ // the rank the shell pretends for `as: nobody` (null when it pretends nothing)
86
+ sim_rank: as === 'nobody' ? rank : null,
87
+ positions,
88
+ title: positions.length ? positions[0].title : null,
89
+ has_position: positions.length > 0,
90
+ _sources: { known: D, viewer_id: R, rank: R, as: D, sim_rank: D, positions: R, title: R, has_position: R },
91
+ };
92
+ }
93
+
94
+ const api = { positionsFor, asValue, nobodyRank, BUILDING_NAMES, KINDS, NOBODY_ID };
95
+ root.GovPositions = api;
96
+ if (typeof module !== 'undefined' && module.exports) module.exports = api;
97
+ }(typeof window !== 'undefined' ? window : globalThis));
@@ -135,8 +135,8 @@
135
135
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
136
136
 
137
137
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
138
- <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
139
- <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
138
+ <script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
139
+ <script src="/builders/shell.js?v=2026-10-10-hall-keys1"></script>
140
140
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
141
141
  <script src="/builders/palette.js" defer></script>
142
142
  <script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
@@ -224,6 +224,9 @@
224
224
  // task 1004422: project founding mode — passed here for the same reason as the
225
225
  // three above, or the index would be the one page the band never appears on.
226
226
  founding: (ctx.lastMeState && ctx.lastMeState.founding_mode) || null,
227
+ // task 1004713: the government positions this builder holds, server-resolved —
228
+ // passed here too, or the index would keep the governing tabs for a seatless builder.
229
+ positions: (ctx.lastMeState && ctx.lastMeState.positions) || null,
227
230
  builder,
228
231
  });
229
232
 
@@ -51,8 +51,8 @@
51
51
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
52
52
 
53
53
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
54
- <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
55
- <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
54
+ <script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
55
+ <script src="/builders/shell.js?v=2026-10-10-hall-keys1"></script>
56
56
  <script src="/builders/palette.js" defer></script>
57
57
  <script src="/builders/dom-utils.js?v=2026-06-23-contrib" defer></script>
58
58
  <!-- task-detail.js still owns the #/idea/N and #/blocker/N overlay, so a ref
@@ -226,8 +226,8 @@
226
226
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
227
227
 
228
228
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
229
- <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
230
- <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
229
+ <script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
230
+ <script src="/builders/shell.js?v=2026-10-10-hall-keys1"></script>
231
231
  <script src="/builders/palette.js" defer></script>
232
232
  <script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
233
233
  <!-- task 1003069 (R08) — the quick-filing form's routed result links a task
@@ -107,8 +107,8 @@
107
107
  <!-- The app shell (sidebar + top bar + view router). Dependency-free; loaded
108
108
  BEFORE builders.js so the chrome ids exist when events are wired. -->
109
109
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab" defer></script>
110
- <script src="/builders/craft-mode.js?v=2026-10-08-city-tab" defer></script>
111
- <script src="/builders/shell.js?v=2026-10-08-glyph-fix" defer></script>
110
+ <script src="/builders/craft-mode.js?v=2026-10-09-living3" defer></script>
111
+ <script src="/builders/shell.js?v=2026-10-10-hall-keys1" defer></script>
112
112
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
113
113
  <script src="/builders/palette.js" defer></script>
114
114
  <!-- task 2166: the shared component kit (window.OTBKit) — pager/ledger/rail.
@@ -139,7 +139,7 @@
139
139
  window.OTBHallRender(ctx) once during its own setup. The module
140
140
  hall-widget tags the server injects still anchor on builders.js's tag
141
141
  below (it matches by filename), so they land between the two. -->
142
- <script src="/builders/hall-render.js?v=2026-08-24-hallrender1" defer></script>
142
+ <script src="/builders/hall-render.js?v=2026-10-09-positions1" defer></script>
143
143
  <!-- task 1002802 (P06): the profile-completion nudge slice. Exposes
144
144
  window.OTBProfileNudge; goal-inbox.js's mount() calls it once it has
145
145
  created the #attention-profile div, so load order is not load-bearing. -->
@@ -102,8 +102,8 @@
102
102
  <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
103
103
 
104
104
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
105
- <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
106
- <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
105
+ <script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
106
+ <script src="/builders/shell.js?v=2026-10-10-hall-keys1"></script>
107
107
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
108
108
  <script src="/builders/palette.js" defer></script>
109
109
  <script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
@@ -0,0 +1,334 @@
1
+ /* modules/hall-ui/public/my-agents.css — MY AGENTS (task 1004685, the living-city
2
+ prototype; round-3 boards 6-8). Rides the oversight family's sheet
3
+ (oversight.css, linked first): its group head and foot line are used as they
4
+ are, and the row here is that family's hairline row at the owner's desk density
5
+ (a name, one fact, at most two buttons; choices as one-tap chips).
6
+
7
+ Colour: the fifteen pack tokens and the shell's derived tiers, as var() and
8
+ color-mix() only. The accent is not spent here: nothing on this page waits on
9
+ the reader, and on the governing surfaces salmon means exactly that. A chosen
10
+ chip is ink on glass, a lock is a dashed hairline, a law band is an ink wash.
11
+ No :root here (tests/hall_reading_world.mjs): page tokens live on the body.
12
+ The two dark blocks are byte-identical twins (the hall's switch is
13
+ html[data-theme]; the media block is first paint). Light mode cannot glow, so
14
+ the lit pip is a solid ink fill there and gains a soft ink halo only in dark.
15
+
16
+ Motion is CSS only, on transform alone, and one-shot: a lit pip pops in when it
17
+ is drawn, a saved row's tick scales in when my-agents.js sets data-saved. The
18
+ kill switch at the foot stops both, and the still frame is the same page. */
19
+
20
+ body[data-page="my-agents"] {
21
+ --ma-pip-glow: none;
22
+ --ma-law-wash: color-mix(in srgb, var(--ink) 4%, transparent);
23
+ --ma-ease: cubic-bezier(.16, 1, .3, 1);
24
+ }
25
+ html[data-theme="dark"] body[data-page="my-agents"] {
26
+ --ma-pip-glow: 0 0 9px color-mix(in srgb, var(--ink) 34%, transparent);
27
+ --ma-law-wash: color-mix(in srgb, var(--ink) 6%, transparent);
28
+ }
29
+ @media (prefers-color-scheme: dark) {
30
+ html:not([data-theme]) body[data-page="my-agents"] {
31
+ --ma-pip-glow: 0 0 9px color-mix(in srgb, var(--ink) 34%, transparent);
32
+ --ma-law-wash: color-mix(in srgb, var(--ink) 6%, transparent);
33
+ }
34
+ }
35
+
36
+ /* ---- the "viewing as nobody" line ---- */
37
+ .ma-as {
38
+ margin: 0 0 var(--sp-sm);
39
+ padding: 8px 14px;
40
+ border: var(--line) dashed var(--rule);
41
+ border-radius: var(--radius-pill);
42
+ font-size: 13px;
43
+ color: var(--ink-soft);
44
+ }
45
+ .ma-as a { display: inline-block; min-height: 24px; min-width: 24px; padding: 3px 4px; margin: -3px 0; line-height: 18px; color: var(--ink); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--ink) 35%, transparent); text-underline-offset: 3px; }
46
+
47
+ /* ---- your seats ---- */
48
+ .ma-seat { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 12px; font-size: 13.5px; }
49
+ .ma-seat__l {
50
+ font-family: var(--label-face);
51
+ font-size: var(--label-size);
52
+ letter-spacing: var(--label-space);
53
+ text-transform: var(--label-case);
54
+ color: var(--ink-faint);
55
+ margin-right: 4px;
56
+ }
57
+ .ma-seat .fact-pill { color: var(--ink-soft); }
58
+ .ma-seat .ma-seat__lead { color: var(--ink); }
59
+ .ma-seat__none { color: var(--ink-soft); }
60
+
61
+ /* ---- the strictness strip: the project's preset, and a preview of the others ---- */
62
+ .ma-strict { margin: 0 0 var(--sp-md); }
63
+ .ma-strict__band {
64
+ display: grid;
65
+ grid-template-columns: minmax(0, 1fr) auto auto;
66
+ gap: 16px 28px;
67
+ align-items: center;
68
+ padding: 18px 22px;
69
+ background: var(--glass);
70
+ border: var(--line) solid var(--glass-edge);
71
+ border-radius: var(--radius);
72
+ backdrop-filter: blur(var(--glass-blur));
73
+ -webkit-backdrop-filter: blur(var(--glass-blur));
74
+ }
75
+ .ma-strict__h {
76
+ display: flex;
77
+ align-items: center;
78
+ gap: 10px;
79
+ margin: 0 0 4px;
80
+ font-family: var(--font-display);
81
+ font-weight: 300;
82
+ font-size: 26px;
83
+ line-height: 1.1;
84
+ letter-spacing: -0.03em;
85
+ color: var(--ink);
86
+ text-shadow: var(--type-halo);
87
+ }
88
+ .ma-strict__eyebrow {
89
+ margin: 0 0 2px;
90
+ font-family: var(--label-face);
91
+ font-size: var(--label-size);
92
+ letter-spacing: var(--label-space);
93
+ text-transform: var(--label-case);
94
+ color: var(--ink-faint);
95
+ }
96
+ .ma-strict__line { margin: 0 0 4px; font-size: 13.5px; color: var(--ink-soft); }
97
+ .ma-strict__who { margin: 0; font-size: 12.5px; color: var(--ink-faint); }
98
+ .ma-strict__presets { display: flex; gap: 8px; }
99
+ .ma-preset {
100
+ display: flex;
101
+ flex-direction: column;
102
+ align-items: flex-start;
103
+ gap: 2px;
104
+ min-height: 44px;
105
+ min-width: 118px;
106
+ padding: 6px 14px;
107
+ border: var(--line) solid var(--rule);
108
+ border-radius: var(--radius-sm);
109
+ background: none;
110
+ color: var(--ink-soft);
111
+ font: inherit;
112
+ text-align: left;
113
+ cursor: pointer;
114
+ }
115
+ .ma-preset:hover { color: var(--ink); border-color: var(--ink-faint); }
116
+ .ma-preset[aria-pressed="true"] { color: var(--ink); border-color: var(--ink-soft); background: var(--glass-strong); }
117
+ .ma-preset__name { display: flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 500; white-space: nowrap; }
118
+ .ma-preset__ours {
119
+ font-family: var(--label-face);
120
+ font-size: 10px;
121
+ font-weight: 400;
122
+ letter-spacing: var(--label-space);
123
+ text-transform: var(--label-case);
124
+ color: var(--ink-faint);
125
+ }
126
+ .ma-preset__n { font-size: 11.5px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
127
+ .ma-strict__vote { margin: 10px 0 0; }
128
+ .ma-strict__locks { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 10px 14px; }
129
+ .ma-tile { display: inline-flex; align-items: baseline; gap: 8px; }
130
+ .ma-tile__n {
131
+ font-family: var(--font-display);
132
+ font-weight: 300;
133
+ font-size: 34px;
134
+ line-height: 1;
135
+ letter-spacing: -0.035em;
136
+ font-variant-numeric: tabular-nums;
137
+ color: var(--ink);
138
+ text-shadow: var(--type-halo);
139
+ }
140
+ .ma-tile__l { font-size: 12.5px; color: var(--ink-faint); }
141
+ /* one pip per setting a law could lock; a lit pip is a locked one */
142
+ .ma-pips { display: inline-flex; flex-wrap: wrap; gap: 4px; }
143
+ .ma-pip { position: relative; width: 10px; height: 10px; border: var(--line) solid var(--rule); border-radius: 3px; box-sizing: border-box; }
144
+ .ma-pip[data-on]::after {
145
+ content: '';
146
+ position: absolute;
147
+ inset: 1px;
148
+ border-radius: 2px;
149
+ background: var(--ink);
150
+ box-shadow: var(--ma-pip-glow);
151
+ animation: ma-pop 420ms var(--ma-ease) both;
152
+ }
153
+ @keyframes ma-pop { from { transform: scale(0); } to { transform: scale(1); } }
154
+
155
+ /* ---- two columns: the desk, and what the agent reads first ---- */
156
+ .ma-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 380px); gap: var(--sp-md); align-items: start; }
157
+ .ma-reads { position: sticky; top: calc(var(--topbar-h) + 16px); }
158
+ @media (max-width: 1100px) {
159
+ .ma-grid { grid-template-columns: minmax(0, 1fr); }
160
+ .ma-reads { position: static; }
161
+ }
162
+
163
+ /* ---- the row: a name, one fact, the chips ---- */
164
+ .ma-group { margin-top: var(--sp-md); }
165
+ .ma-group:first-child { margin-top: 4px; }
166
+ .ma-rows { list-style: none; margin: 0; padding: 0; }
167
+ .ma-row {
168
+ display: grid;
169
+ grid-template-columns: minmax(118px, 160px) minmax(0, 1fr) auto;
170
+ gap: 6px 18px;
171
+ align-items: center;
172
+ min-height: 48px;
173
+ padding: 8px 0;
174
+ border-top: var(--line) solid var(--rule-soft);
175
+ }
176
+ .ma-rows > .ma-row:first-child { border-top: 0; }
177
+ .ma-row__name { display: flex; align-items: center; gap: 8px; font-size: 14.5px; font-weight: 500; letter-spacing: -0.01em; color: var(--ink); min-width: 0; }
178
+ /* the fact, and under it what YOU chose when a law holds the row */
179
+ .ma-row__fact { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; min-width: 0; font-size: 14px; color: var(--ink-soft); }
180
+ .ma-row__yours { font-size: 12px; color: var(--ink-faint); }
181
+ .ma-row__act { justify-self: end; display: flex; align-items: center; min-width: 0; }
182
+ .ma-row--locked .ma-row__fact { color: var(--ink); }
183
+ .ma-row__link {
184
+ display: inline-block;
185
+ min-height: 24px;
186
+ min-width: 24px;
187
+ padding: 3px 4px;
188
+ margin: -3px -4px;
189
+ line-height: 18px;
190
+ font-size: 12.5px;
191
+ color: var(--ink); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--ink) 35%, transparent); text-underline-offset: 3px;
192
+ }
193
+ .ma-mono { font-family: var(--font-mono); font-size: 12.5px; font-weight: 400; }
194
+
195
+ /* the lit tick: scales in when a choice saves, stays on a proposed habit */
196
+ .ma-tick { width: 14px; height: 14px; flex: none; color: var(--ok); transform: scale(0); transition: transform 320ms var(--ma-ease); }
197
+ .ma-row[data-saved] .ma-tick, .ma-row--done .ma-tick { transform: scale(1); }
198
+
199
+ /* one-tap chips: a hairline pill; the chosen one is ink on glass */
200
+ .ma-chips { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }
201
+ .ma-chip {
202
+ display: inline-flex;
203
+ align-items: center;
204
+ justify-content: center;
205
+ min-height: 28px;
206
+ min-width: 28px;
207
+ padding: 0 12px;
208
+ border: var(--line) solid var(--rule);
209
+ border-radius: var(--radius-pill);
210
+ background: none;
211
+ color: var(--ink-soft);
212
+ font: inherit;
213
+ font-size: 13px;
214
+ white-space: nowrap;
215
+ cursor: pointer;
216
+ }
217
+ .ma-chip:hover:not(:disabled) { color: var(--ink); border-color: var(--ink-faint); }
218
+ .ma-chip[aria-pressed="true"] { color: var(--ink); background: var(--glass-strong); border-color: var(--ink-soft); cursor: default; }
219
+ .ma-chip:disabled { cursor: default; }
220
+
221
+ /* a lock: the law that holds this row, on a dashed hairline */
222
+ .ma-lock {
223
+ display: inline-flex;
224
+ align-items: center;
225
+ gap: 6px;
226
+ min-height: 28px;
227
+ padding: 3px 12px;
228
+ border: var(--line) dashed var(--rule);
229
+ border-radius: var(--radius-pill);
230
+ font-size: 12.5px;
231
+ line-height: 1.35;
232
+ color: var(--ink-soft);
233
+ }
234
+ .ma-lock__icon { width: 13px; height: 13px; flex: none; }
235
+
236
+ /* a cap (task 1004714): the law that caps a row, under its fact; the chips offer the rest */
237
+ .ma-row__cap { display: inline-flex; align-items: center; gap: 4px; }
238
+
239
+ /* the per-skill list, opened in place */
240
+ .ma-sub { padding: 0 0 6px 18px; border-left: 2px solid var(--rule-soft); margin: 0 0 6px; }
241
+ .ma-row--sub { min-height: 40px; padding: 4px 0; }
242
+ .ma-row--sub .ma-row__fact { font-size: 13px; }
243
+
244
+ /* ---- what the agent reads first ---- */
245
+ .ma-read { margin: 0 0 12px; }
246
+ .ma-read--project { padding: 12px 14px; background: var(--ma-law-wash); border-radius: var(--radius-sm); }
247
+ .ma-read--mine { padding: 12px 14px 4px; }
248
+ .ma-read__l {
249
+ display: flex;
250
+ flex-wrap: wrap;
251
+ align-items: center;
252
+ gap: 4px 8px;
253
+ margin: 0 0 6px;
254
+ font-family: var(--label-face);
255
+ font-size: var(--label-size);
256
+ letter-spacing: var(--label-space);
257
+ text-transform: var(--label-case);
258
+ color: var(--ink);
259
+ }
260
+ .ma-read__n {
261
+ display: inline-flex;
262
+ align-items: center;
263
+ justify-content: center;
264
+ width: 20px;
265
+ height: 20px;
266
+ border: var(--line) solid var(--rule);
267
+ border-radius: var(--radius-pill);
268
+ font-family: var(--font-mono);
269
+ font-size: 11px;
270
+ letter-spacing: 0;
271
+ color: var(--ink-soft);
272
+ flex: none;
273
+ }
274
+ .ma-read__who { margin-left: auto; font-family: var(--font-body); font-size: 11.5px; letter-spacing: 0; text-transform: none; color: var(--ink-faint); }
275
+ .ma-laws { list-style: none; margin: 0; padding: 0; }
276
+ .ma-law { display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 0 8px; padding: 6px 0; border-top: var(--line) solid var(--rule-soft); }
277
+ .ma-law:first-child { border-top: 0; }
278
+ .ma-law__no { font-family: var(--font-mono); font-size: 12px; color: var(--ink-faint); font-variant-numeric: tabular-nums; padding-top: 1px; }
279
+ .ma-law__t { font-size: 13.5px; font-weight: 500; color: var(--ink); }
280
+ .ma-law__e { grid-column: 2; font-size: 12.5px; line-height: 1.45; color: var(--ink-soft); }
281
+ .ma-said { margin: 0 0 10px; }
282
+ .ma-said__t { margin: 0 0 4px; font-size: 13px; font-weight: 500; color: var(--ink); }
283
+ .ma-said__lines { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
284
+ .ma-said__lines li {
285
+ display: -webkit-box;
286
+ -webkit-box-orient: vertical;
287
+ -webkit-line-clamp: 2;
288
+ overflow: hidden;
289
+ font-size: 12.5px;
290
+ line-height: 1.5;
291
+ color: var(--ink-soft);
292
+ }
293
+ .ma-said__lines--all li { display: block; -webkit-line-clamp: unset; overflow: visible; }
294
+ .ma-said__lines b { font-weight: 500; color: var(--ink); }
295
+ .ma-said__note { margin: 4px 0 0; font-size: 12.5px; color: var(--ink-faint); }
296
+ .ma-readall { margin: 0 0 8px; }
297
+
298
+ /* ---- quiet lines ---- */
299
+ .ma-quiet { margin: 6px 0; font-size: 13.5px; color: var(--ink-faint); }
300
+ .ma-quiet a { display: inline-block; min-height: 24px; min-width: 24px; padding: 3px 4px; margin: -3px 0; line-height: 18px; color: var(--ink); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--ink) 35%, transparent); text-underline-offset: 3px; }
301
+
302
+ /* ---- narrow: the presets take their own line, then the strip stacks; a row puts
303
+ its chips under its name and fact, and on the smallest phone each part its own line ---- */
304
+ @media (max-width: 1240px) {
305
+ .ma-strict__band { grid-template-columns: minmax(0, 1fr) auto; }
306
+ .ma-strict__presets { grid-column: 1 / -1; order: 3; }
307
+ }
308
+ @media (max-width: 640px) {
309
+ .ma-strict__band { grid-template-columns: minmax(0, 1fr); padding: 16px; }
310
+ .ma-strict__locks { justify-content: flex-start; }
311
+ .ma-preset { flex: 1 1 0; min-width: 0; padding: 6px 10px; }
312
+ .ma-preset__name { white-space: normal; flex-wrap: wrap; }
313
+ .ma-row {
314
+ grid-template-columns: minmax(0, 1fr) auto;
315
+ grid-template-areas: "name fact" "act act";
316
+ gap: 6px 12px;
317
+ }
318
+ .ma-row__name { grid-area: name; }
319
+ .ma-row__fact { grid-area: fact; align-items: flex-end; text-align: right; }
320
+ .ma-row__act { grid-area: act; justify-self: start; }
321
+ .ma-chips { justify-content: flex-start; }
322
+ }
323
+ @media (max-width: 420px) {
324
+ .ma-row { grid-template-columns: minmax(0, 1fr); grid-template-areas: "name" "fact" "act"; gap: 4px; }
325
+ .ma-row__name { flex-wrap: wrap; }
326
+ .ma-row__fact { align-items: flex-start; text-align: left; }
327
+ }
328
+
329
+ /* ---- the kill switch: nothing on this page moves under reduced motion ---- */
330
+ @media (prefers-reduced-motion: reduce) {
331
+ body[data-page="my-agents"] *,
332
+ body[data-page="my-agents"] *::before,
333
+ body[data-page="my-agents"] *::after { animation: none !important; transition: none !important; }
334
+ }
@@ -0,0 +1,72 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>My agents — {{worldName}}</title>
7
+ <meta name="description" content="How your own Claude works for you: how it talks, how far it wanders and which models run.">
8
+ <link rel="icon" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><text x='16' y='24' font-size='24' text-anchor='middle' font-family='sans-serif'>⌂</text></svg>">
9
+ <link rel="preconnect" href="https://fonts.googleapis.com">
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link rel="stylesheet" href="/builders/style.css?v=2026-07-02-shell1">
12
+ <!-- The oversight family's archetype: a titled row with facts and actions, the
13
+ group head and the foot line (records/oversight-family.md). This page's
14
+ repeated thing is that row at the desk's one-line density. -->
15
+ <link rel="stylesheet" href="/builders/oversight.css">
16
+ <link rel="stylesheet" href="/builders/my-agents.css">
17
+ </head>
18
+ <body data-page="my-agents" data-page-title="My agents">
19
+
20
+ <div class="app">
21
+ <aside class="app-sidebar" id="app-sidebar" aria-label="Primary"></aside>
22
+ <div class="app-scrim" id="app-scrim" hidden></div>
23
+ <div class="app-body">
24
+ <header class="app-topbar" id="app-topbar"></header>
25
+ <div class="app-content">
26
+ <!-- task 1004685 (the living-city prototype, round-3 boards 6-8): the personal
27
+ half of "the city steers everyone, My agents steers yours". Every row is
28
+ filled by my-agents.js from GET /me and its prefs; the strictness strip
29
+ from GET /government/presets (all real, task 1004715). -->
30
+ <div class="page-head page-head--board">
31
+ <h1 class="page-head__h">My agents</h1>
32
+ <p class="page-head__sub" id="ma-sub">How your Claude works for you. Tap a setting to change it.</p>
33
+ </div>
34
+
35
+ <main id="hall-main" class="ma-main" aria-busy="true">
36
+ <p class="ma-as" id="ma-as" role="status" hidden></p>
37
+
38
+ <section class="ma-strict" id="ma-strict" aria-labelledby="ma-strict-h" hidden></section>
39
+
40
+ <div class="ma-grid">
41
+ <section class="scroll ma-desk" id="ma-desk" aria-labelledby="ma-desk-h">
42
+ <h2 class="scroll__h" id="ma-desk-h">Your agents</h2>
43
+ <p class="scroll__lede" id="ma-desk-lede">One line each. Tap to change; it saves straight away.</p>
44
+ <div id="ma-rows" aria-live="polite"><p class="ma-quiet">Reading your settings…</p></div>
45
+ </section>
46
+
47
+ <aside class="scroll ma-reads" id="ma-reads" aria-labelledby="ma-reads-h">
48
+ <h2 class="scroll__h" id="ma-reads-h">What your agent reads first</h2>
49
+ <p class="scroll__lede">At the start of every session, in this order.</p>
50
+ <div id="ma-reads-body" aria-live="polite"><p class="ma-quiet">Reading…</p></div>
51
+ </aside>
52
+ </div>
53
+ </main>
54
+
55
+ <footer class="app-foot" id="app-foot"></footer>
56
+ </div>
57
+ </div>
58
+ </div>
59
+
60
+ <div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
61
+
62
+ <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
63
+ <script src="/builders/craft-mode.js?v=2026-10-09-living3"></script>
64
+ <script src="/builders/shell.js?v=2026-10-10-hall-keys1"></script>
65
+ <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
66
+ <script src="/builders/palette.js" defer></script>
67
+ <script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
68
+ <script src="/builders/gov-living.js?v=2026-10-10-real1"></script>
69
+ <script src="/builders/gov-positions.js?v=2026-10-09-positions1"></script>
70
+ <script src="/builders/my-agents.js?v=2026-10-10-real1"></script>
71
+ </body>
72
+ </html>