fix(enable): address review findings on the storage question · Entire

fix(enable): address review findings on the storage question

453577e→main·

peyton-alt·9h ago·6 files·+38 added/-8 removed

From /review, four review agents, and Copilot (all converging):

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

Changes

6

76 unmodified lines

77
78
79
80
80
81
82
83
84
7 unmodified lines

92
93
94
94
95
95
96
97
98
99
100

76 unmodified lines

}

// checkpointBackendChoices returns the storage picker's options — git-refs
// first, pre-selected, labeled recommended — and the recommended default.
// first, labeled recommended — and the recommended value the caller
// pre-selects.
// Split from promptCheckpointBackend so the ordering/labeling contract is
// unit-testable without a TTY.
func checkpointBackendChoices() (opts []huh.Option[string], recommended string) {
7 unmodified lines

// during first-time interactive setup, with the git-refs backend pre-selected
// as the recommendation — most users should just press Enter. It returns the
// chosen canonical backend type; cancellation (Ctrl+C or a cancelled ctx)
// returns "" so the caller falls through to the recommended default, matching
// the optional-prompt behavior elsewhere in setup. Callers must gate this on
// prints a cancellation note and returns "" (a soft skip, nil error, like
// other setup prompts) so the caller falls through to the recommended
// default. Callers must gate this on
// an interactive terminal (and skip it when ENTIRE_CHECKPOINTS_PRIMARY is
// active — the env fully replaces settings, so an answer could not take
// effect and would only write diverging config).

Mcmd/entire/cli/checkpoint_backend.go+5/-3

2 unmodified lines

3
4
5
6
7
8
9
1 unmodified line

11
12
13
13
14
15
16

2 unmodified lines

import (
    "context"
    "io"
    "strings"
    "testing"

"github.com/stretchr/testify/assert"
    "github.com/entireio/cli/cmd/entire/cli/checkpoint"
    "github.com/entireio/cli/cmd/entire/cli/settings"
    "strings"
)

func TestResolveCheckpointBackendType(t *testing.T) {

Mcmd/entire/cli/checkpoint_backend_test.go+1/-1

1241 unmodified lines

1242
1243
1244
1245
1246
1245
1246
1247
1248
1249
1250
1251
5 unmodified lines

1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274

1241 unmodified lines

// Checkpoint storage backend. An explicit --checkpoint-backend always
    // wins. Otherwise a first interactive setup asks, with git-refs
    // pre-selected as the recommendation (one Enter for most users);
    // non-interactive/--yes/cancelled first runs take the recommendation
    // silently. Either way the choice is written explicitly into the new
    // non-interactive/--yes first runs take the recommendation silently,
    // and a cancelled prompt takes it with an explicit note (unless the
    // command context itself was cancelled — then enable stops).
    // Either way the choice is written explicitly into the new
    // settings file, and the config-less runtime fallback stays git-branch
    // so existing repos are untouched. The prompt is skipped while
    // ENTIRE_CHECKPOINTS_PRIMARY is active (firstRunCheckpointBackendDefault
5 unmodified lines

if err != nil {
        return err
    }
    if ctx.Err() != nil {
        // A cancelled command context (SIGINT/SIGTERM) surfaces as a
        // form cancellation, but the user asked to stop: setup must not
        // adopt a default and keep mutating the repo.
        return fmt.Errorf("checkpoint storage selection: %w", ctx.Err())
    }
    if chosen == "" {
        // Cancelled prompt: the recommendation is adopted, but never
        // silently — every other cancelled setup prompt skips its
        // action, so persisting a choice here must be disclosed.
        fmt.Fprintln(w, "Using the recommended git-refs checkpoint storage.")
    }
    opts.CheckpointBackend = chosen // "" (cancelled) falls through to the recommendation
}
if opts.CheckpointBackend == "" && firstRun {

Mcmd/entire/cli/setup.go+16/-2

3925 unmodified lines

3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945

3925 unmodified lines

}
})

t.Run("non-interactive first run without --yes takes the recommendation", func(t *testing.T) {
    // The most common real path: a headless first run without --yes
    // (go test => CanPromptInteractively false). The storage prompt must
    // be skipped and the recommendation written — every other first-run
    // subtest passes Yes: true, so this is the only coverage of the
    // !opts.Yes non-TTY branch. Telemetry: false dodges the telemetry
    // prompt, which (pre-existing) has no headless guard.
    setupTestRepo(t)
    cfg := enable(t, EnableOptions{Telemetry: false})
    if cfg == nil || cfg.Primary.Type != checkpoint.BackendTypeGitRefs {
        t.Errorf("Checkpoints = %+v, want the git-refs recommendation", cfg)
    }
})

t.Run("re-run of an existing config-less repo stays config-less", func(t *testing.T) {
    setupTestRepo(t)
    // A repo set up before this change: settings.json exists, no

Mcmd/entire/cli/setup_test.go+14

163 unmodified lines

164
165
166
167
167
168
169
170

163 unmodified lines

| State | `primary` | Behavior |
|-------|-----------|----------|
| **Config-less fallback** | `git-branch` | Hex checkpoints on the `v1` branch; unchanged legacy behavior for repos set up before the git-refs default (new setups get an explicit `git-refs` primary written by `entire enable`) |
| **Config-less fallback** | `git-branch` | Hex checkpoints on the `v1` branch; unchanged legacy behavior for repos set up before the git-refs default (new setups write an explicit primary — `git-refs` as the recommended pick unless the setup question chose branch) |
| **Refs-only** | `git-refs` | New checkpoints are ULIDs written as per-checkpoint refs; pre-existing hex/`v1` checkpoints stay readable via the read-routing fallback |

## Checkpoint version and policy

Mdocs/architecture/ref-checkpoint-backend.md+1/-1

148 unmodified lines

149
150
151
152
152
153
154
155

148 unmodified lines

| Persistent (git-branch) | `entire/checkpoints/v1` branch, sharded `<id[:2]>/<id[2:]>/` | Metadata + commit reference |
| Persistent (git-refs) | `refs/entire/checkpoints/<shard>/<id>`, one ref per checkpoint | Metadata + commit reference |

The persistent store is pluggable: `git-branch` stores every committed checkpoint as a subtree of a single `entire/checkpoints/v1` branch, while `git-refs` stores one ref per checkpoint. New setups get `git-refs` written into their settings by `entire enable`; a repo with no checkpoints config still resolves to `git-branch` (the config-less fallback), so pre-existing repos keep their behavior. Both are git-backed and share the same checkpoint tree layout; they differ only in where that tree is committed. This document describes the git-branch layout; for the ref-based backend — its ref naming, sharding, push/fetch model, read routing, and configuration — see [Ref-Based Checkpoint Backend](ref-checkpoint-backend.md).
The persistent store is pluggable: `git-branch` stores every committed checkpoint as a subtree of a single `entire/checkpoints/v1` branch, while `git-refs` stores one ref per checkpoint. New setups write an explicit backend choice via `entire enable` (`git-refs` recommended and pre-selected); a repo with no checkpoints config still resolves to `git-branch` (the config-less fallback), so pre-existing repos keep their behavior. Both are git-backed and share the same checkpoint tree layout; they differ only in where that tree is committed. This document describes the git-branch layout; for the ref-based backend — its ref naming, sharding, push/fetch model, read routing, and configuration — see [Ref-Based Checkpoint Backend](ref-checkpoint-backend.md).

### Session State