# Add interactive resume picker for stopped/idle sessions

`103fcd7`→[main](/content/gh/entireio/cli/commits/main/index.html)· 
Soph·1mo ago·12 files·+838 added/-240 removed

`entire resume` with no argument now opens an interactive picker of
resumable sessions across all worktrees, so you don't have to remember
which branch you left work on. Picking a session checks out its branch
and prints the command to continue the agent; if the branch is already
checked out in another worktree, it points you there instead of failing
a checkout. `entire resume <branch>` is unchanged.

## Details:
- Resumable = any session not currently mid-turn (idle + ended), not just
  sessions explicitly ended via `session stop`. Exiting an agent leaves a
  session idle (only a real SessionEnd marks it ended), so idle is the
  common "walked away" case and must be included.
- Adds a `Branch` field to session state, captured on each turn start, and
  surfaced in `session list --json`. For sessions recorded before the
  field existed, the branch is derived by matching the session's last
  checkpoint ID against branch-only commit trailers. Internal `entire/`
  refs (metadata branch + shadow branches) are excluded from that index,
  both to avoid mis-resolving to a non-resumable ref and to keep the scan
  fast (the index is also built lazily and avoids go-git MergeBase).
- Resume now keeps an existing local session log as-is by default; only a
  missing log is restored from the checkpoint. `--force` overwrites. This
  is driven by file existence, not transcript timestamps.

Tests cover the picker filtering/sorting, labels, branch derivation,
internal-ref exclusion, worktree-clash detection, and keep-existing-log
behavior. Obsolete overwrite-prompt tests removed; timestamp resume
integration tests updated to keep-by-default semantics.

## Sessions

## Changes

- 12

- MCLAUDE.md+6/-1

- cmd/entire/cli

- integration_test

- Dresume_interactive_test.go-155

- Mresume_test.go+44/-38

- Mresume.go+26/-27

- Aresume_picker.go+344

- Aresume_picker_test.go+294

- session

- Mstate.go+8

- Msessions.go+4/-2

- strategy

- Mmanual_commit_hooks.go+16

- Mmanual_commit_rewind.go+34/-17

- Mrewind_test.go+55

- docs/architecture

- Msessions-and-checkpoints.md+7

---

### Code

```go
//go:build integration && unix

package integration

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"
)

func (env *TestEnv) RunResumeInteractive(branchName string, respond func(ptyFile *os.File) string) (string, error) {
	env.T.Helper()
	return env.RunCommandInteractive([]string{"resume", branchName}, respond)
}

func TestResume_LocalLogNewerTimestamp_UserConfirmsOverwrite(t *testing.T) {
	t.Parallel()
	env := NewFeatureBranchEnv(t)

// Create a session with a specific timestamp
	session := env.NewSession()
	if err := env.SimulateUserPromptSubmit(session.ID); err != nil {
		t.Fatalf("SimulateUserPromptSubmit failed: %v", err)
	}

content := "def hello; end"
	env.WriteFile("hello.rb", content)
	
	session.CreateTranscript(
		"Create hello method",
		[]FileChange{{Path: "hello.rb", Content: content}},
	)
	if err := env.SimulateStop(session.ID, session.TranscriptPath); err != nil {
		t.Fatalf("SimulateStop failed: %v", err)
	}

// Commit the session's changes (manual-commit requires user to commit)
	env.GitCommitWithShadowHooks("Create hello method", "hello.rb")

featureBranch := env.GetCurrentBranch()

// Create a local log with a NEWER timestamp than the checkpoint
	if err := os.MkdirAll(env.ClaudeProjectDir, 0o755); err != nil {
		t.Fatalf("failed to create Claude project dir: %v", err)
	}
	existingLog := filepath.Join(env.ClaudeProjectDir, session.ID+".jsonl")
	futureTimestamp := time.Now().Add(24 * time.Hour).UTC().Format(time.RFC3339)
	newerContent := fmt.Sprintf(`{"type":"human","timestamp":"%s","message":{"content":"newer local work"}}`, futureTimestamp)
	if err := os.WriteFile(existingLog, []byte(newerContent), 0o644); err != nil {
		t.Fatalf("failed to write existing log: %v", err)
	}

// Switch to main
	env.GitCheckoutBranch(masterBranch)

// Resume interactively and confirm the overwrite
	output, err := env.RunResumeInteractive(featureBranch, func(ptyFile *os.File) string {
		out, promptErr := WaitForPromptAndRespond(ptyFile, "[y/N]", "y\n", 10*time.Second)
		if promptErr != nil {
			t.Logf("Warning: %v", promptErr)
		}
		return out
	})
	if err != nil {
		t.Fatalf("resume with user confirmation failed: %v\nOutput: %s", err, output)
	}

// Verify local log was overwritten with checkpoint content
	data, err := os.ReadFile(existingLog)
	if err != nil {
		t.Fatalf("failed to read log: %v", err)
	}
	if strings.Contains(string(data), "newer local work") {
		t.Errorf("local log should have been overwritten after user confirmed, but still has newer content: %s", string(data))
	}
	if !strings.Contains(string(data), "Create hello method") {
		t.Errorf("restored log should contain checkpoint transcript, got: %s", string(data))
	}
}

// Other relevant tests...
```

## Example Outputs

- In tests: Ensure logs are preserved and actions taken are in line with user inputs.

- Demonstrate branch handling and session resumption logic.
