harness: a new PM run reads current launch state and open tasks before each turn, and old messages show their age, row 109 (#1603)

The broker gains a read-only state verb (launch state with the event that set it, open tasks capped). The runner fetches it before each turn and puts a "Current state" block at the top of the request; a failed read fails the turn. turnRequest() adds the message time. roles/pm.md gets one rule: the block is the truth for launch state and task status. Seat session, seat sandbox and cli launcher tests re-anchored to the new request shape.

Built by Researcher, packet 875c515e9. Filbert approved round 3, comment 28333, candidate manifest 0a62225e (11 paths). Sage gate on 9774d70db plus row109.patch: every package node suite and every scripts/test-*.sh green on the first run, skipped 0 in bus, harness and seat. Vikunja #259.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-13 19:12:54 -05:00
co-authored by Claude Opus 5.5
parent 848ceb68a4
commit badfa52b9d
11 changed files with 299 additions and 11 deletions
+2 -1
View File
@@ -214,7 +214,8 @@ async function session(t, { expose = () => [] } = {}) {
writeFileSync(join(bundle, "tools.json"), "[]");
const adapter = join(root, "adapter.sh");
writeFileSync(adapter, [
`body=$(printf '%s\\n' "$MOSAIC_REQUEST" | sed '1,/^$/d')`,
// Row 109 (#1603): a state block opens the request, so the body is what follows the "Message ...:" header and its blank line.
`body=$(printf '%s\\n' "$MOSAIC_REQUEST" | sed '1,/^Message .*:$/d' | sed '1d')`,
`case $body in TOOL\\ *) exec '${process.execPath}' '${FAKE}' ;; esac`,
`out=$(cd "$MOSAIC_WORKSPACE" && /bin/sh -c "$body" 2>&1); rc=$?`,
`printf 'rc=%s\\n%s' "$rc" "$out"`,
+3 -1
View File
@@ -224,7 +224,9 @@ test("a session runs in its sandbox as pid 1 of its namespace, claims, answers,
if (!reply) await new Promise((r) => setTimeout(r, 50));
}
assert.ok(reply, "the session answered");
assert.match(reply.body, /^echo: Message .* from pm, class REQUEST:\n\nhello/);
// Row 109 (#1603): the turn opens with the state block, then the header with the time it was sent.
const sentAt = store.get("SELECT at FROM messages WHERE id=?", sent.id).at;
assert.match(reply.body, new RegExp(`^echo: Current state, read at \\S+:\nLaunches: allowed \\(never switched\\)\\.\nOpen tasks: 0\\.\n\nMessage ${sent.id} from pm, sent ${sentAt}, class REQUEST:\n\nhello$`));
const registry = new Registry(dataRoot);
registry.add({ business: "acme", instance: "coder", run, pid: child.pid, startTime: startTimeOf(child.pid), runnerPid: runner.pid, runnerStartTime: runner.startTime });