Code review die elke bug moet bewijzen — benchmark

Code review die elke bug moet bewijzen — benchmark

Vraag een AI om je PR te reviewen en je krijgt een nette checklist terug: injectie gecheckt, secrets gecheckt, auth gecheckt, ziet er goed uit. Het oogt zorgvuldig. Of er ook echt iets gevonden is, is een aparte vraag — en de checklist is precies wat een gemiste bug verbergt. Wij runnen een directory die Claude-skills benchmarkt voor de kost, en toen we onze eigen benchmark op een reviewskill loslieten die we al hadden goedgekeurd, liep hij zo langs een hardcoded secret die de ongestuurde baseline wél oppikte. De lijst had geen regel voor die plek, dus de reviewer keek er nooit naar.

Die misser is de reden dat review-discipline bestaat — en waarom dit al de tweede versie is. Gratis en MIT-licensed: github.com/Skillproofdev/review-discipline. Elke bevinding moet een concrete input noemen die de code raakt en een verkeerde uitkomst oplevert — anders gaat hij gedowngraded het rapport in als [suspicion], nooit als feit gepresenteerd. Op onze seeded-bug-benchmark vangt hij 18,5 van de 21 geplante bugs, met nul false positives en een aangetoond faalpad bij ~100% van de bevindingen.

Het gat: elke reviewskill is een checklist, en checklists geven tunnelvisie

Voordat we een regel schreven, hebben we 321 gecrawlde reviewskills doorgenomen plus het losstaande veld — inclusief Anthropics eigen code-review plugin. Drie mechanismen kwamen in geen enkele van hen voor als afdwingbare regels voor één agent. Alle drie herleiden ze naar hetzelfde falen dat we in onze eigen benchmark zagen gebeuren.

Een checklist vertelt de reviewer waar hij naar moet zoeken. Dat is meteen ook een lijst van waar hij langs kijkt. Staat een categorie er niet bij, dan overleeft de bug — en erger nog, de review komt alsnog groen terug, want elk vakje dat bestaat is afgevinkt. Een review faalt op twee manieren: onbewezen vermoedens als feit rapporteren (ruis) en stilletjes een echte bug overslaan omdat hij klein is of omdat een engere bug alle aandacht opeiste (gemiste dekking). Een checklist is structureel goed in allebei.

Anthropics plugin bestrijdt de ruis-helft met parallelle scorer-agents die op een confidence-getal stemmen. Dat is een écht mechanisme, maar het vraagt meerdere agents en pakt de dekkingshelft helemaal niet aan. Niemand levert het ding dat de vorm van de checklist omdraait: eerst alles uitkammen voordat je naar een categorielijst grijpt, elke bevinding daarna bewijzen of labelen, en alleen weglaten wat je écht kunt weerleggen — in één agent, in één installeerbaar bestand.

Acht regels, drie ervan handhaaft niemand anders

De skill is een set afdwingbare regels (volledige SKILL.md). De bekende onderdelen zijn er: P0–P3-ernst met echte definities in plaats van onderbuikgevoel, diff-scope-discipline (review de wijziging, niet de codebase), gemiste-testmeldingen gekoppeld aan het gewijzigde gedrag, en geen lofprijzende opvulzinnen. De onderdelen die niemand anders afdwingt:

  1. Geen aangetoond faalpad, geen bevinding. Elke bevinding moet een concrete input of state noemen die de gemarkeerde code raakt en een verkeerde uitkomst oplevert. Kun je die niet construeren? Dan gaat het als [suspicion] het rapport in, onder elke bewezen bevinding gerangschikt — nooit als feit. Een onbewezen claim die als bug wordt gepresenteerd is de enige verboden output van deze skill.
  2. Twee rondes, eerst de open jacht. Lees de wijziging als een aanvaller zonder categorielijst bij de hand en noteer elke afwijking — geen ondergrens voor ernst, ook iets dat maar licht vreemd aanvoelt wordt genoteerd. Pas daarna volgt de standaardchecklist (secrets, injectie, grenswaarden, rekenkunde, concurrency…) voor alles wat de open jacht miste. Elke concurrent is de checklist; hier komt hij bewust als tweede.
  3. Weerleg je eigen bevinding voordat je ze rapporteert. Eén eerlijke weerleggingspoging per bevinding — upstream guards, bedoeld gedrag, bestaande testdekking, bereikbaarheid — en het rapport vermeldt wat er gecontroleerd is. Weerlegging is de enige poort die een bevinding mag laten vallen; "ik heb de moeite niet genomen het te bewijzen" wordt een [suspicion], geen stille schrapping. Bevindingen die écht sneuvelen, sneuvelen stil.

