@bongos/core 1.24.41 → 1.24.42

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 (61) hide show
  1. package/.bongos-core.json +80 -65
  2. package/docs/copy-inventory.md +91 -112
  3. package/docs/copy-registry.json +177 -385
  4. package/docs/module-api-changelog.md +2 -0
  5. package/docs/page-readings.json +214 -213
  6. package/modules/hall-ui/public/ai-studio.html +1 -1
  7. package/modules/hall-ui/public/atlas.html +1 -1
  8. package/modules/hall-ui/public/blockers.html +1 -1
  9. package/modules/hall-ui/public/board-room.html +1 -1
  10. package/modules/hall-ui/public/builders.js +17 -262
  11. package/modules/hall-ui/public/city.html +1 -1
  12. package/modules/hall-ui/public/collab.html +1 -1
  13. package/modules/hall-ui/public/commands.html +1 -1
  14. package/modules/hall-ui/public/copy-desk.html +1 -1
  15. package/modules/hall-ui/public/deploy.html +1 -1
  16. package/modules/hall-ui/public/goal-map.html +1 -1
  17. package/modules/hall-ui/public/goals.html +1 -1
  18. package/modules/hall-ui/public/government.html +1 -1
  19. package/modules/hall-ui/public/hall-render.js +3 -248
  20. package/modules/hall-ui/public/hall-widgets.js +3 -14
  21. package/modules/hall-ui/public/idea.html +1 -1
  22. package/modules/hall-ui/public/ideas.html +1 -1
  23. package/modules/hall-ui/public/index.html +3 -4
  24. package/modules/hall-ui/public/market-watch-item.html +1 -1
  25. package/modules/hall-ui/public/market-watch-rules.html +1 -1
  26. package/modules/hall-ui/public/market-watch.html +1 -1
  27. package/modules/hall-ui/public/modules.html +1 -1
  28. package/modules/hall-ui/public/money.html +1 -1
  29. package/modules/hall-ui/public/my-agents.html +1 -1
  30. package/modules/hall-ui/public/primer.html +1 -1
  31. package/modules/hall-ui/public/profile.html +1 -1
  32. package/modules/hall-ui/public/project-settings.html +1 -1
  33. package/modules/hall-ui/public/roadmap.html +1 -1
  34. package/modules/hall-ui/public/roster.html +1 -1
  35. package/modules/hall-ui/public/settings.html +1 -1
  36. package/modules/hall-ui/public/setup-gate.js +156 -0
  37. package/modules/hall-ui/public/shell.js +16 -1
  38. package/modules/hall-ui/public/street.html +1 -1
  39. package/modules/hall-ui/public/studio.html +1 -1
  40. package/modules/hall-ui/public/style.css +85 -117
  41. package/modules/hall-ui/public/task.html +1 -1
  42. package/modules/hall-ui/public/thinking.html +1 -1
  43. package/modules/hall-ui/public/tweak-editor.html +1 -1
  44. package/modules/hall-ui/public/watch.html +1 -1
  45. package/modules/hall-ui/public/work.html +1 -1
  46. package/modules/hall-ui/records/setup-gate.md +43 -0
  47. package/modules/lifecycle/routes/tasks.js +2 -2
  48. package/modules/onboarding/onboarding-state.js +41 -20
  49. package/package-lock.json +2 -2
  50. package/package.json +1 -1
  51. package/release-notes.json +6 -0
  52. package/src/bongos/routes/me.js +2 -2
  53. package/src/module-api.js +1 -1
  54. package/tests/hall_board_world.mjs +1 -1
  55. package/tests/hall_landing_boot.mjs +2 -3
  56. package/tests/hall_onboarding_bongos_setup.mjs +14 -14
  57. package/tests/module_contributions.mjs +4 -2
  58. package/tests/nav_permission_atoms.mjs +3 -2
  59. package/tests/onboarding_state.mjs +33 -0
  60. package/tests/setup_flow.mjs +242 -0
  61. package/tests/welcome_boot.mjs +3 -2
@@ -89,7 +89,7 @@
89
89
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
90
90
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
91
91
  <script src="/builders/craft-mode.js?v=2026-11-05-oversight"></script>
92
- <script src="/builders/shell.js?v=2026-11-05-oversight"></script>
92
+ <script src="/builders/shell.js?v=2026-11-05-setup-gate"></script>
93
93
  <script src="/builders/palette.js" defer></script>
