launchpad: row 294 round 2 (#1800): browser.test pin gains /federation.js at index 2 (Mos mos-1412 (a)), G5 pins one action.refused {code: access-refused} per refused verb and every other table unchanged (sage-3194); manifest round 2 (18 paths), ASSERTION-PRESERVATION.json, run 1 receipts; unrun

This commit is contained in:
jason.woltje committed 2026-10-23 00:03:51 -05:00
1 parent 685ff053b6
commit 66c1817176
11 files changed
+139 -18

No files matched your search

@@ -0,0 +1,22 @@
{
"row": 294,
"round": 2,
"ruling": "mos-1412 (through sage-3195): option (a) approved, (b) rejected",
"changes": [
{
"file": "packages/webui/tests/browser.test.mjs",
"line": 21,
"kind": "comment",
"old": " // Rows 129, 154, 191 and 194: chat.js, editor.js, processing.js and agents.js are the scripts added, same origin; the list is the pin, so another script is a visible change.",
"new": " // Rows 129, 154, 191, 194 and 294: chat.js, editor.js, processing.js, agents.js and federation.js are the scripts added, same origin; the list is the pin, so another script is a visible change."
},
{
"file": "packages/webui/tests/browser.test.mjs",
"line": 22,
"kind": "assertion",
"old": " assert.deepEqual(await b.evaluate('[...document.querySelectorAll(\"script\")].map(s => s.getAttribute(\"src\"))'), ['/editor.js', '/processing.js', '/brand.js', '/app.js', '/markdown-preview.js', '/chat.js', '/agents.js', '/bus.js']);",
"new": " assert.deepEqual(await b.evaluate('[...document.querySelectorAll(\"script\")].map(s => s.getAttribute(\"src\"))'), ['/editor.js', '/processing.js', '/federation.js', '/brand.js', '/app.js', '/markdown-preview.js', '/chat.js', '/agents.js', '/bus.js']);"
}
],
"unchanged": "every other line of browser.test.mjs is byte-identical to c902a767d"
}
+42 -1
View File
@@ -204,7 +204,12 @@ and an in-process Broker with an access function, like bus/tests/user-principal.
routes, agents, processing, project files, /api/bus/message, /api/board), a user session gets routes, agents, processing, project files, /api/bus/message, /api/board), a user session gets
403 `owner-only` and the transport ran zero times. 403 `owner-only` and the transport ran zero times.
- G5 the bus refusal stands alone: the same session's user transport, called directly with each - G5 the bus refusal stands alone: the same session's user transport, called directly with each
owner verb, gets `access-refused` from the broker and nothing is written. owner verb, gets `access-refused` from the broker. The only write is the broker's own refusal
evidence: exactly one `action.refused` event per verb, the count taken from the verb list's length
(22 today), each body exactly `{ code: 'access-refused' }`, and every other table's row count
unchanged (round 2; run 1 placed the round 1 "events unchanged" pin as a test defect, sage-3194).
The broker's `#refused` (bus broker.mjs:4423) writes the code alone and no verb, so the test can't
match each event to its verb; pinning the whole body means a field added there shows up here.
- G9 the C6 seam (sage-3153, sage-3157), with the test's userOptions built by userOptionsFor as - G9 the C6 seam (sage-3153, sage-3157), with the test's userOptions built by userOptionsFor as
cli.mjs builds them: a user session runs the chat's project list, thread create, list, cli.mjs builds them: a user session runs the chat's project list, thread create, list,
open, send and messages. The owner transport (a recording `ownerCall`) saw only open, send and messages. The owner transport (a recording `ownerCall`) saw only
@@ -308,4 +313,40 @@ exception is accepted and does not go to Mos.
- N4: the user-bus.mjs fold-back (C7) is proposed to Sage as a queue row, for the next - N4: the user-bus.mjs fold-back (C7) is proposed to Sage as a queue row, for the next
channel-proof re-pin. channel-proof re-pin.
Round 2 (Mos mos-1412 through Sage sage-3195; for Duckworth): two test changes after run 1, no
product change. The manifest adds packages/webui/tests/browser.test.mjs (18 paths).
- Red 1, old test, Mos approved (a): browser.test.mjs:22 pins index.html's script list. It gains
'/federation.js' at index 2, where 294's index.html:7 puts it, ahead of brand.js. The :21 comment
adds row 294 and federation.js. No other assertion in the file changes. Old and new lines are in
ASSERTION-PRESERVATION.json. (b), loading the federation view another way, was rejected.
- Red 2, new test G5: the pin is the one in the G5 note above. Mos's suggestion is taken: the count
is `refusals.length`, not a literal. The verb check is not possible, because the event names no
verb; the test pins the whole body instead.
## Runs ## Runs
### Run 1, 2026-10-23 04:57Z (sage-3187 CLEAR), head 685ff053b, manifest 0b3f9c9d…94f3
Before the run, the branch was rebased from 253346e3c onto c902a767d. `git range-diff -s` showed all 6
commits "=", and the stable patch-ids matched. The head was pushed as launchpad/row294-on-c902a767d
024499fc2. TMPDIR was under /mnt/storage/scratch/tmp. npm ci --ignore-scripts ran at the root only.
| Step | Result | Time | Limit |
|---|---|---|---|
| webui suite | 365 tests: 362 pass, 2 fail, 1 skip | 55.8 s | 600 s |
The driver stopped at the first red, so the cli, bus, scripts and mutants did not run. The slot was
returned (launchpad-0060).
- browser.test.mjs:22, an old test, pins index.html's script list. 294 adds `/federation.js` at
index 2. It went to Mos through Sage (sage-3192); I made no change before the ruling.
- G5:262, a new test, failed `22 !== 0`: the broker writes one `action.refused` per refusal. This
was placed as a test defect under mos-1272 and accepted by Sage (sage-3194). It is fixed in round 2.
- The skip was the editor rebuild check (editor-provenance.test.mjs:162), which needs esbuild
0.28.2 from packages/webui's own lockfile. An environment fix: the next run also runs npm ci
--ignore-scripts in packages/webui (sage-3194).
- The last landed whole-webui gate skipped the same test: row 264a's run, webui 345 pass of 346 with
1 skipped, "the esbuild 0.28.1 editor rebuild" (gizmoduck queue-264 BUILD.md:516-518, DEFERRED
264a N2). Row 270's gate ran only webui pinned-copy.test. The fresh 294 gate still runs npm ci in
packages/webui first, so the test should run here. If it skips again, the run names it and says why.
+21 -10
View File
@@ -1,15 +1,26 @@
# Row 294 (FED R6, #1800) candidate manifest, round 1 # Row 294 (FED R6, #1800) candidate manifest, round 2
Branch launchpad/row294, base 253346e3c, pushed tip 9450774cbe7986d80150b27a4da33b43d93bf026. Branch launchpad/row294, base c902a767d (the round 1 head ee77b3635 rebased with range-diff all "="
MANIFEST.sha256 lists the 17 code and test paths changed from the base, hashed from the tip's and stable patch-ids unchanged; receipts in run1/). The round 2 head is the commit that adds this
blobs (`sha256sum -c` passes on the tip). BUILD.md is the row note and is not in the manifest. file. MANIFEST.sha256 lists the 18 code and test paths changed from the base, hashed from that
No old test changes. webui/src/bus.mjs is byte-identical to the base (channel-proof hash pin, C7). commit's blobs (`sha256sum -c` passes on it). BUILD.md, ASSERTION-PRESERVATION.json and run1/ are
packages/cli/tests/access.test.mjs is unchanged; packages/cli/src/access.mjs overlaps row 295, the row note and are not in the manifest. webui/src/bus.mjs is byte-identical to the base
which rebases after this row (sage-3153). (channel-proof hash pin, C7). packages/cli/tests/access.test.mjs is unchanged;
packages/cli/src/access.mjs overlaps row 295, which rebases after this row (sage-3153).
Nothing has run. Runs follow Duckworth's approval and Sage's test CLEAR, in slot order: each Round 1 was 0b3f9c9d…94f3, approved by Duckworth (rev 3435, duckworth-0249b). Round 2 changes two
touched file alone, mutants M1-M11, the webui, cli and bus suites and every scripts/test-*.sh, tests after run 1 went red, and no product file:
with the limits in BUILD.md.
- packages/webui/tests/browser.test.mjs (new to the manifest; an old test, Mos's ruling (a) in
mos-1412): the script-list pin at :22 gains '/federation.js' at index 2 and the :21 comment adds
row 294. No other line changes. ASSERTION-PRESERVATION.json has the old and new lines.
- packages/webui/tests/granted-user.test.mjs, G5 (new test, a run 1 placement Sage accepted in
sage-3194): exactly one `action.refused` per refused verb, the count from the verb list's length,
each body exactly `{ code: 'access-refused' }`, and every other table's row count unchanged.
Run 1 (webui only, stopped at the first red) is recorded in BUILD.md. The whole gate runs fresh on
Sage's next CLEAR: npm ci --ignore-scripts at the root and in packages/webui, the webui, cli and
bus suites, every scripts/test-*.sh, then mutants M1-M11, with the limits in BUILD.md.
## Exception for Duckworth to rule on: the owner transport in a user's chat (C6; mos-1394, sage-3157) ## Exception for Duckworth to rule on: the owner transport in a user's chat (C6; mos-1394, sage-3157)
@@ -14,4 +14,5 @@ e7673188c1d76ecc63cdc24e7d1470922b1d69bedeb994a862e94924edfc27d2 packages/webui
9343ea9edb862c1545df2886754244ffd76b714cc90d7791fc32aee4ecfec594 packages/webui/src/serve.mjs 9343ea9edb862c1545df2886754244ffd76b714cc90d7791fc32aee4ecfec594 packages/webui/src/serve.mjs
70b243ed9a83ff822a4c7a148528ff5153574cc87d5c776fd2e12f340762ed76 packages/webui/src/sso.mjs 70b243ed9a83ff822a4c7a148528ff5153574cc87d5c776fd2e12f340762ed76 packages/webui/src/sso.mjs
8cc1185beda9085ced62470f1b9e39d95dcca2dcc8bf9325c18c2f0b2da618dc packages/webui/src/user-bus.mjs 8cc1185beda9085ced62470f1b9e39d95dcca2dcc8bf9325c18c2f0b2da618dc packages/webui/src/user-bus.mjs
8f89a1cc853ad275e62a518eb4f5567b5aaa629d32060c11daaaa671aded29db packages/webui/tests/granted-user.test.mjs 58f022643839b78c0bd149927157d1f7b36977212975a4fe549c9661c31c4e40 packages/webui/tests/browser.test.mjs
8bf20e514817d21356e59ca21a8a99ee25609f084f4a26c5a409d71a90b6f6a4 packages/webui/tests/granted-user.test.mjs
@@ -0,0 +1,6 @@
4abc648140eef53c8cb841ae64c22afc4211d86b
bee007832071139bac9af318096710aeb95f1f79
6de7443b94d28676a42630986d86bac9de1479fb
f3ed47f0b12f628cdbf0efe66970e184eef74ae2
3cf8180c22ed655b4f163f7a35b06deb47b54493
d1689ae8ba689ab811560b5f8ae82d95cc745c3e
@@ -0,0 +1,6 @@
4abc648140eef53c8cb841ae64c22afc4211d86b
bee007832071139bac9af318096710aeb95f1f79
6de7443b94d28676a42630986d86bac9de1479fb
f3ed47f0b12f628cdbf0efe66970e184eef74ae2
3cf8180c22ed655b4f163f7a35b06deb47b54493
d1689ae8ba689ab811560b5f8ae82d95cc745c3e
@@ -0,0 +1,6 @@
1: c866a8a69 = 1: df21d2f4d launchpad: row 294 FED R6 build and plan, granted-user sign-in (unrun, #1800)
2: 338e93185 = 2: f392be6ac launchpad: row 294 rulings sage-3153 (boot refusal line, owner transport seam G9, C7 follow-up, access.test.mjs unchanged; unrun, #1800)
3: 77514b8b9 = 3: c22dcfdd0 launchpad: row 294 BUILD.md M4 kill names the moved test
4: 9450774cb = 4: 0622c2fc8 launchpad: row 294 sage-3157, owner-transport exception written out, userOptionsFor, G9 pins no user value, M10/M11 (unrun, #1800)
5: ca710eabd = 5: 65f1b81f3 launchpad: row 294 round 1 manifest (17 paths from 9450774cb) and notes with the owner-transport exception
6: ee77b3635 = 6: 024499fc2 launchpad: row 294 BUILD.md M1 expectation corrected (Duckworth C1), review recorded with N1-N4 dispositions
@@ -0,0 +1,3 @@
TMPDIR /mnt/storage/scratch/tmp/g8gFnfF head 685ff053b6336311668104d08826e923d9f4532d
webui rc=1 seconds=55.787 limit=600 04:58:35Z
STOP at webui
@@ -0,0 +1,13 @@
✖ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (3039.999029ms)
✖ R6 G5 the bus refuses every owner verb over the user transport on its own (555.936822ms)
ℹ tests 365
ℹ suites 0
ℹ pass 362
ℹ fail 2
ℹ cancelled 0
ℹ skipped 1
ℹ todo 0
ℹ duration_ms 55747.039135
✖ failing tests:
✖ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (3039.999029ms)
✖ R6 G5 the bus refuses every owner verb over the user transport on its own (555.936822ms)
+2 -2
View File
@@ -18,8 +18,8 @@ test('served Console browser: real board fixtures, keyboard, drafts, receipts, t
assert.equal(await b.evaluate('document.querySelector("#session-count").textContent'), '3 of 4'); assert.equal(await b.evaluate('document.querySelector("#session-count").textContent'), '3 of 4');
await b.evaluate('document.querySelector("#hide-offline").click()'); await b.evaluate('document.querySelector("#hide-offline").click()');
assert.equal(await b.evaluate('document.querySelectorAll("table.sessions tbody tr").length'), 4); assert.equal(await b.evaluate('document.querySelectorAll("table.sessions tbody tr").length'), 4);
// Rows 129, 154, 191 and 194: chat.js, editor.js, processing.js and agents.js are the scripts added, same origin; the list is the pin, so another script is a visible change. // Rows 129, 154, 191, 194 and 294: chat.js, editor.js, processing.js, agents.js and federation.js are the scripts added, same origin; the list is the pin, so another script is a visible change.
assert.deepEqual(await b.evaluate('[...document.querySelectorAll("script")].map(s => s.getAttribute("src"))'), ['/editor.js', '/processing.js', '/brand.js', '/app.js', '/markdown-preview.js', '/chat.js', '/agents.js', '/bus.js']); assert.deepEqual(await b.evaluate('[...document.querySelectorAll("script")].map(s => s.getAttribute("src"))'), ['/editor.js', '/processing.js', '/federation.js', '/brand.js', '/app.js', '/markdown-preview.js', '/chat.js', '/agents.js', '/bus.js']);
assert.equal(await b.evaluate(`document.querySelectorAll('script[src="/processing.js"]').length`), 1); assert.equal(await b.evaluate(`document.querySelectorAll('script[src="/processing.js"]').length`), 1);
assert.equal(await b.evaluate(`document.querySelectorAll('script[src="/chat.js"]').length`), 1); assert.equal(await b.evaluate(`document.querySelectorAll('script[src="/chat.js"]').length`), 1);
assert.equal(await b.evaluate('!!window.injected'), false); assert.equal(await b.evaluate('!!window.injected'), false);
+16 -4
View File
@@ -123,6 +123,9 @@ async function signIn(env, sub) {
return { r, session: sessionOf(r) }; return { r, session: sessionOf(r) };
} }
const events = env => env.store.get('SELECT count(*) n FROM events').n; const events = env => env.store.get('SELECT count(*) n FROM events').n;
// Every table's row count but events', for a "nothing else written" pin.
const tables = env => Object.fromEntries(env.store.all("SELECT name FROM sqlite_master WHERE type='table' AND name NOT IN ('events', 'sqlite_sequence') ORDER BY name")
.map(({ name }) => [name, env.store.get(`SELECT count(*) n FROM "${name}"`).n]));
test('R6 G1 a granted user signs in, gets the user page and reaches the broker as itself', async t => { test('R6 G1 a granted user signs in, gets the user page and reaches the broker as itself', async t => {
const env = await setup(t); const env = await setup(t);
@@ -247,8 +250,8 @@ test('R6 G4 every owner route answers 403 owner-only before any bus call', async
test('R6 G5 the bus refuses every owner verb over the user transport on its own', async t => { test('R6 G5 the bus refuses every owner verb over the user transport on its own', async t => {
const env = await setup(t); const env = await setup(t);
const o = consoleBus(env.userTransport('alice'), { send: true, owner: env.ownerCall }); const o = consoleBus(env.userTransport('alice'), { send: true, owner: env.ownerCall });
const before = events(env); const before = env.store.get('SELECT max(seq) n FROM events').n, rest = tables(env);
for (const [why, run] of [ const refusals = [
['inbox', () => o.bus.inbox()], ['tasks', () => o.bus.tasks()], ['agents', () => o.bus.agents()], ['trail', () => o.bus.trail()], ['inbox', () => o.bus.inbox()], ['tasks', () => o.bus.tasks()], ['agents', () => o.bus.agents()], ['trail', () => o.bus.trail()],
['decisions', () => o.bus.decisions()], ['instances', () => o.bus.instances()], ['routes', () => o.bus.routes()], ['thread.claims', () => o.bus['thread.claims']()], ['decisions', () => o.bus.decisions()], ['instances', () => o.bus.instances()], ['routes', () => o.bus.routes()], ['thread.claims', () => o.bus['thread.claims']()],
['message.send', () => o.send({ to: 'chief', body: 'as the owner' })], ['limits.set', () => o.settingsWrite({ revision: 'x' })], ['message.send', () => o.send({ to: 'chief', body: 'as the owner' })], ['limits.set', () => o.settingsWrite({ revision: 'x' })],
@@ -258,8 +261,17 @@ test('R6 G5 the bus refuses every owner verb over the user transport on its own'
['instance.launch', () => o.agentWrite('instance.launch', {})], ['processing.status', () => o.processing.read()], ['instance.launch', () => o.agentWrite('instance.launch', {})], ['processing.status', () => o.processing.read()],
['processing.halt', () => o.processing.halt({})], ['library.status', () => o.libraryStatus({})], ['processing.halt', () => o.processing.halt({})], ['library.status', () => o.libraryStatus({})],
['project.create', () => o.chat.createProject({ name: 'mine' })], ['project.create', () => o.chat.createProject({ name: 'mine' })],
]) await assert.rejects(Promise.resolve().then(run), e => e.code === 'access-refused', why); ];
assert.equal(events(env), before, 'a refused verb wrote'); for (const [why, run] of refusals) await assert.rejects(Promise.resolve().then(run), e => e.code === 'access-refused', why);
// The broker records each refusal (row 37): one action.refused per verb, its body the code
// alone (#refused names no verb). No other table gains or loses a row.
const added = env.store.all('SELECT kind, body FROM events WHERE seq > ? ORDER BY seq', before);
assert.equal(added.length, refusals.length, 'one event per refused verb');
for (const e of added) {
assert.equal(e.kind, 'action.refused');
assert.deepEqual(JSON.parse(e.body), { code: 'access-refused' });
}
assert.deepEqual(tables(env), rest, 'a refused verb wrote');
}); });
// sage-3153 (C6): in a user's chat the owner transport carries `plugins` with {} and nothing else, // sage-3153 (C6): in a user's chat the owner transport carries `plugins` with {} and nothing else,