@bongos/core 1.25.17 → 1.25.18

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 (68) hide show
  1. package/.bongos-core.json +131 -61
  2. package/clients/bongos-client/README.md +1 -1
  3. package/clients/bongos-client/bongos-client.global.js +10 -0
  4. package/clients/bongos-client/index.cjs +10 -0
  5. package/clients/bongos-client/index.d.ts +15 -1
  6. package/clients/bongos-client/index.mjs +10 -0
  7. package/docs/adr/0408-a-genesis-stage-is-three-doors-onto-one-record.md +1 -0
  8. package/docs/api/openapi.json +243 -6
  9. package/docs/api-reference.md +12 -3
  10. package/docs/copy-inventory.md +118 -108
  11. package/docs/copy-registry.json +315 -172
  12. package/docs/file-map.md +2 -1
  13. package/docs/module-api-changelog.md +2 -0
  14. package/docs/page-inventory.json +3 -0
  15. package/docs/page-readings.json +62 -62
  16. package/modules/app-host/CLAUDE.md +15 -0
  17. package/modules/app-host/module.json +20 -0
  18. package/modules/app-host/public/settings-widget.js +143 -0
  19. package/modules/app-host/routes/app-host.js +88 -0
  20. package/modules/government/charter-advice.js +103 -0
  21. package/modules/government/presets.js +42 -0
  22. package/modules/government/recommendations.js +102 -7
  23. package/modules/government/routes/government.js +1 -0
  24. package/modules/lifecycle/first-read-catalog.js +62 -0
  25. package/modules/lifecycle/first-read-db.js +47 -9
  26. package/modules/lifecycle/first-read.js +88 -23
  27. package/modules/lifecycle/migrations/lifecycle_023_repo_map_dismissed.sql +19 -0
  28. package/modules/lifecycle/routes/first-read.js +27 -5
  29. package/modules/onboarding/genesis-work.js +101 -4
  30. package/modules/onboarding/routes/genesis-work.js +2 -2
  31. package/modules/platform-identity/module.json +1 -1
  32. package/modules/platform-identity/routes/sso-app-status.js +65 -0
  33. package/modules/provisioning/module.json +1 -0
  34. package/modules/provisioning/seams.js +32 -1
  35. package/modules/provisioning/starter-bundles.js +1 -0
  36. package/modules/public-landing/public/assets/guide-core.js +475 -0
  37. package/modules/public-landing/public/assets/guide-hall.css +121 -0
  38. package/modules/public-landing/public/assets/guide-hall.js +164 -0
  39. package/modules/public-landing/public/assets/guide-scene.css +9 -0
  40. package/modules/public-landing/public/assets/guide-scene.js +58 -381
  41. package/modules/public-landing/public/index.html +46 -1
  42. package/modules/public-landing/public/projects.html +11 -2
  43. package/modules/ui-design/kit/serve.js +1 -1
  44. package/package-lock.json +2 -2
  45. package/package.json +1 -1
  46. package/release-notes.json +18 -0
  47. package/scripts/bongos/first-read.js +45 -11
  48. package/scripts/bongos/genesis.js +21 -1
  49. package/scripts/bongos/publish-manifest.js +1 -0
  50. package/scripts/bongos/seam-wiring-guard.js +3 -2
  51. package/scripts/hall-preview/server.js +2 -0
  52. package/src/bongos/auth-admission.js +64 -0
  53. package/src/bongos/auth.js +2 -1
  54. package/src/bongos/module-scope-map.js +4 -0
  55. package/src/bongos/routes/core-update.js +3 -16
  56. package/src/bongos/routes/modules.js +11 -0
  57. package/src/bongos/serve-internal.js +20 -6
  58. package/src/module-api.js +6 -1
  59. package/src/module-loader/loader.js +2 -2
  60. package/tests/app_host.mjs +413 -0
  61. package/tests/first_read.mjs +184 -8
  62. package/tests/genesis_work.mjs +74 -3
  63. package/tests/government_charter_advice.mjs +150 -0
  64. package/tests/landing_guide_hall.mjs +364 -0
  65. package/tests/landing_guide_scene.mjs +8 -5
  66. package/tests/module_api.mjs +1 -0
  67. package/tests/module_loader.mjs +1 -1
  68. package/tests/npm_release_where.mjs +13 -3
