@@ -299,66 +299,16 @@ func TestAttach_OutputContainsCheckpointID(t *testing.T) {
299299 }
300300}
301301
302- func TestAttach_V2DualWriteEnabled (t * testing.T ) {
303- setupAttachTestRepo (t )
304-
305- repoDir := mustGetwd (t )
306- setAttachCheckpointsV2Enabled (t , repoDir )
307-
308- sessionID := "test-attach-v2-dual-write"
309- setupClaudeTranscript (t , sessionID , `{"type":"user","message":{"role":"user","content":"create hello.txt"},"uuid":"uuid-1"}
310- {"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","id":"tu_1","name":"Write","input":{"file_path":"hello.txt","content":"hello"}}]},"uuid":"uuid-2"}
311- {"type":"user","message":{"content":[{"type":"tool_result","tool_use_id":"tu_1","content":"wrote file"}]},"uuid":"uuid-3"}
312- {"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"Done."}]},"uuid":"uuid-4"}
313- ` )
314-
315- var out bytes.Buffer
316- if err := runAttach (context .Background (), & out , sessionID , agent .AgentNameClaudeCode , attachOptions {Force : true }); err != nil {
317- t .Fatalf ("runAttach failed: %v" , err )
318- }
319-
320- store , err := session .NewStateStore (context .Background ())
321- if err != nil {
322- t .Fatal (err )
323- }
324- state , err := store .Load (context .Background (), sessionID )
325- if err != nil {
326- t .Fatal (err )
327- }
328- if state == nil || state .LastCheckpointID .IsEmpty () {
329- t .Fatal ("expected attach to persist a checkpoint ID" )
330- }
331-
332- repo , err := git .PlainOpen (repoDir )
333- if err != nil {
334- t .Fatal (err )
335- }
336-
337- cpPath := state .LastCheckpointID .Path ()
338- mainCompact , found := readFileFromRef (t , repo , paths .V2MainRefName , cpPath + "/0/" + paths .CompactTranscriptFileName )
339- if ! found {
340- t .Fatalf ("expected %s on %s" , paths .CompactTranscriptFileName , paths .V2MainRefName )
341- }
342- if ! strings .Contains (mainCompact , "create hello.txt" ) {
343- t .Errorf ("compact transcript missing prompt, got:\n %s" , mainCompact )
344- }
345-
346- fullTranscript , found := readFileFromRef (t , repo , paths .V2FullCurrentRefName , cpPath + "/0/" + paths .V2RawTranscriptFileName )
347- if ! found {
348- t .Fatalf ("expected %s on %s" , paths .V2RawTranscriptFileName , paths .V2FullCurrentRefName )
349- }
350- if ! strings .Contains (fullTranscript , "hello.txt" ) {
351- t .Errorf ("raw transcript missing file content, got:\n %s" , fullTranscript )
352- }
353- }
354-
355- func TestAttach_CheckpointsVersion2 (t * testing.T ) {
302+ // TestAttach_CheckpointsVersion2_FallsBackToV1 verifies that
303+ // strategy_options.checkpoints_version: 2 is now ignored — attach writes
304+ // v1 metadata only, and never creates v2 refs solely because of the setting.
305+ func TestAttach_CheckpointsVersion2_FallsBackToV1 (t * testing.T ) {
356306 setupAttachTestRepo (t )
357307
358308 repoDir := mustGetwd (t )
359309 setAttachCheckpointsV2Only (t , repoDir )
360310
361- sessionID := "test-attach-v2-only "
311+ sessionID := "test-attach-v2-disallowed "
362312 setupClaudeTranscript (t , sessionID , `{"type":"user","message":{"role":"user","content":"create hello.txt"},"uuid":"uuid-1"}
363313{"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","id":"tu_1","name":"Write","input":{"file_path":"hello.txt","content":"hello"}}]},"uuid":"uuid-2"}
364314{"type":"user","message":{"content":[{"type":"tool_result","tool_use_id":"tu_1","content":"wrote file"}]},"uuid":"uuid-3"}
@@ -388,53 +338,12 @@ func TestAttach_CheckpointsVersion2(t *testing.T) {
388338 }
389339
390340 cpPath := state .LastCheckpointID .Path ()
391- if _ , found := readFileFromRef (t , repo , paths .MetadataBranchName , cpPath + "/" + paths .MetadataFileName ); found {
392- t .Fatalf ("did not expect %s metadata for %s when checkpoints_version is 2" , paths .MetadataBranchName , cpPath )
393- }
394-
395- mainCompact , found := readFileFromRef (t , repo , paths .V2MainRefName , cpPath + "/0/" + paths .CompactTranscriptFileName )
396- if ! found {
397- t .Fatalf ("expected %s on %s" , paths .CompactTranscriptFileName , paths .V2MainRefName )
398- }
399- if ! strings .Contains (mainCompact , "create hello.txt" ) {
400- t .Errorf ("compact transcript missing prompt, got:\n %s" , mainCompact )
401- }
402-
403- fullTranscript , found := readFileFromRef (t , repo , paths .V2FullCurrentRefName , cpPath + "/0/" + paths .V2RawTranscriptFileName )
404- if ! found {
405- t .Fatalf ("expected %s on %s" , paths .V2RawTranscriptFileName , paths .V2FullCurrentRefName )
406- }
407- if ! strings .Contains (fullTranscript , "hello.txt" ) {
408- t .Errorf ("raw transcript missing file content, got:\n %s" , fullTranscript )
409- }
410- }
411-
412- func TestAttach_V2DualWriteDisabled (t * testing.T ) {
413- setupAttachTestRepo (t )
414-
415- repoDir := mustGetwd (t )
416-
417- sessionID := "test-attach-v2-disabled"
418- setupClaudeTranscript (t , sessionID , `{"type":"user","message":{"role":"user","content":"create hello.txt"},"uuid":"uuid-1"}
419- {"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","id":"tu_1","name":"Write","input":{"file_path":"hello.txt","content":"hello"}}]},"uuid":"uuid-2"}
420- {"type":"user","message":{"content":[{"type":"tool_result","tool_use_id":"tu_1","content":"wrote file"}]},"uuid":"uuid-3"}
421- {"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"Done."}]},"uuid":"uuid-4"}
422- ` )
423-
424- var out bytes.Buffer
425- if err := runAttach (context .Background (), & out , sessionID , agent .AgentNameClaudeCode , attachOptions {Force : true }); err != nil {
426- t .Fatalf ("runAttach failed: %v" , err )
427- }
428-
429- repo , err := git .PlainOpen (repoDir )
430- if err != nil {
431- t .Fatal (err )
341+ v1Ref := string (plumbing .NewBranchReferenceName (paths .MetadataBranchName ))
342+ if _ , found := readFileFromRef (t , repo , v1Ref , cpPath + "/" + paths .MetadataFileName ); ! found {
343+ t .Fatalf ("expected v1 metadata at %s for %s — checkpoints_version: 2 should fall back to v1" , paths .MetadataBranchName , cpPath )
432344 }
433345 if _ , err := repo .Reference (plumbing .ReferenceName (paths .V2MainRefName ), true ); err == nil {
434- t .Fatalf ("did not expect %s when checkpoints_v2 is disabled" , paths .V2MainRefName )
435- }
436- if _ , err := repo .Reference (plumbing .ReferenceName (paths .V2FullCurrentRefName ), true ); err == nil {
437- t .Fatalf ("did not expect %s when checkpoints_v2 is disabled" , paths .V2FullCurrentRefName )
346+ t .Fatalf ("did not expect %s when checkpoints_version: 2 is configured but disallowed" , paths .V2MainRefName )
438347 }
439348}
440349
@@ -622,36 +531,32 @@ func TestAttach_RefusesWhenCheckpointOnlyInRemoteTrackingRef(t *testing.T) {
622531 }
623532}
624533
625- // In v2-only mode, the refuse hint must reference the v2 /main ref and
626- // its fully-qualified refspec (refs/entire/checkpoints/v2/main lives under
627- // refs/entire/, not refs/heads/, so a short refspec won't resolve).
628- func TestAttach_RefuseHint_V2Only (t * testing.T ) {
534+ // TestAttach_RefuseHint_CheckpointsVersion2IgnoredFallsBackToV1 verifies that
535+ // strategy_options.checkpoints_version: 2 no longer flips attach into v2-only
536+ // mode — the refuse hint references the v1 metadata branch, not the v2 /main
537+ // ref, because v2 is disallowed and the system falls back to v1.
538+ func TestAttach_RefuseHint_CheckpointsVersion2IgnoredFallsBackToV1 (t * testing.T ) {
629539 setupAttachTestRepo (t )
630540
631541 repoRoot := mustGetwd (t )
632542 setAttachCheckpointsV2Only (t , repoRoot )
633543
634544 runGitInDir (t , repoRoot , "commit" , "--amend" , "-m" , "init\n \n Entire-Checkpoint: ffffffffeeee" )
635545
636- sessionID := "v2-orphaned -attach"
546+ sessionID := "v2-disallowed -attach"
637547 setupClaudeTranscript (t , sessionID , `{"type":"user","message":{"role":"user","content":"hi"},"uuid":"u1"}
638548` )
639549
640550 var out bytes.Buffer
641551 err := runAttach (context .Background (), & out , sessionID , agent .AgentNameClaudeCode , attachOptions {Force : true })
642552 if err == nil {
643- t .Fatal ("expected v2-only attach to refuse when checkpoint is missing" )
553+ t .Fatal ("expected attach to refuse when checkpoint is missing" )
644554 }
645- if ! strings .Contains (err .Error (), "missing from the local v2 /main ref" ) {
646- t .Errorf ("error should describe the v2 /main ref; got: %v" , err )
647- }
648- v2Refspec := paths .V2MainRefName + ":" + paths .V2MainRefName
649- if ! strings .Contains (err .Error (), v2Refspec ) {
650- t .Errorf ("error should include v2 refspec %q; got: %v" , v2Refspec , err )
555+ if ! strings .Contains (err .Error (), "missing from the local entire/checkpoints/v1 branch" ) {
556+ t .Errorf ("error should describe the v1 branch (v2 is disallowed); got: %v" , err )
651557 }
652- // And must NOT suggest the v1 refspec.
653- if strings .Contains (err .Error (), "entire/checkpoints/v1:entire/checkpoints/v1" ) {
654- t .Errorf ("v2-only hint should not reference the v1 branch; got: %v" , err )
558+ if ! strings .Contains (err .Error (), "entire/checkpoints/v1:entire/checkpoints/v1" ) {
559+ t .Errorf ("error should include v1 refspec; got: %v" , err )
655560 }
656561}
657562
@@ -1627,18 +1532,6 @@ func enableEntire(t *testing.T, repoDir string) {
16271532 }
16281533}
16291534
1630- func setAttachCheckpointsV2Enabled (t * testing.T , repoDir string ) {
1631- t .Helper ()
1632- entireDir := filepath .Join (repoDir , ".entire" )
1633- if err := os .MkdirAll (entireDir , 0o750 ); err != nil {
1634- t .Fatal (err )
1635- }
1636- settingsContent := `{"enabled": true, "strategy_options": {"checkpoints_v2": true}}`
1637- if err := os .WriteFile (filepath .Join (entireDir , "settings.json" ), []byte (settingsContent ), 0o600 ); err != nil {
1638- t .Fatal (err )
1639- }
1640- }
1641-
16421535func setAttachCheckpointsV2Only (t * testing.T , repoDir string ) {
16431536 t .Helper ()
16441537 entireDir := filepath .Join (repoDir , ".entire" )
0 commit comments