strategy

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: 53 Imported by: 0

Documentation

Overview

Package strategy provides the manual-commit strategy for managing Claude Code session changes via shadow branches and checkpoint condensation.

Index

Constants

View Source
const MaxCommitTraversalDepth = 1000

MaxCommitTraversalDepth is the safety limit for walking git commit history. Prevents unbounded traversal in repositories with very long histories.

View Source
const MaxDescriptionLength = 60

MaxDescriptionLength is the maximum length for descriptions in commit messages before truncation occurs.

View Source
const NoDescription = "No description"

NoDescription is the default description for sessions without one.

View Source
const (

	// Strategy name constants
	StrategyNameManualCommit = "manual-commit"
)

Common branch name constants for default branch detection.

Variables

View Source
var ErrBranchNotFound = errors.New("branch not found")

ErrBranchNotFound is returned by DeleteBranchCLI when the branch does not exist.

View Source
var ErrEmptyRepository = errors.New("repository has no commits yet")

ErrEmptyRepository is returned when the repository has no commits yet.

View Source
var ErrNoMetadata = errors.New("commit has no entire metadata")

ErrNoMetadata is returned when a commit does not have an Entire metadata trailer.

View Source
var ErrNoSession = errors.New("no session info available")

ErrNoSession is returned when no session info is available.

View Source
var ErrNotTaskCheckpoint = errors.New("not a task checkpoint")

ErrNotTaskCheckpoint is returned when a rewind point is not a task checkpoint.

Functions

func CalculateAttributionWithAccumulated

func CalculateAttributionWithAccumulated(
	ctx context.Context,
	baseTree *object.Tree,
	shadowTree *object.Tree,
	headTree *object.Tree,
	filesTouched []string,
	promptAttributions []PromptAttribution,
	repoDir string,
	attributionBaseCommit string,
	headCommitHash string,
) *checkpoint.InitialAttribution

CalculateAttributionWithAccumulated computes final attribution using accumulated prompt data. This provides more accurate attribution than tree-only comparison because it captures user edits that happened between checkpoints (which would otherwise be mixed into the checkpoint snapshots).

The calculation: 1. Sum user edits from PromptAttributions (captured at each prompt start) 2. Add user edits after the final checkpoint (shadow → head diff) 3. Calculate agent lines from base → shadow 4. Estimate user self-modifications vs agent modifications using per-file tracking 5. Compute percentages

attributionBaseCommit and headCommitHash are optional commit hashes for fast non-agent file detection via git diff-tree. When empty, falls back to go-git tree walk.

Note: Binary files (detected by null bytes) are silently excluded from attribution calculations since line-based diffing only applies to text files.

See docs/architecture/attribution.md for details on the per-file tracking approach.

func CheckAndWarnHookManagers added in v0.4.5

func CheckAndWarnHookManagers(ctx context.Context, w io.Writer, localDev, absolutePath bool)

CheckAndWarnHookManagers detects external hook managers and writes a warning to w if any are found. localDev controls whether the warning references "go run" or the "entire" binary. absolutePath embeds the full binary path for GUI git clients.

func ClearHooksDirCache added in v0.4.6

func ClearHooksDirCache()

ClearHooksDirCache clears the cached hooks directory. This is primarily useful for testing when changing directories.

func ClearSessionState

func ClearSessionState(ctx context.Context, sessionID string) error

ClearSessionState removes the session state file for the given session ID.

func CountTodos

func CountTodos(todosJSON []byte) int

CountTodos returns the number of todo items in the JSON array. Returns 0 if the JSON is invalid or empty.

func DeleteBranchCLI added in v0.3.13

func DeleteBranchCLI(ctx context.Context, branchName string) error

DeleteBranchCLI deletes a git branch using the git CLI. Uses `git branch -D` instead of go-git's RemoveReference because go-git v5 doesn't properly persist deletions when refs are packed (.git/packed-refs) or in a worktree context. This is the same class of go-git v5 bug that affects checkout and reset --hard (see HardResetWithProtection).

Returns ErrBranchNotFound if the branch does not exist, allowing callers to use errors.Is for idempotent deletion patterns.

func DeleteOrphanedCheckpoints

func DeleteOrphanedCheckpoints(ctx context.Context, checkpointIDs []string) (deleted []string, failed []string, err error)

DeleteOrphanedCheckpoints removes checkpoint directories from the entire/checkpoints/v1 branch.

func DeleteOrphanedSessionStates

func DeleteOrphanedSessionStates(ctx context.Context, sessionIDs []string) (deleted []string, failed []string, err error)

DeleteOrphanedSessionStates deletes the specified session state files.

func DeleteShadowBranches

func DeleteShadowBranches(ctx context.Context, branches []string) (deleted []string, failed []string, err error)

DeleteShadowBranches deletes the specified branches from the repository. Returns two slices: successfully deleted branches and branches that failed to delete. Individual branch deletion failures do not stop the operation - all branches are attempted.

func EnsureEntireGitignore

func EnsureEntireGitignore(ctx context.Context) error

EnsureEntireGitignore ensures all required entries are in .entire/.gitignore Works correctly from any subdirectory within the repository.

func EnsureMetadataBranch

func EnsureMetadataBranch(repo *git.Repository) error

EnsureMetadataBranch creates or updates the local entire/checkpoints/v1 branch. If the remote-tracking branch (origin/entire/checkpoints/v1) exists and the local branch is missing or empty, creates/updates the local branch from it. Otherwise creates an empty orphan.

func EnsureRedactionConfigured added in v0.5.1

func EnsureRedactionConfigured()

EnsureRedactionConfigured loads PII redaction settings and configures the redact package. No-op if PII is not enabled in settings. Must be called at each process entry point before checkpoint writes (e.g., hook PersistentPreRunE, doctor PreRun).

func EnsureSetup added in v0.4.8

func EnsureSetup(ctx context.Context) error

EnsureSetup ensures the strategy is properly set up.

func ExtractFirstPrompt

func ExtractFirstPrompt(content string) string

ExtractFirstPrompt extracts and truncates the first meaningful prompt from prompt content. Prompts are separated by "\n\n---\n\n". Skips empty prompts and separator-only content. Returns empty string if no valid prompt is found.

func ExtractInProgressTodo

func ExtractInProgressTodo(todosJSON []byte) string

ExtractInProgressTodo extracts the content of the in-progress todo item from tool_input. This is used for commit messages in incremental checkpoints.

Priority order:

  1. in_progress item (current work)
  2. first pending item (next work - fallback)
  3. last completed item (final work just finished)
  4. first item with unknown status (edge case)
  5. empty string (no items)

