Skip to content

fix(#384): the six-pass review no longer approves on absent evidence - #385

Merged
randomm merged 1 commit into
mainfrom
fix/issue-384-lens-diff
Aug 7, 2026
Merged

fix(#384): the six-pass review no longer approves on absent evidence#385
randomm merged 1 commit into
mainfrom
fix/issue-384-lens-diff

Conversation

@randomm

@randomm randomm commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Closes #384.

Where this came from

An operator asked whether the six-prong code review had been getting skipped in recent /work runs. Measured answer: it had not. Across every .pi/work-state/*.json in this repo, every cycle that reached lens-review ran lens-review×6, and no cycle recorded a lens-skipped-empty-diff event:

cycle reached lens-review skipped dispatches
208, 282, 286, 312, 318, 327 0 lens-review×6 (round 1)
5, 334, 338, 339, 304 0 up to round 3 + developer:lens-fix-N
277, 279, 305, 308 ❌ never got there aborted/handoff before commit-pr

Cycles where the review looks absent aborted earlier. But the question exposed a real hazard, and this PR fixes it.

The hazard

runLens treats an empty diff as approved — correct for a cycle that genuinely changed nothing. The diff came from fetchIntegratedDiff (work-driver-diff.ts:131-149), which swallowed every git error and returned "":

} catch (err) {
  trace(`work-driver: fetchIntegratedDiff(${branchName}) failed: ...`);
  return "";          // <-- indistinguishable from "nothing to review"
}

So a stale origin/<branch> ref, a transient git failure, a maxBuffer overrun on a large diff, or an unset branch name all read as approved, and the code merged unreviewed. Under always-worktree (#287) the fallback read is also empty, so there was no second opinion. Same defect class as the ci-status: substring #380 removed from the merge step: a gate whose no-signal answer is approval is a gate that cannot fail.

This had already bitten twice from the other direction — pre-PR11 the guard fired on every successful cycle (34ms skip → merged unreviewed), and #287 re-introduced it when worktrees went detached. Both were fixed by changing which diff is read. The structural problem was never fixed.

The fix

readIntegratedDiff returns a discriminated result, and empty is established positively: git rev-list --count origin/<base>..origin/<branch> must return 0. Anything else halts with the new cap lens-diff-unreadable, carrying the git error verbatim in pipelineState.lensDiffError.

Situation Before After
origin/<branch> missing approved halt
git fails / maxBuffer overrun approved halt
commits ahead but empty diff approved halt
no branch name recorded approved halt
0 commits ahead of base approved approved (unchanged, now proven)

Two tests were passing for the wrong reason

test-work-driver-pr6.ts and test-work-driver-pr11-lens-diff.ts both claimed to cover the genuine no-work cycle. Neither created refs/remotes/origin/<branch> — so git diff origin/main..origin/<branch> failed with "unknown revision", and they were exercising a git failure the whole time. Both fixtures now create the ref and test what they say they test.

Testing

test-lens-diff-evidence.ts uses real git repositories, not a mocked exec. The bug lives in the gap between what git actually does and what the code assumed it does, and a fake that returns whatever the test wants cannot see that gap — which is precisely how the two fixtures above went years without noticing.

Covers: missing ref, genuine no-work branch, a real diff, commits-with-empty-diff, no branch name, not-a-git-repo. Plus an end-to-end assertion that an unreadable diff produces zero lens-approved events, spawns no lens children, and does not merge.

Restoring the old swallow-and-return-"" behaviour makes six of those assertions fail.

Quality gate

bun run build ✅ · bunx tsc --noEmit ✅ · bun run check ✅ · 78/78 offline smoke tests ✅

Raised by an operator asking whether the six-prong code review had been
getting skipped. Measured across every `.pi/work-state/*.json` in this
repo: it had NOT. Every cycle that reached `lens-review` ran
`lens-review×6`, and no cycle recorded a `lens-skipped-empty-diff` event.
Cycles where the review appears absent (#277, #279, #305, #308) aborted
or handed off before reaching the step.

The question exposed a real hazard anyway, and it is the same class as
#380's `ci-status:` substring: a gate whose "no signal" answer is
approval.

`runLens` treats an empty diff as approved — correct for a cycle that
genuinely changed nothing. But the diff came from `fetchIntegratedDiff`,
which swallowed EVERY git error and returned `""`. So a stale
`origin/<branch>` ref, a transient git failure, a `maxBuffer` overrun on
a large diff, or an unset branch name all produced the same value as
"there is nothing to review" — and that value meant approve, then merge.
Under always-worktree (#287) the fallback read is also empty, so there
was no second opinion.

This had already bitten twice from the other direction (pre-PR11 the
guard fired on every successful cycle; #287 re-introduced it when
worktrees went detached). Both were fixed by changing WHICH diff is read.
The structural problem — unreadable being indistinguishable from empty,
and both approving — was never fixed.

`readIntegratedDiff` now returns a discriminated result. Empty is
established POSITIVELY: `git rev-list --count origin/<base>..origin/<branch>`
must return 0. Anything else — the ref missing, git failing, or commits
existing while the diff comes back empty — halts with the new cap
`lens-diff-unreadable`, carrying the git error verbatim in
`pipelineState.lensDiffError`.

Two pre-existing fixtures were passing for the wrong reason.
`test-work-driver-pr6.ts` and `test-work-driver-pr11-lens-diff.ts` both
claimed to cover the genuine no-work cycle, and neither created
`refs/remotes/origin/<branch>` — so `git diff origin/main..origin/<branch>`
failed with "unknown revision" and they were exercising a git FAILURE the
whole time. Both now create the ref and test what they say they test.

Tests: `test-lens-diff-evidence.ts` uses REAL git repositories rather
than a mocked exec, because the bug lives in the gap between what git
actually does and what the code assumed — a fake that returns whatever
the test wants cannot see that gap. Covers the missing ref, the genuine
no-work branch, a real diff, commits-with-empty-diff, no branch name, and
not-a-git-repo; plus an end-to-end assertion that an unreadable diff
produces ZERO `lens-approved` events, spawns no lens children, and does
not merge. Restoring the old swallow-and-return-"" behaviour makes six of
those fail.

Closes #384
@randomm
randomm merged commit 3a30a70 into main Aug 7, 2026
1 check passed
@randomm
randomm deleted the fix/issue-384-lens-diff branch August 7, 2026 07:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(work-driver): an unreadable diff makes six-pass review self-approve instead of halting

1 participant