Skip to content

fix(checkpoint): kind-route backfill writes to the store holding the checkpoint#1811

Open
peyton-alt wants to merge 3 commits into
mainfrom
fix/checkpoint-backfill-kind-routing
Open

fix(checkpoint): kind-route backfill writes to the store holding the checkpoint#1811
peyton-alt wants to merge 3 commits into
mainfrom
fix/checkpoint-backfill-kind-routing

Conversation

@peyton-alt

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

Copy link
Copy Markdown
Contributor

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

Problem

entire checkpoint explain --generate <hex-id> under a git-refs primary generated the AI summary, then discarded it, and printed the misleading error no checkpoint or commit found matching "<id>" — for a checkpoint the same command had just displayed.

Root cause: kindRoutingStore kind-routes reads across both git backends (a hex ID under a git-refs primary reads refs, then falls back to the v1 branch), but writes always went to the configured primary. A pre-migration hex checkpoint that only exists on the v1 branch therefore resolved on read but failed every backfill with ErrCheckpointNotFound from the refs store.

Fix

Backfill writes (SessionSummary, SessionTranscript, CheckpointAttribution) target an existing checkpoint, so they now follow the same store order reads use, falling through to the next store on ErrCheckpointNotFound:

  • hex under git-refs primary → refs (via the mirror fan-out writer), then v1 branch
  • ULID → always refs, regardless of primary
  • a backfill landing on the primary still fans out to mirrors; one landing on a fallback store skips them (mirrors follow the primary)
  • creates (Session) are unchanged — their ID is minted to match the primary's format

Verification

  • TDD: new TestKindRoutingStore_* tests written first (bug repro fails with checkpoint not found before the fix)
  • Full unit suite green (8122 tests), mise run fmt + mise run lint clean
  • Verified end-to-end against the real repro: entire checkpoint explain --generate 2cb795c79075 in this repo now persists the summary to the v1 branch and it reads back

Related follow-ups shipped separately (not stacked): explain's misleading error-message conflation, and the stale entire explain --generate hint text.

🤖 Generated with Claude Code


Note

Cursor Bugbot is generating a summary for commit 3848cac. Configure here.

…checkpoint

Backfill writes (SessionSummary, SessionTranscript, CheckpointAttribution)
always went to the configured primary, while reads are kind-routed across
both git backends. Under a git-refs primary, a pre-migration hex checkpoint
that only exists on the v1 branch resolved fine on read but failed every
backfill with ErrCheckpointNotFound — 'entire checkpoint explain --generate'
generated the AI summary, then discarded it on save.

Backfills now follow the same store order as reads, falling through on
ErrCheckpointNotFound. A backfill landing on the primary still fans out to
mirrors; one landing on a fallback store skips them (mirrors follow the
primary). Creates (Session) are unchanged: their ID is minted to match the
primary's format.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@peyton-alt
peyton-alt requested a review from a team as a code owner July 20, 2026 20:01
Copilot AI review requested due to automatic review settings July 20, 2026 20:01

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

Fixes a checkpoint backfill bug in the persistent-store kind router: when a repo is configured with a git-refs primary, reads can fall back to the git-branch (v1) backend for legacy hex checkpoints, but backfill writes (e.g., checkpoint explain --generate) previously always targeted the primary and could discard generated data with a misleading “not found” error.

Changes:

  • Kind-route backfill writes (summary/transcript/attribution) using the same backend priority order as reads, falling through on ErrCheckpointNotFound.
  • Preserve mirror fan-out when the backfill lands on the configured primary; skip mirrors when it lands on a fallback backend.
  • Add regression and routing tests covering hex-on-branch fallback, ULID routing, and mirror fan-out behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
cmd/entire/cli/checkpoint/routing_store.go Implements kind-routed backfill write fallback (on ErrCheckpointNotFound) while keeping creates routed to the primary writer.
cmd/entire/cli/checkpoint/routing_store_test.go Adds regression tests for summary/transcript/attribution backfills across mixed backends and verifies mirror fan-out semantics.
cmd/entire/cli/checkpoint/open.go Updates store-opening comment to reflect that kind routing now applies to backfill writes as well as reads.

