BASELINES

The two baselines

The corpus carries a trivial operating point worth block-only F1 0.20503174229955326 and a length signal worth AUC 0.7692264380822134, both with no model. Every F1 and every AUC here sits against those two.

The trivial floor

Blocking every case scores block-only F1 0.20503174229955326 at 11.42% prevalence: tp 436, fp 3,381, fn 0, tn 0, precision 0.1142258318, recall 1.0, block FPR 1.0. Allowing every case scores 0.0.

A false-positive rate of 1.0 fails any deployment gate, so this is not a claim that trivial blocking competes with a model. It is a claim about what an F1 below the floor tells you: the operating point is broken, and the figure says nothing about whether the model can discriminate.

2 of the 3 scored arms clear the floor. control-modernbert-base has the highest shipped F1 at 0.2496318114874816, and it is a negative control with no safety training.

Block-only F1 at each arm's shipped operating point, against the trivial floor

Blocking every case scores 0.20503174229955326 at 11.42% prevalence. Its false-positive rate is 1.0, so it fails any deployment gate. An F1 at or below the line says the operating point is broken, and says nothing about discrimination.

Cohort candidateMLM negative controlTrivial baseline, no model
0 0.1 0.2 0.3 0.4 block everything 0.20503 control-modernbert-base 0.2496 deberta-v3-prompt-injection-v2 0.2106 control-modernbert-large 0.1893 block every case 0.2050
Table view (every plotted value)
ArmBlock-only F1tpfpfntnBlock FPR
control-modernbert-base0.2496318114873391,941971,4400.574091
deberta-v3-prompt-injection-v20.2105781057814283,20181800.946761
control-modernbert-large0.1893274853802592,0411771,3400.603668
block every case0.2050317423004363,381001.000000
Argmax F1 in this frame is a calibration diagnostic. Every value plotted here is read at build time from cohort-scoring/cohort-scores.json, final-comparisons.json. The table view lists them all.

Argmax F1 is a calibration diagnostic here. An in-sample best F1 found by sweeping thresholds on the same rows it is scored on is an oracle upper bound, and is labelled as one wherever it appears.

The length cue

Five scalars read off the request, containing no model, reach AUC 0.7692264380822134 (prompt tokens, max over events), 0.7772553177633239 (event count), 0.7445374041120237 (context_events) and 0.7266059794480217 (context_bytes). Destructive multi-step trajectories in this corpus are longer than benign ones, so this is a property of the data-generating process and not a labelling artifact.

AUC of five counting variables that contain no model

Each row is a scalar read off the request: how long the prompt is, how many events the context carries, how many bytes. Destructive multi-step trajectories in this corpus are longer than benign ones, which is a property of the data-generating process.

0 0.2 0.4 0.5 0.6 0.8 1 chance 0.5 event count 0.7773 prompt tokens, max 0.7692 prompt tokens, sum 0.7666 context events 0.7445 context bytes, max 0.7266
Table view (every plotted value)
Counting variableAUCOracle thresholdOracle best F1
event_count_in_prediction0.7772553178170.3870192308
natural_prompt_tokens (max over events)0.76922643811,0850.3851976451
natural_prompt_tokens (sum over events)0.76659740488,4540.3431372549
context_events0.744537404170.3404940924
context_bytes (max over events)0.72660597942,8750.3459320948
The oracle best-F1 column is an in-sample upper bound. Every value plotted here is read at build time from cohort-scoring/leakage-diagnostic.json. The table view lists them all.

Every arm's headline AUC therefore contains a length component. Each arm carries a length-controlled AUC beside its raw AUC: the corpus is stratified into five prompt-length quintiles, the AUC is computed inside each, and the five are averaged unweighted.

The pure length counter falls from 0.7692264380822134 to 0.5398672584287441 under that stratification.

AUC inside each prompt-length quintile

Stratifying on prompt length removes the length component from every arm's score. The length counter falls to 0.5398672584 under its own control, and both MLM controls land inside the chance band.

0.0 0.2 0.4 0.6 0.8 1.0 Q1 71–89 Q2 90–236 Q3 237–673 Q4 674–1077 Q5 1078–3379 deberta-v3-prompt-injection-v2 modernbert-base modernbert-large prompt tokens, no model AUC within the quintile
Table view (every plotted value)
QuintileCasesPositivesdeberta-v3-prompt-injection-v2prompt tokens, no modelmodernbert-basemodernbert-large
Q167220.92723880600.54216417910.75410447760.6992537313
Q2852240.64590881640.75042773750.34981380840.6719001610
Q3765800.86285583940.46198905110.43007299270.4368978102
Q47641000.82865210840.56880271080.56350150600.2742319277
Q57642300.85503582480.37595261360.49171144760.3804307116
Quintile 1 carries 2 positives, so its AUC rests on two cases and is the noisiest column in the chart. Every value plotted here is read at build time from cohort-scoring/final-comparisons.json, leakage-diagnostic.json. The table view lists them all.

The chance band

For 436 positives and 3,381 negatives the Hanley–McNeil standard error at AUC 0.5 is 0.014691343359335349, so the 95% chance interval is [0.471205496131191, 0.528794503868809]. It is shaded on every AUC chart here.

Both MLM controls land inside or below that band under length control: control-modernbert-base at 0.5178408464714641 and control-modernbert-large at 0.49254286838283756. Raw figures are 0.6622467295653802 and 0.46228994190416495; the decomposition is on Results.

Computed by scoring/final.py and scoring/leakage.py over cases_sha256 39f2c1df2369952a0525cc4c5575f4bdb590fb3ca8c1bc6805cf4f376c1adbf7.