Returns empty string if no suitable item is found or JSON is invalid.

func ExtractLastCompletedTodo

func ExtractLastCompletedTodo(todosJSON []byte) string

ExtractLastCompletedTodo extracts the content of the last completed todo item from tool_input. This represents the work that was just finished and is used for commit messages.

When TodoWrite is called in PostToolUse, the NEW list is provided which has the just-completed work marked as "completed". The last completed item is the most recently finished task.

Returns empty string if no completed items exist or JSON is invalid.

func ExtractSessionIDFromCommit

func ExtractSessionIDFromCommit(commit *object.Commit) string

ExtractSessionIDFromCommit extracts the session ID from a commit's trailers. It checks the Entire-Session trailer first, then falls back to extracting from the metadata directory path in the Entire-Metadata trailer. Returns empty string if no session ID is found.

func FindMostRecentSession added in v0.3.13

func FindMostRecentSession(ctx context.Context) string

FindMostRecentSession returns the session ID of the most recently interacted session (by LastInteractionTime) in the current worktree. Returns empty string if no sessions exist. Scoping to the current worktree prevents cross-worktree pollution in log routing. Falls back to unfiltered search if the worktree path can't be determined.

func FormatIncrementalMessage

func FormatIncrementalMessage(todoContent string, sequence int, toolUseID string) string

FormatIncrementalMessage formats a commit message for an incremental checkpoint. Format: "<todo-content> (<tool-use-id>)"

If todoContent is empty, falls back to: "Checkpoint #<sequence>: <tool-use-id>"

func FormatIncrementalSubject

func FormatIncrementalSubject(
	incrementalType string,
	subagentType string,
	taskDescription string,
	todoContent string,
	incrementalSequence int,
	shortToolUseID string,
) string

FormatIncrementalSubject formats the commit message subject for incremental checkpoints. Delegates to FormatIncrementalMessage.

Note: The incrementalType, subagentType, and taskDescription parameters are kept for API compatibility but are not currently used. They may be used in the future for different checkpoint types.

func FormatSubagentEndMessage

func FormatSubagentEndMessage(agentType, description, toolUseID string) string

FormatSubagentEndMessage formats a commit message for when a subagent completes. Format: "Completed '<agent-type>' agent: <description> (<tool-use-id>)"

Edge cases:

  • Empty description: "Completed '<agent-type>' agent (<tool-use-id>)"
  • Empty agentType: "Completed agent: <description> (<tool-use-id>)"
  • Both empty: "Task: <tool-use-id>"

func GetCurrentBranchName

func GetCurrentBranchName(repo *git.Repository) string

GetCurrentBranchName returns the short name of the current branch if HEAD points to a branch. Returns an empty string if in detached HEAD state or if there's an error reading HEAD. This is used to capture branch metadata for checkpoints.

func GetDefaultBranchName

func GetDefaultBranchName(repo *git.Repository) string

GetDefaultBranchName returns the name of the default branch. First checks origin/HEAD, then falls back to checking if main/master exists. Returns empty string if unable to determine. NOTE: Duplicated from cli/git_operations.go - see ENT-129 for consolidation.

func GetGitAuthorFromRepo

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. Delegates to checkpoint.GetGitAuthorFromRepo — this wrapper exists so callers within the strategy package don't need a qualified import.

func GetGitCommonDir

func GetGitCommonDir(ctx context.Context) (string, error)

GetGitCommonDir returns the path to the shared git directory. In a regular checkout, this is .git/ In a worktree, this is the main repo's .git/ (not .git/worktrees/<name>/) Uses git rev-parse --git-common-dir for reliable handling of worktrees.

func GetGitDir

func GetGitDir(ctx context.Context) (string, error)

GetGitDir returns the actual git directory path by delegating to git itself. This handles both regular repositories and worktrees, and inherits git's security validation for gitdir references.

func GetHooksDir added in v0.4.5

func GetHooksDir(ctx context.Context) (string, error)

GetHooksDir returns the active hooks directory path. This respects core.hooksPath and correctly resolves to the common hooks directory when called from a linked worktree. The result is cached per working directory.

func GetMainBranchHash

func GetMainBranchHash(repo *git.Repository) plumbing.Hash

getMainBranchHash returns the hash of the main branch (main or master). Returns ZeroHash if no main branch is found.

func GetMainRepoRoot

func GetMainRepoRoot(ctx context.Context) (string, error)

GetMainRepoRoot returns the root directory of the main repository. In the main repo, this is the worktree path (repo root). In a worktree, this parses the .git file to find the main repo. This function works correctly from any subdirectory within the repository.

Per gitrepository-layout(5), a worktree's .git file is a "gitfile" containing "gitdir: <path>" pointing to $GIT_DIR/worktrees/<id> in the main repository. See: https://git-scm.com/docs/gitrepository-layout

func GetMetadataBranchTree

func GetMetadataBranchTree(repo *git.Repository) (*object.Tree, error)

GetMetadataBranchTree returns the tree object for the entire/checkpoints/v1 branch.

func GetRemoteMetadataBranchTree

func GetRemoteMetadataBranchTree(repo *git.Repository) (*object.Tree, error)

GetRemoteMetadataBranchTree returns the tree object for origin/entire/checkpoints/v1.

func HardResetWithProtection

func HardResetWithProtection(ctx context.Context, commitHash plumbing.Hash) (shortID string, err error)

HardResetWithProtection performs a git reset --hard to the specified commit. Uses the git CLI instead of go-git because go-git's HardReset incorrectly deletes untracked directories (like .entire/) even when they're in .gitignore. Returns the short commit ID (7 chars) on success for display purposes.

func InstallGitHook

func InstallGitHook(ctx context.Context, silent, localDev, absolutePath bool) (int, error)

InstallGitHook installs generic git hooks that delegate to `entire hook` commands. These hooks work with any strategy - the strategy is determined at runtime. If silent is true, no output is printed (except backup notifications, which always print). localDev controls whether hooks use "go run" (true) or the "entire" binary (false). absolutePath embeds the full binary path in hooks for GUI git clients. Returns the number of hooks that were installed (0 if all already up to date).

func IsAncestorOf

func IsAncestorOf(ctx context.Context, repo *git.Repository, commit, target plumbing.Hash) bool

IsAncestorOf checks if commit is an ancestor of (or equal to) target. Returns true if target can reach commit by following parent links. Limits search to MaxCommitTraversalDepth commits to avoid excessive traversal.

func IsEmptyRepository added in v0.4.3