94
94
  <script src="/builders/tweak-editor-lib.js?v=2026-09-28-tw23"></script>
95
95
  <script src="/builders/studio-lib.js?v=2026-10-09-day"></script>
@@ -92,7 +92,7 @@
92
92
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
93
93
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
94
94
  <script src="/builders/craft-mode.js?v=2026-11-05-oversight"></script>
95
- <script src="/builders/shell.js?v=2026-11-05-oversight"></script>
95
+ <script src="/builders/shell.js?v=2026-11-05-setup-gate"></script>
96
96
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
97
97
  <script src="/builders/palette.js" defer></script>
98
98
  <script src="/builders/atlas.js?v=2026-09-02-index" defer></script>
@@ -61,7 +61,7 @@
61
61
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
62
62
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
63
63
  <script src="/builders/craft-mode.js?v=2026-11-05-oversight"></script>
64
- <script src="/builders/shell.js?v=2026-11-05-oversight"></script>
64
+ <script src="/builders/shell.js?v=2026-11-05-setup-gate"></script>
65
65
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
66
66
  <script src="/builders/palette.js" defer></script>
67
67
  <!-- the branding pack's currency label, loaded BEFORE blockers.js. -->
@@ -63,7 +63,7 @@
63
63
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
64
64
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
65
65
  <script src="/builders/craft-mode.js?v=2026-11-05-oversight"></script>
66
- <script src="/builders/shell.js?v=2026-11-05-oversight"></script>
66
+ <script src="/builders/shell.js?v=2026-11-05-setup-gate"></script>
67
67
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
68
68
  <script src="/builders/palette.js" defer></script>
69
69
  <script src="/builders/hall-kit.js"></script>
@@ -126,14 +126,14 @@
126
126
  // gone — both now use the OTBKit pager, which clamps, persists per-page and
127
127
  // paints the bar from one implementation.)
128
128
 
129
- // ---- repo info (the clone URL the welcome walkthrough hands a newcomer) ---
129
+ // ---- repo info (the clone URL the setup screen hands a newcomer) ---
130
130
  //
131
131
  // The /builder-* commands live INSIDE the repo (.claude/skills/, shelling out
132
132
  // to scripts/bongos/*.js). The old repo-clone walkthrough (and the
133
133
  // /public/repo-info fetch that fed it) was removed with the setup-first
134
- // redesign (#777); the welcome panel's clone block now reads the instance's
135
- // repo coords instead. The /public/repo-info surface still exists for other
136
- // callers.
134
+ // redesign (#777); the setup screen's clone block (setup-gate.js, task 1005076)
135
+ // reads the instance's repo coords instead. The /public/repo-info surface
136
+ // still exists for other callers.
137
137
 
138
138
  // ---- rank badge (V3.R16 #240) -------------------------------------------
139
139
  // Three live ranks per ADR 0018: archon > metic > xenos. Missing rank
@@ -149,7 +149,7 @@
149
149
  // xenos — #692 / ADR 0034) to the entry rank. Reserved values still on the
150
150
  // citizen/divine ladder would otherwise render as a dashed "unknown" plaque
151
151
  // while the hall elsewhere shows them as xenos. Applied to the
152
- // builder-facing standing surfaces — the welcome panel, the profile Standing
152
+ // builder-facing standing surfaces — the profile Standing
153
153
  // badge, and the public Roll — so they agree. NOT applied to the Archon-only
154
154
  // roster below, which intentionally shows the true stored rank so an Archon
155
155
  // can spot and fix a stray value. hall-render.js's "Where you stand" card
@@ -187,27 +187,10 @@
187
187
  // GATE new claims and whose reward is pending until they land on ship.
188
188
  let lastRebaseState = null;
189
189
 
190
- // Cached /me payload from the most recent loadAll() call. Used by the
191
- // welcome-chip reopen path (#408) so we can re-render the welcome panel
192
- // from cached state without a fresh /me round-trip. Distinct from
193
- // lastKarmaState: that one only stashes karma; this stashes the whole
194
- // payload so renderWelcome's builder + onboarding args are available.
190
+ // Cached /me payload from the most recent loadAll() call, for re-renders
191
+ // that need the builder without a fresh /me round-trip.
195
192
  let lastMeState = null;
196
193
 
