Methodology

We make our scanner grade itself — on a holdout it has never seen

Most tools that score your code have a quiet credibility problem: you can't check them. They hand you a number, you can't see the evidence, you can't reproduce it, and the tool never has to pass its own test. So we made ourselves do the uncomfortable thing — grade the scanner, in public, on data it had never seen, and commit to publishing the result before we knew what it would be.

← Back to cejel.dev · Repository Evidence Review

Preregister, then don't touch the holdout

Before running anything, we froze the scoring rubric and wrote down the pass/fail gates — precision floors, recall envelopes, false-positive ceilings, minimum evidence counts — and committed that document first, so we couldn't move the goalposts after seeing results.

Then a deterministic, seeded procedure selected a 200-repository holdout and froze it. The rule we held to: the holdout is selected once, never expanded, never adjusted after outcomes are visible, and no result is used to tune the rubric being measured. Every repository from every prior experiment was excluded, so nothing the detector had already seen could leak in. The scan is static and offline by construction — it reads tracked files at a frozen revision, never executes the repository's code, removes remotes before scoring, and treats “insufficient evidence” as a recorded outcome rather than a reason to guess.

How we label evidence

The results below are Measured. The preregistration, the frozen gate table and the terminal decision are Verifiable — they are published in the repository. Calibration frames are single-use: their membership is bound by a SHA-256 commitment when the frame freezes and stays closed while the evaluation is live. When a frame retires, its pinned members are published in a retirement reveal and the frame is never reused. The v17 frame is retired, and its sanctioned membership reveal records all 200 pinned revisions. The canonicalization and digest rules are published in the hash conventions. Adjudication labels and reviewer records remain closed; revealing membership does not make the accuracy figures independently reproducible.

The result

Rubric v17 passed every preregistered gate on the untouched holdout: finding precision 96.43% (95% lower bound 94.16%), rubric-agreement recall 95.64% (95% lower bound 92.23%), and a worst-case false-positive rate of 0.66% (95% upper bound 1.10%). This is not detection recall — three different things on this site are called recall, compared side by side.

The defect-class census publishes the coverage-breadth boundary: which defect classes any shipped rule targets. It is not a recall claim.

And — this matters as much as the numbers — we published the boundary right next to them. This is finding-level calibration of one rule set on one preregistered population. It is not a universal security guarantee, not proof your code is safe, not a claim about every framework. We also disclosed the un-flattering statistic: the intervals are not adjusted for the number of rubric revisions tried during development, and we say so in the record rather than hoping nobody asks.

Why “publish either way” is the whole point

A scanner that can't fail its own test isn't measuring anything. Our harness can return NO-GO, and when a gate isn't met, that's the published result — not a quiet retry until the number looks good. If you build developer tools, we'd gently push this: don't just show a score. Show the evidence, show the boundary, and show what happened when you pointed the tool at itself. It's more work and it's less flattering, and it's the only version of trust that survives contact with a skeptical engineer.

The same method applies to other people's instruments. On 20 September 2026 we preregistered five predictions about a commercial judge model's ability to tell false agent completion reports from true ones, ran it against known outcomes, and published the result with three of the five contradicted: the Jev 1.13 judge calibration.

The other thing called recall: what rubric v22 actually detected

The holdout result above is rubric agreement. It answers “when Cejel scores a finding, does a human reviewer agree?” — not “what share of the real defects in a repository does Cejel find?” That second question is detection recall, it is a much harder measurement, and we now have one for the prospective rubric v22.

v22 in-scope detection recall: 34.0% (95% CI 21.0-53.5%), measured across seven rules on a 200-repository untouched cohort under a preregistered protocol; measurement valid, no decidability ceiling tripped (aggregate control insufficient-context 7.94% against a 20% ceiling).

False-positive rate 0.77% (95% CI 0-2.1%).

Instrument. Measured on an engine built from source at commit e434a40e, between releases 0.4.5 and 0.4.6; no published package reproduces this instrument. The measurement predates cejel #276, #277 and the 0.4.8 abstention-scoring change, so a re-measurement on the current release is owed and this figure does not describe it.

Scope. v22 is prospective and explicit-only: it is not what a default scan runs, and it is not what produced any certificate or any row on the published board. v17 is the calibrated default. This is a measurement publication and not a promotion — the signed cycle-12 promotion decision is NO-GO and v22 stays unreleased. No equivalent detection-recall figure exists for v17, and none should be inferred from this one.

Three different things on this site are called recall

They come from different instruments, different populations and different rubric versions. None of them is a restatement of another, and none can be substituted for another in either direction.

Quantity
Rubric-agreement recall — 95.64% (95% lower bound 92.23%)
Rubric version
v17
Status
Calibrated default — the rubric an ordinary scan runs.
Population
A frozen, preregistered, untouched 200-repository open-source holdout, scored finding by finding.
Not this
Not detection recall. It does not say what share of a repository’s real defects Cejel finds.
Record
free-core v50 calibration record
Quantity
Detection recall, fixture-scoped — v17 cited 16/30 (95% Wilson [36.1%, 69.8%]); v22 cited 24/30 ([62.7%, 90.5%])
Rubric version
v17 and v22, measured as a pair
Status
v17 calibrated default; v22 prospective and explicit-only.
Population
A frozen, preregistered, in-scope held-out fixture set of 30 named defects.
Not this
Not a cohort-scale figure. Thirty fixtures is a small instrument, which is why both intervals are wide.
Record
bounded in-scope recall, in the cejel README
Quantity
v22 in-scope detection recall — 34.0% (95% CI 21.0-53.5%), paired always with a false-positive rate of 0.77% (95% CI 0-2.1%)
Rubric version
v22
Status
Prospective and explicit-only. Not the default; promotion is NO-GO.
Population
Seven rules on a 200-repository untouched cohort, under a preregistered protocol.
Not this
Not rubric agreement, and not a v17 figure. No equivalent measurement exists for v17.
Record
v22 detection-recall record

There is no v22-comparable detection-recall figure for the calibrated default. The v22 in-scope figure was measured on v22 only; v17’s sole published detection-recall numbers are the fixture-scoped 16/30 above, on a much smaller instrument. Nothing here supports inferring a cohort-scale detection-recall figure for v17, and none should be read into it.

Records: the v22 detection-recall record · the preregistered estimation protocol · the estimation result

See the record

The gates, the corpus deltas, and the published GO/NO-GO are all in the open. Run it yourself in one line: npx @cejel/cejel@latest .

See the published board →