FLOOR: finished work, and find by id (#1)

A person looking at a rig's floor can now see its finished work, with each item's answer first in plain words, and find an item by id. Coverage is honest: a bounded or unreadable read says so instead of claiming there's nothing. An artifact reference wraps without changing its text.

Six files (+291/-8): the floor page and server, the runtime contract, and tests. Source-only entry; no tag, pin, release or deploy.
This commit is contained in:
Mike Schwarz authored and GitHub committed 2026-10-23 01:45:42 -07:00
1 parent e7346bbdbd
commit 652d2980b5
6 files changed
+291 -8

No files matched your search

+9 -1
View File
@@ -581,8 +581,16 @@ function factoryState() {
const attachment = typeof d.attached === "boolean"
? { attached: d.attached, reason: d.reason ?? null, detail: d.detail ?? null }
: {};
// Finished work, when the generator sends it (optional; see the contract). Absent stays absent ("this provider doesn't send
// finished work"). Sent but not in the declared shape (rows not a list, a row that isn't an item with a string id) is carried as
// unreadable, never as "none finished", and never at the cost of the open work beside it.
const okRow = (r) => !!r && typeof r === "object" && !Array.isArray(r) && typeof r.id === "string";
const done = d.done === undefined ? {}
: d.done && typeof d.done === "object" && Array.isArray(d.done.rows) && d.done.rows.every(okRow)
? { done: { rows: d.done.rows, coverage: d.done.coverage && typeof d.done.coverage === "object" && !Array.isArray(d.done.coverage) ? d.done.coverage : {} } }
: { done: { rows: [], coverage: { unreadable: "the finished work this box sent wasn't in the declared shape" } } };
return { ok: true, rig: d.rig || "fixture", generatedAt: new Date().toISOString(), ...attachment,
seats: Array.isArray(d.seats) ? d.seats : [], queue: Array.isArray(d.queue) ? d.queue : [] };
seats: Array.isArray(d.seats) ? d.seats : [], queue: Array.isArray(d.queue) ? d.queue : [], ...done };
}
// ---- stream: SSE change-signal (signal-only contract) ----------------------
+83 -4
View File
@@ -78,6 +78,16 @@
.queue-title { color: var(--text); font-weight: 600; }
.queue-state { color: var(--idle); font-size: 10px; font-weight: 650; letter-spacing: .04em; text-transform: uppercase; }
.route { color: var(--muted); overflow-wrap: anywhere; }
.item-id { display: block; margin-top: 3px; color: var(--muted); font: 10px ui-monospace, SFMono-Regular, Menlo, monospace; overflow-wrap: anywhere; }
.result { max-width: 40ch; white-space: pre-wrap; overflow-wrap: anywhere; }
.artifact { color: var(--muted); overflow-wrap: break-word; }
.unset { color: var(--muted); font-style: italic; }
.coverage { margin: -4px 0 10px; color: var(--muted); font-size: 11px; }
/* An element marked hidden stays hidden, whatever display a class gives it (the find box is display:flex). */
[hidden] { display: none !important; }
.find { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 0 0 18px; }
.find input { flex: 1 1 260px; max-width: 420px; min-width: 0; padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); color: var(--text); font: 12px ui-monospace, SFMono-Regular, Menlo, monospace; }
.find output { color: var(--muted); font-size: 11px; }
.notice { padding: 18px; color: var(--blocked); }
footer { margin-top: 22px; color: var(--muted); font-size: 11px; }
@media (max-width: 600px) {
@@ -93,6 +103,7 @@
<div><div class="eyebrow">Live activity</div><h1 id="rig">Rig floor</h1></div>
<div id="connection" class="connection"><span class="pulse"></span><span>connecting</span></div>
</header>
<div class="find" id="findbox" role="search" hidden><input id="find" type="search" placeholder="Find work by id (qitem-…)" aria-label="Find work by id" autocomplete="off" spellcheck="false"><output id="found" aria-live="polite"></output></div>
<div id="content"><div class="notice">Reading the runtime contract…</div></div>
<footer id="updated"></footer>
</main>
@@ -156,13 +167,56 @@
<td class="numeric">${seat.ageMinutes == null ? 'unknown' : `${escapeHtml(seat.ageMinutes)}m`}</td>
<td class="numeric">${escapeHtml(seat.pendingWork)}</td>
</tr>`).join('') || '<tr><td class="empty" colspan="6">No seats reported.</td></tr>';
// Ids and the find box come with finished work: a generator that sends no `done` gets the floor exactly as before.
const showIds = !!(state.done && Array.isArray(state.done.rows));
document.querySelector('#findbox').hidden = !showIds;
const queue = state.queue.map(item => `
<tr>
<td class="queue-title">${escapeHtml(item.title)}</td>
<tr${showIds ? ` data-id="${escapeHtml(item.id)}"` : ''}>
<td class="queue-title">${escapeHtml(item.title)}${showIds ? `<span class="item-id">${escapeHtml(item.id)}</span>` : ''}</td>
<td class="queue-state">${escapeHtml(item.state)}</td>
<td class="route">${escapeHtml(item.source)}</td>
<td class="route">${escapeHtml(item.destination)}</td>
</tr>`).join('') || '<tr><td class="empty" colspan="4">Queue is clear.</td></tr>';
// While a find is on, a table with no matching row says so instead of standing empty under its count.
const queueRows = queue + (showIds && state.queue.length ? '<tr id="nomatch-open" hidden><td class="empty" colspan="4">No match in the queue.</td></tr>' : '');
// Work that finished, from a provider that sends `done` (an older one doesn't, and then this section isn't drawn). The answer
// a seat closed the work with is its result; a field the work doesn't carry reads "not recorded", and a result the provider
// couldn't read says so instead of looking empty.
const unset = (text) => `<span class="unset">${text}</span>`;
// A closure in plain words; the queue's own word stays in the tooltip.
const SAY = { 'no-follow-on': 'Done, nothing follows', handed_off_to: 'Handed off to', blocked_on: 'Blocked on', denied: 'Denied', canceled: 'Canceled', escalation: 'Escalated' };
const decisionOf = (d) => !d?.reason ? unset('not recorded')
: `<span title="${escapeHtml(d.reason)}">${escapeHtml(SAY[d.reason] || d.reason)}${d.target ? `${SAY[d.reason] && /to$|on$/.test(SAY[d.reason]) ? ' ' : ': '}${escapeHtml(d.target)}` : ''}</span>`;
// An artifact reference may break after "@", ":", "/" or "#", not inside a word.
// Split the raw text first and escape each part: inserting after escaping would cut an entity (&#39;) apart.
const breakable = (t) => String(t).split(/(?<=[@:/#])/).map(escapeHtml).join('<wbr>');
const done = state.done && Array.isArray(state.done.rows) ? state.done : null;
const doneRows = done ? done.rows.map(item => {
if (!item || typeof item !== 'object') return '';
const decision = decisionOf(item.decision);
const answer = item.result ?? item.resolution;
const result = item.resultRead === false ? unset("couldn't be read") : typeof answer === 'string' && answer !== '' ? escapeHtml(answer) : unset('not recorded');
const closed = Date.parse(item.closedAt || '');
return `
<tr data-id="${escapeHtml(item.id)}">
<td class="queue-title">${escapeHtml(item.title)}<span class="item-id">${escapeHtml(item.id)}</span></td>
<td class="result">${result}</td>
<td class="route">${decision}</td>
<td class="artifact">${item.artifact ? breakable(item.artifact) : unset('not recorded')}</td>
<td class="numeric">${Number.isFinite(closed) ? escapeHtml(new Date(closed).toLocaleString(undefined, { timeZoneName: 'short' })) : unset('unknown')}</td>
</tr>`; }).join('') || `<tr><td class="empty" colspan="5">None of this rig's work among the newest ${escapeHtml(done.coverage?.looked ?? 0)} finished items on this box.</td></tr>` : '';
const cov = done?.coverage || {};
const doneSection = !done ? '' : cov.unreadable
? `<section><h2>Done recently</h2><div class="notice">Finished work couldn't be read: ${escapeHtml(cov.unreadable)}.</div></section>`
: `<section>
<h2>Done recently · ${done.rows.length}</h2>
<p class="coverage">The newest ${escapeHtml(done.rows.length)} of this rig's finished work, from the newest ${escapeHtml(cov.looked ?? 0)} finished items on this box.</p>
<div class="table-wrap"><table aria-label="Finished work">
<thead><tr><th>Work</th><th>Result</th><th>Decision</th><th>Artifact</th><th class="numeric">Closed</th></tr></thead>
<tbody>${doneRows}${done.rows.length ? '<tr id="nomatch-done" hidden><td class="empty" colspan="5">No match in finished work.</td></tr>' : ''}</tbody>
</table></div>
</section>`;
content.innerHTML = `
${welcomeHtml()}
@@ -182,12 +236,37 @@
<h2>Queue · ${state.queue.length}</h2>
<div class="table-wrap"><table aria-label="Rig queue">
<thead><tr><th>Work</th><th>State</th><th>Source</th><th>Destination</th></tr></thead>
<tbody>${queue}</tbody>
<tbody>${queueRows}</tbody>
</table></div>
</section>`;
</section>${doneSection}`;
lastState = state;
findWork();
updated.textContent = `Runtime snapshot · ${new Date(state.generatedAt).toLocaleString()}`;
}
// Find by id: only among the work this floor already holds (this rig's open work and its newest finished work); it reads
// nothing else. Kept outside #content so a refresh doesn't clear what was typed, and applied again after every refresh.
let lastState = null;
const findInput = document.querySelector('#find'), found = document.querySelector('#found');
// "This rig's" work is work with one of this floor's seats at either end: a generator that still sends other rigs' open work
// can't make the find box call that ours.
function findWork() {
const q = findInput.value.trim();
const seats = new Set((lastState?.seats || []).map(s => s.seat));
const ours = item => item && (seats.has(item.source) || seats.has(item.destination));
const hit = item => ours(item) && String(item.id).includes(q);
const openHits = (lastState?.queue || []).filter(hit), doneHits = (lastState?.done?.rows || []).filter(hit);
const shown = new Set([...openHits, ...doneHits].map(item => String(item.id)));
for (const row of content.querySelectorAll('tr[data-id]')) row.hidden = !!q && !shown.has(row.dataset.id);
for (const [sel, hits] of [['#nomatch-open', openHits], ['#nomatch-done', doneHits]]) { const r = document.querySelector(sel); if (r) r.hidden = !q || hits.length > 0; }
if (!q) { found.textContent = ''; return; }
const done = lastState?.done;
found.textContent = openHits.length || doneHits.length ? `${openHits.length} open, ${doneHits.length} finished`
: done?.coverage?.unreadable ? "Not in this rig's open work. Finished work couldn't be read, so this can't say whether it finished."
: `No work with that id in this rig's open work or its newest ${done?.rows?.length ?? 0} finished items (older finished work isn't searched).`;
}
findInput.addEventListener('input', findWork);
// The box's own introduction, declared in its manifest. Absent on a box
// that declares none, which is the normal case — this surface ships to
// every install and must not assume it is anybody's landing page.
+21
View File
@@ -110,6 +110,27 @@ by this contract (declared here, field-by-field), not by any backing system.
the nearest minute, or `null` when no activity timestamp is known. It
measures quietness, not uptime: a `working` seat can have a nonzero age.
- Degraded shape: `{ "ok": false, "degraded": "<why>", "rig": null, "seats": [], "queue": [] }`.
- `done` (optional, provisional): finished work, so work handed to a seat stays findable after it closes. Absent means the
generator doesn't send finished work; `rows: []` means none has finished. `queue` stays open work only.
```json
"done": {
"rows": [
{ "id": "<item id>", "state": "done", "title": "<one line>",
"source": "<session>", "destination": "<session>", "closedAt": "<ISO timestamp>",
"decision": { "reason": "<closure reason> | null", "target": "<closure target> | null" },
"result": "<the note the item was closed with> | null", "resultRead": true,
"resolution": "<string> | null", "artifact": "<evidence reference> | null",
"handedOffTo": "<item id> | null", "handedOffFrom": "<item id> | null" }
],
"coverage": { "looked": 100, "ours": 12, "shown": 10, "limit": 100 }
}
```
A field the item doesn't carry is `null`, never invented. `resultRead: false` means the result couldn't be read (not that
there is none). `coverage` says how much was looked at; `{ "unreadable": "<why>" }` there means finished work couldn't be read.
The runtime carries `done` through only in this shape: a `done` that is sent but isn't in it (rows not a list, a row without a
string `id`) arrives as `{ "rows": [], "coverage": { "unreadable": "<why>" } }`, never as none, and the open work is kept. Its text is shown as written: this runtime has no private display mode.
## stream
+139
View File
@@ -0,0 +1,139 @@
// FLOOR keeps finished work findable: the runtime carries the generator's optional `done` block in its declared shape
// (contract/runtime-api.md), and the surface shows it as "Done recently" with "not recorded" where a field is missing and a
// find-by-id box that looks only at what the floor already holds. Invented fixture data only.
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import net from "node:net";
import path from "node:path";
import vm from "node:vm";
import { spawn } from "node:child_process";
import { fileURLToPath } from "node:url";
const REPO = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const surface = fs.readFileSync(path.join(REPO, "app", "surfaces", "floor.html"), "utf8");
const DONE = { rows: [
{ id: "qitem-20261023070000-aaaa", state: "done", title: "Fix the README typo.", source: "assistant@lab", destination: "lab-impl@lab",
closedAt: "2026-10-23T07:00:00.000Z", decision: { reason: "no-follow-on", target: null }, result: "Fixed <b>line 12</b>.", resultRead: true,
resolution: null, artifact: "docs/README.md@1a2b3c4", handedOffTo: null, handedOffFrom: null },
{ id: "qitem-20261023065900-bbbb", state: "done", title: "Answer a question", source: "lab-qa@lab", destination: "lab-impl@lab",
closedAt: "2026-10-23T06:59:00.000Z", decision: { reason: null, target: null }, result: null, resultRead: true, resolution: null, artifact: null },
{ id: "qitem-20261023065800-cccc", state: "done", title: "Unread", source: "lab-qa@lab", destination: "lab-impl@lab",
closedAt: "2026-10-23T06:58:00.000Z", decision: { reason: "handed_off_to", target: "qitem-x" }, result: null, resultRead: false, artifact: null },
], coverage: { looked: 40, ours: 3, shown: 3, limit: 100 } };
const SEATS = [{ seat: "lab-impl@lab" }, { seat: "lab-qa@lab" }];
const OPEN = [{ id: "qitem-20261023071000-dddd", state: "pending", destination: "lab-impl@lab", source: "assistant@lab", tags: [], updated: "2026-10-23T07:10:00.000Z", title: "Open work" }];
const freePort = () => new Promise((resolve, reject) => { const s = net.createServer(); s.once("error", reject); s.listen(0, "127.0.0.1", () => { const { port } = s.address(); s.close(() => resolve(port)); }); });
async function stateFrom(fixture) {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "floor-done-"));
fs.cpSync(path.join(REPO, "app"), path.join(dir, "app"), { recursive: true });
fs.cpSync(path.join(REPO, "fixtures"), path.join(dir, "fixtures"), { recursive: true });
fs.writeFileSync(path.join(dir, "fixtures", "factory-state.json"), JSON.stringify(fixture));
const port = await freePort(), proc = spawn(process.execPath, [path.join(dir, "app", "serve-studio.mjs"), "--port", String(port), "--fixtures", path.join(dir, "fixtures")], { cwd: dir, stdio: "ignore" });
try {
for (let i = 0; i < 100; i++) { try { return await (await fetch(`http://127.0.0.1:${port}/api/factory/state`)).json(); } catch { await new Promise((r) => setTimeout(r, 100)); } }
throw new Error("runtime never answered");
} finally { proc.kill(); fs.rmSync(dir, { recursive: true, force: true }); }
}
test("the runtime carries `done` through in its declared shape; absent stays absent; a malformed one is carried as unreadable, never as none", async () => {
const s = await stateFrom({ rig: "lab", attached: true, seats: [], queue: OPEN, done: DONE });
assert.deepEqual(s.done, DONE); assert.deepEqual(s.queue, OPEN, "queue is unchanged");
assert.equal("done" in await stateFrom({ rig: "lab", attached: true, seats: [], queue: [] }), false, "a generator that sends no done: absent, not empty");
for (const bad of ["nope", { rows: [null] }, { rows: [{ title: "no id" }] }, { rows: "x" }, null]) {
const s2 = await stateFrom({ rig: "lab", attached: true, seats: [], queue: OPEN, done: bad });
assert.deepEqual(s2.done, { rows: [], coverage: { unreadable: "the finished work this box sent wasn't in the declared shape" } }, JSON.stringify(bad));
assert.deepEqual(s2.queue, OPEN, "a bad finished-work block never costs the open work");
}
assert.deepEqual((await stateFrom({ rig: "lab", attached: true, seats: [], queue: [], done: { rows: [] } })).done, { rows: [], coverage: {} });
});
// The surface's own script, run with just enough of a page for render() and the find box.
function page() {
const el = (sel) => ({ sel, innerHTML: "", textContent: "", value: "", className: "", lastElementChild: { textContent: "" }, hidden: false,
addEventListener() {}, querySelectorAll() { return rowsOf(this.innerHTML); } });
const els = { "#content": el("#content"), "#rig": el("#rig"), "#updated": el("#updated"), "#connection": el("#connection"), "#find": el("#find"), "#found": el("#found"), "#findbox": el("#findbox"), "#nomatch-open": el("#nomatch-open"), "#nomatch-done": el("#nomatch-done") };
const rows = new Map();
const rowsOf = (html) => [...html.matchAll(/<tr data-id="([^"]+)">/g)].map((m) => rows.get(m[1]) || rows.set(m[1], { dataset: { id: m[1] }, hidden: false }).get(m[1]));
const ctx = { document: { querySelector: (s) => els[s] }, fetch: () => new Promise(() => {}), EventSource: function () {}, setInterval, clearInterval, setTimeout, clearTimeout, parent: { postMessage() {} }, console };
vm.createContext(ctx);
vm.runInContext(surface.match(/<script>([\s\S]*)<\/script>/)[1].replace(/\bboot\(\);\s*$/, ""), ctx);
return { ctx, els, rowsOf };
}
test("FLOOR draws 'Done recently': id, decision, result (escaped), artifact; 'not recorded' and 'couldn't be read' are said; the open count is open work only", () => {
const { ctx, els } = page();
ctx.render({ ok: true, rig: "lab", generatedAt: "2026-10-23T07:11:00.000Z", attached: true, seats: SEATS, queue: OPEN, done: DONE });
const h = els["#content"].innerHTML;
assert.match(h, /<b>1<\/b><span>queue items<\/span>/, "finished work doesn't count as queued");
assert.match(h, /<h2>Done recently · 3<\/h2>/);
assert.match(h, /The newest 3 of this rig's finished work, from the newest 40 finished items on this box\./);
assert.match(h, /<span class="item-id">qitem-20261023070000-aaaa<\/span>/);
assert.match(h, /<td class="route"><span title="no-follow-on">Done, nothing follows<\/span><\/td>/, "the decision in plain words, the queue's word in the tooltip");
assert.match(h, /<th>Work<\/th><th>Result<\/th><th>Decision<\/th><th>Artifact<\/th><th class="numeric">Closed<\/th>/, "the answer right after the work (ux 07:42Z)");
assert.match(h, /<td class="result">Fixed &lt;b&gt;line 12&lt;\/b&gt;\.<\/td>/, "result text is escaped, never markup");
assert.match(h, /<td class="artifact">docs\/<wbr>README\.md@<wbr>1a2b3c4<\/td>/, "an artifact breaks after / @ : #, not inside a word");
assert.equal((h.match(/<span class="unset">not recorded<\/span>/g) || []).length, 4, "row b: decision, result and artifact; row c: artifact only (its decision is recorded, its result couldn't be read)");
assert.match(h, /<td class="result"><span class="unset">couldn't be read<\/span><\/td>/);
assert.match(h, /<span title="handed_off_to">Handed off to qitem-x<\/span>/);
ctx.render({ ok: true, rig: "lab", generatedAt: "x", attached: true, seats: [], queue: [] });
assert.doesNotMatch(els["#content"].innerHTML, /Done recently/, "a provider that sends no done: no section");
ctx.render({ ok: true, rig: "lab", generatedAt: "x", attached: true, seats: [], queue: [], done: { rows: [], coverage: { unreadable: "rig queue timed out" } } });
assert.match(els["#content"].innerHTML, /Finished work couldn't be read: rig queue timed out\./);
});
test("find by id looks only at the floor's own rows: matches are kept, others hidden, and a miss says so plainly", () => {
const { ctx, els, rowsOf } = page();
ctx.render({ ok: true, rig: "lab", generatedAt: "x", attached: true, seats: SEATS, queue: OPEN, done: DONE });
els["#find"].value = "aaaa"; ctx.findWork();
assert.equal(els["#nomatch-open"].hidden, false, "the queue says it has no match instead of standing empty"); assert.equal(els["#nomatch-done"].hidden, true);
assert.match(els["#content"].innerHTML, /<tr id="nomatch-open" hidden><td class="empty" colspan="4">No match in the queue\.<\/td><\/tr>/);
assert.match(els["#content"].innerHTML, /<tr id="nomatch-done" hidden><td class="empty" colspan="5">No match in finished work\.<\/td><\/tr>/);
const rows = rowsOf(els["#content"].innerHTML);
assert.deepEqual(rows.filter((r) => !r.hidden).map((r) => r.dataset.id), ["qitem-20261023070000-aaaa"]);
assert.equal(els["#found"].textContent, "0 open, 1 finished");
els["#find"].value = "qitem-from-another-rig"; ctx.findWork();
assert.equal(els["#found"].textContent, "No work with that id in this rig's open work or its newest 3 finished items (older finished work isn't searched).");
assert.ok(rowsOf(els["#content"].innerHTML).every((r) => r.hidden));
els["#find"].value = ""; ctx.findWork(); assert.equal(els["#found"].textContent, ""); assert.ok(rowsOf(els["#content"].innerHTML).every((r) => !r.hidden));
assert.doesNotMatch(surface.slice(surface.indexOf("function findWork"), surface.indexOf("findInput.addEventListener")), /fetch\(/, "the find box reads nothing");
});
// Review fixes on the first candidate. Each fails on it.
test("find counts only this floor's work: another rig's open item a generator still sends is neither found nor shown", () => {
const { ctx, els, rowsOf } = page();
const foreign = { id: "qitem-20261023071100-ffff", state: "pending", destination: "y@other", source: "x@other", tags: [], updated: "x", title: "theirs" };
ctx.render({ ok: true, rig: "lab", generatedAt: "x", attached: true, seats: SEATS, queue: [...OPEN, foreign], done: DONE });
els["#find"].value = "ffff"; ctx.findWork();
assert.match(els["#found"].textContent, /^No work with that id in this rig's open work/);
assert.ok(rowsOf(els["#content"].innerHTML).every((r) => r.hidden));
els["#find"].value = "dddd"; ctx.findWork(); assert.equal(els["#found"].textContent, "1 open, 0 finished");
});
test("bounded and unreadable finished work are said as such: no 'yet', and find doesn't claim a miss it can't know", () => {
const { ctx, els } = page();
ctx.render({ ok: true, rig: "lab", generatedAt: "x", attached: true, seats: SEATS, queue: OPEN, done: { rows: [], coverage: { looked: 100, ours: 0, shown: 0, limit: 100 } } });
assert.match(els["#content"].innerHTML, /None of this rig's work among the newest 100 finished items on this box\./); assert.doesNotMatch(els["#content"].innerHTML, /yet/);
ctx.render({ ok: true, rig: "lab", generatedAt: "x", attached: true, seats: SEATS, queue: OPEN, done: { rows: [], coverage: { unreadable: "rig queue timed out" } } });
els["#find"].value = "qitem-anything"; ctx.findWork();
assert.equal(els["#found"].textContent, "Not in this rig's open work. Finished work couldn't be read, so this can't say whether it finished.");
});
test("a hidden element stays hidden whatever a class says: the stylesheet makes [hidden] win", () => {
assert.match(surface, /\[hidden\] \{ display: none !important; \}/);
assert.match(surface, /\.find \{ display: flex;/, "the rule [hidden] has to beat is still there (positive control)");
assert.match(surface, /<div class="find" id="findbox" role="search" hidden>/);
});
test("an artifact reference wraps without changing its text: an apostrophe or ampersand survives the break points", () => {
const { ctx, els } = page();
const ref = "folder/owner's-output#1 & more@v2:x";
ctx.render({ ok: true, rig: "lab", generatedAt: "x", attached: true, seats: SEATS, queue: [], done: { rows: [{ ...DONE.rows[0], artifact: ref }], coverage: { looked: 1 } } });
const cell = els["#content"].innerHTML.match(/<td class="artifact">([\s\S]*?)<\/td>/)[1];
assert.doesNotMatch(cell, /&#<wbr>/, "no entity is cut");
const text = cell.replace(/<wbr>/g, "").replace(/&#39;/g, "'").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"');
assert.equal(text, ref, "the rendered text is the reference itself");
assert.equal((cell.match(/<wbr>/g) || []).length, 4, "after /, #, @ and :");
});
+1 -1
View File
@@ -10,7 +10,7 @@ const surface = fs.readFileSync(SURFACE, "utf8");
test("FLOOR renders seats and queue as semantic tables instead of cards", () => {
assert.match(surface, /<title>Rig Floor<\/title>/, "positive control: loaded the FLOOR surface");
assert.equal((surface.match(/<table\b/g) || []).length, 2);
assert.equal((surface.match(/<table\b/g) || []).length, 3, "seats, queue and finished work");
for (const heading of ["Seat", "Pod / member", "State", "Lifecycle", "Age", "Pending"]) {
assert.match(surface, new RegExp(`<th[^>]*>${heading.replace(" / ", " \\/ ")}<\\/th>`, "i"));
+38 -2
View File
@@ -23,9 +23,21 @@ import net from "node:net";
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import vm from "node:vm";
const REPO = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
// What FLOOR's own script draws into #content from one state, run with just enough of a page (no network, no timers fired).
function renderedFloor(html, state) {
const el = () => ({ innerHTML: "", textContent: "", value: "", className: "", hidden: true, lastElementChild: { textContent: "" }, addEventListener() {}, querySelectorAll: () => [] });
const els = {};
const ctx = { document: { querySelector: (s) => (els[s] ??= el()) }, fetch: () => new Promise(() => {}), EventSource: function () {}, setInterval, clearInterval, setTimeout, clearTimeout, parent: { postMessage() {} }, console };
vm.createContext(ctx);
vm.runInContext(html.match(/<script>([\s\S]*)<\/script>/)[1].replace(/\bboot\(\);\s*$/, ""), ctx);
ctx.render(state);
return els["#content"].innerHTML;
}
const git = (...args) => {
const r = spawnSync("git", args, { cwd: REPO, encoding: "utf8" });
assert.equal(r.status, 0, `git ${args.join(" ")} failed: ${r.stderr}`);
@@ -120,8 +132,32 @@ test("zero-config: the served rail and its bytes are unchanged from before the c
assert.deepEqual(await after.json("/surfaces.json"), await before.json("/surfaces.json"),
"the zero-config manifest projection changed");
assert.equal(await after.text("/surfaces/floor.html"), await before.text("/surfaces/floor.html"),
"the bytes of the SDK's own surface changed for a consumer who adopted nothing");
// The SDK's own surface for a consumer who adopted nothing. Its bytes can't stay frozen forever (FLOOR gained finished work,
// shown only to a generator that sends `done`), so what is held is what such a consumer SEES, styles included:
// - the markup outside style and script is the same, apart from elements marked hidden, and those count as unseen ONLY because
// the stylesheet says `[hidden] { display: none !important; }` (no class rule can then show them);
// - no style rule was removed or changed, and every added rule names only classes and ids that page doesn't show;
// - render() draws the same thing from the shipped fixture state.
const [a, b] = [await after.text("/surfaces/floor.html"), await before.text("/surfaces/floor.html")];
const styleOf = (h) => (h.match(/<style>([\s\S]*?)<\/style>/)?.[1] || "").replace(/\/\*[\s\S]*?\*\//g, "").replace(/@media[^{]*\{/g, "");
const rules = (h) => new Set([...styleOf(h).matchAll(/([^{}]+)\{([^{}]*)\}/g)].map((m) => `${m[1].trim().replace(/\s+/g, " ")} { ${m[2].trim().replace(/\s+/g, " ")} }`));
const [ra, rb] = [rules(a), rules(b)];
assert.ok(rb.size > 10, `positive control: the baseline's rules were read (${rb.size})`);
assert.deepEqual([...rb].filter((r) => !ra.has(r)), [], "a style rule the zero-config page uses was removed or changed");
const hides = ra.has("[hidden] { display: none !important; }");
const markup = (h) => h.replace(/<style>[\s\S]*?<\/style>/, "").replace(/<script>[\s\S]*?<\/script>/, "");
const unhidden = (h) => (hides ? h.replace(/<(\w+)\b[^>]*\shidden\b[^>]*>[\s\S]*?<\/\1>\s*/g, "") : h);
assert.equal(unhidden(markup(a)), markup(b), "the visible markup of the SDK's own surface changed for a consumer who adopted nothing");
const fixture = await after.json("/api/factory/state");
assert.equal("done" in fixture, false, "positive control: the shipped fixture sends no finished work");
const drawn = renderedFloor(a, fixture);
assert.equal(drawn, renderedFloor(b, fixture), "what FLOOR draws changed for a consumer who adopted nothing");
const seen = unhidden(markup(a)) + drawn;
for (const r of [...ra].filter((x) => !rb.has(x) && x !== "[hidden] { display: none !important; }")) {
const names = r.split("{")[0].match(/[.#][A-Za-z_][\w-]*/g) || [];
for (const n of names) assert.ok(!new RegExp(n[0] === "." ? `class="[^"]*\\b${n.slice(1)}\\b` : `id="${n.slice(1)}"`).test(seen),
`the added rule "${r}" styles ${n}, which a consumer who adopted nothing sees`);
}
});
test("zero-config: the contract answer is additive — one field gained, none lost, version unmoved", async (t) => {