Skip to content

Commit abff675

Browse files
committed
docs(subagent): document yield take of terminal wait results
1 parent 5c3e1a9 commit abff675

2 files changed

Lines changed: 52 additions & 5 deletions

File tree

‎src/subagent/agent-fleet.test.ts‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3914,6 +3914,50 @@ describe("wait_agents timed_out collection (CL-8028)", () => {
39143914
);
39153915
expect(fleetRecords.peek(worker.id)?.collected).toBe(true);
39163916
});
3917+
3918+
test("a mixed yield takes the done report and peeks the running sibling", async () => {
3919+
const liveGate = deferred<RunSubAgentResult>();
3920+
const deps = makeDeps(async (params) => {
3921+
if (params.description === "done lane") return { report: "shipped" };
3922+
return liveGate.promise;
3923+
});
3924+
const spawn = createSpawnAgentTool(deps);
3925+
const wait = createWaitAgentsTool({
3926+
sessions: deps.sessions,
3927+
fleetRecords: deps.fleetRecords,
3928+
shouldYieldWait: () => occupancyShouldYieldWait(deps.fleetRecords),
3929+
});
3930+
const doneSpawn = await callTool(spawn, {
3931+
description: "done lane",
3932+
prompt: "do it",
3933+
intent: "explore",
3934+
});
3935+
const liveSpawn = await callTool(spawn, {
3936+
description: "live lane",
3937+
prompt: "do it",
3938+
intent: "explore",
3939+
});
3940+
const doneId = doneSpawn.agent_id as string;
3941+
const liveId = liveSpawn.agent_id as string;
3942+
await waitUntilMailboxTerminal(deps.fleetRecords, deps.sessions, doneId);
3943+
expect(occupancyShouldYieldWait(deps.fleetRecords)).toBe(true);
3944+
const waited = await callTool(wait, {
3945+
targets: [doneId, liveId],
3946+
timeout_ms: 5_000,
3947+
});
3948+
expect(waited.timed_out).toBe(true);
3949+
const results = waited.results as Record<string, unknown>[];
3950+
const doneRow = defined(results.find((row) => row.agent_id === doneId));
3951+
const liveRow = defined(results.find((row) => row.agent_id === liveId));
3952+
expect(doneRow.status).toBe("done");
3953+
expect(doneRow.report).toBe("shipped");
3954+
expect(deps.fleetRecords.peek(doneId)?.collected).toBe(true);
3955+
expect(liveRow.status).toBe("running");
3956+
expect(liveRow.report).toBeUndefined();
3957+
expect(deps.sessions.get(liveId)?.status).toBe("running");
3958+
expect(deps.fleetRecords.peek(liveId)?.collected).not.toBe(true);
3959+
liveGate.resolve({ report: "ok" });
3960+
});
39173961
});
39183962

39193963
describe("wait_agents tool copy", () => {

‎src/subagent/agent-fleet.ts‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,8 +1559,10 @@ interface WaitAgentsDeps {
15591559
/**
15601560
* Supported but unwired in production: no current mount passes this
15611561
* (TUI does not mount wait_agents; exec mounts without the predicate).
1562-
* When true, finish the wait as a timeout (workers untouched, no take)
1563-
* so occupancy can deliver mailbox mail or a queued operator steer.
1562+
* When true, finish the wait as a timeout so occupancy can deliver
1563+
* mailbox mail or a queued operator steer. Live and awaiting_director
1564+
* records stay peeked (workers keep running); terminals are taken
1565+
* unless already bodyHanded.
15641566
*/
15651567
shouldYieldWait?: () => boolean;
15661568
}
@@ -1575,9 +1577,10 @@ function isWaitTerminal(id: string, fleetRecords: FleetMailboxHandle): boolean {
15751577
* elapses, or the optional (currently unwired in production)
15761578
* `shouldYieldWait` predicate is true. Driven by the session
15771579
* store's mailbox (`subscribe`) raced against a timer and the parent tool
1578-
* signal; never polls. Timeout, abort, and yield have no side effects:
1579-
* workers keep running and remain waitable. Overlay writers wake this wait
1580-
* via `sessions.wake()`.
1580+
* signal; never polls. Timeout, abort, and yield do not interrupt
1581+
* workers: live and awaiting_director stay peeked; terminals are taken
1582+
* unless already bodyHanded. Overlay writers wake this wait via
1583+
* `sessions.wake()`.
15811584
*/
15821585
async function waitForTerminal(
15831586
sessions: SubAgentSessionStore,

0 commit comments

Comments
 (0)