Skip to content

feat(import): anchor imported checkpoints to the default branch head#1825

Merged
peyton-alt merged 8 commits into
mainfrom
feat/import-commit-link
Jul 23, 2026
Merged

feat(import): anchor imported checkpoints to the default branch head#1825
peyton-alt merged 8 commits into
mainfrom
feat/import-commit-link

Conversation

@peyton-alt

@peyton-alt peyton-alt commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

https://entire.io/gh/entireio/cli/trails/916

What

entire import now stamps a commit_sha field into every checkpoint it writes — the default branch's head at import time (origin tip preferred → local branch → HEAD → empty). It lands in both the session metadata.json and the root CheckpointSummary (omitempty, preserve-on-rewrite), giving the UI a join key to anchor imported sessions to a commit so repo pages and stats populate immediately after an import.

Why

Imported history is commit-less: the normal commit↔checkpoint join is the Entire-Checkpoint trailer, which pre-existing commits don't have and never will (we don't rewrite history). The anchor is deliberately a link, not attribution — it says "imported at this point in time", not "this session built that commit". The sha lives inside the checkpoint metadata rather than in a ref name: checkpoint IDs are strictly 12-hex/ULID, and stuffing a 40-hex sha into refs/entire/checkpoints/ would break ID validation and force a growing shared-ref list for the common all-anchors-same-sha case.

How

  • WriteOptions.CommitSHA → session Metadata + root CheckpointSummary (commit_sha, omitempty; root summary preserves a stamped value if a later write carries an empty one, mirroring the existing Imported/HasReview pattern)
  • agentimport.Options.LinkCommitSHA threaded through RunwriteTurn; resolution stays out of the package
  • resolveImportLinkCommitSHA in the cli package: origin's default-branch tip (the commit the server already knows) → local branch → HEAD → "" (best-effort; an unresolvable repo imports unlinked, never fails)
  • No new refs, no new commits, no flags, no backfill of previously-imported checkpoints

Per-turn real-commit anchors

When a Claude Code transcript records the commits a turn made (toolUseResult.gitOperation.commit, kind committed), that turn's checkpoint anchors to the real commit instead of the head anchor: the recorded (short) sha is resolved, must be an ancestor of the default-branch tip (ancestry doubles as the reachability check — squash-merged/rebased-away commits fall through), and the last such commit of the turn wins. Everything else — older transcripts without the records, unresolvable or unreachable shas — falls back to the default-branch-head anchor above. The fallback's ancestor set is memoized lazily (one history walk per import run). Same commit_sha field either way; consumers see no schema difference.

Testing

  • TDD unit tests throughout, including a mutation-verified origin-over-local preference test (diverged origin/main vs local main) and coverage of the HEAD-fallback and empty-repo arms
  • Manual E2E on both backends: git-branch (v1) and git-refs — commit_sha present and correct in both, idempotent re-import leaves it untouched
  • Prod smoke test (fresh /et repo, real transcript, full enable→import→push flow): refs with commit_sha round-trip through the server intact. Control experiment confirmed server ingestion is currently trailer-driven: a normal checkpoint ingested into /me/recap in ~2 min while the imported refs (on the server, commit_sha and all) were never indexed.

Notes for reviewers

  • Bounded ancestor walk: the resolver's memoized ancestor set is capped by date (lookback + 60d slack) and by commit count (50k), walking newest-first (committer-time order) so early-stopping is sound. Addresses the inline review comment about unbounded time/memory on huge histories.
  • Mixed CLI versions: Metadata/CheckpointSummary are not schema-versioned, so an older CLI that rewrites an existing checkpoint (OPF pre-push re-redaction, compact-marker update, multi-session summary rebuild) round-trips through structs without commit_sha and silently drops it. This is the same exposure every additive metadata field has had; the existing fence is the checkpoint policy ref (checkpoint_min_version). Practical blast radius for imported checkpoints is narrow — attribution never targets them and rewind/generate are blocked.

Out of scope / follow-ups

  • entire.io ingestion + UI (the other half): index checkpoint refs whose metadata carries commit_sha (kind imported) and join on that field; render imported sessions as anchored to the commit, not attributed to it. The smoke test above is the repro.
  • Historical-commit matching (v2) would only change the stamped value, not the schema.
  • The test-only fsstore backend doesn't map the new field (consistent with it already skipping Imported).

🤖 Generated with Claude Code


Note

Low Risk
Additive metadata and best-effort import resolution; no changes to normal checkpoint writes or git history rewriting.

Overview
Adds an optional commit_sha field on checkpoint WriteOptions, session Metadata, and root CheckpointSummary so imported history can be tied to a git commit without an Entire-Checkpoint trailer.

entire import now resolves a link SHA at the CLI (resolveImportLinkCommitSHA: origin/<default> → local default branch → HEAD"") and passes it through agentimport.Options.LinkCommitSHA into each imported turn. The anchor is display-only (“imported at this point”), not attribution; import still succeeds when resolution fails.

The persistent git store persists commit_sha on session metadata and the root summary, with omitempty and preserve-on-rewrite when a later write leaves it empty (same pattern as Imported / HasReview). Architecture docs describe the field; tests cover resolver preference, import stamping, and persistence.

Reviewed by Cursor Bugbot for commit d2df272. Configure here.

