The anti-AI corpus check itself never failed. Run in isolation, anti_ai_voice_gate.py
returns GATE: PASS, score 0, zero severity-3 hits on all 22 episodes. What was printing
GATE: FAIL is the full hv_review_gate_v2.py battery, whose first gate (G1)
wraps the anti-AI corpus, so a failure anywhere in the battery reads at a glance like "the anti-AI
corpus failed." The failing gates were two downstream checks, and one of them was a bug.
The uniqueness gate scans the _outputs/ archive for a matching opener and excluded
"self" only by exact path. Each deployed review at public/<route>/index.md collided with its
own byte-identical twin at _outputs/<archive>/s5eNN.md, a phantom 100% overlap on every episode.
The gate needs a sibling index.claims.md (at least 8 verbatim CLAIM/EVIDENCE pairs tied to the
transcript). The sheets already existed in _outputs/, they were just never copied next to
the deployed HTML, so every review looked un-grounded.
1 · Root-cause the gate bug. opener_uniqueness() now also skips any archive candidate
whose full-text Jaccard vs the draft is at least 0.85, which marks it as the review's own archive copy
rather than a distinct episode. The separation is decisive: a self-copy scores 1.0, two different
episodes of the same show score ~0.27, and real openers overlap only 0.22 (well under the
0.55 fail line), so a genuinely recycled opener is still caught.
2 · Ship the evidence. Copied the existing s5eNN.claims.md into each route as index.claims.md
(all 22) and s5eNN.beats.tsv as index.beats.tsv (12 available).
Placing claims also switched on the COVERAGE gate, which passes.
| Episode | Opener overlap | Evidence verified | Words | Verdict |
|---|
$ python3 anti_ai_voice_gate.py check s5e21/index.md GATE: PASS score 0 severity-3 hits 0 # the "corpus" was always clean $ python3 hv_review_gate_v2.py s5e21/index.md # BEFORE x U1 opener not unique: 100% token-overlap with s5e21.md x F1 no claims sheet GATE: FAIL $ python3 hv_review_gate_v2.py s5e21/index.md # AFTER opener uniqueness: 22% overlap | fact grounding: 59 evidence lines verified GATE: PASS deploy → final state: READY curl / 200 curl /horror-vanguard-parks-s5e21 200 curl /horror-vanguard-parks-s5e21/index.md 200 curl /horror-vanguard-parks-s5e21/index.claims.md 200 22/22 hv_review_gate_v2 → GATE: PASS
~/Projects/horror-vanguard-tp/hv_review_gate_v2.py · sheets:
public/horror-vanguard-parks-s5eNN/index.claims.md ·
live review: /horror-vanguard-parks-s5e21