197
- // Instance repo coords for the "get the code" clone block. The public instance
198
- // manifest (GET /api/bongos/instance) is the channel for cross-instance repo coords
199
- // — clientBranding deliberately omits `repo`, so window.__BRANDING__ can't carry
200
- // it. Cached; the welcome re-renders when it lands so a fresh instance shows ITS
201
- // OWN repo, never a hardcoded one (ADR 0062 §3, task 1705).
202
- let instanceRepo = null;
203
- async function loadInstanceRepo() {
204
- try {
205
- const inst = await getJSON(`${API}/instance`, { softAuth: true });
206
- instanceRepo = inst && inst.repo && !inst.repo.error ? inst.repo : null;
207
- if (instanceRepo && lastMeState) renderWelcome(lastMeState.builder, lastMeState.onboarding || null);
208
- } catch (_) { /* best-effort — the clone block falls back to generic guidance */ }
209
- }
210
-
211
194
  // ---- hall section nav (#408) --------------------------------------------
212
195
  //
213
196
  // Single source of truth for what appears in the sticky strip at top of
@@ -218,9 +201,6 @@
218
201
  //
219
202
  // Filter rules at render time:
220
203
  // archonOnly: true → skip unless /me returns rank=archon.
221
- // welcomeChip:true → ALWAYS shown pre-graduation (even when the
222
- // panel is dismissed) so the builder can re-open
223
- // it. Hidden post-graduation just like the panel.
224
204
  // default → skip if the section's element is [hidden].
225
205
  //
226
206
  // Adding a new section: add a row here AND give the <section> a stable
@@ -266,7 +246,7 @@
266
246
  // container (falling back to <main>), in registry order, then render its
267
247
  // skeleton via mount(host). Idempotent: a second call (defensive) re-uses an
268
248
  // existing <section>. Runs once at bootstrap BEFORE wireEvents() so the static
269
- // element ids the data-render + event-wiring code expects (#welcome-minimize,
249
+ // element ids the data-render + event-wiring code expects (#acclaim-feed,
270
250
  // #recent-ships, #lb-prev, …) are present. Each widget mount is
271
251
  // failure-isolated so one bad widget can't blank the hall.
272
252
  // task 2169: zone budgets — Home cannot grow unbounded again. Caps count
@@ -281,12 +261,9 @@
281
261
  // the kit owns the IntersectionObserver that used to live here as
282
262
  // setupNavObserver(). Built lazily on the first renderNav and refreshed after,
283
263
  // so the same instance survives re-renders.
284
- // 2. the Home re-open affordance for a dismissed welcome banner (the old
285
- // welcome chip's only job);
286
- // 3. the Standing view's in-page section rail (#standing-rail) — task 2174:
287
- // one entry per GROUP that currently has something to show, not one per
288
- // widget. A group with every member hidden (a newcomer, an empty karma
289
- // feed) hides itself and drops off the rail.
264
+ // The rail (#standing-rail) has one entry per GROUP that currently has
265
+ // something to show, not one per widget. A group with every member hidden
266
+ // (a newcomer, an empty karma feed) hides itself and drops off the rail.
290
267
  // Keeps its (builder, onboarding) signature — all call sites pass them.
291
268
 
292
269
  // #748: newcomer gate. A Xenos sees a deliberately spare hall — their
@@ -309,7 +286,7 @@
309
286
  // (which un-hide their own scroll on data) respect it; the section-hiding
310
287
  // sweep then runs before renderNav so the chip strip matches.
311
288
  const NEWCOMER_VISIBLE_SECTIONS = new Set([
312
- 'welcome-scroll', 'onboarding-scroll', 'profile-scroll',
289
+ 'profile-scroll',
313
290
  ]);
314
291
  let newcomerGated = false;
315
292
 
@@ -325,21 +302,6 @@
325
302
  // gates. This function keeps only the widget-section sweep.
326
303
  }
327
304
 
328
- function reopenWelcomeFromNav(e) {
329
- e.preventDefault();
330
- const id = window.__buildersSelfId;
331
- if (!id || !lastMeState) return;
332
- try {
333
- window.localStorage.removeItem(welcomeDismissalKey(id));
334
- } catch (_) { /* private mode — re-open in-memory only */ }
335
- // Re-render welcome from cached /me state and refresh the nav so the
336
- // chip drops its "dismissed" styling.
337
- renderWelcome(lastMeState.builder, lastMeState.onboarding || null);
338
- renderNav(lastMeState.builder, lastMeState.onboarding || null);
339
- // Now scroll to the (newly-unhidden) welcome panel.
340
- const target = document.getElementById('welcome-scroll');
341
- if (target) target.scrollIntoView({ behavior: 'smooth', block: 'start' });
342
- }
343
305
 