func IsEmptyRepository(repo *git.Repository) bool

IsEmptyRepository returns true if the repository has no commits yet. After git-init, HEAD points to an unborn branch (e.g., refs/heads/main) whose target does not yet exist. repo.Head() returns ErrReferenceNotFound in this case.

func IsGitHookInstalled

func IsGitHookInstalled(ctx context.Context) bool

IsGitHookInstalled checks if all generic Entire CLI hooks are installed.

func IsGitHookInstalledInDir added in v0.4.4

func IsGitHookInstalledInDir(ctx context.Context, repoDir string) bool

IsGitHookInstalledInDir checks if all Entire CLI hooks are installed in the given repo directory. This is useful for tests that need to check hooks without changing the working directory.

func IsInsideWorktree

func IsInsideWorktree(ctx context.Context) bool

IsInsideWorktree returns true if the current directory is inside a git worktree (as opposed to the main repository). Worktrees have .git as a file pointing to the main repo, while the main repo has .git as a directory. This function works correctly from any subdirectory within the repository.

func IsMetadataDisconnected added in v0.5.0

func IsMetadataDisconnected(ctx context.Context, repo *git.Repository) (bool, error)

IsMetadataDisconnected checks whether local and remote entire/checkpoints/v1 branches exist but share no common ancestor (the "empty-orphan bug"). Returns (false, nil) if either branch is missing, they point to the same hash, or they share a common ancestor (normal divergence handled by push merge). Returns (true, nil) only when both exist and are truly disconnected.

func IsOnDefaultBranch

func IsOnDefaultBranch(repo *git.Repository) (bool, string)

IsOnDefaultBranch checks if the repository HEAD is on the default branch. Returns (isOnDefault, currentBranchName). NOTE: Duplicated from cli/git_operations.go - see ENT-129 for consolidation.

func IsShadowBranch

func IsShadowBranch(branchName string) bool

IsShadowBranch returns true if the branch name matches the shadow branch pattern. Shadow branches have the format "entire/<commit-hash>-<worktree-hash>" where the commit hash is at least 7 hex characters and worktree hash is 6 hex characters. The "entire/checkpoints/v1" branch is NOT a shadow branch.

func ListShadowBranches

func ListShadowBranches(ctx context.Context) ([]string, error)

ListShadowBranches returns all shadow branches in the repository. Shadow branches match the pattern "entire/<commit-hash>" (7+ hex chars). The "entire/checkpoints/v1" branch is excluded as it stores permanent metadata. Returns an empty slice (not nil) if no shadow branches exist.

func LoadModelHint added in v0.5.0

func LoadModelHint(ctx context.Context, sessionID string) string

LoadModelHint reads the LLM model name from the hint file for the given session. Returns empty string if the hint file doesn't exist or can't be read.

func ManagedGitHookNames added in v0.4.4

func ManagedGitHookNames() []string

ManagedGitHookNames returns the list of git hooks managed by Entire CLI. This is useful for tests that need to manipulate hooks.

func OpenRepository

func OpenRepository(ctx context.Context) (*git.Repository, error)

OpenRepository opens the git repository from the repo root. It uses 'git rev-parse --show-toplevel' to find the repository root, which works correctly even when called from a subdirectory or a linked worktree.

func PromptOverwriteNewerLogs

func PromptOverwriteNewerLogs(errW io.Writer, sessions []SessionRestoreInfo) (bool, error)

PromptOverwriteNewerLogs asks the user for confirmation to overwrite local session logs that have newer timestamps than the checkpoint versions.

func PushTrailsBranch added in v0.5.0

func PushTrailsBranch(ctx context.Context, remote string) error

PushTrailsBranch pushes the entire/trails/v1 branch to the remote. Trails are always pushed regardless of the push_sessions setting.

func ReadAgentTypeFromTree added in v0.4.4

func ReadAgentTypeFromTree(tree *object.Tree, checkpointPath string) types.AgentType

ReadAgentTypeFromTree reads the agent type from a checkpoint's metadata.json file in a git tree. If metadata.json doesn't exist (shadow branches), it falls back to detecting the agent from the presence of agent-specific config files (.gemini/settings.json or .claude/). Returns agent.AgentTypeUnknown if the agent type cannot be determined.

func ReadAllSessionPromptsFromTree

func ReadAllSessionPromptsFromTree(tree *object.Tree, checkpointPath string, sessionCount int, sessionIDs []string) []string

ReadAllSessionPromptsFromTree reads the first prompt for all sessions in a multi-session checkpoint. Returns a slice of prompts parallel to sessionIDs (oldest to newest). For single-session checkpoints, returns a slice with just the root prompt.

func ReadLatestSessionPromptFromCommittedTree added in v0.4.9

func ReadLatestSessionPromptFromCommittedTree(tree *object.Tree, cpID id.CheckpointID, sessionCount int) string

ReadLatestSessionPromptFromCommittedTree reads the first prompt from a committed checkpoint's latest session on the metadata branch tree. This navigates the sharded directory layout: <cpID.Path()>/<latestSessionIndex>/prompt.txt

Falls back through earlier sessions when the latest has no prompt. Avoids reading full transcripts — only reads prompt.txt files. sessionCount is the number of sessions in the checkpoint (from CommittedInfo.SessionCount).

func ReadSessionPromptFromTree

func ReadSessionPromptFromTree(tree *object.Tree, checkpointPath string) string

ReadSessionPromptFromTree reads the first meaningful prompt from a checkpoint's prompt.txt file in a git tree. Returns an empty string if the prompt cannot be read.

func ReconcileDisconnectedMetadataBranch added in v0.5.0

func ReconcileDisconnectedMetadataBranch(ctx context.Context, repo *git.Repository, w io.Writer) error

ReconcileDisconnectedMetadataBranch detects and repairs disconnected local/remote entire/checkpoints/v1 branches. Disconnected means no common ancestor, which only happens due to the empty-orphan bug. Diverged (shared ancestor) is normal and handled by the push path's tree merge.

Repair strategy: cherry-pick local commits onto remote tip, preserving all data. Checkpoint shards use unique paths (<id[:2]>/<id[2:]>/), so cherry-picks always apply cleanly.

Progress messages are written to w (typically os.Stderr for hooks or cmd.ErrOrStderr() for commands).

func RemoveGitHook

func RemoveGitHook(ctx context.Context) (int, error)

RemoveGitHook removes all Entire CLI git hooks from the repository. If a .pre-entire backup exists, it is restored. Returns the number of hooks removed.

func ResolveAgentForRewind added in v0.4.3

