diff --git a/src/headless-triage.ts b/src/headless-triage.ts index 0564120ac..0dce57de7 100644 --- a/src/headless-triage.ts +++ b/src/headless-triage.ts @@ -156,41 +156,49 @@ export async function handleTriage( return { exitCode: 0 }; } - if (options.json) { - process.stdout.write( - `${JSON.stringify({ - ok: true, - count: candidates.length, - candidates: candidates.map((c) => ({ - id: c.id, - kind: c.kind, - severity: c.severity, - summary: c.summary, - ts: c.ts, - impact: c.impactScore ?? null, - effort: c.effortEstimate ?? null, - })), - })}\n`, - ); - return { exitCode: 0 }; - } - - if (options.list) { - process.stdout.write( - `${candidates.length} candidate${candidates.length === 1 ? "" : "s"} (priority: impact↓ effort↑ ts↑)\n\n`, - ); - for (const c of candidates) { - const impact = c.impactScore != null ? `i${c.impactScore}` : "i?"; - const effort = c.effortEstimate != null ? `e${c.effortEstimate}` : "e?"; + // --run takes precedence over --json/--list because they describe the + // OUTPUT FORMAT, not the action. With --run, --json controls whether + // the run-result is JSON vs. human text. Without --run, --json emits + // the candidate digest as JSON (the inspect path). + if (!options.run) { + if (options.json) { process.stdout.write( - ` [${c.severity}] ${impact} ${effort} ${c.id} ${c.kind}\n`, + `${JSON.stringify({ + ok: true, + count: candidates.length, + candidates: candidates.map((c) => ({ + id: c.id, + kind: c.kind, + severity: c.severity, + summary: c.summary, + ts: c.ts, + impact: c.impactScore ?? null, + effort: c.effortEstimate ?? null, + })), + })}\n`, ); - process.stdout.write(` ${c.summary}\n`); + return { exitCode: 0 }; + } + + if (options.list) { + process.stdout.write( + `${candidates.length} candidate${candidates.length === 1 ? "" : "s"} (priority: impact↓ effort↑ ts↑)\n\n`, + ); + for (const c of candidates) { + const impact = c.impactScore != null ? `i${c.impactScore}` : "i?"; + const effort = + c.effortEstimate != null ? `e${c.effortEstimate}` : "e?"; + process.stdout.write( + ` [${c.severity}] ${impact} ${effort} ${c.id} ${c.kind}\n`, + ); + process.stdout.write(` ${c.summary}\n`); + } + return { exitCode: 0 }; } - return { exitCode: 0 }; } - // Default: emit the canonical triage prompt for piping into a model. + // Render the canonical triage prompt (used by both the default + // pipe-to-model output and the --run dispatch path below). let prompt: string; try { prompt = drainModule.buildInlineFixPrompt(candidates);