@bongos/core 1.21.77 → 1.21.79

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 (73) hide show
  1. package/.bongos-core.json +103 -73
  2. package/.claude/skills/goal-create/SKILL.md +2 -1
  3. package/clients/bongos-client/README.md +1 -1
  4. package/clients/bongos-client/bongos-client.global.js +8 -0
  5. package/clients/bongos-client/index.cjs +8 -0
  6. package/clients/bongos-client/index.d.ts +13 -0
  7. package/clients/bongos-client/index.mjs +8 -0
  8. package/docs/api/openapi.json +285 -3
  9. package/docs/api-reference.md +6 -2
  10. package/docs/copy-inventory.md +48 -38
  11. package/docs/copy-registry.json +152 -61
  12. package/docs/module-api-changelog.md +4 -0
  13. package/docs/page-inventory.json +4 -2
  14. package/docs/page-readings.json +215 -206
  15. package/migrations/core_273_module_install_reports.sql +66 -0
  16. package/modules/hall-ui/public/atlas.html +1 -1
  17. package/modules/hall-ui/public/blockers.html +1 -1
  18. package/modules/hall-ui/public/board-room.html +1 -1
  19. package/modules/hall-ui/public/city.html +1 -1
  20. package/modules/hall-ui/public/collab.html +1 -1
  21. package/modules/hall-ui/public/commands.html +1 -1
  22. package/modules/hall-ui/public/copy-desk.html +1 -1
  23. package/modules/hall-ui/public/deploy.html +1 -1
  24. package/modules/hall-ui/public/diagrams.html +1 -1
  25. package/modules/hall-ui/public/drachmae.html +1 -1
  26. package/modules/hall-ui/public/fleet.html +1 -1
  27. package/modules/hall-ui/public/gate.html +1 -1
  28. package/modules/hall-ui/public/goal-map.html +1 -1
  29. package/modules/hall-ui/public/goals-page.js +13 -1
  30. package/modules/hall-ui/public/goals-render.js +1 -1
  31. package/modules/hall-ui/public/goals.html +1 -1
  32. package/modules/hall-ui/public/government.html +1 -1
  33. package/modules/hall-ui/public/idea.html +1 -1
  34. package/modules/hall-ui/public/ideas.html +1 -1
  35. package/modules/hall-ui/public/index.html +1 -1
  36. package/modules/hall-ui/public/modules.html +1 -1
  37. package/modules/hall-ui/public/primer.html +1 -1
  38. package/modules/hall-ui/public/profile.html +1 -1
  39. package/modules/hall-ui/public/project-settings.html +1 -1
  40. package/modules/hall-ui/public/ranks.html +1 -1
  41. package/modules/hall-ui/public/roadmap.html +1 -1
  42. package/modules/hall-ui/public/roster.html +1 -1
  43. package/modules/hall-ui/public/sessions.html +1 -1
  44. package/modules/hall-ui/public/settings-usage-reports.js +96 -0
  45. package/modules/hall-ui/public/settings.html +19 -1
  46. package/modules/hall-ui/public/settings.states.json +1 -0
  47. package/modules/hall-ui/public/shell.js +61 -29
  48. package/modules/hall-ui/public/street.html +1 -1
  49. package/modules/hall-ui/public/studio.html +1 -1
  50. package/modules/hall-ui/public/task-lib.js +21 -2
  51. package/modules/hall-ui/public/task.html +1 -1
  52. package/modules/hall-ui/public/thinking.html +1 -1
  53. package/modules/hall-ui/public/tweak-editor.html +1 -1
  54. package/modules/hall-ui/public/watch.html +1 -1
  55. package/modules/hall-ui/public/work.html +1 -1
  56. package/package-lock.json +2 -2
  57. package/package.json +1 -1
  58. package/release-notes.json +24 -0
  59. package/scripts/gds/module-assess-installs.js +143 -0
  60. package/scripts/gds/module.js +29 -5
  61. package/scripts/hall-preview/live-identity.js +1 -0
  62. package/src/bongos/module-usage-reports.js +112 -0
  63. package/src/bongos/routes/modules.js +96 -0
  64. package/src/module-api.js +1 -1
  65. package/tests/goal_map_page.mjs +1 -1
  66. package/tests/goal_plan_with_claude.mjs +41 -0
  67. package/tests/hall_commands.mjs +1 -1
  68. package/tests/hall_nav.mjs +42 -0
  69. package/tests/hall_tweak_editor.mjs +1 -1
  70. package/tests/module_assess_installs.mjs +272 -0
  71. package/tests/module_install.mjs +3 -0
  72. package/tests/module_update.mjs +3 -0
  73. package/tests/nav_permission_atoms.mjs +1 -1