@@ -0,0 +1,164 @@
1
+ /* assets/guide-hall.js — THE START-A-PROJECT GUIDE, plain (task 1005276, goal 1000106).
2
+
3
+ The same conversation as the game scene (guide-scene.js), presented plainly for a
4
+ visitor who does not want the game: one panel (#guideHall in index.html), who said
5
+ what as a list, the count of messages left in words, the plan under the talk, and the
6
+ one closing action, "Sign up and get started". Same server, same caps, same plan, same
7
+ hand-off: everything but the look is assets/guide-core.js, which both share.
8
+
9
+ Which one a visitor sees: the doors open the game unless this browser picked the plain
10
+ one before (guide-core.js VIEW_KEY). "Use the simple version" in the game and "Use the
11
+ game version" here swap them with the chat as it stands.
12
+
13
+ No innerHTML; no motion (the waiting line is words), so reduced motion changes nothing.
14
+ boot() runs under a DOM stub in tests/landing_guide_hall.mjs. */
15
+ (function (factory) {
16
+ 'use strict';
17
+ var core = typeof module === 'object' && module.exports ? require('./guide-core.js') : window.GuideCore;
18
+ var api = factory(core);
19
+ if (typeof module === 'object' && module.exports) module.exports = api;
20
+ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
21
+ window.GuideHall = api;
22
+ api.boot(window, document);
23
+ }
24
+ })(function (core) {
25
+ 'use strict';
26
+
27
+ var COPY = core.COPY;
28
+
29
+ function boot(win, doc) {
30
+ var panel = doc.getElementById('guideHall');
31
+ if (!panel || !core.guideOn(win.__MODULES__)) return;
32
+ var ctl = core.controller(win, doc);
33
+ if (!ctl) return;
34
+ var $ = function (name) { return panel.querySelector('[data-gh="' + name + '"]'); };
35
+ var log = $('log'), err = $('err'), form = $('form'), text = $('text'), hp = $('website');
36
+ var send = $('send'), end = $('end'), go = $('go'), left = $('left'), body = $('body');
37
+ var plan = $('plan'), planBody = $('plan-body'), saved = $('saved');
38
+ var makePlan = $('make-plan'), againPlan = $('plan-again'), game = $('switch');
39
+
40
+ function el(tag, cls, txt) {
41
+ var e = doc.createElement(tag);
42
+ if (cls) e.className = cls;
43
+ if (txt != null) e.textContent = txt;
44
+ return e;
45
+ }
46
+ function clear(node) { while (node.firstChild) node.removeChild(node.firstChild); }
47
+ function line(role, who, words) {
48
+ var li = el('li', 'gh__msg gh__msg--' + role);
49
+ if (who) li.appendChild(el('span', 'gh__who', who));
50
+ li.appendChild(el('p', 'gh__words', words));
51
+ return li;
52
+ }
53
+
54
+ function paintLog(state) {
55
+ clear(log);
56
+ state.messages.forEach(function (m) {
57
+ log.appendChild(line(m.role, m.role === 'note' ? '' : m.role === 'guide' ? 'Guide' : 'You', m.text));
58
+ });
59
+ if (state.phase === 'starting' || state.phase === 'sending') log.appendChild(line('wait', 'Guide', COPY.waitTalk + '…'));
60
+ if (state.phase === 'planning') log.appendChild(line('wait', 'Guide', COPY.waitPlan + '…'));
61
+ if (state.phase === 'fallback') log.appendChild(line('guide', 'Guide', state.fallback));
62
+ }
63
+
64
+ function paintCount(state) {
65
+ var limits = ctl.limits();
66
+ var total = state.total || (limits && limits.max_messages) || 0;
67
+ var shown = state.phase !== 'fallback' && state.phase !== 'starting' && total > 0;
68
+ left.hidden = !shown;
69
+ if (shown) left.textContent = COPY.left(state.left, total);
70
+ }
71
+
72
+ // the plan sits under the talk once there is one to show or to wait for
73
+ function paintPlan(state) {
74
+ clear(planBody);
75
+ var p = state.plan;
76
+ plan.hidden = !p && state.phase !== 'planning' && state.phase !== 'ended';
77
+ if (!p) {
78
+ planBody.appendChild(el('p', 'gh__planwait', COPY.planWait(state.phase)));
79
+ } else {
80
+ if (p.summary) planBody.appendChild(el('p', 'gh__plansum', p.summary));
81
+ p.sections.forEach(function (s) {
82
+ if (s.heading) planBody.appendChild(el('h4', 'gh__planh4', s.heading));
83
+ var ul = el('ul', 'gh__planlist');
84
+ s.items.forEach(function (t) { ul.appendChild(el('li', null, t)); });
85
+ planBody.appendChild(ul);
86
+ });
87
+ if (p.note) planBody.appendChild(el('p', 'gh__plannote', p.note));
88
+ }
89
+ saved.textContent = state.saved;
90
+ saved.hidden = !state.saved || state.phase === 'fallback';
91
+ }
92
+
93
+ function paint(state) {
94
+ panel.setAttribute('data-phase', state.phase);
95
+ paintLog(state);
96
+ paintCount(state);
97
+ paintPlan(state);
98
+ var talking = state.phase === 'chat' || state.phase === 'sending' || state.phase === 'starting';
99
+ form.hidden = !talking;
100
+ end.hidden = talking;
101
+ text.disabled = state.phase !== 'chat';
102
+ send.disabled = state.phase !== 'chat';
103
+ makePlan.hidden = !(state.phase === 'chat' && state.sent > 0);
104
+ againPlan.hidden = !(state.phase === 'ended' && !state.plan && state.conv);
105
+ go.hidden = state.phase === 'planning';
106
+ text.maxLength = state.maxChars;
107
+ err.hidden = !state.error;
108
+ err.textContent = state.error;
109
+ go.textContent = state.phase === 'fallback' ? 'Start a project' : state.next;
110
+ if (state.restore && !text.value) text.value = state.restore;
111
+ // keep the newest line in view; once the plan is in, start at its heading
112
+ if (state.plan && state.phase === 'ended') body.scrollTop = plan.offsetTop || 0;
113
+ else body.scrollTop = body.scrollHeight;
114
+ }
115
+
116
+ function focusables() {
117
+ return Array.prototype.filter.call(
118
+ panel.querySelectorAll('a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]):not([tabindex="-1"])'),
119
+ function (n) { return n.offsetParent !== null; });
120
+ }
121
+ function focusFirst() {
122
+ if (panel.hidden) return;
123
+ var target = !text.disabled && !form.hidden ? text : (!end.hidden && !go.hidden ? go : $('close'));
124
+ try { target.focus(); } catch (e) { /* not focusable yet */ }
125
+ }
126
+
127
+ ctl.addView('hall', {
128
+ show: function () {
129
+ game.hidden = !ctl.has('game');
130
+ panel.hidden = false;
131
+ doc.documentElement.classList.add('gd-open');
132
+ },
133
+ hide: function () {
134
+ panel.hidden = true;
135
+ doc.documentElement.classList.remove('gd-open');
136
+ },
137
+ paint: paint,
138
+ focusFirst: focusFirst,
139
+ website: function () { return hp.value; },
140
+ });
141
+
142
+ function submit() {
143
+ if (ctl.state().phase !== 'chat') return;
144
+ var words = text.value.trim();
145
+ if (words) text.value = '';
146
+ ctl.send(words);
147
+ }
148
+ form.addEventListener('submit', function (e) { e.preventDefault(); submit(); });
149
+ text.addEventListener('keydown', function (e) {
150
+ if (e.key === 'Enter' && !e.shiftKey && !e.isComposing) { e.preventDefault(); submit(); }
151
+ });
152
+ makePlan.addEventListener('click', ctl.askPlan);
153
+ againPlan.addEventListener('click', ctl.askPlan);
154
+ $('close').addEventListener('click', ctl.close);
155
+ game.addEventListener('click', function () { ctl.switchTo('game'); });
156
+ panel.addEventListener('click', function (e) { if (e.target === panel) ctl.close(); });
157
+ panel.addEventListener('keydown', function (e) {
158
+ if (e.key === 'Escape') { e.preventDefault(); ctl.close(); return; }
159
+ if (e.key === 'Tab') core.trapTab(doc, focusables(), e);
160
+ });
161
+ }
162
+
163
+ return { boot: boot };
164
+ });
@@ -167,6 +167,15 @@ html.gd-open, html.gd-open body { overflow: hidden; }
167
167
  color: var(--gd-ice); font-size: var(--ds-text-md); text-decoration: underline; text-underline-offset: 3px;
168
168
  }
169
169
  .gd__skip:hover { color: var(--ink); }
170
+ /* Use the simple version: the plain twin of this scene (guide-hall.css, task 1005276), same chat */
171
+ .gd__switch {
172
+ margin-left: auto; display: inline-flex; align-items: center; min-height: 24px; padding: 2px 0;
173
+ background: transparent; border: 0; cursor: pointer;
174
+ color: var(--gd-ice); font: inherit; font-size: var(--ds-text-md); text-decoration: underline; text-underline-offset: 3px;
175
+ }
176
+ .gd__switch:hover { color: var(--ink); }
177
+ .gd__switch[hidden] { display: none; }
178
+ .gd__switch:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; box-shadow: none; }
170
179
 
171
180
  /* what you press: cut, in the name voice. The primary is the one accent bar. */
172
181
  .gd__send, .gd__go, .gd__planbtn {