@bongos/core 1.24.28 → 1.24.30

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 (63) hide show
  1. package/.bongos-core.json +100 -70
  2. package/.claude/skills/builder-claim/SKILL.md +1 -1
  3. package/.claude/skills/builder-ship/SKILL.md +1 -1
  4. package/clients/bongos-client/README.md +1 -1
  5. package/clients/bongos-client/bongos-client.global.js +4 -0
  6. package/clients/bongos-client/index.cjs +4 -0
  7. package/clients/bongos-client/index.d.ts +4 -0
  8. package/clients/bongos-client/index.mjs +4 -0
  9. package/docs/api/openapi.json +36 -1
  10. package/docs/api-reference.md +7 -1
  11. package/docs/copy-inventory.md +247 -280
  12. package/docs/copy-registry.json +381 -691
  13. package/docs/module-api-changelog.md +4 -0
  14. package/docs/page-inventory.json +5 -10
  15. package/docs/page-readings.json +327 -393
  16. package/modules/builder-settings/interaction-prefs.js +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/builders.js +3 -79
  21. package/modules/hall-ui/public/hall-render.js +6 -81
  22. package/modules/hall-ui/public/hall-widgets.js +4 -45
  23. package/modules/hall-ui/public/home-city-draw.js +275 -0
  24. package/modules/hall-ui/public/home-city.css +66 -0
  25. package/modules/hall-ui/public/home-city.js +223 -0
  26. package/modules/hall-ui/public/index.html +5 -6
  27. package/modules/hall-ui/public/index.states.json +73 -8
  28. package/modules/hall-ui/public/my-agents.js +35 -2
  29. package/modules/hall-ui/public/palette.js +8 -0
  30. package/modules/hall-ui/public/settings-moved.js +41 -0
  31. package/modules/hall-ui/public/settings.css +4 -28
  32. package/modules/hall-ui/public/settings.html +19 -107
  33. package/modules/hall-ui/public/settings.js +20 -215
  34. package/modules/hall-ui/public/settings.states.json +2 -4
  35. package/modules/hall-ui/records/home-city.md +66 -0
  36. package/modules/hall-ui/records/my-agents.md +3 -2
  37. package/modules/hall-ui/records/panel-family.md +2 -0
  38. package/modules/lifecycle/home-city.js +340 -0
  39. package/modules/lifecycle/module.json +1 -0
  40. package/modules/lifecycle/routes/home-city.js +29 -0
  41. package/modules/lifecycle/ship-card.js +2 -2
  42. package/package-lock.json +2 -2
  43. package/package.json +1 -1
  44. package/release-notes.json +16 -0
  45. package/src/module-api.js +1 -1
  46. package/tests/claim_from_task_and_home.mjs +8 -43
  47. package/tests/government_tidy_up.mjs +21 -24
  48. package/tests/hall_board_world.mjs +10 -12
  49. package/tests/hall_home_ships_bounded.mjs +4 -3
  50. package/tests/hall_my_agents.mjs +88 -2
  51. package/tests/hall_palette.mjs +12 -0
  52. package/tests/hall_settings_world.mjs +64 -100
  53. package/tests/helpers.mjs +6 -5
  54. package/tests/home_bounded_reads.mjs +16 -31
  55. package/tests/home_city.mjs +385 -0
  56. package/tests/home_city_widget.mjs +120 -0
  57. package/tests/interaction_posture.mjs +3 -1
  58. package/tests/leaderboard_roles.mjs +3 -2
  59. package/tests/speciality_offer_ui.mjs +6 -5
  60. package/tests/speciality_walkthrough_ui.mjs +7 -5
  61. package/modules/hall-ui/public/settings-interaction.js +0 -132
  62. package/modules/hall-ui/public/settings-law-locks.js +0 -53
  63. package/modules/hall-ui/public/settings-render.js +0 -138
