@bongos/core 1.24.37 → 1.24.38

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 (51) hide show
  1. package/.bongos-core.json +55 -55
  2. package/docs/copy-inventory.md +21 -21
  3. package/docs/copy-registry.json +23 -23
  4. package/docs/module-api-changelog.md +2 -0
  5. package/docs/page-readings.json +340 -341
  6. package/modules/hall-ui/public/ai-studio.html +2 -2
  7. package/modules/hall-ui/public/atlas.html +2 -2
  8. package/modules/hall-ui/public/blockers.html +2 -2
  9. package/modules/hall-ui/public/board-room.html +2 -2
  10. package/modules/hall-ui/public/city.html +2 -2
  11. package/modules/hall-ui/public/collab.html +2 -2
  12. package/modules/hall-ui/public/commands.html +2 -2
  13. package/modules/hall-ui/public/copy-desk.html +2 -2
  14. package/modules/hall-ui/public/craft-mode.js +5 -3
  15. package/modules/hall-ui/public/deploy.html +2 -2
  16. package/modules/hall-ui/public/gate.html +2 -2
  17. package/modules/hall-ui/public/goal-map.html +2 -2
  18. package/modules/hall-ui/public/goals.html +2 -2
  19. package/modules/hall-ui/public/government.html +2 -2
  20. package/modules/hall-ui/public/idea.html +2 -2
  21. package/modules/hall-ui/public/ideas.html +2 -2
  22. package/modules/hall-ui/public/index.html +2 -2
  23. package/modules/hall-ui/public/market-watch-item.html +2 -2
  24. package/modules/hall-ui/public/market-watch-rules.html +2 -2
  25. package/modules/hall-ui/public/market-watch.html +2 -2
  26. package/modules/hall-ui/public/modules.html +2 -2
  27. package/modules/hall-ui/public/money.html +2 -2
  28. package/modules/hall-ui/public/my-agents.html +2 -2
  29. package/modules/hall-ui/public/primer.html +2 -2
  30. package/modules/hall-ui/public/profile.html +2 -2
  31. package/modules/hall-ui/public/project-settings.html +2 -2
  32. package/modules/hall-ui/public/roadmap.html +2 -2
  33. package/modules/hall-ui/public/roster.html +2 -2
  34. package/modules/hall-ui/public/sessions.html +2 -2
  35. package/modules/hall-ui/public/settings.html +2 -2
  36. package/modules/hall-ui/public/shell.js +106 -89
  37. package/modules/hall-ui/public/street.html +2 -2
  38. package/modules/hall-ui/public/studio.html +2 -2
  39. package/modules/hall-ui/public/task.html +2 -2
  40. package/modules/hall-ui/public/thinking.html +2 -2
  41. package/modules/hall-ui/public/tweak-editor.html +2 -2
  42. package/modules/hall-ui/public/watch.html +2 -2
  43. package/modules/hall-ui/public/work.html +2 -2
  44. package/package-lock.json +2 -2
  45. package/package.json +1 -1
  46. package/release-notes.json +6 -0
  47. package/src/module-api.js +1 -1
  48. package/tests/craft_mode_nav.mjs +12 -10
  49. package/tests/goal_map_page.mjs +5 -2
  50. package/tests/hall_nav.mjs +20 -13
  51. package/tests/nav_permission_atoms.mjs +1 -1
