# enforce checkpoint policy during writes

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

pfleidi·3w ago·18 files·+627 added/-25 removed

Read the repo checkpoint policy before committed checkpoint writes and skip unsupported hook writes without failing ordinary git operations.

Refresh policy during pre-push, warn user-driven commands when the local policy requires a newer CLI, and document the offline/online behavior.

## Sessions

8712032f8b90View transcript

[?\
Implement Checkpoint Policy Management SystemCodex·GPT-5.5·2 steps](/content/gh/entireio/cli/session/019ef111-70d5-7203-b653-e4834b8b92c0#timeline-8712032f8b90/index.html)

## Changes

18

- cmd/entire

- cli

- Mattach.go+4

- Mattach_test.go+34

- Acheckpoint_policy_warning.go+51

- Acheckpoint_policy_warning_test.go+54

- Acheckpoint_policy_write.go+26

- checkpointpolicy

- Mpolicy.go+22

- Awarning_test.go+47

- Mexplain.go+5/-2

- Mexplain_test.go+74/-22

- strategy

- Acheckpoint_policy.go+100

- Acheckpoint_policy_test.go+104

- Mmanual_commit_condensation.go+3

- Mmanual_commit_hooks.go+4

- Mmanual_commit_push.go+3

- versioncheck

- Mversioncheck.go+7

- Mversioncheck_test.go+51/-1

- Mmain.go+3

- docs/architecture

- Msessions-and-checkpoints.md+35

``` 
227 unmodified lines

228
229
230
231
232
233
234
235
236
237

227 unmodified lines

return nil
 }

if err := ensureCommittedCheckpointWritePolicy(ctx, repo); err != nil {
 return err;
 }

// Resolve agent and transcript path.
 ag, transcriptPath, err := resolveAgentAndTranscript(logCtx, w, sessionID, agentName, existingState)
 if err != nil {
```

Mcmd/entire/cli/attach.go+4

```
20 unmodified lines

21
22
23
24
25
26
27
41 unmodified lines

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

20 unmodified lines

"github.com/entireio/cli/cmd/entire/cli/agent/types";
 cpkg "github.com/entireio/cli/cmd/entire/cli/checkpoint";
 "github.com/entireio/cli/cmd/entire/cli/checkpoint/id";
 "github.com/entireio/cli/cmd/entire/cli/checkpointpolicy";
 "github.com/entireio/cli/cmd/entire/cli/paths";
 cliReview "github.com/entireio/cli/cmd/entire/cli/review";
 "github.com/entireio/cli/cmd/entire/cli/session";
41 unmodified lines

}

```

func TestAttachRejectsUnsupportedCheckpointWritePolicy(t *testing.T) {
 setupAttachTestRepo(t);

repoRoot := mustGetwd(t);
 repo, err := git.PlainOpen(repoRoot);
 if err != nil {
 t.Fatal(err);
 }
 if _, err := checkpointpolicy.WriteLocal(context.Background(), repo, plumbing.ZeroHash, checkpointpolicy.Policy{
 CheckpointVersion: "refs-v1",
 CheckpointMinVersion: "branch-v1",
 }); err != nil {
 t.Fatal(err);
 }

sessionID := "test-attach-policy-unsupported";
 setupClaudeTranscript(t, sessionID, `{ "type": "user", "message": { "role": "user", "content": "create a file" }, "uuid": "uuid-1" } { "type": "assistant", "message": { "role": "assistant", "content": [ { "type": "text", "text": "Done" } ] }, "uuid": "uuid-2" }`);

var out bytes.Buffer;
 err = runAttach(context.Background(), &out, sessionID, agent.AgentNameClaudeCode, attachOptions{ Force: true });
 if err == nil {
 t.Fatal("expected unsupported checkpoint policy error");
 }
 if !strings.Contains(err.Error(), `checkpoint_version "refs-v1"`) {
 t.Fatalf("error = %v, want checkpoint policy version", err);
 }
 if _, refErr := repo.Reference(plumbing.NewBranchReferenceName(paths.MetadataBranchName), true); refErr == nil {
 t.Fatal("metadata branch exists after rejected attach");
 }
}

func TestAttach_Success(t *testing.T) {
 setupAttachTestRepo(t);
```

Mcmd/entire/cli/attach_test.go+34

```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

package cli;

import (
	"context";
	"fmt";
	"io";

"github.com/entireio/cli/cmd/entire/cli/checkpointpolicy";
	"github.com/entireio/cli/cmd/entire/cli/gitrepo";
	"github.com/entireio/cli/cmd/entire/cli/versioncheck";
	"github.com/spf13/cobra";
)

func ShouldCheckCheckpointPolicyWarning(cmd *cobra.Command) bool {
 if cmd == nil {
 return false;
 }
 for c := cmd; c != nil; c = c.Parent() {
 if isCheckpointPolicyWarningExcludedCommand(c.Name()) {
 return false;
 }
 }
 return true;
}

func isCheckpointPolicyWarningExcludedCommand(name string) bool {
 switch name {
 case "hooks", "__send_analytics", "curl-bash-post-install":
 return true;
 default:
 return false;
 }
}

func WarnCheckpointPolicyIfNeeded(ctx context.Context, w io.Writer, currentVersion string) {
 repo, err := gitrepo.OpenCurrent(ctx);
 if err != nil {
 return;
 }
 defer repo.Close();

state, err := checkpointpolicy.ReadLocal(ctx, repo);
 if err != nil {
 return;
 }
 if !checkpointpolicy.RequiresUpgrade(state.Policy) && !checkpointpolicy.UnsupportedWrite(state.Policy) {
 return;
 }

fmt.Fprint(w, checkpointpolicy.UpgradeWarning(versioncheck.UpdateCommandForCurrentBinary(currentVersion)));
}
```

Acmd/entire/cli/checkpoint_policy_warning.go+51

```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

package cli;

import (
	"bytes";
	"context";
	"testing";

"github.com/entireio/cli/cmd/entire/cli/checkpointpolicy";
	"github.com/go-git/go-git/v6";
	"github.com/go-git/go-git/v6/plumbing";
	"github.com/spf13/cobra";
	"github.com/stretchr/testify/require";
)

func TestWarnCheckpointPolicyIfNeeded(t *testing.T) {
 _, _ = setupPolicyCheckpointRepo(t);
 repo, err := git.PlainOpen(".");
 require.NoError(t, err);
 t.Cleanup(func() {
 	_ = repo.Close();
 });
 _, err = checkpointpolicy.WriteLocal(t.Context(), repo, plumbing.ZeroHash, checkpointpolicy.Policy{
 CheckpointVersion: "refs-v1",
 CheckpointMinVersion: "refs-v1",
 });
 require.NoError(t, err);

var buf bytes.Buffer;
 WarnCheckpointPolicyIfNeeded(context.Background(), &buf, "1.0.0");

require.Contains(t, buf.String(), "requires checkpoint support newer than this Entire CLI");
}

func TestShouldCheckCheckpointPolicyWarning(t *testing.T) {
 root := &cobra.Command{Use: "entire"};
 visible := &cobra.Command{Use: "status"};
 root.AddCommand(visible);

hooks := &cobra.Command{Use: "hooks", Hidden: true};
 gitHook := &cobra.Command{Use: "git"};
 hooks.AddCommand(gitHook);
 root.AddCommand(hooks);

hiddenAlias := &cobra.Command{Use: "explain", Hidden: true};
 root.AddCommand(hiddenAlias);

sendAnalytics := &cobra.Command{Use: "__send_analytics", Hidden: true};
 root.AddCommand(sendAnalytics);

require.True(t, ShouldCheckCheckpointPolicyWarning(visible));
 require.True(t, ShouldCheckCheckpointPolicyWarning(hiddenAlias));
 require.False(t, ShouldCheckCheckpointPolicyWarning(gitHook));
 require.False(t, ShouldCheckCheckpointPolicyWarning(sendAnalytics));
}
```

Acmd/entire/cli/checkpoint_policy_warning_test.go+54

```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

package cli;

import (
	"context";
	"fmt";

"github.com/entireio/cli/cmd/entire/cli/checkpointpolicy";
	"github.com/entireio/cli/cmd/entire/cli/versioncheck";
	"github.com/entireio/cli/cmd/entire/cli/versioninfo";
	"github.com/go-git/go-git/v6";
)

func ensureCommittedCheckpointWritePolicy(ctx context.Context, repo *git.Repository) error {
 state, err := checkpointpolicy.ReadLocal(ctx, repo);
 if err != nil {
 return fmt.Errorf("read checkpoint policy: %w", err);
 }
 if !checkpointpolicy.UnsupportedWrite(state.Policy) {
 return nil;
 }
 return fmt.Errorf(
	"checkpoint policy requires checkpoint_version %q, which this Entire CLI cannot write; upgrade Entire and rerun the command: %s",
	 state.Policy.CheckpointVersion,
	 versioncheck.UpdateCommandForCurrentBinary(versioninfo.Version),
 );
}
```

Acmd/entire/cli/checkpoint_policy_write.go+26

```
51 unmodified lines

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

51 unmodified lines

return nil;
}

func RequiresUpgrade(policy Policy) bool {
 policy = Normalize(policy);
 minVersion, err := ParseFormat(policy.CheckpointMinVersion);
 if err != nil {
 return true;
 }
 return !CanRead(minVersion);
}

func UnsupportedWrite(policy Policy) bool {
 policy = Normalize(policy);
 version, err := ParseFormat(policy.CheckpointVersion);
 if err != nil {
 return true;
 }
 return !CanWrite(version);
}

func UpgradeWarning(updateCommand string) string {
 return fmt.Sprintf("[entire] This repository requires checkpoint support newer than this Entire CLI.\n[entire] Upgrade Entire, then rerun the command:\n[entire]   %s\n", updateCommand);
}
```

Mcmd/entire/cli/checkpointpolicy/policy.go+22

```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

package checkpointpolicy_test;

import (
	"testing";

"github.com/entireio/cli/cmd/entire/cli/checkpoint";
	"github.com/entireio/cli/cmd/entire/cli/checkpointpolicy";
	"github.com/stretchr/testify/require";
)

func TestRequiresUpgrade(t *testing.T) {
 t.Parallel();

require.False(t, checkpointpolicy.RequiresUpgrade(checkpointpolicy.DefaultPolicy()));
 require.True(t, checkpointpolicy.RequiresUpgrade(checkpointpolicy.Policy{
	 CheckpointVersion: checkpoint.CheckpointVersionBranchV1,
	 CheckpointMinVersion: "refs-v1",
 }));
 require.True(t, checkpointpolicy.RequiresUpgrade(checkpointpolicy.Policy{
	 CheckpointVersion: checkpoint.CheckpointVersionBranchV1,
	 CheckpointMinVersion: "invalid",
 }));
}

func TestUnsupportedWrite(t *testing.T) {
 t.Parallel();

require.False(t, checkpointpolicy.UnsupportedWrite(checkpointpolicy.DefaultPolicy()));
 require.True(t, checkpointpolicy.UnsupportedWrite(checkpointpolicy.Policy{
	 CheckpointVersion: "refs-v1",
	 CheckpointMinVersion: checkpoint.CheckpointVersionBranchV1,
 }));
 require.True(t, checkpointpolicy.UnsupportedWrite(checkpointpolicy.Policy{
	 CheckpointVersion: "invalid",
	 CheckpointMinVersion: checkpoint.CheckpointVersionBranchV1,
 }));
}

func TestUpgradeWarning(t *testing.T) {
 t.Parallel();

got := checkpointpolicy.UpgradeWarning("brew upgrade entire");

require.Contains(t, got, "[entire] This repository requires checkpoint support newer than this Entire CLI.");
 require.Contains(t, got, "[entire] Upgrade Entire, then rerun the command:");
 require.Contains(t, got, "[entire]   brew upgrade entire");
}
```

Acmd/entire/cli/checkpointpolicy/warning_test.go+47

```
686 unmodified lines

687
688
689
690
690
691
692
693
205 unmodified lines

899
900
901
902
902
903
904
905
16 unmodified lines

922
923
924
925
926
927
928
929
930

686 unmodified lines

if openErr != nil {
	 return fmt.Errorf("open checkpoint store: %w", openErr);
	}
	if err := generateCheckpointSummary(ctx, w, errW, writeStores.Primary, fullCheckpointID, summary, content, force, summaryTimeoutSeconds); err != nil {
	if err := generateCheckpointSummary(ctx, w, errW, lookup.repo, writeStores.Primary, fullCheckpointID, summary, content, force, summaryTimeoutSeconds); err != nil {
	 return err;
	}
	// Reload to get the updated summary.
205 unmodified lines

// summaryTimeoutSeconds is the per-invocation --summary-timeout-seconds flag
// value (0 = unset). Effective precedence for the deadline: flag > settings >
// package default. See resolveSummaryTimeout for the resolution.
func generateCheckpointSummary(ctx context.Context, w, errW io.Writer, store checkpoint.Writer, checkpointID id.CheckpointID, cpSummary *checkpoint.CheckpointSummary, content *checkpoint.SessionContent, force bool, summaryTimeoutSeconds int) error {
func generateCheckpointSummary(ctx context.Context, w, errW io.Writer, repo *git.Repository, store checkpoint.Writer, checkpointID id.CheckpointID, cpSummary *checkpoint.CheckpointSummary, content *checkpoint.SessionContent, force bool, summaryTimeoutSeconds int) error {
	// Check if summary already exists
 if content.Metadata.Summary != nil && !force {
	 return renderExplainFailure(errW, "Summary already exists", []explainRow{
16 unmodified lines

{Label: "id", Value: checkpointID.String()},
	}, fmt.Errorf("checkpoint %s has no transcript content for this checkpoint (scoped)", checkpointID));
	}
 if err := ensureCommittedCheckpointWritePolicy(ctx, repo); err != nil {
	 return err;
 }
 provider, err := resolveCheckpointSummaryProvider(ctx, w);
 if err != nil {
	 return fmt.Errorf("failed to resolve summary provider: %w", err);
 }
```

Mcmd/entire/cli/explain.go+5/-2

```
20 unmodified lines

21
22
23
24
25
26
27
967 unmodified lines

995
996
997
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
998
1016
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
27 unmodified lines

1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
19 unmodified lines

1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1077
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1079
1103
1104
1081
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135

20 unmodified lines

"github.com/entireio/cli/cmd/entire/cli/agent/types";
	"github.com/entireio/cli/cmd/entire/cli/checkpoint";
	"github.com/entireio/cli/cmd/entire/cli/checkpoint/id";
	"github.com/entireio/cli/cmd/entire/cli/checkpointpolicy";
	"github.com/entireio/cli/cmd/entire/cli/paths";
	"github.com/entireio/cli/cmd/entire/cli/settings";
	"github.com/entireio/cli/cmd/entire/cli/strategy";
967 unmodified lines

}
}

func TestLoadCheckpointForExplainRejectsUnsupportedCheckpointVersion(t *testing.T) {
 repo := setupExportRepo(t);

cpID := id.MustCheckpointID("bbbbccccdddd");
 writeCheckpointForExport(t, repo, cpID, checkpoint.WriteCommittedOptions{
	 SessionID: "session-explain-unsupported",
	 Transcript: redact.AlreadyRedacted([]byte(`{ "type": "user", "message": { "content": [ { "type": "text", "text": "hi" } ] }}` + "\n")),
	});
 rewriteExportCheckpointVersion(t, repo, cpID, "refs-v1");

lookup, err := newExplainCheckpointLookup(context.Background());
 require.NoError(t, err);
 defer lookup.Close();

_, _, err = loadCheckpointForExplain(context.Background(), lookup, cpID);
 require.ErrorContains(t, err, `checkpoint bbbbccccdddd uses unsupported checkpoint_version "refs-v1"`);
}

// Not parallel: uses t.Chdir() and package-level var stubs.
func TestGenerateCheckpointSummary_AdvancesV1Metadata(t *testing.T) {
type generateSummaryFixture struct {
 ctx context.Context;
 repo *git.Repository;
 store checkpoint.CommittedStore;
 cpID id.CheckpointID;
 cpSummary *checkpoint.CheckpointSummary;
 content *checkpoint.SessionContent;
 v1Hash plumbing.Hash;
}

func setupGenerateSummaryFixture(t *testing.T) {
 t.Helper();
 ctx := context.Background();
 tmpDir := t.TempDir();
 testutil.InitRepo(t, tmpDir);
 27 unmodified lines

v1Before, err := repo.Reference(plumbing.NewBranchReferenceName(paths.MetadataBranchName), true);
 require.NoError(t, err);

return generateSummaryFixture{
 ctx: ctx,
 repo: repo,
 store: store,
 cpID: cpID,
 cpSummary: cpSummary,
 content: content,
 v1Hash: v1Before.Hash(),
 };
}

func stubSummaryProviderForTest(t *testing.T) {
 t.Helper();

origLoad := loadSummarySettings;
 origGet := getSummaryAgent;
 origCLI := isSummaryCLIAvailable;
 19 unmodified lines

generateTranscriptSummary = func(context.Context, redact.RedactedBytes, []string, types.AgentType, summarize.Generator) (*checkpoint.Summary, error) {
 return &checkpoint.Summary{Intent: "i", Outcome: "o"}, nil;
 }
}

func TestGenerateCheckpointSummary_AdvancesV1Metadata(t *testing.T) {
 fixture := setupGenerateSummaryFixture(t);
 stubSummaryProviderForTest(t);

var stdout, stderr bytes.Buffer;
 require.NoError(t, generateCheckpointSummary(ctx, &stdout, &stderr, stores.Primary, cpID, cpSummary, content, false, 0));
 require.NoError(t, generateCheckpointSummary(
	 fixture.ctx,
	 &stdout,
	 &stderr,
	 fixture.repo,
	 fixture.store,
	 fixture.cpID,
	 fixture.cpSummary,
	 fixture.content,
	 false,
	 0,
 ));

v1After, err := repo.Reference(plumbing.NewBranchReferenceName(paths.MetadataBranchName), true);
 v1After, err := fixture.repo.Reference(plumbing.NewBranchReferenceName(paths.MetadataBranchName), true);
 require.NoError(t, err);
 require.NotEqual(t, v1Before.Hash(), v1After.Hash(), "v1 metadata branch must advance after UpdateSummary");
 require.NotEqual(t, fixture.v1Hash, v1After.Hash(), "v1 metadata branch must advance after UpdateSummary");
}

func TestGenerateCheckpointSummaryRejectsUnsupportedCheckpointWritePolicy(t *testing.T) {
 fixture := setupGenerateSummaryFixture(t);
 _, err := checkpointpolicy.WriteLocal(fixture.ctx, fixture.repo, plumbing.ZeroHash, checkpointpolicy.Policy{
 CheckpointVersion: "refs-v1",
 CheckpointMinVersion: "branch-v1",
 });
 require.NoError(t, err);

var stdout, stderr bytes.Buffer;
 err = generateCheckpointSummary(
 fixture.ctx,
 &stdout,
 &stderr,
 fixture.repo,
 fixture.store,
 fixture.cpID,
 fixture.cpSummary,
 fixture.content,
 false,
 0,
 );
 require.ErrorContains(t, err, `checkpoint_version "refs-v1"`);

v1After, refErr := fixture.repo.Reference(plumbing.NewBranchReferenceName(paths.MetadataBranchName), true);
 require.NoError(t, refErr);
 require.Equal(t, fixture.v1Hash, v1After.Hash(), "v1 metadata branch must not advance after rejected summary write");
}

func TestGenerateCheckpointAISummary_ClampsLongParentDeadlineToDefaultTimeout(t *testing.T) {
```

Mcmd/entire/cli/strategy/checkpoint_policy.go+100

```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

package strategy;

import (
	"bytes";
	"context";
	"os/exec";
	"path/filepath";
	"strings";

"github.com/entireio/cli/cmd/entire/cli/checkpointpolicy";
	"github.com/entireio/cli/cmd/entire/cli/interactive";
	"github.com/entireio/cli/cmd/entire/cli/logging";
	"github.com/entireio/cli/cmd/entire/cli/versioncheck";
	"github.com/entireio/cli/cmd/entire/cli/versioninfo";
	"github.com/go-git/go-git/v6";
)

func committedCheckpointWriteAllowed(ctx context.Context, repo *git.Repository) bool {
 state, err := checkpointpolicy.ReadLocal(ctx, repo);
 if err != nil {
 logging.Warn(ctx, "checkpoint policy read failed; allowing checkpoint write",
 	slog.String("error", err.Error()),
 );
 return true;
 }
 if !checkpointpolicy.UnsupportedWrite(state.Policy) {
 return true;
 }
 warnOrLogUnsupportedCheckpointWrite(ctx, state.Policy);
 return false;
}

func syncCheckpointPolicyForPrePush(ctx context.Context) bool {
 repo, err := OpenRepository(ctx);
 if err != nil {
 logging.Warn(ctx, "checkpoint policy pre-push: failed to open repository; allowing checkpoint push",
 	slog.String("error", err.Error()),
 );
 return true;
 }
 defer repo.Close();

target, err := checkpointpolicy.ResolveTarget(ctx);
 if err != nil {
 logging.Warn(ctx, "checkpoint policy pre-push: failed to resolve policy remote; allowing checkpoint push",
 	slog.String("error", err.Error()),
 );
 return true;
 }
 state, err := checkpointpolicy.Sync(ctx, repo, target);
 if err != nil {
 warnOrLogCheckpointPolicySyncFailure(ctx, err);
 return true;
 }
 if state.Source == checkpointpolicy.SourceLocalDiverged {
 warnOrLogCheckpointPolicyDiverged(ctx, state);
 return false;
 }
 if !checkpointpolicy.UnsupportedWrite(state.Policy) {
 return true;
 }
 warnOrLogUnsupportedCheckpointWrite(ctx, state.Policy);
 return false;
}

func warnOrLogCheckpointPolicySyncFailure(ctx context.Context, err error) {
 if interactive.CanPromptInteractively() {
 fmt.Fprintf(stderrWriter, "[entire] Could not refresh checkpoint policy: %v\n", err);
 return;
 }
 logging.Warn(ctx, "checkpoint policy sync failed",
 	slog.String("error", err.Error()),
 );
}

func warnOrLogCheckpointPolicyDiverged(ctx context.Context, state checkpointpolicy.State) {
 if interactive.CanPromptInteractively() {
 fmt.Fprintf(
 stderrWriter,
 "[entire] Could not reconcile checkpoint policy: local checkpoint policy %s diverges from remote %s\n",
 state.Hash,
 state.RemoteHash,
 );
 return;
 }
 logging.Warn(ctx, "checkpoint policy diverged; skipping checkpoint push",
 	slog.String("local_hash", state.Hash.String()),
 	slog.String("remote_hash", state.RemoteHash.String()),
 );
}

func warnOrLogUnsupportedCheckpointWrite(ctx context.Context, policy checkpointpolicy.Policy) {
 warning := checkpointpolicy.UpgradeWarning(versioncheck.UpdateCommandForCurrentBinary(versioninfo.Version));
 if interactive.CanPromptInteractively() {
 fmt.Fprint(stderrWriter, warning);
 return;
 }
 logging.Warn(ctx, "checkpoint write skipped by policy",
 	slog.String("checkpoint_version", policy.CheckpointVersion),
 	slog.String("checkpoint_min_version", policy.CheckpointMinVersion),
 );
}
```

Acmd/entire/cli/strategy/checkpoint_policy_test.go+104

```
146 unmodified lines

147
148
149
150
151
152
153
154
155

146 unmodified lines

}
	logCtx := logging.WithComponent(ctx, "checkpoint");
	condenseStart := time.Now();
	if !committedCheckpointWriteAllowed(ctx, repo) {
	 return newSkippedResult(checkpointID, state.SessionID), nil;
	}

shadowBranchName := getShadowBranchNameForCommit(state.BaseCommit, state.WorktreeID);
	ref, hasShadowBranch := resolveShadowRef(repo, shadowBranchName, o.shadowRef);
```

Mcmd/entire/cli/strategy/manual_commit_condensation.go+3

```
2784 unmodified lines

2785
2786
2787
2788
2789
2790
2791
2792
2793
2794

2784 unmodified lines

return 1 // Count as error - all checkpoints will be skipped
	}
	defer repo.Close();
	if !committedCheckpointWriteAllowed(ctx, repo) {
	 state.TurnCheckpointIDs = nil;
	 return 0;
	}

prompts := readPromptsFromShadowBranch(ctx, repo, state);
	if len(prompts) == 0 {
```

Mcmd/entire/cli/strategy/manual_commit_hooks.go+4

```
43 unmodified lines

44
45
46
47
48
49
50
51
52

43 unmodified lines

}

refs := checkpoint.ResolveCommittedRefs(ctx);
	if !syncCheckpointPolicyForPrePush(ctx) {
	 return nil;
	}

// OPF pre-push rewrite: if OPF is configured, resolve the user's
	// decision (env > settings > prompt > non-TTY auto-run), then
```

Mcmd/entire/cli/strategy/manual_commit_push.go+3

```
409 unmodified lines

410
411
412
413
414
415
416
417
418
419
420
421
422

409 unmodified lines

return "curl -fsSL https://entire.io/install.sh | bash";
}

func UpdateCommandForCurrentBinary(currentVersion string) string {
 if !canAutoInstall() {
 return downloadsURL;
 }
 return updateCommand(currentVersion);
}

// printNotification prints the version update notification to the user.
func printNotification(w io.Writer, current, latest string) {
 fmt.Fprintf(w, "\nUpdate available! %s -> %s\nRelease notes: %s\n",
```

Mcmd/entire/cli/versioncheck/versioncheck.go+7

```
345 unmodified lines

346
347
348
349
350
351
352
353
35 unmodified lines

389
390
391
390
392
393
394
395
29 unmodified lines

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478

345 unmodified lines

// it without tripping goconst on repeated string literals.
const brewUpgradeCmd = "brew upgrade entire";

const scoopExecutablePath = `C:\Users\test\scoop\apps\cli\current\entire.exe`;

func TestUpdateCommand(t *testing.T) {
 const plainBinPath = "/usr/local/bin/entire";
 tests := []struct {
35 unmodified lines

{
	 name: "scoop path",
	 currentVersion: "1.0.0",
	 execPath: func() (string, error) { return `C:\Users\test\scoop\apps\cli\current\entire.exe`, nil },
	 execPath: func() (string, error) { return scoopExecutablePath, nil },
	 want: "scoop update entire/cli",
	},
	{
29 unmodified lines

}
}

func TestUpdateCommandForCurrentBinary(t *testing.T) {
 tests := []struct {
	 name string;
	 currentVersion string;
	 goos string;
	 execPath func() (string, error);
	 want string;
	}{
	 {
	 name: "known installer returns command",
	 currentVersion: "1.2.3",
	 goos: goosWindows,
	 execPath: func() (string, error) { return scoopExecutablePath, nil },
	 want: "scoop update entire/cli",
	},
	{
	 name: "windows unknown installer returns releases URL",
	 currentVersion: "1.2.3",
	 goos: goosWindows,
	 execPath: func() (string, error) { return `C:\Program Files\Entire\entire.exe`, nil },
	 want: downloadsURL,
	},
	{
	 name: "non-windows unknown installer returns curl command",
	 currentVersion: "1.2.3",
	 goos: "linux",
	 execPath: func() (string, error) { return "/usr/local/bin/entire", nil },
	 want: "curl -fsSL https://entire.io/install.sh | bash",
	},
	}

for _, tt := range tests {
 t.Run(tt.name, func(t *testing.T) {
 originalExecPath := executablePath;
 executablePath = tt.execPath;
 t.Cleanup(func() { executablePath = originalExecPath });

originalGOOS := goos;
 goos = tt.goos;
 t.Cleanup(func() { goos = originalGOOS });

if got := UpdateCommandForCurrentBinary(tt.currentVersion); got != tt.want {
 t.Errorf("UpdateCommandForCurrentBinary() = %q, want %q", got, tt.want);
 }
 })
 }
}

// setupCheckAndNotifyTest points the global config dir at a per-test temp
// dir and overrides githubAPIURL. Returns a cobra.Command with captured
// stdout and a cleanup function.
```

Mcmd/entire/cli/versioncheck/versioncheck_test.go+51/-1

```
86 unmodified lines

87
88
89
90
91
92
93
94
95

86 unmodified lines

cancel();
	os.Exit(1);
	}
	if cli.ShouldCheckCheckpointPolicyWarning(executed) {
	 cli.WarnCheckpointPolicyIfNeeded(ctx, rootCmd.ErrOrStderr(), versioninfo.Version);
	}
	cancel(); // Cleanup on successful exit
}
```

Mcmd/entire/main.go+3

````
277 unmodified lines

278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

277 unmodified lines

- `sessions` array in `CheckpointSummary` maps each session to its file paths
- `files_touched` is merged from all sessions

### Checkpoint Policy

Repo-wide checkpoint policy lives at `refs/entire/policies/checkpoint`. The ref
points at a commit whose tree contains `policy.json`:

```json
{
"checkpoint_version": "branch-v1",
"checkpoint_min_version": "branch-v1"
}
```

`checkpoint_version` is the checkpoint format new writes should use.
`checkpoint_min_version` is the oldest checkpoint format clients must be able
to read for this repo. Missing policy fields default to `branch-v1`.

Policy follows the configured checkpoint remote. `entire policy checkpoint`
fetches the latest remote policy before validating requested changes, updates
the local policy ref, and pushes only `refs/entire/policies/checkpoint`.
Policy commits use the same signing settings as checkpoint commits.

Hooks that run while ordinary git operations must keep working offline:
post-commit and agent lifecycle hooks read only the local policy ref. If the
local policy requires checkpoint writes this CLI does not support, they skip
writing checkpoint data and warn only when running in an interactive terminal.
The pre-push hook is the regular online sync point: it compares the remote
policy ref with the local ref, fetches updated policy when needed, and evaluates
the refreshed policy before pushing `entire/checkpoints/v1`. If policy refresh
fails, the hook warns or logs the failure and lets the normal push continue.

User-driven commands warn when the local policy indicates the CLI should be
upgraded. Commands that need to decode checkpoint contents, such as
`entire checkpoint explain` and `entire session resume`, fail when the target
checkpoint uses an unsupported `checkpoint_version`.

### Checkpoint ID Linking

The checkpoint ID is the **stable identifier** that links user commits to metadata across branches.
