doctor: check and repair the v1.1 committed-read mirror - #1350
Conversation
Read paths use the v1.1 mirror as-is (no read-time self-repair), so a missing, stale, or diverged refs/entire/checkpoints/v1.1 silently makes v1.1 reads miss checkpoints with no repair path. Make doctor the repair tool: - strategy.DiagnoseCommittedMetadataMirror classifies the mirror against the local v1 tip (read-only): not configured, ok, missing, behind, diverged, or v1-branch-missing. - entire doctor reports the state and repairs missing/stale/diverged with confirmation (auto under --force) via the existing MirrorCommittedMetadataRef. The mirror-outlives-v1 anomaly is warn-only with a fetch suggestion; restoring v1 is out of scope. - entire doctor bundle captures entire-related refs plus the mirror diagnosis in entire-refs.txt for bug reports. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 1513a1ef2b6b
- Split MirrorNoMetadata out of MirrorPrimaryMissing so the diagnosis is self-describing; the bundle no longer labels a fresh v1.1 repo V1 MISSING. - Derive doctor headlines from MirrorStatus.String() — one source for status labels across doctor and bundle output. - Render the primary ref from diag.Refs.Primary instead of hardcoding entire/checkpoints/v1, so guidance survives a future topology flip. - Extract confirmDoctorFix, shared with checkDisconnectedMetadata. - Document why the bundle's for-each-ref globs are broader than the resolved topology refs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: dbe157735b54
Collapse the seven checkCommittedMetadataMirror tests into one table-driven test (setup returns the expected final mirror state) and cut comment prose throughout the mirror check, diagnosis, and bundle report to the essentials. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 2e1b1751fbc2
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 39b2bbc. Configure here.
There was a problem hiding this comment.
Pull request overview
Adds a dedicated repair path for the v1.1 committed-read mirror (refs/entire/checkpoints/v1.1) by moving drift detection/repair into entire doctor, plus bundling ref-state diagnostics for supportability. This fits the post-#1335 contract where read paths must treat the mirror “as-is” and never implicitly repair it.
Changes:
- Introduces
strategy.DiagnoseCommittedMetadataMirrorwith a sharedMirrorStatusclassifier to detect missing/stale/diverged/outlived-primary mirror states. - Wires a new
entire doctorcheck to diagnose and (optionally /--force) repair the v1.1 read mirror via existing mirroring logic. - Extends
entire doctor bundleto capture entire-related refs and mirror diagnosis inentire-refs.txt, with tests and docs updates.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/architecture/sessions-and-checkpoints.md | Documents entire doctor as the explicit v1.1 mirror repair tool and notes bundle capture. |
| cmd/entire/cli/strategy/v1_custom_ref_mirror.go | Adds MirrorStatus, MirrorDiagnosis, and DiagnoseCommittedMetadataMirror (read-only diagnosis). |
| cmd/entire/cli/strategy/v1_custom_ref_mirror_test.go | Adds table-driven coverage for all mirror diagnosis states + read-only invariant. |
| cmd/entire/cli/doctor.go | Adds doctor check to diagnose/repair mirror drift; factors prompt into confirmDoctorFix. |
| cmd/entire/cli/doctor_test.go | Adds tests for mirror check output/behavior, wiring into main doctor flow, and force repair behavior. |
| cmd/entire/cli/doctor_bundle.go | Adds entire-refs.txt to bundles and includes mirror status line derived from shared status strings. |
| cmd/entire/cli/doctor_bundle_test.go | Verifies entire-refs.txt contains entire refs and mirror diagnosis line. |
- confirmDoctorFix now runs via RunWithContext and treats a cancelled command context as a clean skip (guards before huh opens the TTY), honoring interrupts instead of surfacing a wrapped error. - Fix the STALE headline: "advance the mirror to the <primary> tip" instead of the contradictory "to its tip". - Close the go-git repo opened in mirrorStatusReportLine. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 82c0ad9a1407