344
306
 
345
307
  // Wires the public landing's access-request form. Submits to the one public
@@ -371,93 +333,6 @@
371
333
  }
372
334
  }
373
335
 
374
- // ---- first-visit welcome panel (V3.R77 #296) ----------------------------
375
- // Greets a not-yet-graduated builder with their rank, what their rank
376
- // unlocks, the next checklist step, and the two doors into the hall: the
377
- // orientation maps and the /builder-start command. Dismissable. Reappears
378
- // if the builder's onboarding stage regresses (rare — e.g. a stage row
379
- // wipe in dev or an Archon-driven reset).
380
- //
381
- // Persistence: localStorage key `builders:welcome-dismissed:<builder_id>`
382
- // stores the stage *index* (0-6) at the moment of dismissal. On every
383
- // render we compute the builder's current stage index; if it's strictly
384
- // less than the dismissed-at index, the panel reappears. Per-builder key
385
- // so a shared browser doesn't carry one builder's dismissal to another.
386
- //
387
- // The panel only renders for the LOGGED-IN viewer (uses /me). It is not
388
- // shown on profile pages of other builders — that's the read-only
389
- // onboarding-list panel below, which is roster-visible.
390
-
391
- // Canonical order of the onboarding stages, mirroring
392
- // src/bongos/onboarding-state.js STAGES. 'graduated' is the terminal stage;
393
- // when current === 'graduated' the panel hides entirely.
394
-
395
-
396
-
397
- // task 2169 (banner budget): exactly one banner panel at a time. The
398
- // checklist render runs before the welcome render in the boot pass, so after
399
- // the welcome panel's visibility settles we re-evaluate the checklist —
400
- // welcome visible → checklist waits; welcome dismissed/hidden → checklist
401
- // takes the banner slot (renderOnboarding carries the mirror check).
402
- function renderWelcome(builder, onboarding) {
403
- renderWelcomeCore(builder, onboarding);
404
- renderOnboarding(
405
- onboarding || (lastMeState && lastMeState.onboarding) || null,
406
- lastMeState && lastMeState.discord
407
- );
408
- }
409
-
410
-
411
- // ---- onboarding checklist (V3.R75 #294; reshaped #777) ------------------
412
- // Renders the "Path into the City" checklist for the CURRENT logged-in
413
- // builder. Hidden once graduated (current_stage === 'graduated') so it
414
- // doesn't clutter the hall for full citizens. The displayed list (#777) is a
415
- // short, action-only orientation path: Join Discord → Choose craft → Run
416
- // /builder-setup → Ship three (→ Thetes). Every step AUTO-detects server-side
417
- // (#777, per Lars: no manual ticks). Only two carry a control:
418
- // * pick_disciplines — the craft picker (PATCH /me/disciplines).
419
- // * join_discord — a Connect-Discord button (the existing OAuth flow,
420
- // auto-joins + assigns rank role); clears when linked.
421
- // cli_setup clears once the Bongos CLI is authenticated (db.hasCliSession) and
422
- // ship_three on the 3rd ship — both passive. The terminal ship_three step
423
- // shows the live "N of 3" counter (its `detail`). `discord` is the /me discord
424
- // block ({ linked, configured }) — when Discord isn't configured server-side
425
- // the Connect button is suppressed.
426
-
427
-
428
- // V3 (2026-05-30): clear the pick_disciplines onboarding stage from the path
429
- // checklist. Saves the chosen craft via the same PATCH /me/disciplines route
430
- // the profile uses, then re-renders the checklist (and the profile picker) so
431
- // both reflect the choice. The route echoes the updated onboarding state.
432
- async function pickDiscipline(value) {
433
- // Multi-select toggle: add the craft if not yet chosen, remove it if it is,
434
- // then save the full set (any mix of engineer, artist, ideator).
435
- const current = (lastMeState && lastMeState.builder && Array.isArray(lastMeState.builder.preferred_disciplines))
436
- ? lastMeState.builder.preferred_disciplines : [];
437
- const selected = current.includes(value)
438
- ? current.filter((d) => d !== value)
439
- : [...current, value];
440
- const buttons = document.querySelectorAll('.onboarding-item__disc');
441
- buttons.forEach((b) => { b.disabled = true; });
442
- try {
443
- const resp = await patchJSON(`${API}/me/disciplines`, { preferred_disciplines: selected });
444
- if (resp.builder && lastMeState) {
445
- // Keep the cached /me state and the profile picker in sync.
446
- lastMeState.builder = resp.builder;
447
- lastMeState.onboarding = resp.onboarding || lastMeState.onboarding;
448
- }
449
- if (resp.onboarding) renderOnboarding(resp.onboarding, lastMeState && lastMeState.discord);
450
- if (resp.builder) renderProfile(resp.builder);
451
- const axis = window.OTB.roleAxisLabel();
452
- toast(selected.length ? `${axis}: ${selected.map((d) => window.OTB.roleLabel(d)).join(', ')}.` : `${axis} cleared.`);
453
- } catch (err) {
454
- if (err && err.message === 'redirecting to auth') return;
455
- console.error('[builders] pick discipline failed', err);
456
- toast('Could not save just now. Try again.');
457
- buttons.forEach((b) => { b.disabled = false; });
458
- }
459
- }
460
-
461
336
  // ---- achievements --------------------------------------------------------
