Add git-refs per-checkpoint checkpoint backend · Entire
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/
- 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/
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 }