tests: launch notice routing and talk waiting/reply pinned (row 151, #1645)

Row 151 round 1, Dewey's candidate on 686fc1cb6. Filbert approved
(comment 28726). Test-only. Sage's landing gate ran on this commit
plus row 153.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-15 19:32:58 -05:00
co-authored by Claude Opus 5.5
parent c9df996ac1
commit 810186578a
2 changed files with 44 additions and 0 deletions
@@ -92,6 +92,12 @@ test('a message to a stopped role sends launch.by one notice, and the result say
launcherRunning: true,
});
assert.equal(ctx.notices().length, 2);
// Row 151 (#1645): the notice is routed to launch.by's holder, which the Console's waiting lists read.
// message.receive selects on to_role, so only this row shows a notice routed anywhere else.
assert.equal(
ctx.store().get("SELECT holder_run FROM deliveries WHERE message=? AND op='routed'", ctx.notices().at(-1).id).holder_run,
'chief-run',
);
// A role's message to a stopped role tells launch.by too.
ctx.launch('coder', 'coder');
ctx.claim('coder');
+38
View File
@@ -118,6 +118,44 @@ test("talk says when the role isn't running, whether launch.by was told, and how
assert.equal(await text(s, "coder"), "");
});
// Row 151 (#1645): rows 146 and 142 in one talk. The waiting line prints once after "sent", a
// message that isn't the reply arrives first and stays unread, then the reply prints and talk exits 0.
test("talk to a stopped role prints the waiting line once, skips a non-reply and prints the reply", async (t) => {
const s = setup(t, {}, { demo: { ...BUSINESSES.demo, launch: { by: "pm", instances: ["cto", "coder"], models: {}, limits: {} } } });
const pm = s.b.bindLaunch({ business: "demo", role: "pm", run: "pm-run", harness: "pi" });
call(s.b, pm, "role.claim");
// pm's note arrives on the first poll; cto comes up and answers on the second.
let polls = 0;
let note;
let reply;
const transport = (business) => {
const inner = s.transport(business);
return async (verb, args) => {
if (verb === "message.receive" && ++polls === 1) note = call(s.b, pm, "message.send", { to: "human", body: "launching cto", class: "INFO" });
if (verb === "message.receive" && polls === 2) {
const cto = s.b.bindLaunch({ business: "demo", role: "cto", run: "cto-run", harness: "pi" });
call(s.b, cto, "role.claim");
const [m] = call(s.b, cto, "message.receive");
reply = call(s.b, cto, "message.send", { to: m.from_role, body: "on it", class: "RESULT", in_reply_to: m.id });
}
return inner(verb, args);
};
};
const r = await s.run(["talk", "cto", "review the plan", "--wait", "5", "--business", "demo"], io(), { transport });
assert.equal(r.code, 0, r.error);
const sent = s.store.get("SELECT id FROM messages WHERE from_role='human' ORDER BY seq DESC LIMIT 1");
assert.equal(
r.io.out.text,
`sent ${sent.id.slice(0, 8)} to cto\ncto isn't running, pm has been told\ncto (RESULT, re ${sent.id.slice(0, 8)}) ${reply.id.slice(0, 8)}:\non it\n`,
);
assert.equal(polls, 2, "the note came first");
assert.deepEqual(s.calls.filter((c) => c.verb === "message.read").map((c) => c.args.id), [reply.id], "only the reply was marked read");
const inbox = io();
await main(["inbox", "--business", "demo"], inbox, { system: { dataRoot: s.dataRoot }, transport: s.transport });
assert.match(inbox.out.text, /messages: 1 unread\n/);
assert.match(inbox.out.text, new RegExp(`pm \\(INFO\\) ${note.id.slice(0, 8)}:\nlaunching cto\n`));
});
test("talk, stop and launches off/on refuse inside an agent run; bad arguments are usage errors", async (t) => {
const s = setup(t);
const agent = () => io({ ...io().env, CLAUDECODE: "1" });