Files

17 KiB

Row278 / #1783: Console thread claims

Gander, prepared 2026-10-22T11:37:16Z. Reviewer Webby. Brief: docs/plans/2026-10-22_owner-thread-claims.md, section Brief: the Console shows thread claims. Authority sage-2491, design notes gander-0087/0088, Webby acceptances webby-0115/0116 (39c821e7c, 873992a9e), then build instruction sage-2607 after277 landed62f53b1e0. Final277 shape is argument-free [{thread,instance,holder_run,harness,at}], oldest thread first.

Current state and boundaries

Row253 is not mid-run and has no completed C4 gate. It is held unchanged while278 goes first. Already in the seat's isolated worktree; node_modules remains the plain canonical symlink. No install, new runtime dependency, harness launch, live config/unit/port change, credential read, provider call or paid action. Sage registers sessions. Claim and queue-next commands execute Node, so neither ran while another seat holds the slot. The claimant move belongs in the same CLEAR gap as the gate.

Sage-2625 moved the required base from980cec88c to6af85df4b. New branch gander/row278-b preserves gander/row278 and the row253 branches. There were no row278 commits yet, so the rebase has zero replayed commits; the pending source/test blobs were preserved. BASE-DRIFT.json records upstream's three test paths. No candidate path overlaps. Focused tests do not import/read those test files; shared fixture.mjs close() is unchanged, as is processing-http.mjs imported by serve.mjs. WebUI and bus whole suites include the changed processing.test.mjs and tasks.test.mjs on the new base.

Implementation decisions under the accepted design

  • cli.mjs adds only the normal listener's named thread.claims read adapter. It sends no arguments and makes no eligibility guess. views.mjs and testerBus are unchanged. The bus checks human/reader authority. No --send requirement.
  • serve.mjs has a named read allowlist entry, refuses query arguments, and gives the tester listener explicit403 tester-refused before busRead or any supplied bus callback. GET only; no new write route.
  • bus.js adds a separate Thread claims table after the unchanged Held roles section. Only thread, holder_run, harness and at are projected through existing text/time escaping. Extra instance/name/body/address fields never render. No s1-agents selector or role count change.
  • R1: only signed-out escapes the section catch. Every other error, including403, evicts only thread.claims from the existing cache, shows its reason locally and preserves roles. The following stale repaint cannot recover refused claims.
  • Sign-out uses the existing global data/DOM clearing path. The section also rejects an answer that arrives while signed out and deletes that late cache entry. The sign-out tests check the visible data and subsequent fallback behavior; the late-answer test also waits for JSON consumption.
  • The section awaits the existing config read before testing known tester mode. This prevents a direct Agents navigation from requesting owner metadata before the tester flag arrives. The server guard is independent of this client display choice.

Tests written before implementation, not executed

Four tests in thread-claims.test.mjs cover read envelope/no-store/no-send, argument and method refusal, malformed/empty/refused answers, tester-socket403 with zero bus calls, and a loader stand-in proving the normal adapter sends thread.claims with no args. Six browser tests cover:

  1. Held/empty/released claims, exact headers/time and byte-equal role section/count before/after refresh.
  2. HTTP403 plus not-configured and outcome-unknown stay local; a subsequent all-read failure proves old claims cannot return through the stale cache.
  3. Hostile visible fields are escaped; hostile extra instance/name/body/address fields are absent; no injected DOM nodes or scripts execute.
  4. A claims401 sign-in-required response uses global sign-out, removes claims/roles and prevents cached re-use.
  5. The actual tester socket browser retains role rows, renders no owner section, and makes no claims HTTP or bus call.
  6. A held claims response delivered after sign-out is not displayed or recovered on the next unavailable read.

The test-first execution order is intentionally held by Sage's no-Node rule. No RED or GREEN observation is claimed. On CLEAR, window.py red restores all three source files to6af85df4b temporarily, runs the named HTTP/section RED cases, then restores byte-identical source and git status. Only intentional missing-feature failures count as RED.

Named proposed checks

