fix: store checkpoint as success commit hash and show cumulative metrics
- Swap commitGitSuccess/getGitCommitHash order so checkpoint in session.json points to the success commit (which contains deliverables) instead of the pre-agent marker commit - Simplify restoreGitCheckpoint: git reset --hard now naturally preserves completed agent deliverables, removing the in-memory backup/restore - Show cumulative cost/duration in workflow.log from session.json - Fill in per-agent metrics for skipped agents in workflow.log breakdown - Display cumulative cost in client output for resume runs
This commit is contained in:
@@ -246,7 +246,8 @@ async function runAgentActivity(
|
||||
throw new Error(`Agent ${agentName} failed output validation`);
|
||||
}
|
||||
|
||||
// 9. Success - commit and log
|
||||
// 9. Success - commit deliverables, then capture checkpoint hash
|
||||
await commitGitSuccess(repoPath, agentName);
|
||||
const commitHash = await getGitCommitHash(repoPath);
|
||||
await auditSession.endAgent(agentName, {
|
||||
attemptNumber,
|
||||
@@ -256,7 +257,6 @@ async function runAgentActivity(
|
||||
model: result.model,
|
||||
...(commitHash && { checkpoint: commitHash }),
|
||||
});
|
||||
await commitGitSuccess(repoPath, agentName);
|
||||
|
||||
// 10. Return metrics
|
||||
return {
|
||||
@@ -606,7 +606,8 @@ export async function restoreGitCheckpoint(
|
||||
): Promise<void> {
|
||||
console.log(chalk.blue(`Restoring git workspace to ${checkpointHash}...`));
|
||||
|
||||
// Git reset to checkpoint
|
||||
// Checkpoint hash points to the success commit (after commitGitSuccess),
|
||||
// so git reset --hard naturally preserves all completed agent deliverables.
|
||||
await executeGitCommandWithRetry(
|
||||
['git', 'reset', '--hard', checkpointHash],
|
||||
repoPath,
|
||||
@@ -618,8 +619,7 @@ export async function restoreGitCheckpoint(
|
||||
'clean untracked files for resume'
|
||||
);
|
||||
|
||||
|
||||
// Explicitly delete deliverables for incomplete agents
|
||||
// Clean up any partial deliverables from incomplete agents
|
||||
for (const agentName of incompleteAgents) {
|
||||
const deliverablePath = getDeliverablePath(agentName, repoPath);
|
||||
try {
|
||||
@@ -629,7 +629,6 @@ export async function restoreGitCheckpoint(
|
||||
await fs.unlink(deliverablePath);
|
||||
}
|
||||
} catch (error) {
|
||||
// Non-fatal, just log
|
||||
console.log(chalk.gray(`Note: Failed to delete ${deliverablePath}: ${error}`));
|
||||
}
|
||||
}
|
||||
@@ -709,7 +708,37 @@ export async function logWorkflowComplete(
|
||||
const auditSession = new AuditSession(sessionMetadata);
|
||||
await auditSession.initialize(workflowId);
|
||||
await auditSession.updateSessionStatus(summary.status);
|
||||
await auditSession.logWorkflowComplete(summary);
|
||||
|
||||
// Use cumulative metrics from session.json (includes all resume attempts)
|
||||
const sessionData = await auditSession.getMetrics() as {
|
||||
metrics: {
|
||||
total_duration_ms: number;
|
||||
total_cost_usd: number;
|
||||
agents: Record<string, { final_duration_ms: number; total_cost_usd: number }>;
|
||||
};
|
||||
};
|
||||
|
||||
// Fill in metrics for skipped agents (completed in previous runs)
|
||||
const agentMetrics = { ...summary.agentMetrics };
|
||||
for (const agentName of summary.completedAgents) {
|
||||
if (!agentMetrics[agentName]) {
|
||||
const agentData = sessionData.metrics.agents[agentName];
|
||||
if (agentData) {
|
||||
agentMetrics[agentName] = {
|
||||
durationMs: agentData.final_duration_ms,
|
||||
costUsd: agentData.total_cost_usd,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const cumulativeSummary: WorkflowSummary = {
|
||||
...summary,
|
||||
totalDurationMs: sessionData.metrics.total_duration_ms,
|
||||
totalCostUsd: sessionData.metrics.total_cost_usd,
|
||||
agentMetrics,
|
||||
};
|
||||
await auditSession.logWorkflowComplete(cumulativeSummary);
|
||||
|
||||
// Copy all deliverables to audit-logs once at workflow end (non-fatal)
|
||||
try {
|
||||
|
||||
+16
-1
@@ -46,6 +46,9 @@ interface SessionJson {
|
||||
originalWorkflowId?: string;
|
||||
resumeAttempts?: Array<{ workflowId: string }>;
|
||||
};
|
||||
metrics: {
|
||||
total_cost_usd: number;
|
||||
};
|
||||
}
|
||||
|
||||
dotenv.config();
|
||||
@@ -356,7 +359,19 @@ async function startPipeline(): Promise<void> {
|
||||
console.log(chalk.gray(`Duration: ${Math.floor(result.summary.totalDurationMs / 1000)}s`));
|
||||
console.log(chalk.gray(`Agents completed: ${result.summary.agentCount}`));
|
||||
console.log(chalk.gray(`Total turns: ${result.summary.totalTurns}`));
|
||||
console.log(chalk.gray(`Total cost: $${result.summary.totalCostUsd.toFixed(4)}`));
|
||||
console.log(chalk.gray(`Run cost: $${result.summary.totalCostUsd.toFixed(4)}`));
|
||||
|
||||
// Show cumulative cost from session.json (includes all resume attempts)
|
||||
if (isResume) {
|
||||
try {
|
||||
const session = await readJson<SessionJson>(
|
||||
path.join('./audit-logs', sessionId, 'session.json')
|
||||
);
|
||||
console.log(chalk.gray(`Cumulative cost: $${session.metrics.total_cost_usd.toFixed(4)}`));
|
||||
} catch {
|
||||
// Non-fatal, skip cumulative cost display
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
clearInterval(progressInterval);
|
||||
|
||||
Reference in New Issue
Block a user