@@ -2,17 +2,82 @@
2
2
  "_": "The hall's HOME page through modules/ui-design/kit/render.js (task 1003304). Home is served at the surface root, so its page path has no last segment to name the file — run it with `--states modules/hall-ui/public/index.states.json`, not `--page`.",
3
3
  "page": "/builders/",
4
4
  "surface": "hall-ui",
5
- "stub": { "prefix": "/builders/" },
5
+ "stub": {
6
+ "prefix": "/builders/"
7
+ },
6
8
  "modeQuery": false,
7
9
  "_feeds": "As work.states.json: the kit's stub is not the hall's feed set, so Home renders its skeletons and empty states here. The populated dashboard is the hall-preview harness.",
8
- "ignoreRequests": ["/api/(gds|bongos)/me$", "/api/(gds|bongos)/me/", "/api/(gds|bongos)/tasks", "/api/(gds|bongos)/claims", "/api/(gds|bongos)/goals", "/api/(gds|bongos)/inbox", "/api/(gds|bongos)/live", "/api/(gds|bongos)/analytics/", "/api/(gds|bongos)/achievements", "/api/(gds|bongos)/versions", "/api/(gds|bongos)/leaderboard"],
9
- "ignoreConsole": ["/api/(gds|bongos)/", "\\b401\\b", "\\b404\\b", "Unauthorized", "Not Found", "load failed"],
10
+ "ignoreRequests": [
11
+ "/api/(gds|bongos)/me$",
12
+ "/api/(gds|bongos)/me/",
13
+ "/api/(gds|bongos)/tasks",
14
+ "/api/(gds|bongos)/claims",
15
+ "/api/(gds|bongos)/goals",
16
+ "/api/(gds|bongos)/inbox",
17
+ "/api/(gds|bongos)/live",
18
+ "/api/(gds|bongos)/analytics/",
19
+ "/api/(gds|bongos)/achievements",
20
+ "/api/(gds|bongos)/versions",
21
+ "/api/(gds|bongos)/leaderboard",
22
+ "/api/(gds|bongos)/home/"
23
+ ],
24
+ "ignoreConsole": [
25
+ "/api/(gds|bongos)/",
26
+ "\\b401\\b",
27
+ "\\b404\\b",
28
+ "Unauthorized",
29
+ "Not Found",
30
+ "load failed"
31
+ ],
10
32
  "_1003441": "The `leaderboard` state left with the view: the Roll is the /roster page now and #leaderboard REDIRECTS there, so there is no #view-leaderboard on this page to make visible. The redirect is proven in tests/hall_nav.mjs (it asserts location.replace('/roster') fires on the index and nowhere else) rather than by a render state, because a state whose page navigates away measures the destination, not this page. `standing-karma` replaces the coverage: task 2178 made each Standing rail section addressable and none had a measured state.",
11
33
  "states": {
12
- "home": { "auth": true, "expect": { "visible": ["#view-home"], "hidden": ["#view-standing"] } },
13
- "standing": { "auth": true, "url": "/builders/#accomplishments", "actions": [["wait", 400]], "expect": { "visible": ["#view-standing"] } },
14
- "standing-karma": { "auth": true, "url": "/builders/#standing-karma", "actions": [["wait", 400]], "expect": { "visible": ["#view-standing"] } },
15
- "out": { "auth": false }
34
+ "home": {
35
+ "auth": true,
36
+ "expect": {
37
+ "visible": [
38
+ "#view-home"
39
+ ],
40
+ "hidden": [
41
+ "#view-standing"
42
+ ]
43
+ }
44
+ },
45
+ "standing": {
46
+ "auth": true,
47
+ "url": "/builders/#accomplishments",
48
+ "actions": [
49
+ [
50
+ "wait",
51
+ 400
52
+ ]
53
+ ],
54
+ "expect": {
55
+ "visible": [
56
+ "#view-standing"
57
+ ]
58
+ }
59
+ },
60
+ "standing-karma": {
61
+ "auth": true,
62
+ "url": "/builders/#standing-karma",
63
+ "actions": [
64
+ [
65
+ "wait",
66
+ 400
67
+ ]
68
+ ],
69
+ "expect": {
70
+ "visible": [
71
+ "#view-standing"
72
+ ]
73
+ }
74
+ },
75
+ "out": {
76
+ "auth": false
77
+ }
78
+ },
79
+ "reducedMotion": {
80
+ "auth": true
16
81
  },