func ResolveAgentForRewind(agentType types.AgentType) (agent.Agent, error)

ResolveAgentForRewind resolves the agent from checkpoint metadata.

func SaveSessionState

func SaveSessionState(ctx context.Context, state *SessionState) error

SaveSessionState saves the session state atomically.

func StatusToText

func StatusToText(status SessionRestoreStatus) string

StatusToText returns a human-readable status string.

func StoreModelHint added in v0.5.0

func StoreModelHint(ctx context.Context, sessionID, model string) error

StoreModelHint writes the LLM model name to a lightweight hint file (.git/entire-sessions/{session_id}.model) for cross-process persistence.

Why a separate file instead of SessionState?

SessionState requires BaseCommit (used for shadow branch naming, checkpoint writing, doctor classification, etc.) and is only created during TurnStart when the git repo is fully inspected. Some agents report the model on earlier hooks that fire as separate CLI processes before TurnStart:

  • Claude Code sends "model" on SessionStart (before any TurnStart)
  • Gemini CLI sends "llm_request.model" on BeforeModel (after TurnStart, so handleLifecycleModelUpdate writes to SessionState directly when it exists and only falls back to this hint file otherwise)

The hint is read by handleLifecycleTurnStart/TurnEnd when event.Model is empty, passed to InitializeSession, and persisted in state.ModelName. After that the hint file is redundant — it sits unused until ClearSessionState removes it alongside the session state file.

func TaskMetadataDir

func TaskMetadataDir(sessionMetadataDir, toolUseID string) string

TaskMetadataDir returns the path to a task's metadata directory within the session metadata directory.

func TransitionAndLog added in v0.3.13

func TransitionAndLog(goCtx context.Context, state *SessionState, event session.Event, ctx session.TransitionContext, handler session.ActionHandler) error

TransitionAndLog runs a session phase transition, applies actions via the handler, and logs the transition. Returns the first handler error from ApplyTransition (if any) so callers can surface it. The error is also logged internally for diagnostics. This is the single entry point for all state machine transitions to ensure consistent logging of phase changes.

func TruncateDescription

func TruncateDescription(s string, maxLen int) string

TruncateDescription truncates a string to maxLen runes, adding "..." if truncated. Uses rune-based slicing to avoid splitting multi-byte UTF-8 characters. If maxLen is less than 3, truncates without ellipsis.

func WarnIfMetadataDisconnected added in v0.5.0

func WarnIfMetadataDisconnected()

WarnIfMetadataDisconnected checks (once per process) whether the metadata branch is disconnected and prints a warning to stderr if so. It does NOT fix the problem — users are directed to 'entire doctor'.

Uses sync.Once, so a transient failure on the first call permanently suppresses the warning. This is acceptable because the check is advisory only and 'entire doctor' is the authoritative repair path.

Types

type Checkpoint

type Checkpoint struct {
	// CheckpointID is the stable 12-hex-char identifier for this checkpoint.
	// Used to look up metadata at <id[:2]>/<id[2:]>/ on entire/checkpoints/v1 branch.
	CheckpointID id.CheckpointID

	// Message is the commit message or checkpoint description
	Message string

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

	// IsTaskCheckpoint indicates if this is a task checkpoint (vs a session checkpoint)
	IsTaskCheckpoint bool

	// ToolUseID is the tool use ID for task checkpoints (empty for session checkpoints)
	ToolUseID string
}

Checkpoint represents a save point within a session. Checkpoints can be either session-level (on Stop) or task-level (on subagent completion).

type CheckpointInfo

type CheckpointInfo struct {
	CheckpointID     id.CheckpointID `json:"checkpoint_id"` // 12-hex-char from Entire-Checkpoint trailer, used as directory path
	SessionID        string          `json:"session_id"`
	CreatedAt        time.Time       `json:"created_at"`
	CheckpointsCount int             `json:"checkpoints_count"`
	FilesTouched     []string        `json:"files_touched"`
	Agent            types.AgentType `json:"agent,omitempty"` // Human-readable agent name (e.g., "Claude Code")
	IsTask           bool            `json:"is_task,omitempty"`
	ToolUseID        string          `json:"tool_use_id,omitempty"`
	SessionCount     int             `json:"session_count,omitempty"` // Number of sessions (1 if omitted)
	SessionIDs       []string        `json:"session_ids,omitempty"`   // All session IDs in this checkpoint
}

CheckpointInfo represents checkpoint metadata stored on the sessions branch. Metadata is stored at sharded path: <checkpoint_id[:2]>/<checkpoint_id[2:]>/

func ListCheckpoints

func ListCheckpoints(ctx context.Context) ([]CheckpointInfo, error)

ListCheckpoints returns all checkpoints from the entire/checkpoints/v1 branch. Scans sharded paths: <id[:2]>/<id[2:]>/ directories containing metadata.json.

func ReadCheckpointMetadata

func ReadCheckpointMetadata(tree checkpoint.FileReader, checkpointPath string) (*CheckpointInfo, error)

ReadCheckpointMetadata reads metadata.json from a checkpoint path on entire/checkpoints/v1. With the new format, root metadata.json is a CheckpointSummary with Agents array. This function reads the summary and extracts relevant fields into CheckpointInfo, also reading session-level metadata for IsTask/ToolUseID fields.

Uses streaming json.Decoder and minimal structs to avoid loading large nested objects (Summary, InitialAttribution, TokenUsage) into memory.

func ReadCheckpointMetadataFromSubtree added in v0.5.1

func ReadCheckpointMetadataFromSubtree(tree checkpoint.FileReader, checkpointPath string) (*CheckpointInfo, error)

ReadCheckpointMetadataFromSubtree reads checkpoint metadata from a tree that is already rooted at the checkpoint directory (e.g., after tree.Tree(checkpointID.Path())). checkpointPath is the original sharded path (e.g., "ca/b75de47439") and is used to strip the prefix from absolute session metadata paths stored in the summary.

func ResolveLatestCheckpointFromMap added in v0.5.0

func ResolveLatestCheckpointFromMap(cpIDs []id.CheckpointID, infoMap map[id.CheckpointID]CheckpointInfo) (CheckpointInfo, bool)

ResolveLatestCheckpointFromMap picks the checkpoint with the latest CreatedAt from a list of checkpoint IDs. Filters to IDs present in infoMap, then picks the one with the most recent CreatedAt.

type CleanupItem

type CleanupItem struct {
	Type   CleanupType
	ID     string // Branch name, session ID, or checkpoint ID
	Reason string // Why this item is considered orphaned
}

