105 lines
5.8 KiB
Markdown
105 lines
5.8 KiB
Markdown
# `[2026-09-17]` The leak gate passed with five protagonist names still in every copy
|
||
|
||
Found during D4 pre-flight, three stages downstream of where it happened. Commit `c559664`.
|
||
|
||
```
|
||
leak gate, 2026-09-17 morning 0 of 75 renameable, 0 of 37 sub-threshold, both controls green
|
||
actually present, all 6 copies Bell x2 Chigurh x3 Moss x2 Toadvine x4 Glanton x2
|
||
```
|
||
|
||
## The mechanism
|
||
|
||
`leak_gate.py` scans `\b(Surface)\b`. **A character inserted inside a name defeats that
|
||
pattern outright**, so a mangled occurrence is not merely unrepaired — it is *unrenameable*
|
||
by `rename.py` and *unreportable* by the gate, and the gate prints a clean zero over it.
|
||
Two extraction artifacts produce exactly that:
|
||
|
||
```
|
||
B ell C higurh M oss T oadvine a small-caps drop cap kept as its own token
|
||
Toad-vine Glan-ton a print line-break hyphen kept by the extractor
|
||
```
|
||
|
||
⭐ **Every VISIBLE occurrence had been renamed correctly** — exact-match survivors were 0,
|
||
as the gate said. That is what makes this residue invisible to a spot-read: the names are
|
||
gone everywhere you look. `Bell` sits in the entity map at 147 capitals, `Glanton` at 365.
|
||
|
||
This is the third member of a family. lv-bronte's was `_Antigua_` (`_` is a word character,
|
||
so `\bAntigua\b` cannot match inside it), found by hand in 2026-09-16 and never generalised.
|
||
**The generalisation is the point: any separator inside a name blinds a word-boundary scan.**
|
||
|
||
## Fixed at three levels, and all three must stay
|
||
|
||
1. **`build_corpus_mccarthy.py` rules 4 and 5** repair the source text — 32 split initials
|
||
with a *lowercase* remainder (rule 1 requires a following ALL-CAPS word and DROPCAP
|
||
requires two, so this is the class both leave behind), 5 hyphen-split names by name.
|
||
Both carry expected counts so a master change fails the build.
|
||
⚠ **Rule 4's letter class is consonants only.** `I` opens **1,966** paragraphs (the
|
||
pronoun), `A` opens 143 (the article), `Y` opens 32 (Spanish *y*). Folding any of them
|
||
would corrupt 2,141 lines to fix 32 — the same `I`/`A` trap that bit `audit_stoplist.py`.
|
||
2. **`leak_gate.py` runs a separator-tolerant pass every time**, with its own positive and
|
||
negative controls, and **it fails the gate**. Validated against the pre-fix tree: reports
|
||
all five surfaces, exits 1.
|
||
3. The exact-match passes are untouched, so the old verdict is reproduced alongside the new.
|
||
|
||
⚠ **The fragment filter is what makes the new pass usable.** A naive separator-tolerant
|
||
scan is dominated by false positives — on Hemingway it returns 21 hits of which **18 are
|
||
ordinary text** (`God damn` for the surface `Goddamn` ×14, plus `I run`, `On an`, `Do me`,
|
||
`Si le`). The discriminator, with no dictionary: in a genuine split at least one FRAGMENT
|
||
is not a word of this corpus. `God` and `damn` occur constantly; `Primi`, `tivo`, `ell`,
|
||
`higurh`, `Toad` do not. That one test cleared all 18 and kept all 3 real ones.
|
||
|
||
⚠ **My first negative control could not pass.** It planted the split nonce in its own probe
|
||
text and then asserted the nonce was absent — an alarm wired to itself, failing on every
|
||
run. It now hunts the split nonce in the *real* copies. A control that cannot pass is not a
|
||
control.
|
||
|
||
## The shipped corpora, checked with the committed instrument
|
||
|
||
Re-derived with the COMMITTED gate, not a scratch probe:
|
||
|
||
```
|
||
lv-bronte GATE PASSED 0 separator-split survivors (9.7 s)
|
||
lv-hemingway GATE FAILED Pasionaria, Primitivo, Chicote (34.6 s)
|
||
1 occurrence each per copy, in all 6 copies — SHIPPED and LIVE
|
||
```
|
||
|
||
⚠ The first version of this scan was **too slow to run** on Hemingway — per-surface scanning
|
||
is O(surfaces x copies x corpus) and 881 surfaces x 10 copies was still going at 5 minutes
|
||
when it was killed. Rebuilt as one alternation pass, same trick `scan()` already used: 35 s,
|
||
identical verdict and identical hit counts on both McCarthy trees. **A gate too slow to run
|
||
is not a gate.**
|
||
|
||
**Operator call outstanding** on whether 3 names in a 958k-word corpus warrant re-gating and
|
||
retraining a live adapter. Not acted on.
|
||
|
||
## The chain was recovered, not remembered — and is now written down
|
||
|
||
There was **no McCarthy runbook**, and the D1→D3 session issued its commands over
|
||
non-interactive ssh so no shell history survived. The chain was recovered by rebuilding
|
||
candidates and matching sha256 against the artifacts on disk, then pinned:
|
||
|
||
```
|
||
D1 build_corpus_mccarthy.py 6 works byte-identical
|
||
D2 entities.py --min-count 5 --fold-clitics --drop-acronyms --min-mid-ratio 0.2 --min-mid 2
|
||
D2c apply_gender_overrides.py entities-final.json byte-identical
|
||
D3 rename.py --preset mccarthy --scope corpus --min-cap 5 --copies 6 --seed 4919
|
||
--holdout-chapter 7 17 all 36 copy files byte-identical
|
||
```
|
||
|
||
⚠ `--min-mid-ratio` is what keeps `Yeah`/`Buenas`/`Shh`/`Sí` out of the map. The map is
|
||
**insensitive** to it: any value in [0.05, 0.3] with `--min-mid` 1 or 2 reproduces byte-for-
|
||
byte; `--min-mid 3` does not. The original values are unrecoverable and it does not matter —
|
||
which is worth saying, because an exact-looking recipe that was never pinned invites a
|
||
false claim of reproduction. Full recipe and every deviation: `scripts/mccarthy-corpus/RUNBOOK.md`.
|
||
|
||
⚠ **D1 must run on nh3-dev** — the builder reads the kvasir catalogue by absolute path and
|
||
gx10 has no copy. The previous session's "on gx10" note is true of D2 onward only.
|
||
|
||
⚠ **No phrase map exists for this corpus**, so the gate's phrase audit does not run at all.
|
||
Yarros and Brontë both had one. Not closed.
|
||
|
||
Rollback: `~/lv-mccarthy/corpus-{clean,renamed}.pre-splitfix` on gx10.
|
||
|
||
Related: [[2026-09-17-mccarthy-d1-d3]], [[2026-09-17-beat-contamination-leak]],
|
||
[[2026-09-17-lv-hemingway-gate]], [[2026-09-17-lv-bronte-gate]].
|