fix: recover missing Reasonix sessions
This commit is contained in:
+29
-4
@@ -23,7 +23,12 @@ import { execFileSync } from "node:child_process";
|
||||
import { resolveWorkflowConfig, validateHostDecision, validateWorkflowPlan, WorkflowConfigError } from "./workflow-config.js";
|
||||
import { checkConvergence, decisionSignatures } from "./workflow-convergence.js";
|
||||
import type { FindingSignature } from "./workflow-convergence.js";
|
||||
import { createExecutorAdapter, probeExecutor, validateClaudeSessionForWorkflow } from "./workflow-executor.js";
|
||||
import {
|
||||
createExecutorAdapter,
|
||||
findReasonixSessionForWorkflow,
|
||||
probeExecutor,
|
||||
validateClaudeSessionForWorkflow,
|
||||
} from "./workflow-executor.js";
|
||||
import {
|
||||
WorkflowLockError,
|
||||
acquireLock,
|
||||
@@ -1269,7 +1274,8 @@ export async function retryExecuteWorkflow(opts: RetryExecuteWorkflowOpts): Prom
|
||||
const retryableFailure = staleExecution || (state.status === "blocked"
|
||||
&& (state.stopDescription?.startsWith("Executor exited with failure:") === true
|
||||
|| state.stopDescription?.startsWith("Executor failed to resume:") === true
|
||||
|| state.stopDescription?.startsWith("Executor resume failed:") === true));
|
||||
|| state.stopDescription?.startsWith("Executor resume failed:") === true
|
||||
|| state.stopDescription === "No session handle available for resume."));
|
||||
if (!retryableFailure) {
|
||||
throw new WorkflowEngineError(
|
||||
`Run '${opts.runId}' cannot retry execution from status '${state.status}'. Only failed executor runs with a resumable session are eligible.`,
|
||||
@@ -1282,7 +1288,15 @@ export async function retryExecuteWorkflow(opts: RetryExecuteWorkflowOpts): Prom
|
||||
if (!cycle || cycle.diffFile || cycle.hostReviewFile || cycle.decisionFile || cycle.scopeViolations) {
|
||||
throw new WorkflowEngineError("Cannot retry execution: the failed cycle already contains review artifacts.", 4);
|
||||
}
|
||||
if (!state.sessionHandle && !opts.sessionId) {
|
||||
const recoveredReasonixSession = !state.sessionHandle && state.executor === "reasonix"
|
||||
? findReasonixSessionForWorkflow(
|
||||
state.repoRoot,
|
||||
state.plan.title,
|
||||
previousCycle?.startedAt ?? cycle.startedAt,
|
||||
previousCycle?.completedAt,
|
||||
)
|
||||
: undefined;
|
||||
if (!state.sessionHandle && !opts.sessionId && !recoveredReasonixSession) {
|
||||
throw new WorkflowEngineError("Cannot retry execution: no executor session handle is available.", 4);
|
||||
}
|
||||
const recoveringInitialCycle = state.currentCycle === 1;
|
||||
@@ -1365,6 +1379,8 @@ export async function retryExecuteWorkflow(opts: RetryExecuteWorkflowOpts): Prom
|
||||
: undefined;
|
||||
if (opts.sessionId) {
|
||||
state.sessionHandle = { kind: "claude", sessionId: opts.sessionId };
|
||||
} else if (recoveredReasonixSession) {
|
||||
state.sessionHandle = { kind: "reasonix", sessionFilePath: recoveredReasonixSession };
|
||||
}
|
||||
|
||||
state.status = "executing";
|
||||
@@ -1382,6 +1398,14 @@ export async function retryExecuteWorkflow(opts: RetryExecuteWorkflowOpts): Prom
|
||||
cycleIndex: state.currentCycle,
|
||||
data: { previousSessionId, sessionId: opts.sessionId },
|
||||
});
|
||||
} else if (recoveredReasonixSession) {
|
||||
appendEvent(dir, {
|
||||
kind: "executor_session_rebound",
|
||||
runId: state.runId,
|
||||
timestamp: state.updatedAt,
|
||||
cycleIndex: state.currentCycle,
|
||||
data: { sessionFilePath: recoveredReasonixSession, recovery: "reasonix_project_session" },
|
||||
});
|
||||
}
|
||||
|
||||
// Determine recovery mode: stale_execution trumps initial_continuation
|
||||
@@ -1405,7 +1429,8 @@ export async function retryExecuteWorkflow(opts: RetryExecuteWorkflowOpts): Prom
|
||||
},
|
||||
});
|
||||
|
||||
process.stdout.write(`retrying executor cycle ${state.currentCycle} with the ${opts.sessionId ? "rebound" : "existing"} ${state.executor} session\n`);
|
||||
const sessionMode = opts.sessionId || recoveredReasonixSession ? "recovered" : "existing";
|
||||
process.stdout.write(`retrying executor cycle ${state.currentCycle} with the ${sessionMode} ${state.executor} session\n`);
|
||||
await resumeExecutorCycle(state, dir, cycle, acceptedFindings);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user