Remove Unused Checkpoint Version Gates

For added context:
Session summary: Remove checkpoint_version from checkpoint metadata
Goal: Remove the CheckpointVersion property from checkpoint metadata.json and the gates that check it. Existing checkpoints will be handled by an external migration script, so no backward-compat handling for the stored attribute is needed.
Scope decision (after investigation): The version machinery has three parts: (A) the checkpoint_version stamp in metadata.json — a pure label nothing dispatches on (backend selection comes from settings topology, not the stamp), (B) the EnsureCanReadVersion read gates at resume/explain/rewind/export — forward-compat tripwires that can only fire for hypothetical future formats, and (C) the checkpointpolicy subsystem (policy ref at refs/entire/policies/checkpoint, hidden entire checkpoint policy command, write gates, telemetry). Agreed scope: remove A + B only; C stays untouched. Existing policy refs are left alone.
Approved plan: step-by-step execution, two commits:
remove checkpoint_version read gatesdrop checkpoint_version from checkpoint metadata
(Gates must go first — they read the field being removed in commit 2.)
Step 1 — done, awaiting review/commit approval:
- Deleted
cmd/entire/cli/checkpointpolicy/version.goand the gate-only test filecheckpoint_policy_read_test.go. - Removed the 7 gate call sites and unreachable
IsUnsupportedVersionerror branches inresume.go,explain.go,explain_export.go,rewind.go,strategy/manual_commit_rewind.go. - Dropped two redundant
ReadCheckpointcalls (resume session-log restore, rewind transcript restore) that existed only to feed the gate —ReadRawSessionLogForCheckpointalready reads the checkpoint internally. - Removed 5 gate-behavior tests and the
rewriteExportCheckpointVersionToRefsV2test helper. - Docs: removed the sentence in
docs/architecture/sessions-and-checkpoints.mdabout explain/resume failing on unsupportedcheckpoint_version. - Verified:
go build ./...clean, focused tests pass (cli,checkpointpolicy,strategypackages),mise run fmt && mise run lint→ 0 issues.
Next steps: Commit Step 1 on approval, then Step 2: remove WriteOptions.CheckpointVersion and CheckpointSummary.CheckpointVersion (api/checkpoint/metadata.go), the stamping plumbing in checkpoint/persistent.go / refs_store.go / manual_commit_condensation.go, normalizeCheckpointSummary, checkpointVersionForNewCheckpoint (attach.go switches to ensureCheckpointPolicyAllowsCheckpointData to keep the write gate), the now-unused CheckpointVersionRefsV1 constant, associated tests, and the metadata.json doc example. Plan file: ~/.claude/plans/abstract-splashing-lemon.md.
Step 1 is complete and ready for your review — here's the checkpoint summary.
Step 1: remove checkpoint_version read gates
- Deleted
cmd/entire/cli/checkpointpolicy/version.go(theEnsureCanReadVersiongate) and its gate-only test filecheckpoint_policy_read_test.go. - Removed the 7 gate call sites and the now-unreachable
IsUnsupportedVersionerror branches acrossresume.go,explain.go,explain_export.go,rewind.go, andstrategy/manual_commit_rewind.go. - Dropped two
ReadCheckpointcalls (in the resume session-log restore and the rewind transcript restore) that existed only to feed the gate —ReadRawSessionLogForCheckpointalready reads the checkpoint itself. - Removed 5 gate-behavior tests plus the
rewriteExportCheckpointVersionToRefsV2test helper, and dropped the sentence indocs/architecture/sessions-and-checkpoints.mdabout explain/resume failing on unsupported versions.
Verification (all from this step, nothing changed since): go build ./... clean, focused tests in the cli, checkpointpolicy, and strategy packages pass, and mise run fmt && mise run lint reported 0 issues.
One thing worth calling out from the diff: the dropped redundant ReadCheckpoint calls are a small behavior simplification, not just gate removal — the reads were gate-feeders only, so nothing downstream loses data.
On your approval I'll commit this as remove checkpoint_version read gates, then start Step 2 (dropping the checkpoint_version stamp from metadata writes: WriteOptions.CheckpointVersion, CheckpointSummary.CheckpointVersion, the stamping plumbing, normalizeCheckpointSummary, checkpointVersionForNewCheckpoint, the unused constant, tests, and the doc example).
Committed as bc49bc896b — remove checkpoint_version read gates (11 files, 4 insertions, 359 deletions).
Ready to start Step 2 when you say go: dropping the checkpoint_version stamp itself from metadata writes (WriteOptions.CheckpointVersion, CheckpointSummary.CheckpointVersion, the stamping plumbing in checkpoint/persistent.go / refs_store.go / manual_commit_condensation.go, normalizeCheckpointSummary, checkpointVersionForNewCheckpoint, the unused constant, associated tests, and the metadata.json doc example).
Step 1 missed nothing, and Step 2's plan is nearly complete — the sweep found two small additions to fold into Step 2, plus confirmation that everything else remaining is the policy subsystem we agreed to leave alone.
Additions for Step 2:
cmd/entire/cli/checkpoint/aliases.go:57-58— the re-exportedCheckpointVersionRefsV1alias has to go along with the underlying constant inapi/checkpoint/errors.go. (TheCheckpointVersionBranchV1constant and its alias must stay — the policy subsystem uses it heavily as the default policy version incheckpointpolicy/policy.go.)- Doc paragraph, not just the example — in
sessions-and-checkpoints.md, the checkpoint metadata example (line 254) is planned, but the Checkpoint Policy section's prose (lines 323-329) sayscheckpoint_version"selects the checkpoint format for new writes" and that "the CLI writes its default checkpoint version." After Step 2 nothing is written — the policy field becomes purely a write gate (writers fail if the configured version is unsupported, whichensureCheckpointPolicyAllowsCheckpointDatakeeps enforcing). That paragraph needs a light rewording, not removal. The policy file example at line 311 stays as-is — that's the policy's own field, not the metadata stamp.
Confirmed in-plan: normalizeCheckpointSummary lives in checkpoint/persistent_reader.go (its only job is backfilling the version default, so file and both call sites in persistent.go go away), and the version-asserting tests are in persistent_write_test.go, persistent_update_test.go, refs_store_test.go, refs_store_seam_test.go, and persistent_tripwire_test.go.
Confirmed out of scope (policy subsystem, stays): hook_registry.go, hooks_git_cmd.go, import_cmd.go's help text, and everything under checkpointpolicy/ — those all reference the policy's CheckpointVersion field, not the metadata stamp. attach.go switching from checkpointVersionForNewCheckpoint to ensureCheckpointPolicyAllowsCheckpointData matches the existing pattern in explain.go:701 and import_cmd.go:59, after which checkpointVersionForNewCheckpoint is deleted.
Say the word and I'll execute Step 2 with these two additions folded in.
Step 2: drop checkpoint_version from checkpoint metadata — ready for review, 32 insertions / 302 deletions across 15 files.
What changed:
api/checkpoint/metadata.go: removedWriteOptions.CheckpointVersionandCheckpointSummary.CheckpointVersion;api/checkpoint/errors.goandcheckpoint/aliases.go: removed the now-unusedCheckpointVersionRefsV1constant and its alias.CheckpointVersionBranchV1stays — the policy subsystem uses it as its default version.checkpoint/persistent.go+refs_store.go: thecheckpointVersionparameter is gone from the whole write chain (applySessionWrite→writeStandardCheckpointEntries→writeCheckpointSummary), along with the preserve-existing-version read inwriteCheckpointSummary.normalizeCheckpointSummarydeleted frompersistent_reader.go(the file keepsAuthorReader); its two call sites now return the parsed summary directly.strategy/manual_commit_condensation.goandattach.go: no longer resolve a version from the policy. The policy write gate stays in both — condensation keeps itsCanSatisfyPolicycheck, and attach switched fromcheckpointVersionForNewCheckpoint(deleted fromcheckpoint_policy_write.go) to the existingensureCheckpointPolicyAllowsCheckpointData, matching explain and import.- Tests: deleted the six version stamp/backfill/preserve tests and the now-orphaned
rewriteRootSummaryhelper; dropped the version assertion from the refs-store and seam tests (their other assertions stay). - Docs: removed
checkpoint_versionfrom the metadata.json example, and reworded the policy section — itscheckpoint_versionfield is now described as a pure write guard rather than "selects the format for new writes", since nothing is stamped anymore.
One diff note: attach.go shows more changed lines than the logical edit because removing CheckpointVersion (the longest field name) made gofmt realign the whole writeOpts struct literal.
Verification: go build ./... clean; go test -count=1 passes on api/checkpoint, all cmd/entire/cli/checkpoint/... packages, strategy, and cli; mise run fmt && mise run lint → 0 issues on the formatted tree. A leftover-reference sweep finds only the policy subsystem's own CheckpointVersion fields, which are intentionally untouched.
On approval I'll commit as drop checkpoint_version from checkpoint metadata, which completes the planned work.
I'm assuming CheckpointVersionBranchV1 is still used for the other policy decisions, like setting checkpoint version via a policy, correct?
Correct. CheckpointVersionBranchV1 remains the anchor value for the whole policy subsystem — that's exactly why it stayed while CheckpointVersionRefsV1 was deleted. In checkpointpolicy/policy.go it feeds:
DefaultPolicy()/DefaultCheckpointVersion()— the values used when no policy ref is configured (lines 15-24).Normalize()— backfills bothcheckpoint_versionandcheckpoint_min_versionwhen a policy omits them or sets them to empty (lines 26-34).- The gate evaluations built on those —
ValidatePolicy(rejects a--checkpoint-versionthis CLI can't write, and min > version downgrades),CanSatisfyPolicy(the write gate that condensation, attach, explain, and import still call),RequiresUpgrade, and the upgrade-nudge error messages.
So entire checkpoint policy --checkpoint-version ... still works end to end: the value is parsed via ParseFormat, validated against CanWrite, stored in the policy ref, and enforced as a write gate on every checkpoint-data writer. The only thing that changed is what happens after the gate passes — the resolved version used to also be stamped into each checkpoint's metadata.json, and now it isn't consumed for anything beyond the gate decision. That matches the doc rewording in Step 2: the policy field went from "selects the format for new writes" to a pure write guard.
Still holding at the Step 2 checkpoint — ready to commit on your approval.
Committed as e4ca4508d0 — drop checkpoint_version from checkpoint metadata (15 files, 32 insertions, 302 deletions).
That was the last planned step, so the branch is complete: two commits, gates removed first, then the stamp itself.
bc49bc896b— remove checkpoint_version read gatese4ca4508d0— drop checkpoint_version from checkpoint metadata
The policy subsystem (refs/entire/policies/checkpoint, the hidden entire checkpoint policy command, write gates, telemetry) is untouched as agreed, and existing checkpoints' stored checkpoint_version values are left for the external migration script.
One note before this ships: I ran unit tests on the changed packages but not mise run test:integration or the e2e canary — if any integration test asserts on checkpoint_version in metadata.json, it would only surface there. Want me to run the integration suite, or go straight to /pr?