fix(review): failures are never clean: engine errors reported, per-file isolation, PII abstention, gate dismissal
RA
31m ago+438+438+012345678901234567890123456789-61-61-01234567890123456789
Issue for this PR
Closes #
Stacked on #1722 (← #1721 ← #1720 ← #1719); merge in that order.
Type of change
- Bug fix
- New feature
- Refactor / code improvement
- Documentation
What does this PR do?
A broken review could look like a clean one:
- Silent engine failures: every
ReviewRunnermethod caught its errors and returned empty. A failed native core read as "no findings" and could produce APPROVE. - One file aborts everything: the per-model precompute and the lane
Promise.allhad no error handling, so one file throwing rejected the whole review. - PII "no columns" ambiguity: an empty PII result looked the same whether the model was clean or core couldn't parse it.
- Gate never clears: a blocking review stayed blocking after a clean rerun.
Fixes:
- Engine errors: the dispatcher runner records each throwing call as method, first reason and count (13 call sites), and still returns its empty result. These are signed into the envelope as
engineErrors, named in the comment, and counted inreview_run.engine_errors. An empty review with engine errors is COMMENT, never APPROVE. - Per-file isolation: a failure preparing one file, or a lane throwing for one file, marks that file unverified with the reason; the rest is reviewed. The PR-level lanes (sibling consistency, topology equivalence) and the core-ran check are guarded too. A test caught the core-ran check aborting the review after a lane failure.
- PII abstention:
detectPiireturnsabstainedwhen core couldn't analyse the SQL (check didn't run, orpii.parse_error). The model is listed as not fully verified. - Gate lifecycle: when a rerun's event is non-blocking, earlier altimate
CHANGES_REQUESTEDreviews are dismissed with a pointer to the new verdict.postGitHubReviewtakes an optional client, so dedup, dismissal and skip are tested without the network.
Not in this PR: wiring the break-glass override (applyOverride) behind maintainer authorization. That needs a decision on who may override and where the audit record lives.
How did you verify your code works?
- New
test/altimate/review-failures-gate.test.ts(9 tests):- engine failure → COMMENT with a note;
engineErrorssigned and tamper-evident; an empty clean run still approves - unreadable content and a throwing lane each degrade only their file
- PII abstention reported
- with a fake GitHub client: a clean rerun dismisses only the bot's blocking review; a still-blocking rerun doesn't dismiss; already-posted findings aren't re-posted and no repeat review is created
- engine failure → COMMENT with a note;
- 1,892 tests across the review files and release gates pass.
bun typecheckis clean.
Cost side effects
None. At most one dismissReview call per stale blocking review on a non-blocking rerun.
Screenshots / recordings
N/A (CLI).
Checklist
- I have tested my changes locally
- I have not included unrelated changes in this PR
- I checked for cost side effects (model calls, queries or cloud resources that grow with user data) and described them, or wrote "none"
🤖 Generated with Claude Code
Summary by cubic
Fixes the review so engine failures, per-file crashes, and PII parse errors can no longer read as a clean pass, and a stale blocking review is dismissed on a clean rerun.
Bug Fixes
- Dispatcher runner records each throwing engine call (method, first reason, count) instead of silently returning empty; the errors are signed into the envelope as
engineErrors, shown in the comment, and counted in telemetry, and an empty review with engine errors is COMMENT, never APPROVE. - A failure preparing one file, or a lane throwing for one file, marks that file unverified; the rest of the PR is still reviewed, and PR-level lanes are guarded the same way.
detectPiireportsabstainedwhen core couldn't analyse the SQL (check didn't run or its PII parser errored), listing the model as not fully verified instead of PII-clean.- A non-blocking rerun dismisses earlier blocking altimate reviews with a pointer to the new verdict (
pull-requests: writerequired); the GitHub client is injectable so dedup, dismissal, and skip rules are tested without the network.