M1 removes the section and M2 merges thread rows into roles; both are killed only if the named held/release browser test fails. M3 also rethrows403; the named byte-equal role-section test must kill it. M4 removes the tester guard; the socket test must observe the wrong status/call count. M5 dispatches agents instead of thread.claims; the adapter test checks the exact verb/args. M6 retains the claims cache on refusal; the stale repaint in the local403 test must expose that. UNIQUENESS.json is a source-only count/hash check: all six old strings occur exactly once. It is not kill evidence.

Gate prepared, all steps NOTRUN

On Sage CLEAR: claimant move, syntax preflight, two intended RED cases, both touched files whole, M1-M6 with passing bases and per-change byte-identical restoration, bus whole, webui whole, all ten scripts/test-*.sh. Use TMPDIR from mktemp -d /mnt/storage/scratch/tmp/gXXXXXX, pipefail and tee. Busy check before every start. Log/wrapper names must not match the busy detector. Prepare commands in JSON to keep their text out of wrapper argv. checks.py and window.py were prepared from the proven253 harness but have not run; syntax classification uses node --check only, and runtime failures remain test failures. Per-case timeout is a stop for classification, never silently counted as a kill. Conservative stop on the first unexpected failure and report it to Sage; no retry without a ruling. Return the slot with per-step pass/fail/skip counts, elapsed seconds, kill table and cwd sweep count.

Manifest digest: d6e1476c8c37f41e7b199175bf9fec84696c950c6f169bb4e5c14286103ca882. Final review is Webby's manifest round; no author self-review replaces it. Static author review so far: examined all three source hunks, request/auth dispatch, local versus global refusal, tester config timing, field projection/escaping and fixture cleanup. git diff --check is the only executed check and finds no whitespace errors. No Node, browser, syntax execution or test has run.

Committed candidate under sage-2630

Source commit e7d21b91b8 contains all six runnable source/test/doc paths on gander/row278-b. Sage clarifies that invariant8 gates refactor commits, while the seat gate and Webby need a committed candidate tree. The previous packet-only status is superseded. This following commit records the source SHA separately, regenerates the manifest from git blobs and saves sha256sum -c output. Digest remains d6e1476c8c37f41e7b199175bf9fec84696c950c6f169bb4e5c14286103ca882; all six source blobs equal the previously frozen candidate. No Node, test, syntax execution or browser ran. No push until green.

The accepted first-run stop rule is explicit: a red in our new tests stops and goes to Sage; a red in a test already on refactor goes to Mos before Sage places it (mos-1272). Both categories stop immediately. Expected missing-feature RED observations are the intentional red stage, not unexpected failures. No automatic rerun.

Run1 void, test-only repair and run2

Grant sage-2632: claimant move rev3195 succeeded. Syntax5/0 (0.320s total); two intended RED cases observed (0.265s HTTP404,3.922s missing section) with byte-identical restoration; first new file whole3/1/0 in0.315s. Failure: the adapter loader omitted BusReadError required by the base's chat.mjs import. The runner stopped before the browser whole file or any remaining step. No timeout. Cwd sweep0 run leftovers; the raw match was only pre-existing chrome-devtools-mcp PID2880439, recorded with its start receipt and untouched. No pre-existing test ran red. Reported as gander-0092 and returned the slot.

Sage-2638 places the first own-test red and approves only the fake export, with all assertions unchanged. Webby-0133 confirms the import graph. Test-only source commit 964b6b1848 adds that export. Run1 is void; no result carries, including intended REDs. New manifest digest 188071d851e1f68297a7160a2bd557d9ca1b2776897ea2dd3b2c910ffd1c1f4a; only the new HTTP/adapter test blob changes. Runtime source and other tests are identical.

The harness now wraps every controlled node --test invocation with timeout -k10 300. The wrapper's124/137 outcomes are marked timeout, never pass or killed; the outer330s harness wait is a fallback. Each command uses the busy check, pipefail and tee. The source/test-only repair and record commit execute no Node. Run2 may start on own busy CLEAR without another Sage message, under2638. It repeats syntax, both REDs, both files whole, M1-M6, bus whole, webui whole and ten shells. A second unexpected red of any kind goes to Sage before any further change, then Mos under mos-1272. No automatic rerun. A15-minute status and40-minute notice still apply. Run2 numbers follow here after execution; none is claimed yet.

