resume picker: resume the selected session, not the branch's latest · Entire
resume picker: resume the selected session, not the branch's latest
5866380→main· Soph·1mo ago·3 files·+243 added/-45 removed
The picker is session-oriented but the action only passed the branch to runResume, which re-derived the latest checkpoint on that branch and ignored the selected session. So two sessions on the same branch both resumed the latest, and an idle session with a stored branch but no committed checkpoint was selectable yet resumed unrelated work (or failed with "No Entire checkpoint found").
Fix:
- Carry each session's checkpoint ID through the picker. A row is selectable only when it has BOTH a branch and a committed checkpoint; otherwise it's shown disabled with the reason (no branch / no committed checkpoint).
- On selection, resume that specific checkpoint via a new resumeSessionOnBranch/resumeByCheckpointID path that switches to the branch and restores the chosen session, instead of searching branch history. Checkout logic is shared with runResume via switchToBranchForResume (no duplication).
Tests:
- two sessions on one branch each carry their own checkpoint;
- resuming a specific checkpoint restores that session and not the newer one;
- a branch-only session with no checkpoint is not selectable.
Sessions
f0b960dc6333View transcript
Changes
3
cmd/entire/cli
Mresume.go+92/-23
Mresume_picker.go+38/-16
Mresume_picker_test.go+113/-6
88 unmodified lines
func switchToBranchForResume(ctx context.Context, w, errW io.Writer, branchName string, force bool) (bool, error) {
// Check if we're already on this branch
currentBranch, err := GetCurrentBranch(ctx)
if err == nil && currentBranch == branchName {
// Already on the branch, skip checkout
return resumeFromCurrentBranch(ctx, w, errW, branchName, force)
}
// Check if branch exists locally
exists, err := BranchExistsLocally(ctx, branchName)
if err != nil {
return fmt.Errorf("failed to check branch: %w", err)
}
if !exists {
// Branch doesn't exist locally, check if it exists on remote
remoteExists, err := BranchExistsOnRemote(ctx, branchName)
if err != nil {
return fmt.Errorf("failed to check remote branch: %w", err)
}
if !remoteExists {
return fmt.Errorf("branch '%s' not found locally or on origin", branchName)
}
// Ask user if they want to fetch from remote (--force skips the prompt)
if !force {
shouldFetch, err := promptFetchFromRemote(branchName)
if err != nil {
return err
}
if !shouldFetch {
return nil
}
}
}
// Checkout the branch
if err := CheckoutBranch(ctx, branchName); err != nil {
fmt.Fprintf(errW, "Error: failed to checkout branch: %v\n", err)
return NewSilentError(errors.New("failed to checkout branch"))
}
fmt.Fprintf(w, "✓ Switched to branch %s\n", branchName)
return true, nil
}
func resumeSessionOnBranch(ctx context.Context, cmd *cobra.Command, branchName string, checkpointID id.CheckpointID, force bool) error {
// Check if session can be resumed
return resumeFromCurrentBranch(ctx, w, errW, branchName, force)
}
resumableSession struct
type resumableSession struct {
state *strategy.SessionState
branch string
checkpointID id.CheckpointID
}
func (r resumableSession) isResumable() bool {
return r.branch != "" && !r.checkpointID.IsEmpty()
}
func (r resumableSession) unresumableReason() string {
if r.branch == "" {
return "no branch"
}
return "no committed checkpoint"
}
func buildResumeOptions(items []resumableSession) (string, bool) {
options := []huh.Option{}
hasSelectable := false
for i, item := range items {
options = append(options, huh.NewOption(resumeOptionLabel(item), strconv.Itoa(i)))
if item.branch != "" {
if item.isResumable() {
hasSelectable = true
}
}
}
return options, hasSelectable
}
Summary
The session picker allows dynamic resumption of multiple checkpoints, facilitating effective session management across branches with robust validation to prevent process overlap.