Merge pull request #1789 from entireio/feat/enable-defaults-git-refs · Entire
Merge pull request #1789 from entireio/feat/enable-defaults-git-refs
7a69e1f→main · peyton-alt · 10h ago · 11 files · +181 added / -55 removed
enable: default new setups to git-refs checkpoint storage (drop wizard question)
Changes
11
cmd/entire/cli
Mcheckpoint_backend.go -35
integration_test
Aenable_backend_default_test.go +54
Minvestigate_test.go +4 / -1
Mreview_test.go +4 / -1
Msha256_repo_test.go +4
Msetup.go +28 / -11
Msetup_test.go +66
docs/architecture
Mref-checkpoint-backend.md +1 / -1
Msessions-and-checkpoints.md +1 / -1
e2e/tests
Mmain_test.go +9 / -3
internal/entireclient/tokenstore
Mfile_test.go +10 / -2
// promptCheckpointBackend asks the user to choose a checkpoint storage backend
// during first-time interactive setup. The default is the git-branch backend;
// the git-refs backend is offered as the selectable alternative. It returns the
// canonical backend type, or "" when the user kept the default (or cancelled) so
the caller can skip writing a redundant config block.
func promptCheckpointBackend(ctx context.Context, w io.Writer) (string, error) {
choice := checkpoint.BackendTypeGitBranch
form := NewAccessibleForm(
huh.NewGroup(
huh.NewSelect[string]().
Title("Checkpoint storage backend").
Description("How Entire stores committed session checkpoints in your repo.").
Options(
huh.NewOption("Branch — one shared branch, entire/checkpoints/v1 (default)", checkpoint.BackendTypeGitBranch),
huh.NewOption("Refs — one git ref per checkpoint", checkpoint.BackendTypeGitRefs),
).
Value(&choice),
),
)
if err := form.RunWithContext(ctx); err != nil {
return "", handleFormCancellation(w, "Checkpoint backend selection", err)
}
if choice == checkpoint.BackendTypeGitBranch {
return "", nil
}
return choice, nil
}
Checkpoint version and policy
| State | primary |
Behavior |
|---|---|---|
| Default (today) | git-branch |
Hex checkpoints on the v1 branch; unchanged legacy 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) |
| 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 |
| 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 (the default) stores every committed checkpoint as a subtree of a single entire/checkpoints/v1 branch, while git-refs stores one ref per checkpoint. 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.
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.
Session State
func TestEnableDefault_GitRefsRoundTrip(t *testing.T) {
t.Parallel()
env := NewTestEnv(t)
testutil.InitRepo(t, env.RepoDir)
env.WriteFile("README.md", "# fresh repo\n")
gitOutput(t, env.RepoDir, "add", "README.md")
gitOutput(t, env.RepoDir, "commit", "-m", "initial commit")
env.RunCLI("enable", "--agent", "claude-code", "--telemetry=false")
settings := env.ReadFile(".entire/settings.json")
if !strings.Contains(settings, `"git-refs"`) {
t.Fatalf("first-run enable should write the git-refs primary into settings.json, got:\n%s", settings)
}
initialHead := gitOutput(t, env.RepoDir, "rev-parse", "HEAD")
sess := env.NewSession()
prompt := "Create a file"
if err := env.SimulateUserPromptSubmitWithPromptAndTranscriptPath(sess.ID, prompt, sess.TranscriptPath); err != nil {
t.Fatalf("user-prompt-submit failed: %v", err)
}
const content = "package main\n\nfunc main() {}\n"
env.WriteFile("main.go", content)
sess.CreateTranscript(prompt, []FileChange{{Path: "main.go", Content: content}})
if err := env.SimulateStop(sess.ID, sess.TranscriptPath); err != nil {
t.Fatalf("stop hook failed: %v", err)
}
_ = initialHead
env.GitCommitWithShadowHooks("Add main", "main.go")
refs := gitOutput(t, env.RepoDir, "for-each-ref", "refs/entire/checkpoints")
if refs == "" {
t.Fatal("expected the condensed checkpoint as a per-checkpoint ref under refs/entire/checkpoints (settings-driven git-refs)")
}
}
func enableReviewAgent(t *testing.T, env *TestEnv, name string) {
t.Helper()
env.RunCLI("enable", "--agent", name, "--telemetry=false")
// Pin the git-branch backend: readCheckpointSummary/readSessionMetadata
// resolve checkpoint content from the v1 metadata branch, and first-run
// enable now defaults new setups to git-refs.
env.RunCLI("enable", "--agent", name, "--telemetry=false", "--checkpoint-backend", "branch")
}
//go:build integration
package integration
import (
"strings"
"testing"
"github.com/entireio/cli/cmd/entire/cli/testutil"
)