@bongos/core 1.21.36 → 1.21.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.
- package/.bongos-core.json +90 -70
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +2 -0
- package/clients/bongos-client/index.cjs +2 -0
- package/clients/bongos-client/index.d.ts +3 -0
- package/clients/bongos-client/index.mjs +2 -0
- package/docs/api/openapi.json +77 -3
- package/docs/api-reference.md +3 -2
- package/docs/copy-inventory.md +8 -8
- package/docs/copy-registry.json +8 -8
- package/docs/module-api-changelog.md +4 -0
- package/docs/page-readings.json +234 -234
- package/modules/government/board-withdraw.js +38 -0
- package/modules/government/board.js +1 -0
- package/modules/government/db.js +20 -0
- package/modules/government/migrations/government_026_board_outcome_withdrawn.sql +29 -0
- package/modules/government/routes/government.js +26 -0
- package/modules/hall-ui/public/atlas.html +3 -3
- package/modules/hall-ui/public/blockers.html +3 -3
- package/modules/hall-ui/public/board-room.html +3 -3
- package/modules/hall-ui/public/city.html +3 -3
- package/modules/hall-ui/public/collab.html +3 -3
- package/modules/hall-ui/public/commands.html +3 -3
- package/modules/hall-ui/public/copy-desk.html +3 -3
- package/modules/hall-ui/public/craft-mode.js +44 -6
- package/modules/hall-ui/public/deploy.html +3 -3
- package/modules/hall-ui/public/diagrams.html +3 -3
- package/modules/hall-ui/public/drachmae.html +3 -3
- package/modules/hall-ui/public/fleet.html +3 -3
- package/modules/hall-ui/public/gate.html +3 -3
- package/modules/hall-ui/public/goal-map.html +3 -3
- package/modules/hall-ui/public/goals.html +3 -3
- package/modules/hall-ui/public/government.html +3 -3
- package/modules/hall-ui/public/idea.html +3 -3
- package/modules/hall-ui/public/ideas.html +3 -3
- package/modules/hall-ui/public/index.html +3 -3
- package/modules/hall-ui/public/modules.html +3 -3
- package/modules/hall-ui/public/primer.html +3 -3
- package/modules/hall-ui/public/profile.html +3 -3
- package/modules/hall-ui/public/project-settings.html +3 -3
- package/modules/hall-ui/public/ranks.html +3 -3
- package/modules/hall-ui/public/roadmap.html +3 -3
- package/modules/hall-ui/public/roster.html +3 -3
- package/modules/hall-ui/public/sessions.html +3 -3
- package/modules/hall-ui/public/settings.html +3 -3
- package/modules/hall-ui/public/street-card.js +16 -0
- package/modules/hall-ui/public/street-desk.js +2 -0
- package/modules/hall-ui/public/street.html +3 -3
- package/modules/hall-ui/public/street.js +1 -1
- package/modules/hall-ui/public/studio.html +3 -3
- package/modules/hall-ui/public/style.css +121 -2
- package/modules/hall-ui/public/task.html +3 -3
- package/modules/hall-ui/public/thinking.html +3 -3
- package/modules/hall-ui/public/tweak-editor.html +3 -3
- package/modules/hall-ui/public/watch.html +3 -3
- package/modules/hall-ui/public/work.html +3 -3
- package/modules/hall-ui/records/craft-mode.md +8 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +12 -0
- package/src/bongos/route-rank-check.js +4 -0
- package/src/module-api.js +1 -1
- package/tests/craft_mode_looks.mjs +170 -0
- package/tests/craft_mode_nav.mjs +7 -5
- package/tests/government_board_withdraw.mjs +144 -0
- package/tests/government_seed.mjs +1 -0
- package/tests/hall_street_desk.mjs +37 -0
- package/tests/hall_tweak_editor.mjs +1 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// modules/government/board-withdraw.js — a proposer withdraws their own open
|
|
4
|
+
// board sitting before anyone has voted (task 1004564). Its own file because
|
|
5
|
+
// board.js sits at the size ratchet's line cap; it reads and writes through the
|
|
6
|
+
// same db slice and announces the close through board.js's own close event, so
|
|
7
|
+
// the Discord mirror and every other listener see one shape for every close.
|
|
8
|
+
|
|
9
|
+
const db = require('./db');
|
|
10
|
+
const board = require('./board');
|
|
11
|
+
|
|
12
|
+
// The proposer may take back a sitting they opened, but only while nobody has
|
|
13
|
+
// voted on it: once a vote is cast the sitting belongs to the voters too, and
|
|
14
|
+
// pulling it would erase their say. "Proposer" is the person who OPENED it
|
|
15
|
+
// (opened_by) — a Full Idea's sitting opens itself on its grade, so it has no
|
|
16
|
+
// proposer here and cannot be withdrawn this way. An item past its clock is
|
|
17
|
+
// refused as well: the sweep is about to decide it (under consent, silence
|
|
18
|
+
// passes it), and a withdraw then would dodge that outcome.
|
|
19
|
+
//
|
|
20
|
+
// Each refusal is read first so the caller gets a reason; the write itself
|
|
21
|
+
// repeats every guard in its WHERE (db.withdrawBoardItem), so a vote that
|
|
22
|
+
// arrives between the reads and the write leaves the sitting open
|
|
23
|
+
// ('item_changed') rather than withdrawn over a cast vote.
|
|
24
|
+
async function withdrawItem({ itemId, builderId } = {}) {
|
|
25
|
+
const item = await db.getBoardItemForVote(Number(itemId));
|
|
26
|
+
if (!item) return { ok: false, reason: 'item_not_found' };
|
|
27
|
+
if (item.closed_at) return { ok: false, reason: 'item_closed' };
|
|
28
|
+
if (item.opened_by == null || String(item.opened_by) !== String(builderId)) return { ok: false, reason: 'not_proposer' };
|
|
29
|
+
if (item.expired) return { ok: false, reason: 'vote_window_expired' };
|
|
30
|
+
const votes = await db.getVotesForItem(item.id);
|
|
31
|
+
if (votes.length > 0) return { ok: false, reason: 'votes_cast' };
|
|
32
|
+
const closed = await db.withdrawBoardItem({ itemId: item.id, builderId });
|
|
33
|
+
if (!closed) return { ok: false, reason: 'item_changed' };
|
|
34
|
+
await board.emitItemClosed(closed, { cause: 'withdrawn', votes: [] });
|
|
35
|
+
return { ok: true, item: closed };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = { withdrawItem };
|
package/modules/government/db.js
CHANGED
|
@@ -393,6 +393,25 @@ async function getVotesForItem(itemId) {
|
|
|
393
393
|
return rows;
|
|
394
394
|
}
|
|
395
395
|
|
|
396
|
+
// The withdraw write (task 1004564) — a proposer takes back their own open
|
|
397
|
+
// sitting before anyone has voted. EVERY guard is in the WHERE, not only in
|
|
398
|
+
// withdrawItem (board-withdraw.js)'s reads: still open, opened by this builder, and no vote
|
|
399
|
+
// row on it. So a vote that lands between the caller's read and this write
|
|
400
|
+
// makes it match nothing (null), and the sitting stays open — the same
|
|
401
|
+
// single-winner shape as closeBoardItem.
|
|
402
|
+
async function withdrawBoardItem({ itemId, builderId }) {
|
|
403
|
+
const { rows } = await pool.query(
|
|
404
|
+
`UPDATE government_board_items
|
|
405
|
+
SET closed_at = now(), outcome = 'withdrawn'
|
|
406
|
+
WHERE id = $1 AND closed_at IS NULL
|
|
407
|
+
AND opened_by = $2
|
|
408
|
+
AND NOT EXISTS (SELECT 1 FROM government_board_votes WHERE item_id = $1)
|
|
409
|
+
RETURNING *`,
|
|
410
|
+
[itemId, builderId],
|
|
411
|
+
);
|
|
412
|
+
return rows[0] || null;
|
|
413
|
+
}
|
|
414
|
+
|
|
396
415
|
// The close write — STRUCTURALLY SINGLE-WINNER: WHERE closed_at IS NULL means
|
|
397
416
|
// two concurrent closers (a racing vote and the expiry sweep) write exactly one
|
|
398
417
|
// outcome; the loser gets null and reads the winner's row back if it cares.
|
|
@@ -881,6 +900,7 @@ module.exports = {
|
|
|
881
900
|
insertAuthorRatifyKarma,
|
|
882
901
|
getVotesForItem,
|
|
883
902
|
closeBoardItem,
|
|
903
|
+
withdrawBoardItem,
|
|
884
904
|
getIdeaCompleteness,
|
|
885
905
|
getExpiredOpenBoardItems,
|
|
886
906
|
getLatestReturnedItemWithObjection,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
-- government_026_board_outcome_withdrawn.sql — a board sitting may also end
|
|
2
|
+
-- 'withdrawn' or 'expired' (task 1004564, goal 1000125).
|
|
3
|
+
--
|
|
4
|
+
-- WHAT IT IS. government_003 limited government_board_items.outcome to 'passed'
|
|
5
|
+
-- and 'returned'. A proposer may now withdraw their own open sitting before
|
|
6
|
+
-- anyone has voted (POST /government/board/items/:itemId/withdraw), which closes
|
|
7
|
+
-- it with outcome 'withdrawn'. 'expired' is added in the same statement because
|
|
8
|
+
-- the docket already names it (modules/government/docket-floors.js
|
|
9
|
+
-- OUTCOME_WORDS) — nothing writes it yet; allowing it now saves a second
|
|
10
|
+
-- constraint swap later.
|
|
11
|
+
--
|
|
12
|
+
-- Additive only: the CHECK is WIDENED. Every row the old CHECK allowed ('passed',
|
|
13
|
+
-- 'returned', NULL for an open item) is still allowed, so no row can fail it and
|
|
14
|
+
-- no data changes. The closed-consistency CHECK (closed_at and outcome set
|
|
15
|
+
-- together) is untouched.
|
|
16
|
+
-- Idempotent: DROP CONSTRAINT IF EXISTS + ADD, the government_017/020 idiom.
|
|
17
|
+
-- The constraint name is the one Postgres gave government_003's inline CHECK.
|
|
18
|
+
-- Approved by the owner on 2026-10-04 — the only schema change that task carries.
|
|
19
|
+
|
|
20
|
+
BEGIN;
|
|
21
|
+
|
|
22
|
+
ALTER TABLE government_board_items
|
|
23
|
+
DROP CONSTRAINT IF EXISTS government_board_items_outcome_check;
|
|
24
|
+
|
|
25
|
+
ALTER TABLE government_board_items
|
|
26
|
+
ADD CONSTRAINT government_board_items_outcome_check
|
|
27
|
+
CHECK (outcome IN ('passed', 'returned', 'withdrawn', 'expired'));
|
|
28
|
+
|
|
29
|
+
COMMIT;
|
|
@@ -25,6 +25,7 @@ const db = require('../db');
|
|
|
25
25
|
const sessionScopes = require('../session-scopes');
|
|
26
26
|
const boardMembership = require('../board-membership');
|
|
27
27
|
const board = require('../board');
|
|
28
|
+
const boardWithdraw = require('../board-withdraw');
|
|
28
29
|
const recommendations = require('../recommendations');
|
|
29
30
|
const docket = require('../docket');
|
|
30
31
|
// task 1003208: structured logging (pino via the doorway) — was console.*.
|
|
@@ -807,6 +808,31 @@ module.exports = function buildGovernmentRouter() {
|
|
|
807
808
|
}
|
|
808
809
|
});
|
|
809
810
|
|
|
811
|
+
// rank: perm board.item.open — withdraw your own open sitting (task 1004564).
|
|
812
|
+
// The same atom as putting one up: taking it back is the proposer's half of
|
|
813
|
+
// the same act. The atom is only the coarse gate; the walls are in
|
|
814
|
+
// board-withdraw.js and repeated in its write — only the builder who opened
|
|
815
|
+
// the sitting, only while it is open and inside its clock, and only before
|
|
816
|
+
// anyone has voted. It closes with outcome 'withdrawn' (government_026).
|
|
817
|
+
router.post('/government/board/items/:itemId/withdraw', api.requireBuilder, api.requirePermission('board.item.open'), async (req, res) => {
|
|
818
|
+
const itemId = parseId(req, res, { param: 'itemId', code: 'bad_item_id', positiveInt: true });
|
|
819
|
+
if (itemId === null) return;
|
|
820
|
+
try {
|
|
821
|
+
const out = await boardWithdraw.withdrawItem({ itemId, builderId: req.builder.id });
|
|
822
|
+
if (!out.ok) {
|
|
823
|
+
const status =
|
|
824
|
+
out.reason === 'item_not_found' ? 404 :
|
|
825
|
+
out.reason === 'not_proposer' ? 403 :
|
|
826
|
+
409; // item_closed / vote_window_expired / votes_cast / item_changed
|
|
827
|
+
return res.fail(out.reason, status, { item_id: itemId });
|
|
828
|
+
}
|
|
829
|
+
res.json({ ok: true, item_closed: true, outcome: out.item.outcome, item: out.item });
|
|
830
|
+
} catch (err) {
|
|
831
|
+
log.error('[gds] POST /government/board/items/:itemId/withdraw', err);
|
|
832
|
+
res.fail('withdraw_failed', { status: 500, message: 'internal error' });
|
|
833
|
+
}
|
|
834
|
+
});
|
|
835
|
+
|
|
810
836
|
// rank: perm board.vote.cast — cast a vote on an open board item (R08 of goal
|
|
811
837
|
// 1000069, ADR 0175). The atom FLOORS AT XENOS deliberately (the R04 carry-
|
|
812
838
|
// note): the permission is only the coarse gate, and the real wall is the
|
|
@@ -91,9 +91,9 @@
|
|
|
91
91
|
|
|
92
92
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
93
93
|
|
|
94
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
95
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
96
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
94
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
95
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
96
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
|
|
51
51
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
52
52
|
chrome exists before the page script runs. -->
|
|
53
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
54
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
55
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
53
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
54
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
55
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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
|
|
@@ -60,9 +60,9 @@
|
|
|
60
60
|
|
|
61
61
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
62
62
|
|
|
63
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
64
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
65
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
63
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
64
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
65
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -83,9 +83,9 @@
|
|
|
83
83
|
</div>
|
|
84
84
|
</div>
|
|
85
85
|
|
|
86
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
87
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
88
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
86
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
87
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
88
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></script>
|
|
89
89
|
<script src="/builders/palette.js" defer></script>
|
|
90
90
|
<script src="/builders/city-draw.js?v=2026-10-02-city1"></script>
|
|
91
91
|
<script src="/builders/city.js?v=2026-10-02-city1"></script>
|
|
@@ -148,9 +148,9 @@
|
|
|
148
148
|
|
|
149
149
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
150
150
|
|
|
151
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
152
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
153
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
151
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
152
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
153
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
|
|
55
55
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
56
56
|
|
|
57
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
58
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
59
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
57
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
58
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
59
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -177,9 +177,9 @@
|
|
|
177
177
|
|
|
178
178
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
179
179
|
|
|
180
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
181
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
182
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
180
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
181
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
182
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
//
|
|
9
9
|
// It is a MODE the existing hall wears, never a second hall (the founding-mode
|
|
10
10
|
// precedent, docs/design/project-startup-direction.md). The nav follows the mode
|
|
11
|
-
// (task 1004493, MODE_TABS below)
|
|
12
|
-
// own tasks (
|
|
11
|
+
// (task 1004493, MODE_TABS below), and so does the look (task 1004495, LOOKS
|
|
12
|
+
// below); the mode tools are their own tasks (1004496 onward). Legacy mode is the
|
|
13
|
+
// hall exactly as it was.
|
|
13
14
|
//
|
|
14
15
|
// NO MODE is the default and the fallback: a reader who closes the picker, a
|
|
15
16
|
// browser whose storage throws, a page that opts out — none of them get the
|
|
@@ -44,15 +45,15 @@
|
|
|
44
45
|
|
|
45
46
|
// ---------- each mode's tabs (task 1004493) ----------
|
|
46
47
|
// A mode shows only the nav items its craft needs, by NAV id (shell.js). ALWAYS
|
|
47
|
-
// is the owner's list of tabs no mode may hide (2026-10-01: Builders first
|
|
48
|
-
// every mode's list is ALWAYS plus its own. A mode with no entry here — Legacy,
|
|
48
|
+
// is the owner's list of tabs no mode may hide (2026-10-01: Builders first;
|
|
49
|
+
// 2026-10-03: Collab and Profile too), and every mode's list is ALWAYS plus its own. A mode with no entry here — Legacy,
|
|
49
50
|
// or no mode at all — shows every tab, exactly as the hall did before.
|
|
50
51
|
// Government lives in Governing alone, and Governing is the shortest list.
|
|
51
52
|
// Hiding is cosmetic: a hidden tab's page still opens by its URL (ADR 0016).
|
|
52
|
-
var ALWAYS_TABS = ['roster'];
|
|
53
|
+
var ALWAYS_TABS = ['roster', 'collab', 'profile'];
|
|
53
54
|
var MODE_TABS = {
|
|
54
55
|
building: ['home', 'roadmap', 'goals', 'goal-map', 'work', 'blockers', 'thinking', 'studio',
|
|
55
|
-
'standing',
|
|
56
|
+
'standing',
|
|
56
57
|
'primer', 'ranks', 'economy', 'commands', 'diagrams', 'atlas', 'modules', 'apidocs'],
|
|
57
58
|
artistry: ['studio', 'goals', 'thinking'],
|
|
58
59
|
ideating: ['goal-map', 'thinking', 'goals'],
|
|
@@ -91,6 +92,40 @@
|
|
|
91
92
|
else head.removeAttribute('data-craft-off');
|
|
92
93
|
}
|
|
93
94
|
}
|
|
95
|
+
// ---------- each mode's look (task 1004495) ----------
|
|
96
|
+
// Artistry, Ideating and Governing each wear a look: the colour tokens in
|
|
97
|
+
// style.css (keyed on html[data-craft]), plus two things only this script can
|
|
98
|
+
// draw — the mode's words beside the page title, and its door's scene framed
|
|
99
|
+
// under the brand (artHtml, the picker's own art, so the two never drift).
|
|
100
|
+
// Building, Legacy and no mode have no entry here and wear nothing.
|
|
101
|
+
var LOOKS = { artistry: 'the studio · night', ideating: 'the sky', governing: 'the city' };
|
|
102
|
+
function remove(el) { if (el && el.parentNode) el.parentNode.removeChild(el); }
|
|
103
|
+
function applyLook(mode) {
|
|
104
|
+
var look = Object.prototype.hasOwnProperty.call(LOOKS, mode) ? LOOKS[mode] : null;
|
|
105
|
+
var plate = document.getElementById('craft-plate');
|
|
106
|
+
if (plate && plate.getAttribute('data-plate') !== (look ? mode : null)) { remove(plate); plate = null; }
|
|
107
|
+
var nav = document.getElementById('app-sidebar');
|
|
108
|
+
var brand = look && nav && nav.querySelector ? nav.querySelector('.app-sidebar__brand') : null;
|
|
109
|
+
if (!plate && brand && brand.parentNode) {
|
|
110
|
+
plate = document.createElement('div');
|
|
111
|
+
plate.id = 'craft-plate';
|
|
112
|
+
plate.className = 'craft-plate';
|
|
113
|
+
plate.setAttribute('data-plate', mode);
|
|
114
|
+
plate.setAttribute('aria-hidden', 'true');
|
|
115
|
+
plate.innerHTML = artHtml(mode);
|
|
116
|
+
brand.parentNode.insertBefore(plate, brand.nextSibling);
|
|
117
|
+
}
|
|
118
|
+
var mark = document.getElementById('craft-eyebrow');
|
|
119
|
+
if (!look) { remove(mark); return; }
|
|
120
|
+
var title = document.getElementById('topbar-title');
|
|
121
|
+
if (!mark && title && title.parentNode) {
|
|
122
|
+
mark = document.createElement('span');
|
|
123
|
+
mark.id = 'craft-eyebrow';
|
|
124
|
+
mark.className = 'craft-eyebrow';
|
|
125
|
+
title.parentNode.insertBefore(mark, title.nextSibling);
|
|
126
|
+
}
|
|
127
|
+
if (mark) mark.textContent = look;
|
|
128
|
+
}
|
|
94
129
|
// sessionStorage: this session's mode, or that the picker was already shown.
|
|
95
130
|
var MODE_KEY = 'hall-craft';
|
|
96
131
|
var ASKED_KEY = 'hall-craft-asked';
|
|
@@ -138,6 +173,7 @@
|
|
|
138
173
|
var sw = document.getElementById('craft-switch');
|
|
139
174
|
if (sw) sw.classList.toggle('craft-switch--unset', !mode);
|
|
140
175
|
applyNav();
|
|
176
|
+
applyLook(mode);
|
|
141
177
|
try { document.dispatchEvent(new CustomEvent('otb:craft', { detail: { mode: mode } })); } catch (_) { /* old engine */ }
|
|
142
178
|
}
|
|
143
179
|
|
|
@@ -344,6 +380,8 @@
|
|
|
344
380
|
ALWAYS_TABS: ALWAYS_TABS.slice(),
|
|
345
381
|
tabsFor: tabsFor,
|
|
346
382
|
applyNav: applyNav,
|
|
383
|
+
LOOKS: LOOKS,
|
|
384
|
+
artHtml: artHtml,
|
|
347
385
|
switchHtml: switchHtml,
|
|
348
386
|
mount: mount,
|
|
349
387
|
onAccess: onAccess,
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
|
|
75
75
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
76
76
|
|
|
77
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
78
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
79
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
77
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
78
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
79
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -97,9 +97,9 @@
|
|
|
97
97
|
|
|
98
98
|
<!-- The app shell (sidebar + top bar + footer). Dependency-free; runs at parse
|
|
99
99
|
time so the chrome exists before the deferred page scripts execute. -->
|
|
100
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
101
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
102
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
100
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
101
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
102
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -98,9 +98,9 @@
|
|
|
98
98
|
|
|
99
99
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
100
100
|
|
|
101
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
102
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
103
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
101
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
102
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
103
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
|
|
55
55
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
56
56
|
|
|
57
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
58
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
59
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
57
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
58
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
59
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -77,9 +77,9 @@
|
|
|
77
77
|
<div id="gate-modal-root"></div>
|
|
78
78
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
79
79
|
|
|
80
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
81
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
82
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
80
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
81
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
82
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -137,9 +137,9 @@
|
|
|
137
137
|
</div>
|
|
138
138
|
</div>
|
|
139
139
|
|
|
140
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
141
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
142
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
140
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
141
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
142
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -230,9 +230,9 @@
|
|
|
230
230
|
|
|
231
231
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
232
232
|
|
|
233
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
234
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
235
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
233
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
234
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
235
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -134,9 +134,9 @@
|
|
|
134
134
|
|
|
135
135
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
136
136
|
|
|
137
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
138
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
139
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
137
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
138
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
139
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
|
|
51
51
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
52
52
|
|
|
53
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
54
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
55
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
53
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
54
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
55
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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
|
|
@@ -225,9 +225,9 @@
|
|
|
225
225
|
|
|
226
226
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
227
227
|
|
|
228
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
229
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
230
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
228
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
229
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
230
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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
|
|
@@ -106,9 +106,9 @@
|
|
|
106
106
|
<script src="/builders/brand-apply.js?v=2026-06-27-r75" defer></script>
|
|
107
107
|
<!-- The app shell (sidebar + top bar + view router). Dependency-free; loaded
|
|
108
108
|
BEFORE builders.js so the chrome ids exist when events are wired. -->
|
|
109
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
110
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
111
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
109
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks" defer></script>
|
|
110
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks" defer></script>
|
|
111
|
+
<script src="/builders/shell.js?v=2026-10-03-looks" 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.
|
|
@@ -101,9 +101,9 @@
|
|
|
101
101
|
|
|
102
102
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
103
103
|
|
|
104
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
105
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
106
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
104
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
105
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
106
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -115,9 +115,9 @@
|
|
|
115
115
|
|
|
116
116
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
117
117
|
|
|
118
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
119
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
120
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
118
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
119
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
120
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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
|
|
@@ -206,9 +206,9 @@
|
|
|
206
206
|
|
|
207
207
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
208
208
|
chrome exists before the page script runs. -->
|
|
209
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
210
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
211
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
209
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
210
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
211
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></script>
|
|
212
212
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
213
213
|
<script src="/builders/palette.js" defer></script>
|
|
214
214
|
<!-- shared frontend toolkit (window.OTB) — loaded before profile.js, which pulls from it. -->
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
|
|
59
59
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
60
60
|
|
|
61
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
62
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
63
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
61
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
62
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
63
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></script>
|
|
64
64
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
65
65
|
<script src="/builders/palette.js" defer></script>
|
|
66
66
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
@@ -77,9 +77,9 @@
|
|
|
77
77
|
|
|
78
78
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
79
79
|
chrome exists before the page script runs. -->
|
|
80
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
81
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
82
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
80
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
81
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
82
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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. -->
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
|
|
42
42
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
43
43
|
|
|
44
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
45
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
46
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
44
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
45
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
46
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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>
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
|
|
54
54
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
55
55
|
chrome exists before the page script runs. -->
|
|
56
|
-
<script src="/builders/shell-trail.js?v=2026-10-03-
|
|
57
|
-
<script src="/builders/craft-mode.js?v=2026-10-03-
|
|
58
|
-
<script src="/builders/shell.js?v=2026-10-03-
|
|
56
|
+
<script src="/builders/shell-trail.js?v=2026-10-03-looks"></script>
|
|
57
|
+
<script src="/builders/craft-mode.js?v=2026-10-03-looks"></script>
|
|
58
|
+
<script src="/builders/shell.js?v=2026-10-03-looks"></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
|