fix(merger): truncate verification output and retry via in-progress

Deterministic verification failures were embedding the raw stderr/stdout
(up to 50MB per VERIFICATION_COMMAND_MAX_BUFFER) in a second log entry,
flooding logs/stdout and crashing the app. The runVerificationCommand
helper already wrote a truncated summary, so verifyDeterministicBuild
now just references it.

When the failure surfaces in the dashboard merge handler, kick the task
back to in-progress with a steering comment so the agent can fix the
failing test/build instead of parking it in in-review with a fatal
error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-11 06:56:18 -07:00
parent 302394b5f5
commit 6dd66f6a31
2 changed files with 33 additions and 2 deletions

View File

@@ -479,6 +479,37 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
const task = await store.getTask(taskId).catch(() => null);
const mergeStrategy = getMergeStrategy(settings);
// Deterministic verification failure: kick the task back to
// "in-progress" so the executor rebuilds it. Parking it in
// "in-review" with a fatal error would require manual
// intervention, but the failing test/build is exactly the kind
// of issue the agent can fix on its own if given another turn.
const isVerificationError = err?.name === "VerificationError"
|| errorMsg.includes("Deterministic test verification failed")
|| errorMsg.includes("Deterministic build verification failed");
if (task && isVerificationError) {
const failedKind = errorMsg.includes("build verification") ? "build" : "test";
try {
await store.addTaskComment(
taskId,
`Deterministic ${failedKind} verification failed during merge. `
+ `See the prior [verification] log entry for the truncated command output. `
+ `Please fix the failing ${failedKind} and push the update so the merge can retry.`,
"agent",
);
await store.updateTask(taskId, { status: null, mergeRetries: 0, error: null });
await store.moveTask(taskId, "in-progress");
await store.logEntry(
taskId,
`Deterministic ${failedKind} verification failed — moved back to in-progress for remediation`,
);
console.log(`[auto-merge] ↩ ${taskId}: deterministic ${failedKind} verification failed — moved to in-progress`);
} catch (moveErr) {
console.log(`[auto-merge] failed to return ${taskId} to in-progress after verification failure:`, moveErr);
}
continue;
}
if (mergeStrategy === "direct") {
// Check if this is a conflict error and if we should retry
const isConflictError = errorMsg.includes("conflict") || errorMsg.includes("Conflict");

View File

@@ -254,7 +254,7 @@ async function runDeterministicVerification(
result.failedCommand = "testCommand";
await store.logEntry(
taskId,
`Deterministic test verification failed (exit ${testResult.exitCode}): ${testResult.stderr || testResult.stdout}`.trim(),
`Deterministic test verification failed (exit ${testResult.exitCode}) — see prior [verification] entry for truncated output`,
"VerificationError",
);
throw new VerificationError(
@@ -276,7 +276,7 @@ async function runDeterministicVerification(
result.failedCommand = "buildCommand";
await store.logEntry(
taskId,
`Deterministic build verification failed (exit ${buildResult.exitCode}): ${buildResult.stderr || buildResult.stdout}`.trim(),
`Deterministic build verification failed (exit ${buildResult.exitCode}) — see prior [verification] entry for truncated output`,
"VerificationError",
);
throw new VerificationError(