@@ -0,0 +1,66 @@
1
+ -- core_273_module_install_reports.sql — the raw reports behind a module's
2
+ -- Install and Reliability parts: did an install work, and how many runtime
3
+ -- errors a version threw on a day.
4
+ --
5
+ -- task 1003793 (goal 1000091, working area 5). ADR 0343 D1 names Install and
6
+ -- Reliability as the parts an author cannot fake, because they come from real
7
+ -- installs. core_265's module_assessment_signals holds FINISHED per-part scores,
8
+ -- not the per-holder reports those scores are worked out from, so the reports
9
+ -- need a place of their own.
10
+ --
11
+ -- Privacy (owner decision, Will, 2026-10-01): COUNTS ONLY, ON BY DEFAULT, WITH
12
+ -- AN OPT-OUT. A report carries only
13
+ -- (a) whether an install worked: yes/no plus a short error CODE, and
14
+ -- (b) a daily count of runtime errors per module version.
15
+ -- No error text, no file paths, no user data — the columns below have nowhere
16
+ -- to put any, and error_code is held to a short lowercase code by a CHECK so a
17
+ -- free-text message cannot be smuggled in through it.
18
+ --
19
+ -- module_install_reports one row per (version, holder): that holder's LATEST
20
+ -- install or update attempt of the version (the same
21
+ -- holder identity as module_entitlements, core_259). A
22
+ -- new attempt replaces the row, so the table grows with
23
+ -- holders, never with retries, and Install is scored
24
+ -- from it without scanning a history. ok = true carries
25
+ -- no code; ok = false carries one.
26
+ -- module_runtime_error_counts one row per (version, holder, day): how many
27
+ -- runtime errors that version threw for that holder on
28
+ -- that day. A second report for the same day replaces
29
+ -- the count rather than adding a row.
30
+ -- module_usage_report_optouts a holder that has switched reporting off. No
31
+ -- row = reporting on (the default). The store drops a
32
+ -- report from an opted-out holder at intake, so the
33
+ -- switch holds whatever client sends the report.
34
+ --
35
+ -- Additive only (new tables), so forward-safe. Idempotent: safe to re-run.
36
+
37
+ CREATE TABLE IF NOT EXISTS module_install_reports (
38
+ version_id bigint NOT NULL REFERENCES store_module_versions(id) ON DELETE CASCADE,
39
+ holder_kind text NOT NULL CHECK (holder_kind IN ('builder', 'instance')),
40
+ holder_ref text NOT NULL,
41
+ ok boolean NOT NULL,
42
+ error_code text CHECK (error_code ~ '^[a-z][a-z0-9_]{0,39}$'),
43
+ reported_at timestamptz NOT NULL DEFAULT now(),
44
+ CHECK ((ok AND error_code IS NULL) OR (NOT ok AND error_code IS NOT NULL)),
45
+ PRIMARY KEY (version_id, holder_kind, holder_ref)
46
+ );
47
+
48
+ CREATE TABLE IF NOT EXISTS module_runtime_error_counts (
49
+ version_id bigint NOT NULL REFERENCES store_module_versions(id) ON DELETE CASCADE,
50
+ holder_kind text NOT NULL CHECK (holder_kind IN ('builder', 'instance')),
51
+ holder_ref text NOT NULL,
52
+ day date NOT NULL,
53
+ error_count integer NOT NULL CHECK (error_count >= 0),
54
+ reported_at timestamptz NOT NULL DEFAULT now(),
55
+ PRIMARY KEY (version_id, holder_kind, holder_ref, day)
56
+ );
57
+
58
+ CREATE TABLE IF NOT EXISTS module_usage_report_optouts (
59
+ holder_kind text NOT NULL CHECK (holder_kind IN ('builder', 'instance')),
60
+ holder_ref text NOT NULL,
61
+ opted_out_at timestamptz NOT NULL DEFAULT now(),
62
+ PRIMARY KEY (holder_kind, holder_ref)
63
+ );
64
+
65
+ INSERT INTO schema_migrations (version) VALUES ('core_273_module_install_reports')
66
+ ON CONFLICT (version) DO NOTHING;
@@ -93,7 +93,7 @@
93
93
 
