feat(FN-3815): quiet stderr logging for clean-exit MCP processes in pi-clau

Adds a changeset for FN-3815. The core change reclassifies clean-exit stderr output in the pi-claude-cli provider to reduce noisy logging, with corresponding test coverage distinguishing between clean and non-zero exit stderr handling.

Fusion-Task-Id: FN-3815
This commit is contained in:
Fusion
2026-05-11 01:18:33 -07:00
committed by gsxdsm
parent a59c84753d
commit a51e7791a5
3 changed files with 45 additions and 18 deletions

View File

@@ -1188,28 +1188,42 @@ describe("streamViaCli", { timeout: 90_000 }, () => {
expect(doneEvent.message.content).toBeDefined();
});
it("logs stderr at warn level on close even with exit code 0", async () => {
const model = mockModels[0] as any;
const context = {
messages: [{ role: "user", content: "Hello" }],
};
it.each([
{ code: 0, shouldWarn: false },
{ code: 42, shouldWarn: true },
])(
"FN-3815: routes close stderr logging by exit code=$code",
async ({ code, shouldWarn }) => {
const model = mockModels[0] as any;
const context = {
messages: [{ role: "user", content: "Hello" }],
};
const warnSpy = vi.spyOn(console, "warn");
const warnSpy = vi.spyOn(console, "warn");
streamViaCli(model, context);
await vi.advanceTimersByTimeAsync(0);
streamViaCli(model, context);
await vi.advanceTimersByTimeAsync(0);
const proc = (spawn as any).mock.results[0].value;
const proc = (spawn as any).mock.results[0].value;
proc.stderr.emit("data", Buffer.from("minor warning from cli"));
proc.emit("close", 0, null);
proc.stdout.end();
await vi.advanceTimersByTimeAsync(100);
proc.stderr.emit("data", Buffer.from("minor warning from cli"));
proc.emit("close", code, null);
proc.stdout.end();
await vi.advanceTimersByTimeAsync(100);
expect(warnSpy).toHaveBeenCalledWith(
expect.stringContaining("minor warning from cli"),
);
});
const stderrWarnCalls = warnSpy.mock.calls.filter(([message]) =>
typeof message === "string" &&
message.includes("[pi-claude-cli] Claude CLI stderr on close:"),
);
if (shouldWarn) {
expect(stderrWarnCalls).toHaveLength(1);
expect(stderrWarnCalls[0]?.[0]).toContain("minor warning from cli");
} else {
expect(stderrWarnCalls).toHaveLength(0);
}
},
);
it("warns when subprocess closes successfully with no content events", async () => {
const model = mockModels[0] as any;