checkpoint resume: add command with target resolution · Entire
checkpoint resume: add command with target resolution
677c3ce→main·
pfleidi·1w ago·3 files·+391 added/-2 removed
Resume agent sessions by checkpoint ID, commit SHA, or branch. Checkpoint and commit targets check out the containing branch at its tip (restore-only when no local branch contains the checkpoint); branch targets reuse the session-resume flow. Auto-detection tries checkpoint, then branch, then commit; --checkpoint/--commit/--branch force one interpretation.
Sessions
01KWYRTVSDQ4WRJ7WQVB0PA0VTView transcript
Changes
3
cmd/entire/cli
Mcheckpoint_group.go+5/-2
Acheckpoint_resume.go+213
Acheckpoint_resume_test.go+173
7 unmodified lines
8
9
10
11
11
12
13
14
6 unmodified lines
21
22
23
24
25
26
27
28
29
29
30
31
32
33
34
3 unmodified lines
38
39
40
41
42
43
44
7 unmodified lines
)
// newCheckpointGroupCmd builds the `entire checkpoint` parent command and
// registers list/explain/tokens/search as children, plus the deprecated rewind.
// registers list/explain/tokens/search/resume as children, plus the deprecated rewind.
func newCheckpointGroupCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "checkpoint",
6 unmodified lines
explain Explain a checkpoint, commit, or session
tokens Show token usage and optimization recommendations
search Search checkpoints (semantic + keyword)
resume Resume the agent session(s) recorded in a checkpoint
Examples:
entire checkpoint list
entire checkpoint explain <id|sha>
entire checkpoint tokens <id>
entire checkpoint search "fix login"`,
entire checkpoint search "fix login"
entire checkpoint resume <id|sha|branch>`,
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
if _, err := paths.WorktreeRoot(cmd.Context()); err != nil {
return errors.New("not a git repository")
3 unmodified lines
}
cmd.AddCommand(newCheckpointListCmd())
cmd.AddCommand(newCheckpointResumeCmd())
cmd.AddCommand(newExplainCmd())
cmd.AddCommand(newCheckpointTokensCmd())
cmd.AddCommand(newCheckpointPolicyCmd())
}
Mcmd/entire/cli/checkpoint_group.go+5/-2
``
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package cli
import (
"context"
"errors"
"fmt"
"regexp"
"github.com/entireio/cli/cmd/entire/cli/agent/external"
"github.com/entireio/cli/cmd/entire/cli/checkpoint/id"
"github.com/entireio/cli/cmd/entire/cli/logging"
"github.com/entireio/cli/cmd/entire/cli/paths"
"github.com/entireio/cli/cmd/entire/cli/trailers"
"github.com/spf13/cobra"
)
// checkpointPrefixShape matches strings that could be a checkpoint ID or a
// prefix of one (legacy 12-hex or 26-char Crockford ULID). Targets that can't
// be checkpoint IDs (e.g. "feature/foo") skip the store lookup and its
// remote-fetch fallback entirely.
var checkpointPrefixShape = regexp.MustCompile(`^(?:[0-9a-f]{1,12}|[0-9ABCDEFGHJKMNPQRSTVWXYZ]{1,26})$`)
var errNoResumeCommit = errors.New("no commit found")
func newCheckpointResumeCmd() *cobra.Command {
var checkpointFlag string
var commitFlag string
var branchFlag string
var force bool
cmd := &cobra.Command{
Use: "resume [checkpoint-id | commit-sha | branch]",
Short: "Resume the agent session(s) recorded in a checkpoint",
Long: `Resume agent sessions from a committed checkpoint.
The target can be a checkpoint ID (or prefix), a commit SHA (or ref) whose
message carries an Entire-Checkpoint trailer, or a branch name. Auto-detection
tries checkpoint ID first, then branch, then commit; use the flags to force
one interpretation.
For a checkpoint or commit target, the branch containing the checkpoint's
commit is checked out at its current tip before the session logs are
restored. If no local branch contains it, the session logs are restored
without switching branches. A branch target behaves like
'entire session resume <branch>'.
With no target, shows recent checkpoints: an interactive picker on a
terminal, a plain-text list otherwise.
Existing local session logs are never overwritten unless --force is given.
`,
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
if checkDisabledGuard(cmd.Context(), cmd.OutOrStdout()) {
return nil
}
var positional string
if len(args) > 0 {
positional = args[0]
if checkpointFlag != "" || commitFlag != "" || branchFlag != "" {
return errors.New("cannot combine positional argument with --checkpoint, --commit, or --branch")
}
}
if _, err := paths.WorktreeRoot(cmd.Context()); err == nil {
logging.SetLogLevelGetter(GetLogLevel)
if err := logging.Init(cmd.Context(), ""); err == nil {
defer logging.Close()
}
}
external.DiscoverAndRegister(cmd.Context())
return runCheckpointResume(cmd.Context(), cmd, positional, checkpointFlag, commitFlag, branchFlag, force)
},
cmd.Flags().StringVarP(&checkpointFlag, "checkpoint", "c", "", "Resume a specific checkpoint (ID or prefix)")
cmd.Flags().StringVar(&commitFlag, "commit", "", "Resume the checkpoint referenced by a commit (SHA or ref)")
cmd.Flags().StringVar(&branchFlag, "branch", "", "Resume the latest checkpoint on a branch")
cmd.Flags().BoolVarP(&force, "force", "f", false, "Skip confirmations and overwrite existing local session logs")
cmd.MarkFlagsMutuallyExclusive("checkpoint", "commit", "branch")
return cmd
}
func runCheckpointResume(ctx context.Context, cmd *cobra.Command, target, checkpointFlag, commitFlag, branchFlag string, force bool) error {
if branchFlag != "" {
return runResume(ctx, cmd, branchFlag, force)
}
lookup, err := newExplainCheckpointLookup(ctx)
if err != nil {
return err
}
initialLookup := lookup
defer func() {
if lookup != nil && lookup != initialLookup {
_ = lookup.Close()
}
_ = initialLookup.Close()
}()
switch {
case checkpointFlag != "":
var matches []id.CheckpointID
matches, lookup = matchCheckpointPrefixWithRemoteFallback(ctx, cmd.ErrOrStderr(), lookup, checkpointFlag)
return resumeMatchedCheckpoints(ctx, cmd, lookup, checkpointFlag, matches, force)
case commitFlag != "":
return resumeCommitTarget(ctx, cmd, lookup, commitFlag, force)
case target != "":
var resumeErr error
lookup, resumeErr = resumeAutoTarget(ctx, cmd, lookup, target, force)
return resumeErr
default:
return runCheckpointResumePicker(ctx, cmd, lookup, force)
}
}
// resumeAutoTarget resolves a positional target: checkpoint-ID prefix first,
// then branch (local or origin-tracking, no network), then commit revision.
// Returns the possibly-swapped lookup so the caller's deferred close stays
// correct.
func resumeAutoTarget(ctx context.Context, cmd *cobra.Command, lookup *explainCheckpointLookup, target string, force bool) (*explainCheckpointLookup, error) {
if checkpointPrefixShape.MatchString(target) {
var matches []id.CheckpointID
matches, lookup = matchCheckpointPrefixWithRemoteFallback(ctx, cmd.ErrOrStderr(), lookup, target)
if len(matches) > 0 {
return lookup, resumeMatchedCheckpoints(ctx, cmd, lookup, target, matches, force)
}
}
if _, err := branchCommit(lookup.repo, target); err == nil {
return lookup, runResume(ctx, cmd, target, force)
}
err := resumeCommitTarget(ctx, cmd, lookup, target, force)
if errors.Is(err, errNoResumeCommit) {
return lookup, fmt.Errorf("nothing matched %q as a checkpoint ID, branch, or commit\nHint: run 'entire checkpoint list' to see available checkpoints", target)
}
return lookup, err
}
func resumeMatchedCheckpoints(ctx context.Context, cmd *cobra.Command, lookup *explainCheckpointLookup, prefix string, matches []id.CheckpointID, force bool) error {
switch len(matches) {
case 0:
return fmt.Errorf("no committed checkpoint matched %q\nHint: run 'entire checkpoint list' to see available checkpoints", prefix)
case 1:
return resumeResolvedCheckpoint(ctx, cmd, lookup, matches[0], force)
default:
renderAmbiguousPrefixFailure(cmd.ErrOrStderr(), prefix, "committed checkpoints", buildAmbiguousCheckpointMatches(matches, lookup.committed))
return NewSilentError(fmt.Errorf("%w: %s matches %d checkpoints", errAmbiguousCommitPrefix, prefix, len(matches)))
}
}
// resumeCommitTarget resolves ref to a commit and resumes the checkpoint its
// Entire-Checkpoint trailer references. Multiple trailers (squash merge)
// resolve to the newest checkpoint by CreatedAt.
func resumeCommitTarget(ctx context.Context, cmd *cobra.Command, lookup *explainCheckpointLookup, ref string, force bool) error {
w := cmd.OutOrStdout()
errW := cmd.ErrOrStderr()
hash, ambiguousMatches, err := resolveCommitUnambiguous(lookup.repo, ref)
if err != nil {
if errors.Is(err, errAmbiguousCommitPrefix) {
renderAmbiguousPrefixFailure(errW, ref, "commits", buildAmbiguousCommitMatches(lookup.repo, ambiguousMatches))
return NewSilentError(err)
}
return fmt.Errorf("%w matching %q", errNoResumeCommit, ref)
}
commit, err := lookup.repo.CommitObject(hash)
if err != nil {
return fmt.Errorf("failed to get commit %s: %w", abbreviateCommitHash(lookup.repo, hash), err)
}
cpIDs := trailers.ParseAllCheckpoints(commit.Message)
if len(cpIDs) == 0 {
printNoTrailerMessage(w, lookup.repo, hash)
return NewSilentError(fmt.Errorf("commit %s has no Entire-Checkpoint trailer", abbreviateCommitHash(lookup.repo, hash)))
}
cpID := cpIDs[0]
if len(cpIDs) > 1 {
latest, found, latestErr := resolveLatestCheckpoint(ctx, lookup.store, cpIDs)
if latestErr != nil {
return latestErr
}
if found {
cpID = latest.CheckpointID
}
}
return resumeResolvedCheckpoint(ctx, cmd, lookup, cpID, force)
}
// resumeResolvedCheckpoint resumes one committed checkpoint: checks out the
// branch containing it (at the branch's current tip) when one exists, points
// at the owning worktree when that branch is checked out elsewhere, and falls
// back to restoring session logs in place when no local branch contains it.
func resumeResolvedCheckpoint(ctx context.Context, cmd *cobra.Command, lookup *explainCheckpointLookup, cpID id.CheckpointID, force bool) error {
w := cmd.OutOrStdout()
branch := buildCheckpointBranchIndex(lookup.repo)[cpID.String()]
if branch == "" {
fmt.Fprintf(w, "Checkpoint %s is not on any local branch; restoring session logs without switching branches.\n", cpID)
return resumeByCheckpointID(ctx, w, cmd.ErrOrStderr(), cpID, force)
}
if otherPath, ok := branchCheckedOutElsewhere(ctx, branch); ok {
fmt.Fprint(w, worktreeClashMessage(branch, otherPath, ""))
return nil
}
return resumeSessionOnBranch(ctx, cmd, branch, cpID, force)
}
func runCheckpointResumePicker(_ context.Context, _ *cobra.Command, _ *explainCheckpointLookup, _ bool) error {
return errors.New("pass a checkpoint ID, commit SHA, or branch (picker lands in the next commit)")
}