checkpoint

package
v0.5.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 19, 2026 License: MIT Imports: 33 Imported by: 0

Documentation

Overview

Package checkpoint provides types and interfaces for checkpoint storage.

A Checkpoint captures a point-in-time within a session, containing either full state (Temporary) or metadata with a commit reference (Committed).

See docs/architecture/sessions-and-checkpoints.md for the full domain model.

Index

Constants

View Source
const (
	// ShadowBranchPrefix is the prefix for shadow branches.
	ShadowBranchPrefix = "entire/"

	// ShadowBranchHashLength is the number of hex characters used in shadow branch names.
	// Shadow branches are named "entire/<hash>" using the first 7 characters of the commit hash.
	ShadowBranchHashLength = 7

	// WorktreeIDHashLength is the number of hex characters used for worktree ID hash.
	WorktreeIDHashLength = 6
)

Variables

View Source
var (
	// ErrCheckpointNotFound is returned when a checkpoint ID doesn't exist.
	ErrCheckpointNotFound = errors.New("checkpoint not found")

	// ErrNoTranscript is returned when a checkpoint exists but has no transcript.
	ErrNoTranscript = errors.New("no transcript found for checkpoint")
)

Errors returned by checkpoint operations.

Functions

func ApplyTreeChanges added in v0.4.8

func ApplyTreeChanges(
	repo *git.Repository,
	rootTreeHash plumbing.Hash,
	changes []TreeChange,
) (plumbing.Hash, error)

ApplyTreeChanges applies multiple file-level changes to a tree efficiently. Changes are grouped by directory and applied in a single recursive pass. Unchanged subdirectories retain their hashes — this is the key optimization over FlattenTree + BuildTreeFromEntries for sparse changes.

func BuildTreeFromEntries

func BuildTreeFromEntries(repo *git.Repository, entries map[string]object.TreeEntry) (plumbing.Hash, error)

BuildTreeFromEntries builds a proper git tree structure from flattened file entries. Exported for use by strategy package (push_common.go, session_test.go)

func CreateBlobFromContent

func CreateBlobFromContent(repo *git.Repository, content []byte) (plumbing.Hash, error)

CreateBlobFromContent creates a blob object from in-memory content. Exported for use by strategy package (session_test.go)

func CreateCommit added in v0.5.0

func CreateCommit(repo *git.Repository, treeHash, parentHash plumbing.Hash, message, authorName, authorEmail string) (plumbing.Hash, error)

CreateCommit creates a git commit object with the given tree, parent, message, and author. If parentHash is ZeroHash, the commit is created without a parent (orphan commit).

func FlattenTree

func FlattenTree(repo *git.Repository, tree *object.Tree, prefix string, entries map[string]object.TreeEntry) error

FlattenTree recursively flattens a tree into a map of full paths to entries.

func GetGitAuthorFromRepo added in v0.4.5

func GetGitAuthorFromRepo(repo *git.Repository) (name, email string)

GetGitAuthorFromRepo retrieves the git user.name and user.email, checking both the repository-local config and the global ~/.gitconfig.

func HashWorktreeID

func HashWorktreeID(worktreeID string) string

HashWorktreeID returns a short hash of the worktree identifier. Used to create unique shadow branch names per worktree.

func LookupSessionLog

func LookupSessionLog(ctx context.Context, cpID id.CheckpointID) ([]byte, string, error)

LookupSessionLog is a convenience function that opens the repository and retrieves a session log by checkpoint ID. This is the primary entry point for callers that don't already have a GitStore instance. Returns ErrCheckpointNotFound if the checkpoint doesn't exist. Returns ErrNoTranscript if the checkpoint exists but has no transcript.

func ParseShadowBranchName

func ParseShadowBranchName(branchName string) (commitPrefix, worktreeHash string, ok bool)

ParseShadowBranchName extracts the commit prefix and worktree hash from a shadow branch name. Input format: "entire/<commit[:7]>-<worktreeHash[:6]>" Returns (commitPrefix, worktreeHash, ok). Returns ("", "", false) if not a valid shadow branch.

func ShadowBranchNameForCommit

func ShadowBranchNameForCommit(baseCommit, worktreeID string) string

ShadowBranchNameForCommit returns the shadow branch name for a base commit hash and worktree identifier. The worktree ID should be empty for the main worktree or the internal git worktree name for linked worktrees. Format: entire/<commit[:7]>-<hash(worktreeID)[:6]>

func UpdateSubtree added in v0.4.8

func UpdateSubtree(
	repo *git.Repository,
	rootTreeHash plumbing.Hash,
	pathSegments []string,
	newEntries []object.TreeEntry,
	opts UpdateSubtreeOptions,
) (plumbing.Hash, error)

UpdateSubtree replaces or creates a subtree at the given path within an existing tree. It walks the tree path, replacing only the entries along the modified path. All sibling entries at each level retain their original hashes — no re-reading needed.

pathSegments is the directory path split into segments (e.g., ["a3", "b2c4d5e6f7"]). newEntries are the files/dirs to place at the leaf directory. Returns the new root tree hash.

Types

type Author

type Author struct {
	Name  string
	Email string
}

Author contains author information for a checkpoint.

type BlobFetchFunc added in v0.5.1

type BlobFetchFunc func(ctx context.Context, hashes []plumbing.Hash) error

BlobFetchFunc fetches missing blob objects by hash from a remote.

type BlobResolver added in v0.5.1

type BlobResolver struct {
	// contains filtered or unexported fields
}