De dragende regel is de volgorde: eerst breedte, dan diepgang. Verzamel elke afwijking zonder ondergrens voor ernst voordat je er ook maar één verifieert, zodat de deep-dive op één bug nooit de jacht op de rest kan afkappen. Dat klinkt vanzelfsprekend. Het is ook precies de regel die onze eerste versie niet had — en de reden dat die verloor.

De eerlijke benchmark (negatieve resultaten inbegrepen)

Seeded-bugs-protocol: echte codevoorbeelden (~200–400 regels elk, TypeScript / Python / JS) geplant met gedocumenteerde bugs van bekende ernst — logica, security, edge-case, concurrency — met ground truth vastgelegd vóór elke run. Echte, intacte code blijft in elk voorbeeld staan om false positives te meten. Zelfde prompts, zelfde model; de enige variabele is of de agent eerst de SKILL.md leest. Volledige methodologie: skillproof.dev/methodology.

4 voorbeelden, 21 geplante bugs, 12 bewust gezonde false-positive-vallen. De interessante kolom is niet base-versus-skill — het is v1 versus v2, want onze eigen benchmark dwong de rebuild af.

Metriek Base (geen skill) Skill v1 Skill v2
Geplante bugs gevangen (van 21) 17,0 (81%) 16,5 (79%) 18,5 (88%)
P0-vangst (misbruikbaar / dataverlies) 3/3 3/3 3/3
P1-vangst (fout gedrag, realistisch pad) 7/7 7/7 7/7
P2-vangst (edge-/rekenpaden) 6/7 4/7 7/7
Hardcoded-secret-probe gevangen gevangen gevangen
False-positive-rate 5,6% (1 FP) 0% 0%
Bevindingen met aangetoond faalpad ~63% ~100% ~100%
[suspicion]-downgrades (eerlijke hedges) 0 3 5
Lof-/opvulregels aanwezig geen geen

Kijk naar de middelste kolom en je ziet het falen dat deze skill zijn naam gaf. v1 scoorde 16,5 — onder de ongestuurde baseline's 17. Hij had de faalpad-discipline (dat bracht false positives naar nul en toonde ~100% van de bevindingen aan), maar hij was slechter in bugs vinden, omdat hij zich vastbeet in de enge P0's in één voorbeeld en nooit de stille afrondingsregels doorspit. Hij tunnelvisioneerde. Onze eigen publieke benchmark van een skill die we al hadden goedgekeurd, ving dit op: v1 miste twee echte P2's — een prorate /30-logicafout en een int(amount × 100)-afronding — die de baseline gewoon oppikte door lineair te lezen.

De oplossing was de breedte-voor-diepgang-regel. v2 verzamelt elke afwijking zonder ondergrens voor ernst voordat er ook maar één geverifieerd wordt. Resultaat: P2 ging van 4/7 naar een schone 7/7 (het herstelde zelfs een lege-CSV StopIteration die zowel base als v1 misten), totale recall klom naar 18,5 — voorbij base's 17 — en de discipline hield stand: nog steeds nul false positives, nog steeds ~100% aangetoonde paden, en meer eerlijke [suspicion]-hedges (5 tegen 3) in plaats van minder. De volledige 3-wegs-adjudicatie staat in bench/results/verdict.md.

Eén mythe die de benchmark ook ontkrachtte, ronduit: de checklist-tunnelvisie-op-secrets-hypothese die het hele project motiveerde reproduceerde niet in de seeded run — alle drie de armen vingen de hardcoded-secret-probe (S4-B1). De oorspronkelijke misser was echt en leerde ons de vorm van het probleem — de seeded benchmark laat alleen zien dat de secret zelf niet is waar breedte loont. De afrondingsedge-cases zijn dat wel. We rapporteren het mechanisme dat de cijfers echt bewoog, niet het mechanisme met het betere ontstaansverhaal.

Waar v2 verloor — toch gepubliceerd

Onze methodologie eist dat de verliezen naast de winsten staan. v2 is de beste arm op alles wat een merge blokkeert, maar het is geen strikte superset van v1, en dat verdoezelen we niet.