94
94
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
95
95
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
96
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
96
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
97
97
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
98
98
  <script src="/builders/palette.js" defer></script>
99
99
  <script src="/builders/atlas.js?v=2026-09-02-index" defer></script>
@@ -52,7 +52,7 @@
52
52
  chrome exists before the page script runs. -->
53
53
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
54
54
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
55
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
55
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
56
56
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
57
57
  <script src="/builders/palette.js" defer></script>
58
58
  <!-- shared frontend toolkit (window.OTB — rank labels, number formats) + the
@@ -62,7 +62,7 @@
62
62
 
63
63
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
64
64
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
65
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
65
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
66
66
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
67
67
  <script src="/builders/palette.js" defer></script>
68
68
  <script src="/builders/dom-utils.js?v=2026-06-16-board"></script>
@@ -85,7 +85,7 @@
85
85
 
86
86
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
87
87
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
88
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
88
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
89
89
  <script src="/builders/palette.js" defer></script>
90
90
  <script src="/builders/city-draw.js?v=2026-10-04-pins1"></script>
91
91
  <script src="/builders/city.js?v=2026-10-04-pins1"></script>
@@ -150,7 +150,7 @@
150
150
 
151
151
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
152
152
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
153
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
153
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
154
154
  <script src="/builders/palette.js" defer></script>
155
155
  <script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
156
156
  <script src="/builders/collab-lib.js?v=2026-09-24-archive"></script>
@@ -56,7 +56,7 @@
56
56
 
57
57
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
58
58
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
59
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
59
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
60
60
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
61
61
  <script src="/builders/palette.js" defer></script>
62
62
  <script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
@@ -179,7 +179,7 @@
179
179
 
180
180
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
181
181
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
182
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
182
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
183
183
  <script src="/builders/palette.js" defer></script>
184
184
  <script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
185
185
  <script src="/builders/hall-kit.js"></script>
@@ -76,7 +76,7 @@
76
76
 
77
77
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
78
78
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
79
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
79
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
80
80
  <script src="/builders/palette.js" defer></script>
81
81
  <script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
82
82
  <script src="/builders/hall-kit.js"></script>
@@ -99,7 +99,7 @@
99
99
  time so the chrome exists before the deferred page scripts execute. -->
100
100
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
101
101
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
102
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
102
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
103
103
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
104
104
  <script src="/builders/palette.js" defer></script>
105
105
  <script src="/builders/diagram-viewer.js?v=2026-06-14-diagviewer-1" defer></script>
@@ -100,7 +100,7 @@
100
100
 
101
101
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
102
102
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
103
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
103
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
104
104
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
105
105
  <script src="/builders/palette.js" defer></script>
106
106
  <script src="/builders/md-reader.js?v=2026-09-02-mdreader-2"></script>