CleanupItem represents an orphaned item that can be cleaned up.

func ListAllCleanupItems

func ListAllCleanupItems(ctx context.Context) ([]CleanupItem, error)

ListAllCleanupItems returns all orphaned items across all categories. It iterates over all registered strategies and calls ListOrphanedItems on those that implement OrphanedItemsLister. Returns an error if the repository cannot be opened.

func ListOrphanedSessionStates

func ListOrphanedSessionStates(ctx context.Context) ([]CleanupItem, error)

ListOrphanedSessionStates returns session state files that are orphaned. A session state is orphaned if:

  • No checkpoints on entire/checkpoints/v1 reference this session ID
  • No shadow branch exists for the session's base commit

This is strategy-agnostic as session states are shared by all strategies.

type CleanupResult

type CleanupResult struct {
	ShadowBranches    []string // Deleted shadow branches
	SessionStates     []string // Deleted session state files
	Checkpoints       []string // Deleted checkpoint metadata
	FailedBranches    []string // Shadow branches that failed to delete
	FailedStates      []string // Session states that failed to delete
	FailedCheckpoints []string // Checkpoints that failed to delete
}

CleanupResult contains the results of a cleanup operation.

func DeleteAllCleanupItems

func DeleteAllCleanupItems(ctx context.Context, items []CleanupItem) (*CleanupResult, error)

DeleteAllCleanupItems deletes all specified cleanup items. Logs each deletion for audit purposes.

type CleanupType

type CleanupType string

CleanupType identifies the type of orphaned item.

const (
	CleanupTypeShadowBranch CleanupType = "shadow-branch"
	CleanupTypeSessionState CleanupType = "session-state"
	CleanupTypeCheckpoint   CleanupType = "checkpoint"
)

type CondenseResult

type CondenseResult struct {
	CheckpointID         id.CheckpointID // 12-hex-char from Entire-Checkpoint trailer, used as directory path
	SessionID            string
	CheckpointsCount     int
	FilesTouched         []string
	Prompts              []string // User prompts from the condensed session
	TotalTranscriptLines int      // Total lines in transcript after this condensation
	Transcript           []byte   // Raw transcript bytes for downstream consumers (trail title generation)
}

CondenseResult contains the result of a session condensation operation.

type ExtractedSessionData

type ExtractedSessionData struct {
	Transcript          []byte   // Full transcript content for the session
	FullTranscriptLines int      // Total line count in full transcript
	Prompts             []string // User prompts from the current checkpoint portion
	FilesTouched        []string
	TokenUsage          *agent.TokenUsage // Token usage calculated from transcript (since CheckpointTranscriptStart)
}

ExtractedSessionData contains data extracted from a shadow branch.

type ManualCommitStrategy

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

ManualCommitStrategy implements the manual-commit strategy for session management. It stores checkpoints on shadow branches and condenses session logs to a permanent sessions branch when the user commits.

func NewManualCommitStrategy

func NewManualCommitStrategy() *ManualCommitStrategy

NewManualCommitStrategy creates a new manual-commit strategy instance.

func (*ManualCommitStrategy) CanRewind

func (s *ManualCommitStrategy) CanRewind(ctx context.Context) (bool, string, error)

CanRewind checks if rewinding is possible. For manual-commit strategy, rewind restores files from a checkpoint - uncommitted changes are expected and will be replaced by the checkpoint contents. Returns true with a warning message showing what changes will be reverted.

func (*ManualCommitStrategy) ClearSessionState

func (s *ManualCommitStrategy) ClearSessionState(ctx context.Context, sessionID string) error

ClearSessionState is the exported version of clearSessionState. Used by the rewind reset command to clean up session state files.

func (*ManualCommitStrategy) CommitMsg

func (s *ManualCommitStrategy) CommitMsg(_ context.Context, commitMsgFile string) error

func (*ManualCommitStrategy) CondenseSession

func (s *ManualCommitStrategy) CondenseSession(ctx context.Context, repo *git.Repository, checkpointID id.CheckpointID, state *SessionState, committedFiles map[string]struct{}, opts ...condenseOpts) (*CondenseResult, error)

CondenseSession condenses a session's shadow branch to permanent storage. checkpointID is the 12-hex-char value from the Entire-Checkpoint trailer. Metadata is stored at sharded path: <checkpoint_id[:2]>/<checkpoint_id[2:]>/ Uses checkpoint.GitStore.WriteCommitted for the git operations.

For mid-session commits (no Stop/SaveStep called yet), the shadow branch may not exist. In this case, data is extracted from the live transcript instead.

func (*ManualCommitStrategy) CondenseSessionByID added in v0.3.13

func (s *ManualCommitStrategy) CondenseSessionByID(ctx context.Context, sessionID string) error

CondenseSessionByID force-condenses a session by its ID and cleans up. This is used by "entire doctor" to salvage stuck sessions.

func (*ManualCommitStrategy) CountOtherActiveSessionsWithCheckpoints added in v0.3.12

func (s *ManualCommitStrategy) CountOtherActiveSessionsWithCheckpoints(ctx context.Context, currentSessionID string) (int, error)

CountOtherActiveSessionsWithCheckpoints counts how many other active sessions from the SAME worktree (different from currentSessionID) have created checkpoints on the SAME base commit (current HEAD). This is used to show an informational message about concurrent sessions that will be included in the next commit. Returns 0, nil if no such sessions exist.

func (*ManualCommitStrategy) FindSessionsForCommit

func (s *ManualCommitStrategy) FindSessionsForCommit(ctx context.Context, baseCommitSHA string) ([]*SessionState, error)

FindSessionsForCommit is the exported version of findSessionsForCommit. Used by the rewind reset command to find sessions to clean up.

func (*ManualCommitStrategy) GetAdditionalSessions

func (s *ManualCommitStrategy) GetAdditionalSessions(ctx context.Context) ([]*Session, error)

GetAdditionalSessions implements SessionSource interface. Returns active sessions from .git/entire-sessions/ that haven't yet been condensed.

func (*ManualCommitStrategy) GetCheckpointLog

func (s *ManualCommitStrategy) GetCheckpointLog(ctx context.Context, checkpoint Checkpoint) ([]byte, error)

GetCheckpointLog returns the session transcript for a specific checkpoint. For manual-commit strategy, metadata is stored at sharded paths on entire/checkpoints/v1 branch.

func (*ManualCommitStrategy) GetLogsOnlyRewindPoints

func (s *ManualCommitStrategy) GetLogsOnlyRewindPoints(ctx context.Context, limit int) ([]RewindPoint, error)