BlobResolver checks blob existence and reads blobs from go-git's local object store (loose objects + packfiles). It performs no remote operations.

func NewBlobResolver added in v0.5.1

func NewBlobResolver(s storer.EncodedObjectStorer) *BlobResolver

NewBlobResolver creates a BlobResolver backed by the given object store.

func (*BlobResolver) HasBlob added in v0.5.1

func (r *BlobResolver) HasBlob(hash plumbing.Hash) bool

HasBlob returns true if the blob exists in the local object store. Checks both loose objects and packfile indices without reading blob content.

func (*BlobResolver) ReadBlob added in v0.5.1

func (r *BlobResolver) ReadBlob(hash plumbing.Hash) ([]byte, error)

ReadBlob reads a blob's content from the local object store. Returns plumbing.ErrObjectNotFound if the blob is not present locally.

type Checkpoint

type Checkpoint struct {
	// ID is the unique checkpoint identifier
	ID string

	// SessionID is the session this checkpoint belongs to
	SessionID string

	// Timestamp is when this checkpoint was created
	Timestamp time.Time

	// Type indicates temporary (full state) or committed (metadata only)
	Type Type

	// Message is a human-readable description of the checkpoint
	Message string
}

Checkpoint represents a save point within a session.

type CheckpointSummary

type CheckpointSummary struct {
	CLIVersion       string             `json:"cli_version,omitempty"`
	CheckpointID     id.CheckpointID    `json:"checkpoint_id"`
	Strategy         string             `json:"strategy"`
	Branch           string             `json:"branch,omitempty"`
	CheckpointsCount int                `json:"checkpoints_count"`
	FilesTouched     []string           `json:"files_touched"`
	Sessions         []SessionFilePaths `json:"sessions"`
	TokenUsage       *agent.TokenUsage  `json:"token_usage,omitempty"`
}

CheckpointSummary is the root-level metadata.json for a checkpoint. It contains aggregated statistics from all sessions and a map of session IDs to their file paths. Session-specific data (including initial_attribution) is stored in the session's subdirectory metadata.json.

Structure on entire/checkpoints/v1 branch:

<checkpoint-id[:2]>/<checkpoint-id[2:]>/
├── metadata.json         # This CheckpointSummary
├── 1/                    # First session
│   ├── metadata.json     # Session-specific CommittedMetadata
│   ├── full.jsonl
│   ├── prompt.txt
│   └── content_hash.txt
├── 2/                    # Second session
└── 3/                    # Third session...

type CodeLearning

type CodeLearning struct {
	Path    string `json:"path"`               // File path
	Line    int    `json:"line,omitempty"`     // Start line number
	EndLine int    `json:"end_line,omitempty"` // End line for ranges (optional)
	Finding string `json:"finding"`            // What was learned
}

CodeLearning captures a learning tied to a specific code location.

type CommittedInfo

type CommittedInfo struct {
	// CheckpointID is the stable 12-hex-char identifier
	CheckpointID id.CheckpointID

	// SessionID is the session identifier (most recent session for multi-session checkpoints)
	SessionID string

	// CreatedAt is when the checkpoint was created
	CreatedAt time.Time

	// CheckpointsCount is the total number of checkpoints across all sessions
	CheckpointsCount int

	// FilesTouched are files modified during all sessions
	FilesTouched []string

	// Agent identifies the agent that created this checkpoint
	Agent types.AgentType

	// IsTask indicates if this is a task checkpoint
	IsTask bool

	// ToolUseID is the tool use ID for task checkpoints
	ToolUseID string

	// Multi-session support
	SessionCount int      // Number of sessions (1 if single session)
	SessionIDs   []string // All session IDs that contributed
}

CommittedInfo contains summary information about a committed checkpoint.

type CommittedMetadata

type CommittedMetadata struct {
	CLIVersion       string          `json:"cli_version,omitempty"`
	CheckpointID     id.CheckpointID `json:"checkpoint_id"`
	SessionID        string          `json:"session_id"`
	Strategy         string          `json:"strategy"`
	CreatedAt        time.Time       `json:"created_at"`
	Branch           string          `json:"branch,omitempty"` // Branch where checkpoint was created (empty if detached HEAD)
	CheckpointsCount int             `json:"checkpoints_count"`
	FilesTouched     []string        `json:"files_touched"`

	// Agent identifies the agent that created this checkpoint (e.g., "Claude Code", "Cursor")
	Agent types.AgentType `json:"agent,omitempty"`

	// Model is the LLM model used during the session (e.g., "claude-sonnet-4-20250514")
	Model string `json:"model,omitempty"`

	// TurnID correlates checkpoints from the same agent turn.
	// When a turn's work spans multiple commits, each gets its own checkpoint
	// but they share the same TurnID for future aggregation/deduplication.
	TurnID string `json:"turn_id,omitempty"`

	// Task checkpoint fields (only populated for task checkpoints)
	IsTask    bool   `json:"is_task,omitempty"`
	ToolUseID string `json:"tool_use_id,omitempty"`

	// Transcript position at checkpoint start - tracks what was added during this checkpoint
	TranscriptIdentifierAtStart string `json:"transcript_identifier_at_start,omitempty"` // Last identifier when checkpoint started (UUID for Claude, message ID for Gemini)
	CheckpointTranscriptStart   int    `json:"checkpoint_transcript_start,omitempty"`    // Transcript line offset at start of this checkpoint's data

	// Deprecated: Use CheckpointTranscriptStart instead. Written for backward compatibility with older CLI versions.
	TranscriptLinesAtStart int `json:"transcript_lines_at_start,omitempty"`

	// Token usage for this checkpoint
	TokenUsage *agent.TokenUsage `json:"token_usage,omitempty"`

	// SessionMetrics contains hook-provided session metrics (duration, turns, context usage).
	// Populated for agents that provide these metrics via hooks (e.g., Cursor).
	SessionMetrics *SessionMetrics `json:"session_metrics,omitempty"`

	// AI-generated summary of the checkpoint
	Summary *Summary `json:"summary,omitempty"`

	// InitialAttribution is line-level attribution calculated at commit time
	InitialAttribution *InitialAttribution `json:"initial_attribution,omitempty"`
}