Op jacht naar exhaustieve breedte stopte v2 met diepgraven in één functie (_parse_tags) en liep langs een subtiel literal_eval-diepnestingsvermoeden (S2-B5) dat v1's diepgaande pass als enige had gevangen. Op de P3-/buiten-checklist-as regresseerde v2 dus echt — van v1's 2,5/4 naar 1,5/4. Netto is het een goede ruil (+2 medium voor −1 subtiele P3), maar het is een echte regressie op die ene as, geen schone dominantie. De ideale reviewer is v2's breedte plus v1's bereidheid om nog één niveau dieper te graven in code die er stil uitziet — en dat vertellen we liever dan het af te ronden.

Er is ook een bug die geen enkele arm ving: een coupon-vervaldatum-strikt-<-gelijkstand (S1-B6), gemist door base, v1 én v2. De skill vermindert missers; het maakt Claude niet onfeilbaar.

SKILLPROOF SKILL

review-discipline is gratis, MIT, en het geheel is één bestand. Lees de acht regels, de seeded-bug-harness en het volledige 3-wegs-verdict — en run het dan op je eigen diffs.

Haal review-discipline op GitHub

Installatie

git clone https://github.com/Skillproofdev/review-discipline ~/.claude/skills/review-discipline

Herstart Claude Code. Eén commando — de repo is de skill. Hij triggert op "review deze PR/diff", "check dit voor de merge", "vind bugs in", en pre-merge checks — en blijft weg bij feature-schrijfwerk, style-only linting en proza-review. Hij hoort bij onze discipline-reeks: token-discipline verlaagt wat een agent kost, research-discipline verlaagt wat hij feitelijk fout heeft, en deze verlaagt wat een review mist.

GRATIS STARTERPACK

Wil je onze best scorende skills plus de installchecklist die we voor elke test draaien? We mailen je de gratis starterpack.

Haal de gratis starterpack

FAQ

Hoe verschilt dit van Anthropics code-review plugin? De plugin filtert false positives door parallelle scorer-agents op een confidence-getal te laten stemmen — effectief, maar het vraagt meerdere agents en pakt alleen het ruisprobleem aan. review-discipline filtert met een aangetoond faalpad in één enkele agent, in één installeerbaar bestand, en pakt ook het dekkingsprobleem aan dat de plugin niet raakt: de open-jacht-vóór-checklist-regel die onze eigen P2-recall van 4/7 naar 7/7 tilde.

Zorgt "bewijs elke bevinding" er niet voor dat hij dingen mist die hij niet kan aantonen? Nee — daar is het [suspicion]-mechanisme voor. Een echte bug waarvoor je geen faalpad kunt bouwen (heeft runtime-state nodig die je niet ziet, of een extern systeem) wordt alsnog gerapporteerd, gemarkeerd als [suspicion] en onder de bevestigde bevindingen gerangschikt, met één regel over wat er ontbreekt. Confidence downgraden is het middel; weglaten niet. In de benchmark gaf v2 5 van zulke eerlijke hedges af in plaats van ze in te slikken.

Reviewt hij de hele codebase of alleen mijn diff? Alleen de wijziging. Bevindingen moeten veroorzaakt of geactiveerd zijn door deze diff; bestaande problemen gaan in een korte out-of-scope-notitie, niet op de gerangschikte lijst. De enige uitzondering is een bestaande P0 — een live secret of actieve kwetsbaarheid — die altijd prominent wordt gemeld. Die uitzondering bestaat precies vanwege de misser uit het ontstaansverhaal.

Is 18,5/21 goed genoeg om menselijke review over te slaan? Nee. Hij vangt elke P0 en P1 merge-blocker in onze benchmark en verslaat een ongestuurde baseline op totale recall met nul false positives — dat maakt hem een sterke eerste reviewer die nooit klakkeloos afvinkt en altijd noemt wat hij heeft aangevallen. Maar hij miste één geplante bug volledig en ruilde een subtiele P3 in voor breedte, beide hierboven gedocumenteerd. Gebruik hem zodat de voor de hand liggende en de stille rekenkundige bugs een mens niet meer bereiken; houd de mens voor het laatste diepteniveau.

★ 9.6/10 × 3

Het gratis starterspakket

De 3 skills met onze hoogste testscores plus de installatiechecklist — de setup die wij op een verse machine zouden zetten. Gratis, per e-mail.

Eén e-mail met het pakket + een korte wekelijkse digest met nieuwe testresultaten. Uitschrijven kan altijd.