GetLogsOnlyRewindPoints finds commits in the current branch's history that have condensed session logs on the entire/checkpoints/v1 branch. These are commits that were created with session data but the shadow branch has been condensed.

The function works by: 1. Getting all checkpoints from the entire/checkpoints/v1 branch 2. Building a map of checkpoint ID -> checkpoint info 3. Scanning the current branch history for commits with Entire-Checkpoint trailers 4. Matching by checkpoint ID (stable across amend/rebase)

func (*ManualCommitStrategy) GetMetadataRef

func (s *ManualCommitStrategy) GetMetadataRef(_ context.Context, checkpoint Checkpoint) string

GetMetadataRef returns a reference to the metadata for the given checkpoint. For manual-commit strategy, returns the sharded path on entire/checkpoints/v1 branch.

func (*ManualCommitStrategy) GetRewindPoints

func (s *ManualCommitStrategy) GetRewindPoints(ctx context.Context, limit int) ([]RewindPoint, error)

GetRewindPoints returns available rewind points. Uses checkpoint.GitStore.ListTemporaryCheckpoints for reading from shadow branches.

func (*ManualCommitStrategy) GetSessionInfo

func (s *ManualCommitStrategy) GetSessionInfo(ctx context.Context) (*SessionInfo, error)

GetSessionInfo returns the current session info.

func (*ManualCommitStrategy) GetSessionMetadataRef

func (s *ManualCommitStrategy) GetSessionMetadataRef(ctx context.Context, _ string) string

GetSessionMetadataRef returns a reference to the most recent metadata commit for a session. For manual-commit strategy, metadata lives on the entire/checkpoints/v1 branch.

func (*ManualCommitStrategy) GetTaskCheckpoint

func (s *ManualCommitStrategy) GetTaskCheckpoint(ctx context.Context, point RewindPoint) (*TaskCheckpoint, error)

GetTaskCheckpoint retrieves a task checkpoint.

func (*ManualCommitStrategy) GetTaskCheckpointTranscript

func (s *ManualCommitStrategy) GetTaskCheckpointTranscript(ctx context.Context, point RewindPoint) ([]byte, error)

GetTaskCheckpointTranscript retrieves the transcript for a task checkpoint.

func (*ManualCommitStrategy) HandleTurnEnd added in v0.3.13

func (s *ManualCommitStrategy) HandleTurnEnd(ctx context.Context, state *SessionState) error

func (*ManualCommitStrategy) HasBlobFetcher added in v0.5.1

func (s *ManualCommitStrategy) HasBlobFetcher() bool

HasBlobFetcher reports whether a blob fetcher is configured. Used in tests to verify the strategy is properly wired for treeless fetch support.

func (*ManualCommitStrategy) InitializeSession

func (s *ManualCommitStrategy) InitializeSession(ctx context.Context, sessionID string, agentType types.AgentType, transcriptPath string, userPrompt string, model string) error

InitializeSession creates session state for a new session or updates an existing one. This implements the optional SessionInitializer interface. Called during UserPromptSubmit to allow git hooks to detect active sessions.

If the session already exists and HEAD has moved (e.g., user committed), updates BaseCommit to the new HEAD so future checkpoints go to the correct shadow branch.

If there's an existing shadow branch with commits from a different session ID, returns a SessionIDConflictError to prevent orphaning existing session work.

agentType is the human-readable name of the agent (e.g., "Claude Code"). transcriptPath is the path to the live transcript file (for mid-session commit detection). userPrompt is the user's prompt text (stored truncated as LastPrompt for display). model is the LLM model identifier (e.g., "claude-sonnet-4-20250514"); empty if unknown.

func (*ManualCommitStrategy) ListOrphanedItems

func (s *ManualCommitStrategy) ListOrphanedItems(ctx context.Context) ([]CleanupItem, error)

ListOrphanedItems returns orphaned items created by the manual-commit strategy. This includes:

  • Shadow branches that weren't auto-cleaned during commit condensation
  • Session state files with no corresponding checkpoints or shadow branches

func (*ManualCommitStrategy) PostCommit

func (s *ManualCommitStrategy) PostCommit(ctx context.Context) error

func (*ManualCommitStrategy) PrePush

func (s *ManualCommitStrategy) PrePush(ctx context.Context, remote string) error

PrePush is called by the git pre-push hook before pushing to a remote. It pushes the entire/checkpoints/v1 branch alongside the user's push.

If a checkpoint_remote is configured in settings, the checkpoint branch is pushed to the derived URL instead of the user's push remote. Trails always go to the user's push remote.

Configuration options (stored in .entire/settings.json under strategy_options):

  • push_sessions: false to disable automatic pushing of checkpoints
  • checkpoint_remote: {"provider": "github", "repo": "org/repo"} to push to a separate repo

func (*ManualCommitStrategy) PrepareCommitMsg

func (s *ManualCommitStrategy) PrepareCommitMsg(ctx context.Context, commitMsgFile string, source string) error

func (*ManualCommitStrategy) PreviewRewind

func (s *ManualCommitStrategy) PreviewRewind(ctx context.Context, point RewindPoint) (*RewindPreview, error)

PreviewRewind returns what will happen if rewinding to the given point. This allows showing warnings about untracked files that will be deleted.

func (*ManualCommitStrategy) Reset

func (s *ManualCommitStrategy) Reset(ctx context.Context, w, errW io.Writer) error

Reset deletes the shadow branch and session state for the current HEAD. This allows starting fresh without existing checkpoints.

func (*ManualCommitStrategy) ResetSession added in v0.3.13

func (s *ManualCommitStrategy) ResetSession(ctx context.Context, w, errW io.Writer, sessionID string) error

ResetSession clears a single session's state and removes the shadow branch if no other sessions reference it. File changes remain in the working directory.

func (*ManualCommitStrategy) RestoreLogsOnly

func (s *ManualCommitStrategy) RestoreLogsOnly(ctx context.Context, w, errW io.Writer, point RewindPoint, force bool) ([]RestoredSession, error)

RestoreLogsOnly restores session logs from a logs-only rewind point. This fetches the transcript from entire/checkpoints/v1 and writes it to the agent's session directory. Does not modify the working directory. When multiple sessions were condensed to the same checkpoint, ALL sessions are restored. If force is false, prompts for confirmation when local logs have newer timestamps. Returns info about each restored session so callers can print correct per-session resume commands.

func (*ManualCommitStrategy) Rewind

func (s *ManualCommitStrategy) Rewind(ctx context.Context, w, errW io.Writer, point RewindPoint) error

func (*ManualCommitStrategy) SaveStep added in v0.4.6

func (s *ManualCommitStrategy) SaveStep(ctx context.Context, step StepContext) error

SaveStep saves a checkpoint to the shadow branch. Uses checkpoint.GitStore.WriteTemporary for git operations.

func (*ManualCommitStrategy) SaveTaskStep added in v0.4.6

func (s *ManualCommitStrategy) SaveTaskStep(ctx context.Context, step TaskStepContext) error

SaveTaskStep saves a task step checkpoint to the shadow branch. Uses checkpoint.GitStore.WriteTemporaryTask for git operations.

func (*ManualCommitStrategy) SetBlobFetcher added in v0.5.1

func (s *ManualCommitStrategy) SetBlobFetcher(f checkpoint.BlobFetchFunc)

SetBlobFetcher configures on-demand blob fetching for the checkpoint store. Must be called before the first checkpoint store access (e.g., before RestoreLogsOnly).

func (*ManualCommitStrategy) ValidateRepository

func (s *ManualCommitStrategy) ValidateRepository() error

ValidateRepository validates that the repository is suitable for this strategy.

type PromptAttribution

type PromptAttribution = session.PromptAttribution

PromptAttribution is an alias for session.PromptAttribution.

func CalculatePromptAttribution

func CalculatePromptAttribution(
	baseTree *object.Tree,
	lastCheckpointTree *object.Tree,
	worktreeFiles map[string]string,
	checkpointNumber int,
) PromptAttribution

CalculatePromptAttribution computes line-level attribution at the start of a prompt. This captures user edits since the last checkpoint BEFORE the agent makes changes.

Parameters:

  • baseTree: the tree at session start (the base commit)
  • lastCheckpointTree: the tree from the previous checkpoint (nil if first checkpoint)
  • worktreeFiles: map of file path → current worktree content for files that changed
  • checkpointNumber: which checkpoint we're about to create (1-indexed)

Returns the attribution data to store in session state. For checkpoint 1 (when lastCheckpointTree is nil), AgentLinesAdded/Removed will be 0 since there's no previous checkpoint to measure cumulative agent work against.

Note: Binary files (detected by null bytes) in reference trees are silently excluded from attribution calculations since line-based diffing only applies to text files.

type RestoredSession added in v0.4.3

type RestoredSession struct {
	SessionID string
	Agent     types.AgentType
	Prompt    string
	CreatedAt time.Time // From session metadata; used by resume to determine most recent
}

RestoredSession describes a single session that was restored by RestoreLogsOnly. Each session may come from a different agent, so callers use this to print per-session resume commands without re-reading the metadata tree.

type RewindPoint

type RewindPoint struct {
	// ID is the unique identifier for this rewind point
	// (commit hash, branch name, stash ref, etc.)
	ID string

	// Message is the human-readable description/summary
	Message string

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

	// Date is when this rewind point was created
	Date time.Time

	// IsTaskCheckpoint indicates if this is a task checkpoint (vs a session checkpoint)
	IsTaskCheckpoint bool

	// ToolUseID is the tool use ID for task checkpoints (empty for session checkpoints)
	ToolUseID string

	// IsLogsOnly indicates this is a commit with session logs but no shadow branch state.
	// The logs can be restored from entire/checkpoints/v1, but file state requires git checkout.
	IsLogsOnly bool

	// CheckpointID is the stable 12-hex-char identifier for logs-only points.
	// Used to retrieve logs from entire/checkpoints/v1/<id[:2]>/<id[2:]>/full.jsonl
	// Empty for shadow branch checkpoints (uncommitted).
	CheckpointID id.CheckpointID

	// Agent is the human-readable name of the agent that created this checkpoint
	// (e.g., "Claude Code", "Cursor")
	Agent types.AgentType

	// SessionID is the session identifier for this checkpoint.
	// Used to distinguish checkpoints from different concurrent sessions.
	SessionID string

	// SessionPrompt is the initial prompt that started this session.
	// Used to help users identify which session a checkpoint belongs to.
	SessionPrompt string

	// SessionCount is the number of sessions in this checkpoint (1 for single-session).
	// Only populated for logs-only points with multi-session checkpoints.
	SessionCount int

	// SessionIDs contains all session IDs when this is a multi-session checkpoint.
	// The last entry is the most recent session (same as SessionID).
	// Only populated for logs-only points with multi-session checkpoints.
	SessionIDs []string

	// SessionPrompts contains the first prompt for each session (parallel to SessionIDs).
	// Used to display context when showing resume commands for multi-session checkpoints.
	SessionPrompts []string
}

RewindPoint represents a point to which the user can rewind. This abstraction allows different strategies to use different identifiers (commit hashes, branch names, stash refs, etc.)

type RewindPreview

type RewindPreview struct {
	// FilesToRestore are files from the checkpoint that will be written/restored.
	FilesToRestore []string

	// FilesToDelete are untracked files that will be removed.
	// These are files created after the checkpoint that aren't in the checkpoint tree
	// and weren't present at session start.
	FilesToDelete []string

	// TrackedChanges are tracked files with uncommitted changes that will be reverted.
	// These come from the existing CanRewind() warning.
	TrackedChanges []string
}

RewindPreview describes what will happen when rewinding to a checkpoint. Used to warn users about files that will be modified or deleted.

type Session

type Session struct {
	// ID is the unique session identifier (e.g., "2025-12-01-8f76b0e8-b8f1-4a87-9186-848bdd83d62e")
	ID string

	// Description is a human-readable summary of the session
	// (typically the first prompt or derived from commit messages)
	Description string

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

	// StartTime is when the session was started
	StartTime time.Time

	// Checkpoints is the list of save points within this session
	Checkpoints []Checkpoint
}

Session represents a Claude Code session with its checkpoints. A session is created when a user runs `claude` and tracks all changes made during that interaction.

func GetSession

func GetSession(ctx context.Context, sessionID string) (*Session, error)

GetSession finds a session by ID (supports prefix matching). Returns ErrNoSession if no matching session is found.

func ListSessions

func ListSessions(ctx context.Context) ([]Session, error)

ListSessions returns all sessions from the entire/checkpoints/v1 branch, plus any additional sessions from strategies implementing SessionSource. It automatically discovers all registered strategies and merges their sessions.

type SessionInfo

type SessionInfo struct {
	// SessionID is the session identifier extracted from the latest commit's metadata
	SessionID string

	// Reference is a strategy-specific reference string.
	// For manual-commit strategy: "entire/abc1234" (the shadow branch name)
	// Empty for commit strategy (metadata is in the same commit).
	Reference string

	// CommitHash is the full SHA of the commit containing the session metadata.
	// Empty for commit strategy.
	CommitHash string
}