CommittedMetadata contains the metadata stored in metadata.json for each checkpoint.

func (CommittedMetadata) GetTranscriptStart added in v0.3.13

func (m CommittedMetadata) GetTranscriptStart() int

GetTranscriptStart returns the transcript line offset at which this checkpoint's data begins. Returns 0 for new checkpoints (start from beginning). For data written by older CLI versions, falls back to the deprecated TranscriptLinesAtStart field.

type FetchingTree added in v0.5.1

type FetchingTree struct {
	// contains filtered or unexported fields
}

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 exists locally and fetches it from the remote if missing, using FindEntry to locate the blob hash without resolving the blob itself.

Because go-git's ObjectStorage caches the packfile index and never refreshes it, blobs fetched by external git commands (e.g. git fetch-pack) may not be visible to go-git's storer. As a fallback, File() reads the blob via "git cat-file" which always sees the current on-disk object store.

For best performance, call PreFetch before reading files. PreFetch walks the tree, identifies locally-missing blobs, and batch-fetches them in a single network round-trip instead of one fetch per File() miss.

func NewFetchingTree added in v0.5.1

func NewFetchingTree(ctx context.Context, tree *object.Tree, s storer.EncodedObjectStorer, fetch BlobFetchFunc) *FetchingTree

NewFetchingTree wraps a git tree with on-demand blob fetching. The storer is used to check if blobs exist locally, and fetch is called to download any that are missing. If fetch is nil, File() behaves identically to the underlying tree.

func (*FetchingTree) File added in v0.5.1

func (t *FetchingTree) File(path string) (*object.File, error)

File returns the file at the given path. If the blob is not available locally (e.g. after a treeless fetch), it is fetched on demand. If go-git's storer still can't see the blob after fetching (due to cached packfile index), the blob is read via "git cat-file" and an in-memory File is returned.

func (*FetchingTree) Files added in v0.5.1

func (t *FetchingTree) Files() *object.FileIter

Files returns a recursive file iterator from the underlying tree. Warning: after a treeless fetch, this iterator will fail when it tries to resolve blob objects. Use File() for on-demand blob fetching instead.

func (*FetchingTree) PreFetch added in v0.5.1

func (t *FetchingTree) PreFetch() (int, error)

PreFetch walks the tree recursively, identifies blob entries that are missing from the local object store, and batch-fetches them in a single call to t.fetch. This avoids per-blob network round-trips during subsequent File() calls. It is safe to call even when all blobs are already local (no-op). Returns the number of blobs fetched.

func (*FetchingTree) RawEntries added in v0.5.1

func (t *FetchingTree) RawEntries() []object.TreeEntry

RawEntries returns the direct tree entries (no blob reads needed).

func (*FetchingTree) Tree added in v0.5.1

func (t *FetchingTree) Tree(path string) (*FetchingTree, error)

Tree returns the subtree at the given path, wrapped with the same fetching behavior.

func (*FetchingTree) Unwrap added in v0.5.1

func (t *FetchingTree) Unwrap() *object.Tree

Unwrap returns the underlying *object.Tree.

type FileOpener added in v0.5.1

type FileOpener interface {
	Reader() (io.ReadCloser, error)
}

FileOpener provides access to a file's content reader. *object.File implements this interface.

type FileReader added in v0.5.1

type FileReader interface {
	File(path string) (*object.File, error)
}

FileReader provides read access to files within a git tree. Both *object.Tree and *FetchingTree implement this interface.

type GitStore

type GitStore struct {
	// contains filtered or unexported fields
}

GitStore provides operations for both temporary and committed checkpoint storage. It implements the Store interface by wrapping a git repository.

func NewGitStore

func NewGitStore(repo *git.Repository) *GitStore

NewGitStore creates a new checkpoint store backed by the given git repository.

func (*GitStore) DeleteShadowBranch

func (s *GitStore) DeleteShadowBranch(ctx context.Context, baseCommit, worktreeID string) error

DeleteShadowBranch deletes the shadow branch for the given base commit and worktree. worktreeID should be empty for main worktree or the internal git worktree name for linked worktrees. Uses git CLI instead of go-git's RemoveReference because go-git v5 doesn't properly persist deletions with packed refs or worktrees.

func (*GitStore) GetCheckpointAuthor

func (s *GitStore) GetCheckpointAuthor(ctx context.Context, checkpointID id.CheckpointID) (Author, error)

GetCheckpointAuthor retrieves the author of a checkpoint from the entire/checkpoints/v1 commit history. 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 (*GitStore) GetSessionLog

func (s *GitStore) GetSessionLog(ctx context.Context, cpID id.CheckpointID) ([]byte, string, error)

