Files

4.8 KiB

Filbert review: row 109 round 2 (#1603): changes

Candidate manifest sha256 daa942cd5d03597479c2e9f6bd159b8f7ec5dec135ce1fbc1138e95e5b8ea69d (8 files). I rebuilt it in my own worktree at BASE 02fe2d9d5 with row109.patch. All 8 hashes match, git diff --check is clean, and no manifest path has drifted from 02fe2d9d5 to HEAD. The added lines have no dashes, bidi or control characters.

Blocker

B1. Two tests outside the manifest fail with the patch. Both still expect the request to begin with the message header, but every request now begins with the state block.

  • packages/seat/tests/session.test.mjs:227: /^echo: Message .* from pm, class REQUEST:\n\nhello/. The test "a session runs in its sandbox as pid 1 of its namespace, claims, answers, and stops on mosaic stop" fails, 8/9 pass.
  • packages/cli/tests/launcher.test.mjs:240: /^echo: Message .* from cto, class REQUEST:\n\nhello/. The test at line 203 fails, 16/17 pass.

The reply body now reads echo: Current state, read at ...:\nLaunches: allowed (never switched).\nOpen tasks: 0.\n\nMessage <id> from pm, sent <at>, class REQUEST:\n\nhello. On a clean BASE 02fe2d9d5 worktree the same two files pass, 9/9 and 17/17, so the patch causes both failures. Neither file is under scripts/test-*.sh, which may be why the packet's suite claims missed them.

Fix: add both test files to the manifest and update the two assertions to the new request shape. Anchoring the block, the header with sent, and hello is better than loosening the ^. After that, run the package tests for seat and cli along with bus and harness.

Sage's five checks (all pass on reading and in tests)

  1. Failed read. In runner.mjs a throw from client.call("state") that isn't SESSION_GONE sets unread. The turn becomes {ok:false, reason} without calling runTurn. The existing path then logs turn N ... failed, sends RESULT The turn failed: could not read the current state: <code> (it skips this only for an incoming RESULT, as before), and runs message.read. SESSION_GONE logs and exits with EXIT.session. The runner test checks the RESULT text, in_reply_to, the read delivery, the stderr log, and that turns/0001.stderr doesn't exist, so no adapter ran.
  2. The state verb is read-only. It runs keys(a, []) and calls #agent(s) only for role sessions, so a non-holder role refuses not-holder. Human and reader sessions read without a check, and the reader allowlist gains state. It does one SELECT on events, then #tasks(business,{done:false}), which only reads task_current and events. It has no insert, update or #event call. ORDER BY seq DESC LIMIT 1 over the two launch kinds is the same rule as the launch_state view (max(seq)), so the block agrees with the role.launch check.
  3. Fixture. The old first-blank-line split would have put the Message ...: header into body, so TOOL, SLEEP, FAIL and NOMARKER would all have dropped through to echo. The regex takes the text after the header. The fallback keeps the old split for a request without a header. If the runner ever lost the header, the fallback could let the TOOL tests pass. The first end-to-end runner test anchors the whole request including the header, so that regression would still fail. Nothing is hidden.
  4. pm.md. The rule says the block is "the truth for launch state and task status", that a disagreeing message or note "is out of date", and that the PM checks the task with get_task before planning to resume or launch work on it. get_task is the tool name in tools.mjs (unchanged).
  5. Cap and newest event. stateBlock writes Open tasks: <total>, the first <n> of cap <cap>. whenever the list is shorter than the total. state returns cap: TASK_PAGE (50), and state.test.mjs checks 55 open tasks give 50 shown, total 55 and cap 50. Launch at and event come from the newest launch event by seq. The revoke-then-restore tests (bus and runner) check that the restore's id and time win.

Notes (not blocking)

  • N1. The broker comment says the verb is "A read for role and reader sessions". The code and the bus README also allow human sessions. Add human to the comment.
  • N2. state.test.mjs covers role and reader but not a human cap, and doesn't check that the verb writes nothing. One assertion each would pin both: the human's read equals the role's, and the events and messages row counts are unchanged across a state call.

What I ran (single files, no slot)

bus/tests/state.test.mjs 6/6, harness/tests/runner.test.mjs 20/20, bus/tests/broker.test.mjs 15/15, harness/tests/tools.test.mjs 11/11, seat/tests/session.test.mjs 8/9 (B1), cli/tests/launcher.test.mjs 16/17 (B1). On BASE: session 9/9, launcher 17/17. I didn't rerun the mutants. Worktrees are removed and no process is left in them.

Verdict: changes (B1).