SessionInfo contains information about the current session state. This is used to generate trailers for linking commits to their AI session.

type SessionRestoreInfo

type SessionRestoreInfo struct {
	SessionID      string
	Prompt         string               // First prompt preview for display
	Status         SessionRestoreStatus // Status of this session
	LocalTime      time.Time
	CheckpointTime time.Time
}

SessionRestoreInfo contains information about a session being restored.

type SessionRestoreStatus

type SessionRestoreStatus int

SessionRestoreStatus represents the status of a session being restored.

const (
	StatusNew             SessionRestoreStatus = iota // Local file doesn't exist
	StatusUnchanged                                   // Local and checkpoint are the same
	StatusCheckpointNewer                             // Checkpoint has newer entries
	StatusLocalNewer                                  // Local has newer entries (conflict)
)

func ClassifyTimestamps

func ClassifyTimestamps(localTime, checkpointTime time.Time) SessionRestoreStatus

ClassifyTimestamps determines the restore status based on local and checkpoint timestamps.

type SessionState

type SessionState = session.State

SessionState is an alias for session.State. Previously this was a separate struct with manual conversion functions.

func ListSessionStates added in v0.3.13

func ListSessionStates(ctx context.Context) ([]*SessionState, error)

ListSessionStates returns all session states from the state directory. This is a package-level function that doesn't require a specific strategy instance.

func LoadSessionState

func LoadSessionState(ctx context.Context, sessionID string) (*SessionState, error)

LoadSessionState loads the session state for the given session ID. Returns (nil, nil) when session file doesn't exist or session is stale (not an error condition). Stale sessions are automatically deleted by the underlying StateStore.

type StepContext added in v0.4.6

type StepContext struct {
	// SessionID is the Claude Code session identifier
	SessionID string

	// ModifiedFiles is the list of files modified during the session
	// (extracted from the transcript, already filtered and relative)
	ModifiedFiles []string

	// NewFiles is the list of new files created during the session
	// (pre-computed by CLI from pre-prompt state comparison)
	NewFiles []string

	// DeletedFiles is the list of files deleted during the session
	// (tracked files that no longer exist)
	DeletedFiles []string

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

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

	// CommitMessage is the generated commit message
	CommitMessage string

	// TranscriptPath is the path to the transcript file
	TranscriptPath string

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

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

	// AgentType is the human-readable agent name (e.g., "Claude Code", "Cursor")
	AgentType types.AgentType

	// Transcript position at step/turn start - tracks what was added during this step
	StepTranscriptIdentifier string // Last identifier when step started (UUID for Claude, message ID for Gemini)
	StepTranscriptStart      int    // Transcript line count when this step/turn started

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

StepContext contains all information needed for saving a step checkpoint. All file paths should be pre-filtered and normalized by the CLI layer.

type SubagentCheckpoint

type SubagentCheckpoint struct {
	Type      string          `json:"type"`        // Tool name: "TodoWrite", "Edit", "Write"
	ToolUseID string          `json:"tool_use_id"` // The tool use ID that created this checkpoint
	Timestamp time.Time       `json:"timestamp"`   // When the checkpoint was created
	Data      json.RawMessage `json:"data"`        // Type-specific payload (tool_input)
}

SubagentCheckpoint represents an intermediate checkpoint created during subagent execution. These are created by PostToolUse hooks for tools like TodoWrite, Edit, Write.

type TaskCheckpoint

type TaskCheckpoint struct {
	SessionID      string `json:"session_id"`
	ToolUseID      string `json:"tool_use_id"`
	CheckpointUUID string `json:"checkpoint_uuid"`
	AgentID        string `json:"agent_id,omitempty"`
}

TaskCheckpoint contains the checkpoint information written to checkpoint.json

func ReadTaskCheckpoint

func ReadTaskCheckpoint(taskMetadataDir string) (*TaskCheckpoint, error)

ReadTaskCheckpoint reads the checkpoint.json file from a task metadata directory. This is used during rewind to get the checkpoint UUID for transcript truncation. Uses os.Root for traversal-resistant file reads within the metadata directory.

type TaskStepContext added in v0.4.6

type TaskStepContext struct {
	// SessionID is the Claude Code session identifier
	SessionID string

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

	// AgentID is the subagent identifier (from tool_response.agentId)
	AgentID string

	// ModifiedFiles is the list of files modified by the subagent
	// (extracted from the subagent's transcript)
	ModifiedFiles []string

	// NewFiles is the list of new files created by the subagent
	// (computed from pre-task state comparison)
	NewFiles []string

	// DeletedFiles is the list of files deleted by the subagent
	DeletedFiles []string

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

	// SubagentTranscriptPath is the path to the subagent's transcript (if available)
	SubagentTranscriptPath string

	// CheckpointUUID is the UUID for transcript truncation when rewinding
	CheckpointUUID 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 during task execution,
	// not a final task completion checkpoint. When true:
	// - Writes to checkpoints/NNN-{tool-use-id}.json instead of checkpoint.json
	// - Skips transcript handling
	// - Uses incremental commit message
	IsIncremental bool

	// IncrementalSequence is the checkpoint sequence number (1, 2, 3, ...)
	// Only used when IsIncremental is true
	IncrementalSequence int

	// IncrementalType is the tool that triggered this checkpoint ("TodoWrite", "Edit", etc.)
	// Only used when IsIncremental is true
	IncrementalType string

	// IncrementalData is the tool_input payload for this checkpoint
	// Only used when IsIncremental is true
	IncrementalData json.RawMessage

	// SubagentType is the type of subagent (e.g., "dev", "reviewer")
	// Extracted from tool_input.subagent_type in Task tool
	// Used for descriptive commit messages
	SubagentType string

	// TaskDescription is the task description provided to the subagent
	// Extracted from tool_input.description in Task tool
	// Used for descriptive commit messages
	TaskDescription string

	// TodoContent is the content of the in-progress todo item
	// Extracted from tool_input.todos where status == "in_progress"
	// Used for descriptive incremental checkpoint messages
	TodoContent string

	// AgentType is the human-readable agent name (e.g., "Claude Code", "Cursor")
	AgentType types.AgentType
}

TaskStepContext contains all information needed for saving a task step checkpoint. This is called by the PostToolUse[Task] hook when a subagent completes. The strategy is responsible for creating metadata structures and storing them according to its storage approach.

Jump to

Keyboard shortcuts

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