17
- "reducedMotion": { "auth": true }
82
+ "_1005054": "The project city (home-city.js, task 1005054) reads GET /home/city, which the kit stub does not serve: here the city stays hidden, as it does for a signed-out visitor or a failed read, and the inbox below renders as before. The populated city is measured in the hall-preview harness (scripts/hall-preview/fixtures/home__city.json) and by tests/home_city_widget.mjs."
18
83
  }
@@ -81,6 +81,22 @@
81
81
  // 1005052: its tools are more than a desk row's two buttons, and they are the
82
82
  // shared speciality-tools.js component, which this desk's redraw would wipe.
83
83
  ];
84
+ // Deep links (task 1005044): #<anchor> lands on a group this page draws, or on
85
+ // the speciality section. Settings' old links arrive here (settings-moved.js):
86
+ // #talk holds how Claude talks to you and session cards, #work wandering,
87
+ // #skills opens the per-skill voices, #knows is What it knows.
88
+ const ANCHORS = {
89
+ talk: { group: 'talk' },
90
+ work: { group: 'work' },
91
+ models: { group: 'models' },
92
+ skills: { group: 'models', openSkills: true },
93
+ knows: { id: 'specialities-scroll' },
94
+ };
95
+ function anchorFor(hash) {
96
+ const key = String(hash || '').replace(/^#/, '');
97
+ const a = Object.prototype.hasOwnProperty.call(ANCHORS, key) ? ANCHORS[key] : null;
98
+ return a ? { id: a.id || 'ma-group-' + a.group, openSkills: !!a.openSkills } : null;
99
+ }
84
100
  // the permission atom that may file a laws vote (POST /government/board/laws)
85
101
  const PROPOSE_ATOM = 'board.item.open';
86
102
 
@@ -317,7 +333,7 @@
317
333
  };
318
334
  }
319
335
 
320
- const pure = { buildView, writeFor, proposalFor, pendingLaws, SETTING, LAW_LINES, GROUPS };
336
+ const pure = { buildView, writeFor, proposalFor, pendingLaws, anchorFor, ANCHORS, SETTING, LAW_LINES, GROUPS };
321
337
  root.OTBMyAgents = pure;
322
338
  if (typeof module !== 'undefined' && module.exports) { module.exports = pure; return; }
323
339
  if (typeof document === 'undefined' || !root.BongosClient) return;
@@ -422,7 +438,7 @@
422
438
  }
423
439
  function rowsHtml(v) {
424
440
  let html = v.groups.map((g) =>
425
- '<div class="ov-group ma-group" data-group="' + esc(g.key) + '">' +
441
+ '<div class="ov-group ma-group" id="ma-group-' + esc(g.key) + '" data-group="' + esc(g.key) + '">' +
426
442
  '<div class="ov-group__head"><span class="ov-group__name">' + esc(g.title) + '</span>' +
427
443
  (g.locked ? '<span class="ov-group__n">' + esc(g.locked) + ' locked</span>' : '') +
428
444
  '<span class="ov-group__note">live</span></div>' +
@@ -619,8 +635,24 @@
619
635
  });
620
636
  }
621
637
 