462
337
 
463
338
  function renderAchievements(all, unlocked, lockedWithProgress) {
@@ -888,79 +763,6 @@
888
763
  // builder isn't on the roll). Matched by github_login (rows carry no id).
889
764
 
890
765
 
891
- // ---- onboarding live-tick poll (task 1444) -------------------------------
892
- //
893
- // The onboarding checklist is rendered once from the page-load /me snapshot.
894
- // But two of its steps clear from LIVE server signals that flip WITHOUT any
895
- // local action or page reload while the hall sits open:
896
- // * cli_setup — stamped when the Bongos CLI is first authenticated;
897
- // * join_discord — flips on the OAuth link (usually a full redirect, but can
898
- // also land from another tab).
899
- // Without a poll, a newcomer who signs the CLI in AFTER opening the hall sees
900
- // the step stay unchecked until they manually reload — exactly the bug scootermack
901
- // hit. "The city watches" only worked on the next full reload. So while any
902
- // live-signal step is still uncleared, re-fetch /me on an interval and re-render
903
- // the checklist; stop once they all clear (or the builder graduates).
904
- let onboardingPollTimer = null;
905
- const ONBOARDING_POLL_MS = 15000;
906
-
907
- // True while at least one step that clears from a live signal (cli/discord)
908
- // is still uncleared and the builder hasn't graduated. The pick_disciplines and
909
- // ship_three steps flip via local action (PATCH re-renders) or shipping, so they
910
- // don't need a poll — scoping to the live-signal steps bounds polling to the
911
- // setup window rather than running forever for any non-graduated builder.
912
- function onboardingNeedsLivePoll(onboarding) {
913
- if (!onboarding || onboarding.graduated) return false;
914
- const stages = Array.isArray(onboarding.stages) ? onboarding.stages : [];
915
- return stages.some((s) =>
916
- (s.source === 'cli' || s.source === 'discord') && !s.cleared);
917
- }
918
-
919
- function stopOnboardingPoll() {
920
- if (onboardingPollTimer) { clearTimeout(onboardingPollTimer); onboardingPollTimer = null; }
921
- }
922
-
923
- function scheduleOnboardingPoll(onboarding) {
924
- stopOnboardingPoll();
925
- if (!onboardingNeedsLivePoll(onboarding)) return;
926
- onboardingPollTimer = setTimeout(refreshOnboardingFromServer, ONBOARDING_POLL_MS);
927
- }
928
-
929
- async function refreshOnboardingFromServer() {
930
- onboardingPollTimer = null;
931
- // Don't poll a backgrounded tab — wait for it to come back (the
932
- // visibilitychange listener re-arms from the cached state).
933
- if (document.hidden) { scheduleOnboardingPoll(lastMeState && lastMeState.onboarding); return; }
934
- let me;
935
- try {
936
- me = await getJSON(`${API}/me`, { softAuth: true });
937
- } catch (err) {
938
- // Session expired → stop (a redirect/landing will take over on next action).
939
- if (err && err.code === AUTH_NEEDED) { stopOnboardingPoll(); return; }
940
- // Transient (network blip / 5xx) → try again next interval so a single
941
- // failure doesn't permanently kill the auto-tick.
942
- scheduleOnboardingPoll(lastMeState && lastMeState.onboarding);
943
- return;
944
- }
945
- if (!me || !me.builder) return;
946
- const wasGraduated = !!(lastMeState && lastMeState.onboarding && lastMeState.onboarding.graduated);
947
- lastMeState = me;
948
- lastKarmaState = me.karma || lastKarmaState;
949
- lastCostState = me.cost || lastCostState;
950
- lastNeedsState = me.needs || lastNeedsState;
951
- // ADR 0120 part 5: owed-rebase list is authoritative on every /me (an empty
952
- // array means "nothing owed now"), so take it verbatim when present.
953
- if (Array.isArray(me.needs_rebase_tasks)) lastRebaseState = me.needs_rebase_tasks;
954
- renderOnboarding(me.onboarding || null, me.discord);
955
- // If they graduated while watching, hide the welcome panel + rebuild the nav
956
- // (drops the Welcome/Path chips) — the same transition loadAll would render.
957
- if (me.onboarding && me.onboarding.graduated && !wasGraduated) {
958
- renderWelcome(me.builder, me.onboarding);
959
- renderNav(me.builder, me.onboarding || null);
960
- }
961
- scheduleOnboardingPoll(me.onboarding || null);
962
- }
963
-
964
766
  // ---- bootstrap -----------------------------------------------------------
965
767
 
966
768
  // `prefetchedMe` is boot()'s already-resolved /me — the SAME payload, handed in
@@ -986,33 +788,17 @@
986
788
  lastCostState = me.cost || null;
987
789
  lastNeedsState = me.needs || null; // task 1013 / ADR 0073: action-needed banner
988
790
  lastRebaseState = Array.isArray(me.needs_rebase_tasks) ? me.needs_rebase_tasks : null; // ADR 0120 part 5: owed-rebase banner
989
- // #408: stash the whole /me payload so reopenWelcomeFromNav can re-render
990
- // the welcome panel without a fresh round-trip.
991
791
  lastMeState = me;
992
792
  // #748: decide the newcomer gate up front so the async karma/acclaim feeds
993
793
  // (which un-hide their own scroll on data arrival) honour it too.
994
794
  newcomerGated = normalizeRank(me.builder?.rank) === 'xenos';
995
- // V3.R77 (#296): first-visit welcome panel. Renders above the profile and
996
- // hides itself once dismissed or once the builder graduates. Computed
997
- // before profile so the dismiss button is wired by the time the user
998
- // sees the page.
999
- // Cache self id on window so the dismiss-click handler can find it
1000
- // without re-fetching /me. Set BEFORE renderWelcome so the wired
1001
- // dismiss listener (attached once at bootstrap) can use it immediately.
795
+ // Cache self id on window for handlers wired once at bootstrap.
1002
796
  window.__buildersSelfId = me.builder?.id ?? null;
1003
- renderWelcome(me.builder, me.onboarding || null);
1004
797
  renderProfile(me.builder);
1005
798
  renderGreeting(); // task 1003464: "Good morning, <name>" — the h1 — as soon as /me answers
1006
799
  // #731: the CLI-token re-issue card (V3.R91 #401) and the Discord connect/
1007
800
  // link card (F7, ADR 0033) moved to /builders/settings — the hall's Standing
1008
801
  // card is identity-only now.
1009
- // V3.R75 (#294): auto-completing onboarding checklist. The /me payload
1010
- // carries the builder's own state directly so this is a render-only call.
1011
- renderOnboarding(me.onboarding || null, me.discord);
1012
- // task 1444: keep the checklist live — re-fetch /me on an interval while a
1013
- // cli/discord step is still uncleared, so it ticks itself without a manual
1014
- // reload the moment the CLI or Discord links.
1015
- scheduleOnboardingPoll(me.onboarding || null);
1016
802
  renderRecentGrades(me.grades?.recent || []);
1017
803
  renderRollingNote(me.grades?.rolling || null);
1018
804
  // V3.R72 (#291, C5): the dev curve. Loaded fire-and-forget — a slow or
@@ -1028,10 +814,10 @@
1028
814
  // slow/failed feed can't hold up the rest of the hall.
1029
815
  loadAcclaimFeed();
1030
816
  // #408: build the sticky nav now that every section has settled its
1031
- // hidden state (welcome → karma → onboarding → security/roster).
817
+ // hidden state (karma → security/roster).
1032
818
  // The renderNav call also wires the IntersectionObserver for active-
1033
- // section highlighting. Idempotent — safe to call again on dismiss/re-open.
1034
- // #748: collapse the hall to the newcomer view (onboarding + Standing) for
819
+ // section highlighting. Idempotent — safe to call again.
820
+ // #748: collapse the hall to the newcomer view (Standing) for
1035
821
  // a Xenos BEFORE building the nav, so the chip strip matches what's shown.
1036
822
  applyNewcomerGate();
1037
823
  renderNav(me.builder, me.onboarding || null);
@@ -1129,33 +915,6 @@
1129
915
  reloadCurveForKind(kind);
1130
916
  });
