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):
- A cancelled storage prompt no longer persists the recommendation silently: it prints 'Using the recommended git-refs checkpoint storage.'
- Every other cancelled setup prompt skips its action, so adopting one here must be disclosed (silent-failure review, HIGH).
- A cancelled command context (SIGINT/SIGTERM) now stops enable instead of being swallowed as a form cancellation and mutating the repo further (silent-failure review, HIGH).
- New subtest covers the headless-without---yes first run — the most common real path, previously only exercised with Yes: true.
- Comment accuracy: 'silently' no longer claimed for the cancelled case (Copilot + comment review); 'pre-selected' attribution and the 'matching optional prompts' claim made precise.
- strings import moved to the stdlib group (Copilot + code review).
- Architecture docs no longer imply refs is unconditional for new setups; it is the recommended, pre-selected choice.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
Changes
6
cmd/entire/cli
Mcheckpoint_backend.go+5/-3
Mcheckpoint_backend_test.go+1/-1
Msetup.go+16/-2
Msetup_test.go+14
docs/architecture
Mref-checkpoint-backend.md+1/-1
Msessions-and-checkpoints.md+1/-1
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