test(subagents): add regression matrix for nested announce delivery

This commit is contained in:
Tyler Yust
2026-03-04 15:44:36 -08:00
parent d65bc347eb
commit 2f7e66856e
3 changed files with 685 additions and 0 deletions

View File

@@ -2055,6 +2055,7 @@ describe("subagent announce formatting", () => {
});
it("ignores post-completion announce traffic for completed run-mode requester sessions", async () => {
// Regression guard: late announces for ended run-mode orchestrators must be ignored.
subagentRegistryMock.isSubagentSessionRunActive.mockReturnValue(false);
subagentRegistryMock.shouldIgnorePostCompletionAnnounceForSession.mockReturnValue(true);
sessionStore = {
@@ -2286,4 +2287,503 @@ describe("subagent announce formatting", () => {
expect(call?.params?.channel, testCase.name).toBe(testCase.expectedChannel);
}
});
describe("subagent announce regression matrix for nested completion delivery", () => {
function makeChildCompletion(params: {
runId: string;
childSessionKey: string;
requesterSessionKey: string;
task: string;
createdAt: number;
frozenResultText: string;
outcome?: { status: "ok" | "error" | "timeout"; error?: string };
endedAt?: number;
cleanupCompletedAt?: number;
label?: string;
}) {
return {
runId: params.runId,
childSessionKey: params.childSessionKey,
requesterSessionKey: params.requesterSessionKey,
requesterDisplayKey: params.requesterSessionKey,
task: params.task,
label: params.label,
cleanup: "keep" as const,
createdAt: params.createdAt,
endedAt: params.endedAt ?? params.createdAt + 1,
cleanupCompletedAt: params.cleanupCompletedAt ?? params.createdAt + 2,
frozenResultText: params.frozenResultText,
outcome: params.outcome ?? ({ status: "ok" } as const),
};
}
it("regression simple announce, leaf subagent with no children announces immediately", async () => {
// Regression guard: repeated refactors accidentally delayed leaf completion announces.
subagentRegistryMock.countPendingDescendantRuns.mockReturnValue(0);
const didAnnounce = await runSubagentAnnounceFlow({
childSessionKey: "agent:main:subagent:leaf-simple",
childRunId: "run-leaf-simple",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
roundOneReply: "leaf says done",
});
expect(didAnnounce).toBe(true);
expect(agentSpy).toHaveBeenCalledTimes(1);
const call = agentSpy.mock.calls[0]?.[0] as { params?: { message?: string } };
expect(call?.params?.message ?? "").toContain("leaf says done");
});
it("regression nested 2-level, parent announces direct child frozen result instead of placeholder text", async () => {
// Regression guard: parent announce once used stale waiting text instead of child completion output.
subagentRegistryMock.countPendingDescendantRuns.mockReturnValue(0);
subagentRegistryMock.listSubagentRunsForRequester.mockImplementation((sessionKey: string) =>
sessionKey === "agent:main:subagent:parent-2-level"
? [
makeChildCompletion({
runId: "run-child-2-level",
childSessionKey: "agent:main:subagent:parent-2-level:subagent:child",
requesterSessionKey: "agent:main:subagent:parent-2-level",
task: "child task",
createdAt: 10,
frozenResultText: "child final answer",
}),
]
: [],
);
const didAnnounce = await runSubagentAnnounceFlow({
childSessionKey: "agent:main:subagent:parent-2-level",
childRunId: "run-parent-2-level",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
roundOneReply: "placeholder waiting text",
});
expect(didAnnounce).toBe(true);
const call = agentSpy.mock.calls[0]?.[0] as { params?: { message?: string } };
const message = call?.params?.message ?? "";
expect(message).toContain("Child completion results:");
expect(message).toContain("child final answer");
expect(message).not.toContain("placeholder waiting text");
});
it("regression parallel fan-out, parent defers until both children settle and then includes both outputs", async () => {
// Regression guard: fan-out paths previously announced after the first child and dropped the sibling.
let pending = 1;
subagentRegistryMock.countPendingDescendantRuns.mockImplementation((sessionKey: string) =>
sessionKey === "agent:main:subagent:parent-fanout" ? pending : 0,
);
subagentRegistryMock.listSubagentRunsForRequester.mockImplementation((sessionKey: string) =>
sessionKey === "agent:main:subagent:parent-fanout"
? [
makeChildCompletion({
runId: "run-fanout-a",
childSessionKey: "agent:main:subagent:parent-fanout:subagent:a",
requesterSessionKey: "agent:main:subagent:parent-fanout",
task: "child a",
createdAt: 10,
frozenResultText: "result A",
}),
makeChildCompletion({
runId: "run-fanout-b",
childSessionKey: "agent:main:subagent:parent-fanout:subagent:b",
requesterSessionKey: "agent:main:subagent:parent-fanout",
task: "child b",
createdAt: 11,
frozenResultText: "result B",
}),
]
: [],
);
const deferred = await runSubagentAnnounceFlow({
childSessionKey: "agent:main:subagent:parent-fanout",
childRunId: "run-parent-fanout",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
});
expect(deferred).toBe(false);
expect(agentSpy).not.toHaveBeenCalled();
pending = 0;
const announced = await runSubagentAnnounceFlow({
childSessionKey: "agent:main:subagent:parent-fanout",
childRunId: "run-parent-fanout",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
});
expect(announced).toBe(true);
expect(agentSpy).toHaveBeenCalledTimes(1);
const call = agentSpy.mock.calls[0]?.[0] as { params?: { message?: string } };
const message = call?.params?.message ?? "";
expect(message).toContain("result A");
expect(message).toContain("result B");
});
it("regression parallel timing difference, fast child cannot trigger early parent announce before slow child settles", async () => {
// Regression guard: timing skew once allowed partial parent announces with only fast-child output.
let pendingSlowChild = 1;
subagentRegistryMock.countPendingDescendantRuns.mockImplementation((sessionKey: string) =>
sessionKey === "agent:main:subagent:parent-timing" ? pendingSlowChild : 0,
);
subagentRegistryMock.listSubagentRunsForRequester.mockImplementation((sessionKey: string) =>
sessionKey === "agent:main:subagent:parent-timing"
? [
makeChildCompletion({
runId: "run-fast",
childSessionKey: "agent:main:subagent:parent-timing:subagent:fast",
requesterSessionKey: "agent:main:subagent:parent-timing",
task: "fast child",
createdAt: 10,
endedAt: 11,
frozenResultText: "fast child result",
}),
makeChildCompletion({
runId: "run-slow",
childSessionKey: "agent:main:subagent:parent-timing:subagent:slow",
requesterSessionKey: "agent:main:subagent:parent-timing",
task: "slow child",
createdAt: 11,
endedAt: 40,
frozenResultText: "slow child result",
}),
]
: [],
);
const prematureAttempt = await runSubagentAnnounceFlow({
childSessionKey: "agent:main:subagent:parent-timing",
childRunId: "run-parent-timing",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
});
expect(prematureAttempt).toBe(false);
expect(agentSpy).not.toHaveBeenCalled();
pendingSlowChild = 0;
const settledAttempt = await runSubagentAnnounceFlow({
childSessionKey: "agent:main:subagent:parent-timing",
childRunId: "run-parent-timing",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
});
expect(settledAttempt).toBe(true);
const call = agentSpy.mock.calls[0]?.[0] as { params?: { message?: string } };
const message = call?.params?.message ?? "";
expect(message).toContain("fast child result");
expect(message).toContain("slow child result");
});
it("regression nested parallel, middle waits for two children then parent receives the synthesized middle result", async () => {
// Regression guard: nested fan-out previously leaked incomplete middle-agent output to the parent.
const middleSessionKey = "agent:main:subagent:parent-nested:subagent:middle";
let middlePending = 2;
subagentRegistryMock.countPendingDescendantRuns.mockImplementation((sessionKey: string) => {
if (sessionKey === middleSessionKey) {
return middlePending;
}
return 0;
});
subagentRegistryMock.listSubagentRunsForRequester.mockImplementation((sessionKey: string) => {
if (sessionKey === middleSessionKey) {
return [
makeChildCompletion({
runId: "run-middle-a",
childSessionKey: `${middleSessionKey}:subagent:a`,
requesterSessionKey: middleSessionKey,
task: "middle child a",
createdAt: 10,
frozenResultText: "middle child result A",
}),
makeChildCompletion({
runId: "run-middle-b",
childSessionKey: `${middleSessionKey}:subagent:b`,
requesterSessionKey: middleSessionKey,
task: "middle child b",
createdAt: 11,
frozenResultText: "middle child result B",
}),
];
}
if (sessionKey === "agent:main:subagent:parent-nested") {
return [
makeChildCompletion({
runId: "run-middle",
childSessionKey: middleSessionKey,
requesterSessionKey: "agent:main:subagent:parent-nested",
task: "middle orchestrator",
createdAt: 12,
frozenResultText: "middle synthesized output from A and B",
}),
];
}
return [];
});
const middleDeferred = await runSubagentAnnounceFlow({
childSessionKey: middleSessionKey,
childRunId: "run-middle",
requesterSessionKey: "agent:main:subagent:parent-nested",
requesterDisplayKey: "agent:main:subagent:parent-nested",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
});
expect(middleDeferred).toBe(false);
middlePending = 0;
const middleAnnounced = await runSubagentAnnounceFlow({
childSessionKey: middleSessionKey,
childRunId: "run-middle",
requesterSessionKey: "agent:main:subagent:parent-nested",
requesterDisplayKey: "agent:main:subagent:parent-nested",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
});
expect(middleAnnounced).toBe(true);
const parentAnnounced = await runSubagentAnnounceFlow({
childSessionKey: "agent:main:subagent:parent-nested",
childRunId: "run-parent-nested",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
});
expect(parentAnnounced).toBe(true);
expect(agentSpy).toHaveBeenCalledTimes(2);
const parentCall = agentSpy.mock.calls[1]?.[0] as { params?: { message?: string } };
expect(parentCall?.params?.message ?? "").toContain("middle synthesized output from A and B");
});
it("regression sequential spawning, parent preserves child output order across child 1 then child 2 then child 3", async () => {
// Regression guard: synthesized child summaries must stay deterministic for sequential orchestration chains.
subagentRegistryMock.countPendingDescendantRuns.mockReturnValue(0);
subagentRegistryMock.listSubagentRunsForRequester.mockImplementation((sessionKey: string) =>
sessionKey === "agent:main:subagent:parent-sequential"
? [
makeChildCompletion({
runId: "run-seq-1",
childSessionKey: "agent:main:subagent:parent-sequential:subagent:1",
requesterSessionKey: "agent:main:subagent:parent-sequential",
task: "step one",
createdAt: 10,
frozenResultText: "result one",
}),
makeChildCompletion({
runId: "run-seq-2",
childSessionKey: "agent:main:subagent:parent-sequential:subagent:2",
requesterSessionKey: "agent:main:subagent:parent-sequential",
task: "step two",
createdAt: 20,
frozenResultText: "result two",
}),
makeChildCompletion({
runId: "run-seq-3",
childSessionKey: "agent:main:subagent:parent-sequential:subagent:3",
requesterSessionKey: "agent:main:subagent:parent-sequential",
task: "step three",
createdAt: 30,
frozenResultText: "result three",
}),
]
: [],
);
const didAnnounce = await runSubagentAnnounceFlow({
childSessionKey: "agent:main:subagent:parent-sequential",
childRunId: "run-parent-sequential",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
});
expect(didAnnounce).toBe(true);
const call = agentSpy.mock.calls[0]?.[0] as { params?: { message?: string } };
const message = call?.params?.message ?? "";
const firstIndex = message.indexOf("result one");
const secondIndex = message.indexOf("result two");
const thirdIndex = message.indexOf("result three");
expect(firstIndex).toBeGreaterThanOrEqual(0);
expect(secondIndex).toBeGreaterThan(firstIndex);
expect(thirdIndex).toBeGreaterThan(secondIndex);
});
it("regression child error handling, parent announce includes child error status and preserved child output", async () => {
// Regression guard: failed child outcomes must still surface through parent completion synthesis.
subagentRegistryMock.countPendingDescendantRuns.mockReturnValue(0);
subagentRegistryMock.listSubagentRunsForRequester.mockImplementation((sessionKey: string) =>
sessionKey === "agent:main:subagent:parent-error"
? [
makeChildCompletion({
runId: "run-child-error",
childSessionKey: "agent:main:subagent:parent-error:subagent:child-error",
requesterSessionKey: "agent:main:subagent:parent-error",
task: "error child",
createdAt: 10,
frozenResultText: "traceback: child exploded",
outcome: { status: "error", error: "child exploded" },
}),
]
: [],
);
const didAnnounce = await runSubagentAnnounceFlow({
childSessionKey: "agent:main:subagent:parent-error",
childRunId: "run-parent-error",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
});
expect(didAnnounce).toBe(true);
const call = agentSpy.mock.calls[0]?.[0] as { params?: { message?: string } };
const message = call?.params?.message ?? "";
expect(message).toContain("status: error: child exploded");
expect(message).toContain("traceback: child exploded");
});
it("regression descendant count gating, announce defers at pending > 0 then fires at pending = 0", async () => {
// Regression guard: completion gating depends on countPendingDescendantRuns and must remain deterministic.
let pending = 2;
subagentRegistryMock.countPendingDescendantRuns.mockImplementation((sessionKey: string) =>
sessionKey === "agent:main:subagent:parent-gated" ? pending : 0,
);
subagentRegistryMock.listSubagentRunsForRequester.mockImplementation((sessionKey: string) =>
sessionKey === "agent:main:subagent:parent-gated"
? [
makeChildCompletion({
runId: "run-gated-child",
childSessionKey: "agent:main:subagent:parent-gated:subagent:child",
requesterSessionKey: "agent:main:subagent:parent-gated",
task: "gated child",
createdAt: 10,
frozenResultText: "gated child output",
}),
]
: [],
);
const first = await runSubagentAnnounceFlow({
childSessionKey: "agent:main:subagent:parent-gated",
childRunId: "run-parent-gated",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
});
expect(first).toBe(false);
expect(agentSpy).not.toHaveBeenCalled();
pending = 0;
const second = await runSubagentAnnounceFlow({
childSessionKey: "agent:main:subagent:parent-gated",
childRunId: "run-parent-gated",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
});
expect(second).toBe(true);
expect(subagentRegistryMock.countPendingDescendantRuns).toHaveBeenCalledWith(
"agent:main:subagent:parent-gated",
);
expect(agentSpy).toHaveBeenCalledTimes(1);
});
it("regression deep 3-level re-check chain, child announce then parent re-check emits synthesized parent output", async () => {
// Regression guard: child completion must unblock parent announce on deterministic re-check.
const parentSessionKey = "agent:main:subagent:parent-recheck";
const childSessionKey = `${parentSessionKey}:subagent:child`;
let parentPending = 1;
subagentRegistryMock.countPendingDescendantRuns.mockImplementation((sessionKey: string) => {
if (sessionKey === parentSessionKey) {
return parentPending;
}
return 0;
});
subagentRegistryMock.listSubagentRunsForRequester.mockImplementation((sessionKey: string) => {
if (sessionKey === childSessionKey) {
return [
makeChildCompletion({
runId: "run-grandchild",
childSessionKey: `${childSessionKey}:subagent:grandchild`,
requesterSessionKey: childSessionKey,
task: "grandchild task",
createdAt: 10,
frozenResultText: "grandchild settled output",
}),
];
}
if (sessionKey === parentSessionKey && parentPending === 0) {
return [
makeChildCompletion({
runId: "run-child",
childSessionKey,
requesterSessionKey: parentSessionKey,
task: "child task",
createdAt: 20,
frozenResultText: "child synthesized from grandchild",
}),
];
}
return [];
});
const parentDeferred = await runSubagentAnnounceFlow({
childSessionKey: parentSessionKey,
childRunId: "run-parent-recheck",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
});
expect(parentDeferred).toBe(false);
const childAnnounced = await runSubagentAnnounceFlow({
childSessionKey,
childRunId: "run-child-recheck",
requesterSessionKey: parentSessionKey,
requesterDisplayKey: parentSessionKey,
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
});
expect(childAnnounced).toBe(true);
parentPending = 0;
const parentAnnounced = await runSubagentAnnounceFlow({
childSessionKey: parentSessionKey,
childRunId: "run-parent-recheck",
requesterSessionKey: "agent:main:main",
requesterDisplayKey: "main",
...defaultOutcomeAnnounce,
expectsCompletionMessage: true,
});
expect(parentAnnounced).toBe(true);
expect(agentSpy).toHaveBeenCalledTimes(2);
const childCall = agentSpy.mock.calls[0]?.[0] as { params?: { message?: string } };
expect(childCall?.params?.message ?? "").toContain("grandchild settled output");
const parentCall = agentSpy.mock.calls[1]?.[0] as { params?: { message?: string } };
expect(parentCall?.params?.message ?? "").toContain("child synthesized from grandchild");
});
});
});

