@bongos/core 1.24.43 → 1.24.45
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 +71 -76
- package/docs/copy-inventory.md +42 -74
- package/docs/copy-registry.json +87 -446
- package/docs/file-map.md +1 -1
- package/docs/module-api-changelog.md +4 -0
- package/docs/page-inventory.json +8 -36
- package/docs/page-readings.json +374 -431
- package/modules/hall-ui/public/ai-studio.html +2 -2
- package/modules/hall-ui/public/atlas.html +2 -2
- package/modules/hall-ui/public/blockers.html +2 -2
- package/modules/hall-ui/public/board-room.html +2 -2
- package/modules/hall-ui/public/city.html +2 -2
- package/modules/hall-ui/public/collab.html +2 -2
- package/modules/hall-ui/public/commands.html +2 -2
- package/modules/hall-ui/public/copy-desk.html +2 -2
- package/modules/hall-ui/public/craft-mode.js +4 -1
- package/modules/hall-ui/public/deploy.html +2 -2
- package/modules/hall-ui/public/goal-map.html +2 -2
- package/modules/hall-ui/public/goals.html +14 -2
- package/modules/hall-ui/public/government.html +2 -2
- package/modules/hall-ui/public/idea.html +2 -2
- package/modules/hall-ui/public/ideas.html +2 -2
- package/modules/hall-ui/public/index.html +2 -2
- package/modules/hall-ui/public/market-watch-item.html +2 -2
- package/modules/hall-ui/public/market-watch-rules.html +2 -2
- package/modules/hall-ui/public/market-watch.html +2 -2
- package/modules/hall-ui/public/modules.html +2 -2
- package/modules/hall-ui/public/money.html +2 -2
- package/modules/hall-ui/public/my-agents.html +2 -2
- package/modules/hall-ui/public/primer.html +2 -2
- package/modules/hall-ui/public/profile.html +2 -2
- package/modules/hall-ui/public/project-settings.html +2 -2
- package/modules/hall-ui/public/roadmap.css +7 -138
- package/modules/hall-ui/public/roadmap.js +35 -293
- package/modules/hall-ui/public/roster.html +2 -2
- package/modules/hall-ui/public/settings.html +2 -2
- package/modules/hall-ui/public/shell.js +24 -4
- package/modules/hall-ui/public/street.html +2 -2
- package/modules/hall-ui/public/studio.html +2 -2
- package/modules/hall-ui/public/task.html +2 -2
- package/modules/hall-ui/public/thinking.html +2 -2
- package/modules/hall-ui/public/tweak-editor.html +2 -2
- package/modules/hall-ui/public/watch.html +2 -2
- package/modules/hall-ui/public/work.html +3 -3
- package/modules/hall-ui/records/hall-navigation.md +5 -0
- package/modules/onboarding/founding-mode.js +2 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +12 -0
- package/scripts/bongos/gen-hall-sitemap.js +4 -1
- package/src/bongos/serve-internal.js +6 -6
- package/src/module-api.js +1 -1
- package/tests/craft_mode_nav.mjs +53 -4
- package/tests/founding_mode.mjs +5 -3
- package/tests/hall_goals_band.mjs +88 -0
- package/tests/hall_kit_charts.mjs +4 -3
- package/tests/hall_nav.mjs +5 -2
- package/tests/hall_page_gate_map.mjs +5 -1
- package/tests/hall_reading_world.mjs +17 -18
- package/tests/hall_sitemap.mjs +2 -1
- package/tests/nav_permission_atoms.mjs +4 -2
- package/modules/hall-ui/public/roadmap.html +0 -58
- package/modules/hall-ui/public/roadmap.states.json +0 -31
|
@@ -28,3 +28,8 @@ Covers: every shelled hall page (`shell.js`, `style.css`), plus `goal-map.html`
|
|
|
28
28
|
`goal-map.html` now uses thinking.html's structure: sidebar and top-bar mounts, `style.css`, `shell.js`, the sky inside `<main id="hall-main" class="sky-stage">`, and a `<div class="brand">` because the shell's bar is the page's one `<header>`. In `thinking.css` both pages share one stage rule, `body[data-page] .sky-stage`. No hall page is standalone any more (`tests/hall_audit.mjs` `STANDALONE_EXEMPT` is empty).
|
|
29
29
|
|
|
30
30
|
Tests: `tests/hall_fullscreen.mjs` (the standard switch, `plain`, Back link, trail, fallback and exit cases), `tests/hall_record_world.mjs` §10 (the record places its exit), `tests/goal_map_page.mjs`, `tests/hall_audit.mjs` §8.
|
|
31
|
+
|
|
32
|
+
## The rail paints at once, and Home is one button (task 1005070)
|
|
33
|
+
|
|
34
|
+
- Every hall page is a full load, and the gate waits on `/me`, so the rail used to boot with only Home and pop the rest in once `/me` answered — longest for the owner, whose `/me` is the heaviest. `shell.js` now keeps the last settled access in `localStorage['hall-nav-access']` (rank, graduated/showWork, the nav permission map, the user chip; never the needs roster, so no badge is stale) and paints from it at boot. `/me` still settles the real state. It is forgotten on any signed-out settle (a 401 or a refused 403) and by the sign-out link, and is not painted once a day old.
|
|
35
|
+
- In a craft the plate under the brand is the Home button (task 1005065), so no mode's tab list names `home` — Building used to, which drew two home icons. With no craft chosen there is no plate and the Home tab shows. Pinned in `tests/craft_mode_nav.mjs`.
|
|
@@ -34,7 +34,8 @@ const STAGES = Object.freeze(['decide', 'scope', 'strategize', 'charter', 'legal
|
|
|
34
34
|
// 'community' wakes only when the planet is ALIVE, which is when founding mode switches
|
|
35
35
|
// off entirely, so during founding it is always asleep.
|
|
36
36
|
const WAKES = Object.freeze({
|
|
37
|
-
|
|
37
|
+
// task 1005051: Roadmap folded into Goals, so scope wakes Goals and its map.
|
|
38
|
+
scope: Object.freeze(['goals', 'goal-map']),
|
|
38
39
|
strategize: Object.freeze(['work']),
|
|
39
40
|
charter: Object.freeze(['board-room']),
|
|
40
41
|
// task 1005046: legalize woke Economy and legislation woke Ranks. Both pages
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.24.
|
|
3
|
+
"version": "1.24.45",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.24.
|
|
9
|
+
"version": "1.24.45",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.24.
|
|
3
|
+
"version": "1.24.45",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
package/release-notes.json
CHANGED
|
@@ -11221,5 +11221,17 @@
|
|
|
11221
11221
|
"id": "1005050",
|
|
11222
11222
|
"text": "Your numbers are on one page now: your Profile. The separate Accomplishments page is gone from the sidebar. The parts only you should see — your rank and how to reach the next one, how your work was reviewed, your karma histor"
|
|
11223
11223
|
}
|
|
11224
|
+
],
|
|
11225
|
+
"1.24.44": [
|
|
11226
|
+
{
|
|
11227
|
+
"id": "1005051",
|
|
11228
|
+
"text": "Goals now opens with the version's progress and the timeline of every version, so the separate Roadmap page is gone from the sidebar. Old Roadmap links open Goals. The Tasks board's 'see the version' line points at Goals too."
|
|
11229
|
+
}
|
|
11230
|
+
],
|
|
11231
|
+
"1.24.45": [
|
|
11232
|
+
{
|
|
11233
|
+
"id": "1005070",
|
|
11234
|
+
"text": "The hall's sidebar now appears instantly on every page instead of popping in late, and Building mode shows a single Home button."
|
|
11235
|
+
}
|
|
11224
11236
|
]
|
|
11225
11237
|
}
|
|
@@ -64,6 +64,7 @@ const ROUTES = {
|
|
|
64
64
|
'/diagrams': { to: '/primer', why: 'now a Primer chapter, redirects; its images still serve (task 1005046)' },
|
|
65
65
|
'/sessions': { to: '/watch', why: 'now a Watch tab, redirects (task 1005049)' },
|
|
66
66
|
'/gate': { to: '/watch', why: 'Autobongos, now a Watch tab, redirects (task 1005049)' },
|
|
67
|
+
'/roadmap': { to: '/goals', why: 'now the top of Goals, redirects (task 1005051)' },
|
|
67
68
|
};
|
|
68
69
|
// Targets that leave the hall on purpose: sign-in, the hub's /account (platform-server.js;
|
|
69
70
|
// settings.js points the link at the hub), the API, module assets, and any file with an extension.
|
|
@@ -268,7 +269,9 @@ function build() {
|
|
|
268
269
|
};
|
|
269
270
|
});
|
|
270
271
|
|
|
271
|
-
|
|
272
|
+
// 'home' is in every craft: there the plate under the brand IS the Home button
|
|
273
|
+
// (tasks 1005065, 1005070), so no mode lists the Home tab beside it.
|
|
274
|
+
const inAnyCraft = new Set(['home', ...CRAFTS.flatMap((c) => crafts.tabs[c])]);
|
|
272
275
|
const findings = {
|
|
273
276
|
broken: dedupe(broken).sort((a, b) => (a.from + a.href).localeCompare(b.from + b.href)),
|
|
274
277
|
orphan: rows.filter((r) => r.url !== '/' && !r.nav.length && !r.in.length).map((r) => r.url),
|
|
@@ -1039,10 +1039,10 @@ function mountInternalSurfaces(app) {
|
|
|
1039
1039
|
return res.redirect(302, `${isBuildersHost(req) ? '' : '/builders'}/market-watch${qs}#settings`);
|
|
1040
1040
|
});
|
|
1041
1041
|
|
|
1042
|
-
// Pages folded into
|
|
1043
|
-
//
|
|
1044
|
-
const RETIRED_TO_SECTION = Object.freeze({ fleet: 'money#hosting', sessions: 'watch#sessions', gate: 'watch#autobongos' });
|
|
1045
|
-
const RETIRED_SECTION_RE = /^\/builders\/(fleet|sessions|gate)(?:\.html)?\/?$/;
|
|
1042
|
+
// Pages folded into another page; 302 and no gate, as above. Task 1005047: Fleet costs is
|
|
1043
|
+
// /money#hosting; 1005049: Sessions and Autobongos are Watch tabs; 1005051: Roadmap is Goals'.
|
|
1044
|
+
const RETIRED_TO_SECTION = Object.freeze({ fleet: 'money#hosting', sessions: 'watch#sessions', gate: 'watch#autobongos', roadmap: 'goals' });
|
|
1045
|
+
const RETIRED_SECTION_RE = /^\/builders\/(fleet|sessions|gate|roadmap)(?:\.html)?\/?$/;
|
|
1046
1046
|
app.use((req, res, next) => {
|
|
1047
1047
|
if (isModuleSurfaceHost(req)) return next();
|
|
1048
1048
|
if (req.method !== 'GET' && req.method !== 'HEAD') return next();
|
|
@@ -1050,7 +1050,7 @@ function mountInternalSurfaces(app) {
|
|
|
1050
1050
|
if (!m) return next();
|
|
1051
1051
|
const qs = req.url.includes('?') ? req.url.slice(req.url.indexOf('?')) : '';
|
|
1052
1052
|
const [page, section] = RETIRED_TO_SECTION[m[1]].split('#');
|
|
1053
|
-
return res.redirect(302, `${isBuildersHost(req) ? '' : '/builders'}/${page}${qs}
|
|
1053
|
+
return res.redirect(302, `${isBuildersHost(req) ? '' : '/builders'}/${page}${qs}${section ? `#${section}` : ''}`);
|
|
1054
1054
|
});
|
|
1055
1055
|
|
|
1056
1056
|
// task 1005046 (owner decision 2026-11-03, idea 1001311): ONE reading room. Ranks,
|
|
@@ -1348,7 +1348,7 @@ function mountInternalSurfaces(app) {
|
|
|
1348
1348
|
// whole gate; the governing reads it adds are gated by their own routes.
|
|
1349
1349
|
// task 1004921 `ai-studio` (the viewer's own routes).
|
|
1350
1350
|
const SIGNEDIN_BUILDERS_PAGE_RE =
|
|
1351
|
-
/^\/builders\/(?:work|settings|atlas|modules|goals|goal-map|
|
|
1351
|
+
/^\/builders\/(?:work|settings|atlas|modules|goals|goal-map|copy-desk|studio|ai-studio|tweak-editor|ideas|thinking|collab|task|idea|primer(?:\.md)?|my-agents|commands)(?:\.html)?\/?$/;
|
|
1352
1352
|
// The diagram image assets under /builders/diagrams/ ride the same tier as the
|
|
1353
1353
|
// page that embeds them — the Primer, since task 1005046 retired the Diagrams
|
|
1354
1354
|
// page (its URL now 302s to the Primer's first diagram, above).
|
package/src/module-api.js
CHANGED
|
@@ -81,7 +81,7 @@ const { sleep } = require('./sleep');
|
|
|
81
81
|
// MAJOR (see allowBoxScope below): passes the request through untouched.
|
|
82
82
|
function deprecatedNoopMiddleware(_req, _res, next) { next(); }
|
|
83
83
|
|
|
84
|
-
const CORE_VERSION = '1.24.
|
|
84
|
+
const CORE_VERSION = '1.24.45'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
85
85
|
|
|
86
86
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
87
87
|
// Usage: const log = api.logger('discord'); log.info('mounted');
|
package/tests/craft_mode_nav.mjs
CHANGED
|
@@ -63,7 +63,7 @@ function parseSidebar(html) {
|
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
function boot({ session = {}, perms = { 'board.vote.cast': true } } = {}) {
|
|
66
|
+
function boot({ session = {}, local = {}, perms = { 'board.vote.cast': true } } = {}) {
|
|
67
67
|
const root = makeEl('HTML');
|
|
68
68
|
const topbar = makeEl('DIV');
|
|
69
69
|
const sidebar = makeEl('NAV');
|
|
@@ -95,7 +95,7 @@ function boot({ session = {}, perms = { 'board.vote.cast': true } } = {}) {
|
|
|
95
95
|
__BRANDING__: {}, __MODULES__: { enabled: { provisioning: true } },
|
|
96
96
|
BongosClient: { createClient: () => ({ request: () => new Promise(() => {}) }) },
|
|
97
97
|
matchMedia: () => ({ matches: false, addEventListener() {} }),
|
|
98
|
-
localStorage: mk(
|
|
98
|
+
localStorage: mk(local), sessionStorage: mk(session), location,
|
|
99
99
|
clearTimeout() {}, setTimeout() { return 0; }, requestAnimationFrame() {}, scrollTo() {},
|
|
100
100
|
addEventListener() {}, dispatchEvent() { return true; },
|
|
101
101
|
};
|
|
@@ -116,6 +116,7 @@ function boot({ session = {}, perms = { 'board.vote.cast': true } } = {}) {
|
|
|
116
116
|
return {
|
|
117
117
|
craft, root,
|
|
118
118
|
signIn: (rank = 'archon') => shell.applyAccess({ authed: true, rank, permissions: perms, builder: { id: 7, rank } }),
|
|
119
|
+
signOut: () => shell.applyAccess({ authed: false }),
|
|
119
120
|
// The tabs a reader can see: the gate let them through AND the mode kept them.
|
|
120
121
|
showing: () => parsed().flatMap((g) => g.items).filter((a) => !a.hidden && !a.hasAttribute('data-craft-off')).map((a) => a.id.slice(4)),
|
|
121
122
|
headShowing: (group) => {
|
|
@@ -146,10 +147,24 @@ test('THE ALWAYS-PRESENT LIST: one shared list, Builders first, then Collab and
|
|
|
146
147
|
|
|
147
148
|
test('every tab a mode names is a real NAV item, and every NAV item lives in some mode', () => {
|
|
148
149
|
const { craft } = boot();
|
|
149
|
-
|
|
150
|
+
// 24 since task 1005051 folded the Roadmap into Goals (a sanity floor, not a count).
|
|
151
|
+
assert.ok(NAV_IDS.length >= 24, `read ${NAV_IDS.length} NAV ids from shell.js`);
|
|
150
152
|
const named = new Set(CRAFTS.flatMap((m) => craft.tabsFor(m)));
|
|
151
153
|
for (const id of named) assert.ok(NAV_IDS.includes(id), `${id} is a NAV id`);
|
|
152
|
-
|
|
154
|
+
// Home is the one exception: in a mode the craft plate IS the Home button
|
|
155
|
+
// (task 1005065), so no mode lists the Home tab beside it (task 1005070).
|
|
156
|
+
for (const id of NAV_IDS) {
|
|
157
|
+
if (id === 'home') continue;
|
|
158
|
+
assert.ok(named.has(id), `${id} is reachable from some mode's nav`);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test('ONE HOME: no mode shows the Home tab, because the plate is Home in every mode (task 1005070)', () => {
|
|
163
|
+
const { craft } = boot();
|
|
164
|
+
for (const m of CRAFTS) assert.ok(!craft.tabsFor(m).includes('home'), `${m} does not list the Home tab beside the plate`);
|
|
165
|
+
const none = boot();
|
|
166
|
+
none.signIn();
|
|
167
|
+
assert.ok(none.showing().includes('home'), 'with no mode there is no plate, so the Home tab shows');
|
|
153
168
|
});
|
|
154
169
|
|
|
155
170
|
test('Government shows only in Governing, and Governing is the shortest list', () => {
|
|
@@ -325,3 +340,37 @@ test('the dropdown opens on its own when the page you are on is inside it', () =
|
|
|
325
340
|
assert.equal(bootTree({ mode: 'artistry' }).fold(), null, 'no other mode folds anything');
|
|
326
341
|
assert.equal(bootTree().fold(), null, 'nor does no mode');
|
|
327
342
|
});
|
|
343
|
+
|
|
344
|
+
// ── the remembered nav (task 1005070) ──────────────────────────────────────
|
|
345
|
+
// Every hall page is a full load and /me is the slowest read the owner makes, so
|
|
346
|
+
// the rail used to boot empty and pop its tabs in once /me answered. The shell
|
|
347
|
+
// now keeps the last settled access and paints from it; /me (whose client never
|
|
348
|
+
// answers in this harness) still settles the rest.
|
|
349
|
+
const NAV_KEY = 'hall-nav-access';
|
|
350
|
+
|
|
351
|
+
test('THE REMEMBERED NAV: a signed-in settle is kept, and the next page paints it before /me answers', () => {
|
|
352
|
+
const local = {};
|
|
353
|
+
const first = boot({ local });
|
|
354
|
+
first.signIn();
|
|
355
|
+
const settled = first.showing();
|
|
356
|
+
const kept = JSON.parse(local[NAV_KEY]);
|
|
357
|
+
assert.equal(kept.rank, 'archon');
|
|
358
|
+
assert.equal(kept.builder.id, 7);
|
|
359
|
+
assert.ok(!('needs' in kept), 'never the needs roster, so a badge is never stale');
|
|
360
|
+
const next = boot({ local });
|
|
361
|
+
assert.deepEqual(next.showing(), settled, 'the next page paints the same tabs with /me still out');
|
|
362
|
+
const cold = boot();
|
|
363
|
+
assert.deepEqual(cold.showing(), ['home'], 'with nothing kept the rail waits for /me, as before');
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
test('THE REMEMBERED NAV is forgotten on a signed-out settle, and an old one is not painted', () => {
|
|
367
|
+
const local = {};
|
|
368
|
+
const p = boot({ local });
|
|
369
|
+
p.signIn();
|
|
370
|
+
assert.ok(local[NAV_KEY]);
|
|
371
|
+
p.signOut();
|
|
372
|
+
assert.ok(!(NAV_KEY in local), 'a sign-out or a 401 drops it');
|
|
373
|
+
const stale = boot({ local: { [NAV_KEY]: JSON.stringify({ at: Date.now() - 2 * 24 * 60 * 60 * 1000, rank: 'archon', builder: { id: 7 } }) } });
|
|
374
|
+
assert.deepEqual(stale.showing(), ['home'], 'a day-old memory is not painted');
|
|
375
|
+
assert.match(SHELL, /function doLogout\(\) \{\n\s+forgetAccess\(\);/, 'the sign-out link forgets it before it leaves');
|
|
376
|
+
});
|
package/tests/founding_mode.mjs
CHANGED
|
@@ -43,14 +43,16 @@ test('active with no stage yet is the decide pre-stage, and every room sleeps',
|
|
|
43
43
|
assert.equal(f.stage, 'decide');
|
|
44
44
|
assert.equal(f.stage_number, 0);
|
|
45
45
|
assert.equal(f.stage_count, 5);
|
|
46
|
-
|
|
46
|
+
// task 1005051: Roadmap folded into Goals; scope wakes Goals and its map.
|
|
47
|
+
for (const id of ['goals', 'goal-map', 'work', 'board-room', 'collab', 'roster']) {
|
|
47
48
|
assert.ok(id in f.asleep, `${id} sleeps while deciding`);
|
|
48
49
|
}
|
|
49
50
|
});
|
|
50
51
|
|
|
51
52
|
test('a room wakes once the stage that wakes it is behind', () => {
|
|
52
53
|
const f = fm.shapeFoundingMode({ active: 'true', stage: 'charter' });
|
|
53
|
-
for (const id of ['
|
|
54
|
+
for (const id of ['goals', 'goal-map', 'work']) assert.ok(!(id in f.asleep), `${id} woke`);
|
|
55
|
+
assert.ok(!('roadmap' in f.asleep), 'the folded Roadmap is no room to wake');
|
|
54
56
|
assert.equal(f.asleep['board-room'], 'charter');
|
|
55
57
|
// task 1005046: Economy and Ranks were the rooms legalize and legislation woke;
|
|
56
58
|
// they are Primer chapters now, and the Primer never sleeps.
|
|
@@ -121,7 +123,7 @@ class El {
|
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
function makeHall() {
|
|
124
|
-
const navIds = ['home', '
|
|
126
|
+
const navIds = ['home', 'goals', 'goal-map', 'work', 'board-room', 'collab', 'roster', 'profile'];
|
|
125
127
|
const nav = navIds.map((id) => { const a = new El('a'); a.id = 'nav-' + id; a.className = 'nav-item'; return a; });
|
|
126
128
|
const appBody = new El('div');
|
|
127
129
|
const topbar = new El('header'); topbar.id = 'app-topbar';
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// tests/hall_goals_band.mjs — Roadmap folds into Goals (task 1005051, owner
|
|
2
|
+
// decision 2026-11-03, idea 1001315 item 4).
|
|
3
|
+
//
|
|
4
|
+
// Since one version is built at a time (task 1004821) the Roadmap page mostly
|
|
5
|
+
// repeated Goals. Goals now opens with the version's progress and the timeline:
|
|
6
|
+
//
|
|
7
|
+
// * THE BAND. goals.html carries #rm-root at the top of its list view, with
|
|
8
|
+
// roadmap.css, roadmap-timeline.js (still the drawing) and roadmap.js.
|
|
9
|
+
// * OLD LINKS LAND ON GOALS. /roadmap 302s to /goals (serve-internal.js
|
|
10
|
+
// RETIRED_TO_SECTION), query kept; the real middleware runs here.
|
|
11
|
+
// * NOTHING POINTS AT IT. No nav item, no Governing/Building tab, no founding
|
|
12
|
+
// room, and the Tasks board's "see the version" line names Goals.
|
|
13
|
+
//
|
|
14
|
+
// The band's own rendering (the timeline glue, a missing module, an undated
|
|
15
|
+
// version) is run in tests/hall_reading_world.mjs bootRoadmap.
|
|
16
|
+
//
|
|
17
|
+
// Run: node tests/hall_goals_band.mjs
|
|
18
|
+
|
|
19
|
+
import { test } from 'node:test';
|
|
20
|
+
import assert from 'node:assert/strict';
|
|
21
|
+
import fs from 'node:fs';
|
|
22
|
+
import http from 'node:http';
|
|
23
|
+
import path from 'node:path';
|
|
24
|
+
import { createRequire } from 'node:module';
|
|
25
|
+
import { fileURLToPath } from 'node:url';
|
|
26
|
+
|
|
27
|
+
const require = createRequire(import.meta.url);
|
|
28
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
29
|
+
const HALL = path.join(ROOT, 'modules', 'hall-ui', 'public');
|
|
30
|
+
const read = (f) => fs.readFileSync(path.join(HALL, f), 'utf8');
|
|
31
|
+
|
|
32
|
+
async function withHall(fn) {
|
|
33
|
+
const express = require('express');
|
|
34
|
+
const { mountInternalSurfaces } = require('../src/bongos/serve-internal.js');
|
|
35
|
+
const app = express();
|
|
36
|
+
mountInternalSurfaces(app);
|
|
37
|
+
const server = app.listen(0, '127.0.0.1');
|
|
38
|
+
await new Promise((r) => server.once('listening', r));
|
|
39
|
+
const { port } = server.address();
|
|
40
|
+
const get = (p, host) => new Promise((resolve, reject) => {
|
|
41
|
+
http.get({ host: '127.0.0.1', port, path: p, headers: { host } }, (res) => {
|
|
42
|
+
res.resume();
|
|
43
|
+
res.on('end', () => resolve({ status: res.statusCode, location: res.headers.location || '' }));
|
|
44
|
+
}).on('error', reject);
|
|
45
|
+
});
|
|
46
|
+
try { await fn(get); } finally { server.close(); }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
test('RUN: /roadmap 302s to /goals, in every spelling, with its query', async () => {
|
|
50
|
+
await withHall(async (get) => {
|
|
51
|
+
for (const form of ['/roadmap', '/roadmap/', '/roadmap.html']) {
|
|
52
|
+
const r = await get(form, 'builders.127.0.0.1');
|
|
53
|
+
assert.equal(r.status, 302, `${form} is a temporary redirect`);
|
|
54
|
+
assert.equal(r.location, '/goals', `${form} lands on Goals, with no stray fragment`);
|
|
55
|
+
}
|
|
56
|
+
assert.equal((await get('/roadmap?from=mail', 'builders.127.0.0.1')).location, '/goals?from=mail');
|
|
57
|
+
// the map it joined still carries its sections
|
|
58
|
+
assert.equal((await get('/sessions', 'builders.127.0.0.1')).location, '/watch#sessions');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('Goals opens with the band, and loads what draws it', () => {
|
|
63
|
+
const html = read('goals.html');
|
|
64
|
+
const list = html.slice(html.indexOf('<section id="goals-list-view"'));
|
|
65
|
+
assert.ok(list.indexOf('id="rm-root"') > 0 && list.indexOf('id="rm-root"') < list.indexOf('class="scroll goals-panel"'),
|
|
66
|
+
'the band sits above the goals list');
|
|
67
|
+
assert.match(list, /<div id="rm-root"><div class="hall-loading" role="status">Loading the version…<\/div><\/div>/, 'with a Loading… line');
|
|
68
|
+
assert.match(html, /href="\/builders\/roadmap\.css"/);
|
|
69
|
+
const i = (s) => html.indexOf(s);
|
|
70
|
+
assert.ok(i('/builders/hall-kit.js') < i('/builders/roadmap-timeline.js'), 'the kit before the timeline');
|
|
71
|
+
assert.ok(i('/builders/roadmap-timeline.js') < i('/builders/roadmap.js'), 'the timeline before the band');
|
|
72
|
+
assert.ok(!fs.existsSync(path.join(HALL, 'roadmap.html')), 'the page itself is gone');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test('the band draws the version and the timeline, and no goal summary of its own', () => {
|
|
76
|
+
const js = read('roadmap.js');
|
|
77
|
+
assert.match(js, /function versionCard\(v\)/);
|
|
78
|
+
assert.match(js, /html \+= timelineHtml\(all, Date\.now\(\)\)/);
|
|
79
|
+
assert.ok(!/\/goals\?version=|goalSummary|goalsBlock/.test(js), 'Goals already reads the goals; the band does not read them again');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('nothing points at the Roadmap any more', () => {
|
|
83
|
+
assert.ok(!/href: '\/roadmap'/.test(read('shell.js')), 'no nav item');
|
|
84
|
+
assert.ok(!/'roadmap'/.test(read('craft-mode.js')), 'no craft tab');
|
|
85
|
+
assert.ok(!/'roadmap'/.test(fs.readFileSync(path.join(ROOT, 'modules/onboarding/founding-mode.js'), 'utf8')), 'no founding room');
|
|
86
|
+
assert.ok(!/href="\/roadmap"/.test(read('work.html')), 'the Tasks board names Goals');
|
|
87
|
+
assert.match(read('work.html'), /See <a href="\/goals">Goals<\/a> for the version's progress/);
|
|
88
|
+
});
|
|
@@ -353,9 +353,10 @@ test('the kit is loaded before every page that draws through it', () => {
|
|
|
353
353
|
['watch.html', 'watch.js'],
|
|
354
354
|
['profile.html', 'profile-charts.js'],
|
|
355
355
|
// task 1003447: the roadmap's own series module reads the kit, and the page
|
|
356
|
-
// reads that. Both edges of the chain are ordered here
|
|
357
|
-
|
|
358
|
-
['
|
|
356
|
+
// reads that. Both edges of the chain are ordered here — on Goals since task
|
|
357
|
+
// 1005051 folded the Roadmap into its top.
|
|
358
|
+
['goals.html', 'roadmap-timeline.js'],
|
|
359
|
+
['goals.html', 'roadmap.js'],
|
|
359
360
|
]) {
|
|
360
361
|
// The loaded ORDER, read off the script tags — index.html's prose mentions
|
|
361
362
|
// hall-render.js ~90 lines above where it loads it, so a substring search
|
package/tests/hall_nav.mjs
CHANGED
|
@@ -291,8 +291,11 @@ test('sidebar groups read by audience, in order', () => {
|
|
|
291
291
|
// default-off market-watch module is not enabled (this boot reports no module state).
|
|
292
292
|
// task 1005071: the project group split three ways. Work is the project's state;
|
|
293
293
|
// Make is where things get made; Govern is the board's rooms.
|
|
294
|
-
|
|
294
|
+
// task 1005051: 'roadmap' left — the version's progress and timeline open Goals,
|
|
295
|
+
// and /roadmap redirects there (owner decision 2026-11-03, idea 1001315).
|
|
296
|
+
assert.deepEqual(nav[0].items.map((i) => i.id), ['home', 'work', 'goals', 'goal-map', 'blockers', 'thinking'],
|
|
295
297
|
'Work = the project itself (task 1005071 order)');
|
|
298
|
+
assert.ok(!nav.flatMap((g) => g.items).some((i) => i.href === '/roadmap'), 'no item points at the folded Roadmap');
|
|
296
299
|
assert.deepEqual(nav[1].items.map((i) => i.id), ['studio', 'market-watch'], 'Make = where things get made');
|
|
297
300
|
// task 1004685 (the living-city prototype, round-3 board 6): 'my-agents' joins You —
|
|
298
301
|
// how your own Claude works for you, the personal half of "the city steers
|
|
@@ -859,7 +862,7 @@ test('POSITION: ?as=nobody views the hall with no seat, and can only hide', asyn
|
|
|
859
862
|
assert.equal(b.navHidden('my-agents'), false);
|
|
860
863
|
// a xenos stand-in stays a xenos: the pretend rank never rises above the real one
|
|
861
864
|
const x = await seated({ builder: { id: '9', rank: 'xenos' }, positions: block([lead('planning', 'Planning Lead')]), search: '?as=nobody' });
|
|
862
|
-
assert.equal(x.navHidden('
|
|
865
|
+
assert.equal(x.navHidden('goal-map'), true, 'a member page stays hidden from a real xenos');
|
|
863
866
|
});
|
|
864
867
|
|
|
865
868
|
test('My agents draws its own glyph and lands on a real page', () => {
|
|
@@ -70,7 +70,9 @@ const ORACLE = {
|
|
|
70
70
|
// the URL now serves THE PROJECT SKY (the same page as /thinking, in its whole-project
|
|
71
71
|
// lens) on the same tier, and holds the nav slot under Goals the map was denied.
|
|
72
72
|
'/builders/goal-map': 'requireBuilderPage',
|
|
73
|
-
|
|
73
|
+
// Gone (task 1005051, owner decision 2026-11-03): the Roadmap is the top of Goals,
|
|
74
|
+
// and /builders/roadmap 302s there before any gate runs.
|
|
75
|
+
'/builders/roadmap': null,
|
|
74
76
|
// Gated at this tier all along, but with no row until task 1003448 walked the
|
|
75
77
|
// module's pages: copy-desk (task 1003113) and ideas (task 1002928) are open to
|
|
76
78
|
// every rank by design, and collab's reads (task 1003172) are scoped to the
|
|
@@ -365,6 +367,8 @@ const GONE_PAGES = {
|
|
|
365
367
|
// Task 1005049 — one oversight page: each is a tab on Watch, and the old URL 302s to it.
|
|
366
368
|
'/builders/sessions': 'task 1005049 — the session log is Watch\'s Sessions tab; /sessions redirects there',
|
|
367
369
|
'/builders/gate': 'task 1005049 — the runner panel is Watch\'s Autobongos tab; /gate redirects there',
|
|
370
|
+
// Task 1005051 — the version's progress and timeline open Goals; /roadmap redirects there.
|
|
371
|
+
'/builders/roadmap': 'task 1005051 — the roadmap is the top of Goals; /roadmap redirects there',
|
|
368
372
|
};
|
|
369
373
|
|
|
370
374
|
test('a row that is null because the page left the hall serves no page', () => {
|
|
@@ -74,7 +74,8 @@ const primerJs = read('primer.js');
|
|
|
74
74
|
const viewerJs = read('diagram-viewer.js');
|
|
75
75
|
const mdReaderJs = read('md-reader.js');
|
|
76
76
|
const primerHtml = read('primer.html');
|
|
77
|
-
|
|
77
|
+
// task 1005051: the Roadmap folded into the top of Goals; its band draws there.
|
|
78
|
+
const roadmapHtml = read('goals.html');
|
|
78
79
|
|
|
79
80
|
const decomment = (css) => css.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
80
81
|
// The body of the first rule matching `selector {`, comments stripped. Naive on
|
|
@@ -106,12 +107,12 @@ test('no hall page sheet declares a :root of its own', () => {
|
|
|
106
107
|
'the pack :root is spliced at the end of <head> — a page-local one is outranked one way and defeats re-branding the other. Put page tokens on body.');
|
|
107
108
|
});
|
|
108
109
|
|
|
109
|
-
test('roadmap.css
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
110
|
+
test('roadmap.css keeps no page-local tokens and draws no shadow', () => {
|
|
111
|
+
// task 1005051: the two body tokens (--rm-plan, --rm-terra-weak) painted the
|
|
112
|
+
// goal summaries and the staged cards, which went with the page; nothing on the
|
|
113
|
+
// Goals band spends them, so they left with them rather than lingering unread.
|
|
114
|
+
assert.doesNotMatch(decomment(roadmapCss), /--rm-(plan|terra-weak)\s*:/, 'no unread page token left behind');
|
|
115
|
+
assert.doesNotMatch(decomment(roadmapCss), /:root\s*\{/, 'and never a page-local :root');
|
|
115
116
|
assert.doesNotMatch(decomment(roadmapCss), /--rm-shadow-soft/,
|
|
116
117
|
'v3 separates by TONE — a panel is never a drawn box and never a shadow');
|
|
117
118
|
assert.doesNotMatch(decomment(roadmapCss), /box-shadow\s*:\s*(?!inset)[^;]*(?:rgba|0 )/,
|
|
@@ -350,7 +351,7 @@ test('the viewer drops the white ground mermaid bakes into the SVG', () => {
|
|
|
350
351
|
// ---- 8. every room has exactly one h1 -------------------------------------
|
|
351
352
|
|
|
352
353
|
// task 1005046: diagrams.html and ranks.html folded into the primer's chapters.
|
|
353
|
-
const ROOMS = [['primer.html', primerHtml], ['
|
|
354
|
+
const ROOMS = [['primer.html', primerHtml], ['goals.html', roadmapHtml]];
|
|
354
355
|
|
|
355
356
|
// An HTML comment that mentions <h1> is prose, not markup — and these pages each
|
|
356
357
|
// carry one explaining why the heading is there at all.
|
|
@@ -369,7 +370,7 @@ test('the DOCS room takes the room voice; the deck takes the board\'s', () => {
|
|
|
369
370
|
assert.match(html, /class="page-head page-head--room"/, `${name} is a reading room`);
|
|
370
371
|
}
|
|
371
372
|
assert.match(roadmapHtml, /class="page-head page-head--board"/,
|
|
372
|
-
'the roadmap is a working surface whose figures are the thing to look at, so its own name stays quiet');
|
|
373
|
+
'Goals, which carries the roadmap band, is a working surface whose figures are the thing to look at, so its own name stays quiet');
|
|
373
374
|
});
|
|
374
375
|
|
|
375
376
|
test('the document\'s own h1 is suppressed, or the article would render a second one', () => {
|
|
@@ -418,19 +419,17 @@ test('no reading room carries an inline <style>, and none needs an audit excepti
|
|
|
418
419
|
// was the last page carrying a one-line block; task 1003440 deleted the page.)
|
|
419
420
|
});
|
|
420
421
|
|
|
421
|
-
test('
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
422
|
+
test('the version band\'s sub-24px link clears the floor', () => {
|
|
423
|
+
// task 1005051: the goal-row title (.rm-goal__t) went with the goal summaries
|
|
424
|
+
// when the Roadmap folded into Goals — the goals are the list right below — so
|
|
425
|
+
// the band's one small control left is its "View tasks" link.
|
|
426
|
+
assert.equal(rule(roadmapCss, '.rm-goal__t'), null, 'the goal rows are gone, and their rule with them');
|
|
425
427
|
const more = rule(roadmapCss, '.rm-gmore');
|
|
426
428
|
assert.ok(more, '.rm-gmore has a rule');
|
|
427
429
|
assert.match(more, /min-height:\s*24px/, 'measured 19px');
|
|
428
|
-
// the WIDTH half is the one that gets missed: at 320 the four fixed items in
|
|
429
|
-
// the row ate it and `flex: 1; min-width: 0` resolved the title to 0x26
|
|
430
|
-
assert.match(decomment(roadmapCss), /@media\s*\(max-width:400px\)[\s\S]*?\.rm-goal__t\s*\{[^}]*flex:\s*1 0 100%/,
|
|
431
|
-
'and the row wraps before the title can resolve to zero width');
|
|
432
430
|
});
|
|
433
431
|
|
|
432
|
+
|
|
434
433
|
// ---- 10. the parser, actually run -----------------------------------------
|
|
435
434
|
|
|
436
435
|
// md-reader.js is a browser IIFE that only touches `window` and `location`, so
|
|
@@ -709,7 +708,7 @@ test('RUN: a deck whose versions carry no dates renders every other section unha
|
|
|
709
708
|
versions: { versions: [{ id: 'BONGOS-V1', name: 'x', status: 'building', started_at: null, shipped_at: null }] },
|
|
710
709
|
});
|
|
711
710
|
assert.doesNotMatch(html, /In time</, 'no timeline section');
|
|
712
|
-
assert.match(html, /rm-
|
|
711
|
+
assert.match(html, /rm-card--feat/, 'but the version still renders');
|
|
713
712
|
assert.doesNotMatch(html, /NaN|undefined/);
|
|
714
713
|
});
|
|
715
714
|
|
package/tests/hall_sitemap.mjs
CHANGED
|
@@ -21,7 +21,8 @@ const model = gen.build();
|
|
|
21
21
|
test('the parse found the hall, so nothing below passes against an empty map', () => {
|
|
22
22
|
const files = fs.readdirSync(path.join(ROOT, 'modules/hall-ui/public')).filter((f) => f.endsWith('.html'));
|
|
23
23
|
assert.equal(model.pages.length, files.length, 'one row per page file');
|
|
24
|
-
|
|
24
|
+
// 24 since task 1005051 folded the Roadmap into Goals.
|
|
25
|
+
assert.ok(model.nav.length >= 24, `expected the shell's nav, found ${model.nav.length} items`);
|
|
25
26
|
for (const c of ['building', 'artistry', 'ideating', 'governing']) {
|
|
26
27
|
assert.ok(model.crafts.tabs[c].length > model.crafts.always.length, `${c} lists tabs of its own`);
|
|
27
28
|
}
|
|
@@ -98,8 +98,10 @@ test('the hall-preview fixture carries every atom /me resolves', () => {
|
|
|
98
98
|
// task 1005046: Ranks, Economy and Diagrams left Docs (one reading room, the Primer);
|
|
99
99
|
// task 1005049: Sessions and Autobongos left the sidebar (tabs on Watch);
|
|
100
100
|
// task 1005076: the setup flow's holdForSetup;
|
|
101
|
-
// task 1005050: Accomplishments left it (folded into Profile; its hashes redirect)
|
|
102
|
-
|
|
101
|
+
// task 1005050: Accomplishments left it (folded into Profile; its hashes redirect);
|
|
102
|
+
// task 1005051: Roadmap left it (folded into Goals; /roadmap redirects).
|
|
103
|
+
// task 1005070: the remembered nav (the rail paints before /me).
|
|
104
|
+
const SHELL_SHA = 'dbbe6f2eb49a65c3';
|
|
103
105
|
|
|
104
106
|
test('shell.js has not changed without its cache-bust being bumped', () => {
|
|
105
107
|
const actual = crypto.createHash('sha256').update(SHELL).digest('hex').slice(0, 16);
|
|
@@ -1,58 +0,0 @@
|
|
|
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>Roadmap — {{worldName}}</title>
|
|
7
|
-
<meta name="description" content="How the whole build is doing — the program at a glance, then each version — {{worldName}}.">
|
|
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-07-24-deck1">
|
|
12
|
-
<link rel="stylesheet" href="/builders/roadmap.css">
|
|
13
|
-
</head>
|
|
14
|
-
<body data-page="roadmap" data-page-title="Roadmap">
|
|
15
|
-
|
|
16
|
-
<div class="app">
|
|
17
|
-
<aside class="app-sidebar" id="app-sidebar" aria-label="Primary"></aside>
|
|
18
|
-
<div class="app-scrim" id="app-scrim" hidden></div>
|
|
19
|
-
<div class="app-body">
|
|
20
|
-
<header class="app-topbar" id="app-topbar"></header>
|
|
21
|
-
<div class="app-content">
|
|
22
|
-
<!-- The page had no <h1> at all before task 1003306, so it failed
|
|
23
|
-
one-header-main-h1 on every render. The deck takes the BOARD voice,
|
|
24
|
-
not the reading room's: it is a working surface whose figures are the
|
|
25
|
-
thing to look at, and its own name is the quietest thing on it. -->
|
|
26
|
-
<div class="page-head page-head--board">
|
|
27
|
-
<h1 class="page-head__h">Roadmap</h1>
|
|
28
|
-
<p class="page-head__sub" id="roadmap-sub">Loading the roadmap…</p>
|
|
29
|
-
</div>
|
|
30
|
-
|
|
31
|
-
<main id="hall-main">
|
|
32
|
-
<div id="rm-root">
|
|
33
|
-
<div class="hall-loading hall-loading--page" role="status">Loading the roadmap…</div>
|
|
34
|
-
</div>
|
|
35
|
-
</main>
|
|
36
|
-
|
|
37
|
-
<footer class="app-foot" id="app-foot"></footer>
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
|
|
42
|
-
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
43
|
-
|
|
44
|
-
<script src="/builders/dom-utils.js?v=2026-11-05-numbers"></script>
|
|
45
|
-
<script src="/builders/shell-trail.js?v=2026-11-05-numbers"></script>
|
|
46
|
-
<script src="/builders/craft-mode.js?v=2026-11-05-numbers"></script>
|
|
47
|
-
<script src="/builders/shell.js?v=2026-11-05-numbers"></script>
|
|
48
|
-
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
49
|
-
<script src="/builders/palette.js" defer></script>
|
|
50
|
-
<!-- The chart kit and the timeline's series builders (task 1003447). Both MUST
|
|
51
|
-
precede roadmap.js: the page reads window.OTBKit / window.OTBRoadmapTimeline
|
|
52
|
-
at render time, so loading either after would be a blank section in
|
|
53
|
-
production and a green unit suite. tests/hall_kit_charts.mjs pins the order. -->
|
|
54
|
-
<script src="/builders/hall-kit.js"></script>
|
|
55
|
-
<script src="/builders/roadmap-timeline.js"></script>
|
|
56
|
-
<script src="/builders/roadmap.js?v=2026-09-03-timeline"></script>
|
|
57
|
-
</body>
|
|
58
|
-
</html>
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"_": "The hall's roadmap deck through modules/ui-design/kit/render.js (task 1003306). The deck is the hall's densest figure surface — a hero band, four status groups and a summarised goal layer per version — so its floors are the 24px one (the goal rows are links in a tight list) and horizontal overflow at 320.",
|
|
3
|
-
"page": "/builders/roadmap",
|
|
4
|
-
"surface": "hall-ui",
|
|
5
|
-
"stub": { "prefix": "/builders/" },
|
|
6
|
-
"modeQuery": false,
|
|
7
|
-
"_feeds": "The kit's stub carries the public-landing fixtures, not the hall's versions/goals feeds, so the deck renders its EMPTY state here and the feed 404s are declared, never hidden. The populated deck is the hall-preview harness's job: node scripts/hall-preview/server.js --port 4612 --fixture-me, then this same file with --base-in/--base-out pointed at it.",
|
|
8
|
-
"ignoreRequests": [
|
|
9
|
-
"/api/(gds|bongos)/me$",
|
|
10
|
-
"/api/(gds|bongos)/me/",
|
|
11
|
-
"/api/(gds|bongos)/versions",
|
|
12
|
-
"/api/(gds|bongos)/goals",
|
|
13
|
-
"/api/(gds|bongos)/tasks",
|
|
14
|
-
"/api/(gds|bongos)/inbox/",
|
|
15
|
-
"/api/(gds|bongos)/public/"
|
|
16
|
-
],
|
|
17
|
-
"ignoreConsole": [
|
|
18
|
-
"/api/(gds|bongos)/",
|
|
19
|
-
"\\b401\\b",
|
|
20
|
-
"\\b404\\b",
|
|
21
|
-
"Unauthorized",
|
|
22
|
-
"Not Found",
|
|
23
|
-
"load failed",
|
|
24
|
-
"roadmap"
|
|
25
|
-
],
|
|
26
|
-
"states": {
|
|
27
|
-
"in": { "auth": true, "expect": { "visible": ["#rm-root"] } },
|
|
28
|
-
"out": { "auth": false }
|
|
29
|
-
},
|
|
30
|
-
"reducedMotion": { "auth": true }
|
|
31
|
-
}
|