Run2 void, awaiting Mos before any repair

Grant sage-2638 on42abda031/source964b6b184: syntax5/0 in0.320s; expected REDs0.214s and3.772s, restored byte-identically; new HTTP/adapter whole4/0/0 in0.365s; new browser whole6/0/0 in4.023s; M1-M6 killed6/6, survivor0, timeout0, passing bases2.159s and changed runs12.765s; bus whole793/0/0 in23.116s; webui whole344/1/1 in55.324s. All ten shell files NOTRUN. run2/SUMMARY.json is assembled from preserved results and raw logs; KILL-TABLE.md names every check. All results are VOID under sage-2644, with no carry into run3.

The second unexpected red is pre-existing shell.test.mjs:415, five states on Board, Inbox, Tasks, Agents and Trail, assertion463: Agents normal state expected0 banners, got1. Static read shows stubBus lacks thread.claims. The section correctly shows the resulting local invalid-response banner. Proposed repair is an empty row array and callback in that existing stub, with every assertion unchanged. No repair, source/test/fixture/driver change or rerun has been made while Mos rules. Reported to Sage, Mos and Webby as gander-0094; slot returned. Sweep0 run leftovers, pre-existing chrome-devtools-mcp excluded with evidence from run1.

Named environment-only skip: editor rebuild from source needs exactly esbuild0.28.2; canonical node_modules has0.28.1. MOSAIC_REQUIRE_EDITOR_BUILD=1 would turn it into a failure. No install attempted; preserve and name this skip in run3.

Sage-2644 settles nested timeouts: do not edit any scripts/test-*.sh, even temporarily. At the call, wrap each whole file as timeout -k10 900 bash scripts/test-X.sh, which bounds all nested children. No such script was edited or run in run2. The planned harness-only call change will be made after Mos's ruling, before run3. Every direct node --test call already uses timeout -k10 300; command JSONs verify that prefix. Run3 starts from the top after Megavolt and on the granted slot. No Node executes while waiting.

Mos-1274 repair and run3 bounds, before execution

Test-only commit 9696d1fcb7 changes exactly two fixture lines in shell.test.mjs: adds an empty thread.claims row list and the callback using the existing verb() fail/hold path. No assertion changes. No runtime blob changes. This file joins the manifest and the independent whole-file phase, for seven paths and digest 8fa859a0c617defe42e50028b057a603c6634f6db47ac2e3f7c01dfb290228a3. Webby rechecks this digest. No Node or test has executed after the second stop.

Run3 waits for Sage's slot-to-you after Megavolt. It starts from the top. window.py now includes shell.test.mjs in the touched whole-file phase and wraps each whole shell invocation as timeout -k10 LIMIT bash scripts/test-X.sh. No scripts/test-*.sh bytes are edited. Any such timeout is unplaced to Sage and Mos. A further red or moved existing assertion is likewise unplaced; no automatic rerun.

Longest receipt selection: scanned every available Gander row196 JSON result/summary at ec1e7fad8 for successful, complete bash whole-file entries with one scripts/test-.sh argument. This is the recorded-duration set available to this seat, not a claim to all fleet timings. Row278 runs1/2 ran no shell file. Each bound is ceil(3longest)+120 seconds for headroom against newer-base changes; if no record existed it would be900 per sage-2646. All ten have receipts. SHELL-LIMITS.json records the exact durations, sources, script hashes and consulted set.

