# MEME-outcome gate v2 — final (guaranteed-monotone, exportable, validated on ALL /data MEME jobs)

Retrained on the user-visible label (MEME reports >=1 site at p<=0.1). Validated on a held-out
production sample AND the FULL /data corpus (8981 MEME jobs). Fixes both root causes of the
calibration write-up + both veg/datamonkey3#151 items.

## Model
**XGBoost XGBClassifier, monotone_constraints=(1,1,1)** — GUARANTEED non-decreasing in all three
features by construction (verified 0 violations on a thorough multi-background sweep). Features
[num_seqs, num_sites, median_pos_dist]; frac_p_defined dropped (#151b); median_pos_dist floored 0.001 / capped 10.
 - Held-out test AUC 0.891 | full-corpus AUC 0.870 (vs shipped model's production 0.745).
- Ships as meme_gate.json (XGBoost native format, booster.save_model). No converter, no ONNX.
   FloatTensorType([None,3]), output 'probabilities' [N,1] = P(MEME reports a site at p<=0.1).

## DELIVERABLE 4 — bands (FULL /data corpus, 8981 jobs, base rate 0.85)

| Band | Cut | OBSERVED hit rate | Fires on |
|---|---|---|---|
| **Unlikely** | <0.30 | **0.209** | 4.1% |
| **Uncertain** | 0.30-0.70 | **0.553** | 12.7% |
| **Likely** | >=0.70 | **0.927** | 83.2% |

**Three bands supportable** — 20/55/92 cleanly separated, middle is ~coin-flip. HONEST COPY REQUIRED:
"Unlikely" at 20% means "often finds little (~1 in 5)", NOT "won't report".
No cut at this 85% base rate makes "unlikely" mean ~0% (that fires on <0.5% of jobs). If the
product needs that claim, drop the band — the data won't support it.

## Full calibration table (/data corpus)
| score < t | % data | hit BELOW | hit ABOVE |
|---|---|---|---|
| 0.05 | 0.9% | 0.051 | 0.857 |
| 0.1 | 1.4% | 0.057 | 0.861 |
| 0.2 | 2.8% | 0.166 | 0.87 |
| 0.3 | 4.1% | 0.209 | 0.878 |
| 0.35 | 4.6% | 0.242 | 0.88 |
| 0.4 | 5.6% | 0.253 | 0.886 |
| 0.5 | 8.2% | 0.325 | 0.897 |
| 0.6 | 12.1% | 0.385 | 0.915 |
| 0.7 | 16.8% | 0.469 | 0.927 |
| 0.8 | 25.0% | 0.546 | 0.952 |
| 0.9 | 37.8% | 0.651 | 0.971 |

## Deliverables
- train_gate_final.py  — AUTHORITATIVE trainer (reproduces the shipped model)
- validate_full.py / finalize_full.py  — full /data validation
- calibration_full_universe.json / calibration_report.json  — observed hit-rates per threshold