1131
917
 
1132
- // task 1723: the Home "show the setup guide again" link re-opens a dismissed
1133
- // welcome banner (the old welcome chip's job) — clears the dismissal flag,
1134
- // re-renders the panel, refreshes the nav, then scrolls to it.
1135
- document.getElementById('welcome-reopen')?.addEventListener('click', (e) => {
1136
- reopenWelcomeFromNav(e);
1137
- });
1138
-
1139
- // V3.R75 (#294): the onboarding list re-renders on each /me load, so the
1140
- // inline craft picker is wired by delegation to the list container. (The
1141
- // primer-read ack button that also lived here was removed in #766.)
1142
- $('#onboarding-list')?.addEventListener('click', (e) => {
1143
- const disc = e.target.closest('.onboarding-item__disc[data-disc]');
1144
- if (disc) { pickDiscipline(disc.dataset.disc); return; }
1145
- // #777: the only other control is the Connect-Discord anchor, which is a
1146
- // real link (full-page nav into the OAuth flow) — nothing to handle here.
1147
- // Both new steps (join_discord, cli_setup) auto-detect server-side.
1148
- });
1149
-
1150
- // Welcome panel minimize toggle (replaces full dismiss).
1151
- $('#welcome-minimize')?.addEventListener('click', () => {
1152
- const scroll = $('#welcome-scroll');
1153
- const btn = $('#welcome-minimize');
1154
- if (!scroll) return;
1155
- const minimized = scroll.classList.toggle('scroll--welcome--minimized');
1156
- if (btn) btn.textContent = minimized ? '+' : '−';
1157
- });
1158
-
1159
918
  // task 1004833: the shared vote control reports each landed vote to the feed.
