From 55e2e8636ab6776f0550919fd3362c8b971153a5 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Sat, 12 Sep 2026 13:23:46 -0700 Subject: [PATCH] Reset the tool-less narration count on tool-using turns --- src/subagent/nudge-director.test.ts | 29 +++++++++++++++++++++++++++++ src/subagent/nudge-director.ts | 1 + 2 files changed, 30 insertions(+) diff --git a/src/subagent/nudge-director.test.ts b/src/subagent/nudge-director.test.ts index 27647b516..78b2b1ff3 100644 --- a/src/subagent/nudge-director.test.ts +++ b/src/subagent/nudge-director.test.ts @@ -794,6 +794,35 @@ describe("SubAgentDirector incomplete-report wiring", () => { expect(reply.content).toContain("read-1.ts"); }); + test("tool-using turns reset the tool-less narration count (CL-7788)", async () => { + const director = new SubAgentDirector("system", [], undefined, 30); + const caps = capabilities(); + + await director.decide( + inferenceDoneText("Still looking at the files..."), + state, + caps, + ); + await director.decide(inferenceDone(["read-1"]), state, caps); + await director.decide(toolDone("read-1"), state, caps); + await director.decide(inferenceDone(["read-2"]), state, caps); + await director.decide(toolDone("read-2"), state, caps); + + const result = actions( + await director.decide( + inferenceDoneText("Still narrating, no envelope."), + state, + caps, + ), + ); + expect(result).toContainEqual({ + type: "checkpoint", + message: "subagent-incomplete-report-nudge", + }); + expect(result.some((action) => action.type === "reply")).toBe(false); + expect(result.some((action) => action.type === "infer")).toBe(true); + }); + test("tool-less turn with the four headings completes normally", async () => { const director = new SubAgentDirector("system", [], undefined, 30); const caps = capabilities(); diff --git a/src/subagent/nudge-director.ts b/src/subagent/nudge-director.ts index 0a4846354..5dcff3b50 100644 --- a/src/subagent/nudge-director.ts +++ b/src/subagent/nudge-director.ts @@ -330,6 +330,7 @@ export class SubAgentDirector extends DefaultDirector { this.lastAssistantText = lastText(content); const hasToolCalls = content.some((block) => block.type === "tool_call"); if (hasToolCalls) { + this.toolLessNarrationCycles = 0; this.verbatimToolCallNudgeFired = false; this.thrashState = nextThrashState(this.thrashState, content); }