GetSessionLog retrieves the session transcript and session ID for a checkpoint. This is the primary method for looking up session logs by checkpoint ID. Returns ErrCheckpointNotFound if the checkpoint doesn't exist. Returns ErrNoTranscript if the checkpoint exists but has no transcript.

func (*GitStore) GetTranscript

func (s *GitStore) GetTranscript(ctx context.Context, checkpointID id.CheckpointID) ([]byte, error)

GetTranscript retrieves the transcript for a specific checkpoint ID. Returns the latest session's transcript.

func (*GitStore) GetTranscriptFromCommit

func (s *GitStore) GetTranscriptFromCommit(ctx context.Context, commitHash plumbing.Hash, metadataDir string, agentType types.AgentType) ([]byte, error)

GetTranscriptFromCommit retrieves the transcript from a specific commit's tree. This is used for shadow branch checkpoints where the transcript is stored in the commit tree rather than on the entire/checkpoints/v1 branch. commitHash is the commit to read from, metadataDir is the path within the tree. agentType is used for reassembling chunked transcripts in the correct format. Handles both chunked and non-chunked transcripts.

func (*GitStore) ListAllTemporaryCheckpoints

func (s *GitStore) ListAllTemporaryCheckpoints(ctx context.Context, sessionID string, limit int) ([]TemporaryCheckpointInfo, error)

ListAllTemporaryCheckpoints lists checkpoint commits from ALL shadow branches. This is used for checkpoint lookup when the base commit is unknown (e.g., HEAD advanced since session start). The sessionID filter, if provided, limits results to commits from that session.

func (*GitStore) ListCheckpointsForBranch

func (s *GitStore) ListCheckpointsForBranch(ctx context.Context, branchName, sessionID string, limit int) ([]TemporaryCheckpointInfo, error)

ListCheckpointsForBranch lists checkpoint commits for a shadow branch by name. Use this when you already have the full branch name (e.g., from ListTemporary). The sessionID filter, if provided, limits results to commits from that session.

func (*GitStore) ListCommitted

func (s *GitStore) ListCommitted(ctx context.Context) ([]CommittedInfo, error)

func (*GitStore) ListTemporary

func (s *GitStore) ListTemporary(ctx context.Context) ([]TemporaryInfo, error)

ListTemporary lists all shadow branches with their checkpoint info.

func (*GitStore) ListTemporaryCheckpoints

func (s *GitStore) ListTemporaryCheckpoints(ctx context.Context, baseCommit, worktreeID, sessionID string, limit int) ([]TemporaryCheckpointInfo, error)

ListTemporaryCheckpoints lists all checkpoint commits on a shadow branch. This returns individual commits (rewind points), not just branch info. The sessionID filter, if provided, limits results to commits from that session. worktreeID should be empty for main worktree or the internal git worktree name for linked worktrees.

func (*GitStore) ReadCommitted

func (s *GitStore) ReadCommitted(ctx context.Context, checkpointID id.CheckpointID) (*CheckpointSummary, error)

ReadCommitted reads a committed checkpoint's summary by ID from the entire/checkpoints/v1 branch. Returns only the CheckpointSummary (paths + aggregated stats), not actual content. Use ReadSessionContent to read actual transcript/prompts/context. Returns nil, nil if the checkpoint doesn't exist.

The storage format uses numbered subdirectories for each session (0-based):

<checkpoint-id>/
├── metadata.json      # CheckpointSummary with sessions map
├── 0/                 # First session
│   ├── metadata.json  # Session-specific metadata
│   └── full.jsonl     # Transcript
├── 1/                 # Second session
└── ...

func (*GitStore) ReadLatestSessionContent

func (s *GitStore) ReadLatestSessionContent(ctx context.Context, checkpointID id.CheckpointID) (*SessionContent, error)

ReadLatestSessionContent is a convenience method that reads the latest session's content. This is equivalent to ReadSessionContent(ctx, checkpointID, len(summary.Sessions)-1).

func (*GitStore) ReadSessionContent

func (s *GitStore) ReadSessionContent(ctx context.Context, checkpointID id.CheckpointID, sessionIndex int) (*SessionContent, error)

ReadSessionContent reads the actual content for a specific session within a checkpoint. sessionIndex is 0-based (0 for first session, 1 for second, etc.). Returns the session's metadata, transcript, prompts, and context. Returns an error if the checkpoint or session doesn't exist.

func (*GitStore) ReadSessionContentByID

func (s *GitStore) ReadSessionContentByID(ctx context.Context, checkpointID id.CheckpointID, sessionID string) (*SessionContent, error)

ReadSessionContentByID reads a session's content by its session ID. This is useful when you have the session ID but don't know its index within the checkpoint. Returns ErrCheckpointNotFound if the checkpoint doesn't exist. Returns an error if no session with the given ID exists in the checkpoint.

func (*GitStore) ReadTemporary

func (s *GitStore) ReadTemporary(ctx context.Context, baseCommit, worktreeID string) (*ReadTemporaryResult, error)

ReadTemporary reads the latest checkpoint from a shadow branch. Returns nil if the shadow branch doesn't exist. worktreeID should be empty for main worktree or the internal git worktree name for linked worktrees.

func (*GitStore) Repository

func (s *GitStore) Repository() *git.Repository

Repository returns the underlying git repository. This is useful for strategies that need direct repository access.

func (*GitStore) SetBlobFetcher added in v0.5.1

func (s *GitStore) SetBlobFetcher(f BlobFetchFunc)

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.

