Skip to content

Commit d29a499

Browse files
committed
fix(server): exclude failed supervisor evaluations from cycle totals
1 parent 83df987 commit d29a499

2 files changed

Lines changed: 95 additions & 2 deletions

File tree

packages/server/src/supervisor/target-store.test.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,41 @@ describe("target store", () => {
380380
]);
381381
});
382382

383+
it("does not count failed evaluation records in recoverable target cycle totals", async () => {
384+
await createTargetFiles(workspacePath, {
385+
targetId: "tgt-1",
386+
sessionId: "sess-1",
387+
workspaceId: "ws-1",
388+
objective: "Recover this target",
389+
createdAt: 1,
390+
});
391+
392+
await appendTargetCycleRecord(workspacePath, "tgt-1", {
393+
cycleId: "cycle-1",
394+
targetId: "tgt-1",
395+
startedAt: 1,
396+
completedAt: 2,
397+
result: "continue",
398+
reason: "Needs more work",
399+
guidance: "Continue",
400+
injected: true,
401+
attemptCount: 1,
402+
});
403+
await appendTargetCycleRecord(workspacePath, "tgt-1", {
404+
cycleId: "cycle-2",
405+
targetId: "tgt-1",
406+
startedAt: 3,
407+
completedAt: 4,
408+
result: "error",
409+
errorReason: "Evaluator exploded",
410+
attemptCount: 1,
411+
});
412+
413+
const targets = await listRecoverableTargets(workspacePath);
414+
415+
expect(targets[0]?.cycleCount).toBe(1);
416+
});
417+
383418
it("clones a target into a new target id and rewrites persisted identifiers", async () => {
384419
await createTargetFiles(workspacePath, {
385420
targetId: "tgt-old",
@@ -514,6 +549,60 @@ describe("target store", () => {
514549
]);
515550
});
516551

552+
it("returns only non-error cycle records when cloning target files", async () => {
553+
await createTargetFiles(workspacePath, {
554+
targetId: "tgt-old",
555+
sessionId: "sess-old",
556+
workspaceId: "ws-1",
557+
objective: "Old objective",
558+
createdAt: 10,
559+
});
560+
561+
await appendTargetCycleRecord(workspacePath, "tgt-old", {
562+
cycleId: "cycle-1",
563+
targetId: "tgt-old",
564+
startedAt: 10,
565+
completedAt: 11,
566+
result: "continue",
567+
reason: "Keep copying",
568+
guidance: "Copy state",
569+
injected: true,
570+
attemptCount: 1,
571+
});
572+
await appendTargetCycleRecord(workspacePath, "tgt-old", {
573+
cycleId: "cycle-2",
574+
targetId: "tgt-old",
575+
startedAt: 12,
576+
completedAt: 13,
577+
result: "error",
578+
errorReason: "Evaluator exploded",
579+
attemptCount: 1,
580+
});
581+
582+
const cycleCount = await cloneTargetFiles(workspacePath, {
583+
sourceTargetId: "tgt-old",
584+
targetId: "tgt-new",
585+
sessionId: "sess-new",
586+
workspaceId: "ws-2",
587+
objective: "New objective",
588+
createdAt: 20,
589+
});
590+
591+
expect(cycleCount).toBe(1);
592+
expect(await readTargetCycleRecords(workspacePath, "tgt-new")).toEqual([
593+
expect.objectContaining({
594+
cycleId: "cycle-2",
595+
result: "error",
596+
targetId: "tgt-new",
597+
}),
598+
expect.objectContaining({
599+
cycleId: "cycle-1",
600+
result: "continue",
601+
targetId: "tgt-new",
602+
}),
603+
]);
604+
});
605+
517606
it("deletes the source target after a successful restore", async () => {
518607
await createTargetFiles(workspacePath, {
519608
targetId: "tgt-delete",

packages/server/src/supervisor/target-store.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,10 @@ function buildTargetMemory(targetId: string, createdAt: number): SupervisorTarge
413413
};
414414
}
415415

416+
function countsTowardCycleTotal(record: SupervisorCycleTargetRecord): boolean {
417+
return record.result !== "error";
418+
}
419+
416420
async function writeResetTargetFiles(
417421
dirPath: string,
418422
input: {
@@ -620,7 +624,7 @@ export async function listRecoverableTargets(
620624
status: meta.status,
621625
updatedAt: meta.updatedAt,
622626
progressSummary: memory.progressSummary,
623-
cycleCount: cycles.length,
627+
cycleCount: cycles.filter(countsTowardCycleTotal).length,
624628
} satisfies RecoverableTargetSummary;
625629
})
626630
);
@@ -673,7 +677,7 @@ export async function cloneTargetFiles(
673677
await appendTargetCycleRecord(workspacePath, input.targetId, cycle);
674678
}
675679

676-
return nextCycles.length;
680+
return nextCycles.filter(countsTowardCycleTotal).length;
677681
}
678682

679683
export async function deleteTarget(workspacePath: string, targetId: string): Promise<void> {

0 commit comments

Comments
 (0)