638
+ // Land a deep link (task 1005044) once its target is drawn: the desk groups
639
+ // after the first render; What it knows is revealed by speciality-tools.js when
640
+ // its own read lands, so a hidden target is watched (no timer) until it shows.
641
+ function land() {
642
+ const a = anchorFor(root.location.hash);
643
+ if (!a) return;
644
+ if (a.openSkills && !S.skillsOpen && S.view) { S.skillsOpen = true; render(); }
645
+ const el = $(a.id);
646
+ if (!el) return;
647
+ if (!el.hidden) { el.scrollIntoView({ block: 'start' }); return; }
648
+ if (typeof MutationObserver !== 'function') return;
649
+ const watch = new MutationObserver(() => { if (!el.hidden) { watch.disconnect(); el.scrollIntoView({ block: 'start' }); } });
650
+ watch.observe(el, { attributes: true, attributeFilter: ['hidden'] });
651
+ }
652
+
622
653
  async function boot() {
623
654
  wire();
655
+ root.addEventListener('hashchange', () => land());
624
656
  const me = await getJSON('/me');
625
657
  if (me === null || me === false || !me.builder) {
626
658
  const rows = $('ma-rows');
@@ -637,6 +669,7 @@
637
669
  S.constitution = constitution;
638
670
  S.skills = skills || null;
639
671
  render();
672
+ land();
640
673
  }
641
674
  boot();
642
675
  }(typeof window !== 'undefined' ? window : globalThis));
@@ -53,6 +53,7 @@
53
53
  // work → work.js makeTabs ids
54
54
  // government → government.js makeTabs ids (two rooms since ADR 0266)
55
55
  // settings → settings.js RAIL_GROUPS