func (*GitStore) ShadowBranchExists

func (s *GitStore) ShadowBranchExists(baseCommit, worktreeID string) bool

ShadowBranchExists checks if a shadow branch exists for the given base commit and worktree. worktreeID should be empty for main worktree or the internal git worktree name for linked worktrees.

func (*GitStore) UpdateCommitted added in v0.4.5

func (s *GitStore) UpdateCommitted(ctx context.Context, opts UpdateCommittedOptions) error

UpdateCommitted replaces the transcript, prompts, and context for an existing committed checkpoint. Uses replace semantics: the full session transcript is written, replacing whatever was stored at initial condensation time.

This is called at stop time to finalize all checkpoints from the current turn with the complete session transcript (from prompt to stop event).

Returns ErrCheckpointNotFound if the checkpoint doesn't exist.

func (*GitStore) UpdateSummary

func (s *GitStore) UpdateSummary(ctx context.Context, checkpointID id.CheckpointID, summary *Summary) error

UpdateSummary updates the summary field in the latest session's metadata. Returns ErrCheckpointNotFound if the checkpoint doesn't exist.

func (*GitStore) WriteCommitted

func (s *GitStore) WriteCommitted(ctx context.Context, opts WriteCommittedOptions) error

WriteCommitted writes a committed checkpoint to the entire/checkpoints/v1 branch. Checkpoints are stored at sharded paths: <id[:2]>/<id[2:]>/

For task checkpoints (IsTask=true), additional files are written under tasks/<tool-use-id>/:

  • For incremental checkpoints: checkpoints/NNN-<tool-use-id>.json
  • For final checkpoints: checkpoint.json and agent-<agent-id>.jsonl

func (*GitStore) WriteTemporary

func (s *GitStore) WriteTemporary(ctx context.Context, opts WriteTemporaryOptions) (WriteTemporaryResult, error)

WriteTemporary writes a temporary checkpoint to a shadow branch. Shadow branches are named entire/<base-commit-short-hash>. Returns the result containing commit hash and whether it was skipped. If the new tree hash matches the last checkpoint's tree hash, the checkpoint is skipped to avoid duplicate commits (deduplication).

func (*GitStore) WriteTemporaryTask

func (s *GitStore) WriteTemporaryTask(ctx context.Context, opts WriteTemporaryTaskOptions) (plumbing.Hash, error)

WriteTemporaryTask writes a task checkpoint to a shadow branch. Task checkpoints include both code changes and task-specific metadata. Returns the commit hash of the created checkpoint.

type Info

type Info struct {
	// ID is the checkpoint identifier
	ID string

	// SessionID identifies the session
	SessionID string

	// Type indicates temporary or committed
	Type Type

	// CreatedAt is when the checkpoint was created
	CreatedAt time.Time

	// Message is a summary description
	Message string
}

Info provides summary information for listing checkpoints. This is the generic checkpoint info type.

type InitialAttribution

type InitialAttribution struct {
	CalculatedAt    time.Time `json:"calculated_at"`
	AgentLines      int       `json:"agent_lines"`      // Lines added by agent (base → shadow diff)
	HumanAdded      int       `json:"human_added"`      // Lines added by human (excluding modifications)
	HumanModified   int       `json:"human_modified"`   // Lines modified by human (estimate: min(added, removed))
	HumanRemoved    int       `json:"human_removed"`    // Lines removed by human (excluding modifications)
	TotalCommitted  int       `json:"total_committed"`  // Net additions in commit (agent + human new lines, not total file size)
	AgentPercentage float64   `json:"agent_percentage"` // agent_lines / total_committed * 100 (0 for deletion-only commits)
}

InitialAttribution captures line-level attribution metrics at commit time. This is a point-in-time snapshot comparing the checkpoint tree (agent work) against the committed tree (may include human edits).

Attribution Metrics:

  • TotalCommitted measures "net additions" (lines added that remain in the commit)
  • AgentPercentage represents "of the new code added, what percentage came from the agent"
  • Deletion work is tracked separately in HumanRemoved (not included in percentage)

Deletion-Only Commits: For commits with only deletions (no additions), TotalCommitted will be 0 and AgentPercentage will be 0. This is by design - the percentage metric is only meaningful for commits that add code. Deletion contributions are captured in the HumanRemoved field but don't affect the attribution percentage.

type LearningsSummary

type LearningsSummary struct {
	Repo     []string       `json:"repo"`     // Codebase-specific patterns/conventions
	Code     []CodeLearning `json:"code"`     // File/module specific findings
	Workflow []string       `json:"workflow"` // General dev practices
}

LearningsSummary contains learnings grouped by scope.

type MergeMode added in v0.4.8

type MergeMode int

MergeMode controls how entries at the leaf directory are handled by UpdateSubtree.

const (
	// ReplaceAll replaces the entire leaf directory contents with the new entries.
	ReplaceAll MergeMode = iota
	// MergeKeepExisting merges new entries into the existing leaf directory,
	// keeping existing entries that are not overwritten (unless in DeleteNames).
	MergeKeepExisting
)

type ReadTemporaryResult

type ReadTemporaryResult struct {
	// CommitHash is the hash of the checkpoint commit
	CommitHash plumbing.Hash

	// TreeHash is the hash of the tree containing the checkpoint state
	TreeHash plumbing.Hash

	// SessionID is the session identifier from the commit trailer
	SessionID string

	// MetadataDir is the metadata directory path from the commit trailer
	MetadataDir string

	// Timestamp is when the checkpoint was created
	Timestamp time.Time
}

