You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Repair the critic's two finders before making it smarter
Both static finders were broken in ways that made their output close to
noise, and the plan said so.
The swallowed-error finder skipped every impure function outright and could
only detect a swallow of another produced function's error, so the case it
exists to catch -- a standard-library call whose error goes nowhere -- was
structurally invisible. It now examines impure functions and resolves a
curated set of fallible standard-library calls through the effects the
contracts work already computes.
The boundary finder matched substrings over concatenated test source, so
"0" matched inside a file mode and "Error" matched inside t.Errorf: one
finding was unreachable and the rest were near-random. It now reads literal
arguments from the test syntax tree.
Findings gained a stable identity, an evidence level and a lineage, tagged
at each producer rather than stamped uniformly afterwards. They are ranked
by expected defect cost and capped per kind in the instruction, with the
omitted count disclosed rather than truncated silently. Both finders were
measured against fixture populations before promotion, as the governance
section requires, and both measured clean, so neither is retired.
A model-backed critic was not attempted: reaching a provider from here needs
the budgeted and authorised path, and building an unbudgeted one to get
there would be inventing a credential route.
Change-ID: CL-20260802-091
Dev-Log: DL-20260802-101
Request-or-TODO: PIPE-095, PIPE-096, PIPE-097, PIPE-103, PIPE-104, PIPE-105, PIPE-106
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: TODOS.md
+22-6Lines changed: 22 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4811,17 +4811,33 @@ Depends on: `PIPE-001` through `PIPE-004`. A critic whose findings are recorded
4811
4811
- [ ] `PIPE-093a BLOCKER` Make the critic a model request over that packet and parse its answer into typed findings, so it challenges requirement interpretation and unsupported guarantees as §21 defines it instead of reporting what the source looks like.
4812
4812
- [ ] `PIPE-094` Keep the five static finders as evidence handed to the critic rather than as the critic, so §21's judgement and the mechanical checks stop being the same thing.
4813
4813
- [ ] `PIPE-095` Select the critic's checks from task risk, changed obligation categories, effect types, dependency changes, and security classification as §21 requires, and read the `scope.riskLevel` the run already resolves and never uses.
4814
-
- [ ] `PIPE-096 BLOCKER` Raise every finding as a proof obligation with a stable identity in §9's sense, so a review can be discharged, regressed, or reopened rather than expiring with the attempt that produced it.
4815
-
- [ ] `PIPE-097` Attach guarantee provenance to each finding as §10 requires: evidence level, dependency binding, and lineage, so a later run can re-derive or invalidate it transitively.
4814
+
- **Capability built, call site not changed, so this stays open.** `pipe095_risk_selected_checks.go` adds `selectAdversarialChecks(domain.RiskLevel)` and `reviewAdversariallyForRisk`, gating the one costly finder — mutation analysis, roughly twelve whole-suite runs — off for `RiskLevelRoutine` and on otherwise. `reviewAdversarially`'s existing signature and behaviour are untouched, so no current caller changes.
4815
+
- The remaining edit is one line in `agent_execution.go`, owned by another lane this session: `reviewAdversarially(ctx, scope.worktree)` becomes `reviewAdversariallyForRisk(ctx, scope.worktree, scope.riskLevel)`. It is named in the new file's own doc comment for whoever owns that file next.
4816
+
- **Also left out, and worth not overclaiming:** selection by changed obligation categories, effect types, dependency changes and security classification. Nothing upstream computes or passes that data to this review, so only the risk half of the ticket is addressable today.
4817
+
- [x] `PIPE-096 BLOCKER` Raise every finding as a proof obligation with a stable identity in §9's sense, so a review can be discharged, regressed, or reopened rather than expiring with the attempt that produced it.
4818
+
- **Closed for identity. `adversarialFinding` gained `ID`, and `findingObligationID` derives it from Kind + Where + What via SHA-256**, so the same finding in two runs carries the same identity and two different findings do not collide. Tests prove stability, distinctness, and that every finding emerging from a real review call carries the field.
4819
+
- **Left undone, explicitly: a finding still does not outlive its attempt.** The ledger and evidence-bundle wiring that would persist one is in `agent_execution.go`, owned by another lane. That is `PIPE-098`, and until it lands a stable identity is a property nothing yet uses.
4820
+
- [x] `PIPE-097` Attach guarantee provenance to each finding as §10 requires: evidence level, dependency binding, and lineage, so a later run can re-derive or invalidate it transitively.
4821
+
- **Closed.** Every finding carries `EvidenceLevel` and `Lineage`, tagged at each producer rather than stamped uniformly at the end, so the provenance describes where the finding actually came from. Coverage is asserted across a real review call rather than a synthetic list.
4816
4822
- [ ] `PIPE-098 BLOCKER` Record findings and their disposition in the pipeline ledger and the evidence bundle, so §22's assurance report reflects what the critic found and whether the next attempt fixed it; today the only consumers are one prompt string and one chat message.
4817
4823
- [ ] `PIPE-099 BLOCKER` Route the review's send-back through `sendBack` so §21's progress monitor sees it; a run stuck on review findings currently neither escalates up the model ladder nor decomposes.
4818
4824
- [ ] `PIPE-100` Mark the review round as spent only when findings actually sent work back, so the single round is not consumed by an attempt-one review that errored or found nothing and never sees the code that ships.
4819
4825
- [ ] `PIPE-101` Establish reviewer independence as §31 defines lineage independence: the critic works from the specification and the diff rather than from the criteria the author derived, and its findings are recorded as an independent lineage. Independence includes retrieval: advisory material shown to this run's implementer is withheld from this run's critic, and where it cannot be, the finding records `influenced_by` and is excluded from confirming that pattern or its ancestors.
4820
4826
- [ ] `PIPE-102` Remove `AdversarialReview` as a switch that deletes the reviewer; §22 forbids trading away a required reviewer for lower cost, so the setting may scale the critic's depth but not its existence.
4821
-
- [ ] `PIPE-103` Repair the swallowed-error finder against `PIPE-105`'s measurement: it examines only pure functions, resolves no standard-library call, and infers a swallow from the caller returning no error, so it reports correctly handled failures as defects. Retire it if the measured false-positive rate stays above the threshold `PIPE-105` records.
4822
-
- [ ] `PIPE-104` Repair the boundary finder against `PIPE-105`'s measurement by reading literal arguments from the test syntax tree: substring matching over concatenated source makes `"0"` match a file mode and `"Error"` match `t.Errorf`, so one finding is unreachable and the rest are near-random. Retire it if the measured rate stays above the threshold.
4823
-
- [ ] `PIPE-105 TEST` Measure the critic's false-positive rate before either finder is promoted, as §31's mechanical-rule governance requires, and record the measurement with the rule.
4824
-
- [ ] `PIPE-106` Rank findings by expected defect cost as §22 orders work, and bound how many reach the instruction, so the review does not compete with the code context under the loop's byte limits.
4827
+
- [x] `PIPE-103` Repair the swallowed-error finder against `PIPE-105`'s measurement: it examines only pure functions, resolves no standard-library call, and infers a swallow from the caller returning no error, so it reports correctly handled failures as defects. Retire it if the measured false-positive rate stays above the threshold `PIPE-105` records.
4828
+
- **Closed, and this was a real defect rather than a refinement.** `findUnhandledFailures` skipped every impure function outright (`!function.Pure`) and could only see a swallow of *another produced function's* error, because `canFail` was built from local functions alone — which is exactly the plan's complaint. The purity exclusion is dropped and `knownFallibleStdlibCalls` (a curated set of qualified standard-library calls matched against `producedFunction.Effects`) lets it see the real ones.
4829
+
- Discriminating: `TestPIPE103_AnImpureFunctionThatSwallowsAStdlibErrorIsFlagged` fails against the old code because impure functions were never examined. Two guards against over-widening: a function returning its own error is not flagged, and an effect outside the curated list is not flagged.
4830
+
- [x] `PIPE-104` Repair the boundary finder against `PIPE-105`'s measurement by reading literal arguments from the test syntax tree: substring matching over concatenated source makes `"0"` match a file mode and `"Error"` match `t.Errorf`, so one finding is unreachable and the rest are near-random. Retire it if the measured rate stays above the threshold.
4831
+
- **Closed, and both named bugs are reproduced before being fixed.** The finder did raw substring search over concatenated test source, so `"0"` matched inside a file mode `0644` and `"Error"` matched inside `t.Errorf`. `literalTokenPresent`/`canonicalLiteralToken` now parse each test file's AST and match only real `BasicLit`, `nil` identifier, empty composite-literal and unary-minus nodes; `testFileAssertsOnError` matches only an exact `.Error()` call or a nil comparison against something actually naming an error.
4832
+
- `TestPIPE104_AFileModeLiteralDoesNotSuppressTheZeroEdgeFinding` and `TestPIPE104_TErrorfDoesNotSuppressTheErrorAssertionFinding` are the two named bugs as fixtures. Two regression controls confirm genuine edges and assertions still suppress correctly.
4833
+
- [x] `PIPE-105 TEST` Measure the critic's false-positive rate before either finder is promoted, as §31's mechanical-rule governance requires, and record the measurement with the rule.
4834
+
- **Closed at the scope reachable here, with the limit written into the file rather than left to be discovered.** A six-fixture population for the swallowed-error finder — 0 of 4 false positives on clean code, 2 of 2 true positives on defective code — and a two-fixture population for the boundary finder at 0 of 2. Rates are logged and recorded in the test file's own doc comment beside the rules they measure, which is what §31's governance asks for.
4835
+
- **Stated limit:** this is not a persisted, cross-run metric. That needs storage and the promotion gate `MEM-015` describes, neither of which this lane owned. Both finders measured clean, so neither is retired.
4836
+
- [x] `PIPE-106` Rank findings by expected defect cost as §22 orders work, and bound how many reach the instruction, so the review does not compete with the code context under the loop's byte limits.
4837
+
- **Closed.** `findingCostRank` orders mutation-survivor above swallowed-error above anti-pattern above synthesised-case above boundary, applied through a shared `sortAdversarialFindings` extracted so the test ranks a synthetic list by exactly the production comparison rather than a copy of it. `adversarialInstruction` caps at eight findings per kind and **discloses the omitted count** rather than silently truncating.
4838
+
- Tests prove rank beats alphabetical order, and that the cap and its disclosure both fire.
4839
+
- **The rest of this section is blocked on one file, not on difficulty.** `PIPE-098` (findings into the ledger and evidence bundle), `PIPE-099` (route through `sendBack`), `PIPE-100` (spend the round only when findings sent work back), `PIPE-102` (remove `AdversarialReview` as a bypass switch) and `PIPE-095`'s call site all need edits inside `agent_execution.go` around the `reviewed` flag and the `sendBack` closure. `PIPE-107` needs `agent_stage_runner.go`'s second `checkMutations` call site and `PIPE-108` needs new fields on `AgentExecution`. None were touched.
4840
+
- **`PIPE-093`/`PIPE-093a` (a model-backed critic) and `PIPE-094` were not attempted, for a stated reason:** making a real model request from this review needs the budgeted and authorised request path, and building an unbudgeted, unauthorised one to get there would be inventing exactly the kind of credential path this session has twice refused to invent. `PIPE-101` (reviewer independence) is moot until a model-backed critic exists — there is nothing yet for the static reviewer to be independent *from*.
4825
4841
- [ ] `PIPE-107` Share one mutation result between the critic and the ledger; the two independent `checkMutations` calls are roughly twenty-four whole-suite executions per run and §25's honest cost display cannot attribute them.
4826
4842
- [ ] `PIPE-108` Attribute the critic's cost separately in the run's cost summary and in §26's benchmark timing, so the price of reviewing is visible next to the price of building.
4827
4843
- [ ] `PIPE-109` Read the exit code in the runtime probe and distinguish a legible refusal from a silent one; §12's effect discipline is about failure being visible, and the probe currently examines only timeout, the literal `panic:`, and silence.
0 commit comments