diff --git a/persistent-memory.d/2026-09-11-babyyarros-leak-gate-passes.md b/persistent-memory.d/2026-09-11-babyyarros-leak-gate-passes.md new file mode 100644 index 0000000..b3181d3 --- /dev/null +++ b/persistent-memory.d/2026-09-11-babyyarros-leak-gate-passes.md @@ -0,0 +1,140 @@ +# `[2026-09-11]` BabyYarros — the leak gate passes, and closing it found three defects nobody was looking for + +Operator's goal for the session: *"finish the hardening and start the yarros training on +the gx10."* Both done. The gate went 212 → 0 and the first BabyYarros training is live. + +## The gate did not exist, which is why the number was wrong + +There was no committed instrument for *does any of the author's own proper nouns survive +the rename*. Brontë's "0 of 203" was produced by hand, and BabyYarros's "86 of 232" was +too. `scripts/r49-corpus/leak_gate.py` is now that instrument. + +It runs **both directions every time**, because a detector that only ever sees renamed +text cannot distinguish *absent* from *blind*: + +- **positive control** — the same scan over the UNRENAMED source; every surface must be found +- **negative control** — a nonce string that must appear nowhere + +Its first reading on the corpus as built was **212 surviving, not 86**. Two reasons, and +both are structural rather than a disagreement about counting: it scans the **whole corpus** +rather than each work separately, and it counts the **sub-threshold** entities `rename.py` +never looked at. A per-work gate reports a name renamed in one book and printed verbatim in +another as clean. + +## Defect 1 — a second typography defect, and the D1 note was right about the wrong thing + +The D1 build notes say no unwrap was needed because Kvasir's cleaner emits flowing +paragraphs. That is true and Brontë's hard-wrap defect genuinely is absent. A different one +is present: + + — M AJOR A FENDRA’S G UIDE TO THE R IDERS Q UADRANT (U NAUTHORIZED E DITION ) + T he flight field at Basgiath is still dark… + +The Empyrean books set chapter epigraphs in **small caps**; the extractor rendered the +small-caps run as uppercase and left the large initial as its own token. **106 lines, ~700 +splits**, plus **52 drop caps** (51 of them iron-flame). That is the entire origin of the +entities called `IDERS`, `UADRANT`, `NAUTHORIZED`, `DITION`, and seventeen bare single letters. + +⭐ **The restoration is exact, not approximate.** A split initial beside an uppercased run +recovers the original mixed case: a word WITH a split initial was capitalised in the source, +an all-caps word WITHOUT one was lowercase. So the line above restores to +*"—Major Afendra's Guide to the Riders Quadrant (Unauthorized Edition)"*, which is what she wrote. + +⚠ Two guards, both load-bearing: only lines with **≥2** splits are treated as a small-caps +run (one split is an ordinary sentence beside an acronym), and **`I`, `A`, `O` are excluded** +from the drop-cap join — otherwise `A slow smile spreads` becomes `Aslow`. + +`scripts/yarros-corpus/repair_typography.py`. Cost: 768 fragments rejoined. + +## Defect 2 — back matter inside the prose, in all five works + +The builder splits on chapter headings and nothing follows the last one, so every work +carried its acknowledgments, newsletter pitches and cover-artist credits **inside the final +chapter**: 4,555 words naming the author's agent, her editors and her children, in a corpus +whose entire purpose is that no identifiable name survives. + +Found by the phrase audit surfacing **`Louise Fury`** (Yarros's literary agent) — not by +reading. ⚠ iron-flame's marker is `ACKNOWLEDGMENTS` in **all caps** and a case-sensitive +scan missed it. The strip is case-insensitive, last-chapter-only, and refuses if it would +remove more than 2% of the corpus. + +## Defect 3 — the gate read 0 of 314 while `Afendra` was in every copy + +The worst failure shape available: a clean number over a real leak. + +`Afendra` never appears unpossessed, so it keyed as `Afendra’s` — and **`rename.py` and the +gate both skip apostrophe keys as contractions.** Unrenamed and unreported at once. Fixed by +folding clitics so `Afendra’s` counts toward `Afendra` (`--fold-clitics`). + +`Baxter` escaped a different way and is the better story. `wilder` renders an in-book news +article **entirely in lowercase** as a typographic device: + + eighteen-year-old eleanor baxter was found late last night… + …using a helicopter rescue team to bring ms. baxter from the ravine. + +So 3 lowercase against 23 capitalised — **ratio 0.13 against a 0.05 bar** — and a real +character is silently never renamed. The cap/lowercase ratio assumes consistent typography. +Fixed by readmitting ratio-rejects that a title precedes (`--rescue-honorific 2`). + +⚠ **The first version of that rescue was badly wrong and the measurement caught it.** +Matching the wide honorific list case-insensitively readmitted **143 junk tokens** — `the`, +`says`, `like`, `up`, `across` — because `major`, `general`, `father`, `sir`, `agent` and +`coach` are ordinary lowercase words. The rescue list is now five abbreviations that are +never anything else (`Mr/Mrs/Ms/Dr/Miss`) and the lowercase arm additionally requires the +period, so `ms. baxter` counts and `I miss you` does not. Readmits: 143 → 2. + +## A leak class the unigram scan structurally cannot see + +`Riders Quadrant`, `Scribe Quadrant`, `Flame Section`, `War Games`, `Orange Daggertail` — +and **`Fourth Wing`, the book's own title**. Every component is an ordinary word the +cap/lowercase detector *correctly* refuses to call a name, so **48 recurring capitalised +phrases survived a gate that read 0.** + +This is `Thornfield × 100` one level up, and it needs a **map, not a detector**: substituting +a head noun is a choice about register, not a measurement. `phrase_map_yarros.json` carries +10 phrases plus 13 capitalised tokens (Quadrant→Division, Wing→Flight, Section→Cohort, +Squad→Unit, Daggertail→Spinecrest), applied AFTER the entity pass so it can never eat a +replacement name, whole-word and case-sensitive so a dragon's lowercase `wing` survives. The +gate now audits recurring 2–3grams against an explicit allow list. 48 → 0. + +## Corpus scope, not work scope + +`--scope corpus` uses ONE map per copy across every work. It closes the cross-work leak +(`Rebel` renamed in `rebel`, verbatim in the other two Renegades books) and fixes something +Brontë's four unrelated novels never raised: **Yarros is two series**, so Violet has to be +the same person in Fourth Wing and Iron Flame. 8 cross-work gender conflicts held neutral +rather than guessed. + +## The stoplist is short because every surface was read in context + +A plausible-looking guess would have been wrong most of the time. **`Violence` is Xaden's +nickname for Violet.** `Continent`, `Presentation`, `Battle Brief`, `Curator`, `Sage`, +`Barrens`, `Originals`, `Montserrat`, `Athena` and `Aura` are all in-world. Only real-world +geography, brands, three nationality adjectives and four generic title words are excluded — +**ambiguous cases are deliberately renamed, because renaming is the safe direction and +leaving is the leaking one.** + +## Brontë was protected the boring way + +Five new detector behaviours, all **opt-in and OFF by default**, and after every single +change the Brontë entity map was re-derived on gx10 and diffed against the pre-change one: +identical keys, identical surfaces, identical every field, across all four works. One +intermediate version DID change Shirley (an unconditional acronym rule dropped `charles`, +`george`, `hugo`, `nelson`) and that is exactly why the check was run each time rather than once. + +## Final state + + 0 of 325 source entities survive · 0 of 91 audited phrases survive · both controls PASS + corpus sha e85f69f1e49d57c9 · 6 copies · 1,248 records · 4.65M words + +⚠ **Sensitivity floor, stated because a negative without one is unfalsifiable:** 3 +capitalised occurrences per work for a name, 5 recurrences for a phrase. Below those the +gate does not detect, does not rename, and does not report. + +Training launched 10:06 PT — `gx10:~/r49-runs/yarros-4b-instruct-1ep/`, Qwen3-4B-Instruct, +1 epoch, seed 4919, **178 steps · 5,824,512 tokens**, 252 adapted modules, sdpa/bf16, +37.9 s/it (~1h52m), eval+save every 25. The launcher **refuses to start unless the gate +report on disk says PASSED** — a launcher that trusts a human to have remembered is not a guard. + +Pipeline and evidence table: `scripts/yarros-corpus/RUNBOOK.md`. +Related: [[2026-09-10-r49-babybronte-d1-d3-and-the-1-epoch-pilot]] diff --git a/persistent-memory.md b/persistent-memory.md index 7fc6226..fd69e96 100644 --- a/persistent-memory.md +++ b/persistent-memory.md @@ -1,6 +1,6 @@ # Persistent memory — eshpfi-management -_Last updated: 2026-09-11 09:00 PT (BabyYarros D1 built + D2 gender fixed, D3 BLOCKED on the leak gate and nothing trained; R49 carrier sweep COMPLETE 3.329/3.018/2.814 and the instruct probe shows voice + instruction-following coexist; mog-sec settled at a measured 160k ceiling, 17h zero restarts)_ +_Last updated: 2026-09-11 10:10 PT (BabyYarros UNBLOCKED — leak gate PASSES 0/325 entities + 0/91 phrases, and closing it found three corpus defects nobody was looking for; Qwen3-4B-Instruct training LIVE on pfi-gx10, 178 steps; R49 carrier sweep COMPLETE 3.329/3.018/2.814; mog-sec settled at a measured 160k ceiling)_ > **Always check for `/tmp/infra-ops-handoff.md`** — if it exists and its > `Written:` stamp is under an hour old, read it (it carries the in-flight @@ -112,25 +112,27 @@ no longer deployed sidecars here. See Recent decisions.) ## Current state / in-flight _As of 2026-09-11 09:00 PT._ -### BabyYarros — the live project, and it is BLOCKED +### BabyYarros — UNBLOCKED, gate passes, TRAINING LIVE -- **Source located and D1 BUILT.** 5 Rebecca Yarros works in the Kvasir licensed library - (`~/development/kvasir/data/library/catalog.sqlite`, `rights=gated`): Fourth Wing, Iron Flame, - Wilder, Nova, Rebel. Corpus at `nh3-dev:~/yarros-corpus` — **208 chapters · 780,744 words**, 15% - larger than Brontë. Builder `scripts/yarros-corpus/build_corpus_yarros.py` emits the SAME record - schema as the Brontë one so `entities.py` / `rename.py` / `train_voice_lora.py` all run unchanged. -- ⚠ **No unwrap step needed** — Kvasir's cleaner already emits flowing paragraphs (median line 102 - chars). The Brontë hard-wrap defect does not exist in this corpus. -- **D2 gender resolution FIXED and validated** — `scripts/yarros-corpus/pov_gender.py`, 9 correct / - 9 held / **0 wrong** against the prior 7/8/**3-wrong**. See Recent decisions for the pathology. -- ⛔ **D3 rename BLOCKED on the leak gate: 86 of 232 renameable source entities survive.** Brontë's - run reached 0 of 203. Three classes: detector false positives (`Hopefully`, `Whoa`, `Hey`, `Hmm` — - need a stopword filter, not a rename), genuine misses among worldbuilding nouns (`Krovlan`, - `Poromish`, `Fuil`, `Iorson` — the `Thornfield × 100` case), and a third class (`Elizabeth`, - `Penelope`, `Messina` appearing as both pool draws and surviving source entities) not yet diagnosed. -- **NOTHING HAS BEEN TRAINED on Yarros.** Training before the gate passes means fitting in-copyright - text with 86 identifiable source entities intact, in a corpus F02 flagged as small enough for - memorisation leak to be real. **Operator's call, surfaced and awaiting a decision.** +- **Training launched 2026-09-11 10:06 PT** — `gx10:~/r49-runs/yarros-4b-instruct-1ep/`, + Qwen3-4B-**Instruct**, 1 epoch, seed 4919, **178 steps · 5,824,512 tokens**, 252 adapted + modules, sdpa/bf16, eval+save every 25. ~1h50m at the 4B rung's ~37.8 s/it. Launcher + `scripts/yarros-corpus/launch-yarros-4b-instruct.sh` **refuses to start unless the gate + report on disk says PASSED** — a launcher that trusts a human to have remembered is not a guard. +- **⛔→✅ The leak gate PASSES: 0 of 325 source entities and 0 of 91 audited phrases survive** + in any of 30 copy files, both controls passing. Corpus sha `e85f69f1e49d57c9`. + ⚠ **Sensitivity floor is part of the result:** 3 capitalised occurrences for a name, 5 + recurrences for a phrase. Below that, nothing is detected, renamed, or reported. +- **The gate is now a committed instrument** (`scripts/r49-corpus/leak_gate.py`). There was + none before — Brontë's "0 of 203" was produced by hand. It runs the same scan over the + UNRENAMED source as a positive control and a nonce string as a negative one, every time. + Run against the corpus as built it reported **212** surviving, not the 86 recorded earlier, + because it scans the whole corpus rather than each work and counts the sub-threshold + entities rename never looked at. +- **Pipeline, flags and evidence: `scripts/yarros-corpus/RUNBOOK.md`.** Every new detector + flag is opt-in and OFF by default; the Brontë entity map was re-derived after each change + and confirmed identical in keys, surfaces and every field. +- **Nothing was trained on the pre-gate corpus.** The run above is the first BabyYarros training. ### R49 / BabyBronte — carrier sweep COMPLETE @@ -165,6 +167,14 @@ _As of 2026-09-11 09:00 PT._ ## Recent decisions +- `[2026-09-11]` ⭐⭐ **BabyYarros UNBLOCKED and TRAINING: the leak gate passes at 0 of 325 entities and 0 of 91 phrases, and closing it turned up three defects nobody was looking for.** The gate itself is the first artifact — there was no committed instrument for "does any of the author's proper nouns survive", so Brontë's 0-of-203 was a hand count. `scripts/r49-corpus/leak_gate.py` now runs the same scan over the UNRENAMED source as a **positive control** plus a nonce **negative control** every time, because a detector that only ever sees renamed text cannot tell *absent* from *blind*. Its first reading was **212 surviving, not 86** — it scans the whole corpus rather than per work, and counts the sub-threshold entities rename never looked at. Training launched 10:06 PT on pfi-gx10: Qwen3-4B-**Instruct**, 1 epoch, seed 4919, 178 steps / 5,824,512 tokens, corpus sha `e85f69f1e49d57c9`. → `persistent-memory.d/2026-09-11-babyyarros-leak-gate-passes.md` +- `[2026-09-11]` ⭐⭐ **A SECOND corpus typography defect, and the D1 note that "no unwrap was needed" was right about the wrong thing.** Kvasir's cleaner does emit flowing paragraphs, so Brontë's hard-wrap defect genuinely does not exist here. A *different* one does: the Empyrean books set chapter epigraphs in small caps and the extractor rendered the run as uppercase while leaving the large initial its own token — `— M AJOR A FENDRA'S G UIDE TO THE R IDERS Q UADRANT (U NAUTHORIZED E DITION)`, **106 lines / ~700 splits**, plus **52 drop caps** (`T he flight field`, `X aden.`, 51 of 52 in iron-flame). That is the entire source of the entities called `IDERS`, `UADRANT`, `NAUTHORIZED`, `DITION` and seventeen bare single letters. ⭐ **The restore is exact, not approximate**: a split initial next to an uppercased run recovers the original mixed case, because a word WITH a split initial was capitalised in the source and an all-caps word WITHOUT one was lowercase. ⚠ Guards that matter: only lines with **≥2** splits are treated as a run (one split is a sentence next to an acronym), and `I`/`A`/`O` are excluded from the drop-cap join or `A slow smile` becomes `Aslow`. `scripts/yarros-corpus/repair_typography.py`. +- `[2026-09-11]` ⚠⚠ **Back matter was inside the prose of all five works — 4,555 words naming the author's agent, editors and children.** The builder splits on chapter headings and nothing follows the last one, so acknowledgments, newsletter pitches and cover-artist credits rode inside the final chapter. Found by the gate's phrase audit surfacing `Louise Fury` (Yarros's literary agent), not by reading. ⚠ **iron-flame's marker is `ACKNOWLEDGMENTS` in all caps** and a case-sensitive scan missed it — the strip is case-insensitive and last-chapter-only, with an acceptance check that refuses if it would remove more than 2% of the corpus. +- `[2026-09-11]` ⭐⭐⭐ **The gate read 0 of 314 while `Afendra` was still in every copy — the worst failure shape available.** The name never appears unpossessed, so it keyed as `Afendra's`, and **rename.py and the gate both skip apostrophe keys as contractions**: unrenamed AND unreported at once. Fixed by folding clitics (`--fold-clitics`) so `Afendra's` counts as `Afendra`. `Baxter` escaped a different way and is the better story: **wilder renders an in-book news article entirely in lowercase**, so `eleanor baxter` / `ms. baxter` appear uncapitalised 3 times against 23 capitalised — ratio **0.13 against a 0.05 bar**, and a real character is silently never renamed. Fixed by readmitting ratio-rejects that a title precedes (`--rescue-honorific 2`). ⚠ **The first version of that rescue matched honorifics case-INSENSITIVELY and readmitted 143 junk tokens** (`the`, `says`, `like`, `up`) because `major`, `general`, `father`, `sir` and `agent` are ordinary lowercase words; the rescue list is now five abbreviations and the lowercase arm requires the period. +- `[2026-09-11]` ⭐⭐ **A whole leak class the unigram scan structurally CANNOT see: `Riders Quadrant`, `Flame Section`, `War Games` — and `Fourth Wing`, the book's own title.** Every component is an ordinary word the cap/lowercase detector correctly refuses to call a name, so 48 recurring capitalised phrases survived a gate reading 0. This is `Thornfield × 100` one level up, and it needs a **map**, not a detector — substituting a head noun is a choice about register, not a measurement. `scripts/yarros-corpus/phrase_map_yarros.json` (10 phrases + 13 capitalised tokens: Quadrant→Division, Wing→Flight, Section→Cohort, Squad→Unit, Daggertail→Spinecrest) applies AFTER the entity pass; the gate audits recurring 2-3grams against an explicit allow list. Result: 48 → 0. +- `[2026-09-11]` **Per-work rename maps leak across works, and for a SERIES they are also wrong.** `Rebel` was renamed in `rebel` and printed verbatim in the two other Renegades books; a per-work gate reports that clean. `--scope corpus` uses ONE map per copy across every work, which also means Violet is the same person in Fourth Wing and Iron Flame — a thing Brontë's four unrelated novels never had to care about. 8 cross-work gender conflicts held to neutral rather than guessed. +- `[2026-09-11]` ⭐ **The mid-sentence test: position as a SECOND filter, which is not the v1 mistake.** entities.py's own history says position-based detection MISSES names that start sentences. As a second filter on top of the ratio it has no such problem, because a real name also appears mid-sentence. Measured: **33 verified names at 0.567–0.985 mid-sentence, 19 verified interjections at 0.000–0.222** — a 2.5x gap, so 0.35 is not a tuned parameter. It fixes `Hey`/`Holy`/`Hopefully`/`Yep`/`Whoa`/`Nope`/`Ugh` being entities. ⚠ It also drops real surnames only ever used as address (`Delgado` 18/64, `Schur` 0/10), so a rescue on honorific-or-possessive runs behind it; all 19 verified interjections score zero on both signals. +- `[2026-09-11]` ⚠ **The stoplist is short because every surface was read IN CONTEXT first, and a plausible guess would have been wrong most of the time.** `Violence` is Xaden's nickname for Violet. `Continent`, `Presentation`, `Battle Brief`, `Curator`, `Sage`, `Barrens`, `Originals`, `Montserrat`, `Athena` and `Aura` are all in-world. Only real-world geography, brands, three nationality adjectives and four generic title words are excluded — **ambiguous cases are deliberately renamed, because renaming is the safe direction and leaving is the leaking one.** `scripts/yarros-corpus/stoplist_yarros.json`. - `[2026-09-11]` **BabyYarros D1 BUILT, D2 gender FIXED, D3 rename BLOCKED on the leak gate.** Operator: *"train the instruct on the yarros corpus -- babyyarros."* Source located: **5 works in the Kvasir licensed library** (`data/library/catalog.sqlite`, `rights=gated`) — Fourth Wing, Iron Flame, Wilder, Nova, Rebel. **D1 built: 208 chapters · 780,744 words** (15% larger than Brontë's 680,291) at `nh3-dev:~/yarros-corpus`. ⚠ **No unwrap needed** — Kvasir's cleaner already emits flowing paragraphs (median line 102 chars), so the Brontë hard-wrap defect does not exist here. **Alphabet RE-DERIVED rather than inherited**: 23 non-ASCII letters across é/à/ï in 780k words. F02 measured 4 (all é) on a 455,800-word sample; same conclusion (ASCII-fold) from a different number, which is why it is re-derived per corpus. - `[2026-09-11]` ⭐⭐ **NEW PATHOLOGY, worse than Brontë's: in a ROTATING first-person POV corpus, every book's narrator gets the WRONG gender.** Measured against 6 names verified in the text: the pronoun resolver called **Violet 'm'** (Fourth Wing's narrator), **Leah 'm'** (Wilder's), **Landon 'f'** (Rebel's) — 3 of 18 wrong, and all three are narrators. Mechanism is Brontë's "Jane called male" amplified: a narrator is *I* in her own book, so her name appears mostly inside the other lead's dialogue among HIS pronouns. ⚠ **And title-first, the Brontë fix, is nearly blind here** — contemporary romance says "Violet", not "Miss Sorrengail": 3 gendered entities per work. **The fix that works for this corpus is the POV header**: chapters open `Chapter One / Leah / Port of Miami`, so resolve each name from the chapters it does NOT narrate. Validated **9 correct / 9 held / 0 WRONG** against 7/8/**3-wrong**; the instrument refuses to write unless it beats what it replaces. `scripts/yarros-corpus/pov_gender.py`. ⚠ Fourth Wing and Iron Flame are SINGLE-POV so they have no headers — Violet is now *held* (neutral token) there rather than wrongly gendered, which is the safe direction. - `[2026-09-11]` ⚠ **Three real bugs found in `rename.py` while re-pointing it, two of which would have silently corrupted BabyYarros:** (1) **gender came ONLY from honorifics** — the entities file's `gender` field was ignored entirely, so my POV fix had no effect until wired in; now `tg.get(key) or e.get("gender")`, titles first so Brontë is unchanged. Effect: 1 → 13 gendered on `wilder`. (2) the pool labels `pool['fr']`/`pool['en']` were hardcoded in a print, so any non-Brontë preset crashed; pools are now a `PRESETS` dict (`bronte` = fr/en excluding en_US for period register; `yarros` = en_US/en_CA + es/it/de/fr at 0.62 US). (3) the collision-filter log said *"dropped N pool names that are Bronte entities"* **regardless of corpus** — the logic was right but the message named the wrong one, which is how a future reader concludes the filter ran against the wrong corpus.