ReadTemporaryResult contains the result of reading a temporary checkpoint.

type SessionContent

type SessionContent struct {
	// Metadata contains the session-specific metadata
	Metadata CommittedMetadata

	// Transcript is the session transcript content
	Transcript []byte

	// Prompts contains user prompts from this session
	Prompts string
}

SessionContent contains the actual content for a session. This is used when reading full session data (transcript, prompts, context) as opposed to just the metadata/summary.

type SessionFilePaths

type SessionFilePaths struct {
	Metadata    string `json:"metadata"`
	Transcript  string `json:"transcript"`
	ContentHash string `json:"content_hash"`
	Prompt      string `json:"prompt"`
}

SessionFilePaths contains the absolute paths to session files from the git tree root. Paths include the full checkpoint path prefix (e.g., "/a1/b2c3d4e5f6/1/metadata.json"). Used in CheckpointSummary.Sessions to map session IDs to their file locations.

type SessionMetrics added in v0.5.0

type SessionMetrics struct {
	DurationMs        int64 `json:"duration_ms,omitempty"`
	TurnCount         int   `json:"turn_count,omitempty"`
	ContextTokens     int   `json:"context_tokens,omitempty"`
	ContextWindowSize int   `json:"context_window_size,omitempty"`
}

SessionMetrics contains hook-provided session metrics from agents that report them via lifecycle hooks (e.g., Cursor). These supplement transcript-derived metrics for agents whose transcripts lack usage/timing data.

type Store

type Store interface {
	// WriteTemporary writes a temporary checkpoint (full state) to a shadow branch.
	// Shadow branches are named entire/<base-commit-short-hash>.
	// Returns a result containing the commit hash and whether the checkpoint was skipped.
	// Checkpoints are skipped (deduplicated) when the tree hash matches the previous checkpoint.
	WriteTemporary(ctx context.Context, opts WriteTemporaryOptions) (WriteTemporaryResult, error)

	// ReadTemporary reads the latest checkpoint from a shadow branch.
	// baseCommit is the commit hash the session is based on.
	// worktreeID is the internal git worktree identifier (empty for main worktree).
	// Returns nil, nil if the shadow branch doesn't exist.
	ReadTemporary(ctx context.Context, baseCommit, worktreeID string) (*ReadTemporaryResult, error)

	// ListTemporary lists all shadow branches with their checkpoint info.
	ListTemporary(ctx context.Context) ([]TemporaryInfo, error)

	// WriteCommitted writes a committed checkpoint to the entire/checkpoints/v1 branch.
	// Checkpoints are stored at sharded paths: <id[:2]>/<id[2:]>/
	WriteCommitted(ctx context.Context, opts WriteCommittedOptions) error

	// ReadCommitted reads a committed checkpoint's summary by ID.
	// Returns only the CheckpointSummary (paths + aggregated stats), not actual content.
	// Use ReadSessionContent to read actual transcript/prompts.
	// Returns nil, nil if the checkpoint does not exist.
	ReadCommitted(ctx context.Context, checkpointID id.CheckpointID) (*CheckpointSummary, error)

	// ReadSessionContent reads the actual content for a specific session within a checkpoint.
	// sessionIndex is 0-based (0 for first session, 1 for second, etc.).
	// Returns the session's metadata, transcript, and prompts.
	ReadSessionContent(ctx context.Context, checkpointID id.CheckpointID, sessionIndex int) (*SessionContent, error)

	// ReadSessionContentByID reads a session's content by its session ID.
	// Useful when you have the session ID but don't know its index within the checkpoint.
	ReadSessionContentByID(ctx context.Context, checkpointID id.CheckpointID, sessionID string) (*SessionContent, error)

	// ListCommitted lists all committed checkpoints.
	ListCommitted(ctx context.Context) ([]CommittedInfo, error)

	// UpdateCommitted replaces the transcript and prompts for an existing
	// committed checkpoint. Used at stop time to finalize checkpoints with the full
	// session transcript (prompt to stop event).
	// Returns ErrCheckpointNotFound if the checkpoint doesn't exist.
	UpdateCommitted(ctx context.Context, opts UpdateCommittedOptions) error
}

Store provides low-level primitives for reading and writing checkpoints. This is used by strategies to implement their storage approach.

The interface matches the GitStore implementation signatures directly: - WriteTemporary takes WriteTemporaryOptions and returns a result with commit hash and skip status - ReadTemporary takes baseCommit (not sessionID) since shadow branches are keyed by commit - List methods return implementation-specific info types for richer data

type Summary

type Summary struct {
	Intent    string           `json:"intent"`     // What user wanted to accomplish
	Outcome   string           `json:"outcome"`    // What was achieved
	Learnings LearningsSummary `json:"learnings"`  // Categorized learnings
	Friction  []string         `json:"friction"`   // Problems/annoyances encountered
	OpenItems []string         `json:"open_items"` // Tech debt, unfinished work
}

Summary contains AI-generated summary of a checkpoint.

type TemporaryCheckpointInfo

type TemporaryCheckpointInfo struct {
	// CommitHash is the hash of the checkpoint commit
	CommitHash plumbing.Hash

	// Message is the first line of the commit message
	Message string

	// SessionID is the session identifier from the Entire-Session trailer
	SessionID string

	// MetadataDir is the metadata directory path from trailers
	MetadataDir string

	// IsTaskCheckpoint indicates if this is a task checkpoint
	IsTaskCheckpoint bool

	// ToolUseID is the tool use ID for task checkpoints
	ToolUseID string

	// Timestamp is when the checkpoint was created
	Timestamp time.Time
}