Whole shell file Longest recorded seconds Limit seconds Receipt
scripts/test-auth.sh 1.908123 126 ec1e7fad8:agents/gander/work/queue-196/r6/whole-results.json
scripts/test-conductor.sh 8.057174 145 ec1e7fad8:agents/gander/work/queue-196/r6/whole-results.json
scripts/test-config.sh 3.167892 130 ec1e7fad8:agents/gander/work/queue-196/r6/whole-results.json
scripts/test-discord.sh 8.776728 147 ec1e7fad8:agents/gander/work/queue-196/r5/resume/whole-results.json
scripts/test-extension-package.sh 3.012857 130 ec1e7fad8:agents/gander/work/queue-196/r5/resume/whole-results.json
scripts/test-foundation.sh 39.708726 240 ec1e7fad8:agents/gander/work/queue-196/r5/resume/whole-results.json
scripts/test-land-work.sh 12.623263 158 ec1e7fad8:agents/gander/work/queue-196/r5/resume/whole-results.json
scripts/test-queue.sh 23.443742 191 ec1e7fad8:agents/gander/work/queue-196/r5/resume/whole-results.json
scripts/test-release.sh 12.168674 157 ec1e7fad8:agents/gander/work/queue-196/r5/resume/whole-results.json
scripts/test-task.sh 36.783798 231 ec1e7fad8:agents/gander/work/queue-196/r5/resume/whole-results.json

Run3 numbers will be appended here after execution. Run1/run2 remain void next to their numbers above. No result carries.

Run3 green under sage-2648

Candidate3e4c77ac6, source9696d1fcb, manifest8fa859a0. Fresh run from the top; nothing carried from void runs1/2. Started12:26:46Z and completed verification12:31:45Z,299 wall seconds. No unexpected failure, assertion change or timeout.

Step Pass/fail/skip Wall seconds
syntax-0 1/0/0 0.064
syntax-1 1/0/0 0.064
syntax-2 1/0/0 0.064
syntax-3 1/0/0 0.064
syntax-4 1/0/0 0.064
syntax-6 1/0/0 0.064
red-0 0/1/0 intended RED 0.214
red-1 0/1/0 intended RED 3.773
focused-0 4/0/0 0.365
focused-1 6/0/0 3.922
focused-2 5/0/0 8.082
bus whole 793/0/0 22.463
webui whole 345/0/1 56.982
scripts/test-auth.sh whole 15/0/0 0.816
scripts/test-conductor.sh whole 17/0/0 6.078
scripts/test-config.sh whole 31/0/0 1.868
scripts/test-discord.sh whole 81/0/0 7.431
scripts/test-extension-package.sh whole 18/0/0 1.366
scripts/test-foundation.sh whole 44/0/0 39.901
scripts/test-land-work.sh whole 86/0/0 11.338
scripts/test-queue.sh whole 28/0/0 21.158
scripts/test-release.sh whole 14/0/0 2.67
scripts/test-task.sh whole 91/0/0 13.843

Syntax6/0. Both intended REDs repeat and restore byte-identical source and tracked status. Touched files whole: new HTTP4/0, new browser6/0, existing shell5/0. M1-M6 killed6/6, survivor0, timeout0, with passing bases and exact restores; run3/KILL-TABLE.md records named killers and times. Bus793/0, WebUI345/0/1, ten shell whole files425/0. Whole-phase reported assertions1563/0/1; this counts shell summary assertions, without adding nested TAP tests again. Focused repeats are listed separately. All direct test command JSONs use timeout -k10 300. Each whole shell command matches its pre-recorded limit exactly. No script changed.

Named skip: rebuilding from the source gives the same bytes, because esbuild0.28.1 is installed and0.28.2 is required. MOSAIC_REQUIRE_EDITOR_BUILD=1 would fail instead. No dependency install. The log line is saved in SUMMARY.json.

Sweep:0 run-created leftovers. The broad sweep found eight additional MCP/npm/code-mode processes plus the previously known browser helper; all predate the gate by over an hour. Their11:23:49-11:24:06Z start times are recorded with /proc ticks and UTC ps in run3/sweep.json and preexisting-processes.txt; initial broad output retained. Nothing signalled. Source and all ten script hashes still match their frozen values. No product/test bytes changed during the gate.

Seven-path manifest remains8fa859a0c617defe42e50028b057a603c6634f6db47ac2e3f7c01dfb290228a3. Records commit follows; publish own branch only under sage-2648, then hand directly to Webby and Sage. BUILD-LOG stays outside the landing manifest.