View File

@@ -0,0 +1,183 @@
import { describe, expect, it } from "vitest";
import {
countPendingDescendantRunsExcludingRunFromRuns,
countPendingDescendantRunsFromRuns,
shouldIgnorePostCompletionAnnounceForSessionFromRuns,
} from "./subagent-registry-queries.js";
import type { SubagentRunRecord } from "./subagent-registry.types.js";
function makeRun(overrides: Partial<SubagentRunRecord>): SubagentRunRecord {
const runId = overrides.runId ?? "run-default";
const childSessionKey = overrides.childSessionKey ?? `agent:main:subagent:${runId}`;
const requesterSessionKey = overrides.requesterSessionKey ?? "agent:main:main";
return {
runId,
childSessionKey,
requesterSessionKey,
requesterDisplayKey: requesterSessionKey,
task: "test task",
cleanup: "keep",
createdAt: overrides.createdAt ?? 1,
...overrides,
};
}
function toRunMap(runs: SubagentRunRecord[]): Map<string, SubagentRunRecord> {
return new Map(runs.map((run) => [run.runId, run]));
}
describe("subagent registry query regressions", () => {
it("regression descendant count gating, pending descendants block announce until cleanup completion is recorded", () => {
// Regression guard: parent announce must defer while any descendant cleanup is still pending.
const parentSessionKey = "agent:main:subagent:parent";
const runs = toRunMap([
makeRun({
runId: "run-parent",
childSessionKey: parentSessionKey,
requesterSessionKey: "agent:main:main",
endedAt: 100,
cleanupCompletedAt: undefined,
}),
makeRun({
runId: "run-child-fast",
childSessionKey: `${parentSessionKey}:subagent:fast`,
requesterSessionKey: parentSessionKey,
endedAt: 110,
cleanupCompletedAt: 120,
}),
makeRun({
runId: "run-child-slow",
childSessionKey: `${parentSessionKey}:subagent:slow`,
requesterSessionKey: parentSessionKey,
endedAt: 115,
cleanupCompletedAt: undefined,
}),
]);
expect(countPendingDescendantRunsFromRuns(runs, parentSessionKey)).toBe(1);
runs.set(
"run-parent",
makeRun({
runId: "run-parent",
childSessionKey: parentSessionKey,
requesterSessionKey: "agent:main:main",
endedAt: 100,
cleanupCompletedAt: 130,
}),
);
runs.set(
"run-child-slow",
makeRun({
runId: "run-child-slow",
childSessionKey: `${parentSessionKey}:subagent:slow`,
requesterSessionKey: parentSessionKey,
endedAt: 115,
cleanupCompletedAt: 131,
}),
);
expect(countPendingDescendantRunsFromRuns(runs, parentSessionKey)).toBe(0);
});
it("regression nested parallel counting, traversal includes child and grandchildren pending states", () => {
// Regression guard: nested fan-out once under-counted grandchildren and announced too early.
const parentSessionKey = "agent:main:subagent:parent-nested";
const middleSessionKey = `${parentSessionKey}:subagent:middle`;
const runs = toRunMap([
makeRun({
runId: "run-middle",
childSessionKey: middleSessionKey,
requesterSessionKey: parentSessionKey,
endedAt: 200,
cleanupCompletedAt: undefined,
}),
makeRun({
runId: "run-middle-a",
childSessionKey: `${middleSessionKey}:subagent:a`,
requesterSessionKey: middleSessionKey,
endedAt: 210,
cleanupCompletedAt: 215,
}),
makeRun({
runId: "run-middle-b",
childSessionKey: `${middleSessionKey}:subagent:b`,
requesterSessionKey: middleSessionKey,
endedAt: 211,
cleanupCompletedAt: undefined,
}),
]);
expect(countPendingDescendantRunsFromRuns(runs, parentSessionKey)).toBe(2);
expect(countPendingDescendantRunsFromRuns(runs, middleSessionKey)).toBe(1);
});
it("regression excluding current run, countPendingDescendantRunsExcludingRun keeps sibling gating intact", () => {
// Regression guard: excluding the currently announcing run must not hide sibling pending work.
const runs = toRunMap([
makeRun({
runId: "run-self",
childSessionKey: "agent:main:subagent:self",
requesterSessionKey: "agent:main:main",
endedAt: 100,
cleanupCompletedAt: undefined,
}),
makeRun({
runId: "run-sibling",
childSessionKey: "agent:main:subagent:sibling",
requesterSessionKey: "agent:main:main",
endedAt: 101,
cleanupCompletedAt: undefined,
}),
]);
expect(
countPendingDescendantRunsExcludingRunFromRuns(runs, "agent:main:main", "run-self"),
).toBe(1);
expect(
countPendingDescendantRunsExcludingRunFromRuns(runs, "agent:main:main", "run-sibling"),
).toBe(1);
});
it("regression post-completion gating, run-mode sessions ignore late announces once the latest run is ended", () => {
// Regression guard: late descendant announces must not reopen completed run-mode sessions.
const childSessionKey = "agent:main:subagent:orchestrator";
const runs = toRunMap([
makeRun({
runId: "run-older",
childSessionKey,
requesterSessionKey: "agent:main:main",
createdAt: 1,
endedAt: 10,
spawnMode: "run",
}),
makeRun({
runId: "run-latest",
childSessionKey,
requesterSessionKey: "agent:main:main",
createdAt: 2,
endedAt: 20,
spawnMode: "run",
}),
]);
expect(shouldIgnorePostCompletionAnnounceForSessionFromRuns(runs, childSessionKey)).toBe(true);
});
it("regression post-completion gating, session-mode sessions keep accepting follow-up announces", () => {
// Regression guard: persistent session-mode orchestrators must continue receiving child completions.
const childSessionKey = "agent:main:subagent:orchestrator-session";
const runs = toRunMap([
makeRun({
runId: "run-session",
childSessionKey,
requesterSessionKey: "agent:main:main",
createdAt: 3,
endedAt: 30,
spawnMode: "session",
}),
]);
expect(shouldIgnorePostCompletionAnnounceForSessionFromRuns(runs, childSessionKey)).toBe(false);
});
});

View File

@@ -163,6 +163,7 @@ describe("subagent registry lifecycle error grace", () => {
});
it("freezes completion result at run termination across deferred announce retries", async () => {
// Regression guard: late lifecycle noise must never overwrite the frozen completion reply.
registerCompletionRun("run-freeze", "freeze", "freeze test");
captureCompletionReplySpy.mockResolvedValueOnce("Final answer X");
announceSpy.mockResolvedValueOnce(false).mockResolvedValueOnce(true);
@@ -193,6 +194,7 @@ describe("subagent registry lifecycle error grace", () => {
});
it("keeps parallel child completion results frozen even when late traffic arrives", async () => {
// Regression guard: fan-out retries must preserve each child's first frozen result text.
registerCompletionRun("run-parallel-a", "parallel-a", "parallel a");
registerCompletionRun("run-parallel-b", "parallel-b", "parallel b");
captureCompletionReplySpy