TemporaryCheckpointInfo contains information about a single commit on a shadow branch. Used by ListTemporaryCheckpoints to provide rewind point data.

type TemporaryInfo

type TemporaryInfo struct {
	// BranchName is the full branch name (e.g., "entire/abc1234")
	BranchName string

	// BaseCommit is the short commit hash this branch is based on
	BaseCommit string

	// LatestCommit is the hash of the latest commit on the branch
	LatestCommit plumbing.Hash

	// SessionID is the session identifier from the latest commit
	SessionID string

	// Timestamp is when the latest checkpoint was created
	Timestamp time.Time
}

TemporaryInfo contains summary information about a shadow branch.

type TranscriptBlobRef added in v0.5.1

type TranscriptBlobRef struct {
	// SessionIndex is the 0-based session index within the checkpoint.
	SessionIndex int

	// Hash is the blob's SHA-1 hash from the tree entry.
	Hash plumbing.Hash

	// Path is the blob's path relative to the checkpoint directory,
	// e.g. "0/full.jsonl" or "0/full.jsonl.001".
	Path string
}

TranscriptBlobRef identifies a blob within a checkpoint tree on the metadata branch. It captures the blob hash from the tree entry without requiring the blob itself to be local.

func CollectTranscriptBlobHashes added in v0.5.1

func CollectTranscriptBlobHashes(tree *object.Tree, checkpointID id.CheckpointID) ([]TranscriptBlobRef, error)

CollectTranscriptBlobHashes walks the metadata branch tree for a checkpoint and returns blob hashes for all transcript files (full.jsonl and chunks) across all sessions. Only reads tree objects — works after a treeless fetch where blobs have not been downloaded.

The function navigates the sharded checkpoint directory structure:

<id[:2]>/<id[2:]>/
├── 0/
│   ├── full.jsonl          ← collected
│   ├── full.jsonl.001      ← collected (chunk)
│   └── metadata.json
├── 1/
│   └── full.jsonl          ← collected
└── metadata.json

type TreeChange added in v0.4.8

type TreeChange struct {
	// Path is the full path within the tree (e.g., "src/pkg/handler.go").
	Path string
	// Entry is the new tree entry. Nil means delete the file at Path.
	Entry *object.TreeEntry
}

TreeChange represents a single file change within a tree. Use a nil Entry to indicate deletion.

type Type

type Type int

Type indicates the storage location and lifecycle of a checkpoint.

const (
	// Temporary checkpoints contain full state (code + metadata) and are stored
	// on shadow branches (entire/<commit-hash>). Used for intra-session rewind.
	Temporary Type = iota

	// Committed checkpoints contain metadata + commit reference and are stored
	// on the entire/checkpoints/v1 branch. They are the permanent record.
	Committed
)

type UpdateCommittedOptions added in v0.4.5

type UpdateCommittedOptions struct {
	// CheckpointID identifies the checkpoint to update
	CheckpointID id.CheckpointID

	// SessionID identifies which session slot to update within the checkpoint
	SessionID string

	// Transcript is the full session transcript (replaces existing)
	Transcript []byte

	// Prompts contains all user prompts (replaces existing)
	Prompts []string

	// Agent identifies the agent type (needed for transcript chunking)
	Agent types.AgentType
}

UpdateCommittedOptions contains options for updating an existing committed checkpoint. Uses replace semantics: the transcript and prompts are fully replaced, not appended. At stop time we have the complete session transcript and want every checkpoint to contain it identically.

type UpdateSubtreeOptions added in v0.4.8

type UpdateSubtreeOptions struct {
	// MergeMode controls how entries at the leaf directory are handled.
	MergeMode MergeMode
	// DeleteNames lists entry names (at the leaf directory level) to delete.
	// Only applicable when MergeMode is MergeKeepExisting.
	DeleteNames []string
}

UpdateSubtreeOptions configures the behavior of UpdateSubtree.

type WriteCommittedOptions