@@ -56,7 +56,7 @@
56
56
 
57
57
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
58
58
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
59
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
59
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
60
60
  <script src="/builders/palette.js" defer></script>
61
61
  <script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
62
62
  <script src="/builders/hall-kit.js"></script>
@@ -79,7 +79,7 @@
79
79
 
80
80
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
81
81
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
82
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
82
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
83
83
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
84
84
  <script src="/builders/palette.js" defer></script>
85
85
  <script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
@@ -139,7 +139,7 @@
139
139
 
140
140
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
141
141
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
142
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
142
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
143
143
  <script src="/builders/palette.js" defer></script>
144
144
 
145
145
  <script src="/builders/idea-objects.js?v=2026-09-27-split"></script>
@@ -31,7 +31,7 @@
31
31
  // below reads exactly as before; the single copy lives in task-lib.js.
32
32
  const {
33
33
  priorityRank, touchesConflict, rankTagHtml, deHashRefs,
34
- creditsPerMinute, buildPromptForTask, friendlyBatchReason,
34
+ creditsPerMinute, buildPromptForTask, buildPlanPromptForGoal, friendlyBatchReason,
35
35
  } = window.OTBTaskLib;
36
36
  // Shared component kit (hall-kit.js, task 2166): pager, filter bar, tabs,
37
37
  // empty/skeleton states — adopted here by task 2171.
@@ -404,6 +404,18 @@
404
404
  } catch (_e) { return false; }
405
405
  }
406
406
  }
