feat(S-104): Add stderr-length and exit-code correlation diagnostics
This commit is contained in:
@@ -90,15 +90,17 @@ export async function executePrompt(
|
|||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
const durationMs = Date.now() - startMs;
|
const durationMs = Date.now() - startMs;
|
||||||
if (options.debug || options.onDebug) {
|
if (options.debug || options.onDebug) {
|
||||||
|
const effectiveExitCode = result?.exitCode ?? (err instanceof ExecError ? err.result.exitCode : null);
|
||||||
const debugInfo: DebugInfo = {
|
const debugInfo: DebugInfo = {
|
||||||
command,
|
command,
|
||||||
args,
|
args,
|
||||||
pid: child.pid ?? undefined,
|
pid: child.pid ?? undefined,
|
||||||
exitCode: result?.exitCode ?? (err instanceof ExecError ? err.result.exitCode : null),
|
exitCode: effectiveExitCode,
|
||||||
exitSignal,
|
exitSignal,
|
||||||
durationMs,
|
durationMs,
|
||||||
stderrLength: stderr.length,
|
stderrLength: stderr.length,
|
||||||
stdoutLength: stdout.length,
|
stdoutLength: stdout.length,
|
||||||
|
noisySuccess: effectiveExitCode === 0 && stderr.length > 0,
|
||||||
};
|
};
|
||||||
options.onDebug?.(debugInfo);
|
options.onDebug?.(debugInfo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export interface DebugInfo {
|
|||||||
durationMs: number;
|
durationMs: number;
|
||||||
stderrLength: number;
|
stderrLength: number;
|
||||||
stdoutLength: number;
|
stdoutLength: number;
|
||||||
|
noisySuccess: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DispatchConfigFile {
|
export interface DispatchConfigFile {
|
||||||
|
|||||||
@@ -320,4 +320,46 @@ describe("executePrompt", () => {
|
|||||||
assert.strictEqual(debugInfos[0].exitCode, null);
|
assert.strictEqual(debugInfos[0].exitCode, null);
|
||||||
assert.strictEqual(debugInfos[0].exitSignal, null);
|
assert.strictEqual(debugInfos[0].exitSignal, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("reports noisySuccess=true when stderr is non-empty and exitCode is 0", async () => {
|
||||||
|
const scenarios = new Map<string, MockScenario>([
|
||||||
|
["codex exec --yolo hello", { stdout: "ok", stderr: "warn", exitCode: 0 }],
|
||||||
|
]);
|
||||||
|
const debugInfos: any[] = [];
|
||||||
|
await executePrompt("codex", "hello", {
|
||||||
|
spawn: mockSpawn(scenarios),
|
||||||
|
existsSync: () => true,
|
||||||
|
debug: true,
|
||||||
|
onDebug: (info) => debugInfos.push(info),
|
||||||
|
});
|
||||||
|
assert.strictEqual(debugInfos[0].noisySuccess, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reports noisySuccess=false when stderr is empty and exitCode is 0", async () => {
|
||||||
|
const scenarios = new Map<string, MockScenario>([
|
||||||
|
["codex exec --yolo hello", { stdout: "ok", stderr: "", exitCode: 0 }],
|
||||||
|
]);
|
||||||
|
const debugInfos: any[] = [];
|
||||||
|
await executePrompt("codex", "hello", {
|
||||||
|
spawn: mockSpawn(scenarios),
|
||||||
|
existsSync: () => true,
|
||||||
|
debug: true,
|
||||||
|
onDebug: (info) => debugInfos.push(info),
|
||||||
|
});
|
||||||
|
assert.strictEqual(debugInfos[0].noisySuccess, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reports noisySuccess=false when exitCode is non-zero even if stderr is non-empty", async () => {
|
||||||
|
const scenarios = new Map<string, MockScenario>([
|
||||||
|
["codex exec --yolo fail", { stdout: "", stderr: "error", exitCode: 1 }],
|
||||||
|
]);
|
||||||
|
const debugInfos: any[] = [];
|
||||||
|
await executePrompt("codex", "fail", {
|
||||||
|
spawn: mockSpawn(scenarios),
|
||||||
|
existsSync: () => true,
|
||||||
|
debug: true,
|
||||||
|
onDebug: (info) => debugInfos.push(info),
|
||||||
|
});
|
||||||
|
assert.strictEqual(debugInfos[0].noisySuccess, false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user