type WriteCommittedOptions struct {
	// CheckpointID is the stable 12-hex-char identifier
	CheckpointID id.CheckpointID

	// SessionID is the session identifier
	SessionID string

	// Strategy is the name of the strategy that created this checkpoint
	Strategy string

	// Branch is the branch name where the checkpoint was created (empty if detached HEAD)
	Branch string

	// Transcript is the session transcript content (full.jsonl)
	Transcript []byte

	// Prompts contains user prompts from the session
	Prompts []string

	// FilesTouched are files modified during the session
	FilesTouched []string

	// CheckpointsCount is the number of checkpoints in this session
	CheckpointsCount int

	// EphemeralBranch is the shadow branch name (for manual-commit strategy)
	EphemeralBranch string

	// AuthorName is the name to use for commits
	AuthorName string

	// AuthorEmail is the email to use for commits
	AuthorEmail string

	// MetadataDir is a directory containing additional metadata files to copy
	// If set, all files in this directory will be copied to the checkpoint path
	// This is useful for copying task metadata files, subagent transcripts, etc.
	MetadataDir string

	// Task checkpoint fields (for task/subagent checkpoints)
	IsTask    bool   // Whether this is a task checkpoint
	ToolUseID string // Tool use ID for task checkpoints

	// Additional task checkpoint fields for subagent checkpoints
	AgentID                string // Subagent identifier
	CheckpointUUID         string // UUID for transcript truncation when rewinding
	TranscriptPath         string // Path to session transcript file (alternative to in-memory Transcript)
	SubagentTranscriptPath string // Path to subagent's transcript file

	// Incremental checkpoint fields
	IsIncremental       bool   // Whether this is an incremental checkpoint
	IncrementalSequence int    // Checkpoint sequence number
	IncrementalType     string // Tool type that triggered this checkpoint
	IncrementalData     []byte // Tool input payload for this checkpoint

	// Commit message fields (used for task checkpoints)
	CommitSubject string // Subject line for the metadata commit (overrides default)

	// Agent identifies the agent that created this checkpoint (e.g., "Claude Code", "Cursor")
	Agent types.AgentType

	// Model is the LLM model used during the session (e.g., "claude-sonnet-4-20250514")
	Model string

	// TurnID correlates checkpoints from the same agent turn.
	TurnID string

	// Transcript position at checkpoint start - tracks what was added during this checkpoint
	TranscriptIdentifierAtStart string // Last identifier when checkpoint started (UUID for Claude, message ID for Gemini)
	CheckpointTranscriptStart   int    // Transcript line offset at start of this checkpoint's data

	// TokenUsage contains the token usage for this checkpoint
	TokenUsage *agent.TokenUsage

	// SessionMetrics contains hook-provided session metrics (duration, turns, context usage)
	SessionMetrics *SessionMetrics

	// InitialAttribution is line-level attribution calculated at commit time
	// comparing checkpoint tree (agent work) to committed tree (may include human edits)
	InitialAttribution *InitialAttribution

	// Summary is an optional AI-generated summary for this checkpoint.
	// This field may be nil when:
	//   - summarization is disabled in settings
	//   - summary generation failed (non-blocking, logged as warning)
	//   - the transcript was empty or too short to summarize
	//   - the checkpoint predates the summarization feature
	Summary *Summary
}

WriteCommittedOptions contains options for writing a committed checkpoint.

type WriteTemporaryOptions

type WriteTemporaryOptions struct {
	// SessionID is the session identifier
	SessionID string

	// BaseCommit is the commit hash this session is based on
	BaseCommit string

	// WorktreeID is the internal git worktree identifier (empty for main worktree)
	// Used to create worktree-specific shadow branch names
	WorktreeID string

	// ModifiedFiles are files that have been modified (relative paths)
	ModifiedFiles []string

	// NewFiles are files that have been created (relative paths)
	NewFiles []string

	// DeletedFiles are files that have been deleted (relative paths)
	DeletedFiles []string

	// MetadataDir is the relative path to the metadata directory
	MetadataDir string

	// MetadataDirAbs is the absolute path to the metadata directory
	MetadataDirAbs string

	// CommitMessage is the commit subject line
	CommitMessage string

	// AuthorName is the name to use for commits
	AuthorName string

	// AuthorEmail is the email to use for commits
	AuthorEmail string

	// IsFirstCheckpoint indicates if this is the first checkpoint of the session
	// When true, all working directory files are captured (not just modified)
	IsFirstCheckpoint bool
}

WriteTemporaryOptions contains options for writing a temporary checkpoint.

type WriteTemporaryResult

type WriteTemporaryResult struct {
	// CommitHash is the hash of the created or existing checkpoint commit
	CommitHash plumbing.Hash

	// Skipped is true if the checkpoint was skipped due to no changes
	// (tree hash matched the previous checkpoint)
	Skipped bool
}

WriteTemporaryResult contains the result of writing a temporary checkpoint.

type WriteTemporaryTaskOptions

type WriteTemporaryTaskOptions struct {
	// SessionID is the session identifier
	SessionID string

	// BaseCommit is the commit hash this session is based on
	BaseCommit string

	// WorktreeID is the internal git worktree identifier (empty for main worktree)
	// Used to create worktree-specific shadow branch names
	WorktreeID string

	// ToolUseID is the unique identifier for this Task tool invocation
	ToolUseID string

	// AgentID is the subagent identifier
	AgentID string

	// ModifiedFiles are files that have been modified (relative paths)
	ModifiedFiles []string

	// NewFiles are files that have been created (relative paths)
	NewFiles []string

	// DeletedFiles are files that have been deleted (relative paths)
	DeletedFiles []string

	// TranscriptPath is the path to the main session transcript
	TranscriptPath string

	// SubagentTranscriptPath is the path to the subagent's transcript
	SubagentTranscriptPath string

	// CheckpointUUID is the UUID for transcript truncation when rewinding
	CheckpointUUID string

	// CommitMessage is the commit message (already formatted)
	CommitMessage string

	// AuthorName is the name to use for commits
	AuthorName string

	// AuthorEmail is the email to use for commits
	AuthorEmail string

	// IsIncremental indicates this is an incremental checkpoint
	IsIncremental bool

	// IncrementalSequence is the checkpoint sequence number
	IncrementalSequence int

	// IncrementalType is the tool that triggered this checkpoint
	IncrementalType string

	// IncrementalData is the tool_input payload for this checkpoint
	IncrementalData []byte
}

WriteTemporaryTaskOptions contains options for writing a task checkpoint. Task checkpoints are created when a subagent completes and contain both code changes and task-specific metadata.

Directories

Path Synopsis
Package id provides the CheckpointID type for identifying checkpoints.
Package id provides the CheckpointID type for identifying checkpoints.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL