memory: snapshot — lv-mccarthy training launched on gx10, and the next voice seat is measured rather than chosen

In-flight rewritten to the live training run (~150/1380, ETA ~00:45 PT) with the
--save-total-limit finding that would otherwise have deleted the epoch-1/epoch-2
checkpoints both prior gates were decided on.

Two decisions added: the next-seat ranking (Faulkner, Morrison, Chandler -- and the
finding that the corpus size ranking inverts the voice ranking, with King and Christie
as the two biggest non-candidates), and the romantasy register measured on the gate's
own char-bigram instrument (Yarros is the cluster outlier we already shipped; Maas is
the centroid and so the worst pick; Kenyon at 27 val units if the lane gets a seat).

Auto-archival: 4 entries moved to archival-memory.md; 4 held back by the open-deferred
guard.
This commit is contained in:
vh
2026-09-17 22:38:13 -07:00
parent 36f2e4dbbc
commit d94b5a1934
9 changed files with 380 additions and 174 deletions
@@ -1,46 +0,0 @@
- `[2026-09-03]` **pfi-gx10 racked and networked: VLAN 50 via a DHCP RESERVATION, not a host static; Wi-Fi down.**
`pfi-gx10.nh3.internal` → **10.100.50.60**, wired only.
**Operator ruling, and the better design:** put the address on the
**switch/firewall side** as a DHCP reservation and leave the host on DHCP. A
host-side static works until the box moves, and then it is a stale netplan file
on a machine whose address you no longer know. A reservation moves with the MAC.
UniFi switch port 22 native network -> nh3-servers (VLAN 50)
UniFi client reservation -> 30:c5:99:3d:a7:45 = 10.100.50.60
host unchanged, still DHCP
`playbooks/gx10-rack-network.yaml` was pre-written to apply a **host static** and
was NOT used — annotated as retired at its top. Its safety *ordering* was
followed and is still right.
⚠ **The port arrived on the native VLAN**, not the server VLAN — it DHCP'd
`10.100.0.111` from `nh3-default`. The switch port had to be repointed before
anything else could work. Do not assume a racked port is on the VLAN you asked
for.
⚠ **`port_overrides` is a WHOLE-ARRAY PUT.** Anything omitted is deleted. Two
unrelated overrides (ports 21, 23) were read, backed up to a file, preserved and
written back.
⚠ **The step that is easy to skip and expensive to miss:** while Wi-Fi was still
up, traffic from the box to nh3-dev **preferred `wlP9s9`** — that interface sits
directly on the userland subnet — so "I can reach it on the new address" proved
NOTHING about the wired path. Downing Wi-Fi on that evidence is a coin flip on
inter-VLAN routing, and losing it is a rack visit. Forcing the interface is what
settled it:
ping -c3 -I enP7s7 10.100.10.50 0% loss VLAN 50 -> VLAN 10
ping -c2 -I enP7s7 1.1.1.1 0% loss egress
Only then did Wi-Fi come down, as its own step, `/etc/netplan` backed up to
`/etc/netplan.bak-preWifiDown`. `nmcli radio wifi off` persists across reboot —
verified by reading `/var/lib/NetworkManager/NetworkManager.state` back.
⚠ **The box now has exactly ONE path.** If that switch port or the reservation
breaks it is a rack visit; the escape hatch is deliberately gone. Correct end
state for a racked server, but a posture change from the desk setup — and this
is the box run 3c moved to.
Runbook `docs/runbooks/gx10-rack-network.md`; commit `a95717e`.
@@ -1,51 +0,0 @@
- `[2026-09-03]` **Three Macs onboarded with infra-ops + NOPASSWD sudo + the DeepSeek Harness, and the fourth is a script instead of a fourth hand-run.**
vuongs-mac-mini 10.100.79.2 infra-ops + lkraven
esh-macbook-air 10.0.10.83 infra-ops + lkraven
esh-mac-studio 10.0.10.10 infra-ops + vhpfi
Each: key auth, `visudo`-validated NOPASSWD drop-in, password rotated to 32
random chars and vaulted at `<name>/infra-ops-password`. `dsh` runs in the
operator's own account on each, on a **device-scoped** LiteLLM key
(`<name>-dsh`, scoped to `gen-reasoning`, scope verified 200/403 rather than
trusted from the mint) — a laptop travels, and losing one should be one
revocation, not a fleet key rotation.
`scripts/provision-mac-dsh.sh <host> <account> [name]` carries every trap; the
operator-run half is `docs/runbooks/mac-provisioning.md`.
⚠ **`sudo -u <user>` KEEPS THE CALLER'S `$HOME`.** Without `-H` and an explicit
`HOME=`, `"$HOME/.local"` resolved to the caller's home and an `rm -rf` aimed at
a **working install in another account**. Only filesystem permissions stopped
it. The script now refuses to run unless `$HOME` matches the target.
⚠ **An account may not own its own home.** A `sudo mkdir` before `sysadminctl`
leaves `/Users/<account>` root-owned; the account authenticates, gets a shell,
reports the right `$HOME`, and cannot write to it — surfacing as a bare
"Permission denied" hours later.
⚠ **A wrong USERNAME looks exactly like a wrong password.** sshd answers
`Permission denied (publickey,password,keyboard-interactive)` for a bad user, a
bad password, AND a user outside `com.apple.access_ssh`. This produced a false
diagnosis twice in one session — once where the password was a typo
(`no-password` vs `nopassword`) and I blamed the access group, once where the
Studio's operator account is **`vhpfi`, not `lkraven`**. Check
`dscl . -list /Users` FIRST.
⚠ **Rotation: use `dscl . -passwd`, not `sysadminctl`.** With FileVault on and
no Secure Token on the account, `sysadminctl -resetPasswordFor` refuses with
"Operation is not permitted without secure token unlock". `dscl` works precisely
because there is no token to desync. True on all three Macs.
⚠ **FileVault kills remote access across reboots** — the machine sits at the
pre-boot unlock screen with no network. Nothing unattended should depend on a
Mac being reachable after a restart.
⚠ macOS has no `adduser`, `useradd`, or `timeout`.
Harness config (all machines): `high` → the seat's `xhigh` via the gateway hook;
`maxTokens 32768` (the 256000 default left 6144 for input and overflowed on a
two-word prompt); `defaultContextWindow 262144`; and `models:` **replacing** the
provider's hard-coded DeepSeek catalog, which the web GUI reads INDEPENDENTLY of
`agent-default-model` — without it the picker offers three models the gateway
does not serve while headless runs work fine. Commits `6ca455a`, `926fc2f`.
@@ -1,3 +0,0 @@
# `[2026-09-03]` nh3-dev wedged for ~40 min and it was the BACKUP, not the disk — a stalled cross-site vzdump holding every gue
**nh3-dev wedged for ~40 min and it was the BACKUP, not the disk — a stalled cross-site vzdump holding every guest write via `copy-before-write`.** Symptoms screamed dying disk: 45 writes in flight completing zero, jbd2 + flush kworkers in D state 33 min, io pressure full 96%, load 26, `virtio_ring` in the stack. ⚠ **The discriminator was the ABSENCE of errors** — no SCSI/ATA/IO errors, rpool ONLINE 21%, guest fs 79%, memory fine, and **Dirty only 3.8 MB** (so nothing backed up in page cache; it was stuck BELOW the block layer). ⚠ **The hypervisor was IDLE** — load 0.63, io pressure 0.00, zpool ~0 writes: nothing was reaching the disk because the filter held it. Cause: `vzdump` of VM 102 → **pbs-ana** did 1% at 64 MiB/s then collapsed to **1.4 MiB/s for 35 min**; Proxmox backups interpose a `copy-before-write` filter, so every guest write queues behind the backup's copy-out. FIX = cancel the task (`pvesh delete /nodes/localhost/tasks/<UPID>`); filter detached, inflight 45→0, D-states gone, 191 MB/s dsync restored. ⚠ **`fleecing 0` on the job is why a slow TARGET can stall a GUEST** — fleecing routes copy-before-write to a fast local image instead. Job = `backup-5d8f1221-8f71`, **daily 21:00, `all 1`, storage pbs-ana** → recurs nightly until changed. A prior run of this VM managed 941 MiB/s read, so 1.4 MiB/s is degradation, not normal. → `docs/runbooks/nh3-dev-io-stall.md`
@@ -1,67 +0,0 @@
- `[2026-09-03]` **SearXNG was returning ZERO results for every query while reporting `healthy` — moved to nh3-docker, updated, and exposed to every CC session as an MCP tool.**
**The failure.** The ana-docker instance answered `/healthz` every 30s, showed
`Up 7 days (healthy)` with 0 restarts, and had a green Homepage card — while
returning **0 results for every query tested**. It was running **2026.4.17
against a current 2026.9.3**: 4.5 months of engine scrapers rotting against
sites that had changed their markup. SearXNG ships near-daily releases for
exactly this reason.
⚠ **`:latest` means "latest AT PULL TIME".** Nothing re-pulls on its own. A
container created in April on `:latest` is pinned to April forever.
⚠ **`/healthz` proves the web app answers and says NOTHING about whether search
works.** That is the whole lesson. Same shape as the nh3-dev "failing disk" that
was a stalled backup, the runner audit that trusted liveness for identity, and
the statusline bell that measured a mechanism.
**Proven before acting**: the new image, same settings file, same host, same
query, in a throwaway container → **20 results where the running one returned
0**. Network was ruled out first — from inside the container DNS resolved and
mojeek/wikipedia were reachable, so engines were reachable and the parsers were
the broken part.
**Why NH3 and not an in-place update** (operator's call, and the measurement
backs it):
ana-docker egress 38.120.12.42 datacenter -> DuckDuckGo/Startpage CAPTCHA
nh3-docker egress 70.230.226.88 residential -> not gated the same way
Search engines gate datacenter ranges. Same reason the fleet keeps a residential
SOCKS5 proxy on nh3-dev for yt-dlp — applied at the source instead of proxied
around. `outgoing.proxies` has the fallback commented in place if NH3's egress
ever changes.
⚠ **Not a complete fix.** `brave`, `duckduckgo`, `startpage` still CAPTCHA from
NH3. `google cse` carries general search at ~20 results/query; `yandex`, `wiby`,
`github`, `stackoverflow`, `marginalia` work. **General search is effectively
single-engine** — if google cse breaks, it goes quiet again.
**Two config defects, both silent:** `base_url` still named
`searxng.pfi.local`, retired 2026-08-19, while the env said otherwise (env wins,
so nothing broke and the file lied to every reader); and the
`karmasearch.videos` removal key never matched because the engine's real name
has a space in it.
**`scripts/searxng-health.sh` asserts results > 0** across three unrelated
queries. That is the only check that could have caught this — the mechanism was
healthy throughout.
**The MCP tool** — `services/searxng-mcp`, `uv tool install`, registered
`claude mcp add --scope user searxng searxng-mcp`, so every CC session gets
`web_search`. ⚠ Zero results **raise** rather than returning an empty list: an
empty list is indistinguishable from a broken aggregator, which is precisely how
this hid. Same principle as althing's "unreachable post office is an OUTAGE,
never an empty inbox".
⚠ Written against **mcp 2.x** (`FastMCP` → `MCPServer`; the v1
`@app.list_tools()` decorator is gone and fails at import). ⚠ **`uv tool install
--force` served a CACHED build** and silently reinstalled the old code — the
installed file still had the v1 API after the source no longer did.
`--reinstall --no-cache` fixed it; `md5sum` of source vs installed is what
caught it.
Old instance stopped and removed; DNS alias repointed to
`searxng.nh3.internal` → 10.100.50.40. Secret vaulted at
`nh3-docker/searxng-secret`. Commit `0f748ea`. See [[2026-09-03-gx10-rack-network]]
for the other UniFi-side change the same day.
@@ -0,0 +1,69 @@
# `[2026-09-17]` Which voices earn a training seat next — measured against the catalogue, not chosen by taste
Method: rank every author in the kvasir catalogue by **usable extracted** works, then apply the
selection criterion the lv-krakauer parking established — *does the author have a voice*, asked
before any corpus work, and specifically **does that voice live where the instrument looks**.
`voice_distance.py` is Burrows's Delta over CHARACTER BIGRAMS, so it sees function-word morphology,
punctuation and sentence rhythm. A writer whose distinction is plot, research or subject matter is
invisible to it — an adapter cannot carry that, and the gate cannot measure it.
⚠ `triage.length` is in **CHARACTERS**, ~5.2 chars/word calibrated against builds we did ourselves
(The Crossing mobi 777,420 chars = our measured 149,985 words). Dedup by title taking the max across
formats, and floor at 100,000 chars — that is what excludes the `accepted`-but-truncated rows
(Blood Meridian epub at 6,031 chars beside the mobi's 623,849).
## ⭐ The size ranking INVERTS the voice ranking at the top
```
Stephen King 76 works 12,133,529 w <- biggest, and NOT a candidate
Agatha Christie 72 5,451,377 <- second biggest, the Krakauer case exactly
Terry Pratchett 52 4,821,474
Georgette Heyer 30 3,416,867
Graham Greene 45 3,037,425
William Faulkner 25 2,981,183 <- the pick
```
Christie is the whole lesson in one row: a superb writer whose genius is plot architecture, in prose
deliberately kept transparent. Nothing for a char-bigram Delta to grip. King is the softer version —
distinctive in pacing and brand-name texture, not in syntax.
## The three that clear both bars
**1. William Faulkner — 25 catalogue rows, ~15 pure novels, ~1.6M words.**
*The voice in one sentence:* sentences that defer their main clause through stacked subordination
and coined compounds until the reader is held inside a single unbroken perception.
About as char-bigram-legible as English gets — the voice IS the clause-joining morphology and the
`and`/`which`/`that` density. ⭐ **And he is McCarthy's stylistic ancestor, which is the real
argument:** the Brontë gate record states the frozen adjudication needs "a control-author panel (to
place an absolute band and a hard-negative sister)" and notes we have none. Faulkner beside McCarthy
makes each the other's hard negative — a METHOD upgrade, not just another roster entry.
⚠ Messiest corpus of the three: a 446k-word `Snopes: The Hamlet, The Town, The Mansion` omnibus
duplicates novels also present individually, and `Three Famous Short Novels` overlaps it again. That
is the Hemingway trap (169,759 words of measured 90-96% collection duplication) — containment pass
before anything else.
**2. Toni Morrison — 13 rows, 11 novels after pruning, ~818k words.**
*The voice:* free-indirect discourse sliding between narrator and character mid-sentence, carried on
incantatory repetition and deliberate fragments.
Cleanest corpus shape on the list: **11 novels → 11 val units, beating Hemingway's 10.** Val units
scale with WORK COUNT, which is the structural reason Brontë's voice axis came back underpowered at
4 with no cheap fix. ⚠ Drop `Burn This Book` (anthology she edited) and `Playing in the Dark`
(criticism) — same reason Krakauer's reporting does not transfer.
**3. Raymond Chandler — 9 rows, 7 novels + a 409k short-story omnibus, ~970k words.**
*The voice:* clipped first-person declaratives that periodically detonate into one baroque simile,
with dialogue carrying most of the scene.
Fills the register gap nobody else fills — **first-person hardboiled**; the line has no first-person
male narrator at all. Corpus is almost exactly Hemingway-sized (997k vs 958k), which was the
decisive gate. ⚠ Drop `Essays and Reviews` — non-fiction.
## Held, and why
**Conrad** (31 works, 2.4M) is a genuine tier-1.5 if a fourth is wanted. **Melville** (10, 1.9M) has
a superb voice but a mixed-register corpus — the cetology chapters are a different book from the
narrative. **Austen** (12, 1.18M) is worth noting because Burrows's Delta was developed on her, so
the instrument is known to resolve her. The romantasy cluster is a separate question entirely —
see [[2026-09-17-romantasy-register-measured]].
Related: [[2026-09-17-mccarthy-split-name-leak]], [[2026-09-17-lv-bronte-gate]],
[[2026-09-17-lv-hemingway-gate]].
@@ -0,0 +1,71 @@
# `[2026-09-17]` Romantasy measured as a register — it is real, we already took its best voice, and the obvious next pick is its worst
Prompted by the operator pushing back on a one-clause dismissal of the lane as "depth behind
Yarros". The dismissal was taste; this is a measurement, on the gate's own instrument.
**Method.** Char-bigram Burrows's Delta, the same measure `voice_distance.py` gates on. ~120k words
per author, sampled from the MIDDLE quartile of each author's largest works (front and back matter
are not the voice), equalised so a bigger sample is not a different measurement. 400 most-frequent
bigrams as the feature set, z-scored over 4,000-word chunks pooled across all authors.
**Controls first, because a between-author number without a within-author floor is unfalsifiable.**
```
A-vs-A floor (two halves of the SAME author)
Yarros 0.285 Maas 0.298 Armentrout 0.314 St. Clair 0.322 Cole 0.338
Kenyon 0.375 Reyne 0.391
McCarthy 0.303 Morrison 0.327 Brontë 0.209 Hemingway 0.454 <- worst, used as the bar
positive controls (known-distinct pairs — the instrument must separate these)
Yarros vs McCarthy 0.862 1.9x
Hemingway vs Brontë 0.773 1.7x
McCarthy vs Morrison 0.675 1.5x
Hemingway vs McCarthy 0.655 1.4x
romantasy, all 21 pairs median 0.537 1.2x floor (range 0.465 - 0.674)
```
**The register is real but tight.** 1.2x floor against controls at 1.4-1.9x. Only one pair falls to
1.0x, so it is not seven names for one voice.
⚠ **Sensitivity floor, stated because a result without one is unfalsifiable.** The 0.454 bar is
Hemingway's, inflated by his own heterogeneous corpus (1920s-1960s, novels + stories + posthumous).
Against the romantasy authors' OWN floors (~0.34) the same pairs read ~1.6x — control-grade. The
truth sits between those readings and **this method cannot split it finer**. One sample per pair, no
repeat draws: read the rank ordering as indicative, do not read small gaps at all.
## Two findings that survive either floor reading
⭐ **Yarros is the cluster OUTLIER, not a typical member.** Four of the five largest distances in the
matrix involve her — Yarros-Kenyon 0.674, Yarros-St. Clair 0.644, Yarros-Reyne 0.637, Yarros-Maas
0.567. **We already trained the most distinctive romantasy voice we hold**, so a second seat in the
lane buys measurably less than the first did. That is the actual answer to "what about romantasy".
⭐ **Maas is the centroid, so the obvious commercial pick is the least distinctive.** Maas-Reyne
0.465 and Maas-Cole 0.470 are the two SMALLEST distances in the whole matrix. She is the biggest
name available (922k words) and measurably the most generic of the seven in char-bigram terms.
Picking by sales rank picks the worst adapter.
## If the lane gets a second seat it is Kenyon
Furthest from the shipped Yarros (0.674), so it adds the most new signal — **and 27 works means 27
val units, the best-powered gate the line could build** (Hemingway 10, McCarthy 6, Brontë 4, where 4
is the documented structural cause of an underpowered voice axis with no cheap fix).
⚠ Two costs: the 27 are one series (Dark-Hunter), so the shared proper-noun space makes
`--scope corpus` mandatory rather than optional; and a "Dark Hunter - The Dark Hunter Complete"
omnibus sits in the catalogue rows, so the containment pass runs first.
**Corpus shapes for the lane** (works ≥100k chars, deduped by title):
```
Sherrilyn Kenyon 27 2,368,396 w Scarlett St. Clair 11 1,133,067
Opal Reyne 14 2,466,307 Kresley Cole 10 1,037,914
Jennifer Armentrout 6 1,179,953 Sarah J. Maas 5 922,711
Rebecca Yarros 5 820,425 <- SHIPPED on this
```
⭐ Worth noting for any future bar-setting: **Yarros shipped on 5 works / 820k words.** The corpus
bar is lower than it looks.
Instrument: `scratchpad/regdist.py` (screening tool, not the gate).
Related: [[2026-09-17-next-voice-seats]], [[2026-09-16-lv-voices-line]], [[2026-09-17-lv-bronte-gate]].