checkpoint: collapse GitStore constructors into NewGitStore(repo, refs) · Entire
Log in
checkpoint: collapse GitStore constructors into NewGitStore(repo, refs)
4ce360f→main·
pfleidi·1mo ago·38 files·+264 added/-269 removed
Every callsite now passes the resolved CommittedRefs (or DefaultV1Refs in tests). The GitStore stores the full topology, not just a read ref. promoteRemoteTrackingMetadataBranch is renamed to promoteRemoteTrackingPrimary; readCheckpointInfoFromRef and checkRemoteMetadata take CommittedRefs. The fallback-to-origin gate in getSessionsBranchTree and the resume bootstrap gate are both Read == Primary && PrimaryFetchableFromOrigin so the local-only mirror ref keeps skipping the remote-tracking fallback.
Sessions
3e44bf1e2c10View transcript
?\ Streamline Checkpoint Version Mirroring with refs.PrimaryClaude Code·1 step
Changes
38
cmd/entire/cli
Mattach.go+14/-17
Mattach_test.go+5/-5
benchutil
Mbenchutil.go+1/-1
checkpoint
Mbackwards_compat_test.go+1/-1
Mcheckpoint_test.go+55/-55
Mcommitted.go+10/-12
Mcommitted_phantom_paths_test.go+2/-2
Dcommitted_read_store.go-12
Mcommitted_read_store_test.go+29/-8
Mcommitted_reader_resolve_test.go+1/-1
Mcommitted_tripwire_test.go+1/-1
Mcommitted_update_test.go+2/-2
Mstore.go+17/-33
Mtree_surgery_equiv_test.go+3/-3
dispatch
Mmode_local.go+1/-1
Mmode_local_test.go+3/-3
Mexplain.go+6/-6
Mexplain_export_test.go+2/-2
Mexplain_test.go+20/-20
Mhead_checkpoint_flags.go+1/-1
Mhead_checkpoint_flags_test.go+1/-1
Mresume.go+42/-35
Mresume_test.go+11/-11
Mreview_context.go+1/-1
Mreview_context_test.go+1/-1
Mrewind.go+2/-2
Mstatus_test.go+1/-1
strategy
Mclean_test.go+2/-2
Mcleanup.go+1/-1
Mcommon.go+1/-1
Mmanual_commit.go+8/-8
Mmanual_commit_condensation.go+2/-2
Mmanual_commit_git.go+2/-2
Mmanual_commit_hooks.go+3/-3
Mmanual_commit_rewind.go+2/-2
Mmanual_commit_test.go+7/-7
Mphase_postcommit_test.go+2/-2
Mrewind_test.go+1/-1
19 unmodified lines
20
21
22
23
23
24
25
5 unmodified lines
31
32
33
35
34
35
36
202 unmodified lines
239
240
241
244
242
243
244
245
246
6 unmodified lines
253
254
255
257
258
256
257
258
259
109 unmodified lines
369
370
371
374
372
373
374
375
376
379
377
378
379
380
2 unmodified lines
383
384
385
388
386
387
388
389
390
391
392
395
393
394
395
396
18 unmodified lines
415
416
417
420
421
422
423
424
425
426
418
419
420
421
422
423
424
425
426
430
427
428
429
430
19 unmodified lines
"github.com/entireio/cli/cmd/entire/cli/checkpoint/remote"
"github.com/entireio/cli/cmd/entire/cli/interactive"
"github.com/entireio/cli/cmd/entire/cli/logging"
"github.com/entireio/cli/cmd/entire/cli/paths"
"github.com/entireio/cli/cmd/entire/cli/session"
"github.com/entireio/cli/cmd/entire/cli/settings"
"github.com/entireio/cli/cmd/entire/cli/strategy"
5 unmodified lines
"charm.land/huh/v2"
"github.com/go-git/go-git/v6"
"github.com/go-git/go-git/v6/plumbing"
"github.com/go-git/go-git/v6/plumbing/object"
"github.com/spf13/cobra"
)
202 unmodified lines
// If HEAD references an existing checkpoint, make sure we have it locally
// before writing — otherwise we'd create a fresh session 0 under the same
// ID and overwrite the original on push.
refreshedRepo, err := ensureCheckpointAvailable(ctx, logCtx, repo, checkpointID, isExistingCheckpoint)
refs := opts.committedRefs(ctx)
refreshedRepo, err := ensureCheckpointAvailable(ctx, logCtx, repo, refs, checkpointID, isExistingCheckpoint)
if refreshedRepo != nil && refreshedRepo != repo {
oldRepo := repo
repo = refreshedRepo
6 unmodified lines
return err
}
// Write directly to entire/checkpoints/v1.
store := cpkg.NewGitStore(repo)
store := cpkg.NewGitStore(repo, refs)
// Defense-in-depth guard: the earlier existingState.LastCheckpointID
// check only fires when the session's state file records its
109 unmodified lines
// metadata fetch fallback chain used by `entire resume` (which advances the
// local ref on success) and re-check. Returns a possibly-freshly-opened repo
// handle so go-git sees any newly fetched packfiles.
func ensureCheckpointAvailable(ctx, logCtx context.Context, repo *git.Repository, checkpointID id.CheckpointID, isExistingCheckpoint bool) (*git.Repository, error) {
func ensureCheckpointAvailable(ctx, logCtx context.Context, repo *git.Repository, refs cpkg.CommittedRefs, checkpointID id.CheckpointID, isExistingCheckpoint bool) (*git.Repository, error) {
if !isExistingCheckpoint {
return repo, nil
}
present, readErr := checkpointPresentLocally(ctx, repo, checkpointID)
present, readErr := checkpointPresentLocally(ctx, repo, refs, checkpointID)
if readErr != nil {
return repo, fmt.Errorf("failed to read checkpoint %s: %w", checkpointID, readErr)
}
2 unmodified lines
}
// Missing locally — try to refresh, then re-check. Use the same fetch
// chain `entire resume` uses for the v1 metadata branch.
// chain `entire resume` uses for the primary metadata ref.
freshRepo, fetchErr := refreshCheckpointRefs(ctx)
if fetchErr != nil {
logging.Warn(logCtx, "failed to refresh metadata branch before attach; proceeding with local state",
slog.String("error", fetchErr.Error()))
} else {
repo = freshRepo
present, readErr = checkpointPresentLocally(ctx, repo, checkpointID)
present, readErr = checkpointPresentLocally(ctx, repo, refs, checkpointID)
if readErr != nil {
return repo, fmt.Errorf("failed to read checkpoint %s after refresh: %w", checkpointID, readErr)
}
18 unmodified lines
}
// checkpointPresentLocally reports whether the checkpoint already exists on
// the local v1 ref we would write to. Remote-tracking alone is not enough;
// see ensureCheckpointAvailable.
func checkpointPresentLocally(ctx context.Context, repo *git.Repository, checkpointID id.CheckpointID) (bool, error) {
localRef := plumbing.NewBranchReferenceName(paths.MetadataBranchName)
if _, err := repo.Reference(localRef, true); err != nil {
// Local branch ref doesn't exist — treat as "not present locally".
// We deliberately do not fall back to remote-tracking: see
// the local primary ref we would write to. Remote-tracking alone is not
// enough; see ensureCheckpointAvailable.
func checkpointPresentLocally(ctx context.Context, repo *git.Repository, refs cpkg.CommittedRefs, checkpointID id.CheckpointID) (bool, error) {
if _, err := repo.Reference(refs.Primary, true); err != nil {
// Local ref doesn't exist — treat as "not present locally". We
// deliberately do not fall back to remote-tracking: see
// ensureCheckpointAvailable's docstring.
return false, nil //nolint:nilerr // Missing ref is the "absent" signal, not an error.
}
summary, err := cpkg.NewGitStore(repo).ReadCommitted(ctx, checkpointID)
summary, err := cpkg.NewGitStore(repo, refs).ReadCommitted(ctx, checkpointID)
if err != nil {
return false, err //nolint:wrapcheck // Caller wraps with checkpoint ID context
}
Mcmd/entire/cli/attach.go+14/-17
336 unmodified lines
337
338
339
340
340
341
342
343
51 unmodified lines
395
396
397
398
398
399
400
401
21 unmodified lines
423
424
425
426
426
427
428
429
716 unmodified lines
1146
1147
1148
1149
1149
1150
1151
1152
69 unmodified lines
1222
1223
1224
1225
1225
1226
1227
1228
336 unmodified lines
t.Fatalf("second attach failed: %v", err)
}
store := cpkg.NewGitStore(repo)
store := cpkg.NewGitStore(repo, cpkg.DefaultV1Refs())
summary, err := store.ReadCommitted(context.Background(), checkpointID)
if err != nil {
t.Fatalf("ReadCommitted(%s): %v", checkpointID, err)
51 unmodified lines
if err != nil {
t.Fatal(err)
}
store := cpkg.NewGitStore(repo)
store := cpkg.NewGitStore(repo, cpkg.DefaultV1Refs())
summary, err := store.ReadCommitted(context.Background(), "ffffffffeeee")
if err != nil {
t.Fatalf("ReadCommitted: %v", err)
21 unmodified lines
// Seed the local branch with a checkpoint representing Alice's session.
alicesCheckpoint := id.MustCheckpointID("abcdef012345")
store := cpkg.NewGitStore(repo)
store := cpkg.NewGitStore(repo, cpkg.DefaultV1Refs())
if writeErr := store.WriteCommitted(context.Background(), cpkg.WriteCommittedOptions{
CheckpointID: alicesCheckpoint,
SessionID: "alice-original",
716 unmodified lines
// Pre-fix observation: session 0 is OVERWRITTEN with the review session,
// losing the original attach. The summary has only one session entry
// despite two attach calls with different IDs.
store := cpkg.NewGitStore(repo)
store := cpkg.NewGitStore(repo, cpkg.DefaultV1Refs())
summary, err := store.ReadCommitted(context.Background(), checkpointID)
if err != nil {
t.Fatalf("ReadCommitted(%s): %v", checkpointID, err)
69 unmodified lines
if err != nil {
t.Fatal(err)
}
store := cpkg.NewGitStore(repo)
store := cpkg.NewGitStore(repo, cpkg.DefaultV1Refs())
summary, err := store.ReadCommitted(context.Background(), "ffffffffeeee")
if err != nil {
t.Fatalf("ReadCommitted: %v", err)
Mcmd/entire/cli/attach_test.go+5/-5
170 unmodified lines
171
172
173
174
174
175
176
177
170 unmodified lines
br := &BenchRepo{
Dir: dir,
Repo: repo,
Store: checkpoint.NewGitStore(repo),
Store: checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs()),
HeadHash: headHash.String(),
Strategy: opts.Strategy,
}
Mcmd/entire/cli/benchutil/benchutil.go+1/-1
47 unmodified lines
48
49
50
51
51
52
53
54
47 unmodified lines
t.Fatalf("failed to commit: %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("def456abc123")
// Write checkpoint WITHOUT token usage (simulates old checkpoints)
Mcmd/entire/cli/checkpoint/backwards_compat_test.go+1/-1
77 unmodified lines
78
79
80
81
81
82
83
84
48 unmodified lines
133
134
135
136
136
137
138
139
203 unmodified lines
343
344
345
346
346
347
348
349
119 unmodified lines
469
470
471
472
472
473
474
475
68 unmodified lines
544
545
546
547
547
548
549
550
135 unmodified lines
686
687
688
689
689
690
691
692
33 unmodified lines
726
727
728
729
729
730
731
732
15 unmodified lines
748
749
750
751
751
752
753
754
65 unmodified lines
820
821
822
823
823
824
825
826
43 unmodified lines
870
871
872
873
873
874
875
876
40 unmodified lines
917
918
919
920
920
921
922
923
10 unmodified lines
934
935
936
937
937
938
939
940
31 unmodified lines
972
973
974
975
975
976
977
978
19 unmodified lines
998
999
1000
1001
1001
1002
1003
1004
16 unmodified lines
1021
1022
1023
1024
1024
1025
1026
1027
74 unmodified lines
1102
1103
1104
1105
1105
1106
1107
1108
84 unmodified lines
1193
1194
1195
1196
1196
1197
1198
1199
53 unmodified lines
1253
1254
1255
1256
1256
1257
1258
1259
55 unmodified lines
1315
1316
1317
1318
1318
1319
1320
1321
13 unmodified lines
1335
1336
1337
1338
1338
1339
1340
1341
46 unmodified lines
1388
1389
1390
1391
1391
1392
1393
1394
31 unmodified lines
1426
1427
1428
1429
1429
1430
1431
1432
46 unmodified lines
1479
1480
1481
1482
1482
1483
1484
1485
56 unmodified lines
1542
1543
1544
1545
1545
1546
1547
1548
38 unmodified lines
1587
1588
1589
1590
1590
1591
1592
1593
35 unmodified lines
1629
1630
1631
1632
1632
1633
1634
1635
64 unmodified lines
1700
1701
1702
1703
1703
1704
1705
1706
16 unmodified lines
1723
1724
1725
1726
1726
1727
1728
1729
63 unmodified lines
1793
1794
1795
1796
1796
1797
1798
1799
122 unmodified lines
1922
1923
1924
1925
1925
1926
1927
1928
92 unmodified lines
2021
2022
2023
2024
2024
2025
2026
2027
102 unmodified lines
2130
2131
2132
2133
2133
2134
2135
2136
93 unmodified lines
2230
2231
2232
2233
2233
2234
2235
2236
114 unmodified lines
2351
2352
2353
2354
2354
2355
2356
2357
104 unmodified lines
2462
2463
2464
2465
2465
2466
2467
2468
116 unmodified lines
2585
2586
2587
2588
2588
2589
2590
2591
107 unmodified lines
2699
2700
2701
2702
2702
2703
2704
2705
91 unmodified lines
2797
2798
2799
2800
2800
2801
2802
2803
89 unmodified lines
2893
2894
2895
2896
2896
2897
2898
2899
40 unmodified lines
2940
2941
2942
2943
2943
2944
2945
2946
128 unmodified lines
3075
3076
3077
3078
3078
3079
3080
3081
69 unmodified lines
3151
3152
3153
3154
3154
3155
3156
3157
77 unmodified lines
3235
3236
3237
3238
3238
3239
3240
3241
71 unmodified lines
3313
3314
3315
3316
3316
3317
3318
3319
31 unmodified lines
3351
3352
3353
3354
3354
3355
3356
3357
48 unmodified lines
3406
3407
3408
3409
3409
3410
3411
3412
64 unmodified lines
3477
3478
3479
3480
3480
3481
3482
3483
106 unmodified lines
3590
3591
3592
3593
3593
3594
3595
3596
211 unmodified lines
3808
3809
3810
3811
3811
3812
3813
3814
35 unmodified lines
3850
3851
3852
3853
3853
3854
3855
3856
38 unmodified lines
3895
3896
3897
3898
3898
3899
3900
3901
94 unmodified lines
3996
3997
3998
3999
3999
4000
4001
4002
247 unmodified lines
4250
4251
4252
4253
4253
4254
4255
4256
297 unmodified lines
4554
4555
4556
4557
4557
4558
4559
4560
46 unmodified lines
4607
4608
4609
4610
4610
4611
4612
4613
77 unmodified lines
}
// Create GitStore and call copyMetadataDir
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
entries := make(map[string]object.TreeEntry)
err = store.copyMetadataDir(metadataDir, "checkpoint/", entries)
48 unmodified lines
}
// Create checkpoint store
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
// Write a committed checkpoint with Agent field
checkpointID := id.MustCheckpointID("a1b2c3d4e5f6")
203 unmodified lines
}
// Create checkpoint store
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
// First checkpoint should be created
baseCommit := initialCommit.String()
119 unmodified lines
t.Fatalf("write settings.json: %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
if err := store.ensureSessionsBranch(context.Background()); err != nil {
t.Fatalf("ensureSessionsBranch() error = %v", err)
}
68 unmodified lines
t.Fatalf("BuildTreeFromEntries() error = %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
commitHash, err := store.createCommit(context.Background(), treeHash, plumbing.ZeroHash, "Initialize metadata branch", "Test", "test@test.com")
if err != nil {
t.Fatalf("createCommit() error = %v", err)
135 unmodified lines
// Write a committed checkpoint with branch information
checkpointID := id.MustCheckpointID("a1b2c3d4e5f6")
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
err = store.WriteCommitted(context.Background(), WriteCommittedOptions{
CheckpointID: checkpointID,
SessionID: "test-session-123",
33 unmodified lines
// Write a committed checkpoint (branch should be empty in detached HEAD)
checkpointID := id.MustCheckpointID("b2c3d4e5f6a7")
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
err = store.WriteCommitted(context.Background(), WriteCommittedOptions{
CheckpointID: checkpointID,
SessionID: "test-session-456",
15 unmodified lines
// field in an existing checkpoint's metadata.
func TestUpdateSummary(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("f1e2d3c4b5a6")
// First, create a checkpoint without a summary
65 unmodified lines
// when the checkpoint doesn't exist.
func TestUpdateSummary_NotFound(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
// Ensure sessions branch exists
err := store.ensureSessionsBranch(context.Background())
43 unmodified lines
}
// Create entire/checkpoints/v1 branch on the remote with a checkpoint
remoteStore := NewGitStore(remoteRepo)
remoteStore := NewGitStore(remoteRepo, DefaultV1Refs())
cpID := id.MustCheckpointID("abcdef123456")
err = remoteStore.WriteCommitted(context.Background(), WriteCommittedOptions{
CheckpointID: cpID,
40 unmodified lines
}
// ListCommitted should find the checkpoint by falling back to remote
localStore := NewGitStore(localRepo)
localStore := NewGitStore(localRepo, DefaultV1Refs())
checkpoints, err := localStore.ListCommitted(context.Background())
if err != nil {
t.Fatalf("ListCommitted() error = %v", err)
10 unmodified lines
// author of the commit that created the checkpoint on the entire/checkpoints/v1 branch.
func TestGetCheckpointAuthor(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("a1b2c3d4e5f6")
// Create a checkpoint with specific author info
31 unmodified lines
// empty author when the checkpoint doesn't exist.
func TestGetCheckpointAuthor_NotFound(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
// Query for a non-existent checkpoint (must be valid hex)
checkpointID := id.MustCheckpointID("ffffffffffff")
19 unmodified lines
t.Fatalf("failed to init git repo: %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("aabbccddeeff")
author, err := store.GetCheckpointAuthor(context.Background(), checkpointID)
16 unmodified lines
// sessions to the same checkpoint ID creates separate numbered subdirectories.
func TestWriteCommitted_MultipleSessionsSameCheckpoint(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("a1a2a3a4a5a6")
// Write first session
74 unmodified lines
// multiple sessions written to the same checkpoint.
func TestWriteCommitted_Aggregation(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("b1b2b3b4b5b6")
// Write first session with specific stats
84 unmodified lines
// a CheckpointSummary with the correct structure including Sessions array.
func TestReadCommitted_ReturnsCheckpointSummary(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("c1c2c3c4c5c6")
// Write two sessions
53 unmodified lines
// specific sessions by their 0-based index within a checkpoint.
func TestReadSessionContent_ByIndex(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("d1d2d3d4d5d6")
// Write two sessions with distinct content
55 unmodified lines
func writeSingleSession(t *testing.T, cpIDStr, sessionID, transcript string) (*GitStore, id.CheckpointID) {
t.Helper()
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID(cpIDStr)
err := store.WriteCommitted(context.Background(), WriteCommittedOptions{
13 unmodified lines
func TestWriteCommitted_CodexSanitizesPortableTranscript(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("c0de1234beef")
transcript := `{"timestamp":"2026-03-25T11:31:11.754Z","type":"response_item","payload":{"type":"reasoning","summary":[{"text":"brief"}],"encrypted_content":"REDACTED"}}
46 unmodified lines
// the content of the most recently added session (highest index).
func TestReadLatestSessionContent(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("f1f2f3f4f5f6")
// Write three sessions
31 unmodified lines
// a session by its session ID rather than by index.
func TestReadSessionContentByID(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("010203040506")
// Write two sessions with distinct IDs
46 unmodified lines
// information for checkpoints with multiple sessions.
func TestListCommitted_MultiSessionInfo(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("212223242526")
// Write two sessions to the same checkpoint
56 unmodified lines
// written without prompts and still be read correctly.
func TestWriteCommitted_SessionWithNoPrompts(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("313233343536")
// Write session without prompts
38 unmodified lines
// Regression test for ENT-243 where Summary was omitted from the struct literal.
func TestWriteCommitted_SessionWithSummary(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("aabbccddeeff")
summary := &Summary{
35 unmodified lines
// to ensure the 0-based indexing works correctly throughout.
func TestWriteCommitted_ThreeSessions(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("515253545556")
// Write three sessions
64 unmodified lines
// nil (not an error) when the checkpoint doesn't exist.
func TestReadCommitted_NonexistentCheckpoint(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
// Ensure sessions branch exists
err := store.ensureSessionsBranch(context.Background())
16 unmodified lines
// returns ErrCheckpointNotFound when the checkpoint doesn't exist.
func TestReadSessionContent_NonexistentCheckpoint(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
// Ensure sessions branch exists
err := store.ensureSessionsBranch(context.Background())
63 unmodified lines
// Create checkpoint store and write first checkpoint
// Note: ModifiedFiles is empty because agent hasn't touched anything yet
// The first checkpoint should still capture README.md because it's modified in working dir
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
baseCommit := initialCommit.String()
result, err := store.WriteTemporary(context.Background(), WriteTemporaryOptions{
122 unmodified lines
t.Fatalf("failed to write transcript: %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
result, err := store.WriteTemporary(context.Background(), WriteTemporaryOptions{
SessionID: "test-session",
BaseCommit: initialCommit.String(),
92 unmodified lines
}
// Create checkpoint store and write first checkpoint
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
baseCommit := initialCommit.String()
result, err := store.WriteTemporary(context.Background(), WriteTemporaryOptions{
102 unmodified lines
}
result, err := store.WriteTemporary(context.Background(), WriteTemporaryOptions{
93 unmodified lines
t.Fatalf("failed to write transcript: %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
baseCommit := initialCommit.String()
// Write first checkpoint to establish the shadow branch
114 unmodified lines
t.Fatalf("failed to write transcript: %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
baseCommit := initialCommit.String()
// First checkpoint
104 unmodified lines
t.Fatalf("failed to write transcript: %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
baseCommit := initialCommit.String()
// First checkpoint
116 unmodified lines
}
// Create checkpoint - agent reports main.go as modified (from transcript)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
baseCommit := initialCommit.String()
result, err := store.WriteTemporary(context.Background(), WriteTemporaryOptions{
107 unmodified lines
}
result, err := store.WriteTemporary(context.Background(), WriteTemporaryOptions{
91 unmodified lines
}
result, err := store.WriteTemporary(context.Background(), WriteTemporaryOptions{
89 unmodified lines
}
result, err := store.WriteTemporary(context.Background(), WriteTemporaryOptions{
40 unmodified lines
func TestWriteCommitted_DuplicateSessionIDUpdatesInPlace(t *testing.T) {
t.Parallel()
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("deda01234567")
// Write session "X" with initial data
128 unmodified lines
func TestWriteCommitted_DuplicateSessionIDSingleSession(t *testing.T) {
t.Parallel()
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("dedb07654321")
// Write session "X" with initial data
69 unmodified lines
func TestWriteCommitted_DuplicateSessionIDReusesIndex(t *testing.T) {
t.Parallel()
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("dedc0abcdef1")
// Write session A at index 0
77 unmodified lines
func TestWriteCommitted_DuplicateSessionIDClearsStaleFiles(t *testing.T) {
t.Parallel()
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("dedd0abcdef2")
// Write session A with prompts and context
71 unmodified lines
func TestWriteCommitted_PreservesRedactedTranscript(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("aabbccddeef1")
// Callers redact before passing to WriteCommitted; the store persists as-is.
31 unmodified lines
func TestWriteCommitted_RedactsPromptSecrets(t *testing.T) {
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("aabbccddeef2")
err := store.WriteCommitted(context.Background(), WriteCommittedOptions{
48 unmodified lines
t.Fatalf("failed to write txt file: %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
entries := make(map[string]object.TreeEntry)
if err := store.copyMetadataDir(metadataDir, "cp/", entries); err != nil {
64 unmodified lines
t.Fatalf("failed to commit: %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("b1c2d3e4f5a6")
sessionID := "test-session-version"
106 unmodified lines
t.Fatalf("failed to commit: %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("c1d2e3f4a5b6")
err = store.WriteCommitted(context.Background(), WriteCommittedOptions{
211 unmodified lines
func TestWriteCommitted_RedactsSummarySecrets(t *testing.T) {
t.Parallel()
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("aabbccddeef7")
err := store.WriteCommitted(context.Background(), WriteCommittedOptions{
35 unmodified lines
func TestUpdateSummary_RedactsSecrets(t *testing.T) {
t.Parallel()
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("aabbccddeef8")
// First write a checkpoint without a summary
38 unmodified lines
func TestWriteCommitted_SubagentTranscript_JSONLFallback(t *testing.T) {
t.Parallel()
repo, _ := setupBranchTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("aabbccddeef9")
// Create a temp file with invalid JSONL containing a secret
94 unmodified lines
t.Fatalf("failed to write transcript: %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
baseCommit := initialCommit.String()
_, err = store.WriteTemporaryTask(context.Background(), WriteTemporaryTaskOptions{
247 unmodified lines
t.Fatalf("failed to write transcript: %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
baseCommit := initialCommit.String()
// Write task checkpoint where subagent reports .env as modified
297 unmodified lines
t.Parallel()
repo := initRepoForCheckpointTest(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("aabbccddeeff")
// First session: investigate session, sets HasInvestigation=true.
46 unmodified lines
t.Parallel()
repo := initRepoForCheckpointTest(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
checkpointID := id.MustCheckpointID("11223344aabb")
if err := store.WriteCommitted(context.Background(), WriteCommittedOptions{
Mcmd/entire/cli/checkpoint/checkpoint_test.go+55/-55
1345 unmodified lines
1346
1347
1348
1349
1349
1350
1351
1352
428 unmodified lines
1781
1782
1783
1784
1785
1786
1787
1788
1784
1785
1786
1787
1788
1790
1789
1790
1792
1793
1791
1792
1793
1795
1796
1794
1795
1796
1797
403 unmodified lines
2201
2202
2203
2206
2204
2205
2206
2207
1345 unmodified lines
return nil, "", fmt.Errorf("failed to open git repository: %w", err)
}
defer repo.Close()
store := NewGitStore(repo)
store := NewGitStore(repo, ResolveCommittedRefs(ctx))
return store.GetSessionLog(ctx, cpID)
}
428 unmodified lines
return NewFetchingTree(ctx, tree, s.repo.Storer, s.blobFetcher), nil
}
// getSessionsBranchTree returns the tree object for the configured committed
// ref (the v1 branch by default, or the v1.1 custom ref for v1.1 read stores).
// For the default v1 branch it falls back to origin/entire/checkpoints/v1 when
// the local branch is missing; the v1.1 custom ref is local-only, so no remote
// fallback applies there.
// getSessionsBranchTree returns the tree object at the configured read ref.
// Falls back to origin's remote-tracking ref when Read equals Primary and
// Primary is in Push (origin tracks it). When reads target the local-only
// mirror, the fallback skips because origin doesn't track the mirror.
func (s *GitStore) getSessionsBranchTree() (*object.Tree, error) {
ref, err := s.repo.Reference(s.committedReadRef, true)
ref, err := s.repo.Reference(s.refs.Read, true)
if err != nil {
if s.committedReadRef != defaultCommittedReadRef() {
return nil, fmt.Errorf("sessions ref %s not found: %w", s.committedReadRef, err)
if s.refs.Read != s.refs.Primary || !s.refs.PrimaryFetchableFromOrigin() {
return nil, fmt.Errorf("sessions ref %s not found: %w", s.refs.Read, err)
}
// Local v1 branch doesn't exist, try remote-tracking branch
remoteRefName := plumbing.NewRemoteReferenceName("origin", paths.MetadataBranchName)
remoteRefName := plumbing.NewRemoteReferenceName("origin", s.refs.Primary.Short())
ref, err = s.repo.Reference(remoteRefName, true)
if err != nil {
return nil, fmt.Errorf("sessions branch not found: %w", err)
403 unmodified lines
// Finds the commit whose subject matches "Checkpoint: <id>" and returns its author.
// Returns empty Author if the checkpoint is not found or the sessions branch doesn't exist.
func (s *GitStore) GetCheckpointAuthor(ctx context.Context, checkpointID id.CheckpointID) (Author, error) {
return getCheckpointAuthorFromRef(ctx, s.repo, s.committedReadRef, checkpointID)
return getCheckpointAuthorFromRef(ctx, s.repo, s.refs.Read, checkpointID)
}
func getCheckpointAuthorFromRef(ctx context.Context, repo *git.Repository, refName plumbing.ReferenceName, checkpointID id.CheckpointID) (Author, error) {
Mcmd/entire/cli/checkpoint/committed.go+10/-12
35 unmodified lines
36
37
38
39
39
40
41
42
39 unmodified lines
82
83
84
85
85
86
87
88
35 unmodified lines
})
require.NoError(t, err)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
cpID := id.MustCheckpointID("d4e5f6a1b2c3")
// Write a checkpoint with NO transcript
39 unmodified lines
})
require.NoError(t, err)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
cpID := id.MustCheckpointID("e5f6a1b2c3d4")
// Write a checkpoint WITH a transcript
Mcmd/entire/cli/checkpoint/committed_phantom_paths_test.go+2/-2
1
2
3
4
5
6
7
8
9
10
11
12
package checkpoint
import (
"context"
"github.com/go-git/go-git/v6"
)
// NewCommittedReadStore returns a GitStore bound to the topology's read ref.
func NewCommittedReadStore(ctx context.Context, repo *git.Repository) *GitStore {
return NewGitStoreWithRef(repo, ResolveCommittedRefs(ctx).Read)
}
Dcmd/entire/cli/checkpoint/committed_read_store.go-12
66 unmodified lines
67
68
69
70
70
71
72
73
24 unmodified lines
98
99
100
101
102
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
106
127
128
129
130
131
132
112
133
134
135
115
136
137
138
139
140
141
121
142
143
144
145
29 unmodified lines
175
176
177
157
178
179
180
181
66 unmodified lines
// writeV1Checkpoint writes a committed checkpoint to the v1 branch.
func writeV1Checkpoint(t *testing.T, repo *git.Repository, cpID id.CheckpointID) {
t.Helper()
require.NoError(t, NewGitStore(repo).WriteCommitted(context.Background(), WriteCommittedOptions{
require.NoError(t, NewGitStore(repo, DefaultV1Refs()).WriteCommitted(context.Background(), WriteCommittedOptions{
CheckpointID: cpID,
SessionID: "session",
Strategy: "manual-commit",
24 unmodified lines
func TestGitStore_CommittedReadRef(t *testing.T) {
t.Parallel()
assert.Equal(t, v1BranchRef(), NewGitStore(nil).CommittedReadRef())
assert.Equal(t, customRef(), NewGitStoreWithRef(nil, customRef()).CommittedReadRef())
assert.Equal(t, v1BranchRef(), NewGitStore(nil, DefaultV1Refs()).CommittedReadRef())
customRefs := CommittedRefs{
Primary: v1BranchRef(),
Read: customRef(),
Mirror: customRef(),
Push: []plumbing.ReferenceName{v1BranchRef()},
}
assert.Equal(t, customRef(), NewGitStore(nil, customRefs).CommittedReadRef())
}
func TestNewGitStore_UsesRefs(t *testing.T) {
t.Parallel()
dir := t.TempDir()
testutil.InitRepo(t, dir)
repo, err := git.PlainOpen(dir)
require.NoError(t, err)
synthetic := plumbing.ReferenceName("refs/entire/checkpoints/synthetic")
refs := CommittedRefs{Primary: synthetic, Read: synthetic, Push: []plumbing.ReferenceName{synthetic}}
store := NewGitStore(repo, refs)
assert.Equal(t, synthetic, store.CommittedReadRef())
assert.Equal(t, refs, store.Refs())
}
// Not parallel: uses t.Chdir() so settings.Load resolves the test repo.
func TestNewCommittedReadStore_SelectsRefByVersion(t *testing.T) {
func TestNewGitStore_SelectsRefByVersion(t *testing.T) {
dir, repo, h := newTestRepo(t)
setRef(t, repo, v1BranchRef(), h)
t.Chdir(dir)
writeSettings(t, dir, "") // v1 only
assert.Equal(t, v1BranchRef(), NewCommittedReadStore(context.Background(), repo).CommittedReadRef())
assert.Equal(t, v1BranchRef(), NewGitStore(repo, ResolveCommittedRefs(context.Background())).CommittedReadRef())
writeSettings(t, dir, `"1.1"`)
assert.Equal(t, customRef(), NewCommittedReadStore(context.Background(), repo).CommittedReadRef())
assert.Equal(t, customRef(), NewGitStore(repo, ResolveCommittedRefs(context.Background())).CommittedReadRef())
}
// v1.1 reads always go through the custom ref as-is (no v1 fallback, and no
// read-time seeding from v1).
// Not parallel: subtests use t.Chdir().
func TestNewCommittedReadStore_V11Reads(t *testing.T) {
func TestNewGitStore_V11Reads(t *testing.T) {
tests := []struct {
name string
mutate func(t *testing.T, dir string, repo *git.Repository) (wantCustomHash plumbing.Hash, wantCustomExists bool)
29 unmodified lines
writeV1Checkpoint(t, repo, cpID)
wantCustomHash, wantCustomExists := tt.mutate(t, dir, repo)
store := NewCommittedReadStore(context.Background(), repo)
store := NewGitStore(repo, ResolveCommittedRefs(context.Background()))
require.Equal(t, customRef(), store.CommittedReadRef(), "must read the custom ref, not fall back to v1")
summary, err := store.ReadCommitted(context.Background(), cpID)
Mcmd/entire/cli/checkpoint/committed_read_store_test.go+29/-8
39 unmodified lines
40
41
42
43
43
44
45
46
39 unmodified lines
repo, err := git.PlainOpen(repoDir)
require.NoError(t, err)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
ctx := context.Background()
cpID := id.MustCheckpointID("222222222222")
Mcmd/entire/cli/checkpoint/committed_reader_resolve_test.go+1/-1
24 unmodified lines
25
26
27
28
28
29
30
31
24 unmodified lines
if err != nil {
t.Fatalf("PlainInit() error = %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
if err := logging.Init(context.Background(), ""); err != nil {
t.Fatalf("logging.Init() error = %v", err)
Mcmd/entire/cli/checkpoint/committed_tripwire_test.go+1/-1
45 unmodified lines
46
47
48
49
49
50
51
52
433 unmodified lines
486
487
488
489
489
490
491
492
45 unmodified lines
t.Fatalf("failed to commit: %v", err)
}
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
cpID := id.MustCheckpointID("a1b2c3d4e5f6")
err = store.WriteCommitted(context.Background(), WriteCommittedOptions{
433 unmodified lines
}
// Write initial checkpoint
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
cpID := id.MustCheckpointID("a1b2c3d4e5f6")
err = store.WriteCommitted(context.Background(), WriteCommittedOptions{
CheckpointID: cpID,
Mcmd/entire/cli/checkpoint/committed_update_test.go+2/-2
2 unmodified lines
3
4
5
6
7
6
7
8
9
10
13
14
11
12
13
14
15
16
17
18
18
19
20
21
22
23
24
25
26
19
20
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
21
22
23
24
25
26
27
28
48
49
29
30
31
32
33
34
55
35
36
37
38
39
40
41
42
43
44
45
62
46
47
2 unmodified lines
import (
"github.com/go-git/go-git/v6"
"github.com/go-git/go-git/v6/plumbing"
"github.com/entireio/cli/cmd/entire/cli/paths"
)
// Compile-time check that GitStore implements the Store interface.
var _ Store = (*GitStore)(nil)
// GitStore provides operations for both temporary and committed checkpoint storage.
// It implements the Store interface by wrapping a git repository.
// GitStore provides operations for both temporary and committed checkpoint
// storage. It wraps a git repository and owns the committed-metadata ref
// topology: writes target refs.Primary, committed reads resolve against
// refs.Read, and mirror advancement runs through strategy.AdvanceCommittedPrimary.
type GitStore struct {
repo *git.Repository
refs CommittedRefs
blobFetcher BlobFetchFunc
// committedReadRef is the ref that committed-checkpoint *reads* resolve
// against. Defaults to the v1 branch; v1.1 read stores bind it to the
// local-only custom ref (paths.MetadataRefName).
//
// Writes intentionally do NOT use this ref: committed writes always target
// the v1 branch (the durable source of truth) and are mirrored to the v1.1
// custom ref separately by the strategy mirror paths. Pointing writes here
// would let a v1.1 read store write ahead of v1 and diverge from it.
committedReadRef plumbing.ReferenceName
}
// defaultCommittedReadRef is the v1 metadata branch ref reads resolve against by
// default.
func defaultCommittedReadRef() plumbing.ReferenceName {
return plumbing.NewBranchReferenceName(paths.MetadataBranchName)
}
// NewGitStore creates a new checkpoint store backed by the given git repository.
// Committed reads resolve against the default v1 metadata branch.
func NewGitStore(repo *git.Repository) *GitStore {
return &GitStore{repo: repo, committedReadRef: defaultCommittedReadRef()}
}
// NewGitStoreWithRef creates a checkpoint store whose committed reads resolve
// against committedReadRef (writes still target the v1 branch; see GitStore).
func NewGitStoreWithRef(repo *git.Repository, committedReadRef plumbing.ReferenceName) *GitStore {
return &GitStore{repo: repo, committedReadRef: committedReadRef}
// NewGitStore creates a checkpoint store backed by the given git repository
// and committed-metadata topology. Pass DefaultV1Refs() for the v1-only default
// or ResolveCommittedRefs(ctx) in code paths that honor settings.
func NewGitStore(repo *git.Repository, refs CommittedRefs) *GitStore {
return &GitStore{repo: repo, refs: refs}
}
// SetBlobFetcher configures the store to automatically fetch missing blobs
// on demand when reading from metadata trees. This is used after treeless
// fetches where tree objects are local but blob objects are not.
// on demand when reading from metadata trees.
func (s *GitStore) SetBlobFetcher(f BlobFetchFunc) {
s.blobFetcher = f
}
// Repository returns the underlying git repository.
// This is useful for strategies that need direct repository access.
func (s *GitStore) Repository() *git.Repository {
return s.repo
}
// Refs returns the committed-metadata topology the store was constructed with.
func (s *GitStore) Refs() CommittedRefs {
return s.refs
}
// CommittedReadRef returns the ref that committed-checkpoint reads resolve against.
func (s *GitStore) CommittedReadRef() plumbing.ReferenceName {
return s.committedReadRef
return s.refs.Read
}
Mcmd/entire/cli/checkpoint/store.go+17/-33
17 unmodified lines
18
19
20
21
21
22
23
24
51 unmodified lines
76
77
78
79
79
80
81
82
36 unmodified lines
119
120
121
122
122
123
124
125
17 unmodified lines
// tree hashes to the old FlattenTree+BuildTreeFromEntries approach.
func TestBuildTreeWithChanges_EquivalenceWithFlattenRebuild(t *testing.T) { //nolint:paralleltest // t.Chdir requires non-parallel
repo, dir := setupTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
// Get the base tree hash from HEAD
head, err := repo.Head()
51 unmodified lines
t.Parallel()
repo, _ := setupTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
head, err := repo.Head()
if err != nil {
36 unmodified lines
t.Parallel()
repo, _ := setupTestRepo(t)
store := NewGitStore(repo)
store := NewGitStore(repo, DefaultV1Refs())
head, err := repo.Head()
if err != nil {
Mcmd/entire/cli/checkpoint/tree_surgery_equiv_test.go+3/-3
177 unmodified lines
178
179
180
181
181
182
183
184
177 unmodified lines
// the cwd may not be a repo at all, so scope settings resolution to this
// repo before consulting the topology.
repoCtx := settings.WithWorktreeRoot(ctx, repoRoot)
store := checkpoint.NewCommittedReadStore(repoCtx, repo)
store := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(repoCtx))
infos, err := store.ListCommitted(ctx)
if err != nil {
return nil, fmt.Errorf("list committed checkpoints: %w", err)
Mcmd/entire/cli/dispatch/mode_local.go+1/-1
421 unmodified lines
422
423
424
425
425
426
427
428
60 unmodified lines
489
490
491
492
492
493
494
495
434 unmodified lines
930
931
932
933
933
934
935
936
421 unmodified lines
if err != nil {
t.Fatal(err)
}
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
parsedID, err := checkpointid.NewCheckpointID(cpID)
if err != nil {
t.Fatal(err)
60 unmodified lines
if err != nil {
t.Fatal(err)
}
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
parsedID, err := checkpointid.NewCheckpointID(cpID)
if err != nil {
t.Fatal(err)
434 unmodified lines
t.Fatal(err)
}
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
cpID, err := checkpointid.NewCheckpointID(cp.id)
if err != nil {
t.Fatal(err)
Mcmd/entire/cli/dispatch/mode_local_test.go+3/-3
637 unmodified lines
638
639
640
641
641
642
643
644
33 unmodified lines
678
679
680
681
681
682
683
684
685
686
687
687
688
689
690
157 unmodified lines
848
849
850
851
851
852
853
854
1147 unmodified lines
2002
2003
2004
2005
2005
2006
2007
2008
97 unmodified lines
2106
2107
2108
2109
2109
2110
2111
2112
637 unmodified lines
// layer, so rawTranscript is always false when generate is true; the
// direct-to-w write path inside explainTemporaryCheckpoint is not
// reachable here and won't leak partial output on error.
output, found, tempErr := explainTemporaryCheckpoint(ctx, w, errW, lookup.repo, checkpoint.NewGitStore(lookup.repo), checkpointIDPrefix, verbose, full, rawTranscript)
output, found, tempErr := explainTemporaryCheckpoint(ctx, w, errW, lookup.repo, checkpoint.NewGitStore(lookup.repo, checkpoint.ResolveCommittedRefs(ctx)), checkpointIDPrefix, verbose, full, rawTranscript)
if tempErr != nil {
return tempErr
}
33 unmodified lines
// Handle summary generation — uses raw transcript.
if generate {
stopLoad(false) // generation prints its own progress to w/errW
writeStore := checkpoint.NewGitStore(lookup.repo)
writeStore := checkpoint.NewGitStore(lookup.repo, checkpoint.ResolveCommittedRefs(ctx))
if err := generateCheckpointSummary(ctx, w, errW, writeStore, fullCheckpointID, summary, content, force, summaryTimeoutSeconds); err != nil {
return err
}
// Reload to get the updated summary.
stopLoad = startSpinner(errW, fmt.Sprintf("Reloading checkpoint %s", fullCheckpointID))
lookup.store = checkpoint.NewCommittedReadStore(ctx, lookup.repo)
lookup.store = checkpoint.NewGitStore(lookup.repo, checkpoint.ResolveCommittedRefs(ctx))
lookup.store.SetBlobFetcher(FetchBlobsByHash)
content, err = checkpoint.ReadLatestSessionContent(ctx, lookup.store, fullCheckpointID, summary)
if err != nil {
157 unmodified lines
// `git fetch` fails against partial-clone repos with "did not send all
// necessary objects"). Falls back to a full metadata-branch fetch if
// fetch-pack also can't reach the blobs.
store := checkpoint.NewCommittedReadStore(ctx, repo)
store := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx))
store.SetBlobFetcher(FetchBlobsByHash)
lookup := &explainCheckpointLookup{
1147 unmodified lines
// Warn (once per process) if metadata branches are disconnected
strategy.WarnIfMetadataDisconnected()
store := checkpoint.NewCommittedReadStore(ctx, repo)
store := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx))
// Get all committed checkpoints for lookup.
committedInfos, err := store.ListCommitted(ctx)
97 unmodified lines
}
// Get temporary checkpoints from ALL shadow branches whose base commit is reachable from HEAD.
tempPoints := getReachableTemporaryCheckpoints(ctx, repo, checkpoint.NewGitStore(repo), head.Hash(), isOnDefault, limit)
tempPoints := getReachableTemporaryCheckpoints(ctx, repo, checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx)), head.Hash(), isOnDefault, limit)
points = append(points, tempPoints...)
// Sort by date, most recent first
Mcmd/entire/cli/explain.go+6/-6
73 unmodified lines
74
75
76
77
77
78
79
80
84 unmodified lines
165
166
167
168
168
169
170
171
73 unmodified lines
if opts.AuthorEmail == "" {
opts.AuthorEmail = exportTestAuthorEmail
}
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
require.NoError(t, store.WriteCommitted(context.Background(), opts))
}
84 unmodified lines
repo := setupExportRepo(t)
cpID := id.MustCheckpointID("777711112222")
v1 := checkpoint.NewGitStore(repo)
v1 := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
require.NoError(t, v1.WriteCommitted(context.Background(), checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: "session-v1-only",
Mcmd/entire/cli/explain_export_test.go+2/-2
412 unmodified lines
413
414
415
416
416
417
418
419
106 unmodified lines
526
527
528
529
529
530
531
532
135 unmodified lines
668
669
670
671
671
672
673
674
92 unmodified lines
767
768
769
770
770
771
772
773
239 unmodified lines
1013
1014
1015
1016
1016
1017
1018
1019
981 unmodified lines
2001
2002
2003
2004
2004
2005
2006
2007
57 unmodified lines
2065
2066
2067
2068
2068
2069
2070
2071
29 unmodified lines
2101
2102
2103
2104
2104
2105
2106
2107
25 unmodified lines
2133
2134
2135
2136
2136
2137
2138
2139
67 unmodified lines
2207
2208
2209
2210
2210
2211
2212
2213
70 unmodified lines
2284
2285
2286
2287
2287
2288
2289
2290
54 unmodified lines
2345
2346
2347
2348
2348
2349
2350
2351
42 unmodified lines
2394
2395
2396
2397
2397
2398
2399
2400
35 unmodified lines
2436
2437
2438
2439
2439
2440
2441
2442
8 unmodified lines
2451
2452
2453
2454
2454
2455
2456
2457
1110 unmodified lines
3568
3569
3570
3571
3571
3572
3573
3574
116 unmodified lines
3691
3692
3693
3694
3694
3695
3696
3697
1944 unmodified lines
5642
5643
5644
5645
5645
5646
5647
5648
61 unmodified lines
5710
5711
5712
5713
5713
5714
5715
5716
65 unmodified lines
5782
5783
5784
5785
5785
5786
5787
5788
412 unmodified lines
ctx := context.Background()
cpID := id.MustCheckpointID("deadbeefcafe")
require.NoError(t, checkpoint.NewGitStore(repo).WriteCommitted(ctx, checkpoint.WriteCommittedOptions{
require.NoError(t, checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs()).WriteCommitted(ctx, checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: "session-auto",
Strategy: "manual-commit",
106 unmodified lines
require.NoError(t, os.WriteFile(testFile, []byte("updated content"), 0o644))
result, err := checkpoint.NewGitStore(repo).WriteTemporary(context.Background(), checkpoint.WriteTemporaryOptions{
result, err := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs()).WriteTemporary(context.Background(), checkpoint.WriteTemporaryOptions{
SessionID: sessionID,
BaseCommit: initialCommit.String()[:7],
ModifiedFiles: []string{"temp.txt"},
135 unmodified lines
ctx := context.Background()
// Seed two committed checkpoints sharing a hex prefix.
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
transcriptBytes := redact.AlreadyRedacted([]byte(`{"type":"user","message":{"content":[{"type":"text","text":"hello"}]}}` + "\n"))
for _, cpID := range []id.CheckpointID{
id.MustCheckpointID("e7aaaaaaaaaa"),
92 unmodified lines
commitPrefix := head.Hash().String()[:7]
collisionID := id.MustCheckpointID(commitPrefix + "aaaaa")
require.NoError(t, checkpoint.NewGitStore(repo).WriteCommitted(ctx, checkpoint.WriteCommittedOptions{
require.NoError(t, checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs()).WriteCommitted(ctx, checkpoint.WriteCommittedOptions{
CheckpointID: collisionID,
SessionID: "session-collision",
Strategy: "manual-commit",
239 unmodified lines
repo, err := git.PlainOpen(tmpDir)
require.NoError(t, err)
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
cpID := id.MustCheckpointID("a1b2c3d4e5f6")
require.NoError(t, store.WriteCommitted(ctx, checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
981 unmodified lines
`{"type":"user","message":{"content":[{"type":"text","text":"old prompt before checkpoint"}]}}` + "\n" +
`{"type":"user","message":{"content":[{"type":"text","text":"scoped prompt for checkpoint"}]}}` + "\n",
)
require.NoError(t, checkpoint.NewGitStore(repo).WriteCommitted(context.Background(), checkpoint.WriteCommittedOptions{
require.NoError(t, checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs()).WriteCommitted(context.Background(), checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: "session-v1",
Strategy: "manual-commit",
57 unmodified lines
cpID := id.MustCheckpointID("ab12ab12ab12")
ctx := context.Background()
require.NoError(t, checkpoint.NewGitStore(repo).WriteCommitted(ctx, checkpoint.WriteCommittedOptions{
require.NoError(t, checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs()).WriteCommitted(ctx, checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: "session-v1-only-generate",
Strategy: "manual-commit",
29 unmodified lines
))
ctx := context.Background()
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
originalGet := getSummaryAgent
originalCLI := isSummaryCLIAvailable
25 unmodified lines
}
cpID := id.MustCheckpointID("cd12cd12cd12")
require.NoError(t, checkpoint.NewGitStore(repo).WriteCommitted(ctx, checkpoint.WriteCommittedOptions{
require.NoError(t, checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs()).WriteCommitted(ctx, checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: "session-v1-mode-generate",
Strategy: "manual-commit",
67 unmodified lines
return &checkpoint.Summary{Intent: "selected v1 intent", Outcome: "selected v1 outcome"}, nil
}
v1Store := checkpoint.NewGitStore(repo)
v1Store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
cpID := id.MustCheckpointID("aabbccddeeff")
ctx := context.Background()
70 unmodified lines
return &checkpoint.Summary{Intent: "generated v1.1 intent", Outcome: "generated v1.1 outcome"}, nil
}
v1Store := checkpoint.NewGitStore(repo)
v1Store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
cpID := id.MustCheckpointID("bbccddee1122")
ctx := context.Background()
54 unmodified lines
cpID := id.MustCheckpointID("e1e2e3e4e5e6")
ctx := context.Background()
v1Store := checkpoint.NewGitStore(repo)
v1Store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
rawTranscript := []byte(
`{"type":"user","message":{"content":[{"type":"text","text":"raw fallback prompt"}]}}` + "\n" +
42 unmodified lines
0o644,
))
v1Store := checkpoint.NewGitStore(repo)
v1Store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
cpID := id.MustCheckpointID("e2e3e4e5e6e7")
ctx := context.Background()
35 unmodified lines
})
require.NoError(t, err)
v1Store := checkpoint.NewGitStore(repo)
v1Store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
ctx := context.Background()
transcript := []byte(`{"type":"user","message":{"content":[{"type":"text","text":"hello"}]}}` + "\n")
8 unmodified lines
AuthorEmail: "t@t.com",
}))
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
results, err := store.ListCommitted(ctx)
require.NoError(t, err)
1110 unmodified lines
}
// Create first checkpoint (baseline copy) - this one gets filtered out
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
baseCommit := initialCommit.String()[:7]
_, err = store.WriteTemporary(context.Background(), checkpoint.WriteTemporaryOptions{
SessionID: sessionID,
116 unmodified lines
}
}
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
baseCommit := initialCommit.String()[:7]
writeCheckpoints := func(sessionID, worktreeID string) {
1944 unmodified lines
}
// Write committed checkpoint metadata so getBranchCheckpoints can find it
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
if err := store.WriteCommitted(context.Background(), checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: "test-session",
61 unmodified lines
}
expectedPrompt := "Refactor the authentication module to use JWT tokens"
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
if err := store.WriteCommitted(context.Background(), checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: "2026-02-27-test-session",
65 unmodified lines
require.NoError(t, err)
cpID := id.MustCheckpointID("bbcc33445566")
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
for _, sessionID := range []string{"older-session-aaaa", "latest-session-bbbb"} {
require.NoError(t, store.WriteCommitted(context.Background(), checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
Mcmd/entire/cli/explain_test.go+20/-20
51 unmodified lines
52
53
54
55
55
56
57
58
51 unmodified lines
return false, false, ""
}
defer repo.Close()
store := checkpoint.NewCommittedReadStore(ctx, repo)
store := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx))
summary, err := checkpoint.ReadCommittedCheckpoint(ctx, store, cpID)
if err != nil || summary == nil {
logging.Debug(ctx, "head checkpoint flags: resolve checkpoint summary",
Mcmd/entire/cli/head_checkpoint_flags.go+1/-1
46 unmodified lines
47
48
49
50
50
51
52
53
46 unmodified lines
func writeHeadCheckpointWithFlags(t *testing.T, repo *git.Repository, hasReview, hasInvestigation bool) id.CheckpointID {
t.Helper()
cpID := id.MustCheckpointID("aabbccdd1122")
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
require.NoError(t, store.WriteCommitted(context.Background(), checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: "head-flags-session",
Mcmd/entire/cli/head_checkpoint_flags_test.go+1/-1
186 unmodified lines
187
188
189
190
190
191
192
193
194
193
194
195
196
197
198
7 unmodified lines
206
207
208
208
209
210
211
212
15 unmodified lines
228
229
230
230
231
232
233
234
67 unmodified lines
302
303
304
304
305
306
307
307
308
309
310
311
7 unmodified lines
319
320
321
321
322
323
324
325
323
326
327
325
328
329
330
331
332
333
331
334
335
336
337
6 unmodified lines
344
345
346
344
347
348
349
350
17 unmodified lines
368
369
370
368
371
372
373
374
15 unmodified lines
390
391
392
390
393
394
395
396
11 unmodified lines
408
409
410
408
411
412
413
414
181 unmodified lines
596
597
598
596
597
599
600
601
602
603
604
605
602
606
607
608
609
606
607
610
611
612
613
614
26 unmodified lines
641
642
643
640
644
645
646
647
12 unmodified lines
660
661
662
659
660
663
664
665
666
667
10 unmodified lines
678
679
680
677
681
682
683
684
25 unmodified lines
710
711
712
709
710
711
712
713
714
715
716
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
721
722
728
729
730
731
732
112 unmodified lines
845
846
847
841
848
849
850
851
186 unmodified lines
checkpointID := result.checkpointIDs[0]
var metadata *strategy.CheckpointInfo
store := checkpoint.NewCommittedReadStore(ctx, repo)
store := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx))
store.SetBlobFetcher(FetchBlobsByHash)
if store.CommittedReadRef() == plumbing.NewBranchReferenceName(paths.MetadataBranchName) {
promoteRemoteTrackingMetadataBranch(ctx, repo)
refs := store.Refs()
if refs.Read == refs.Primary && refs.PrimaryFetchableFromOrigin() {
promoteRemoteTrackingPrimary(ctx, repo, refs)
}
// Multiple checkpoints (squash merge): resolve latest by CreatedAt timestamp.
7 unmodified lines
)
fmt.Fprintf(w, "Found %d checkpoints for commit %s but metadata is not available\n",
len(result.checkpointIDs), result.commitHash[:7])
return checkRemoteMetadata(ctx, w, errW, result.checkpointIDs[0], store.CommittedReadRef())
return checkRemoteMetadata(ctx, w, errW, result.checkpointIDs[0], store.Refs())
}
skipped := len(result.checkpointIDs) - 1
fmt.Fprintf(w, "Found %d checkpoints for commit %s, resuming from the latest (%d older checkpoints skipped)\n",
15 unmodified lines
slog.String("checkpoint_id", checkpointID.String()),
slog.String("error", storeErr.Error()),
)
return checkRemoteMetadata(ctx, w, errW, checkpointID, store.CommittedReadRef())
return checkRemoteMetadata(ctx, w, errW, checkpointID, store.Refs())
}
}
67 unmodified lines
func readCheckpointInfoFromRef(
ctx context.Context,
repo *git.Repository,
committedReadRef plumbing.ReferenceName,
refs checkpoint.CommittedRefs,
checkpointID id.CheckpointID,
) (*strategy.CheckpointInfo, error) {
store := checkpoint.NewGitStoreWithRef(repo, committedReadRef)
store := checkpoint.NewGitStore(repo, refs)
store.SetBlobFetcher(FetchBlobsByHash)
return readCheckpointInfoFromStore(ctx, store, checkpointID)
}
7 unmodified lines
func getMetadataTree(ctx context.Context) (*object.Tree, *git.Repository, error) {
logCtx := logging.WithComponent(ctx, "resume.getMetadataTree")
// Helper to log ref hash for a repo's metadata branch
refs := checkpoint.ResolveCommittedRefs(ctx)
// Helper to log ref hash for a repo's primary metadata ref
logRefHash := func(repo *git.Repository, source string) {
ref, refErr := repo.Reference(plumbing.NewBranchReferenceName("entire/checkpoints/v1"), true)
ref, refErr := repo.Reference(refs.Primary, true)
if refErr != nil {
logging.Debug(logCtx, "metadata branch ref not found",
logging.Debug(logCtx, "primary metadata ref not found",
slog.String("source", source),
slog.String("error", refErr.Error()),
)
return
}
logging.Debug(logCtx, "metadata branch ref resolved",
logging.Debug(logCtx, "primary metadata ref resolved",
slog.String("source", source),
slog.String("ref_hash", ref.Hash().String()),
)
6 unmodified lines
freshRepo, freshErr := openRepository(ctx)
if freshErr == nil {
logRefHash(freshRepo, "checkpoint-remote")
metadataTree, treeErr := strategy.GetMetadataRefTree(freshRepo, plumbing.NewBranchReferenceName(paths.MetadataBranchName))
metadataTree, treeErr := strategy.GetMetadataRefTree(freshRepo, refs.Primary)
if treeErr == nil {
logging.Debug(logCtx, "metadata tree obtained via checkpoint remote fetch",
slog.String("tree_hash", metadataTree.Hash.String()),
17 unmodified lines
freshRepo, repoErr := openRepository(ctx)
if repoErr == nil {
logRefHash(freshRepo, "treeless-fetch")
metadataTree, treeErr := strategy.GetMetadataRefTree(freshRepo, plumbing.NewBranchReferenceName(paths.MetadataBranchName))
metadataTree, treeErr := strategy.GetMetadataRefTree(freshRepo, refs.Primary)
if treeErr == nil {
logging.Debug(logCtx, "metadata tree obtained via treeless fetch",
slog.String("tree_hash", metadataTree.Hash.String()),
15 unmodified lines
localRepo, repoErr := openRepository(ctx)
if repoErr == nil {
logRefHash(localRepo, "local")
metadataTree, err := strategy.GetMetadataRefTree(localRepo, plumbing.NewBranchReferenceName(paths.MetadataBranchName))
metadataTree, err := strategy.GetMetadataRefTree(localRepo, refs.Primary)
if err == nil {
logging.Debug(logCtx, "metadata tree obtained from local branch",
slog.String("tree_hash", metadataTree.Hash.String()),
11 unmodified lines
freshRepo, repoErr := openRepository(ctx)
if repoErr == nil {
logRefHash(freshRepo, "full-fetch")
metadataTree, treeErr := strategy.GetMetadataRefTree(freshRepo, plumbing.NewBranchReferenceName(paths.MetadataBranchName))
metadataTree, treeErr := strategy.GetMetadataRefTree(freshRepo, refs.Primary)
if treeErr == nil {
logging.Debug(logCtx, "metadata tree obtained via full fetch",
slog.String("tree_hash", metadataTree.Hash.String()),
181 unmodified lines
return confirmed, nil
}
// checkRemoteMetadata checks if v1 checkpoint metadata exists on the remote and
// fetches it if available. Custom committed read refs are local-only.
// checkRemoteMetadata checks if checkpoint metadata exists on the remote and
// fetches it if available. Skips when reads don't target a ref origin tracks
// (e.g. the local-only v1.1 mirror).
func checkRemoteMetadata(
ctx context.Context,
w, errW io.Writer,
checkpointID id.CheckpointID,
committedReadRef plumbing.ReferenceName,
refs checkpoint.CommittedRefs,
) error {
logCtx := logging.WithComponent(ctx, "resume.checkRemoteMetadata")
if committedReadRef != plumbing.NewBranchReferenceName(paths.MetadataBranchName) {
fmt.Fprintf(errW, "Checkpoint '%s' found in commit but metadata is not available in %s.\n", checkpointID, committedReadRef)
if refs.Read != refs.Primary || !refs.PrimaryFetchableFromOrigin() {
fmt.Fprintf(errW, "Checkpoint '%s' found in commit but metadata is not available in %s.\n", checkpointID, refs.Read)
fmt.Fprintf(errW, "This ref is local-only. Try: entire explain %s\n", checkpointID)
return nil
}
26 unmodified lines
)
} else {
defer freshRepo.Close()
metadata, err := readCheckpointInfoFromRef(ctx, freshRepo, committedReadRef, checkpointID)
metadata, err := readCheckpointInfoFromRef(ctx, freshRepo, refs, checkpointID)
if err != nil {
logging.Debug(logCtx, "checkpoint remote: fetch succeeded but checkpoint metadata read failed",
slog.String("checkpoint_id", checkpointID.String()),
12 unmodified lines
}
// Fall back to origin's remote-tracking branch
promoteRemoteTrackingMetadataBranch(ctx, repo)
metadata, metadataErr := readCheckpointInfoFromRef(ctx, repo, committedReadRef, checkpointID)
promoteRemoteTrackingPrimary(ctx, repo, refs)
metadata, metadataErr := readCheckpointInfoFromRef(ctx, repo, refs, checkpointID)
if metadataErr == nil {
return resumeSession(ctx, w, errW, metadata, false)
}
10 unmodified lines
)
} else {
defer freshRepo.Close()
metadata, err := readCheckpointInfoFromRef(ctx, freshRepo, committedReadRef, checkpointID)
metadata, err := readCheckpointInfoFromRef(ctx, freshRepo, refs, checkpointID)
if err != nil {
logging.Debug(logCtx, "origin metadata fetch succeeded but checkpoint metadata read failed",
slog.String("checkpoint_id", checkpointID.String()),
25 unmodified lines
return nil
}
// promoteRemoteTrackingMetadataBranch advances the local entire/checkpoints/v1
// ref to match origin's remote-tracking ref. Without this, callers reading
// checkpoint metadata via the local ref miss checkpoints already fetched into
// refs/remotes/origin/...: the committed-checkpoint store only falls back to
// origin/... when the local ref is *missing*, not when it's behind.
func promoteRemoteTrackingMetadataBranch(ctx context.Context, repo *git.Repository) {
localRefName := plumbing.NewBranchReferenceName(paths.MetadataBranchName)
remoteRef, err := repo.Reference(plumbing.NewRemoteReferenceName("origin", paths.MetadataBranchName), true)
// promoteRemoteTrackingPrimary advances the local primary ref to match origin's
// remote-tracking ref. Without this, callers reading checkpoint metadata via
// the local ref miss checkpoints already fetched into refs/remotes/origin/...:
// the committed-checkpoint store only falls back to origin/... when the local
// ref is *missing*, not when it's behind. No-op when Primary isn't in Push
// (no remote-tracking ref exists).
func promoteRemoteTrackingPrimary(ctx context.Context, repo *git.Repository, refs checkpoint.CommittedRefs) {
if !refs.PrimaryFetchableFromOrigin() {
return
}
remoteRef, err := repo.Reference(plumbing.NewRemoteReferenceName("origin", refs.Primary.Short()), true)
if err != nil {
return
}
if err := strategy.SafelyAdvanceLocalRef(ctx, repo, localRefName, remoteRef.Hash()); err != nil {
logging.Debug(ctx, "failed to promote remote-tracking metadata branch",
if err := strategy.SafelyAdvanceLocalRef(ctx, repo, refs.Primary, remoteRef.Hash()); err != nil {
logging.Debug(ctx, "failed to promote remote-tracking primary ref",
slog.String("error", err.Error()),
)
}
112 unmodified lines
return fmt.Errorf("failed to open repository: %w", repoErr)
}
defer repo.Close()
store := checkpoint.NewCommittedReadStore(ctx, repo)
store := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx))
store.SetBlobFetcher(FetchBlobsByHash)
logContent, _, err := checkpoint.ReadRawSessionLogForCheckpoint(ctx, store, checkpointID)
if err != nil {
Mcmd/entire/cli/resume.go+42/-35
528 unmodified lines
529
530
531
532
532
533
534
535
75 unmodified lines
611
612
613
614
614
615
616
617
20 unmodified lines
638
639
640
641
641
642
643
644
58 unmodified lines
703
704
705
706
706
707
708
709
56 unmodified lines
766
767
768
769
769
770
771
772
197 unmodified lines
970
971
972
973
973
974
975
976
107 unmodified lines
1084
1085
1086
1087
1087
1088
1089
1090
20 unmodified lines
1111
1112
1113
1114
1114
1115
1116
1117
40 unmodified lines
1158
1159
1160
1161
1161
1162
1163
1164
48 unmodified lines
1213
1214
1215
1216
1216
1217
1218
1219
19 unmodified lines
1239
1240
1241
1242
1242
1243
1244
1245
528 unmodified lines
) {
t.Helper()
if err := checkpoint.NewGitStore(repo).WriteCommitted(context.Background(), checkpoint.WriteCommittedOptions{
if err := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs()).WriteCommitted(context.Background(), checkpoint.WriteCommittedOptions{
CheckpointID: checkpointID,
SessionID: sessionID,
CreatedAt: createdAt,
75 unmodified lines
// Pass checkpoint IDs in reverse chronological order (newest first),
// simulating git CLI squash merge trailer order.
reverseOrderIDs := []id.CheckpointID{cpID3, cpID2, cpID1}
reader := checkpoint.NewGitStore(repo)
reader := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
latest, err := resolveLatestCheckpoint(context.Background(), reader, reverseOrderIDs)
if err != nil {
t.Fatalf("resolveLatestCheckpoint() error = %v", err)
20 unmodified lines
t.Chdir(tmpDir)
repo, _, _ := setupResumeTestRepo(t, tmpDir, false)
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
cpID := id.MustCheckpointID("112233445566")
ctx := context.Background()
oldCreatedAt := time.Date(2025, 1, 1, 10, 0, 0, 0, time.UTC)
58 unmodified lines
targetID := id.MustCheckpointID("aa11bb22cc33")
writeCommittedResumeCheckpoint(t, repo, targetID, "session-v1-target", time.Date(2025, 1, 1, 10, 0, 0, 0, time.UTC))
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
latest, err := resolveLatestCheckpoint(context.Background(), store, []id.CheckpointID{targetID})
if err != nil {
56 unmodified lines
staleV1ID := id.MustCheckpointID("d1d2d3d4d5d6")
writeCommittedResumeCheckpoint(t, repo, staleV1ID, "session-stale-v1", time.Date(2025, 1, 3, 10, 0, 0, 0, time.UTC))
store := checkpoint.NewCommittedReadStore(context.Background(), repo)
store := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(context.Background()))
store.SetBlobFetcher(FetchBlobsByHash)
_, err := resolveLatestCheckpoint(context.Background(), store, []id.CheckpointID{staleV1ID})
197 unmodified lines
sessionID := "resume-v1-fallback-session"
raw := []byte(`{"type":"user","message":{"content":[{"type":"text","text":"resume v1 fallback"}]}}` + "\n")
v1Store := checkpoint.NewGitStore(repo)
v1Store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
if err := v1Store.WriteCommitted(ctx, checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: sessionID,
107 unmodified lines
// Call checkRemoteMetadata - should find metadata on the remote tree and
// attempt to resume, but fail because the test checkpoint has no agent field.
err = checkRemoteMetadata(context.Background(), os.Stdout, os.Stderr, checkpointID, plumbing.NewBranchReferenceName(paths.MetadataBranchName))
err = checkRemoteMetadata(context.Background(), os.Stdout, os.Stderr, checkpointID, checkpoint.DefaultV1Refs())
if err == nil {
t.Error("checkRemoteMetadata() should return error when agent is missing from metadata")
} else if !strings.Contains(err.Error(), "failed to resolve agent") {
20 unmodified lines
os.Stdout,
os.Stderr,
id.MustCheckpointID("aaa111bbb222"),
plumbing.NewBranchReferenceName(paths.MetadataBranchName),
checkpoint.DefaultV1Refs(),
)
if err != nil {
t.Errorf("checkRemoteMetadata() returned error when no remote branch: %v", err)
40 unmodified lines
os.Stdout,
os.Stderr,
id.MustCheckpointID("abcd12345678"),
plumbing.NewBranchReferenceName(paths.MetadataBranchName),
checkpoint.DefaultV1Refs(),
)
if err != nil {
t.Errorf("checkRemoteMetadata() returned error for missing checkpoint: %v", err)
48 unmodified lines
_ = createCheckpointOnMetadataBranch(t, repo, "2025-01-01-test-session-uuid")
descendantHash := makeLocalMetadataBranchStale(t, repo, initialHash)
promoteRemoteTrackingMetadataBranch(context.Background(), repo)
promoteRemoteTrackingPrimary(context.Background(), repo, checkpoint.DefaultV1Refs())
if got := readMetadataBranchHash(t, repo); got != descendantHash {
t.Errorf("local should be fast-forwarded to remote-tracking ref: got %s, want %s", got, descendantHash)
19 unmodified lines
rawTranscript := []byte(`{"type":"user","message":{"content":[{"type":"text","text":"hi"}]}}` + "\n")
// Agent must be set so RestoreLogsOnly can resolve a session-write target.
v1Store := checkpoint.NewGitStore(repo)
v1Store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
if err := v1Store.WriteCommitted(ctx, checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: "2025-01-01-test-session-uuid",
Mcmd/entire/cli/resume_test.go+11/-11
97 unmodified lines
98
99
100
101
101
102
103
104
97 unmodified lines
return ""
}
defer repo.Close()
store := checkpoint.NewCommittedReadStore(ctx, repo)
store := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx))
var lines []string
seen := map[checkpointid.CheckpointID]bool{}
Mcmd/entire/cli/review_context.go+1/-1
424 unmodified lines
425
426
427
428
428
429
430
431
424 unmodified lines
t.Fatalf("open repo: %v", err)
}
cpID := checkpointid.MustCheckpointID(checkpointID)
err = checkpoint.NewGitStore(repo).WriteCommitted(context.Background(), checkpoint.WriteCommittedOptions{
err = checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs()).WriteCommitted(context.Background(), checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: checkpointID,
Strategy: "manual-commit",
Mcmd/entire/cli/review_context_test.go+1/-1
692 unmodified lines
693
694
695
696
696
697
698
699
41 unmodified lines
741
742
743
744
744
745
746
747
692 unmodified lines
}
defer repo.Close()
store := checkpoint.NewCommittedReadStore(ctx, repo)
store := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx))
content, returnedSessionID, err := checkpoint.ReadRawSessionLogForCheckpoint(ctx, store, cpID)
if err != nil {
return "", fmt.Errorf("failed to get session log: %w", err)
41 unmodified lines
}
// Get transcript from shadow branch commit tree
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx))
content, err := store.GetTranscriptFromCommit(ctx, hash, metadataDir, agent.Type())
if err != nil {
return "", fmt.Errorf("failed to get transcript from shadow branch: %w", err)
Mcmd/entire/cli/rewind.go+2/-2
1889 unmodified lines
1890
1891
1892
1893
1893
1894
1895
1896
1889 unmodified lines
cpHex = "abcdef013333"
}
cpID := id.MustCheckpointID(cpHex)
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
if err := store.WriteCommitted(context.Background(), checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: "status-test-session",
Mcmd/entire/cli/status_test.go+1/-1
489 unmodified lines
490
491
492
493
493
494
495
496
56 unmodified lines
553
554
555
556
556
557
558
559
489 unmodified lines
const sessionID = "test-session-v11-orphan"
cpID := id.MustCheckpointID("b2c3d4e5f6a1")
require.NoError(t, checkpoint.NewGitStore(repo).WriteCommitted(t.Context(), checkpoint.WriteCommittedOptions{
require.NoError(t, checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs()).WriteCommitted(t.Context(), checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: sessionID,
Strategy: "manual-commit",
56 unmodified lines
// Two sequential writes with the same checkpoint ID produce a multi-session
// checkpoint: the second write archives the first session under <sharded>/0
// and lists both IDs in SessionIDs.
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
for _, sid := range []string{archivedSessionID, latestSessionID} {
require.NoError(t, store.WriteCommitted(t.Context(), checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
Mcmd/entire/cli/strategy/clean_test.go+2/-2
168 unmodified lines
169
170
171
172
172
173
174
175
168 unmodified lines
}
// Get all committed checkpoints from the configured read ref to find which sessions have checkpoints
cpStore := checkpoint.NewCommittedReadStore(ctx, repo)
cpStore := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx))
sessionsWithCheckpoints := make(map[string]bool)
checkpoints, listErr := cpStore.ListCommitted(ctx)
Mcmd/entire/cli/strategy/cleanup.go+1/-1
304 unmodified lines
305
306
307
308
308
309
310
311
304 unmodified lines
// Warn (once per process) if metadata branches are disconnected
WarnIfMetadataDisconnected()
store := checkpoint.NewCommittedReadStore(ctx, repo)
store := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx))
committed, err := store.ListCommitted(ctx)
if err != nil {
return nil, fmt.Errorf("failed to list committed checkpoints: %w", err)
Mcmd/entire/cli/strategy/common.go+1/-1
48 unmodified lines
49
50
51
52
53
54
52
53
54
55
56
57
57
58
59
60
58
59
60
61
62
62
63
64
65
48 unmodified lines
return store
}
// getCheckpointStore returns the v1-branch store used by write paths.
func (s *ManualCommitStrategy) getCheckpointStore(repo *git.Repository) *checkpoint.GitStore {
return s.withBlobFetcher(checkpoint.NewGitStore(repo))
// getCheckpointStore returns a store bound to the resolved committed-metadata
// topology. Writes target refs.Primary; reads target refs.Read.
func (s *ManualCommitStrategy) getCheckpointStore(ctx context.Context, repo *git.Repository) *checkpoint.GitStore {
return s.withBlobFetcher(checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx)))
}
// getCommittedReadStore returns a store for reading committed checkpoints, bound
// to the read ref for the active checkpoints_version (the local-only v1.1 custom
// ref when opted in, else the v1 branch). Use this for committed reads;
// getCheckpointStore is for writes.
// getCommittedReadStore returns a store for reading committed checkpoints.
// Equivalent to getCheckpointStore today; kept as a separate name to mark
// read-path call sites.
func (s *ManualCommitStrategy) getCommittedReadStore(ctx context.Context, repo *git.Repository) *checkpoint.GitStore {
return s.withBlobFetcher(checkpoint.NewCommittedReadStore(ctx, repo))
return s.getCheckpointStore(ctx, repo)
}
// NewManualCommitStrategy creates a new manual-commit strategy instance.
Mcmd/entire/cli/strategy/manual_commit.go+8/-8
67 unmodified lines
68
69
70
71
71
72
73
74
109 unmodified lines
184
185
186
187
187
188
189
190
67 unmodified lines
defer repo.Close()
WarnIfMetadataDisconnected()
store := s.getCheckpointStore(repo)
store := s.getCheckpointStore(ctx, repo)
summary, err := cpkg.ReadCommittedCheckpoint(ctx, store, checkpointID)
if err != nil {
109 unmodified lines
return skipped, nil
}
store := s.getCheckpointStore(repo)
store := s.getCheckpointStore(ctx, repo)
// Get author info
authorName, authorEmail := GetGitAuthorFromRepo(repo)
Mcmd/entire/cli/strategy/manual_commit_condensation.go+2/-2
51 unmodified lines
52
53
54
55
55
56
57
58
123 unmodified lines
182
183
184
185
185
186
187
188
51 unmodified lines
}
migrateSpan.End()
store := s.getCheckpointStore(repo)
store := s.getCheckpointStore(ctx, repo)
shadowBranchName := checkpoint.ShadowBranchNameForCommit(state.BaseCommit, state.WorktreeID)
branchExisted := store.ShadowBranchExists(state.BaseCommit, state.WorktreeID)
123 unmodified lines
return fmt.Errorf("failed to check/migrate shadow branch: %w", err)
}
store := s.getCheckpointStore(repo)
store := s.getCheckpointStore(ctx, repo)
shadowBranchName := checkpoint.ShadowBranchNameForCommit(state.BaseCommit, state.WorktreeID)
branchExisted := store.ShadowBranchExists(state.BaseCommit, state.WorktreeID)
Mcmd/entire/cli/strategy/manual_commit_git.go+2/-2
1060 unmodified lines
1061
1062
1063
1064
1064
1065
1066
1067
1702 unmodified lines
2770
2771
2772
2773
2773
2774
2775
2776
109 unmodified lines
2886
2887
2888
2889
2889
2890
2891
2892
1060 unmodified lines
repoDir string,
) error {
logCtx := logging.WithComponent(ctx, "attribution")
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx))
summary, err := store.ReadCommitted(ctx, checkpointID)
if err != nil {
1702 unmodified lines
prompts[i] = redact.String(p)
}
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx))
precomputed := precomputeTranscriptBlobsForFinalize(logCtx, repo, redactedTranscript, state)
109 unmodified lines
) {
logCtx := logging.WithComponent(ctx, "checkpoint")
start := time.Now()
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.ResolveCommittedRefs(ctx))
// Don't include metadata directory in carry-forward. The carry-forward branch
// only needs to preserve file content for comparison - not the transcript.
Mcmd/entire/cli/strategy/manual_commit_hooks.go+3/-3
35 unmodified lines
36
37
38
39
39
40
41
42
594 unmodified lines
637
638
639
640
640
641
642
643
35 unmodified lines
}
defer repo.Close()
store := s.getCheckpointStore(repo)
store := s.getCheckpointStore(ctx, repo)
// Get current HEAD to find matching shadow branch
head, err := repo.Head()
594 unmodified lines
defer repo.Close()
WarnIfMetadataDisconnected()
store := cpkg.NewCommittedReadStore(ctx, repo)
store := cpkg.NewGitStore(repo, cpkg.ResolveCommittedRefs(ctx))
if s.blobFetcher != nil {
store.SetBlobFetcher(s.blobFetcher)
}
Mcmd/entire/cli/strategy/manual_commit_rewind.go+2/-2
484 unmodified lines
485
486
487
488
488
489
490
491
51 unmodified lines
543
544
545
546
546
547
548
549
2676 unmodified lines
3226
3227
3228
3229
3229
3230
3231
3232
210 unmodified lines
3443
3444
3445
3446
3446
3447
3448
3449
229 unmodified lines
3679
3680
3681
3682
3682
3683
3684
3685
108 unmodified lines
3794
3795
3796
3797
3797
3798
3799
3800
458 unmodified lines
4259
4260
4261
4262
4262
4263
4264
4265
484 unmodified lines
cpID := id.MustCheckpointID("a1b2c3d4e5f6")
const wantPrompt = "only-on-mirror"
require.NoError(t, checkpoint.NewGitStore(repo).WriteCommitted(t.Context(), checkpoint.WriteCommittedOptions{
require.NoError(t, checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs()).WriteCommitted(t.Context(), checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: "test-session-v11-rewind",
Strategy: "manual-commit",
51 unmodified lines
const earlierPrompt = "earlier-session-prompt"
// Earlier session carries the only usable prompt.
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
require.NoError(t, store.WriteCommitted(t.Context(), checkpoint.WriteCommittedOptions{
CheckpointID: cpID,
SessionID: "session-earlier",
2676 unmodified lines
}
// Verify the condensed content includes the second prompt
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
content, err := store.ReadLatestSessionContent(t.Context(), checkpointID)
if err != nil {
t.Fatalf("ReadLatestSessionContent() error = %v", err)
210 unmodified lines
}
// Verify condensed data on entire/checkpoints/v1 branch
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
content, err := store.ReadLatestSessionContent(t.Context(), checkpointID)
if err != nil {
t.Fatalf("ReadLatestSessionContent() error = %v", err)
229 unmodified lines
}
// Read condensed metadata
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
content, err := store.ReadLatestSessionContent(t.Context(), checkpointID)
if err != nil {
t.Fatalf("ReadLatestSessionContent() error = %v", err)
108 unmodified lines
t.Errorf("FilesTouched = %v, want [beta.txt]", result.FilesTouched)
}
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
content, err := store.ReadLatestSessionContent(t.Context(), checkpointID)
if err != nil {
t.Fatalf("ReadLatestSessionContent() error = %v", err)
458 unmodified lines
require.NoError(t, err, "redaction failure should not abort condensation")
require.NotNil(t, result)
store := s.getCheckpointStore(repo)
store := s.getCheckpointStore(context.Background(), repo)
committed, err := store.ListCommitted(context.Background())
require.NoError(t, err)
Mcmd/entire/cli/strategy/manual_commit_test.go+7/-7
776 unmodified lines
777
778
779
780
780
781
782
783
575 unmodified lines
1359
1360
1361
1362
1362
1363
1364
1365
776 unmodified lines
require.NoError(t, err, "entire/checkpoints/v1 should exist after first condensation")
// Verify first condensation contains A.txt and B.txt
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
cpID1 := id.MustCheckpointID(checkpointID1)
summary1, err := store.ReadCommitted(context.Background(), cpID1)
require.NoError(t, err)
575 unmodified lines
"TurnCheckpointIDs should be cleared after HandleTurnEnd, even with errors")
// Verify the 2 valid checkpoints were finalized with the full transcript
store := checkpoint.NewGitStore(repo)
store := checkpoint.NewGitStore(repo, checkpoint.DefaultV1Refs())
for _, cpIDStr := range []string{"a1b2c3d4e5f6", "b2c3d4e5f6a1"} {
cpID := id.MustCheckpointID(cpIDStr)
content, readErr := store.ReadSessionContent(context.Background(), cpID, 0)
Mcmd/entire/cli/strategy/phase_postcommit_test.go+2/-2
603 unmodified lines
604
605
606
607
607
608
609
610
603 unmodified lines
) {
t.Helper()
err := cpkg.NewGitStore(repo).WriteCommitted(context.Background(), cpkg.WriteCommittedOptions{
err := cpkg.NewGitStore(repo, cpkg.DefaultV1Refs()).WriteCommitted(context.Background(), cpkg.WriteCommittedOptions{
CheckpointID: checkpointID,
SessionID: sessionID,
CreatedAt: createdAt,
Mcmd/entire/cli/strategy/rewind_test.go+1/-1