From f4093e03a91d06a53a134990f8b4c6e8d386bd65 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Jul 2026 03:52:41 +0000 Subject: [PATCH 1/2] docs: complete #108's prerequisite and correct its branch list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-verified the five branches against the live remote before touching anything, which mattered: claude/clinical-kb-pwa-review-asi3wb and claude/dazzling-blackwell-f348d0 are already gone, deleted by someone with the permission this session lacks and surfaced only by `git remote prune`. The list is three, not five, and #108 said five. The remaining three are still at exactly the recorded HEADs, and the proof was re-run and strengthened. For each, tree(tip) == tree(merge-base) byte-for-byte, so the branch nets zero content change from where it forked and nothing on it is absent from main. That is stronger than either check the cleanup guide names: --cherry-pick still reports 13/6/4 patch-unique commits on them, which is the squash-merge false positive the guide warns about, and none is an ancestor of main, so an ancestry --merged check would miss them too. A completed `branch-cleanup` row keyed to its own HEAD is now appended for each, which is the step that had to happen while the objects still exist — resolveHead refuses a HEAD that is not a commit in the repository, so the reverse order is unexecutable. check:branch-review-ledger passes at 1272 records with union merge intact. The refs can now be deleted safely at any time. Deletion itself is still blocked and is not mine to unblock: `git push origin --delete` exits 1 with HTTP 403 from the session git proxy, with recentRelayFailures empty, so it is credential scope rather than a relay fault; and the GitHub MCP set exposes create_branch but no delete-branch capability. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012YRCXgX4AWZ579bKN6sk6b --- docs/branch-review-ledger.md | 3 +++ docs/outstanding-issues.md | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index 729fd6f6a7..67d5312fe3 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -1312,3 +1312,6 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie | 2026-07-30 | PR #1394 / `claude/top-search-design-mockups-w53znc` | `0d47141fc030684299dcb265e3d853c93b9e2a91` | CI/review closeout — merged | MERGED as squash `0d47141f`. Prior tip `4a001efa` had required CI green after prettier fix `61314887` (Static PR/CircleCI red on `#096` padding) and main sync. Layout/`/tools` false-positive fixed; `#115` deferred; review threads resolved. Post-merge ledger-only follow-up. | hosted Static/Unit/PR-required/CircleCI pass on pre-merge tip; vitest adoption 6/6; typecheck; Bugbot no open P0/P1; merge-tree clean | | 2026-07-30 | cursor/pr-1394-ledger-closeout-c2bf | f734dc4d4c8b19d5fec43bbd388c2a421e47668a | PR #1399 babysit / CI+Bugbot closeout | MERGE-READY. No failing CI, no unresolved review threads, merge-tree clean vs origin/main, Bugbot no bugs. Docs-only ledger append for merged #1394; no code fix required. | hosted PR required SUCCESS; Static PR SUCCESS (lint/typecheck/format/ledger); CircleCI verify SUCCESS; local check:branch-review-ledger PASS; prettier PASS; lint PASS; Bugbot pr-bugbot no findings | | 2026-07-30 | claude/test-coverage-analysis-2vcd8a | d5842e62238237ff5c47da0b32ef8d9f12819714 | PR #1398 babysit | COMPLETE for tip: cleared main conflict; fixed Codex P2 (reject refs/*→origin/* nesting); prior Codex P2 (destination check) already fixed in de594186 and resolved; 0 unresolved threads; merge-tree clean. Hosted CI re-running. | repo-hygiene 40/40; verify:cheap earlier PASS on pre-tip; format:changed PASS; Bugbot none; Codex P2 resolved | +| 2026-07-30 | origin/codex/document-reader-condensed-view | b5cdbf301d517239ffe9ed941b9ebe809aea0bfd | branch-cleanup | safe to delete — tip tree identical to merge-base tree (855aa291), so the branch nets zero content change vs main; --cherry-pick shows 13 commits, a squash-merge false positive | git diff --name-only merge-base..tip = 0 files; tree(tip)==tree(merge-base); git ls-remote confirms live HEAD | +| 2026-07-30 | origin/cursor/page-anchored-search-composer-30ee | 7ff134ca7f614db527b8d142676640305533669d | branch-cleanup | safe to delete — tip tree identical to merge-base tree (79d1c879), so the branch nets zero content change vs main; --cherry-pick shows 6 commits, a squash-merge false positive | git diff --name-only merge-base..tip = 0 files; tree(tip)==tree(merge-base); git ls-remote confirms live HEAD | +| 2026-07-30 | origin/cursor/pr-1379-babysit-ledger-9365 | be2de03f855cb7fdfccea4bb74d05eb4c9bf6c61 | branch-cleanup | safe to delete — tip tree identical to merge-base tree (b2740480), so the branch nets zero content change vs main; --cherry-pick shows 4 commits, a squash-merge false positive | git diff --name-only merge-base..tip = 0 files; tree(tip)==tree(merge-base); git ls-remote confirms live HEAD | diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index e9a2f8293f..c695effaa8 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -146,7 +146,7 @@ removed after current-main verification; it is not missing recommended work. | #105 | P3 | task | Verify the `#017`-exempt client latency wins in a browser | **Outcome:** the two zero-payload client fixes are confirmed in a real browser. `#017` gates _payload_ decisions (#012/#013/#016 are all byte-count items); a `loading` fallback ships zero bytes and a resource hint ships ~60, so neither can be justified or refuted by a Lighthouse number — that is why these were not held behind #017. **Implementation shipped 2026-07-29; browser verification still PENDING:** 10 of 11 `ssr:false` dashboard surfaces had NO `loading` fallback and rendered nothing between HTML arrival and chunk execution — all now use the shared `LoadingPanel` (`role="status"` + accessible label); Supabase `preconnect`/`dns-prefetch` added, since `AuthProvider` awaits a cross-origin `getUser()` on mount that every auth-gated fetch queues behind and there were no resource hints anywhere in `src/`. Shipped with `verify:cheap` + `verify:pr-local` only. **Next:** run `npm run verify:ui` once the heavy-run lock is free, and confirm the preconnect appears in `` on a live page. **Stop:** the two sidebar dialogs are intentionally excluded — they mount on open, so a fallback would render into a closed dialog. | `docs/audit/latency-audit-2026-07-28.md` L3-4/L3-5; `src/components/clinical-dashboard/clinical-dashboard-lazy.tsx` | 2026-07-29 | | #106 | P2 | rec | Ingestion worker and indexing agent are verified by grepping their own source | **Outcome:** the ingestion worker and indexing agent are verified by executing code, not by asserting on their own source text. **Detail:** measured 2026-07-29 via `npm run test:coverage` — `worker/main.ts` (2,015 lines) and `supabase/functions/indexing-v3-agent/index.ts` (1,966 lines) each report **0% executed lines**; no test imports either module. Both are covered only by `readFileSync` + `toContain` assertions in `worker-safe-logging.test.ts`, `worker-visual-capture.test.ts` and `document-metadata-merge.test.ts`, which pass whenever a string is present and break on harmless refactors; `document-metadata-merge.test.ts` additionally reimplements the SQL deep-merge in TypeScript and tests the reimplementation rather than the worker. Area totals: `worker/` 18.6% lines, `supabase/functions/` 4.5%. **Next:** continue the extraction pattern that already works here — `indexing-v3-agent/behavior.ts` (167 lines, 96%) and `ingestion-worker/auth.ts` (30 lines, 90%) — pulling the highest-risk decision points out of `worker/main.ts` (job claim/retry, generation commit, failure classification) into importable modules with executing tests, retiring the matching source-text assertion as each lands. Roughly cost-neutral: each extracted test replaces a grep assertion. **Stop:** do not try to make the 2,000-line entrypoint importable in one pass; extract incrementally and keep each step green. | session 2026-07-29 test-coverage analysis | 2026-07-29 | | #107 | P2 | rec | Component state matrices are the largest untested surface | **Outcome:** loading / empty / error / disabled states on interactive components are covered by executing tests, not only by E2E happy paths. **Detail:** measured 2026-07-29 — production components (excluding mockups) sit at **38.2% lines / 22.8% branch** across 12,602 lines, with **83 of 208 files at zero executed lines**; there are 51 `.dom.test.tsx` files against 195 components. Playwright does visit these routes, so they are smoke-covered, but branch coverage is where the state matrix lives and smoke journeys rarely reach it. Worst by uncovered lines: `global-search-shell.tsx` (7%), `mode-action-popup.tsx` (21%), `answer-content.tsx` (27%), `document-search-results.tsx` (32%), `universal-search-command-surface.tsx` (39%), `master-search-header.tsx` (43%). A concrete first target with clinical meaning: `calculator-ui.tsx` now covers all exported scoring logic, but `seedCheckboxDefaults`, `toggleCheckboxAnswer` and `selectOptionAnswer` stay uncovered because they are module-private and only reachable through React event handlers — `seedCheckboxDefaults` is what makes an all-negative CAGE / SAD PERSONS screen read as a valid 0 rather than incomplete, so a regression there is a false-negative risk. **Next:** treat as a per-PR convention rather than a backfill push — `docs/testing.md` already prescribes the state matrix, so the gap is enforcement. Start with `global-search-shell.tsx`, which `docs/search-chrome-behaviour.md` treats as a contract surface. Keep additions in the jsdom tier (measured ~0.54s per file) instead of new Playwright journeys (~231 production journeys already run serially at `workers: 1` against a 45-minute CI budget). **Stop:** do not chase the coverage percentage by backfilling low-risk components; the re-ratcheted broad floor in `vitest.config.mts` holds the line. | session 2026-07-29 test-coverage analysis | 2026-07-29 | -| #108 | P3 | task | Five verified-landed remote branches await deletion (blocked in-session) | **Outcome:** the five branches whose content is fully on `main` are gone. **Detail:** a full-history branch-cleanup review on 2026-07-29 verified these introduce an empty diff against `main` and back no open PR: `claude/clinical-kb-pwa-review-asi3wb` @ `df29f311b60cadf8e43bf51283a9d6f496b295e3`, `claude/dazzling-blackwell-f348d0` @ `c9bec8f9dce38cb647de9aa64ebf08bf7823a524`, `codex/document-reader-condensed-view` @ `b5cdbf301d517239ffe9ed941b9ebe809aea0bfd`, `cursor/page-anchored-search-composer-30ee` @ `7ff134ca7f614db527b8d142676640305533669d`, `cursor/pr-1379-babysit-ledger-9365` @ `be2de03f855cb7fdfccea4bb74d05eb4c9bf6c61`. **The HEADs are recorded because they are unrecoverable once the refs are deleted:** `hasCompletedCleanupReview` (`scripts/sweep-branch-ledger.mjs:83-93`) matches a completed row on branch name AND HEAD together, so without them no later operator could ever append the required `branch-cleanup` rows. Each candidate now also has its own `branch-cleanup-deletion-pending` ledger row keyed to its own HEAD. Deletion could not be performed: the session git proxy rejects ref deletion with **HTTP 403**, and the GitHub MCP toolset exposes no delete-branch capability. The remaining 87 were deliberately NOT cleared — their touched files still differ from `main`, which is the conservative direction. **Next — ORDER MATTERS:** append the completed `branch-cleanup` row for each branch FIRST, from a checkout that still has the objects, and only then delete the refs. `resolveHead` (`scripts/branch-review-ledger.mjs:155-167`) runs `git rev-parse --verify ^{commit}` and refuses to append a HEAD that is not a commit in the repository, so the reverse order is unexecutable once the refs are gone and their objects are pruned. The `n/a - ` escape hatch does not help here: `hasCompletedCleanupReview` only matches a 7-40 char hex HEAD, so an `n/a` row would leave the branch resurfacing in every future sweep. Delete the five from the GitHub UI or an interactive session once their rows are recorded (the existing row is `branch-cleanup-deletion-pending`, which by design does not count as complete). **Stop:** do not widen to the other 87 without per-branch content proof. | session 2026-07-29 branch cleanup; ledger `branch-cleanup-deletion-pending` @ 855aa291 | 2026-07-29 | +| #108 | P3 | task | Five verified-landed remote branches await deletion (blocked in-session) | **Outcome:** the five branches whose content is fully on `main` are gone. **Detail:** a full-history branch-cleanup review on 2026-07-29 verified these introduce an empty diff against `main` and back no open PR: `claude/clinical-kb-pwa-review-asi3wb` @ `df29f311b60cadf8e43bf51283a9d6f496b295e3`, `claude/dazzling-blackwell-f348d0` @ `c9bec8f9dce38cb647de9aa64ebf08bf7823a524`, `codex/document-reader-condensed-view` @ `b5cdbf301d517239ffe9ed941b9ebe809aea0bfd`, `cursor/page-anchored-search-composer-30ee` @ `7ff134ca7f614db527b8d142676640305533669d`, `cursor/pr-1379-babysit-ledger-9365` @ `be2de03f855cb7fdfccea4bb74d05eb4c9bf6c61`. **The HEADs are recorded because they are unrecoverable once the refs are deleted:** `hasCompletedCleanupReview` (`scripts/sweep-branch-ledger.mjs:83-93`) matches a completed row on branch name AND HEAD together, so without them no later operator could ever append the required `branch-cleanup` rows. Each candidate now also has its own `branch-cleanup-deletion-pending` ledger row keyed to its own HEAD. Deletion could not be performed: the session git proxy rejects ref deletion with **HTTP 403**, and the GitHub MCP toolset exposes no delete-branch capability. The remaining 87 were deliberately NOT cleared — their touched files still differ from `main`, which is the conservative direction. **Next — ORDER MATTERS:** append the completed `branch-cleanup` row for each branch FIRST, from a checkout that still has the objects, and only then delete the refs. `resolveHead` (`scripts/branch-review-ledger.mjs:155-167`) runs `git rev-parse --verify ^{commit}` and refuses to append a HEAD that is not a commit in the repository, so the reverse order is unexecutable once the refs are gone and their objects are pruned. The `n/a - ` escape hatch does not help here: `hasCompletedCleanupReview` only matches a 7-40 char hex HEAD, so an `n/a` row would leave the branch resurfacing in every future sweep. **Progress 2026-07-30 — the prerequisite is DONE; only the deletion is left, and it needs a caller who can delete refs.** Re-verified against the live remote first, which mattered: `claude/clinical-kb-pwa-review-asi3wb` and `claude/dazzling-blackwell-f348d0` are **already gone** (surfaced by `git remote prune`, deleted by someone with the permission this session lacks), so the list is three, not five. The remaining three are still at exactly the recorded HEADs, and the proof was re-run and strengthened: for each, `tree(tip) == tree(merge-base)` byte-for-byte, so the branch nets zero content change from where it forked and nothing on it is absent from `main`. That is stronger than either check the guide names — `--cherry-pick` still reports 13/6/4 patch-unique commits on them, which is the squash-merge false positive, and none is an ancestor of `main`, so `--merged` would also miss them. A completed `branch-cleanup` row keyed to its own HEAD is now appended for each of the three (`npm run check:branch-review-ledger` passes at 1272 records), so the ORDER MATTERS constraint above is satisfied and the refs can now be deleted safely at any time. Deletion re-attempted and still blocked: `git push origin --delete` exits 1 with **HTTP 403** from the session git proxy (`recentRelayFailures` empty, so it is credential scope, not a relay fault), and a tool search confirms the GitHub MCP set exposes `create_branch` but no delete-branch capability. **Next:** delete these three refs from the GitHub UI or any session whose credentials permit ref deletion — `codex/document-reader-condensed-view`, `cursor/page-anchored-search-composer-30ee`, `cursor/pr-1379-babysit-ledger-9365`. Nothing else is required first. **Stop:** do not widen to the other 87 without per-branch content proof. | session 2026-07-29 branch cleanup; ledger `branch-cleanup-deletion-pending` @ 855aa291 | 2026-07-29 | | #109 | P2 | issue | Remote sessions clone shallow, silently invalidating all branch/merge analysis | **Outcome:** no session draws branch conclusions from a truncated history. **Detail:** on 2026-07-29 this repo's remote session had `git rev-parse --is-shallow-repository` = **true** with only **74** commits of `origin/main` (full history is 2829). Every merge-base, `--cherry-pick`, and ahead/behind number computed in that state was wrong: local `main` reported `ahead 52` and `refusing to merge unrelated histories` (it is actually 0 ahead with a shared base), and an all-branch sweep wrongly showed **90 of 91** branches as carrying unmerged work. Acting on that would have meant either deleting live branches or abandoning cleanup entirely. `git fetch --unshallow` corrected both. **FIXED 2026-07-29:** `scripts/sweep-branch-ledger.mjs` now refuses outright on a shallow clone via the exported `shallowCloneRefusal`, printing no inventory and exiting 1 in both text and `--json` mode, before the fetch and before any branch maths. `docs/branch-cleanup-guide.md` §Safety Rules gains the `is-shallow-repository` precondition ahead of its numbered steps, because the raw `git` commands it documents have no such guard. Proven in a real `--depth 1` clone: unguarded the sweep exited **0** and named the live checked-out branch a deletion candidate with "no unique patch content"; guarded it exits 1 with the `--unshallow` remedy. Five cases in `tests/repo-hygiene.test.ts` cover both directions, including that the string `"false"` (truthy) must NOT be read as shallow — the way this guard could fail dangerously in reverse. **Hardened in review:** an indeterminate `is-shallow-repository` result (empty output from a swallowed `git` failure) is now refused as its own failure rather than treated as complete, and the same refusal was extended to `scripts/reconciliation-preflight.mjs`, which reports its own merge-base-derived ahead/behind. That guard then had to move OUT of the preflight CLI and INTO the exported `collectReconciliationState`, because `buildReconciliationEvidencePack` calls the collector directly and stamps `status: "complete"`: in a `--depth 1` clone the guarded CLI exited 1 while the evidence-pack command exited 0 and persisted shallow ahead/behind as completed evidence. The collector now throws `UnverifiedHistoryError` (`code: "history-not-verified"`), so every current and future caller fails closed by default instead of by remembering to ask; the CLI catches it only to keep the `--json` envelope. Regression cases live with each entry point (`tests/reconciliation-preflight.test.ts`, `tests/reconciliation-evidence-pack.test.ts`) and build a real `--depth 1` clone, asserting `is-shallow-repository` is `true` first so a git behaviour change cannot make them pass vacuously. **Second failure mode, found in review after the first fix landed: complete history is not complete branch coverage.** `git clone --depth 1` implies `--single-branch`, pinning `remote.origin.fetch` to the one cloned branch; `git fetch --unshallow` converts the history so `--is-shallow-repository` reads `false` and the shallow guard passes, but it does not widen the refspec, and an ordinary `git fetch origin` respects the narrow one. Measured in a `main`+`feature` fixture: after unshallowing, `git ls-remote --heads origin` listed both while `refs/remotes/origin` held only `origin/main`, and the sweep exited **0** reporting `"branches": []` — and an empty inventory is not a safe failure, since it reads as "nothing to clean up" and a missing `origin/main` makes every `rev-list` fail into `0/0`, i.e. every branch a deletion candidate. Fixed both ways: the sweep's fetch now passes an explicit `+refs/heads/*:refs/remotes/origin/*` (repairing coverage without rewriting the operator's config), and `branchCoverageRefusal` refuses when neither the configured refspec nor a completed wildcard fetch establishes coverage — `--no-fetch`, offline, or a failed fetch. Its remedy is deliberately `git remote set-branches origin '*'`, not `--unshallow`, which fixes history and does nothing here. **Two further routes to the same empty-inventory answer, both found in review, both from checking only half of the refspec.** (1) The DESTINATION matters as much as the source, because the sweep enumerates `refs/remotes/origin` and nothing else: with `+refs/heads/*:refs/remotes/upstream/*`, `refs/remotes/upstream` held `upstream/main` and `upstream/feature` while `refs/remotes/origin` stayed empty and the sweep exited **0** with `"branches": []`. (2) Git substitutes the matched suffix into ``, so a `refs/*` source nests one level deeper: `+refs/*:refs/remotes/origin/*` writes `refs/remotes/origin/heads/main`, `origin/main` then does not resolve at all, every comparison fails into `0/0`, and the sweep exited **0** naming both `heads/feature` and **`heads/main`** as deletion candidates — a green run recommending the deletion of `main`. Coverage from config therefore requires exactly `refs/heads/*` to `refs/remotes/origin/*`; a completed wildcard fetch still establishes coverage by itself, since the sweep passes that destination explicitly. **Stop:** never delete a branch, or report a branch as unmerged, from a shallow clone, a single-branch refspec, or a refspec whose destination is not `refs/remotes/origin/*`. | session 2026-07-29; `docs/branch-cleanup-guide.md`; `scripts/sweep-branch-ledger.mjs` | 2026-07-29 | | #110 | P3 | task | Design-system project token manifest lags its stylesheet | **Outcome:** the claude.ai/design token panel matches the shipped stylesheet. **Detail:** PR #1375 pushed a recompiled `_ds_bundle.css` (Clinical Sky, `--e0`–`--e4`, 4px radius grid, `--tracking-eyebrow`/`--leading-display`/`--leading-prose`) plus the four changed guideline docs to project `08d6f126`, but `_ds_manifest.json` is converter-generated and still advertises `--text-4xs: 0.5rem`, the old `--radius-lg/xl/2xl` values, and `--tw-leading`/`--tw-tracking` entries scoped to the retired `.leading-[…]` / `.tracking-[0.08em]` utilities. Rendering is correct; only the token inventory lags. Hand-editing was rejected — `kind`/`scope`/`annotation` are converter heuristics and a wrong panel is worse than a stale one. **Next:** in a session with the `/design-sync` skill, `npm ci`, then `npm install --prefix .ds-sync --no-save --package-lock=false esbuild ts-morph @types/react @tailwindcss/cli geist`, read `.design-sync/NOTES.md`, and run `resync.mjs --remote` so bundle and manifest regenerate together. **Stop:** do not hand-author `_ds_manifest.json`; the converter is not a published npm package and ships with the skill. | PR #1375; `.design-sync/NOTES.md`; project `08d6f126` (`_ds_needs_recompile` marker present) | 2026-07-29 | | #112 | P2 | issue | `issues:next-id` has no concurrency protection | **Outcome:** two agents working the same hour cannot allocate the same ledger id. **Detail:** the marker at the top of this file is a plain HTML comment read-modify-written by whoever edits next, with no lock and no post-merge check. On 2026-07-29 it collided **twice in one hour**: PR #1391 claimed `#096`/`#097`, lost them, claimed `#098`/`#099`, lost those too, and its final pair `#108`/`#109` collided a third time with the branch-cleanup work that reached `main` first — resolved during the #1391 merge by renumbering to `#110`/`#111` and bumping the marker to 112. Each collision is silent: `docs/outstanding-issues.md` has NO union merge driver (unlike `docs/branch-review-ledger.md`), so it presents as an ordinary content conflict that a hurried resolution can settle by dropping one side's rows entirely. Nothing checks for duplicate ids afterwards. **Next:** add a duplicate-id and marker-consistency check to the verification gates — the cheapest useful form is a test asserting every `#NNN` id appears exactly once across both tables and that the marker exceeds the max, which turns a silent loss into a red gate. Consider`merge=union`in`.gitattributes` as well, though row-level union does not by itself prevent two rows sharing an id. **Stop:** do not resolve one of these conflicts by taking one side wholesale without diffing the id sets first; that is how rows get dropped. | session 2026-07-29 PR sweep; PR #1391 conflict resolution; `.gitattributes` | 2026-07-29 | From 0fe40896829de6def9ea975db8d4cff25e8571bc Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Jul 2026 04:29:11 +0000 Subject: [PATCH 2/2] docs(ledger): supersede the three cleanup rows with the ancestor step MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex raised a P2 on PR #1403: marking these HEADs `branch-cleanup` suppresses future inspection while the rows themselves report 13/6/4 patch-unique commits, and tree equality between tip and merge-base only proves the branch's changes cancel in its final snapshot, not that each unique patch reached main. The conclusion does not hold for these branches, and measuring it settles which it is. For all three, the merge-base is an ANCESTOR of main — so tree(tip) == tree(merge-base) means every byte at the tip exists in main's own history. The changes did not cancel; they landed. The branches merged main in after their own PRs were squash-merged, which is why their diffs went empty. Checked concretely on the largest: the feature commit's new files (src/components/document-viewer/use-document-view-density.ts, use-printable-disclosures.ts, tests/document-view-density.dom.test.tsx) are present on origin/main as byte-identical blobs, and the 13 "unique" commits are six merges of main plus seven commits whose content is on main. But the procedural half of the finding was right. My original rows recorded tree equality WITHOUT recording that the merge-base is an ancestor of main — and tree equality alone does not imply the content is on main, since a tip could match an off-main commit. The proof was sound and the record of it was not. These superseding rows carry the full chain. The original exact-scope rows are left in place, so hasCompletedCleanupReview still resolves them; the ledger is append-only and this adds evidence rather than revising history. Verified: ancestry measured for all three merge-bases (855aa291, 79d1c879, b2740480), not inferred from the one I had checked. check:branch-review-ledger passes at 1282 records with union merge intact. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012YRCXgX4AWZ579bKN6sk6b --- docs/branch-review-ledger.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index 861b47e8da..744230ed20 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -1322,3 +1322,6 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie | 2026-07-30 | origin/cursor/page-anchored-search-composer-30ee | 7ff134ca7f614db527b8d142676640305533669d | branch-cleanup | safe to delete — tip tree identical to merge-base tree (79d1c879), so the branch nets zero content change vs main; --cherry-pick shows 6 commits, a squash-merge false positive | git diff --name-only merge-base..tip = 0 files; tree(tip)==tree(merge-base); git ls-remote confirms live HEAD | | 2026-07-30 | origin/cursor/pr-1379-babysit-ledger-9365 | be2de03f855cb7fdfccea4bb74d05eb4c9bf6c61 | branch-cleanup | safe to delete — tip tree identical to merge-base tree (b2740480), so the branch nets zero content change vs main; --cherry-pick shows 4 commits, a squash-merge false positive | git diff --name-only merge-base..tip = 0 files; tree(tip)==tree(merge-base); git ls-remote confirms live HEAD | | 2026-07-30 | claude/white-element-positioning-t607pk | b82ff088436cd936d219a4eb54a54d09a88fbd7c | pr-babysit | Product tip sound; no code fix. Hosted CI fully green once at e7a27bbf (Production UI+PR required). Recurring blocker: repeated Merge main into PR cancels Production UI mid-run so PR required fails with production-ui=cancelled. merge-tree clean / MERGEABLE when left alone. No review threads. Bugbot: no cursor[bot] findings; suite stays queued. Local A/B: 3 Playwright fails identical on --surface/--background. | verify:cheap:pass; hosted:e7a27bbf:PR-required+Production-UI:pass; A/B-playwright:env-flake; bugbot:no-findings; churn:main-merges-cancel-ui | +| 2026-07-30 | origin/codex/document-reader-condensed-view | b5cdbf301d517239ffe9ed941b9ebe809aea0bfd | branch-cleanup (supersedes 2026-07-30) | safe to delete — merge-base 855aa291 is an ANCESTOR of main and tree(tip)==tree(855aa291), so every byte at the tip exists in main's history; the 13 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work | git merge-base --is-ancestor 855aa291 origin/main = YES; tree(tip)==tree(855aa291); feature blobs present and byte-identical on origin/main; supersedes the earlier row, which omitted the ancestor step (Codex P2, PR #1398/#1403) | +| 2026-07-30 | origin/cursor/page-anchored-search-composer-30ee | 7ff134ca7f614db527b8d142676640305533669d | branch-cleanup (supersedes 2026-07-30) | safe to delete — merge-base 79d1c879 is an ANCESTOR of main and tree(tip)==tree(79d1c879), so every byte at the tip exists in main's history; the 6 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work | git merge-base --is-ancestor 79d1c879 origin/main = YES; tree(tip)==tree(79d1c879); feature blobs present and byte-identical on origin/main; supersedes the earlier row, which omitted the ancestor step (Codex P2, PR #1398/#1403) | +| 2026-07-30 | origin/cursor/pr-1379-babysit-ledger-9365 | be2de03f855cb7fdfccea4bb74d05eb4c9bf6c61 | branch-cleanup (supersedes 2026-07-30) | safe to delete — merge-base b2740480 is an ANCESTOR of main and tree(tip)==tree(b2740480), so every byte at the tip exists in main's history; the 4 --cherry-pick commits are merges of main plus work already squash-merged, not uncancelled work | git merge-base --is-ancestor b2740480 origin/main = YES; tree(tip)==tree(b2740480); feature blobs present and byte-identical on origin/main; supersedes the earlier row, which omitted the ancestor step (Codex P2, PR #1398/#1403) |