1160
919
  $('#acclaim-feed')?.addEventListener('otb-vote', onAcclaimVote);
1161
920
 
@@ -1273,9 +1032,8 @@
1273
1032
  // reads what this page holds NOW rather than what it held at boot. Everything
1274
1033
  // else is stable for the life of the page. This call sits AFTER every
1275
1034
  // declaration it passes — moving it earlier is a temporal-dead-zone crash.
1276
- const { acclaimEvidenceHtml, analyticsState, lbState, mountHallWidgets, renderCurveBody, renderGreeting, renderLanding, renderSessionRefused, renderNav, renderOnboarding, renderProfile, renderRecentShips, renderWelcomeCore, HOME_SHIPS_LIMIT, populateShipVersionFilter, setRecentShips, shipsPager, welcomeDismissalKey } = window.OTBHallRender({
1035
+ const { acclaimEvidenceHtml, analyticsState, lbState, mountHallWidgets, renderCurveBody, renderGreeting, renderLanding, renderSessionRefused, renderNav, renderProfile, renderRecentShips, HOME_SHIPS_LIMIT, populateShipVersionFilter, setRecentShips, shipsPager } = window.OTBHallRender({
1277
1036
  API, RANK_ORDER, api, brandWorld, curLabel, emptyRow, fmtDate, getJSON, mins, normalizeRank, pct, postJSON, rankLabel, rankWeight, signClasses, toast, usd,
1278
- get instanceRepo() { return instanceRepo; },
1279
1037
  get lastCostState() { return lastCostState; },
1280
1038
  get lastKarmaState() { return lastKarmaState; },
1281
1039
  get lastMeState() { return lastMeState; },
@@ -1318,9 +1076,6 @@
1318
1076
  // which only exist once the registry has mounted them.
1319
1077
  mountHallWidgets();
1320
1078
  wireEvents();
1321
- // Fetch the instance's repo coords (public) so the welcome "get the code"
1322
- // clone block shows this instance's own repository (ADR 0062 §3, task 1705).
1323
- loadInstanceRepo();
1324
1079
  // #731: the Discord connect/link card moved to /builders/settings, and the
1325
1080
  // OAuth callback now lands there — so the ?discord=joined|linked toast is
1326
1081
  // handled by settings.js, not here.
@@ -108,7 +108,7 @@
108
108
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
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-11-05-oversight" defer></script>
111
- <script src="/builders/shell.js?v=2026-11-05-oversight" defer></script>
111
+ <script src="/builders/shell.js?v=2026-11-05-setup-gate" defer></script>
112
112
  <script src="/builders/palette.js" defer></script>
113
113
  <script src="/builders/gov-living.js?v=2026-10-09-positions1" defer></script>
114
114
  <script src="/builders/gov-feeds.js?v=2026-10-09-living3" defer></script>
@@ -162,7 +162,7 @@
162
162
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
163
163
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
164
164
  <script src="/builders/craft-mode.js?v=2026-11-05-oversight"></script>
165
- <script src="/builders/shell.js?v=2026-11-05-oversight"></script>
165
+ <script src="/builders/shell.js?v=2026-11-05-setup-gate"></script>
166
166
  <script src="/builders/palette.js" defer></script>
167
167
  <script src="/builders/collab-lib.js?v=2026-09-24-archive"></script>
168
168
  <script src="/builders/collab.js?v=2026-09-24-archive"></script>
@@ -54,7 +54,7 @@
54
54
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
55
55
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
56
56
  <script src="/builders/craft-mode.js?v=2026-11-05-oversight"></script>
57
- <script src="/builders/shell.js?v=2026-11-05-oversight"></script>
57
+ <script src="/builders/shell.js?v=2026-11-05-setup-gate"></script>
58
58
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
59
59
  <script src="/builders/palette.js" defer></script>
60
60
  <script src="/builders/hall-kit.js"></script>
@@ -180,7 +180,7 @@
180
180
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
181
181
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
182
182
  <script src="/builders/craft-mode.js?v=2026-11-05-oversight"></script>
183
- <script src="/builders/shell.js?v=2026-11-05-oversight"></script>
183
+ <script src="/builders/shell.js?v=2026-11-05-setup-gate"></script>
184
184
  <script src="/builders/palette.js" defer></script>
185
185
  <script src="/builders/hall-kit.js"></script>
186
186
  <script src="/builders/copy-desk.js?v=2026-09-01-redesign"></script>
@@ -81,7 +81,7 @@
81
81
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
82
82
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
83
83
  <script src="/builders/craft-mode.js?v=2026-11-05-oversight"></script>
84
- <script src="/builders/shell.js?v=2026-11-05-oversight"></script>
84
+ <script src="/builders/shell.js?v=2026-11-05-setup-gate"></script>
85
85
  <script src="/builders/palette.js" defer></script>
86
86
  <script src="/builders/hall-kit.js"></script>
87
87
  <!-- the shared ask card the move is drawn with (task 1004829) -->
@@ -140,7 +140,7 @@
140
140
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
141
141
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
142
142
  <script src="/builders/craft-mode.js?v=2026-11-05-oversight"></script>
143
- <script src="/builders/shell.js?v=2026-11-05-oversight"></script>
143
+ <script src="/builders/shell.js?v=2026-11-05-setup-gate"></script>
144
144
  <script src="/builders/palette.js" defer></script>
145
145
 
146
146
  <script src="/builders/idea-objects.js?v=2026-09-27-split"></script>
@@ -244,7 +244,7 @@
244
244
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
245
245
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
246
246
  <script src="/builders/craft-mode.js?v=2026-11-05-oversight"></script>
247
- <script src="/builders/shell.js?v=2026-11-05-oversight"></script>
247
+ <script src="/builders/shell.js?v=2026-11-05-setup-gate"></script>
248
248
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
249
249
  <script src="/builders/palette.js" defer></script>
250
250
  <!-- task 1004727: the ONE karma vote control every task/idea list renders -->
@@ -157,7 +157,7 @@
157
157
  <script src="/builders/dom-utils.js?v=2026-10-25-escape"></script>
158
158
  <script src="/builders/shell-trail.js?v=2026-10-08-city-tab"></script>
159
159
  <script src="/builders/craft-mode.js?v=2026-11-05-oversight"></script>
160
- <script src="/builders/shell.js?v=2026-11-05-oversight"></script>
160
+ <script src="/builders/shell.js?v=2026-11-05-setup-gate"></script>
161
161
  <!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
162
162
  <script src="/builders/palette.js" defer></script>
163
163
  <script src="/builders/hall-kit.js"></script>