@@ -243,7 +243,10 @@ test('sidebar groups read by audience, in order', () => {
243
243
  // 'Archon' → 'Governance' in ADR 0157 (the group's pages opened to Metic, so a header
244
244
  // naming the top rank was wrong), then → 'Government' by ADR 0174: a header
245
245
  // reading "Archon" over items a Metic can open would misdescribe the ladder.
246
- assert.deepEqual(nav.map((g) => g.label), ['', 'You', 'Community', 'Docs', 'Government']);
246
+ // task 1005071 (owner decision 2026-11-04, from the sitemap audit): every group is
247
+ // labelled, and the old unlabeled project group split into Work, Make and Govern.
248
+ // Docs became Help; Government became Run the project.
249
+ assert.deepEqual(nav.map((g) => g.label), ['Work', 'Make', 'Community', 'You', 'Govern', 'Run the project', 'Help']);
247
250
  // task 1003113 (R02 of goal 1000074): 'copy-desk' joins the unlabeled group,
248
251
  // after Tasks. It belongs with the project's own work and not in Docs — it is a
249
252
  // QUEUE somebody acts on, not reference material — and not in You or Community,
@@ -285,12 +288,15 @@ test('sidebar groups read by audience, in order', () => {
285
288
  // task 1004939 (goal 1000137): 'market-watch' joins last — the project's scouts on its
286
289
  // market, so its subject is the project. Module-gated: it is dropped wherever the
287
290
  // default-off market-watch module is not enabled (this boot reports no module state).
288
- assert.deepEqual(nav[0].items.map((i) => i.id), ['home', 'roadmap', 'goals', 'goal-map', 'work', 'blockers', 'board-room', 'city', 'thinking', 'studio', 'market-watch'],
289
- 'the unlabeled group is the project itself (task 1002425 order)');
291
+ // task 1005071: the project group split three ways. Work is the project's state;
292
+ // Make is where things get made; Govern is the board's rooms.
293
+ assert.deepEqual(nav[0].items.map((i) => i.id), ['home', 'work', 'goals', 'goal-map', 'roadmap', 'blockers', 'thinking'],
294
+ 'Work = the project itself (task 1005071 order)');
295
+ assert.deepEqual(nav[1].items.map((i) => i.id), ['studio', 'market-watch'], 'Make = where things get made');
290
296
  // task 1004685 (the living-city prototype, round-3 board 6): 'my-agents' joins You —
291
297
  // how your own Claude works for you, the personal half of "the city steers
292
298
  // everyone, My agents steers yours". Its subject is the viewer's own agents.
293
- assert.deepEqual(nav[1].items.map((i) => i.id), ['standing', 'profile', 'my-agents'], 'You = your own numbers and your own agents');
299
+ assert.deepEqual(nav[3].items.map((i) => i.id), ['standing', 'profile', 'my-agents'], 'You = your own numbers and your own agents');
294
300
  // task 1003444: 'people' LEFT the group — the owner deleted the hall's
295
301
  // cross-project directory (ADR 0337 D5); its home is the hub, and /people
296
302
  // redirects to /roster. Builders is the hall's directory now.
@@ -305,19 +311,20 @@ test('sidebar groups read by audience, in order', () => {
305
311
  // 'leaderboard') and is now a real page at /roster labelled Builders. That is
306
312
  // what made this group read as one real page plus a link into the home page.
307
313
  assert.deepEqual(nav[2].items.map((i) => i.id), ['collab', 'roster'], 'Community = everyone else, in this project');
314
+ assert.deepEqual(nav[4].items.map((i) => i.id), ['city', 'board-room'], 'Govern = the board\'s rooms, the city first');
308
315
  assert.ok(!nav.flatMap((g) => g.items).some((i) => /^\/people\b/.test(i.href)), 'no nav item points at the deleted /people');
309
316
  // task 1004473: 'commands' — every skill and CLI verb, read live — is reference
310
317
  // material that reads the same for every builder, so it joins Docs.
311
318
  // task 1005046 (owner decision 2026-11-03, idea 1001311): ONE reading room. Ranks,
312
319
  // Economy and Diagrams explained what the Primer explains; they are its chapters
313
320
  // now, so Docs is the Primer and the four references that are not a document.
314
- assert.deepEqual(nav[3].items.map((i) => i.id),
321
+ assert.deepEqual(nav[6].items.map((i) => i.id),
315
322
  ['primer', 'commands', 'atlas', 'modules', 'apidocs'], 'Docs = reference material');
316
323
  // 'government' (the Permissions tab, BV1.R113) is the group's one archon-gated item.
317
324
  // 'project-settings' joins the Government group at the metic floor (task 1003280,
318
325
  // goal 1000072) — it sits before 'government', which is the one archon-only item.
319
326
  // 'board-room' LED this group from the ADR 0266 carve until task 1003744 moved
320
- // it to the project group — see the note on nav[0]. What is left is rank surface
327
+ // it to the project group — see the note on Govern (nav[4]). What is left is rank surface
321
328
  // throughout, which is what lets the group keep its metic head honestly.
322
329
  // 'deploy' (task 1003159, ADR 0293) is the SECOND archon item, beside 'government':
323
330
  // its gate is the `core.pin.move` atom, archon-floor and system:true. It sits with
@@ -328,7 +335,7 @@ test('sidebar groups read by audience, in order', () => {
328
335
  // 'market-watch-settings' (task 1004938) LEFT the group in task 1005045: the owner saw
329
336
  // "Market Watch" twice and had to guess which was which (owner decision 2026-11-03,
330
337
  // idea 1001310). The settings are an owner-only Settings tab on /market-watch now.
331
- assert.deepEqual(nav[4].items.map((i) => i.id), ['watch', 'gate', 'sessions', 'project-settings', 'money', 'deploy', 'government']);
338
+ assert.deepEqual(nav[5].items.map((i) => i.id), ['watch', 'gate', 'sessions', 'project-settings', 'money', 'deploy', 'government']);
332
339
  // task 1005045: and no label is left twice anywhere in the sidebar, so the next pair
333
340
  // fails here instead of in front of the owner.
334
341
  const labels = [...boot().sidebarHtml.matchAll(/<a class="nav-item" [^>]*>[\s\S]*?<span class="nav-item__label">([^<]*)<\/span>/g)].map((m) => m[1]);
@@ -355,7 +362,7 @@ test('Ranks, Economy and Diagrams are Primer chapters, not pages', () => {
355
362
  for (const f of ['ranks.html', 'drachmae.html', 'diagrams.html']) {
356
363
  assert.ok(!fs.existsSync(path.join(HALL, f)), `${f} left the hall`);
357
364
  }
358
- const primer = nav.find((g) => g.label === 'Docs').items.find((i) => i.id === 'primer');
365
+ const primer = nav.find((g) => g.label === 'Help').items.find((i) => i.id === 'primer');
359
366
  assert.equal(primer.href, '/primer', 'the Primer is the reading room the three became');
360
367
  });
361
368
 
@@ -564,11 +571,11 @@ test('collapsible groups carry a stable storage key (collapse persistence)', ()
564
571
  // hall-nav-collapsed storage key, so any builder who had collapsed the old "archon"
565
572
  // group gets the new one expanded once — cosmetic, and preferable to keeping a stale
566
573
  // slug that no longer matches the visible label.
567
- for (const g of ['you', 'community', 'docs', 'government']) {
574
+ // task 1005071: a label with spaces hyphenates, so the key stays a valid id.
575
+ for (const g of ['work', 'make', 'community', 'you', 'govern', 'run-the-project', 'help']) {
568
576
  assert.match(html, new RegExp(`data-group="${g}"`), `${g} is collapsible (hall-nav-collapsed key)`);
569
577
  }
570
- assert.ok(!/nav-group--collapsible[^>]*>(?!<button)/.test(html.split('<div class="nav-group')[1] || ''),
571
- 'the unlabeled project group stays always-expanded');
578
+ assert.ok(!/aria-controls="[^"]* /.test(html), 'no aria-controls id carries a space');
572
579
  });
573
580
 
574
581
  // ── a nav item can carry a COUNT badge (task 1003737) ───────────────────────
@@ -780,7 +787,7 @@ test('no glyph path data reads as an IP address to the release leak scan', () =>
780
787
  // block (task 1004713). These drive the real shell and the real gov-positions.js.
781
788
 
782
789
  const tick = () => new Promise((resolve) => setImmediate(resolve));
783
- const GOVERNING = ['board-room', 'city', 'watch', 'gate', 'sessions', 'project-settings', 'money', 'deploy', 'government'];
790
+ const GOVERNING = ['city', 'board-room', 'watch', 'gate', 'sessions', 'project-settings', 'money', 'deploy', 'government'];
784
791
  const lead = (building, title) => ({ kind: 'lead', seat: 'lead:' + building, building, title });
785
792
  const block = (held) => ({ held, title: held.length ? held[0].title : null, has_position: held.length > 0 });
786
793
 
@@ -799,7 +806,7 @@ test('POSITION: exactly the governing surfaces carry the flag — the City, the
799
806
  const html = boot().sidebarHtml;
800
807
  const flagged = [...html.matchAll(/id="nav-([^"]+)"[^>]*data-position="1"/g)].map((m) => m[1]);
801
808
  assert.deepEqual(flagged, GOVERNING);
802
- assert.match(html, /class="nav-group__head" data-gate="government" data-position="1" data-group="government"/,
809
+ assert.match(html, /class="nav-group__head" data-gate="government" data-position="1" data-group="run-the-project"/,
803
810
  'the Government head carries it too, so no label is left over an emptied group');
804
811
  const nav = parseNav(html);
805
812
  assert.ok(!nav.find((g) => g.label === 'You').items.some((i) => flagged.includes(i.id)), 'your own pages never need a seat');
@@ -96,7 +96,7 @@ test('the hall-preview fixture carries every atom /me resolves', () => {
96
96
  // Market Watch settings nav item and its fuel glyph; task 1005041: the Update pill replaced the
97
97
  // core-update banner; task 1005045: the Market Watch settings item left (one sidebar item);
98
98
  // task 1005046: Ranks, Economy and Diagrams left Docs (one reading room, the Primer).
99
- const SHELL_SHA = '662e036a340ad33f';
99
+ const SHELL_SHA = 'baf8a15f025eba68';
100
100
 
101
101
  test('shell.js has not changed without its cache-bust being bumped', () => {
102
102
  const actual = crypto.createHash('sha256').update(SHELL).digest('hex').slice(0, 16);