56
+ // my-agents → my-agents.js ANCHORS (the agent settings left Settings, task 1005044)
56
57
  var SECTIONS = [
57
58
  { parent: 'Accomplishments', gate: 'nav-standing', items: [
58
59
  { label: 'Work', href: '/#accomplishments-work' },
@@ -74,6 +75,13 @@
74
75
  { label: 'Constitution', href: '/government#constitution' },
75
76
  { label: 'Ranks & Permissions', href: '/government#ranks' },
76
77
  ] },
78
+ { parent: 'My agents', gate: 'nav-my-agents', items: [
79
+ { label: 'How it talks to you', href: '/my-agents#talk' },
80
+ { label: 'How your agents work', href: '/my-agents#work' },
81
+ { label: 'Which models run', href: '/my-agents#models' },
82
+ { label: 'Skill voices', href: '/my-agents#skills' },
83
+ { label: 'What it knows', href: '/my-agents#knows' },
84
+ ] },
77
85
  { parent: 'Settings', gate: 'shell-user', items: [
78
86
  { label: 'Account', href: '/settings#account' },
79
87
  { label: 'Access', href: '/settings#access' },
@@ -0,0 +1,41 @@
1
+ // modules/hall-ui/public/settings-moved.js — where the agent settings went
2
+ // (task 1005044).
3
+ //
4
+ // How Claude talks to you, Wandering, Rendering (session cards), Skill voices and
5
+ // Your specialities were edited on Settings AND on My agents, on the same routes,
6
+ // with nothing saying the two were one setting. The owner kept them on My agents
7
+ // only. Their old deep links (/settings#interaction, #voices, … and the section
8
+ // ids, which settings.js also resolved) still circulate in docs, skills and old
9
+ // messages, so settings.js asks this file first and sends a moved link on to the
10
+ // My agents anchor that holds the same setting (my-agents.js ANCHORS).
11
+ //
12
+ // PURE: no DOM, no fetch. tests/hall_settings_world.mjs requires it in node.
13
+
14
+ (function (root) {
15
+ 'use strict';
16
+
17
+ // old Settings anchor (and the old section id) → the My agents anchor
18
+ const MOVED = {
19
+ 'interaction': 'talk',
20
+ 'interaction-scroll': 'talk',
21
+ 'rendering': 'talk',
22
+ 'render': 'talk',
23
+ 'render-scroll': 'talk',
24
+ 'wandering': 'work',
25
+ 'wandering-scroll': 'work',
26
+ 'voices': 'skills',
27
+ 'voices-scroll': 'skills',
28
+ 'specialities': 'knows',
29
+ 'specialities-scroll': 'knows',
30
+ };
31
+
32
+ // '/my-agents#<anchor>' for a hash that left Settings, or null to stay.
33
+ function movedTarget(hash) {
34
+ const id = String(hash || '').replace(/^#/, '');
35
+ return Object.prototype.hasOwnProperty.call(MOVED, id) ? '/my-agents#' + MOVED[id] : null;
36
+ }
37
+
38
+ const api = { MOVED, movedTarget };
39
+ root.OTBSettingsMoved = api;
40
+ if (typeof module !== 'undefined' && module.exports) module.exports = api;
41
+ }(typeof window !== 'undefined' ? window : globalThis));
@@ -1,6 +1,6 @@
1
1
  /* settings.css — what Settings has and the rest of the panel family does not
2
2
  (task 1003308, goal 1000081; the archetype is panel.css). The grouped layout
3
- behind the section rail, the group head, the token ladder, the voices grid,
3
+ behind the section rail, the group head, the token ladder,
4
4
  the volume line and the image-key banner. Every colour is a `var()` of the
5
5
  world's tier; the one literal pair is the Discord mark, named below.
6
6
 
@@ -98,31 +98,7 @@
98
98
  .sessions-row__agent { display: inline; margin-left: 8px; }
99
99
  .sessions-row__when { display: block; }
100
100
 
101
- /* ---- Voices (per-skill model picker) ------------------------------------- */
102
- .voices-wrap { margin-top: var(--sp-sm); overflow-x: auto; }
103
- table.voices { width: 100%; border-collapse: collapse; text-align: left; font-size: 14px; color: var(--ink); }
104
- table.voices th, table.voices td {
105
- padding: var(--sp-xs) var(--sp-xs) var(--sp-xs) 0;
106
- vertical-align: middle;
107
- border-top: var(--line) solid var(--rule-soft);
108
- }
109
- table.voices thead th {
110
- padding-top: 0;
111
- border-top: 0;
112
- border-bottom: var(--line) solid var(--rule);
113
- font-family: var(--label-face);
114
- font-size: var(--label-size);
115
- font-weight: 400;
116
- letter-spacing: var(--label-space);
117
- text-transform: var(--label-case);
118
- color: var(--ink-faint);
119
- white-space: nowrap;
120
- }
121
- .voices__skill { white-space: nowrap; }
122
- .voices__skill code { font-family: var(--font-mono); font-size: 12.5px; color: var(--ink-soft); }
123
- .voices__default { margin-left: 0; font-family: var(--font-body); font-size: 14px; letter-spacing: 0; text-transform: none; color: var(--ink-soft); }
124
- td.voices__choice { width: 1%; white-space: nowrap; }
125
- select.voices__select { min-width: 140px; }
101
+ /* ---- empty and error lines (the per-skill voices table left with task 1005044) -- */
126
102
  .voices-empty, .craft-empty { padding: var(--sp-xs) 0; font-size: 13.5px; color: var(--ink-faint); }
127
103
 
128
104
  /* ---- Sounds: the volume line ------------------------------------------- */
@@ -157,8 +133,8 @@ select.voices__select { min-width: 140px; }
157
133
  .settings-btn--discord { background: #5865F2; border-color: #4853c4; color: #ffffff; }
158
134
  .settings-btn--discord:hover:not(:disabled) { background: #4853c4; border-color: #4853c4; color: #ffffff; }
159
135
 
160
- /* The specialities panel's rules moved to speciality-tools.css (task 1005052),
161
- which Settings links right after this sheet and My agents links too. */
136
+ /* The specialities panel's rules moved to speciality-tools.css (task 1005052);
137
+ only My agents links it since task 1005044. */
162
138
 
163
139
  /* ---- Software update (task 1004296) -------------------------------------- */
164
140
  /* A version is read digit by digit and compared against another, so it takes the mono
@@ -4,7 +4,7 @@
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
6
  <title>Settings — {{worldName}}</title>
7
- <meta name="description" content="Your preferences — connections, access keys, skill voices, and sounds.">
7
+ <meta name="description" content="Your preferences — connections, access keys, and sounds.">
8
8
  <!-- the hub's origin, stamped server-side (task 1004259): the Profile and
9
9
  privacy row links to its account page. Empty on an instance with no hub. -->
10
10
  <meta name="hub-origin" content="{{hubOrigin}}">
@@ -18,8 +18,6 @@
18
18
  has — the rail layout, the group head, the token ladder, the voices grid. -->
19
19
  <link rel="stylesheet" href="/builders/panel.css">
20
20
  <link rel="stylesheet" href="/builders/settings.css">
21
- <!-- the speciality tools sheet (task 1005052), shared with My agents -->
22
- <link rel="stylesheet" href="/builders/speciality-tools.css">
23
21
  </head>
24
22
  <body data-page="settings" data-page-title="Settings">
25
23
 
@@ -50,7 +48,7 @@
50
48
  <!-- Grouped layout (task 1723 → kit, task 2172): the sections sit in six
51
49
  groups behind a left sub-nav rail built by OTBKit.makeSectionRail
52
50
  (switch mode). settings.js wires the rail + per-panel anchor deep
53
- links (/settings#cli, /settings#voices, …); only the active group's
51
+ links (/settings#cli, /settings#art-key, …); only the active group's
54
52
  sections display. -->
55
53
  <div class="settings-layout" id="settings-layout">
56
54
  <nav class="section-rail" id="settings-rail" aria-label="Settings sections"></nav>
@@ -271,84 +269,19 @@
271
269
 
272
270
  <!-- ============ group: preferences ============ -->
273
271
 
274
- <!-- INTERACTION PROFILE — how replies are pitched for you (task 2010,
275
- delivered in task 1002514). GET/PATCH /api/bongos/me/interaction.
276
- Several independent fields, each its own single-select; the resolved
277
- contract is injected into every session by the conductor hook. No
278
- rank gate — this is ergonomics, not authority. -->
279
- <section class="scroll" id="interaction-scroll" aria-labelledby="interaction-h" data-group="preferences" hidden>
280
- <h2 id="interaction-h" class="scroll__h">How Claude talks to you</h2>
272
+ <!-- AGENT SETTINGS MOVED (task 1005044) — How Claude talks to you, your
273
+ specialities, Wandering and Rendering were edited here AND on My agents,
274
+ on the same routes. They live on My agents only now; this line is where
275
+ they were. Old deep links (#interaction, #wandering, #rendering, …) are
276
+ sent there by settings-moved.js. -->
277
+ <section class="scroll" id="agents-moved-preferences" aria-labelledby="agents-moved-preferences-h" data-group="preferences">
278
+ <h2 id="agents-moved-preferences-h" class="scroll__h">Your agents</h2>
281
279
  <p class="scroll__lede">
282
- How replies are pitched for you — the vocabulary assumed, how much
283
- hand-holding local tooling gets, how long an answer runs, and how much
284
- of the work behind it is narrated. These reach every session you start.
285
- The defaults assume no software-engineering background; change any of
286
- them and the rest stay as they are.
280
+ How Claude talks to you, wandering, session cards and your specialities are
281
+ set on <a href="/my-agents#talk">My agents</a>.
287
282
  </p>
288
- <div class="prows" id="interaction-rows"></div>
289
- <p class="settings-status" id="interaction-status" role="status" aria-live="polite"></p>
290
283
  </section>
291
284
 
292
- <!-- SPECIALITIES — a named bundle of knowledge + terms UNDER a craft
293
- (task 1003855, ADR 0296). GET/POST /api/bongos/specialities,
294
- POST /specialities/:id/{adopt,abandon,documents}. No rank gate:
295
- a speciality is how an expert's knowledge enters the platform,
296
- and gating that by rank would mean only trusted builders could
297
- be experts. -->
298
- <section class="scroll" id="specialities-scroll" aria-labelledby="specialities-h" data-group="preferences" hidden>
299
- <h2 id="specialities-h" class="scroll__h">Your specialities</h2>
300
- <p class="scroll__lede">
301
- A role says how you work. A speciality says what you work on — and how you,
302
- as someone who knows the subject, want to be engaged inside it. Whichever one
303
- you are using reaches every session where you hold a claim in that role.
304
- Train it by adding things you have written; it also picks things up on its own
305
- as you work.
306
- </p>
307
- <div id="speciality-suggestions"></div>
308
- <ul class="prows" id="specialities-rows"></ul>
309
-
310
- <!-- The create form is rendered by speciality-tools.js (task 1005052), the
311
- one copy Settings and My agents share; this is only its host. -->
312
- <form id="speciality-create" class="speciality-create"></form>
313
-
314
- <p class="settings-status" id="specialities-status" role="status" aria-live="polite"></p>
315
- </section>
316
-
317
- <!-- WANDERING — how readily the agent opens off-task threads (task 1268).
318
- GET/PATCH /api/bongos/me/wandering. Rank sets the default + ceiling; the
319
- server clamps, so options above the rank cap render disabled. -->
320
- <section class="scroll" id="wandering-scroll" aria-labelledby="wandering-h" data-group="preferences" hidden>
321
- <h2 id="wandering-h" class="scroll__h">Wandering</h2>
322
- <p class="scroll__lede">
323
- How readily Claude opens a <em>new thread</em> of work — a tangent, an
324
- investigation, an unprompted suggestion — instead of staying on your
325
- claimed task. It never limits the work on the task itself. Your rank
326
- sets the starting point; newcomers stay locked low.
327
- </p>
328
- <div class="prows" id="wander-rows" role="radiogroup" aria-labelledby="wandering-h"></div>
329
- <p class="settings-status" id="wandering-status" role="status" aria-live="polite"></p>
330
- <p class="section-note" id="wandering-note"></p>
331
- </section>
332
-
333
- <!-- RENDERING — how rich the session cards are (task 1279's toggle,
334
- a four-rung ladder since task 1002518). GET/PATCH
335
- /api/bongos/me/render; the rows are written by
336
- settings-render.js, not settings.js. The default rung is DERIVED
337
- from the builder's interaction profile, which is why the lede
338
- points at that panel rather than describing a fixed default. -->
339
- <section class="scroll" id="render-scroll" aria-labelledby="render-h" data-group="preferences" hidden>
340
- <h2 id="render-h" class="scroll__h">Rendering</h2>
341
- <p class="scroll__lede">
342
- How much your session cards — what <code>/builder-start</code>, claiming,
343
- and shipping show — spend on explaining themselves. Richer cards say more
344
- and cost more tokens; leaner ones carry the same facts for less. By default
345
- this follows how Claude talks to you, so you can set it once in
346
- <a href="#interaction">How Claude talks to you</a> and leave this alone.
347
- </p>
348
- <div class="sound-rows" id="render-rows"></div>
349
- <p class="settings-status" id="render-status" role="status" aria-live="polite"></p>
350
- <p class="section-note">Saves the moment you choose; applies from your next session.</p>
351
- </section>
352
285
 
353
286
  <!-- MODULE INSTALL REPORTS — the opt-out for counting your store-module
354
287
  installs in a module's Install and Reliability scores (task 1003793,
@@ -368,24 +301,13 @@
368
301
 
369
302
  <!-- ============ group: sound ============ -->
370
303
 
371
- <!-- VOICES — per-skill model picker (GET/PATCH /me/skill-prefs). -->
372
- <section class="scroll voices-scroll" id="voices-scroll" aria-labelledby="voices-h" data-group="sound" hidden>
373
- <h2 id="voices-h" class="scroll__h">Skill voices</h2>
304
+ <!-- SKILL VOICES MOVED (task 1005044) — the per-skill model picker lives on
305
+ My agents only now (Which models run → Per skill). -->
306
+ <section class="scroll" id="agents-moved-sound" aria-labelledby="agents-moved-sound-h" data-group="sound">
307
+ <h2 id="agents-moved-sound-h" class="scroll__h">Skill voices</h2>
374
308
  <p class="scroll__lede">
375
- Each slash-command can run on a different model. The system has a
376
- default for every skill; choose another to override it, or leave it
377
- on Default.
309
+ Which model each skill runs on is set on <a href="/my-agents#skills">My agents</a>.
378
310
  </p>
379
- <div class="voices-wrap">
380
- <table class="voices" id="voices-table">
381
- <thead>
382
- <tr><th scope="col">Skill</th><th scope="col">Default</th><th scope="col">Your choice</th></tr>
383
- </thead>
384
- <tbody id="voices-body"></tbody>
385
- </table>
386
- </div>
387
- <p class="settings-status" id="voices-status" role="status" aria-live="polite"></p>
388
- <p class="section-note">Changes save the moment you pick. “Default” clears your override and falls back to the system's choice.</p>
389
311
  </section>
390
312
 
391
313
  <!-- SOUNDS OFF — every notification sound is switched off for now (task 1004554);
@@ -480,25 +402,15 @@
480
402
  <!-- shared record overlay (#/idea|blocker/N) — every hall page carries it; this
481
403
  page was the one gap (task 2172). -->
482
404
  <script src="/builders/task-detail.js?v=2026-07-03-taskdetail"></script>
483
- <script src="/builders/settings-law-locks.js?v=2026-10-17-laws"></script>
484
- <script src="/builders/settings.js?v=2026-10-17-laws"></script>
405
+ <!-- task 1005044: the old deep links to the agent settings that moved to My agents -->
406
+ <script src="/builders/settings-moved.js?v=2026-11-03-moved"></script>
407
+ <script src="/builders/settings.js?v=2026-11-03-moved"></script>
485
408
  <!-- task 1003341: the Active sessions panel. Its own file rather than more of
486
409
  settings.js, which sits close to the 1500-line size ratchet. -->
487
410
  <script src="/builders/settings-sessions.js?v=2026-08-29-sessions"></script>
488
411
  <script src="/builders/settings-passkeys.js?v=2026-10-15-passkeys"></script>
489
412
  <script src="/builders/settings-age.js?v=2026-10-30-age"></script>
490
413
  <script src="/builders/settings-ai-keys.js?v=2026-10-28-ai-keys"></script>
491
- <!-- task 1002514: the interaction-profile panel ("How Claude talks to you"), on
492
- the same precedent and for the same reason — settings.js is against the
493
- 1500-line ratchet, and this panel shares nothing with the rest of the page. -->
494
- <script src="/builders/settings-interaction.js?v=2026-10-17-laws"></script>
495
- <!-- task 1005052: the speciality tools are ONE component Settings and My agents
496
- both mount (it was settings-specialities.js). Task 1005044 removes this mount. -->
497
- <script src="/builders/speciality-tools.js?v=2026-11-03-shared"></script>
498
- <!-- task 1002518: the card-richness ladder. Own file on the same precedent —
499
- the panel grew from one switch to a rung picker with a derived default, and
500
- settings.js is against the 1500-line ratchet. -->
501
- <script src="/builders/settings-render.js?v=2026-09-16-render-levels"></script>
502
414
  <!-- task 1004296: Settings → Software update. Own file on the same precedent. -->
503
415
  <!-- the Update pill's flow, which the panel's Update button runs in place (task 1005041) -->
504
416
  <script src="/builders/update-pill.js?v=2026-11-03-pill"></script>