Skip to content

docs(specs): guardian skeptic — per-finding judgement + impact scoring (#246) - #268

Merged
zaebee merged 2 commits into
mainfrom
docs/spec-246-skeptic-scoring
Jul 29, 2026
Merged

docs(specs): guardian skeptic — per-finding judgement + impact scoring (#246)#268
zaebee merged 2 commits into
mainfrom
docs/spec-246-skeptic-scoring

Conversation

@zaebee

@zaebee zaebee commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Refs #246. Design only — no implementation.

Why now

The recall-lean finder (#249) delegates precision to the skeptic. The skeptic is not delivering, and the live run on #263 today shows why in one picture: 8 findings, all confirmed, all at one severity. One was a real defect (Path.is_file() raises on EACCES/ENAMETOOLONG — accepted and fixed). Two were factually wrong (for size: int in range(...) is not valid Python; as_posix() would have broken the Windows-path case the line exists for). Nothing in the output separated them.

Two causes, only one of which is the model:

  1. Mechanism — one call carries the whole findings list, verdicts mapped back by finding_index. Everything competes for one attention window, and index mapping has its own failure modes.
  2. ContractLiteral["confirmed","refuted","uncertain"] expresses "this is false" but not "this is true and worthless", and cannot be sorted or thresholded.

Swapping the skeptic model under an unchanged mechanism buys the same flat output at higher cost. So #246 becomes mechanism-first; the model matrix runs on top as phase 2.

What the design proposes

  • Two axes. verdict (truth, unchanged semantics — refuted drops) + impact_score: int 0-10 (importance — below threshold hides, never drops, and stays in the JSONL so the benchmark can still see it).
  • One call per finding, carrying only that finding's own hunks from diff_index, bounded concurrency (default 3, mistral's per-minute cap). finding_index disappears along with its failure modes.
  • Partial degradation. skeptic_status gains partial with judged/total; one failed call costs one verdict instead of the whole pass.
  • A previously-reverted lever becomes usable. Few-shot false-positive examples swung mistral into refute-all when there was one axis, because refutation was the only way to express "bad finding". On the importance axis they cannot reach the refutation logic. The truth-axis prompt is reused verbatim — it was bought by reverting a refute-by-default version that killed 7/7 findings including 2 GT matches.
  • "If ruff/mypy would catch it, impact ≤ 2" — Gemini-review advice placed on the axis where it is safe. In the finder prompt the same instruction re-introduces the precision bias that caused recall 0/5.
  • Benchmark by A/B over frozen finder output. Both arms judge the same recorded findings, same model, batch vs per-finding — so movement is attributable to the mechanism. Runs at threshold 0 and records every score, so the recall/noise-vs-threshold curve is computed offline from one run instead of one paid run per candidate value.
  • Falsifiable gate: noise down and zero lost GT versus the batch arm, plus median(score | GT) − median(score | non-GT) ≥ 3 pooled across PRs. A flat distribution fails even if noise happens to drop — that is exactly the fix(context): resolve source_root against stored paths, first match wins (#228) #263 pathology.

Amends 2026-06-10-guardian-sprint-design.md §5.2 ("one call, not N"), which predates the recall-lean finder: with a ≤5-finding gated finder one call was sufficient; with 10–26 it is the bottleneck.

Phase 2 (paid model matrix) does not start without an explicit budget go — the prior gemini run hit the 30 PLN cap.

🤖 Generated with Claude Code

…246)

Design for the skeptic pass: two orthogonal axes (verdict = is it true,
impact_score 0-10 = does it matter), one LLM call per finding with its own
hunks instead of one batch call over the whole list, partial degradation, and
an A/B benchmark over frozen finder output that attributes any movement to the
mechanism rather than the model.

Evidence base: the PR #263 live run (8 findings, all confirmed at one severity,
one real defect indistinguishable from two factually wrong claims) plus the
measured history of same-family skeptics being binary and few-shot FP examples
swinging mistral into refute-all.

Amends 2026-06-10-guardian-sprint-design.md §5.2 ("one call, not N"), which
predates the recall-lean finder.

Refs #246

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

11 TDD tasks: contract fields + sanitizer, FindingJudgement and pure merge,
split_diff_by_file moved to the diff leaf, per-finding prompt with the impact
rubric, bounded-concurrency judge_all, core and chunked wiring, ranking and
threshold in the report, bench per-finding score records with score_separation,
finder record/replay, then deletion of the batch API plus the §5.2 amendment.

The batch API stays alive until the last task so every intermediate task leaves
the suite green.

Refs #246

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@zaebee
zaebee merged commit b47bcbe into main Jul 29, 2026
3 checks passed
@zaebee
zaebee deleted the docs/spec-246-skeptic-scoring branch July 29, 2026 20:00
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.

1 participant