diff --git a/src/temporal/activities.ts b/src/temporal/activities.ts index 454701b..6f76244 100644 --- a/src/temporal/activities.ts +++ b/src/temporal/activities.ts @@ -544,8 +544,17 @@ export async function loadResumeState( .filter((hash): hash is string => hash != null); if (checkpoints.length === 0) { + const successAgents = Object.entries(agents) + .filter(([, data]) => data.status === 'success') + .map(([name]) => name); + throw ApplicationFailure.nonRetryable( - `No successful agent checkpoints found in workspace ${workspaceName}`, + `Cannot resume workspace ${workspaceName}: ` + + (successAgents.length > 0 + ? `${successAgents.length} agent(s) show success in session.json (${successAgents.join(', ')}) ` + + `but their deliverable files are missing from disk. ` + + `Start a fresh run instead.` + : `No agents completed successfully. Start a fresh run instead.`), 'NoCheckpointsError' ); } diff --git a/src/temporal/workflows.ts b/src/temporal/workflows.ts index bed783e..3bc2804 100644 --- a/src/temporal/workflows.ts +++ b/src/temporal/workflows.ts @@ -167,6 +167,15 @@ export async function pentestPipelineWorkflow( incompleteAgents ); + // Check if all agents are already complete + if (resumeState.completedAgents.length === ALL_AGENTS.length) { + console.log(`All ${ALL_AGENTS.length} agents already completed. Nothing to resume.`); + state.status = 'completed'; + state.completedAgents = [...resumeState.completedAgents]; + state.summary = computeSummary(state); + return state; + } + // Record resume attempt in session.json await a.recordResumeAttempt( activityInput,