# feat(import): refuse rewind to imported checkpoints with clear message

`abc9840`→[main](/content/gh/entireio/cli/commits/main/index.html)·

computermode·3w ago·2 files·+104 added/-0 removed

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

## Sessions

9643642e02f9View transcript

[?\
Implement Claude History Import FeatureClaude Code·Opus 4.8·3 steps](/content/gh/entireio/cli/session/897809d4-ecab-4dc6-aa21-97661cb62607#timeline-9643642e02f9/index.html)

## Changes

2

- cmd/entire/cli

- Mrewind.go+36
  - Arewind\_imports\_test.go+68

```
411 unmodified lines

411 unmodified lines

return runRewindToInternal(ctx, w, errW, commitID, logsOnly, reset)

// refuseIfImportedCheckpoint blocks rewinding to imported (read-only,
// commit-less) checkpoints on entire/imports/v1. It matches commitID against
// imported checkpoint IDs (full or >=7-char prefix). Best-effort: when the
// imports ref is absent or unreadable it returns nil so normal rewind proceeds.
func refuseIfImportedCheckpoint(ctx context.Context, errW io.Writer, commitID string) error {
	repo, err := strategy.OpenRepository(ctx)
	if err != nil {
		return nil //nolint:nilerr // fall through to normal rewind resolution
	}
	defer repo.Close()

importsRefs := checkpoint.ImportsRefs()
	stores, err := checkpoint.Open(ctx, repo, checkpoint.OpenOptions{Refs: &importsRefs})
	if err != nil {
		return nil //nolint:nilerr
	}
	infos, err := stores.Persistent.List(ctx)
	if err != nil {
		return nil //nolint:nilerr
	}
	for _, in := range infos {
		idStr := in.CheckpointID.String()
		if idStr == commitID || (len(commitID) >= 7 && strings.HasPrefix(idStr, commitID)) {
			fmt.Fprintln(errW, "This checkpoint was imported from existing agent history. Imported history is read-only and not rewindable.")
			return NewSilentError(errors.New("rewind refused: imported checkpoint"))
		}
	}
	return nil
}

func runRewindToInternal(ctx context.Context, w, errW io.Writer, commitID string, logsOnly bool, reset bool) error {
	start := GetStrategy(ctx)

// Imported history is read-only: refuse rewinding to it with a clear message
	// rather than a confusing "rewind point not found".
	if err := refuseIfImportedCheckpoint(ctx, errW, commitID); err != nil {
		return err
	}

// Check for uncommitted changes (skip for reset which handles this itself)
	if !reset {
		canRewind, changeMsg, err := start.CanRewind(ctx)
```

Mcmd/entire/cli/rewind.go+36

```
package cli

import (
	"bytes"
	"context"
	"strings"
	"testing"

"github.com/go-git/go-git/v6"
	"github.com/go-git/go-git/v6/plumbing/object"

"github.com/entireio/cli/cmd/entire/cli/checkpoint"
	"github.com/entireio/cli/cmd/entire/cli/checkpoint/id"
	"github.com/entireio/cli/cmd/entire/cli/testutil"
	"github.com/entireio/cli/redact"
)

func TestRefuseIfImportedCheckpoint(t *testing.T) {
	// Not parallel: uses t.Chdir for CWD-based repo resolution.
	repoDir := t.TempDir()
	testutil.InitRepo(t, repoDir)
	repo, err := git.PlainOpen(repoDir)
	if err != nil {
		t.Fatal(err)
	}
	wt, err := repo.Worktree()
	if err != nil {
		t.Fatal(err)
	}
	testutil.WriteFile(t, repoDir, "f.txt", "x")
	if _, err := wt.Add("f.txt"); err != nil {
		t.Fatal(err)
	}
	if _, err := wt.Commit("init", &git.CommitOptions{
		Author: &object.Signature{Name: "Test", Email: "test@test.com"},
	}); err != nil {
		t.Fatal(err)
	}
	
t.Chdir(repoDir)

cid := id.MustCheckpointID("aabbccddeeff")
	store := checkpoint.NewGitStore(repo, checkpoint.ImportsRefs())
	red, err := redact.JSONLBytes([]byte(`{"type":"user","uuid":"u1","message":{"role":"user","content":"hi"}}` + "\n"))
	if err != nil {
		t.Fatal(err)
	}
	if err := store.Write(context.Background(), checkpoint.Session(checkpoint.WriteOptions{
		CheckpointID: cid, SessionID: "s", Strategy: "import", Kind: "imported",
		Transcript: red, Prompts: []string{"hi"}, CheckpointsCount: 1,
	})); err != nil {
		t.Fatal(err)
	}

var out bytes.Buffer
	err = refuseIfImportedCheckpoint(context.Background(), &out, cid.String())
	if err == nil {
		t.Fatal("expected refusal error for imported checkpoint")
	}
	if !strings.Contains(out.String(), "read-only and not rewindable") {
		t.Fatalf("missing clear refusal message, got: %q", out.String())
	}

// A non-imported ID must not be refused.
	out.Reset()
	if err := refuseIfImportedCheckpoint(context.Background(), &out, "ffffffffffff"); err != nil {
		t.Fatalf("non-imported id should not be refused: %v", err)
	}
}