https://entire.io/gh/entireio/cli/trails/501
What
Follow-up to #1335. That PR established the v1.1 committed-ref contract: reads resolve
refs/entire/checkpoints/v1.1as-is — read paths no longer create, repair, or advance the mirror. That leaves no repair path when the mirror drifts (pre-#1335 state, a rawgit fetchof v1 outside entire, a crash between v1 write and mirror update, external ref meddling). A drifted mirror silently makes v1.1 reads miss checkpoints.This PR makes
entire doctorthe repair tool:strategy.DiagnoseCommittedMetadataMirror— read-only classifier of the mirror against the local v1 tip:NOT CONFIGURED | OK | NO METADATA | MISSING | STALE (behind) | DIVERGED | V1 BRANCH MISSING. Returns the resolvedCommittedRefsso callers repair via the existingMirrorCommittedMetadataRef.entire doctorcheck Move "clean" root command to "session cleanup", some refactoring #2 (right after the disconnected-metadata check, which rewrites v1 and re-mirrors — this catches residual drift):✓ OKwhen healthy (including fresh repos with no metadata yet)MISSING/STALE/DIVERGED→ explain, confirm (auto with--force), point the mirror at the v1 tip; the diverged copy explicitly says the discarded commits aren't on v1git fetchsuggestion (never auto-"fixed", even under--force)entire doctor bundle— newentire-refs.txt:for-each-refover entire's ref namespaces (v1 branch, v1.1 mirror, shadow/trails branches, origin tracking) plus amirror status: STALE (mirror abc1234, v1 def5678)diagnosis line. Best-effort and goes through the standard redaction path.Design notes
MirrorStatus.String(), so the two surfaces can't drift.diag.Refs.Primaryrather than hardcodingentire/checkpoints/v1, so doctor's guidance survives a future topology flip.strategy.IsAncestorOf: that helper is a depth-capped (1000), error-swallowing log walk, and a long-lived v1 branch grows one commit per condensation — a merely-stale mirror past the cap would misclassify as DIVERGED with misleading messaging. The diagnosis uses go-git's exact ancestry and surfaces errors.confirmDoctorFix, now shared withcheckDisconnectedMetadata.entire cleanand the v1.1 remote-fetch story forentire resume(separate follow-ups).Coverage
strategy: table-drivenTestDiagnoseCommittedMetadataMirror— all seven states, plus the read-only invariant (diagnosis never creates/moves/deletes the ref).cli: table-drivenTestCheckCommittedMetadataMirror— per-state output,--forcerepairs actually move the ref to the v1 tip, warn-only state stays untouched;TestRunSessionsFix_IncludesMirrorCheckproves the wiring into the main doctor flow.cli:TestWriteDoctorBundle_CapturesEntireRefs— bundle containsentire-refs.txtwith the refs and the diagnosis line.sessions-and-checkpoints.mdv1.1 section now names doctor as the repair path.Verification
🤖 Generated with Claude Code
Note
Medium Risk
Repairs rewrite the local mirror ref to match v1 (diverged case discards mirror-only commits after user confirmation), which directly affects checkpoint read visibility but does not change v1 writes or remote sync.
Overview
Adds a checkpoints v1.1 read-mirror repair path to
entire doctor, following the contract that read paths userefs/entire/checkpoints/v1.1as-is.Strategy: Introduces
DiagnoseCommittedMetadataMirrorandMirrorStatuslabels (MISSING,STALE,DIVERGED, etc.) to compare the local mirror to theentire/checkpoints/v1tip using go-git ancestry (not the depth-capped helper). Repair still usesMirrorCommittedMetadataRef.Doctor: New check #2 runs after disconnected-metadata reconciliation; it is silent in v1-only mode, can auto-repair missing/stale/diverged mirrors with
--forceor after confirm via sharedconfirmDoctorFix, and stays warn-only when the mirror exists but v1 is gone (suggestedgit fetch). Mirror check failures accumulate like other doctor errors.Bundle:
entire doctor bundleaddsentire-refs.txtlisting entire-related refs plus amirror status:line using the same status strings.Tests cover diagnosis, doctor wiring, and bundle capture; architecture docs name doctor as the mirror repair tool.
Reviewed by Cursor Bugbot for commit 39b2bbc. Configure here.