Adds WriteOptions.CommitSHA, persisted as commit_sha on both the
session Metadata and root CheckpointSummary (omitempty, so non-import
writers stay byte-identical). agentimport.Options gains LinkCommitSHA,
copied verbatim into each imported turn's WriteOptions.CommitSHA;
resolution of the actual SHA is left to a later task.

Entire-Checkpoint: 01KY33NAEBCQFV87TK2QZM2XYD
Adds resolveImportLinkCommitSHA, which resolves the commit imported
checkpoints stamp as commit_sha: origin's tip of the default branch
(the commit the server already knows) preferred over the local branch
tip, then HEAD, then empty when nothing resolves. Wires it into
`entire import <agent>` via agentimport.Options.LinkCommitSHA.

Entire-Checkpoint: 01KY34D8R1WQXZCK1TV9T2RXHX
Copilot AI review requested due to automatic review settings July 21, 2026 21:19
@peyton-alt
peyton-alt requested a review from a team as a code owner July 21, 2026 21:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an optional commit_sha anchor to checkpoints produced by entire import, linking imported (commit-less) history to the default branch head at import time so downstream UI/services can immediately join imported sessions to a repo/commit context without rewriting git history.

Changes:

  • Thread commit_sha through import (resolveImportLinkCommitSHAagentimport.Options.LinkCommitSHA → checkpoint WriteOptions.CommitSHA).
  • Persist commit_sha on both per-session metadata.json and root CheckpointSummary (with preserve-on-rewrite behavior added for the root summary).
  • Add unit tests and update architecture docs describing the new import anchoring behavior.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
docs/architecture/sessions-and-checkpoints.md Documents commit_sha behavior for imported checkpoints and resolution precedence.
cmd/entire/cli/import_link.go Implements best-effort default-branch/HEAD commit SHA resolution for import anchoring.
cmd/entire/cli/import_link_test.go Adds unit coverage for origin-vs-local preference, HEAD fallback, and empty repo behavior.
cmd/entire/cli/import_cmd.go Wires resolved LinkCommitSHA into the import runner options.
cmd/entire/cli/checkpoint/persistent.go Persists CommitSHA into session metadata + root summary; root summary preserves existing value on rewrite.
cmd/entire/cli/checkpoint/persistent_imported_test.go Verifies persistence + omitempty behavior for commit_sha in imported checkpoints.
cmd/entire/cli/agentimport/agentimport.go Threads LinkCommitSHA through to each imported checkpoint write.
cmd/entire/cli/agentimport/agentimport_test.go Tests that LinkCommitSHA is stamped (and omitted when unset).
api/checkpoint/metadata.go Adds CommitSHA fields to WriteOptions, session Metadata, and root CheckpointSummary.

Comment thread cmd/entire/cli/checkpoint/persistent.go
peyton-alt and others added 2 commits July 21, 2026 14:39
… in tests

Addresses toolkit review findings on #1825: a Debug line records the
resolved anchor (support can tell why an import is unanchored or stale),
an integration assertion pins the import_cmd wiring end to end (omitempty
would otherwise hide a dropped wire), a store test covers the summary
preserve-on-rewrite branch, and comment polish (canonical CommitSHA doc
on WriteOptions, softened default-branch over-claims).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: 01KY39WXXNWBZ6SQQDE9TMJWN8
Retest caught that logging.Debug is a no-op without logging.Init; import
never called it, making the just-added anchor log dead code. Init
best-effort like explain/resume.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: 01KY3A8RAG6E2BFNVZZZYWTGNR
computermode
computermode previously approved these changes Jul 22, 2026
Extends the import commit_sha anchor (PR #1825) to be per-turn: when a
Claude Code transcript records the commit(s) a turn made via gitOperation
records, the turn's checkpoint anchors to the last such commit that
resolves and is an ancestor of the default-branch fallback, instead of
always pointing at the default-branch head. Older transcripts (or
recorded commits that were squashed/rebased away) keep the existing
fallback behavior unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: 01KY5P3CT3T2K4KGK4QCTBGMA6
Thread ctx through turnAnchorResolver so both ancestor-walk failure paths
and per-turn fallback decisions are Debug-logged — import is one-shot, so
an unlogged fallback destroys the only evidence of why a turn didn't
anchor to its recorded commit. Adds a regression test for a well-formed
but nonexistent fallback (no panic, graceful degrade) and a garbage-line
resilience test for commit-SHA extraction. Corrects several comments that
overstated go-git's ambiguity detection, referenced code that never
existed, or were Claude-specific where the type is agent-generic.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: 01KY7JCMV9PHB2XSQ3G71809Q1
Comment thread cmd/entire/cli/agentimport/turn_anchor.go
peyton-alt and others added 2 commits July 23, 2026 10:39
Addresses pjbgf's PR comment and the matching trail finding: the memoized
ancestor walk was a full-history traversal with unbounded memory. It now
emits newest-first (committer-time order) and stops at commits older than
the lookback window plus slack, or at 50k commits — committer-time
ordering is what makes early-stopping sound where a DFS could not. Also
makes resolve report whether a candidate actually won, so the fell-back
debug log no longer fires when a turn's recorded commit IS the tip
(second trail finding).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Entire-Checkpoint: 01KY7PMXSPJ34221FYN8PEWRQ1
@peyton-alt
peyton-alt merged commit 2a88eba into main Jul 23, 2026
11 checks passed
@peyton-alt
peyton-alt deleted the feat/import-commit-link branch July 23, 2026 16:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants