@bongos/core 1.19.1013 → 1.19.1015
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 -85
- package/docs/adr/0227-a-task-network-map-is-refused-the-goal-graph-is-the-map.md +4 -1
- package/docs/adr/0331-the-sky-is-the-ideators-home.md +6 -1
- package/docs/copy-inventory.md +152 -112
- package/docs/copy-registry.json +1001 -304
- package/docs/module-api-changelog.md +4 -0
- package/modules/hall-ui/public/atlas.html +1 -1
- package/modules/hall-ui/public/blockers.html +1 -1
- package/modules/hall-ui/public/board-room.html +1 -1
- package/modules/hall-ui/public/collab.html +1 -1
- package/modules/hall-ui/public/copy-desk.html +1 -1
- package/modules/hall-ui/public/deploy.html +1 -1
- package/modules/hall-ui/public/diagrams.html +1 -1
- package/modules/hall-ui/public/drachmae.html +1 -1
- package/modules/hall-ui/public/fleet-costs.js +80 -0
- package/modules/hall-ui/public/fleet.html +64 -0
- package/modules/hall-ui/public/fleet.js +45 -0
- package/modules/hall-ui/public/fleet.states.json +14 -0
- package/modules/hall-ui/public/gate.html +1 -1
- package/modules/hall-ui/public/goal-map.html +125 -52
- package/modules/hall-ui/public/goal-map.states.json +29 -5
- package/modules/hall-ui/public/goals.html +1 -1
- package/modules/hall-ui/public/government.html +1 -1
- package/modules/hall-ui/public/idea.html +1 -1
- package/modules/hall-ui/public/ideas.html +1 -1
- package/modules/hall-ui/public/index.html +1 -1
- package/modules/hall-ui/public/modules.html +1 -1
- package/modules/hall-ui/public/people.html +1 -1
- package/modules/hall-ui/public/primer.html +1 -1
- package/modules/hall-ui/public/profile.html +1 -1
- package/modules/hall-ui/public/project-settings.html +1 -1
- package/modules/hall-ui/public/ranks.html +1 -1
- package/modules/hall-ui/public/roadmap.html +1 -1
- package/modules/hall-ui/public/roster.html +1 -1
- package/modules/hall-ui/public/sessions.html +1 -1
- package/modules/hall-ui/public/settings.html +1 -1
- package/modules/hall-ui/public/shell.js +15 -0
- package/modules/hall-ui/public/sky-data.js +19 -1
- package/modules/hall-ui/public/sky-interaction.js +14 -7
- package/modules/hall-ui/public/sky-layout.js +2 -1
- package/modules/hall-ui/public/sky-tour.js +10 -6
- package/modules/hall-ui/public/studio.html +1 -1
- package/modules/hall-ui/public/task.html +1 -1
- package/modules/hall-ui/public/thinking.css +6 -3
- package/modules/hall-ui/public/thinking.html +16 -10
- package/modules/hall-ui/public/watch.html +1 -1
- package/modules/hall-ui/public/work.html +1 -1
- package/modules/provisioning/routes/provisioning.js +4 -4
- package/modules/public-landing/public/projects.html +7 -0
- package/modules/ui-design/kit/fixtures/provisioning-instances.json +1 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/bongos/auth.js +8 -0
- package/src/bongos/serve-internal.js +9 -0
- package/src/module-api.js +1 -1
- package/tests/auth_resolve_failure.mjs +3 -2
- package/tests/fleet_cost_view.mjs +189 -0
- package/tests/goal_map_page.mjs +346 -211
- package/tests/hall_audit.mjs +1 -0
- package/tests/hall_nav.mjs +9 -2
- package/tests/hall_page_gate_map.mjs +5 -2
- package/tests/helpers.mjs +21 -5
- package/tests/nav_permission_atoms.mjs +1 -1
- package/tests/render_check.mjs +6 -4
- package/modules/hall-ui/public/goal-map-lib.js +0 -349
- package/modules/hall-ui/public/goal-map.css +0 -117
- package/modules/hall-ui/public/goal-map.js +0 -232
- package/tests/goal_map_lib.mjs +0 -214
|
@@ -2500,5 +2500,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
2500
2500
|
landed since 1.19.1011 with no explicit bump. run 36067980398. (task 1002620)
|
|
2501
2501
|
1.19.1013 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2502
2502
|
landed since 1.19.1012 with no explicit bump. run 36072935774. (task 1002620)
|
|
2503
|
+
1.19.1014 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2504
|
+
landed since 1.19.1013 with no explicit bump. run 36076310606. (task 1002620)
|
|
2505
|
+
1.19.1015 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2506
|
+
landed since 1.19.1014 with no explicit bump. run 36078214605. (task 1002620)
|
|
2503
2507
|
---------------------------------------------------------------------------
|
|
2504
2508
|
```
|
|
@@ -91,7 +91,7 @@
|
|
|
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.js?v=2026-09-
|
|
94
|
+
<script src="/builders/shell.js?v=2026-09-25-sky4b"></script>
|
|
95
95
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
96
96
|
<script src="/builders/palette.js" defer></script>
|
|
97
97
|
<script src="/builders/atlas.js?v=2026-09-02-index" defer></script>
|
|
@@ -50,7 +50,7 @@
|
|
|
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.js?v=2026-09-
|
|
53
|
+
<script src="/builders/shell.js?v=2026-09-25-sky4b"></script>
|
|
54
54
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
55
55
|
<script src="/builders/palette.js" defer></script>
|
|
56
56
|
<!-- shared frontend toolkit (window.OTB — rank labels, number formats) + the
|
|
@@ -60,7 +60,7 @@
|
|
|
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.js?v=2026-09-
|
|
63
|
+
<script src="/builders/shell.js?v=2026-09-25-sky4b"></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-board"></script>
|
|
@@ -148,7 +148,7 @@
|
|
|
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.js?v=2026-09-
|
|
151
|
+
<script src="/builders/shell.js?v=2026-09-25-sky4b"></script>
|
|
152
152
|
<script src="/builders/palette.js" defer></script>
|
|
153
153
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
154
154
|
<script src="/builders/collab-lib.js?v=2026-09-24-archive"></script>
|
|
@@ -177,7 +177,7 @@
|
|
|
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.js?v=2026-09-
|
|
180
|
+
<script src="/builders/shell.js?v=2026-09-25-sky4b"></script>
|
|
181
181
|
<script src="/builders/palette.js" defer></script>
|
|
182
182
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
183
183
|
<script src="/builders/hall-kit.js"></script>
|
|
@@ -60,7 +60,7 @@
|
|
|
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.js?v=2026-09-
|
|
63
|
+
<script src="/builders/shell.js?v=2026-09-25-sky4b"></script>
|
|
64
64
|
<script src="/builders/palette.js" defer></script>
|
|
65
65
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
66
66
|
<script src="/builders/hall-kit.js"></script>
|
|
@@ -97,7 +97,7 @@
|
|
|
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.js?v=2026-09-
|
|
100
|
+
<script src="/builders/shell.js?v=2026-09-25-sky4b"></script>
|
|
101
101
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
102
102
|
<script src="/builders/palette.js" defer></script>
|
|
103
103
|
<script src="/builders/diagram-viewer.js?v=2026-06-14-diagviewer-1" defer></script>
|
|
@@ -98,7 +98,7 @@
|
|
|
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.js?v=2026-09-
|
|
101
|
+
<script src="/builders/shell.js?v=2026-09-25-sky4b"></script>
|
|
102
102
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
103
103
|
<script src="/builders/palette.js" defer></script>
|
|
104
104
|
<script src="/builders/md-reader.js?v=2026-09-02-mdreader-2"></script>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// fleet-costs.js — the fleet cost page's builders (task 1001949, ADR 0327).
|
|
2
|
+
//
|
|
3
|
+
// WHY. GET /provisioning/fleet/cost-ledger answers two questions per project, one
|
|
4
|
+
// column each: what the project costs US, and an ESTIMATE of its owner's own hosting
|
|
5
|
+
// bill. null in either means UNPRICED — the row names no plan anything can price.
|
|
6
|
+
// What this file exists to hold: an unpriced cost never renders as $0 and never moves
|
|
7
|
+
// a total. A $0 there would be a price nobody quoted.
|
|
8
|
+
//
|
|
9
|
+
// Pure, so a test runs the real rendering over the real fixture instead of a copy of
|
|
10
|
+
// it. Exposed as window.OTBFleetCosts; node-require-safe (the roadmap-timeline.js
|
|
11
|
+
// pattern — assignment is the only eval-time side effect). fleet.js is the chrome.
|
|
12
|
+
(() => {
|
|
13
|
+
'use strict';
|
|
14
|
+
|
|
15
|
+
const UNPRICED = 'not priced yet';
|
|
16
|
+
const SHAPE = {
|
|
17
|
+
'cloud-host': 'Cloud host (owner’s account)',
|
|
18
|
+
'byo-host': 'Self-hosted',
|
|
19
|
+
'control-plane': 'This platform’s server',
|
|
20
|
+
'co-tenant': 'Shared server (retired)',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const ESC = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' };
|
|
24
|
+
const esc = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, (c) => ESC[c]);
|
|
25
|
+
const isPriced = (v) => typeof v === 'number' && Number.isFinite(v);
|
|
26
|
+
const quiet = (text) => `<span class="ledger__est">${text}</span>`;
|
|
27
|
+
|
|
28
|
+
function money(v) {
|
|
29
|
+
if (!isPriced(v)) return null;
|
|
30
|
+
return `$${Number.isInteger(v) ? v : v.toFixed(2)}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// A self-hosted project runs on its owner's own machine, so its bill is not ours to
|
|
34
|
+
// see: a different absence from a plan nobody has recorded yet.
|
|
35
|
+
function cellHtml(v, shape, column) {
|
|
36
|
+
if (isPriced(v)) return esc(money(v));
|
|
37
|
+
return quiet(column === 'owner' && shape === 'byo-host' ? 'not visible to us' : UNPRICED);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// The server's total sums only priced rows and counts the rest as one number; the
|
|
41
|
+
// self-hosted share of that count is split back out so the total says what its cells
|
|
42
|
+
// say. A column with NOTHING priced gets no figure at all: the sum of no prices is not $0.
|
|
43
|
+
function totalHtml(total, rows, column) {
|
|
44
|
+
const unpriced = Number(total && total.unpriced) || 0;
|
|
45
|
+
const hidden = column === 'owner'
|
|
46
|
+
? rows.filter((r) => r.hosting_shape === 'byo-host' && !isPriced(r.owner_monthly_usd)).length
|
|
47
|
+
: 0;
|
|
48
|
+
const notPriced = unpriced - hidden;
|
|
49
|
+
if (rows.length - unpriced <= 0) return quiet(notPriced > 0 ? UNPRICED : 'not visible to us');
|
|
50
|
+
const notes = [notPriced > 0 && `${notPriced} not priced`, hidden > 0 && `${hidden} not visible`].filter(Boolean);
|
|
51
|
+
const figure = esc(money(Number(total && total.monthly_usd) || 0));
|
|
52
|
+
return notes.length ? `${figure} ${quiet(`+ ${notes.join(', ')}`)}` : figure;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function rowHtml(r) {
|
|
56
|
+
return `<tr>
|
|
57
|
+
<td>${esc(r.slug)}</td>
|
|
58
|
+
<td>${esc(r.owner)}</td>
|
|
59
|
+
<td>${esc(SHAPE[r.hosting_shape] || r.hosting_shape)}</td>
|
|
60
|
+
<td>${r.tier ? esc(r.tier) : quiet('none recorded')}</td>
|
|
61
|
+
<td class="ledger__num">${cellHtml(r.platform_monthly_usd, r.hosting_shape, 'platform')}</td>
|
|
62
|
+
<td class="ledger__num">${cellHtml(r.owner_monthly_usd, r.hosting_shape, 'owner')}</td>
|
|
63
|
+
</tr>`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function ledgerHtml(ledger) {
|
|
67
|
+
const rows = ledger && Array.isArray(ledger.instances) ? ledger.instances : [];
|
|
68
|
+
if (!rows.length) return '<p class="ledger__note">No projects are hosted here yet.</p>';
|
|
69
|
+
const totals = (ledger && ledger.totals) || {};
|
|
70
|
+
return `<table class="ledger" id="fl-table">
|
|
71
|
+
<thead><tr><th>Project</th><th>Owner</th><th>Hosting</th><th>Plan</th><th>Costs us / month</th><th>Owner’s bill / month (est.)</th></tr></thead>
|
|
72
|
+
<tbody>${rows.map(rowHtml).join('')}</tbody>
|
|
73
|
+
<tfoot><tr><th scope="row" colspan="4">Total</th><td class="ledger__num">${totalHtml(totals.platform, rows, 'platform')}</td><td class="ledger__num">${totalHtml(totals.owner, rows, 'owner')}</td></tr></tfoot>
|
|
74
|
+
</table>`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const api = { money, ledgerHtml };
|
|
78
|
+
if (typeof window !== 'undefined') window.OTBFleetCosts = api;
|
|
79
|
+
if (typeof module !== 'undefined' && module.exports) module.exports = api;
|
|
80
|
+
})();
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>Fleet costs — {{worldName}}</title>
|
|
7
|
+
<meta name="description" content="What each hosted project costs this platform, and an estimate of what its owner pays for their own hosting.">
|
|
8
|
+
<link rel="icon" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><text x='16' y='24' font-size='24' text-anchor='middle' font-family='sans-serif'>⌂</text></svg>">
|
|
9
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
10
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
11
|
+
<link rel="stylesheet" href="/builders/style.css?v=2026-09-23-changelist1">
|
|
12
|
+
<link rel="stylesheet" href="/builders/oversight.css">
|
|
13
|
+
<link rel="stylesheet" href="/builders/project-settings.css">
|
|
14
|
+
</head>
|
|
15
|
+
<body data-page="fleet" data-page-title="Fleet costs">
|
|
16
|
+
|
|
17
|
+
<div class="app">
|
|
18
|
+
<aside class="app-sidebar" id="app-sidebar" aria-label="Primary"></aside>
|
|
19
|
+
<div class="app-scrim" id="app-scrim" hidden></div>
|
|
20
|
+
<div class="app-body">
|
|
21
|
+
<header class="app-topbar" id="app-topbar"></header>
|
|
22
|
+
<div class="app-content">
|
|
23
|
+
<div class="page-head page-head--board">
|
|
24
|
+
<h1 class="page-head__h">Fleet costs</h1>
|
|
25
|
+
<p class="page-head__sub" id="fl-sub">Loading…</p>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<main id="hall-main">
|
|
29
|
+
<section class="scroll" id="fl-sealed" aria-labelledby="fl-sealed-h" hidden>
|
|
30
|
+
<h2 class="scroll__h" id="fl-sealed-h">Restricted</h2>
|
|
31
|
+
<p class="scroll__lede">This page opens at a higher rank.</p>
|
|
32
|
+
</section>
|
|
33
|
+
|
|
34
|
+
<section class="scroll" id="fl-body" aria-labelledby="fl-body-h" hidden>
|
|
35
|
+
<h2 class="scroll__h" id="fl-body-h">What each project costs</h2>
|
|
36
|
+
<!-- Two different bills, one column each (ADR 0327): a cloud host runs on its
|
|
37
|
+
OWNER's account, so it costs this platform nothing and its owner pays their
|
|
38
|
+
hosting provider directly. Nothing on this page is charged to anyone. -->
|
|
39
|
+
<p class="scroll__lede">
|
|
40
|
+
Two different bills, one column each. The first is what a project costs this
|
|
41
|
+
platform. The second is an estimate of what its owner pays their own hosting
|
|
42
|
+
provider, which bills them directly. A project with no recorded plan reads
|
|
43
|
+
"not priced yet", never $0, and is left out of the total. A self-hosted
|
|
44
|
+
project runs on its owner's own machine, so its bill is not visible to us.
|
|
45
|
+
</p>
|
|
46
|
+
<div id="fl-panel"><span class="kit-skel"></span></div>
|
|
47
|
+
</section>
|
|
48
|
+
</main>
|
|
49
|
+
|
|
50
|
+
<footer class="app-foot" id="app-foot"></footer>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
56
|
+
|
|
57
|
+
<script src="/builders/shell.js?v=2026-09-25-sky4b"></script>
|
|
58
|
+
<script src="/builders/palette.js" defer></script>
|
|
59
|
+
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
60
|
+
<script src="/builders/hall-kit.js"></script>
|
|
61
|
+
<script src="/builders/fleet-costs.js"></script>
|
|
62
|
+
<script src="/builders/fleet.js"></script>
|
|
63
|
+
</body>
|
|
64
|
+
</html>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// fleet.js — the fleet cost page (task 1001949, ADR 0327): the chrome around
|
|
2
|
+
// fleet-costs.js, which does all the drawing.
|
|
3
|
+
//
|
|
4
|
+
// One read, GET /provisioning/fleet/cost-ledger, gated on `provisioning.fleet.manage`
|
|
5
|
+
// exactly as this page is. A 403 shows the sealed state rather than an empty table,
|
|
6
|
+
// so a refusal is never mistaken for a fleet with nothing in it.
|
|
7
|
+
(() => {
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
const API = '/api/bongos';
|
|
11
|
+
const api = window.BongosClient.createClient({ baseUrl: '', credentials: 'same-origin', throwOnError: false });
|
|
12
|
+
const { escapeHtml } = window.OTB;
|
|
13
|
+
const $ = (id) => document.getElementById(id);
|
|
14
|
+
|
|
15
|
+
function fail(message) {
|
|
16
|
+
$('fl-body').hidden = false;
|
|
17
|
+
$('fl-sub').textContent = 'Unavailable';
|
|
18
|
+
$('fl-panel').innerHTML = `<p class="ps-invalid">${escapeHtml(message)}</p>`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function load() {
|
|
22
|
+
let res;
|
|
23
|
+
try {
|
|
24
|
+
res = await api.request('GET', `${API}/provisioning/fleet/cost-ledger`);
|
|
25
|
+
} catch (e) {
|
|
26
|
+
return fail('Could not reach the server.');
|
|
27
|
+
}
|
|
28
|
+
if (res.status === 401) { window.location.assign(`${API}/auth/web/start`); return; }
|
|
29
|
+
if (res.status === 403) {
|
|
30
|
+
$('fl-sealed').hidden = false;
|
|
31
|
+
$('fl-sub').textContent = 'Restricted';
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (!res.ok) {
|
|
35
|
+
const err = (res.data && res.data.error) || {};
|
|
36
|
+
return fail(err.message && err.message !== err.code ? err.message : 'Could not read the fleet costs.');
|
|
37
|
+
}
|
|
38
|
+
const n = ((res.data && res.data.instances) || []).length;
|
|
39
|
+
$('fl-sub').textContent = `${n} project${n === 1 ? '' : 's'}`;
|
|
40
|
+
$('fl-body').hidden = false;
|
|
41
|
+
$('fl-panel').innerHTML = window.OTBFleetCosts.ledgerHtml(res.data);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
document.addEventListener('DOMContentLoaded', load);
|
|
45
|
+
})();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_": "FLEET COSTS (task 1001949, ADR 0327) through modules/ui-design/kit/render.js. The page reads ONE authenticated route, GET /provisioning/fleet/cost-ledger, gated on provisioning.fleet.manage, so against the kit's own stub it renders its failed-read state — a state the floors must hold in. To look at the populated ledger run it against the hall-preview harness, whose provisioning__fleet__cost-ledger.json fixture carries two cloud hosts with no recorded plan (every owner cost unpriced, the state live is in today):\n\n node scripts/hall-preview/server.js --port 4620 --fixture-me\n node modules/ui-design/kit/render.js --states modules/hall-ui/public/fleet.states.json --base-in http://localhost:4620 --base-out http://localhost:4620",
|
|
3
|
+
"page": "/builders/fleet",
|
|
4
|
+
"surface": "hall-ui",
|
|
5
|
+
"stub": { "prefix": "/builders/" },
|
|
6
|
+
"modeQuery": false,
|
|
7
|
+
"ignoreRequests": ["/api/(gds|bongos)/"],
|
|
8
|
+
"ignoreConsole": ["/api/(gds|bongos)/", "\\b401\\b", "\\b403\\b", "\\b404\\b", "Unauthorized", "Forbidden", "Not Found", "load failed"],
|
|
9
|
+
"states": {
|
|
10
|
+
"ledger": { "auth": true, "actions": [["wait", 800]], "expect": { "visible": ["#fl-body"] } },
|
|
11
|
+
"out": { "auth": false, "actions": [["wait", 600]] }
|
|
12
|
+
},
|
|
13
|
+
"reducedMotion": { "auth": true, "actions": [["wait", 800]] }
|
|
14
|
+
}
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
<div id="gate-modal-root"></div>
|
|
77
77
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
78
78
|
|
|
79
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
79
|
+
<script src="/builders/shell.js?v=2026-09-25-sky4b"></script>
|
|
80
80
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
81
81
|
<script src="/builders/palette.js" defer></script>
|
|
82
82
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
@@ -2,69 +2,142 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
-
<title>
|
|
7
|
-
<meta name="description" content="
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
6
|
+
<title>The sky — {{worldName}}</title>
|
|
7
|
+
<meta name="description" content="The whole project, drawn from the ledger: every goal a gravity well sized by its credits, the routes between goals that wait on each other, and a ledger drawer that lists all of it.">
|
|
8
8
|
<link rel="icon" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><text x='16' y='24' font-size='24' text-anchor='middle' font-family='sans-serif'>⌂</text></svg>">
|
|
9
9
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
10
10
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
<!-- The faces (Manrope, JetBrains Mono) come from the branding pack's font
|
|
12
|
+
links, injected into this head by the server like every hall page's
|
|
13
|
+
(tests/hall_tokens.mjs: no hall page hardcodes a web-font stylesheet). -->
|
|
14
|
+
<link rel="stylesheet" href="/builders/thinking.css?v=2026-09-25-sky4">
|
|
13
15
|
</head>
|
|
14
|
-
<!-- THE
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
<!-- THE PROJECT SKY (task 1004232 / sky part 4 of 5, goal 1000095; ADR 0331,
|
|
17
|
+
ADR 0227 §11). The SAME page as /thinking — docs/design/mocks/sky/
|
|
18
|
+
sky.template.html, the prototype the owner adopted as the design of record
|
|
19
|
+
— opened in its "the whole project" lens: goals as wells sized by credits,
|
|
20
|
+
settled and collapsed goals with mass, alive wells glowing, routes as rim
|
|
21
|
+
arrows charted by a shuttle, explore on by default, the clock, "my ideas"
|
|
22
|
+
off by default, and the ledger drawer (L) — every goal, both directions of
|
|
23
|
+
each dependency by name — which is what the old goal map's table said and
|
|
24
|
+
is the accessible path. It replaced that goal map (task 1003479) at this
|
|
25
|
+
URL and took the nav slot the map was denied, under Goals (owner,
|
|
26
|
+
2026-09-24; ADR 0227 §11).
|
|
20
27
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
The markup is thinking.html's, verbatim but for three things: the body
|
|
29
|
+
says which lens is home (`data-sky-lens="all"` — sky-tour.js boots into it
|
|
30
|
+
and the tour hands back to it), the brand line and the lens switcher start
|
|
31
|
+
in that lens, and the canvas's own words say what this sky draws. The
|
|
32
|
+
sheet and the seven sky-*.js files are SHARED with /thinking, never
|
|
33
|
+
copied: the switcher's "simple" and "your thinking" leave for /thinking,
|
|
34
|
+
and /thinking's "the whole project" leaves for here. The same rule as
|
|
35
|
+
/thinking on chrome: none — the sky is a full-screen surface with its own
|
|
36
|
+
header, and the hall's doors (the goal, the task, the record) open from
|
|
37
|
+
the panel.
|
|
31
38
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
</section>
|
|
39
|
+
ADR 0227 §1's refusal stands here: tasks are drawn only inside ONE goal
|
|
40
|
+
once its well is past the zoom threshold (dust density on its rings below
|
|
41
|
+
it), never for every goal at once, and there is no "show every task"
|
|
42
|
+
control — tests/goal_map_page.mjs pins both. -->
|
|
43
|
+
<body data-page="goal-map" data-page-title="The sky" data-sky-lens="all">
|
|
38
44
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
<!-- The one <main> landmark the kit's a11y floor asks of every hall page
|
|
46
|
+
(one-header-main-h1). The canvas is the page's content, and the landmark
|
|
47
|
+
wraps it with no rule of its own, so nothing moves — the canvas is
|
|
48
|
+
position: fixed. -->
|
|
49
|
+
<main>
|
|
50
|
+
<canvas id="sky" tabindex="0" role="img" aria-label="The sky, drawn from the ledger: every goal a gravity well, every dependency a route. Every goal here is also a row in the ledger; press L to open it, ? to take the tour."></canvas>
|
|
51
|
+
</main>
|
|
44
52
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
<!-- The <header> is the BRAND (the h1 and the figures) and the lens and tools
|
|
54
|
+
stay its siblings inside the same .top strip — the kit's phone floor
|
|
55
|
+
(top-bar-80px) measures the page's <header>. thinking.html's shape. -->
|
|
56
|
+
<div class="top">
|
|
57
|
+
<header class="brand">
|
|
58
|
+
<h1>the sky <em id="lensWord">— the whole project</em></h1>
|
|
59
|
+
<div class="stats" id="stats"></div>
|
|
60
|
+
</header>
|
|
61
|
+
<div class="lens" role="group" aria-label="Filter" id="lensGroup">
|
|
62
|
+
<button type="button" id="lensSimple" aria-pressed="false">simple</button>
|
|
63
|
+
<button type="button" id="lensMine" aria-pressed="false">your thinking</button>
|
|
64
|
+
<button type="button" id="lensAll" aria-pressed="true">the whole project</button>
|
|
65
|
+
</div>
|
|
66
|
+
<div class="tools" id="tools">
|
|
67
|
+
<button type="button" class="pill" id="roomBtn" aria-pressed="false" title="The same sky, as a list (L)">list</button>
|
|
68
|
+
<button type="button" class="pill" id="recentBtn" aria-pressed="false" hidden title="Only the thoughts of the last thirty days.">recent</button>
|
|
69
|
+
<button type="button" class="pill" id="claudeBtn" aria-pressed="false" hidden title="Show the thoughts a session filed under your name. Off by default: only what a person filed.">claude layer</button>
|
|
70
|
+
<button type="button" class="pill" id="influenceBtn" aria-pressed="false" hidden title="Only the goals your thoughts touched — everything else fades.">my influence</button>
|
|
71
|
+
<button type="button" class="pill" id="exploreBtn" aria-pressed="true" title="Explore: the sky reveals itself as you follow routes from where you begin.">explore</button>
|
|
72
|
+
<button type="button" class="pill" id="ideasBtn" aria-pressed="false" title="Lay your thoughts over the project map.">my ideas</button>
|
|
73
|
+
<button type="button" class="pill" id="rehearse" aria-pressed="false" hidden title="What if: invents removals, dimming and nods — none has happened in the ledger yet — so you can see how the dead would read. Sizes are never invented.">what if</button>
|
|
74
|
+
<button type="button" class="pill icon" id="clockBtn" title="Show or hide the clock" aria-label="Show or hide the clock">◷</button>
|
|
75
|
+
<button type="button" class="pill icon" id="tourBtn" title="How to read the sky (?)" aria-label="How to read the sky">?</button>
|
|
76
|
+
<button type="button" class="pill icon" id="fitBtn" title="Fit the sky (0)" aria-label="Fit the whole sky">⌂</button>
|
|
54
77
|
</div>
|
|
55
78
|
</div>
|
|
56
79
|
|
|
57
|
-
<div
|
|
80
|
+
<div class="jump">
|
|
81
|
+
<input type="search" id="jump" placeholder="jump to a goal or a thought" autocomplete="off" aria-label="Jump to a goal or a thought">
|
|
82
|
+
<ul id="jumpList" hidden></ul>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<div class="composer" id="composerWrap">
|
|
86
|
+
<form id="file" autocomplete="off">
|
|
87
|
+
<input type="text" id="thought" placeholder="release a thought — one line" aria-label="Release a thought" maxlength="180">
|
|
88
|
+
<button type="button" class="mode" id="fullToggle" aria-pressed="false" title="File it as a Full Idea: the line, then five questions, scored on completeness. Off = a quick idea, one line.">full idea</button>
|
|
89
|
+
<button type="submit" class="go" id="fileGo">file</button>
|
|
90
|
+
</form>
|
|
91
|
+
<div class="gravity" id="gravity" aria-live="polite">gravity — the goal that catches it lights as you type; letting it float is a real answer</div>
|
|
92
|
+
<div class="steps" id="fullSteps" hidden></div>
|
|
93
|
+
<div class="receipt" id="receipt" hidden role="status"><span class="dot"></span><span id="receiptText"></span><button type="button" id="receiptGo">see it</button><button type="button" id="receiptX" aria-label="Dismiss">×</button></div>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<div class="card glass" id="card" role="tooltip" aria-hidden="true"></div>
|
|
97
|
+
<div class="menu glass" id="menu" hidden role="menu" aria-label="Chart the routes"></div>
|
|
98
|
+
|
|
99
|
+
<aside class="room" id="room" hidden aria-label="The list">
|
|
100
|
+
<div class="head"><h2 id="roomTitle">the ledger</h2><span class="lbl" id="roomCount"></span></div>
|
|
101
|
+
<div class="filters" id="filters" role="group" aria-label="Filter"></div>
|
|
102
|
+
<div class="rows" id="rows"></div>
|
|
103
|
+
</aside>
|
|
104
|
+
|
|
105
|
+
<aside class="panel" id="panel" hidden aria-live="polite"></aside>
|
|
106
|
+
|
|
107
|
+
<div class="start glass" id="start" hidden role="dialog" aria-label="Where do you begin?">
|
|
108
|
+
<span class="lbl">explore</span>
|
|
109
|
+
<h3>Where do you begin?</h3>
|
|
110
|
+
<p>The sky reveals itself as you go. Pick a well to start in; every route you chart brings the goal at its far end into view.</p>
|
|
111
|
+
<div class="opts" id="startOpts"></div>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<div class="tour glass" id="tour" hidden role="dialog" aria-label="How to read the sky">
|
|
115
|
+
<div class="step"><span class="lbl" id="tourN"></span><span class="dots" id="tourDots"></span></div>
|
|
116
|
+
<h3 id="tourH"></h3>
|
|
117
|
+
<p id="tourP"></p>
|
|
118
|
+
<div class="acts"><button type="button" class="door primary" id="tourNext">next</button><button type="button" class="door" id="tourBack">back</button><button type="button" class="skip" id="tourSkip">skip the tour</button></div>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<footer class="foot">
|
|
122
|
+
<div class="time" id="time">
|
|
123
|
+
<button type="button" class="play" id="play" aria-pressed="false" aria-label="Replay the sky from the first day">▶</button>
|
|
124
|
+
<input type="range" id="clock" min="0" max="1000" value="1000" aria-label="The day the sky is drawn for">
|
|
125
|
+
<span class="when" id="when">today</span>
|
|
126
|
+
<button type="button" class="hide" id="timeHide" aria-label="Hide the clock">×</button>
|
|
127
|
+
</div>
|
|
128
|
+
<div class="footrow">
|
|
129
|
+
<div class="legend" id="legend"></div>
|
|
130
|
+
<div class="alt" id="alt"></div>
|
|
131
|
+
</div>
|
|
132
|
+
</footer>
|
|
58
133
|
|
|
59
|
-
<script src="/builders/
|
|
60
|
-
<script src="/builders/
|
|
61
|
-
<script src="/builders/
|
|
62
|
-
<script src="/builders/
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
<script src="/builders/
|
|
66
|
-
|
|
67
|
-
<script src="/builders/text-fit.js"></script>
|
|
68
|
-
<script src="/builders/goal-map.js"></script>
|
|
134
|
+
<script src="/builders/idea-objects.js?v=2026-09-25-sky4"></script>
|
|
135
|
+
<script src="/builders/sky-data.js?v=2026-09-25-sky4"></script>
|
|
136
|
+
<script src="/builders/sky-layout.js?v=2026-09-25-sky4"></script>
|
|
137
|
+
<script src="/builders/sky-draw.js?v=2026-09-25-sky4"></script>
|
|
138
|
+
<script src="/builders/sky-interaction.js?v=2026-09-25-sky4"></script>
|
|
139
|
+
<script src="/builders/sky-panel.js?v=2026-09-25-sky4"></script>
|
|
140
|
+
<script src="/builders/sky-composer.js?v=2026-09-25-sky4"></script>
|
|
141
|
+
<script src="/builders/sky-tour.js?v=2026-09-25-sky4"></script>
|
|
69
142
|
</body>
|
|
70
143
|
</html>
|
|
@@ -1,14 +1,38 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_": "THE
|
|
2
|
+
"_": "THE PROJECT SKY (task 1004232 / sky part 4 of 5, goal 1000095; ADR 0331, ADR 0227 §11) through modules/ui-design/kit/render.js — the same page as /thinking (thinking.states.json) opened in its 'the whole project' lens. The page draws GET /sky + GET /sky/mine; against the kit's own stub neither exists, so every state below renders the EMPTY sky — a real state the floors must hold in (the lenses, the tools, the ledger drawer and the tour all exist with no goal read). To look at the populated sky — the wells sized by credits, the routes, the shuttle menu, explore's 'where do you begin' — run it against the hall-preview harness, whose sky.json + sky__mine.json fixtures carry the wells and the routes:\n\n node scripts/hall-preview/server.js --port 4620 --fixture-me\n node modules/ui-design/kit/render.js --states modules/hall-ui/public/goal-map.states.json --base-in http://localhost:4620 --base-out http://localhost:4620\n\nThe tour opens by itself on a first visit (sky-tour-seen), so states that want the bare sky skip it first; explore is on by default and asks where you begin the first time (sky-seen), so the 'sky' state renders that prompt on purpose.",
|
|
3
3
|
"page": "/builders/goal-map",
|
|
4
4
|
"surface": "hall-ui",
|
|
5
5
|
"stub": { "prefix": "/builders/" },
|
|
6
|
+
"modes": ["dark"],
|
|
6
7
|
"modeQuery": false,
|
|
7
|
-
"ignoreRequests": ["/api/(gds|bongos)/"],
|
|
8
|
-
"ignoreConsole": ["/api/(gds|bongos)/", "\\b401\\b", "\\b404\\b", "Unauthorized", "Not Found", "load failed"],
|
|
8
|
+
"ignoreRequests": ["/api/(gds|bongos)/", "fonts\\.g(oogleapis|static)\\.com"],
|
|
9
|
+
"ignoreConsole": ["/api/(gds|bongos)/", "\\b401\\b", "\\b404\\b", "Unauthorized", "Not Found", "load failed", "fonts\\.g(oogleapis|static)\\.com"],
|
|
9
10
|
"states": {
|
|
10
|
-
"
|
|
11
|
+
"tour": {
|
|
12
|
+
"auth": true,
|
|
13
|
+
"_": "The first visit: the project sky with the tour's first step over it.",
|
|
14
|
+
"actions": [["wait", 1400]],
|
|
15
|
+
"expect": { "visible": ["#sky", "#tour"] }
|
|
16
|
+
},
|
|
17
|
+
"sky": {
|
|
18
|
+
"auth": true,
|
|
19
|
+
"_": "The 'the whole project' lens, bare: the brand line, the lenses, explore + my ideas + the clock in the tools, the legend — and explore's 'where do you begin' prompt on a first visit.",
|
|
20
|
+
"actions": [["wait", 1200], ["clickIfVisible", "#tourSkip"], ["wait", 300]],
|
|
21
|
+
"expect": { "visible": ["#sky", "#exploreBtn", "#ideasBtn"] }
|
|
22
|
+
},
|
|
23
|
+
"wells": {
|
|
24
|
+
"auth": true,
|
|
25
|
+
"_": "The whole sky at once: 'show me everything' answers the prompt, explore goes off, and every well is drawn — the shot to compare with the old goal map.",
|
|
26
|
+
"actions": [["wait", 1200], ["clickIfVisible", "#tourSkip"], ["wait", 200], ["clickIfVisible", "#startOpts [data-start=\"all\"]"], ["wait", 700]],
|
|
27
|
+
"expect": { "visible": ["#sky", "#exploreBtn"] }
|
|
28
|
+
},
|
|
29
|
+
"ledger": {
|
|
30
|
+
"auth": true,
|
|
31
|
+
"_": "The ledger drawer — every goal as a row, with the alive / wells / settled / collapsed / with-routes filters — opened by the L key.",
|
|
32
|
+
"actions": [["wait", 1200], ["clickIfVisible", "#tourSkip"], ["wait", 200], ["press", "l"], ["wait", 300]],
|
|
33
|
+
"expect": { "visible": ["#room", "#rows"] }
|
|
34
|
+
},
|
|
11
35
|
"out": { "auth": false, "actions": [["wait", 600]] }
|
|
12
36
|
},
|
|
13
|
-
"reducedMotion": { "auth": true, "actions": [["wait", 1200]] }
|
|
37
|
+
"reducedMotion": { "auth": true, "actions": [["wait", 1200], ["clickIfVisible", "#tourSkip"], ["wait", 200]] }
|
|
14
38
|
}
|
|
@@ -235,7 +235,7 @@
|
|
|
235
235
|
|
|
236
236
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
237
237
|
|
|
238
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
238
|
+
<script src="/builders/shell.js?v=2026-09-25-sky4b"></script>
|
|
239
239
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
240
240
|
<script src="/builders/palette.js" defer></script>
|
|
241
241
|
<script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
|
|
@@ -134,7 +134,7 @@
|
|
|
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.js?v=2026-09-
|
|
137
|
+
<script src="/builders/shell.js?v=2026-09-25-sky4b"></script>
|
|
138
138
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
139
139
|
<script src="/builders/palette.js" defer></script>
|
|
140
140
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
|
|
53
53
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
54
54
|
|
|
55
|
-
<script src="/builders/shell.js?v=2026-09-
|
|
55
|
+
<script src="/builders/shell.js?v=2026-09-25-sky4b"></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,7 +225,7 @@
|
|
|
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.js?v=2026-09-
|
|
228
|
+
<script src="/builders/shell.js?v=2026-09-25-sky4b"></script>
|
|
229
229
|
<script src="/builders/palette.js" defer></script>
|
|
230
230
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
231
231
|
<!-- task 1003069 (R08) — the quick-filing form's routed result links a task
|