From 9f6f1cfc793ab40dc9c112bea71346f576622540 Mon Sep 17 00:00:00 2001 From: Fusion Date: Thu, 14 May 2026 20:30:20 -0700 Subject: [PATCH] fix(FN-4545): wire contamination handler into auto-recovery dispatcher Fusion-Task-Id: FN-4545 Fusion-Task-Lineage: 95108429-618e-4a6d-9fa9-7ac2596665a2 --- .../engine/src/auto-recovery-handlers/contamination.ts | 1 - packages/engine/src/executor.ts | 10 ++++++++++ packages/engine/src/run-audit.ts | 4 ++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/engine/src/auto-recovery-handlers/contamination.ts b/packages/engine/src/auto-recovery-handlers/contamination.ts index 366db74fc..58f386b62 100644 --- a/packages/engine/src/auto-recovery-handlers/contamination.ts +++ b/packages/engine/src/auto-recovery-handlers/contamination.ts @@ -20,7 +20,6 @@ export class ContaminationAutoRecoveryHandler implements Pick { - void this.deps.repoDir; const task = ctx.task; if (task.userPaused) { this.logger.warn(`auto-recovery: skipped (userPaused) class=${failure.class} task=${task.id}`); diff --git a/packages/engine/src/executor.ts b/packages/engine/src/executor.ts index c5460bd21..f3af8c685 100644 --- a/packages/engine/src/executor.ts +++ b/packages/engine/src/executor.ts @@ -73,6 +73,7 @@ import type { AgentReflectionService } from "./agent-reflection.js"; import { createRunAuditor, generateSyntheticRunId, type EngineRunContext, type RunAuditor } from "./run-audit.js"; import { AutoRecoveryDispatcher } from "./auto-recovery.js"; import { BranchWorktreeAutoRecoveryHandler } from "./auto-recovery-handlers/branch-worktree.js"; +import { ContaminationAutoRecoveryHandler } from "./auto-recovery-handlers/contamination.js"; import { createFileScopeAutoRecoveryHandler } from "./auto-recovery-handlers/file-scope.js"; import { ReadonlyViolationError, filterCustomToolsForReadonly } from "./workflow-step-tool-policy.js"; import { evaluateSpecStaleness, getPromptPath } from "./spec-staleness.js"; @@ -848,11 +849,20 @@ export class TaskExecutor { runAudit: audit, logger: executorLog, }); + const contaminationHandler = new ContaminationAutoRecoveryHandler({ + taskStore: this.store, + runAudit: audit, + logger: executorLog, + repoDir: this.rootDir, + }); return new AutoRecoveryDispatcher({ taskStore: this.store, auditEmitter: audit, handlers: { issueRetry: async (failure, decision, ctx) => { + if (failure.class === "branch-cross-contamination") { + return contaminationHandler.issueRetry(failure, decision, ctx); + } if (failure.class === "branch-conflict-unrecoverable") { return branchWorktreeHandler.issueRetry(failure, decision, ctx); } diff --git a/packages/engine/src/run-audit.ts b/packages/engine/src/run-audit.ts index 16a1d4d30..079bf6e3b 100644 --- a/packages/engine/src/run-audit.ts +++ b/packages/engine/src/run-audit.ts @@ -105,6 +105,10 @@ export type DatabaseMutationType = | "auto-recovery:retry-issued" | "auto-recovery:ai-session-spawned" | "auto-recovery:pause-because-destructive-ambiguity" + | "contamination:retry-issued" + | "contamination:irreducible-pause" + | "message-delivery:retry-issued" + | "message-delivery:park" | "branch-worktree:auto-requeue" | "branch-worktree:ai-session-spawned" | "branch-worktree:irreducible-pause"