Add git-refs per-checkpoint checkpoint backend · Entire
Add git-refs per-checkpoint checkpoint backend
878ac88·
Soph·2w ago·11 files·+1,143 added/-14 removed
Second slice of #1471: a git-backed store that keeps one commit per
refs/entire/checkpoints/
- refs_store.go: gitRefsStore implements PersistentStore over per-checkpoint refs (orphan-then-parented history, stamps refs-v1, no Vercel merge, List enumerates local refs, optional AuthorReader). Reads resolve a ref → commit tree and use shared read helpers; writes build the subtree via the embedded treeWriter. - Share the tree-read helpers: the git-branch reader's Read/ReadSession now delegate to readSummaryFromCheckpointTree / readSession*FromTree free functions (no behavior change) so both backends read the same way, just navigating to the tree differently. - registry: BackendTypeGitRefs ("git-refs") registered built-in with gitBacked:true + gitRefsBackendFactory; OpenEnv/OpenOptions gain RefFetcher; PrimaryIsRefs helper. - pushqueue.go: flock-protected JSONL push-discovery queue in the git common dir (Enqueue/Drain/Remove); gitRefsStore.setRef enqueues best-effort. (Pre-push consumption lands in the next commit.) - CheckpointVersionRefsV1 = "refs-v1".
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Sessions
a4baf5553823View transcript
Changes
11
api/checkpoint
Merrors.go+6
cmd/entire/cli/checkpoint
Maliases.go+3
- Mfetching_tree.go+6
- Mopen.go+14/-1
- Mpersistent.go+27/-11
- Apushqueue.go+200
- Apushqueue_test.go+109
- Arefs_store.go+381
- Arefs_store_seam_test.go+99
- Arefs_store_test.go+269
- Mregistry.go+29/-2
// CheckpointVersionBranchV1 identifies the branch-backed checkpoint metadata format. const CheckpointVersionBranchV1 = "branch-v1"
// CheckpointVersionRefsV1 identifies the per-checkpoint-ref checkpoint metadata
// format (one ref per checkpoint at refs/entire/checkpoints/
// CheckpointVersionBranchV1 identifies the branch-backed checkpoint metadata format. const CheckpointVersionBranchV1 = apicheckpoint.CheckpointVersionBranchV1
// CheckpointVersionRefsV1 identifies the per-checkpoint-ref checkpoint metadata format. const CheckpointVersionRefsV1 = apicheckpoint.CheckpointVersionRefsV1
// Sentinel errors (re-exported so errors.Is keeps working across packages). var ( ErrCheckpointNotFound = apicheckpoint.ErrCheckpointNotFound )
// BlobFetchFunc fetches missing blob objects by hash from a remote. type BlobFetchFunc func(ctx context.Context, hashes []plumbing.Hash) error
// RefFetchFunc fetches a single checkpoint ref from the remote into the local // ref of the same name. The git-refs store uses it to resolve a checkpoint ref // that is not present locally (e.g. written on another machine). The checkpoint // package cannot resolve the remote target itself, so the CLI layer injects it. type RefFetchFunc func(ctx context.Context, ref plumbing.ReferenceName) error
// FetchingTree wraps a git tree to automatically fetch missing blobs on demand. // After a treeless fetch (--filter=blob:none), tree objects are available locally // but blob objects are not. Each File() call checks whether the target blob
// fetching off. BlobFetcher BlobFetchFunc
// RefFetcher is the CLI-level on-demand checkpoint-ref fetcher, used by the // git-refs backend to resolve a checkpoint ref missing locally. nil leaves // reads local-only; ignored by the git-branch backend. RefFetcher RefFetchFunc
// Refs overrides the default committed-ref topology. A non-nil value wins, // e.g. attach pins reads to Primary via PrimaryAsRead(). Refs *PersistentRefs }
// PrimaryIsRefs reports whether the configured primary backend is the git-refs // per-checkpoint store. It centralizes the topology check so push/pre-push code // does not compare backend-type strings itself. A nil config (default) is the // git-branch backend, so this returns false. func PrimaryIsRefs(cfg *settings.CheckpointsConfig) bool { return cfg != nil && cfg.Primary.Type == BackendTypeGitRefs }
// Stores is the facade returned by Open: the persistent store plus the git-only // ephemeral (shadow-branch) capability and resolved committed-ref topology. type Stores struct {
// default git-branch backend with no mirrors, preserving default behavior. func Open(ctx context.Context, repo *git.Repository, opts OpenOptions) (*Stores, error) { refs := resolveOpenRefs(ctx, opts) env := OpenEnv{Repo: repo, BlobFetcher: opts.BlobFetcher, Refs: refs} env := OpenEnv{Repo: repo, BlobFetcher: opts.BlobFetcher, RefFetcher: opts.RefFetcher, Refs: refs}
cfg, err := settings.LoadCheckpointsConfig(ctx) if err != nil { return nil, nil //nolint:nilnil,nilerr // Checkpoint directory not found }
return readSummaryFromCheckpointTree(checkpointTree) }
// readSummaryFromCheckpointTree reads the root CheckpointSummary from a checkpoint
// tree (the tree holding metadata.json plus the numbered session dirs). It is
// shared by the git-branch store (which descends to
func (s *GitStore) ReadSessionPrompts(ctx context.Context, checkpointID id.CheckpointID, sessionIndex int) (string, error) {
// about reading from session trees. func readSessionContentFromTree(ctx context.Context, sessionTree *FetchingTree) (*SessionContent, error) { result := &SessionContent{}
// Read session-specific metadata (auto-fetches blob if needed) }
// List enumerates local checkpoint refs and reads each root summary, sorted most // recent first. Storage-level listing is local-refs-only for now (no remote // enumeration), matching the issue's first-version scope.
// GetCheckpointAuthor returns the author of the checkpoint ref's tip commit (the // most recent writer). Returns a zero Author when the ref is absent. func (s *gitRefsStore) GetCheckpointAuthor(ctx context.Context, checkpointID id.CheckpointID) (Author, error) { if err := ctx.Err(); err != nil { return Author{}, err //nolint:wrapcheck // Propagating context cancellation } ref, err := s.repo.Reference(RefName(checkpointID), true) if err != nil { return Author{}, nil //nolint:nilerr // no ref → unknown author } commit, err := s.repo.CommitObject(ref.Hash()) if err != nil { return Author{}, nil //nolint:nilerr // unreadable → unknown author } return Author{Name: commit.Author.Name, Email: commit.Author.Email}, nil }
"