Repository navigation
Description
The coverage gate decides whether to approve based on what a reviewer claims it inspected. There is currently no recorded evidence that could contradict a false claim.
Current shape
DecodeFindingsininternal/llm/contracts.godecodesinspected_filesandskipped_filesfrom reviewer structured output.buildReviewerCoverageininternal/pipeline/pipeline.gocopiesinspected_filesinto the coverage entry, filtered to reviewable paths but otherwise as given, and computes missing files from that claimed list.internal/reviewplan/reviewplan.godowngradesApprovetoCommentwhen any reviewer has a failure or incomplete coverage.
What tool evidence exists today (corrected)
An earlier version of this issue said ReviewerToolEvidence "already records per-file tool invocations" and that "the ground truth is already on disk; nothing new needs collecting". That is wrong.
llm.ReviewerToolEvidence (internal/llm/adapter.go) is {DiffStatus, DiffDiagnostic}: one status for the whole session, derived from counts of cr_diff start, complete and fail events, plus the first error text. Only the pi RPC adapter populates it (observeReviewerToolEvent and reviewerToolEvidence in internal/llmadapters/pi_rpc.go); the subprocess adapters never set it. The event parser keeps the tool name and the error result and discards the arguments, so no file path is retained even for cr_diff, and other tool calls are not recorded at all.
reviewerToolEvidenceForcesIncomplete therefore answers exactly the one question the data can answer, whether cr_diff succeeded at least once, and nothing more. There is nothing on disk to reconcile inspected_files against.
The detection gap is one-directional
- A weak-but-honest reviewer that declares skips gets its coverage marked incomplete and the approval withheld, even when the skipped files were irrelevant.
- A reviewer that claims full coverage it did not perform approves silently. No mechanism detects this direction.
For a review tool the second is the one that matters: it is the path where the tool says "approved" about files nobody read.
Proposal, as two steps in this order
- Record per-file tool events as reviewer evidence, starting with the pi RPC adapter, which already sees
tool_execution_startandtool_execution_endper call. Keep the file path argument forcr_diffandcr_read, and persist a bounded per-file list (diffed or read, succeeded or failed) inReviewerToolEvidencealongside the existingDiffStatus.llmlifecyclealready persists and reloadsReviewerToolEvidencein task metadata, so cached and resumed runs keep it. Subprocess adapters stay at "no evidence" until they have a comparable event stream. - Behind a flag, reconcile claimed
inspected_filesagainst the recorded per-file evidence inbuildReviewerCoverage: a file claimed inspected with no recorded read or diff counts as not inspected. Roll out measured rather than flipped, because a strict reconciliation turned on everywhere at once would convert currently-approving runs into comments wherever the evidence is incomplete (subprocess adapters, or tool calls the tracer does not see).
Step 2 without step 1 has nothing to compare against, which is why this is one issue with an explicit order rather than a reconciliation-only ask.
Activity
[-]Coverage gate trusts self-reported inspected_files instead of recorded tool evidence[/-][+]Coverage gate trusts self-reported inspected_files, and no per-file tool evidence exists yet to check it against[/+]zzwong commentedon Sep 12, 2026
Edited the body and retitled. The one-directional-detection observation stands. Two corrections:
ReviewerToolEvidencedoes not record per-file tool invocations. It is a singlecr_diffstatus plus an error string, populated only by the pi RPC adapter from event counts; file paths are not retained and the subprocess adapters emit nothing. The "ground truth is already on disk" claim was wrong, so the proposal is now two ordered steps: collect per-file tool events first, then a flagged reconciliation.Previous title: "Coverage gate trusts self-reported inspected_files instead of recorded tool evidence".