407
+ // task 1004587 (ADR 0366 D4) — the optional "Plan with Claude" hand-off; every planning form works without it.
408
+ async function planWithClaude() {
409
+ const d = state.details.get(String(state.current));
410
+ if (!d) return;
411
+ // The spec task is found in the goal's task list, so wait for it: copying early would hand back the fallback prompt for a goal that has a spec task.
412
+ if (!state.workLoaded) return toast("Still loading this goal's tasks. Try again in a moment.");
413
+ const g = d.goal;
414
+ const ok = await copyText(buildPlanPromptForGoal(g, state.work.todo));
415
+ toast(ok ? 'Prompt copied. Paste it into a Claude Code session to plan this goal.' : 'Could not copy to the clipboard. Try again.');
416
+ }
417
+ // The button is drawn by renderActions (which re-draws it), so the click is delegated.
418
+ document.addEventListener('click', (e) => { if (e.target.closest && e.target.closest('#goal-plan-btn')) planWithClaude(); });
407
419
  async function copyPromptForTask(taskId, btn) {
408
420
  const t = state.work.todo.find((x) => String(x.id) === String(taskId));
409
421
  if (!t) return;
@@ -962,7 +962,7 @@
962
962
  if (canManage && g.status === 'open') {
963
963
  parts.push('<button class="btn-ghost" id="goal-archive-btn" type="button" title="Retire this goal — you will be asked what happens to any unfinished work">Archive goal</button>');
964
964
  }
965
- if (g.status === 'open') {
965
+ if (g.status === 'open') { parts.push('<button class="btn-ghost" id="goal-plan-btn" type="button" title="Copies a prompt to paste into a Claude Code session">Plan with Claude</button>'); // task 1004587
966
966
  if (joined) {
967
967
  parts.push('<button class="btn-ghost" id="goal-leave-btn" type="button">Leave goal</button>');
968
968
  } else if ((g.visibility === 'private' || g.scope_protected) && !isArchon()) {
@@ -232,7 +232,7 @@
232
232
 
233
233
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
234
234
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
235
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
235
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
236
236
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
237
237
  <script src="/builders/palette.js" defer></script>
238
238
  <script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
@@ -136,7 +136,7 @@
136
136
 
137
137
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
138
138
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
139
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
139
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></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>
@@ -52,7 +52,7 @@
52
52
 
53
53
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
54
54
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
55
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
55
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></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
@@ -227,7 +227,7 @@
227
227
 
228
228
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
229
229
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
230
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
230
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></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
@@ -108,7 +108,7 @@
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
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-city-tab" defer></script>
111
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix" 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.
@@ -103,7 +103,7 @@
103
103
 
104
104
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
105
105
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
106
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
106
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></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>
@@ -117,7 +117,7 @@
117
117
 
118
118
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
119
119
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
120
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
120
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
121
121
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
122
122
  <script src="/builders/palette.js" defer></script>
123
123
  <!-- the shared markdown reader (window.OTBMdReader) — primer.js renders through
@@ -209,7 +209,7 @@
209
209
  chrome exists before the page script runs. -->
210
210
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
211
211
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
212
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
212
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
213
213
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
214
214
  <script src="/builders/palette.js" defer></script>
215
215
  <!-- shared frontend toolkit (window.OTB) — loaded before profile.js, which pulls from it. -->
@@ -72,7 +72,7 @@
72
72
 
73
73
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
74
74
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
75
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
75
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
76
76
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
77
77
  <script src="/builders/palette.js" defer></script>
78
78
  <script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
@@ -79,7 +79,7 @@
79
79
  chrome exists before the page script runs. -->
80
80
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
81
81
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
82
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
82
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
83
83
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
84
84
  <script src="/builders/palette.js" defer></script>
85
85
  <!-- shared frontend toolkit (window.OTB) — loaded before ranks.js, which pulls from it. -->
@@ -43,7 +43,7 @@
43
43
 
44
44
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
45
45
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
46
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
46
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
47
47
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
48
48
  <script src="/builders/palette.js" defer></script>
49
49
  <script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
@@ -55,7 +55,7 @@
55
55
  chrome exists before the page script runs. -->
56
56
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
57
57
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
58
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
58
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
59
59
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
60
60
  <script src="/builders/palette.js" defer></script>
61
61
  <!-- shared frontend toolkit (window.OTB — rank labels, number formats) + the
@@ -113,7 +113,7 @@
113
113
  chrome exists before the page script runs. -->
114
114
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
115
115
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
116
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
116
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
117
117
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
118
118
  <script src="/builders/palette.js" defer></script>
119
119
  <!-- shared frontend toolkit (window.OTB) — loaded BEFORE sessions.js so it can pull from it. -->
@@ -0,0 +1,96 @@
1
+ // modules/hall-ui/public/settings-usage-reports.js — the "Module install reports"
2
+ // panel on /builders/settings: the switch that stops your module installs being
3
+ // counted in a module's store score (task 1003793, ADR 0343 D1).
4
+ //
5
+ // WHY IT EXISTS. A store module's Install and Reliability scores come from real
6
+ // installs reporting back. The owner's privacy posture (2026-10-01) is counts
7
+ // only, on by default, with an opt-out — this is the opt-out. The server holds
8
+ // the switch and drops a report from someone who turned it off, so this panel
9
+ // only reads and writes GET/POST /store/usage-reporting; it decides nothing.
10
+ //
11
+ // Own file on the settings-render.js precedent: settings.js is against the
12
+ // 1500-line ratchet, and this panel shares nothing with the rest of the page.
13
+
14
+ (() => {
15
+ 'use strict';
16
+
17
+ const API = '/api/bongos';
18
+ const { $ } = window.OTB;
19
+ const toast = (msg) => window.OTB.toast(msg);
20
+ const api = window.BongosClient.createClient({ baseUrl: '', credentials: 'same-origin', throwOnError: false });
21
+
22
+ const toAuth = () => window.location.assign(`${API}/auth/web/start`);
23
+
24
+ const CHOICES = [
25
+ { value: 'on', label: 'Share counts', desc: 'When you install or update a store module, the store learns whether it worked. Nothing else is sent.' },
26
+ { value: 'off', label: 'Don’t share', desc: 'Your installs are left out of every module’s score.' },
27
+ ];
28
+
29
+ function render(enabled) {
30
+ const wrap = $('#usage-reports-rows');
31
+ if (!wrap) return;
32
+ const current = enabled ? 'on' : 'off';
33
+ wrap.innerHTML =
34
+ '<fieldset class="pgroup" id="usage-reports-group">' +
35
+ '<legend class="prow__label">Share what happens when you install a module</legend>' +
36
+ CHOICES.map((c) => {
37
+ const id = `usage-reports-${c.value}`;
38
+ return (
39
+ `<label class="prow prow--pick" for="${id}">` +
40
+ `<input class="pradio" type="radio" name="usage-reports" id="${id}"` +
41
+ ` value="${c.value}"${current === c.value ? ' checked' : ''}>` +
42
+ '<span class="prow__main">' +
43
+ `<span class="prow__label">${c.label}${c.value === 'on' ? '<span class="prow__tag">default</span>' : ''}</span>` +
44
+ `<span class="prow__desc">${c.desc}</span>` +
45
+ '</span></label>'
46
+ );
47
+ }).join('') +
48
+ '</fieldset>';
49
+ }
50
+
51
+ async function save(value, input) {
52
+ const status = $('#usage-reports-status');
53
+ if (status) status.textContent = 'Saving…';
54
+ if (input) input.disabled = true;
55
+ try {
56
+ const res = await api.request('POST', `${API}/store/usage-reporting`, { body: { enabled: value === 'on' } });
57
+ if (res.status === 401) { toAuth(); return; }
58
+ if (!res.ok) throw new Error(`usage-reporting POST → ${res.status}`);
59
+ render(res.data.enabled);
60
+ const msg = res.data.enabled
61
+ ? 'Saved — your module installs count toward their scores.'
62
+ : 'Saved — your module installs are no longer reported.';
63
+ if (status) status.textContent = msg;
64
+ toast(msg);
65
+ } catch (err) {
66
+ console.error('[settings] save usage reporting failed', err);
67
+ if (status) status.textContent = 'Could not save. Try again.';
68
+ toast('Could not save whether to share your install results. Try again.');
69
+ if (input) input.disabled = false;
70
+ }
71
+ }
72
+
73
+ async function setup() {
74
+ try {
75
+ const res = await api.request('GET', `${API}/store/usage-reporting`);
76
+ if (res.status === 401) { toAuth(); return; }
77
+ if (!res.ok) throw new Error(`usage-reporting GET → ${res.status}`);
78
+ render(res.data.enabled !== false);
79
+ $('#usage-reports-scroll').hidden = false;
80
+ $('#usage-reports-rows').addEventListener('change', (e) => {
81
+ const r = e.target.closest('.pradio');
82
+ if (!r || r.disabled || !r.checked) return;
83
+ save(r.value, r);
84
+ });
85
+ } catch (err) {
86
+ // Its own try/catch, like every other section: a failing endpoint shows
87
+ // this panel's own error rather than taking the settings page down.
88
+ console.error('[settings] failed to load usage reporting', err);
89
+ $('#usage-reports-scroll').hidden = false;
90
+ $('#usage-reports-rows').innerHTML =
91
+ '<p class="voices-empty">Whether you share your install results could not be loaded. Reload the page to try again.</p>';
92
+ }
93
+ }
94
+
95
+ setup();
96
+ })();
@@ -332,6 +332,22 @@
332
332
  <p class="section-note">Saves the moment you choose; applies from your next session.</p>
333
333
  </section>
334
334
 
335
+ <!-- MODULE INSTALL REPORTS — the opt-out for counting your store-module
336
+ installs in a module's Install and Reliability scores (task 1003793,
337
+ ADR 0343 D1; owner: counts only, on by default, with an opt-out).
338
+ GET/POST /store/usage-reporting, rendered by settings-usage-reports.js. -->
339
+ <section class="scroll" id="usage-reports-scroll" aria-labelledby="usage-reports-h" data-group="preferences" hidden>
340
+ <h2 id="usage-reports-h" class="scroll__h">Module install reports</h2>
341
+ <p class="scroll__lede">
342
+ A store module is scored partly on whether it installs and runs cleanly for
343
+ the people who use it. Only counts are sent: whether an install worked, and
344
+ a short code if it did not. No messages, file paths or details about you.
345
+ </p>
346
+ <div class="sound-rows" id="usage-reports-rows"></div>
347
+ <p class="settings-status" id="usage-reports-status" role="status" aria-live="polite"></p>
348
+ <p class="section-note">Saves the moment you choose; applies to your next install.</p>
349
+ </section>
350
+
335
351
  <!-- ============ group: sound ============ -->
336
352
 
337
353
  <!-- VOICES — per-skill model picker (GET/PATCH /me/skill-prefs). -->
@@ -437,7 +453,7 @@
437
453
  chrome exists before the page scripts run. -->
438
454
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
439
455
  <script src="/builders/craft-mode.js?v=2026-10-08-city-tab"></script>
440
- <script src="/builders/shell.js?v=2026-10-08-city-tab"></script>
456
+ <script src="/builders/shell.js?v=2026-10-08-glyph-fix"></script>
441
457
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
442
458
  <script src="/builders/palette.js" defer></script>
443
459
  <!-- shared frontend toolkit (window.OTB) — loaded before consuming IIFEs. -->
@@ -464,5 +480,7 @@
464
480
  <script src="/builders/settings-software-update.js?v=2026-10-06-ask"></script>
465
481
  <!-- task 1004501: Settings → Your Autobongos runner. Own file on the same precedent. -->
466
482
  <script src="/builders/settings-autobongos.js?v=2026-10-01-autobongos"></script>
483
+ <!-- task 1003793: Settings → Module install reports. Own file on the same precedent. -->
484
+ <script src="/builders/settings-usage-reports.js?v=2026-10-08-usage-reports"></script>
467
485
  </body>
468
486
  </html>
@@ -12,6 +12,7 @@
12
12
  "preferences": { "auth": true, "url": "/settings#preferences", "actions": [["wait", 900]], "expect": { "visible": ["#wander-rows", "#render-rows", "#specialities-rows"] } },
13
13
  "skills-walkthrough": { "auth": true, "url": "/settings#preferences", "actions": [["wait", 900], ["click", "#specialities-rows button[data-act=\"adopt\"]"], ["wait", 700]], "expect": { "visible": [".skill-walk", ".skill-walk__facts", "button[data-walk=\"on\"]", "button[data-walk=\"off\"]"] } },
14
14
  "offered-skills": { "auth": true, "url": "/settings#preferences", "actions": [["wait", 900], ["click", "#specialities-rows button[data-act=\"offer\"]"], ["wait", 700]], "expect": { "visible": ["form.speciality-offer", ".speciality-offer__list", ".speciality-offer__filter"] } },
15
+ "install-reports": { "_": "The Module install reports switch (task 1003793): the opt-out for counting your store-module installs in a module's score, on by default. Scrolled into view by focusing its default choice.", "auth": true, "url": "/settings#preferences", "actions": [["wait", 900], ["clickIfVisible", "[data-craft-close]"], ["wait", 300], ["focus", "#usage-reports-on"], ["wait", 300]], "expect": { "visible": ["#usage-reports-h", "#usage-reports-on", "#usage-reports-off"] } },
15
16
  "sound": { "auth": true, "url": "/settings#sound", "actions": [["wait", 900]], "expect": { "visible": ["#voices-table", "#sound-rows", "#event-sound-rows"] } },
16
17
  "update": { "auth": true, "url": "/settings#software-update", "actions": [["wait", 1200]], "expect": { "visible": ["#software-update-h", "#su-body", "#su-update", ".su-versions"] } }
17
18
  },