# Add git-refs per-checkpoint checkpoint backend

`040eac5`·

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/<shard>/<id> (tree root = checkpoint contents), sharing the treeWriter subtree core with the git-branch store.

- 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

12 unmodified lines

// 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/<shard>/<id>). The
// value follows the <family>-v<major> convention (cf. branch-v1) so
// checkpointpolicy.ParseFormat parses it.
const CheckpointVersionRefsV1 = "refs-v1"

Mapi/checkpoint/errors.go+6

// 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
)

Mcmd/entire/cli/checkpoint/persistent.go+27/-11

package checkpoint

import (
    "context"
)

// Push-discovery queue file names, kept in the git common dir so every worktree
// sharing the object store enqueues into one queue. The git-refs backend cannot
// push every local checkpoint ref at pre-push time (reads fetch refs too, and
// deleting them after push would hurt local workflows), so each write records
// the ref it touched here and pre-push drains + batch-pushes exactly those.
const (
    pushQueueFileName = "entire-checkpoint-push-queue.jsonl"
    pushQueueLockName = "entire-checkpoint-push-queue.lock"
)

// pushQueueEntry is one JSONL record: a checkpoint ref awaiting push.
type pushQueueEntry struct {
    Ref string `json:"ref"`
}

// PushQueue is a flock-protected JSONL list of checkpoint refs awaiting push,
// stored in the git common dir. Entries are removed only after a confirmed push
// (Remove), so an interrupted or failed push leaves them for the next pre-push.
// Duplicates are tolerated on disk and collapsed by Drain.
type PushQueue struct {
    dir string
}

// NewPushQueue returns the push queue rooted at gitCommonDir.
func NewPushQueue(gitCommonDir string) *PushQueue {
    return &PushQueue{dir: gitCommonDir}
}

func (q *PushQueue) queuePath() string { return filepath.Join(q.dir, pushQueueFileName) }
func (q *PushQueue) lockPath() string  { return filepath.Join(q.dir, pushQueueLockName) }

// Enqueue appends a ref to the queue. It is safe to enqueue a ref already
// present (or already pushed): Drain collapses duplicates and the batch push is
// idempotent. Enqueue takes the lock so concurrent writers never interleave a
// partial line.
func (q *PushQueue) Enqueue(ref plumbing.ReferenceName) error {
    // Implementation
}

// Drain returns the de-duplicated refs currently queued, in first-seen order. It
// does NOT remove them; call Remove after a confirmed push so a failed push
// retries next time. A missing queue file yields no refs.
func (q *PushQueue) Drain() ([]plumbing.ReferenceName, error) {
    // Implementation
}

// Remove deletes the given refs from the queue, preserving any entries appended
// after a Drain (e.g. a write that landed during the push). Called after a
// confirmed push.
func (q *PushQueue) Remove(refs []plumbing.ReferenceName) error {
    // Implementation
}

// readLocked parses the queue file into de-duplicated refs, preserving first-seen
// order. The caller must hold the lock.
func (q *PushQueue) readLocked() ([]plumbing.ReferenceName, error) {
    // Implementation
}

// writeFileAtomicInDir writes data to a temp file in dir and renames it over
// path, so a reader (under the lock) never sees a half-written queue.
func writeFileAtomicInDir(dir, path string, data []byte) error {
    // Implementation
}
