@@ -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" ,
0 commit comments