Review findings from the PR #1811 multi-agent pass:

- Log the fallthrough: a backfill served by a fallback store now emits
  logging.Info (absent from primary, mirrors skipped) and each skip emits
  logging.Debug — previously the most consequential routing decision in
  the store recorded nothing.
- Branch-store backfills no longer create the v1 branch as a probe side
  effect: requireSessionsBranch reports ErrCheckpointNotFound when the
  sessions branch is absent, instead of ensureSessionsBranch materializing
  an orphan branch in refs-only repos on a miss. Creates still ensure.
- Pin two behaviors with tests: a hard (non-not-found) primary error
  aborts the fallthrough and leaves the fallback store untouched; a
  migrated hex checkpoint present in both backends backfills to refs,
  where refs-first reads can see it.
- Document the deliberate write/read fallthrough asymmetry, the local-only
  backfill absence probe, the closed-union trap in backfillTarget, and the
  isPrimary default arm.
- Update ref-checkpoint-backend.md and sessions-and-checkpoints.md, which
  still described writes as never kind-routed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@peyton-alt

Copy link
Copy Markdown
Contributor Author

Applied the review fix set in 6b961f7:

  • Fallthrough observability: fallback-store backfills now log Info (absent from primary, mirrors skipped); each store skip logs Debug with checkpoint ID + request type.
  • No branch creation on a miss: branch-store backfills use a new requireSessionsBranch (reports ErrCheckpointNotFound when the v1 branch is absent) instead of ensureSessionsBranch, so a refs-only repo no longer grows a live v1 branch from a typo'd explain --generate <hex>. Creates still ensure.
  • Two new pinning tests: hard primary error aborts the fallthrough (fallback store verified untouched); migrated hex present in both backends lands on refs where refs-first reads see it. Plus the branch-guard test (TDD, red first).
  • Comments: documented the deliberate write-vs-read fallthrough asymmetry, the local-only backfill absence probe (refBase does not on-demand fetch), the closed-union trap in backfillTarget, and the isPrimary default arm.
  • Docs: ref-checkpoint-backend.md + sessions-and-checkpoints.md no longer claim writes are never kind-routed.

Not addressed here (follow-up candidates): unifying the refs backfill absence probe with the read path's on-demand fetch (multi-machine mid-migration divergence), and whether fallback backfills should fan out to mirrors best-effort. Full suite green (8125 tests), fmt + lint clean.

…te bug

Cover the full CLI path the field bug broke: auto target resolution, routed
read, summary generation (stubbed provider), kind-routed backfill, and the
summary persisting on the v1 branch — with a git-refs primary configured and
the hex checkpoint existing only on the branch. Verified to fail on main and
pass here.

Closes the coverage gap the trail confidence eval flagged (no end-to-end test
of the explain --generate path).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
peyton-alt added a commit that referenced this pull request Jul 21, 2026
…ore layer

Review findings from the PR #1824 multi-agent pass:

- Tests: pin the zero-cost claim (backfill with a locally-present ref never
  fetches), verify the fetched-then-backfilled data reads back for all three
  request types, and assert the backfill commit parents on the fetched tip
  rather than orphaning over the checkpoint's history.
- Comments rephrased order-agnostically: the write-fallthrough they cited is
  PR #1811's unmerged behavior; they now state the absence-vs-failure
  contract instead of a phantom mechanism. refBase's doc names its other
  deliberate callers (migrate.go local import; attach's externally-guarded
  writeSession).
- FetchCheckpointRef's stale 'caller treats a fetch failure as not found'
  comment inverted the actual contract this PR depends on; it now documents
  failure-surfaces-never-absence, including the remote-lacks-ref caveat.
- ref-checkpoint-backend.md: the write shape and on-demand-fetch sections now
  describe the create/backfill probe split.

Scope note (review CRITICAL): no production write path currently wires a
RefFetcher, so this PR is store-layer semantics + plumbing; the wiring is a
follow-up gated on (1) FetchCheckpointRef distinguishing remote-lacks-ref
(absence) from transport failure — today wiring would break the
pre-migration-hex fallthrough — and (2) a hook-appropriate fetch timeout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

2 participants