fix(#384): the six-pass review no longer approves on absent evidence - #385
Merged
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #384.
Where this came from
An operator asked whether the six-prong code review had been getting skipped in recent
/workruns. Measured answer: it had not. Across every.pi/work-state/*.jsonin this repo, every cycle that reachedlens-reviewranlens-review×6, and no cycle recorded alens-skipped-empty-diffevent:lens-review×6 (round 1)round 3+developer:lens-fix-Ncommit-prCycles where the review looks absent aborted earlier. But the question exposed a real hazard, and this PR fixes it.
The hazard
runLenstreats an empty diff as approved — correct for a cycle that genuinely changed nothing. The diff came fromfetchIntegratedDiff(work-driver-diff.ts:131-149), which swallowed every git error and returned"":So a stale
origin/<branch>ref, a transient git failure, amaxBufferoverrun 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 theci-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
readIntegratedDiffreturns 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 caplens-diff-unreadable, carrying the git error verbatim inpipelineState.lensDiffError.origin/<branch>missingmaxBufferoverrunTwo tests were passing for the wrong reason
test-work-driver-pr6.tsandtest-work-driver-pr11-lens-diff.tsboth claimed to cover the genuine no-work cycle. Neither createdrefs/remotes/origin/<branch>— sogit 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.tsuses 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-approvedevents, 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 ✅