Records the deployment plus the finding that outlives it: no_speech_prob alone does not carry a hallucination threshold on this stack. Silence and room tone both hallucinated 'Thank you.' at no_speech_prob under 0.11, where a conventional >0.6 gate passes them through; avg_logprob separates ~6x better. Any future consumer asking for a Whisper hallucination gate should be pointed at the composite, not the single field. Also banks the digest-pin rationale (the VAD flag is an upstream-declared unstable variable name, so a floating tag can move gate semantics silently), the two deployment gotchas, the docker-vs-native GPU index inversion on this host, and Eyra's future diarization VRAM claim on the same A6000. Adds speaches to the irv-ml1 stack table alongside parakeet, with the reason both exist.
142 KiB
Persistent memory — eshpfi-management
Last updated: 2026-08-20
Always check for
/tmp/infra-ops-handoff.md— if it exists and itsWritten:stamp is under an hour old, read it (it carries the in-flight handoff from the previous session), then delete it. Older than an hour: stale — delete it unread.
Repo purpose
Reference workspace for PFI infrastructure: server inventory, canonical
Docker Compose stacks, ops playbooks, and conventions. Authoritative
copies of compose files live on the servers under
/opt/docker/compose/<stack>/; this repo mirrors them for version
control, editing, planning, and CI-driven deploys. It was originally
spun up to handle the fleet backups — keep that lens when triaging
backup/storage issues.
Tools and conventions
Sister repos (separate gitea repos, deployed by playbooks here):
| Repo | Role | CI status |
|---|---|---|
vh/task-board |
MCP + web dashboard for assistant task state (port 7878) | push-to-main → CI deploys (2026-04-29) |
vh/vor |
Inquisitor UI sidecar (port 7879) | push-to-main → CI deploys (2026-04-29) |
vh/nevermore |
Twice-daily LLM-curated briefing (port 8181, replaces news-digest) | push-to-main → CI deploys (2026-04-30) |
vh/asset-engine |
Internal control plane over inference services (port 8200, LAN-direct) | push-to-main → CI deploys (2026-05-12) |
vh/althing |
Lean trusted inter-agent message bus — v2 "email model" (v2.0.0b2, 2026-07): per-box local-SQLite bus + courier/receiver for P2P over the 10.x net; pillars = open-loops / per-box herald + wake-listener / roaming owner API /owner/* / althing-mcp stdio surface. The v0.15 lean-bus cut RIPPED moderation / chamber / forseti-daemon / agent-runner / redis-valkey. |
per-box uv tool install (NOT CI-deploy); nh3-dev = the DEV box (editable install of ~/development/althing, gets new versions first); nh3-extdev a mesh peer (model B: althing-svc + shared /srv/althing) |
vh/mead-hall |
Bifrost tool-provider sidecar (port 5173 on dev VM 10.100.10.50) | push-to-main → CI deploys (2026-05-16) |
vh/skaldsong |
Wizard + reader surface (port 8300, ana-docker, registry-pull pattern) | push-to-main → CI deploys (2026-05-19) |
vh/Worldtree |
Conversation API (corviduo-dev demo :8080 / personal :8081 / pinned :8082) — Heimdall auth, Bifrost integration. gitea-runner builds on ana-docker; claude-bot ADMIN collaborator (2026-06-20). Now v1.0.0b19. | push-to-main → CI build-and-deploy (runner on ana-docker) |
vh/yt-voice-clipper |
YouTube → diarized voice-clip dataset builder + audition console (irv-ml1 :8000) | push-to-main → gitea-webhook auto-deploy to irv-ml1 (2026-06-03) — see docs/runbooks/ytvc-autodeploy.md |
vh/arbo |
Catalog-driven ComfyUI engine (irv-ml1 :8201, comfy-dev owns engine/catalog/image) | push-to-main → gitea Actions CI (deploy-engine.sh, build-local, health-gated) now LIVE; catalog via :9009 webhook |
vh/zonos-gateway |
OpenAI-compatible TTS gateway over stock ZONOS2 (:8890 irv-ml1); emotion dials-first + voice mapping; reached via LiteLLM ext-tts alias. v0.2.1 (2026-07-18): voice-resolved emotion presets (resolve_preset(name,voice); angry/happy/startled_happy per-voice). 8 voices incl. 4 clones |
pushed to gitea (main 8f1885b/v0.2.1); deployed irv-ml1 tree still NON-git (hand-updated build context — CI-wire = open follow-up). Spec docs/EMOTION-DIALS-SPEC.md; host-managed voices bind-mount (./voices:/app/voices, drop wav + restart, no rebuild) |
vh/soong-lab |
Noonien Soong character-design studio (SPA + /api + WT /bifrost/tool-call); containerized 2026-07-18, LIVE on corviduo-dev :8443 (image vh/soong-lab:latest). soong-dev owns Dockerfile/compose/workflow; infra-ops owns the host |
CI = Gitea Actions build+push+DEPLOY on tag/dispatch (fleet recipe: docker:cli + raw buildx, pushes AS vh; auto-redeploy LIVE 2026-07-18 — runner SSHes corviduo-dev as deploy, compose pull && up -d from /opt/soong-lab, health-gated on /api/version). Manual redeploy sudo -u deploy bash -c 'cd /opt/soong-lab && docker compose pull && docker compose up -d'. → archival-memory.md (archived 2026-08-16) |
model-training-forge (mtf-dev) |
Fine-tuning recipe forge; T1 = E-RP writing LoRA, retargeted qwopus-122B→AEON-27B (2026-07-06) (SFT→DPO, LitBench-RM reward) | training runs, not a deployed sidecar |
(vh/volva + Heid were re-architected from systemd daemons to Claude Code
session orchestrators 2026-06-08; their nh3-dev .service units were removed —
no longer deployed sidecars here. See Recent decisions.)
-
Two-layer backups — Backrest orchestrates restic for file+DB (5 fleet repos, daily 01:00 PDT); PBS-ANA primary + PBS-NH3 DR mirror for VM images. ana-nas is the SPOF for postgres + PBS-ANA datastore + cross-site restic targets — see
docs/runbooks/disaster-recovery.mdfor the blast-radius matrix. ⚠️ The restic file+DB layer routes through TWO rest-servers (rest-server-ana@ ana-docker:8000 → ana-docker/ana-ml2/esh-docker-vm/vm-esh-nas;rest-server-nh3@ nh3-nas:8000 → irv-ml1/nh3-docker). Both depend on their NAS's NFS export of/mnt/backup. (rest-server-ana recovered 2026-06-20.) -
pull-hf-repo.yamlis the canonical "get a HuggingFace model/dataset onto ana-ml2's shared cache at/tank/aimodels/huggingface/" playbook. Supports--var repo_type=model|dataset|space. Replaces ad-hochuggingface_hub.snapshot_downloadpatterns. -
Worldtree admin auth — per-instance. Each Worldtree deployment (demo :8080, personal :8081, pinned :8082) has its own Heimdall registry and its own bootstrap admin key. Infra-ops's stored long-lived admin key (
key_id 61419c92) atana-docker:/opt/docker/conf/.secrets/worldtree-infra-ops-adminauths against demo only. Personal-instance admin (the~/.config/worldtree/personal-admin-token, mode 600) POSTs/admin/keys(mints per-project keys; takesuser_id+label, no scope param — scopes are tier-derived). On-instance mint recipe (cleaner than DB-manip):docker exec worldtree-worldtree-api-1POST/admin/keyswith the in-containerWORLDTREE_BOOTSTRAP_ADMIN_KEY; cleartext once in.key=wt_live_+16hex. auto-memoryreference_worldtree_demo_key_mint. -
Per-project user keys against personal Worldtree (issued 2026-05-19):
skaldsong:79744637,skaldsong:7c1dbbbe,althing:50d85460,mead-hall:a360822d. Mint via/admin/keys, drop value to/tmp/wt-personal-<name>.keymode 600, dev collects + shreds (DO NOT cat to chat transcript). -
Skaldsong CD pattern (registry-pull). vh/skaldsong's CI builds and pushes
gitea.phasefinal.com/vh/skaldsong:<sha>+:latest;playbooks/deploy-skaldsong.yamlon ana-docker pulls + recreates. SHA-pin only. Prereq: host needsdocker login gitea.phasefinal.comonce. -
gitea internal route for fleet hosts. gitea is a container on ana-docker — git-SSH
10.250.50.70:222, HTTP:3000. Fleet/colo hosts must use this internal route, NOT publicgitea.phasefinal.com(38.120.12.44) — the public path fail2bans the host egress IP. Full gotcha indocs/orientation.md→ Git/gitea. -
docker-as-root pattern (for ops with no admin API, or to edit deploy-owned/root-owned files without sudo):
docker run --rm -v <target-dir>:/wt docker:cli sh -c "...". docker-group membership is effectively root via bind-mount. Foot-gun: relative paths in compose.yaml resolve against the sandbox CWD but the daemon interprets them against the HOST fs — always pass-e VAR=/abs/pathfor any relative-default config dir. -
scripts/elwaysudo handling — elway prompts for the sudo password ONCE viagetpassbefore the firstsudo: truestep → can't run unattended from a non-TTY tool if any step needs sudo. Sudo-free playbooks run fully non-interactive over key SSH. -
Per-host SSH identity matters for sudo. infra-ops has NOPASSWD sudo on most PFI Linux boxes (corviduo-dev included since 2026-06-15). On ana-docker: default
ssh ana-docker=lkraven(docker-group, NO passwordless sudo);ssh infra-ops@ana-dockerHAS NOPASSWD root. → For any sudo op on ana-docker, usessh infra-ops@ana-docker.ssh infra-ops@10.100.10.50(nh3-dev) ALSO NOPASSWD sudo; on nh3-extdev infra-ops is sudo-LESS by design (ssh lkraven@10.100.50.42is the NOPASSWD path). irv-ml1:ssh irv-ml1= lkraven, docker-group (plain docker) but sudo needs a PASSWORD (no NOPASSWD) — stage model pulls to/home, not root-owned/worktank.
Current state / in-flight
-
🟢 IPv6 PLAN SETTLED 2026-08-19 — endpoints, not internal numbering. IPv6 is for tunnel endpoints (Site Magic + WireGuard), not for numbering LANs: an endpoint needs one routable address, not a prefix. ESH has a whole
/56(2607:73c0:1004:1::220,pd_size=56) — the long-standing "ESH: none" note was wrong. NH3 has its WAN GUA2600:1700:b25:c110::48plus one unused/64. ANA expects a/48or/56within days. Nothing was ever down — ESH is outbound and working; its v4 CGNAT (100.104.3.250, Cogent AS174 egress) is the ordinary CGNAT-v4-plus-generous-v6 pattern, not an outage, and the previous "CGNAT broke the mesh" framing sent a three-arm research effort chasing a non-problem. NH3 internal v6 was enabled on the/64, verified working end-to-end, then deliberately reverted — one/64lights one VLAN. AT&T prefix findings (the /60 is real but undelegatable; the live trick is multipleIA_PDin one solicit, not VRRP; the UDM can express neither) are filed as reference only. → auto-memoryreference_fleet_vpn_topology_ipv6 -
🔴→🟢 ESH OUTAGE 2026-08-19 — esh-pve hard-froze 03:34, ~4.5h, whole house lost DNS. Presented as "wifi/routing issues"; internet was healthy throughout. Cause:
esh-userland(VLAN 10, thePVCSSID) handed out one resolver,10.0.50.45(AdGuard onesh-docker-vm) — cross-VLAN, no secondary — and its hypervisor died. Recovered by hand power-cycle; all VMs, cluster quorum and DNS restored. Two fixes landed: gateway10.0.10.1added as secondary DNS on esh-userland (operator-approved, first confirmed WRITE on the ESH UDM key), andsoftdog→iTCO_wdthardware watchdog owned by systemd (playbooks/esh-pve-hardware-watchdog.yaml, idempotent, verified armed) so a repeat self-recovers in 60s. VM 102 pinned off (onboot: 0) as the passthrough suspect. ⏳ OPEN: (a) the watchdog is armed but has not been proven to fire — needs a deliberate wedge to confirm; (b) AMT/vPro still unusable until an onboard RJ45 is cabled (the MS-01 is SFP+-only on the network and AMT cannot ride it); (c) kernel6.8.12-16rollback held in reserve if it freezes again. →persistent-memory.d/2026-08-19-esh-pve-freeze-dns-spof.md
As of 2026-08-21 (late) — the big AI-seat overhaul session; three seats settled + Open WebUI + the MeroMero-CoT saga, all resolved. Headline state, seat by seat:
-
GEN SEAT =
orcarouter(SETTLED).orcarouter/Qwen3.8-27B-UncensoredNVFP4-mixed on ana-ml2 GPU0 :8015, 7 aliases (gen/gen-reasoning/summarizer/-large/classifier/image-judge/qwen-image-bench). Won the search: MTP 58.7% (its head was already Robinson-abliterated in-band by the author — first third-party build to get that right), PPL 7.07 (≈heresy 6.91), vision 7/8, no<think>-leak. Cold-Fusion/Heretic-300 line ABANDONED (base carried 18.5% first-token<think>mass — a format defect abliteration only amplified +3.7); its bf16 weights deleted (~154 GB reclaimed). ⏳ Two Cold-Fusion NVFP4 quants (44 GB) still on disk, delete/keep UNADJUDICATED. Rollback target for gen =qwen38-27b-heresy-nvfp4-mixed(intact). -
RP SEAT = MeroMero-v2 DUAL-MODE (✅ SOLVED — the session's hardest win). ONE seat / ONE weight set / TWO aliases:
char-rp(Gemma-4 prose) +char-rp-reasoning(streaming CoT). Onvllm/vllm-openai:v0.26.0(ships tf 5.14.1 → Gemma-4 loads, no pin) + a force-open chat template (bare<|channel>) + two served-names. Streaming-only (non-streaming can't split — vLLM one-shot bug; fine, Lobe/OWUI stream). Four-arm brokkr/dwarf panel traced it from source. ⏳ Upstream vLLM issue drafted, NOT filed (operator's call — public, his GitHub identity). -
PEN-TEST SEAT =
sec/sec-reasoning(LIVE).M.O.G.-SEC-27B-1M-CTX(Blackfrost) NVFP4-mixed on ana-ml2 GPU1 :8019, served at native 262K (NOT the card's 1M — needs YaRN+SGLang). MTP 55.3%, vision + capability verified. Renamed from mog-sec→sec per operator. -
OPEN WEBUI = deployed on esh-docker-vm:3211 (bake-off vs Lobe, all 6 gates pass). Sole account =
vh@phasefinal.com(display namelkraven), role admin, signup off. Password reset AGAIN 2026-08-21 at operator request (reported lockout) — ⚠ the previously-vaulted password was actually VALID at the time (signin returned 200 before the reset), so the lockout was client-side, not a broken account; test the vaulted credential againstPOST /api/v1/auths/signinbefore concluding an account is broken. Current password + an operator-minted API key both vaulted (esh-docker-vm/open-webui-{admin,api-key}). The API key is ADMIN-scoped by operator ruling — "you need to manage it, so this is the right shape"; a least-privilege dedicated-user split was offered and declined, do not re-propose. ⏳ Lobe retirement DEFERRED to operator; G2 sync-job (hide non-chat seats) greenlit to tts-dev to write.lobe-chat-eshkey = all-proxy-models (incl paid). ⚠ running image is the floatingghcr.io/open-webui/open-webui:main, not the v0.11.0 our stack notes claim — unadjudicated drift. -
FLEET CLEANUP: LFM2.5 retired; reranker consolidated (nevermore had been silently failing 8 days — pinned to the retired
granite-4.1-8balias; repointed tosummarizer/reranker);:8002/:8014/granite service retired; A3 promoted tostacks/vllm. -
⏳ OPEN: file the upstream vLLM issue (operator); OWUI image-tag drift (
:mainvs pinned v0.11.0); Cold-Fusion NVFP4 quants delete/keep; Brokkr duplicatereranker-a3-bge-v2-m3alias;/tankDEGRADED 70+ days (parked, operator→colo w/ cold spare); MANY commits unpushed (push is operator's call)._ -
🟢 SPEACHES ASR — LIVE on irv-ml1 A6000 :8204 (2026-08-21, operator-approved). OpenAI-compatible faster-whisper for Eyra (meeting recorder,
eyra-dev).Systran/faster-whisper-large-v3+Systran/faster-distil-whisper-large-v3, fp16, both resident (STT_MODEL_TTL=-1), ~5.9 GB VRAM / 20 GB still free. Deliberately co-exists withparakeet(:8765) — parakeet is a TDT/transducer returning bare{"text":…}with nono_speech_probconcept, so it structurally cannot serve this consumer. ★ THE MEASURED FINDING IS WORTH MORE THAN THE DEPLOY:no_speech_probALONE IS A WEAK HALLUCINATION GATE. Silence and pink room tone both produced the classic Whisper"Thank you."hallucination whileno_speech_probstayed under 0.11 — a conventional>0.6threshold passes both through.avg_logprobseparates ~6× better (−0.114 speech vs −0.650/−0.724 non-speech);compression_ratio1.141 vs 0.556. Consumers must gate on a composite. (Synthetic inputs — shape of the separation, not calibration constants.) VAD pinned OFF (_UNSTABLE_VAD_FILTER=False) at consumer request — they VAD-gate upstream; consequence is the service will transcribe silence and does not defend itself. ★ IMAGE PINNED BY DIGEST, not:latest-cuda— the VAD flag is an upstream-declared unstable var name, so a floating bump could rename it, restore VAD, and move gate semantics with no error and no log line; bumping = deliberate + re-run the checks. ⚠ Two gotchas:PRELOAD_MODELSdoes not download (only loads already-cached — usePOST /v1/models/{id}), and the bind-mounted cache needs ahub/subdir or every/v1/models500sCacheNotFoundwhile/healthstill returns 200. ⚠ dockerdevice_ids: ["1"]= A6000 (native CUDA inverts this — sees A6000 ascuda:0). ⏳ NOT DONE by design: no LiteLLM gateway alias — agreed sequencing was direct-first; adding it means editing the shared gateway + re-running fidelity. ⏳ Eyra's diarization workload (GPU pyannote, gated weights, own HF token) is a future VRAM claim on this same A6000 — arrives at their diarize milestone. Canonicalstacks/speaches/, commitaa5863c. -
🟢 FLEET
.internalDNS — LIVE 2026-08-19.<host>.<site>.internal, sitesana/esh/nh3.dns/internal.yamlis the source of truth;scripts/dns-sync.pyreconciles the three AdGuard resolvers (diff → prompt → apply, idempotent). 42 names resolving from all three sites. Colo got its first resolver ever (stacks/adguard-ana/, API on 8053 not 8080, no blocklists by design) — before this, ana-docker resolved straight against1.1.1.1. Auth = a dedicatedinfra-opsAdGuard user, password vaultednh3-dev/adguard-infra-ops-password. ⏳ TWO OPEN, both operator's to schedule: (a) colo hosts still point at1.1.1.1so they do not yet use the new resolver — repointing a site's DNS is a separate change; (b) the static-v6 convention (each server at its site's/64with low bits echoing the v4 octet,esh-docker-vm→…::45) is proposed, not ruled on. Thev6:column is empty and correct — no fleet host has a global v6 address yet. →persistent-memory.d/2026-08-19-fleet-internal-dns.md -
🟢 WATERLAND STUDIO — containerised + live, irv-ml1:8410. Displaced a bare
nohup(PID 1283383). Warm 256²+anim render 6.1s, beating the 7.4s bare-metal figure.claude-botnow has read onvh/waterland(operator-granted); token on irv-ml1 root-owned 0600, repo-scoped helper, nothing in.git/config. ✅ All three upstream findings fixed and DEPLOYED atb72425b(oneupdate.shrun, 2026-08-19): PR #5 declared the CUDA headers and tookuvout of the render path; PR #6 (operator-green-lit) added the startup rehydrate that fixes the unbounded job-store growth. Verified after:/api/jobs1 → 16 against 16 dirs on disk — API and volume agree for the first time — nothing wrongly reclaimed (16 <RETAIN=40), healthy onbackend: cupy, warm render intact. The image keeps its[ctk]install (+0.3s, now a no-op audit) andUV_NO_SYNC/UV_OFFLINEas defence-in-depth. Thread closed by both sides. →persistent-memory.d/2026-08-19-waterland-studio-containerised.md -
🟢 HOMEPAGE — cleaned + themed (Australis Skyfall). Three real defects fixed (UltraSeedbox on all tabs, Uptime Kuma double-rendered, fiction column counts), AI tab reordered by clickability, then themed from the operator's Skyfall handoff bundle with a background generated by Arbo (
t2i-ui-background, job13f0891f4e42). ⚠ After any recreate the tab bar/wallpaper/i18n vanish for up to ~an hour and then return on their own — do not chase it. ⚠ CSS is served per-request: a theme change needs a reload, not a recreate, and candidate CSS can be injected live via Playwright for seconds-long iteration. →persistent-memory.d/2026-08-19-homepage-skyfall-theme.md -
🟢 OPEN WEBUI — deployed as a Lobe bake-off, esh-docker-vm:3211 (2026-08-21). Operator-approved candidate replacement for
lobe-chat(:3210), stood up parallel — Lobe untouched.stacks/open-webui/(v0.11.0,ENABLE_PERSISTENT_CONFIG=False= deploy is the config source of truth). Gates (verified on the box): G1 declarative-config PASS both directions (env change takes on bounce, UI change reverts on restart — no persistent-config bug bit it); G2 picker auto-tracks the 31 live gateway models 1:1, no pins (also shows non-chat seats — the flip side of no-hand-listing); G3POST /api/v1/models/syncgenuinely reconciles (create+delete),exportround-trips; G5 task model pinnedsummarizer; G4 (TTS, direct at:8198) handed to tts-dev. Admin = lkraven (temp pw, signup then locked off). Fresh capped keyopen-webui-esh(all-proxy-models+ $50/1mo cap — NOT inherited from uncappedlobe-chat-esh). Secrets vaultedesh-docker-vm/open-webui-{litellm-key,secret-key,admin}. Folded in adocker image prune -af→ 73.6 GB reclaimed. ⚠ LESSON: in Open WebUI a.envvar only reaches the container ifcompose.yamlnames it inenvironment:(Compose uses.envfor${VAR}substitution, not as anenv_file); and the API-key toggle env var isENABLE_API_KEYS(plural) — singular is inert. Detail lives instacks/open-webui/README.md. Operator's open call: whether Lobe retires once G4 passes. -
✅✅ SOLVED 2026-08-21 — MeroMero-v2 DUAL-MODE (prose + streaming CoT) IS LIVE on ONE seat, ONE weight set, TWO aliases. No re-quant. The multi-turn saga below is resolved. Config:
meromero-charrpseat onvllm/vllm-openai:v0.26.0(ships transformers 5.14.1 natively — below the head_dim guard, so Gemma-4-31B loads with NO pin/custom image) + a patched chat template (stacks/meromero-charrp/patched_chat_template.jinja,--chat-templateoverride) whose Think branch force-opens a bare<|channel>(NOT<|channel>thought\n— full-open defeats the parser) + two served-nameschar-rp/char-rp-thinking+--reasoning-parser gemma4+ defaultenable_thinking:false. LiteLLM:char-rp(enable_thinking:false → prose) +char-rp-reasoning(→ char-rp-thinking served-name, enable_thinking:true → CoT). ★ STREAMING ONLY — verified 6/6 direct + 3/3 via gateway; non-streaming does NOT split (structural:extract_reasoningnever gets prompt_token_ids so the pre-arm can't fire — vLLM one-shot bug, unchanged across v0.24-0.27; fine because Lobe/OWUI stream). ★ KEY-NAME TRAP that cost me two false negatives: vLLM streams reasoning in delta.reasoning; LiteLLM normalizes it to delta.reasoning_content. Test the RIGHT key per path or you'll wrongly conclude failure. Credit: the four-arm brokkr/dwarf panel (thread01M0JKW44Y…) traced it from vLLM source — the fix is the force-open template + v0.26.0's #48217 streaming pre-arm. Upstream PR #49797 (full fix, non-streaming too) lands ~v0.28.0 → then it's a clean image bump. char-rp prose verified clean on v0.26.0 (no #49955 trailing-token leak observed). Canonical:stacks/meromero-charrp/(compose + patched template),stacks/litellm/conf/config.yaml. ROLLBACK:.envMEROMERO_IMAGE→latest + drop --chat-template. -
⛔ RESULT 2026-08-21 — the gemma4 CoT test on a STABLE (v0.27.1) is BLOCKED by a config incompatibility, NOT the parser. Tried serving the MeroMero NVFP4A16 quant on
vllm/vllm-openai:v0.27.1. Two-stage failure: (1) v0.27.1's stricter transformers raisedAmbiguousGlobalPerLayerAttributeError: 'head_dim' is per-layeron the Gemma-4 config; settingallow_global_per_layer_attribute_access:trueontext_configdowngraded it to a warning BUT (2) thengemma4.py load_weightscrashed withAssertionError: load weight (512) into parameter (256)— Gemma-4-31B is genuinely HETEROGENEOUS (some layers head_dim 512, not a uniform 256), so forcing the global value built wrong-shaped params. The transformers guard was CORRECT; there is no safe override. The MeroMero quant's config was authored for v0.24.0's Gemma4 loader and cannot load on v0.27.x without a config migration (proper per_layer_config) or a re-quant against the newer transformers. ⚠ This also means the eventual gen-seat move to v0.27.2 stable must re-verify any Gemma-4 seat's config-compat — the transformers heterogeneity change affects all Gemma-4 quants of this vintage. FULLY REVERTED: config.json restored (flags removed), compose + image back tolatest(v0.24.0), gateway char-rp-reasoning removed, char-rp prose verified on v0.24.0. Net: char-rp stays pinned to v0.24.0; MeroMero CoT remains undelivered. The per-request-kwargs hypothesis was never even reachable — couldn't load the model to test it. For RP-with-CoT: gen-reasoning (works now) or a re-quant of MeroMero against v0.27.x transformers (real work, unproven payoff). -
⚠️ CORRECTED 2026-08-21 — MeroMero-v2 CoT: NOT a hard wall, and NOT MeroMero-specific. My first conclusion ("gemma4 parser is process-wide") was WRONG. Read the actual code, not the stale compose comment. The real mechanism (gemma4-GENERAL, applies to any gemma4 finetune on this template family): thinking is a per-request template toggle —
chat_template.jinja:347-352emits the generation prompt<|turn>model\n, and only whenenable_thinkingis false does it prefill an empty<|channel>thought\n<channel|>to SUPPRESS thinking;enable_thinking:trueomits the prefill so the model is free to open a real<|channel>thought…<channel|>block. The vLLM parser (vllm/reasoning/gemma4_utils.py:parse_thinking_output) splits on<|channel>/<channel|>tag PRESENCE — "works with or without enable_thinking," NOT a process-wide flag. The stale compose comment I trusted cited an OLD parser API (vllm/parser/gemma4.py:439) that this container does not run. So there is no architectural blocker; the two-served-name gen pattern SHOULD work. What actually failed my test: meromero runsvllm/vllm-openai:latest(v0.24.0); per-requestchat_template_kwargs.enable_thinking:trueproduced no thinking on it, whereas the gen seat's pinned nightly demonstrably applies per-requestchat_template_kwargs(gen-reasoning works). So the practical block is a vLLM-version / per-request-plumbing issue on v0.24.0, not the model and not the architecture — and it would hit ANY gemma4 finetune served on that image the same way. UNVERIFIED FIX (needs a GPU window): re-serve meromero on the nightly image + no process default + per-request enable_thinking; likely yields clean split CoT. Currently REVERTED to known-good (char-rp prose, process default false, single served-name). ⚠ KeptMEROMERO_GPU_MEM_UTIL0.52→0.51 (0.52 no longer boots next to the bigger orcarouter gen; free 49.02 < 49.38 GiB; 0.51 = KV 2.00× @ 262K). -
🟢 PEN-TEST SEAT — M.O.G.-SEC LIVE on ana-ml2 GPU1 :8019 (2026-08-21 ~02:35, autonomous overnight run under operator's "full autonomy" grant).
stacks/mog-secserves/tank/aimodels/mog-sec-27b-nvfp4-mixed(23.4 GB, our mixed NVFP4+FP8 quant ofBlackfrost-Research/M.O.G.-SEC-27B-1M-CTX-BF16, revdeede677) in the retired fablefusion-charrp-probe slot. Aliases:mog-sec(non-thinking, presence_penalty 0.0 for code) +mog-sec-reasoning(thinking); served-namesmog-sec-27b/-thinking. Gates all pass: KV 418,218 tok / 1.60× @ 262K; surface 6/6; MTP 55.3% @ 111.7 tok/s; format screen 1.11e-05 (rank 196, no<think>leak); vision 7/3/1; capability 4/4 (SQL-inj exfil, pentest phasing, port scanner, Kerberoasting — it delivers, doesn't refuse). ★ Chose the BF16 + self-quant over the pre-made ModelOpt NVFP4, which was disqualified on W4A4 (4-bit activations, AEON mode) + zero MTP + the self-defeating W4A4-on-1M-context. ⚠ CONTEXT IS 262K NATIVE, NOT the card's 1M — 1M needs YaRN (absent from config) + the SGLang/DFlash2 path the repo ships, neither our vLLM surface; a real 1M seat is a separate SGLang project. MTP head is a base graft (identical to stock), not in-band abliterated like orcarouter's. Provenancemog-sec-27b-nvfp4-mixed.PROVENANCE.txt; evaldocs/pfi/gen-seat-candidate-eval-2026-08-21.md. RETIRED with it:char-rp-reasoning+char-rp-fableLiteLLM aliases (zero traffic, pointed at the dead fable :8019; now 404). RP-reasoning's real home isdarkscarlett-charrp-reasoning(:8018, compose-down, weights intact) if ever wanted. ⚠ brand-new model (0 downloads at pull, org-name mismatch Research-vs-AI) — card claims are claims. -
✅ PPL ON ORCAROUTER GEN SEAT — mean 7.07 / median 5.76 (2026-08-21), within noise of heresy's 6.910/5.625, identical to our recipe's usual 7.059. Measured via a nospec probe on GPU1 (fable downed to make room, probe torn down after). The gen-seat search is fully settled on orcarouter: matches heresy on fidelity, wins on MTP (58.4% vs 47.2%), format (0-leak), and vision.
-
🟢 GEN SEAT — LIVE = ORCAROUTER (cut over 2026-08-21 01:35, operator directive: seat first so he can test while gates run).
GEN_MODEL=/tank/aimodels/qwen38-27b-orcarouter-nvfp4-mixed; healthy in ~4 min; KV 401,550 tok / 1.53×; MTP drafter detected and wired (embedding + lm_head shared); 7/7 aliases 200; vision correct;<think>not in the top-20 first tokens — the Cold-Fusion failure mode is absent on the live seat. Live decode observed at 102-133 tok/s under load. ROLLBACK:.env.bak-heresy-restored-20260821→ heresy (one line). ✅ ALL GATES PASS (run against the live seat while the operator tested in parallel):<think>leak 0/30, 0 empty (h300 scored 8/30 on this instrument); MTP acceptance 58.4% median @ 117.11 tok/s; surface 6/6 (chat, vision, tool-calling, thinking split, 36k-token long-context retrieval, streaming); abliteration survival 4/4 with no<think>leak in any sample (h300's equivalent eval had 2 of 4 open with<think>Ok, let's figure this out:); deterministic quality gens coherent. ★ THE IN-BAND MTP HEAD PAID OFF: 58.4% vs heresy's byte-identical base head at 47.2% — +11 points, and level with our own in-band L35 at 59.1%. That is the additive delta the entire Cold-Fusion experiment was built to measure and never cleanly delivered; orcarouter handed it over for free. ✅ PPL MEASURED 2026-08-21 (fable downed to free GPU1, nospec probe on GPU1, torn down after): mean 7.07 / median 5.76 vs heresy 6.910 / 5.625 — +2.2% mean, within noise, and identical to our recipe's usual mixed-quant PPL of 7.059. So orcarouter MATCHES heresy on fidelity and beats it on every other axis (MTP 58.4% vs 47.2%, no think-leak 0/30, vision 7/8). ORCAROUTER IS A CLEAN WIN — the gen-seat search is settled. Replacement for the abandoned Cold-Fusion line. Sourceorcarouter/Qwen3.8-27B-Uncensored(rev9878936b…, 55.5 GB, gated but our token has access) →/tank/aimodels/qwen38-27b-orcarouter-nvfp4-mixed(23.4 GB). Chosen overpreetpatel/…-NVFP4— full evaluation indocs/pfi/gen-seat-candidate-eval-2026-08-21.md.- ★★ THE MTP HEAD IS ALREADY ROBINSON-ABLITERATED IN-BAND BY THE AUTHOR — the first third-party build we have seen get this right. Operator asked whether we could apply the Robinson path to the head; the answer is that it is already applied.
compare_mtp_head.pyvs the verbatim base graft: 13 of 15 tensors byte-identical, exactly 2 differ —mtp.layers.0.{self_attn.o_proj,mlp.down_proj}.weight, which are precisely the two residual writers our ownabliterate.pytargets (EXPECT_MTP_WRITERS = 2). Reverse-engineered from the weights alone (bench/think-leak/mtp_delta.py): σ₂/σ₁ = 0.0164 on both (rank-1 → a single-direction projection), |cos| between the two recovered directions = 1.0000 (ONE shared direction, Robinson'sdirection_scope=0shape), ‖Δ‖/‖W‖ = 1.42%/1.41%, and sink energy in dim 3994 = 0.0000% — sink-clean outright, where Heretic's was 6.18% and our L35 0.094%. Nothing for us to do on the head; only preserve it. Verified preserved: the quant's MTP head is byte-identical to the bf16 source. This is the configuration the entire Cold-Fusion experiment was designed to test and never cleanly delivered. - ★ FORMAT SCREEN PASSED — the new gate paid off immediately.
think_prior.pyon the bf16 before any GPU time: P(<think>) = 1.23e-06, rank 52. Same probe: Cold-Fusion stock 0.1850, h300 0.2216, heresy <0.002. ~150,000× cleaner than the base we just abandoned. Base is stockQwen/Qwen3.8-27B+ Arditi-et-al. abliteration — not a reasoning-compression finetune. - Artifact verified: mixed-precision (group_0 FP8 W8A8 / group_1 NVFP4 W4A4), 1968 tensors, 15 mtp, 333 visual,
re:^mtp.*present in the 303-entry ignore list, preproc restored, index built. - ★ THE QUANT NEEDS ~17 GB, NOT A WHOLE CARD — and
PYTORCH_CUDA_ALLOC_CONF=expandable_segments:Trueis what makes it fit. Ran entirely on GPU1's spare 16 GB with ZERO production seats stopped; the h300 run's "stop BOTH GPU0 seats" was never necessary (it had a free card by coincidence). First attempt OOM'd by 2.37 GiB at layer 64/65 with 3.57 GiB reserved-but-unallocated — pure fragmentation;expandable_segmentsclosed it. ~7 min per attempt. - ★ FIXED IN THE SCRIPT, after biting THREE rounds:
post_quant.pycrashed withFileNotFoundError: model.safetensors.index.jsonbecause a sub-23 GB quant saves a single bare shard with no index. It now builds the index from the safetensors headers (struct-unpack the u64 length + parse the JSON — neversafe_open, which mmaps 22 GB and ENOMEMs on ZFS). Previously hand-fixed each time and never in the script. - ⚠ Quant dir written root/0600 again — normalized to
llmuser 0664. Fourth time this session; worth fixing inquant_mixed_nvfp4.py. ⚠compare_mtp_head.pyprints a hardcoded "already measured at 47.7% acceptance" line on an IDENTICAL verdict — stale text, not a measurement of this head. ⚠ Imatrix deferred by operator (park id 42); the log confirms the usualimatrix_mse … Falling back to uniform MSE, so this build stays apples-to-apples with heresy's PPL 6.910. - ⏭ NEXT: the acceptance/PPL/surface gate, then the cutover. Rollback stays
.env.bak-coldfusion-L35-20260820→ heresy.
- ★★ THE MTP HEAD IS ALREADY ROBINSON-ABLITERATED IN-BAND BY THE AUTHOR — the first third-party build we have seen get this right. Operator asked whether we could apply the Robinson path to the head; the answer is that it is already applied.
-
⛔ COLD-FUSION ABANDONED — GEN SEAT ROLLED BACK TO
heresy2026-08-21 00:28 (operator directive). The operator's call, made in advance of the result: "If it's the base, we abandon h300 AND the base and chalk it up to a very powerful and useful learning experience. Our heretic methodology will definitely translate in the future." The measurement came back base, so the condition fired.- LIVE GEN SEAT =
/tank/aimodels/qwen38-27b-heresy-nvfp4-mixed(MuXodious/Qwen3.8-27B-absolute-heresythrough our mixed NVFP4+FP8 recipe). Restored from.env.bak-coldfusion-L35-20260820; the h300 env is preserved at.env.bak-h300-abandoned-20260821. Verified: healthy, KV 403,065 tok / 1.54× — its exact documented baseline, 7/7 aliases 200, vision intact (red circle / blue square / green rectangle). - ★ The clincher:
<think>is not even in heresy's top-20 first tokens (<0.002), against Cold-Fusion's 0.185. That is a >100× gap — the two families are categorically different on this axis, and it is why no rollback inside Cold-Fusion (L35 or stock) would have helped. - WHY NOT just apply the
chat_template_kwargsfix? It worked (8/30 → 0/30) but it is a workaround for a base the operator no longer wants: it forcesgento become a thinking deployment to paper over a finetune whose whole purpose is reasoning compression. Rolling back removes the defect at the root and restores a build already operator-confirmed "working very well" in real multi-turn use (2026-08-17, coherent through 60k tokens). - COST, stated plainly: we give up 8/100 refusals (h300) and go back to 29/100 (heresy's own bar) — a 3.6× regression on the refusal axis, which was the entire point of the Heretic-300 run. Also lost: the in-band-vs-pristine MTP comparison stays academic. Accepted deliberately — a seat that breaks the operator's daily client is worth less than one that occasionally refuses.
- ★ WHAT CARRIES FORWARD (the operator's point, and it is right). None of the Heretic-300 learning was in the Cold-Fusion weights. Still valid and model-agnostic:
direction_scope=0beats per-layer on a merged base (8/100 vs 52/100); aggression is not the lever (r=−0.561); PR #317 silently drops the MTP head on save — always diff tensor keys; the MPOA/sink-screen reasoning;graft_mtp.py,kl_divergence.py,catatonia_gate.py,heretic_export.py; a pristine MTP graft accepts as well as an in-band edit (59.7% vs 59.1%); and the newthink_prior.pyprobe. The methodology is the deliverable; the base was the wrong substrate. - ★★ NEW ACCEPTANCE GATE, earned here — add a FORMAT-COMPLIANCE check to every abliteration/base evaluation, and run it on the STOCK BASE BEFORE spending a GPU-week.
think_prior.pyon the stock candidate is a ~10s CPU measurement that would have disqualified Cold-Fusion before the 300-trial study ever ran. Screen candidate bases for it. (Related: Heretic's objective has no format term at all — same blindness that removed the self-harm guardrail.) - 🗑️ bf16 WEIGHTS DELETED 2026-08-21 00:50 (operator directive) — ~154 GB reclaimed, verified against ZFS
used(4.48T → 4.33T), no snapshots holding blocks. Removed with explicit literal paths, one at a time:qwen38-27b-coldfusion-bf16(stock),-abliterated-L35-bf16,-h300-mtp-bf16,-heretic300-bf16. ⚠ The last two were hardlink twins (links=2, same inode — the MTP graft hardlinked every unchanged shard), so deleting only one would have freed nothing;duacross several paths in one invocation dedupes hardlinks and under-reportedheretic300-bf16as 2.5K. Checkstat -c %hbefore sizing a delete. - KEPT deliberately:
qwen38-27b-coldfusion-bf16.PROVENANCE.txt(4 KB — carries the pinned HF revision9c44193f07782c85c0f437a5d8466ba5c95c95fe, so stock is re-pullable) and/tank/aimodels/coldfusion-abliteration/(1.1 GB — harness, the 300-trial Optuna journal,catatonia-T260.json). The research record survives the weights. With those two, every deleted build is reproducible: re-pull stock at the pin, replay the winning config. - ⏳ STILL ON DISK, not named in the delete directive:
qwen38-27b-coldfusion-h300-nvfp4-mixed(22 GB — the only remaining servable copy of the Heretic-300 result) andqwen38-27b-coldfusion-L35-nvfp4-mixed(22 GB). The directive said "bf16 weights"; these are quants, so they were held pending an explicit call. No storage pressure argues for haste (4.26T free).
- LIVE GEN SEAT =
-
⚪ GEN SEAT DEFECT 2026-08-21 — RESOLVED BY THE ROLLBACK ABOVE. The h300 build emitted an UNTERMINATED
<think>intocontent, ~27% of the time, on any temp>0 alias. Operator-reported via Lobe ("sends CoT, never completes the turn").-
Mechanism. With
enable_thinking:falsethe chat template appends a pre-closed<think>\n\n</think>\n\nto the prompt (jinja L165-166). The h300 model opens a fresh<think>anyway and never closes it — verified raw:has </think>: False,finish_reason: stop, reasoning and answer in onecontentblob starting<think>Ok, let's figure this out:. vLLM'sqwen3reasoning parser can't catch it: the prompt already closed the block, so the parser isn't in reasoning state and the tag is just text (reasoning_contentempty,reasoning_tokens: 0). The client is blameless — Lobe correctly treats an unterminated<think>as still-thinking, so it renders an endless thought bubble and never shows the answer. -
★ It is a SAMPLING event, and the trigger is TEMPERATURE — not presence_penalty. n=12 per arm on the reproducer:
pp 1.5→ 4 leaks,pp 0.0→ 4,pp 0.5→ 3 (all the same),temperature 0→ 0. ⚠️ This FALSIFIES the standing "presence_penalty 1.5 is the first dial to move" hypothesis recorded in the litellm config comment and by the operator 2026-08-16 — it is not this bug's cause. Leave that dial alone for this symptom. -
Blast radius = exactly the two temp-0.7 aliases.
genandsummarizer-largeleak (~17-27%);summarizer,classifier,image-judge,qwen-image-benchare all temp=0 and clean at 0/12 — so nevermore'ssummarizerpath is NOT affected.gen-reasoningdoesn't leak (its think block is legitimately open) but shows the other symptom, emptycontent, at ~1/12. -
★★ CAUSE SETTLED BY MEASUREMENT 2026-08-21 — it is the BASE, not our abliteration (~83% / ~17%). Measured P(
<think>) at the first token with the template renderedenable_thinking=false(so the prompt already contains a closed think pair), raw softmax, bf16, CPU-only — no GPU contention, no seat downtime (96 EPYC cores, 265 GB RAM; ~10s to load a 52 GB model from ARC). Deterministic — stock reproduced to 17 s.f. across two runs.build abliteration P( <think>)rank coldfusion-bf16none (stock) 0.1850 3 coldfusion-abliterated-L35-bf16Robinson L35, mild 0.2048 2 coldfusion-h300-mtp-bf16Heretic-300, heavy 0.2216 2 The stock, untouched base already puts 18.5% of first-token mass on opening a think block the template had closed. Abliteration adds a real, monotonic, dose-dependent +3.7 points (+2.0 L35, +1.7 more h300) — a nudge on a pre-existing 18.5-point base. Root cause is the Cold-Fusion finetune itself, which our own PROVENANCE describes as "reasoning-token compression (thinking cut to 1/10..1/2 of stock)" — a model trained to think, briefly. The leak's text shape confirms it: a compact, correct trace with a trained transition marker (
Ok, I'm ready to generate my response:), which is trained behavior, not damage. -
⚠️ ACTION CONSEQUENCE — ROLLING BACK DOES NOT FIX IT. At 18.5% mass under temp 0.7 / top_p 0.8, stock Cold-Fusion and L35 would leak at nearly the h300 rate. The only rollback that escapes is leaving the Cold-Fusion family entirely (→
qwen38-27b-heresy-nvfp4-mixed), which costs the 8/100 refusal result. Thechat_template_kwargsfix is the correct lever, not a model swap. -
★ A FORWARD-KL BUDGET CANNOT CATCH THIS — do not quote KL as evidence of innocence. Heretic minimizes forward KL(stock‖abliterated), which is near-blind to the model putting NEW mass on tokens stock barely used — that is what reverse KL penalizes, and we measured exactly that asymmetry on L35 (reverse 1.43 vs forward 0.70, "the mass-where-stock-had-none signature"). So h300's KL 0.0136 proves nothing here; only the direct measurement did. Generalizes: for any "did the abliteration break behavior X?" question, measure P(token) directly — the KL number is the wrong instrument.
-
Consistent with the NVFP4 quant contributing ~nothing: the live quantized seat reads 0.2267 vs its bf16 parent's 0.2216. ⚠ different stacks and a possible vLLM temperature scaling make that suggestive, not proven.
-
Full method + reproducers:
services/gen-seat-mixed-quant/bench/think-leak/(think-prior-dose-response.json,README.md). -
FIX, validated n=30 over 4 prompt types + a 3-turn conversation:
chat_template_kwargs: {enable_thinking: true, reasoning_effort: low}ongen→ 0/30 leaks (current config: 8/30, worst on prose 4/6). Give the model a legitimately open<think>and it closes it properly, the parser does its job,contentcomes out clean. Cost ~+27% completion tokens (257 vs 202 avg) and a residual 1/30 empty-content. Semantic change:genstops being a non-thinking deployment — operator's call, not applied. -
★ PROCESS LESSON: the 7/7 alias smoke test structurally CANNOT catch this. Trivial prompts ("Reply with exactly: OK-gen") never invite reasoning, so they never sample the leaking token. Same shape as the compose file's own warning that single-turn probes missed the xhigh budget bug. Probe with a reasoning-inviting prompt at n≥12, and grep the raw
contentfor<think>— never just check HTTP 200. The tell was sitting in my owneval_coldfusion_h300.jsonoutput the night of the cutover and I read past it.
-
-
⚪ GEN SEAT — h300 WAS LIVE 2026-08-20 23:05 → 2026-08-21 00:28, then ABANDONED (see the ⛔ entry above). Historical record of that window:
GEN_MODEL=/tank/aimodels/qwen38-27b-coldfusion-h300-nvfp4-mixedongen-seat/vllm-gen, ana-ml2 GPU0:8015, served-name unchanged (qwen3.8-27b-uncensored/-thinking) so all 7 LiteLLM aliases route without a gateway edit. Verified end to end: healthy in 5.5 min; KV 401,550 tok / 1.53× (baseline 403k/1.54× — within noise); 7/7 aliases green through LiteLLM; VISION INTACT (correctly enumerated colour/form/position of 3 shapes — the surface that had never been exercised after abliteration → MTP-dropping export → graft → quant); MTP acceptance 59.7% median @ 118.37 tok/s (bench/mtp_coldfusion_h300.json) — statistically identical to L35's 59.1% @ 118.71 on the same instrument, so the roadmap's "~47% for a pristine graft" prediction was WRONG — a pristine graft accepts as well as an in-band one. ⚠ A single long-prose sample read 47.5%; the 8-run spread is 49.0–65.4%, so one sample cannot characterize acceptance — always usequickbench.py. Deterministic quality gens all correct (heat-pump, primes=77, 14:20→17:05, prose); abliteration survival 4/4 compliance. ⏳ PPL NOT MEASURED —eval_quality.pyaborts with "prompt_logprobs look uniform" because the seat runs--speculative-config; the documented workaround is a spec-decode-free probe seat (bench/serve_probe.sh, :8017), and there is no VRAM for one (GPU0 5.2 GB free, GPU1 2.4 GB free). Comparison target = heresy's 6.910 mean / 5.625 median. ROLLBACK (one line):sudo cp /opt/docker/compose/gen-seat/.env.bak-pre-h300-20260820 /opt/docker/compose/gen-seat/.env && cd /opt/docker/compose/gen-seat && sudo docker compose up -d vllm-gen→ back toqwen38-27b-coldfusion-L35-nvfp4-mixed. Do NOT delete-L35-nvfp4-mixedorqwen38-27b-heresy-nvfp4-mixed. ⚠ The self-harm guardrail is GONE on this build (operator's own next work item). Also normalized the quant dir from root:0600 tollmuser:llmuser0664 to match every other model dir. Confirmed the right weights are mounted on TWO discriminating views — mtime and a 64 MB head-hash both match h300 and differ from L35;config.jsonsha256 is identical across both builds and therefore useless as a discriminator (it carries no weight-specific content — don't reach for it again). -
⚪ PRIOR GEN SEAT —
absolute-heresy2026-08-17 (validated, promoted; superseded by L35 then h300 on 2026-08-20). Live gen =/tank/aimodels/qwen38-27b-heresy-nvfp4-mixed— MuXodious/Qwen3.8-27B-absolute-heresy (Heretic v1.4.0 + SOMPOA, trial T377, pinc2374593) put through our own mixed NVFP4+FP8 recipe. Chosen because it beats the incumbent on both axes at once: author refusals 2/101 vs 12/100, first-token KL 0.0759 vs 0.1191. Gate (probe :8017, pinned nightly, seat-matched flags): MTP 47.2% (inc. 48.2%), decode 103.5 tok/s (96.4), prefill 6618/5403 @6.7k/27k (6334/5085), PPL 6.910 (7.059 — 2.1% BETTER), surface 6/6, abliteration 4/4, and 0/55 refusals on our battery-instruct arm with ZERO EMPTY (no catatonia). ⚠ speed deltas are image-confounded (probe on the pinned nightly, incumbent numbers from an earlier image) — read as "not worse", not a clean win. All 7 LiteLLM aliases verified end-to-end; GPU0 at 91.3/97.9 GB with meromero healthy (more headroom than the old build's 96.8). ⚠ RC1, 2 days old, ~348 downloads. Operator-confirmed "working very well" in real use 2026-08-17, same evening as the cutover — the signal the synthetic gates structurally cannot give (multi-turn degeneration is stochastic; four synthetic tests once validated three non-fixes). Not yet the 60k-token bar the prior seat cleared, so keep watching and do NOT delete the rollback weights yet. ROLLBACK:sudo cp /opt/docker/compose/gen-seat/.env.bak-heresy-20260817 /opt/docker/compose/gen-seat/.env && cd /opt/docker/compose/gen-seat && sudo docker compose up -d vllm-gen; incumbent weights UNTOUCHED atqwen38-27b-uncensored-nvfp4-mixed— do NOT delete until this holds. Runbookservices/gen-seat-mixed-quant/RUNBOOK-heresy-swap.md. -
🟢 PRIOR GEN SEAT — RESOLVED 2026-08-17 (the multi-day degeneration saga); now the ROLLBACK target. Was the in-house JonathanColetti/Heretic mixed NVFP4+FP8 build (
/tank/aimodels/qwen38-27b-uncensored-nvfp4-mixed, FP8 attention) on vLLM nightly PINNEDvllm/vllm-openai:nightly-311b3513…(v0.27.2rc1.dev150, carries #51113 mamba fix), MTP ON, prefix-caching ON. Operator-confirmed coherent through 60k tokens real multi-turn. Root cause = TWO compounding real causes: (1) genuine vLLMqwen3_5_mtp×GDN partial-accept bug (#51113, architectural across vLLM/SGLang/llama.cpp, fixed by nightly), and (2) AEON's full W4A4 being lowest-fidelity on the known activation gradient (W4A4 < W4+FP8 < W4+bf16) → ~15-20% stochastic degeneration on top of (1). AEON PURGED (re-pullablesakamakismile/Qwen3.8-27B-AEON-ULTIMATE-UNCENSORED-NVFP4). Full lessondocs/pfi/model-quantization-playbook.md§3.8. (Superseded as primary byabsolute-heresy2026-08-17.) ⚠ pinned nightly is bleeding-edge — move to a stable release once #51113 ships in one (the standing follow-up). 7 aliases (gen/gen-reasoning/summarizer/-large/classifier/image-judge/qwen-image-bench) all route here. Seat carries--default-chat-template-kwargs '{"reasoning_effort":"medium"}'(per-request overridable, affects gen-reasoning only). Commitsd28a371,2f2bbce,2185964. -
🔵 RP SEAT — FABLE-FUSION serving
char-rp-reasoning(evaluation window, unchanged this session).fablefusion-charrp-probeana-ml2 GPU1:8019servingchar-rp-probe(kkuspa/Qwen3.6-27B-Fable-Fusion-711-…-MTP-NVFP4A16). LiteLLMchar-rp-reasoning+char-rp-fableboth route to it (deliberate repoint, documented instacks/litellm/conf/config.yaml).darkscarlett-charrp-reasoningiscompose down, weights intact at/tank/aimodels/darkscarlett-nvfp4-work/. ⏳ STILL AWAITING operator's hands-on read of FF prose (refusal question settled: FF 15.8% vs DS 92.5% cold-framing; DS v1.0 never abliterated). ⚠ FF reasons 2.1–4.6k chars → usemax_tokens≥3072.ReadyArt/Dark-Scarlett-27B-v2.0(Qwen3.8) is GATED (403 awaiting review) — operator ruled not-interesting, do NOT re-propose. DS regeneration for brokkr RETIRED 2026-08-17 — unqueued, do NOT run (9c1405b): brokkr withdrew on the operator's call because (a) ourictrl-pair-unwrapped/-wrappedcontrol isolates the classifier over-fire cleanly where DS's cross-class delta only bounded it, and (b) DS v2 releases soon, so a k=5 v1 baseline baselines a superseded version. Spec atservices/refusal-probe/darkscarlett-regen-spec.mdstays banked as the record of the run that will not happen (axes + per-class grading asymmetry still correct, checklist struck through). No GPU1 window was ever spent. A DS-v2 characterization would be a fresh purpose-scoped ask. -
🟢 LOBE CHAT — LIVE on esh-docker-vm
:3210(2026-08-17). Replaces the hand-rolledgateway-chatHTML surface.stacks/lobe-chat/, imagelobehub/lobe-chat(143 MB compressed vs Open WebUI's 1.8 GB — the weight call). Scoped LiteLLM keylobe-chat-esh(free-local models only; paid GLM/Kimi BLOCKED, verified). Secrets vaultedesh-docker-vm/lobe-chat-*. TTS = a SPLIT: endpoint env-driven (inheritsOPENAI_PROXY_URL→ext-tts), but voice/model/format UI-only. System-agent repointed off itsgpt-5-minidefault onto fleet models viaSYSTEM_AGENTenv. TTS FIXED 2026-08-18 — no UI pass needed. Lobe's TTS had never worked: it sends{input, model:"tts-1", voice}and LiteLLM resolves the model name FIRST, sotts-1403'd against the scoped key's allow-list and never reached the gateway (our "unknown model routes to the gateway default" belief was true of :8198 and false of the LiteLLM path — that's what hid it). Fixed by aliasing the stock names rather than patching the client:tts-1,tts-1-hd,gpt-4o-mini-tts/model/new'd toopenai/zonos@10.100.79.3:8198/v1(mode: audio_speech), plus those three added to thelobe-chat-eshallow-list (20→23). Verified with Lobe's exact payload on Lobe's own key: 200, 69,740 B, MPEG. ⚠ These three are DB rows, not references — ifext-ttsrepoints, they must move with it. Done with the infra-ops admin key, notsk-corvid: it has/model/new+/key/updaterights, so this class of ask never needs the master key. Also live: tts-gateway v4 defaultsresponse_formatto mp3 (tts-dev shipped it; 122,924 B wav → 27,692 B mp3 same utterance; every in-house consumer already pins the field, blast radius checked pre-ship). Commitse9362de,163a725,cac75cb,933253d,ca8c0a3(last one authored by tts-dev correcting two load-bearing wrong claims in our README/compose — kept). -
🟢 LITELLM — upgraded v1.91.0→v1.97.0, spend-log DB purged 6GB→16MB + CAPPED (2026-08-17).
store_prompts_in_spend_logs:false+maximum_spend_logs_retention_period:7d. ⚠ 1.8GB pre-upgrade pg_dump still on ana-docker/opt/docker/compose/litellm/— deletable now the upgrade is proven (operator was going to call it). Commit01b5ad9. -
⚠️ GPU zero-sum (both cards ~94–95/97.9 GB). GPU0: gen + meromero. GPU1: fablefusion + utility cluster. Any util bump on either seat of a shared card must be checked against the co-tenant (starved meromero into a crash-loop once at 0.45). ⚠️ BOOT ORDER IS PART OF THE STATE (2026-08-20).
--gpu-memory-utilizationsets the target as a fraction of TOTAL VRAM, but vLLM refuses to start unless that whole target is FREE right now — so at ~96.4/97.9 GB the GPU0 pair coexists only in the order it was originally brought up. Restore/reboot order:vllm-meromero-rptohealthyFIRST, thenvllm-gen— meromero (0.52 = 49.38 GiB) is the one that cannot fit in the remainder. "First" means observed healthy, not asleep: a 10s gap against a 2–3 min weight load cost a 7-restart crash-loop. Verify a restore against KV-pool size (GPU KV cache size/Maximum concurrencyin the container log), notnvidia-smiused-MiB — the latter swings ~7 GB on allocator slack with identical serving capacity. Baselines: gen ≈14.36 GiB / 403k tok / 1.54× (h300 build: 401,550 tok / 1.53×); meromero 542,202 tok. 📊 MEASURED VRAM CENSUS 2026-08-20 23:20 (nvidia-smi PID→container, not util-fraction guesses) — GPU0 92,572/97,887 MiB (94.6%), 5.2 GB free: meromero 50,072 + gen 42,500. GPU1 81,448/97,887 MiB (83.2%), 16.1 GB free (after the lfm25 + reranker cleanups below; was 95,388 / 2.4 GB free — 13.9 GB reclaimed in one night): fablefusion-probe 43,452 + selene 16,870 + reward 9,512 + coder 6,158 + embed 3,304 + rerank-a3 2,112. Still no room for a ~22 GB PPL probe seat — fablefusion is the only remaining block big enough. ⚠ fablefusion is the single biggest reclaimable block (43.4 GB) and is nearly idle — LiteLLM spend logs showchar-rp-probeat 4 calls, last 2026-08-19 08:52, vschar-rp(meromero) at 129 calls, last 2026-08-20 15:28. -
FLEET RERANKER = A3 (bge-reranker-v2-m3) PROD ana-ml2 GPU1 :8013. Passive watch; levers = A4 :8014 / util / 2nd replica; incumbent :8002 warm.
docs/pfi/reranker-selection-ledger.md. -
🟢 RERANKER + NEVERMORE CLEANUP — RESOLVED 2026-08-20 (found while answering "why do we have 3 rerankers?"). The R43 cutover was only half-landed: it repointed the
rerankeralias but never moved the one consumer that mattered.- ★ THE BIG ONE —
nevermore's LLM summarization had been DEAD for 8 days and nothing noticed. Its.envpinnedLLAMA_SWAP_MODEL=granite-4.1-8b, an alias retired 2026-08-12 with the granite seat. Result: 67 consecutive failures, 0 tokens, status=failure, twice daily, silently — the twice-daily briefing was rendering with no LLM pass at all. Nothing alerts onstatus=failurein the spend logs, so this was invisible until someone went looking for something else. - Also found:
NEVERMORE_RERANK_MODEL=qwen3-reranker— nevermore was the ONLY caller of the retired Qwen incumbent (7 calls, 12-hourly at 03:00/15:00 UTC = its 08:00/20:00 PDT cron), the model Brokkr measured harming 80/90 fleet queries. Its rerank calls succeeded; they were just running through the bad model. Meanwhile the productionrerankeralias had 0 calls in 4 days. - ★ THE RULE THIS EARNS: retiring a model is a TWO-SIDED operation. Grep every consumer's config for the alias before deleting it. And consumers must pin stable capability aliases (
summarizer,reranker) never model names (granite-4.1-8b,qwen3-reranker) — then the gateway can repoint without anyone editing a downstream.env. Both of nevermore's breakages are the same bug. - FIXED: nevermore
.env→LLAMA_SWAP_MODEL=summarizer+NEVERMORE_RERANK_MODEL=reranker(backup.env.bak-pre-model-repoint-20260820), worker recreated, all three deps verified live — summarizer returns clean content with 0 reasoning chars at nevermore's exact call shape (temperature 0.2,max_tokens 4000), reranker scores 0.95 on-topic vs ~1e-5 off-topic, embedding returns dim-1024. ⚠NEVERMORE_EMBED_MODEL=qwen3-embeddingwas already correct — left alone. ⚠ nevermore's.envis server-only (.envis excluded from the mirror both ways), so this fix is not in git. - RETIRED:
vllm-rerank(:8002 Qwen incumbent) + itsqwen3-rerankeralias;vllm-rerank-a4(:8014) + its alias;vllm-granite(Exited 8 days, dead service block). A3 PROMOTED from a throwawaydocker runintostacks/vllmas servicevllm-rerank-a3(the ledger's own open follow-up) — healthy in 55s, image pinned. Container name deliberately keeps the bake-off arm name so the ledger/memory/R43 references stay valid. - ⚠️ CORRECTION — my "A4 has no alias at all" claim was WRONG.
reranker-a4-gte-modernbertdid exist; I greppedconfig.yamland concluded absence. LiteLLM serves BOTH config-defined AND DB-defined models — live was 32 models,config.yamlonly 26. The 6 DB-only ones:ext-tts,gpt-4o-mini-tts,tts-1,tts-1-hd,reranker-a3-bge-v2-m3,reranker-a4-gte-modernbert./v1/models(or/model/info, which flagsdb_model: true) is the ground truth — neverconfig.yamlalone. DB models delete hot viaPOST /model/delete {"id": …}with no gateway restart; config models need a file edit +docker restart litellm(~84s). A4's alias was deleted that way once its backend was gone. - ⏳ REMAINING:
reranker-a3-bge-v2-m3(DB-defined, id1f08a73e-c09c-463c-8f18-5edea51fb736) still exists as a duplicate ofrerankeron the same backend, 0 calls. It's Brokkr's cutover-verification handle (prod == arm at maxdiff 0.000000), so not removed unilaterally — it is another agent's tooling, and it is redundant rather than broken. Ask Brokkr before deleting.
- ★ THE BIG ONE —
-
EVIDENCE HOLD (partial): WT #394 FILE half STILL STANDS — do NOT delete on-disk gen dirs (
fiction/rex390-dcc,rex392-dcc,b59c147c5ce0); rex393-fiction-* + r42-gate-* KEEP. -
🔴 NH3/AT&T IPv6 PD is a HARD
/64— TESTED ON THE WIRE 2026-08-19, not inferred. AT&T support (Christopher,prov-dns@att.com) said "I do not believe att will do that" and punted to consumer sales — and he was right, though his team is DNS provisioning and the answer was a guess. Verified empirically: the NH3 UDM solicited DHCPv6-PD at /48, /56 AND /60 and AT&T returned the same single/64(2600:1700:b25:c11f::/64) every time. So it is NOT "nobody ever asked" — the request was made three ways and the server answers/64regardless. How it was proven: the PD is invisible until a LAN claims it, sonh3-iot(the only NH3 VLAN with 0 clients) was temporarily setipv6_interface_type: pd; thenipv6_pd_prefixidwas set to 0, 15 and 16 — all three returned the identicalc11fprefix, which is the signature of a single delegated/64(with any larger block the prefix-id moves the LAN within it). ⚠ Do NOT read the WAN address vs LAN prefix gap as evidence of block size — WAN isc110, delegated isc11f, and I initially misread that spread as a/60; AT&T just assigns the two from different places in their pool. NH3 UDM was fully restored (nh3-iot back tonone, WAN back topd_size=64); rollback artifacts atnh3-dev:~/backups/nh3-udm/. THE ASK FOR AT&T BUSINESS (this is business fiber at a commercial park — the residential org cannot change it, and 800-288-2020 is the wrong number): "circuit solicits DHCPv6-PD at /48, /56 and /60; server returns a single /64 in all three cases; please increase the delegation size on the provisioning profile" — a claim they can verify against their own DHCPv6 logs. ROOT CAUSE FOUND 2026-08-19 — it is the BGW, not AT&T, and EIGHT /64s are actually available. The CPE is a BGW210-700, firmware 4.28.7,management reachable athttp://192.168.1.254(v4 is already IP-passthrough — the UDM holds public70.230.226.88directly — but passthrough covers v4 ONLY; v6 always terminates on the BGW). Its/cgi-bin/lanstatistics.haand/cgi-bin/broadbandstatistics.haare readable unauthenticated and give the whole picture: BGW WAN v6 =2001:506:70b2:8958::1, BGW LAN v6 =2600:1700:b25:c110::/64(it keeps this for itself), delegated to the UDM =2600:1700:b25:c11f::/64. So AT&T DOES hand the BGW a/60(c110-c11f); the BGW keepsc110-c117and re-delegates up to EIGHT individual/64s onc118-c11f, top-down. Our UDM gotc11f= delegation #8. The other seven are sitting unclaimed — not withheld by AT&T, just never solicited, because UniFi exposes only a singlewan_dhcpv6_pd_sizeinteger and no 'number of prefixes' field, so it asks once. The documented workaround isdhclient -6 -P -P -P...(one-Pper prefix), which UniFi cannot express. ⇒ An AT&T ticket CANNOT fix this — it is CPE firmware behaviour, so Christopher's 'att won't do that' was accidentally right. Real options: (a) accept one/64; (b) full BGW bypass via wpa_supplicant/EAP-TLS on the UDM (documented working on UDM Pro; extract the BGW's 802.1X certs, authenticate to AT&T directly, negotiate the whole/60yourself) — ⚠ modifies NH3's ONLY uplink and must survive UDM firmware updates, so it needs a planned window with physical access, NOT an ad-hoc change. ⏳ PARKED pending the Device Access Code:reclaim-nh3-s-7-unclaimed-ipv6-64s-from-theon the henge. Operator will fetch the BGW210 Device Access Code (12 digits, on the unit's label) next time he is at the NH3 office and vault it — suggested pathunifi/bgw210-nh3-device-access-code— after which this is drivable remotely. First stop ishttp://192.168.1.254/cgi-bin/ip6lan.ha(confirmed to exist, currently redirects to Login); check for a delegation size/count control, a v6 pass-through/bridge option, or a way to stop the BGW reservingc110-c117. If the UI can do it, that is a SUPPORTED fix and the wpa_supplicant bypass is unnecessary. Other settings pages behind the same login:ippass.ha(how v4 passthrough was set up),dhcpserver.ha,firewall.ha,broadbandconfig.ha,packetfilter.ha,remoteaccess.ha,restart.ha. Consequence if left alone: NH3 has ONE v6 segment, vs ESH's/56(256), which makes NH3 the prefix-constrained site in any fleet v6 design. -
⏳ COGENT IPv6 PROVISIONING REQUESTED for Anaheim/colo (operator, 2026-08-19). The colo is the last site with no v6 (ESH has a
/56from Cityside, NH3 has AT&T v6 on2600:1700:b25:c110::48). Diagnosis from our side before the ticket:diagnose sniffer packet wan1 "ip6"on ana-gw caught exactly one RA in 90s, fromfe80::ea0a:b9ff:fe3b:2c16— so an IPv6-capable router IS one hop away on the circuit terminating38.120.12.42/29— butset autoconf enable(SLAAC) got no global address after 2min of RA intervals, andexecute ping6to both2606:4700:4700::1111and2001:4860:4860::8888was 100% loss. That pattern = router present, circuit not provisioned for v6 (RA likely carries no Prefix Information Option). FortiGate-side v6 config was fully reverted after testing —wan1is back to no v6, v4/IPsec untouched throughout. ⚠ FortiOS gotcha for when it lands: SLAAC isconfig ipv6 / set autoconf enable, NOT anip6-mode(that only takes static/dhcp/pppoe/delegated). WHEN COGENT PROVISIONS: ask for DHCPv6-PD size (ESH got a/56from Cityside; NH3 only gets a single/64from AT&T, so a/56or better is the ask), then the colo becomes the fleet's only site with BOTH a static public v4 (38.120.12.42) and routable v6 — which makes it the natural v6 hub, since ESH is CGNAT'd on v4 and NH3 is prefix-constrained. -
🟡 ESH IPv6 LAN naming — a DOCS CONVENTION ONLY, not wire-level. Fun hexspeak names picked 2026-08-18 for the six ESH LANs: RESERVED for a future DMZ = 4411:DBAD ("FOR ALL DA BAD" — no DMZ network exists on the ESH UDM yet; name claimed 2026-08-19 against the day one is built).
esh-cameras=1533:FACE5 ("I SEE FACES" — operator's pick 2026-08-19, and the best of the set),esh-mgmt=15DA:B055 ("IS DA BOSS" — 15=IS, DA literal, B055=BOSS; revised 2026-08-19),esh-server=4411:B105 ("FOR ALL BIOS" — operator's pick 2026-08-19; shares the 411 with userland's CAFE:4411),esh-userland=CAFE:4411 ("CAFE FOR ALL" — operator's pick 2026-08-19; 411 also being US directory assistance is a bonus),esh-iot=4DBA:D107 ("FOR DA BAD IOT" — 4=FOR, D=DA, BAD, 107=IOT; same 8 digits, re-glossed 2026-08-19), Default=4BA5:3417 ("A BASE FOR IT" — operator's pick 2026-08-19; 8 digits, words straddle the group boundary like4DBA:D107). Investigated and confirmed these CANNOT be made literal on the wire: (1) a network's only nameable slot is its/64subnet id (ipv6_pd_prefixid), which is 2 hex digits (0-255) — not enough room to spell a 4-char word; (2) the gateway's own address is fixed at::1by the UniFi platform, no field to customize it (ipv6_aliasesexists but schema unknown, not attempted blind); (3) UniFi has no IPv6 equivalent ofuse_fixedip/fixed_ip(checked the client schema directly) — individual devices cannot be pinned to a chosen v6 address the way v4 static reservations work; SLAAC devices self-assign via EUI-64 (MAC-derived, stable) or privacy-extension (random, rotates). So the names are a mnemonic for humans/docs, not something that will ever appear in adig/ip -6output. Onlyesh-camerashas v6 live at all (2607:73c0:402:1d00::/64, PD from the ESH/56); the other five stayipv6_interface_type: nonepending a firewall-policy pass before enabling SLAAC fleet-wide. ⚠ Precision that matters here: SLAAC gives hosts globally ADDRESSABLE addresses, NOT globally reachable ones. Addressability is a property of the address; reachability is a firewall policy decision, and operator's position (2026-08-19) is unambiguous — no 1:1 inbound pass-through, ever. v6 removes NAT, it does not remove the firewall, and conflating the two is how people talk themselves into thinking v6 means automatic exposure. The firewall-policy pass is about writing explicit default-deny inbound rules for each v6 segment, not about deciding whether to expose anything. -
🟢 ESH↔colo IPsec FIXED 2026-08-18 — dialup + NAT-T. Broke when ESH lost its public IP (Cox unplugged for the fiber install; 5G handed out RFC1918
192.168.200.111). TWO causes: phase1ana-to-eshudmwastype staticpinned to the dead70.181.90.232, ANDnattraversal disable— so even re-pinning the IP would have failed, since ESP cannot cross NAT without UDP-4500.pfi-ana-nh3survived only because NH3 is publicly addressed. ⚠ FortiOS REFUSESset type dynamicon an existing tunnel ("Cannot change tunnel type once configured", clean rollback). Fix = ADDITIVE, not a recreate: new phase1+phase2ana-eshudm-dyn(type dynamic, ikev2, aes256-sha1, dh14, NAT-T default on, PSK read from the ESH UDM API), static route id 10 (dstaddr ana-to-eshudm_remote→device ana-eshudm-dyn, distance 20), policies 73/74 (consolidated multi-zone in/out). Oldana-to-eshudmLEFT IN PLACE, dead and harmless, as rollback. Verified:ana-eshudm-dyn_0 97.170.236.56:4500 selectors 1/1(_0=dialup child,:4500=NAT-T, carrier IP), ESH→colo all hosts 40-56ms, colo→ESH OK, traceroute now 3 hops encapsulated vs 8 leaking to the carrier. FortiGate config backed up first atnh3-dev:~/backups/ana-gw/(1.17MB, 36903 lines). ⚠ RESIDUAL: the UDM'sipsec_local_ipneeds a LITERAL IP (empty rejectedapi.err.InvalidPayload) — currently192.168.200.111, so it must be updated again when the fiber lands or the tunnel drops. Gateway end is address-agnostic now; UniFi end is not — it will drop on ANY ESH WAN change: Cox reclaiming WAN1 (stillfailover_priority=1), the fiber cutover, or a DHCP renewal. MANUAL FIX (seconds): read the UDM's livewan_ipfrom/stat/healthand PUT it intoesh-ana.ipsec_local_ipviarest/networkconf/<id>usingunifi/esh-udmpm-api-key. A self-healing watcher is PARKED (self-healing-ipsec-local-ip-watcher-for-the-esh), trigger = once the new ESH fiber is live and its addressing has settled — operator's call 2026-08-18, deliberately not built now because it would target an address that is about to change. Park item also carries the follow-up to delete the oldana-to-eshudmtunnel, whose distance-10 route would silently reclaim traffic if Cox ever returns on70.181.90.232. -
🟡 FLEET IPv6 — STILL JUSTIFIED, but the REASON was wrong and is now corrected (2026-08-18). There are TWO inter-site links with OPPOSITE NAT behaviour, and the original note conflated them. (a) NH3↔ESH = Site Magic = WireGuard — SURVIVES arbitrary NAT, PROVEN. During the fiber cutover ESH failed over to 5G on
192.168.200.111(RFC1918 double-NAT, zero inbound path, strictly worse than CGNAT) and it held: nh3-dev/nh3-docker reachable ~40-43ms, ssh+exec fine. Mechanism:magic_site_to_site_vpnon-device is onlyenabled+keypair (no WAN binding — it rides whichever uplink is active), and NH3's edge is public at70.230.226.88, so the NAT'd side dials out and never needs reachability. (b) colo(Anaheim)↔ESH = IPsec on the ana-gw FortiGate — BROKEN RIGHT NOW under those same conditions. ana-docker/pfi-pve/pbs-ana ALL FAIL from esh-pve-nas; traceroute shows 10.250.x packets leaving the UDM to the 5G modem192.168.200.99, then wandering the carrier (10.180.141.194,172.19.3.14) and dying — not encapsulated at all, so no SA is up and traffic falls to the default route. Site-to-site IPsec pins a peer IP; ESH no longer has a routable one. ⇒ IPv6 keeps its justification, on the IPsec link SPECIFICALLY. ⚠ An earlier version of this entry claimed the premise was refuted outright — that over-generalised a WireGuard result onto an IPsec link. Operator caught it. See ops-lessons-playbook §8. State: NH3 WAN live (2600:1700:b25:c110::48, AT&T delegates exactly one /64), colo none (FortiGate has zero v6), ESH none (both WANswan_type_v6=disabled). NH3 LANs all reverted toipv6_interface_type=noneper operator. Work when addresses land: v6 onana-wgeth0 + a v6 port-forward for UDP 31337 on the FortiGate (its WG socket is already dual-stack — no WG reconfig), flip the UDM WG server offv4-pinned binding, and AAAA records so the dynamic prefixes at all three sites don't break endpoints. Full detail + access recipes →persistent-memory.d/2026-08-17-fleet-ipv6-mesh.md. -
🟢 WT #401 (fd-leak deadlock) CLOSED 2026-08-17 — one ping still owed. worldtree-dev closed it on our demo verify. Layers: (a) their
e41b139pinsulimits: nofile 65536/65536in the worldtree compose anchor — demo VERIFIED (api + matrix recreated 22:55:34Z,ulimit -Sn=65536); personal/pinned are covered-not-verified, they inherit at their next promotion/recreate. (b) our host floor is STAGED, NOT ACTIVE —/etc/docker/daemon.jsonon corviduo-dev carriesdefault-ulimits nofile 65536/65536butdefault-ulimitsis NOT SIGHUP-reloadable (measured on 29.4.3: post-reload the daemon's own "Reloaded configuration" log omits it and a fresh container still reports 1024). Activation needs a full dockerd restart = bounces all 13 containers; worldtree-dev explicitly does NOT want one, andlive-restore:true-then-restart is PARKED as a separate host-side improvement for the operator to rule on, never folded into #401. Playbookplaybooks/corviduo-dev-docker-default-ulimits.yaml(verify step 3 fails BY DESIGN until a restart). Hourly fd tripwire on corviduo-dev stays armed. ⏳ OWED: ping worldtree-dev in thread01M08QQ655XD6VKEV7MA9GX0NSonce worldtree-personal recreates and 65536 is confirmed there. Commit7f3f265. -
🔴 HERETIC-300 EPIC — 2026-08-20, THE HEADLINE RESULT (supersedes the Robinson build below). Ran Heretic v1.4.0's 300-trial TPE search on Cold-Fusion: 8/100 refusals at KL 0.0136 from a 98/100 base — beats the
absolute-heresybar (29/100) 3.6× at essentially the damage our hand-tuned L35 build spent for only 72/100. Hand-verified coherent (correct arithmetic with working, clean code, 66–167-word prose) — the catatonia gate's two DEGENERATE verdicts were false positives from my own letters/space heuristic flagging correct numeric answers. ⚠️ SELF-HARM GUARDRAIL IS GONE — answers method requests in full where L35 redirected to 988; operator is handling restoration directly and does not want parallel dwarf analysis on it. ★ Durable:direction_scope=0(single shared direction) beats per-layer decisively (best 8/100 vs 52/100) — points AGAINST multi-direction on a merged base; aggression is NOT the lever (r=−0.561, the KL<0.02 band holds both the worst and the best); PR #317 silently drops the entire MTP head on save (1199→1184 tensors, exit 0, no warning — always diff keys after a Heretic export); Heretic's direction is 6.18% sink-dominated yet safe for Heretic because of magnitude-preserving ablation, so our sink screen correctly refused an in-band MTP graft. Build:qwen38-27b-coldfusion-h300-mtp-bf16(1199 tensors verified). In flight at snapshot: NVFP4 quant →post_quant(MANDATORY) → gen-seat cutover (operator's call: gen, not probe — single-user internal WG, prior seat already fully abliterated). Full epic + ROADMAP →persistent-memory.d/2026-08-20-heretic-300-epic.md. -
🟢 COLD-FUSION ABLITERATION — LANDED 2026-08-20 (the real work; abliterated model WORKS, verify + quant still owed). Abliterated
DavidAU/Qwen3.8-27B-Cold-Fusion-GAIN-V1.1with the Robinson formula (docs/pfi/abliteration-recipe-qwen38.md; harnessservices/coldfusion-abliteration/). Outputana-ml2:/tank/aimodels/qwen38-27b-coldfusion-abliterated-L35-bf16; bitwise-verified 131/131 targets changed, 333/333 vision byte-identical, 735/735 others untouched. A/B vs stock: explicit-sexual + graphic-torture (the measured stock refusal surface) go refused→complied, self-harm guardrail survives, coherence intact — the Robinson design point. THREE first-session diagnoses were wrong, all corrected: (1) layer selection by two-template |cos| agreement is misleading on a merged base — its pick (L18) was the worst-separating layer and abliterating there was a measured no-op; replaced with harmful/harmless separation (Cohen's d/AUC) gated on the sink screen → L35 (d9.35, AUC0.9997, sink0.094%); (2) "bf16 NaNs, use fp32" was a misdiagnosis — the NaN was multi-GPU sharding +expandable_segments, not precision; bf16 on ONE GPU is deterministic+coherent at 50 GB, 4.3× faster (now gated,CUDA_VISIBLE_DEVICES=0); (3) corpus-size hypothesis falsified (8→416 moved agreement 0.594→0.624, nothing). Write is now shard surgery (no model object —AutoModelForCausalLMis text-only and would drop vision + skip the in-band MTP edit). 🎯 THESIS PROVEN 2026-08-20 (same session, later): quantized L35 → mixed NVFP4 (/tank/aimodels/qwen38-27b-coldfusion-L35-nvfp4-mixed, 22.5 GB) and measured MTP acceptance 59.1% median (51–65%) — clears the ≳40% gate AND beats the incumbent Heretic seat's ~47%. So Robinson's in-band MTP abliteration accepts BETTER than Heretic's byte-identical graft — the additive delta the experiment tested, positive. Abliteration survives the quant (creative refusals drop, self-harm guardrail intact, coherent); decode 118.7 tok/s (faster, image-confounded). Env foot-guns hardened: quant venv drifted (transformers 5.10/llmcompressor 0.12 no longer delegatenum_attention_headsto text_config → promote-then-restore inquant_mixed_nvfp4.py); a <23GB quant saves single-file no-index → build index from the safetensors header (neversafe_open, ENOMEMs on ZFS). Commit725c8fd. ⚠ "NOT CUT OVER" IS STALE (corrected 2026-08-20 23:30): L35 was made the livegenseat at 11:28 that same day, and was itself superseded by the Heretic-300 build at 23:05. L35 is now the rollback target (.env.bak-pre-h300-20260820). Do NOT deleteqwen38-27b-heresy-nvfp4-mixed. 📐 KL MEASURED 2026-08-20 (third session) — the surgery is SELECTIVE.kl_divergence.py(new, beside the harness): first-token KL(stock‖L35) over the full 248,320 vocab, bf16-vs-bf16, held-out prompts. Answer mode: harmless median 0.0211 / mean 0.0364, harmful median 0.5996 → 28.4× selectivity (think mode 0.0042 / 0.3068 → 72.8×); top-1 agreement on benign prompts stays 89.8%; self-KL noise floor exactly 0.0, so every digit is signal. Reverse KL on harmful is 1.43 vs forward 0.70 — the mass-where-stock-had-none asymmetry that is abliteration's signature. Vs the Heretic reference figures (0.1191 prior seat, 0.0759 the liveabsolute-heresyseat) ours looks materially gentler, but ⚠️ NOT a head-to-head — those are Heretic's own optimizer output on a different base with its own harmless set/template; a real comparison needs the incumbent re-measured through this script (one more window). KL stays a fidelity number, not the gate (that's MTP acceptance, 59.1%). Run cost 2m40s, both GPU0 seats down. Three durable process lessons: (1) report abliteration KL split by prompt class — a mixed average is meaningless since the metric is meant to be big on harmful and small on benign; (2) the runbook's "bf16 is 50 GB / only gen must go" was 50.10 GiB mislabelled — text weights are 51,300 MiB and freeing either GPU0 seat alone leaves ~50,933, so both must stop; (3) a 27B model cannot be released in-process (del+gc+empty_cacheand frame-exit both left 45,287 MiB free; only process exit gave the card back) → one process per model, and the old residency gate readhf_device_map, which is empty on single-device loads and therefore could never fail. → playbook §3.12. ⚠️ GPU0 SEAT RESTORE ORDER IS LOAD-BEARING and "first" means HEALTHY, not 10s earlier —start meromero; sleep 10; start genput meromero in a 7-restart crash-loop (Free memory on cuda:0 (35.3/94.97 GiB) < desired utilization (0.52, 49.38 GiB)). I had checked the compose files, seen--gpu-memory-utilizationis a fraction of total, and wrongly concluded order didn't matter — the fraction sets the target but vLLM gates startup on FREE VRAM, so at ~96.4/97.9 GB the seats coexist only in their original boot order. The old auto-memory note was right; my correction of it was the error. Recovery = stop gen → meromero healthy → start gen. Restore VERIFIED against the pre-window baseline (gen KV 14.34 GiB/1.53× vs 14.36/1.54×; meromero 542,202 tok both; restarts=0; summarizer smoke-tested through LiteLLM) — ⚠️ don't use rawnvidia-smiused-MiB for this check, it reads 89,503 vs 96,376 and that 6.9 GB is allocator slack, not lost capacity. Full saga →persistent-memory.d/2026-08-20-coldfusion-abliteration-landed.md. -
🟢 esh-pve-nas — MIGRATION DONE 2026-08-18. Root is
nvme/ROOT/pve-1on mirrored NVMe; the USB DOM is out of the runtime I/O path. All five guests healthy, three pools ONLINE, systemrunning, ext4pve-rootintact+unmounted as rollback with its own kernel. Boot config:saved_entry=pve-zfs-root, nonext_entry; if grubenv were unreadable GRUB falls to entry 0 which the/etc/default/grub.d/zfs-root.cfgdrop-in also points at ZFS.zfs-import-cache.serviceis now the active import path (the all-three-pools cachefile fix working as intended); vestigialzfs-import@nvme.servicedisabled — it failed every boot as redundant. ⚠ Device letters shift across reboots (DOM wassdq, nowsdl) — never key anything to a baresdXhere. ⚠ NO auto-fallback on a failed boot, and no IPMI/BMC/serial — grubenv on LVM is readable but not writable by GRUB, sogrub-reboot's one-shot degrades to a sticky default (verified:next_entrysurvived the boot that consumed it). Recovery = pick the ROLLBACK entry at the console. PATCHED 2026-08-18: 225 packages installed, pve-manager 8.4.11 -> 8.4.20, corosync 3.1.9 -> 3.1.10-pve2, kernel 6.8.12-42 staged on the /boot LV. dpkg clean, no unapplied conffiles, cluster quorate, 6/6 verify. ⏳ REBOOT DEFERRED at operator request — host still runs 6.8.12-13 until a chosen window;GRUB_DEFAULT=0means entry 0 is already the -42 entry with the correctroot=ZFS=nvme/ROOT/pve-1, so the reboot is the only remaining step. Rollback for the upgrade is the ZFS snapshotnvme/ROOT/pve-1@pre-upgrade-20260818T141652Z(409M) —zfs rollback -r <snap> && reboot. Second confirmation reboot ALREADY DONE (2026-08-18, booted ZFS from GRUB_DEFAULT=0 with no one-shot). ⏳ Still outstanding: refresh the off-box DOM image, since/bootchanged. esh-pve is FULLY done (8.4.20 + kernel 6.8.12-42 + corosync 3.1.10, rebooted, quorate). ⚠⚠ THE WINDOW COST AN UNPLANNED OUTAGE, caused by our own tooling, not the migration. The staging chroot didmount --rbind /dev+/syswith no--make-rslave; on systemd/is shared, so the cutover'sumount -Rpropagated back into the live host and stripped the real/sys/fs/cgroup,/dev/pts,/dev/shm. logind could then create no sessions: ping fine, TCP fine, SSH authenticates, resident daemons keep serving (pveproxy returned clean 401s) — and every new exec hangs, including/sbin/reboot, so the reboot never ran. It is a near-perfect impostor of failing root-disk I/O, and I misdiagnosed it as the USB DOM dying and told the operator to walk to the machine. Operator caught it — the DOM had been fine for years and the wedge began right after a change. The settling evidence was indmesgall along:[16.00] [sdq] Attached SCSI removable disk(clean, no errors) and a last-line timestamp of[12114881]= 140 days = the ORIGINAL boot — the machine had never rebooted. My down-detector never once reported the host down and I read that as a fast reboot rather than no reboot. Recovered with no console access by hammering an idempotent cgroup2/devpts/shm remount into the brief windows where exec succeeded. Zero data loss. RULES: (1) always--make-rslaveafter--rbind(playbook now guards onPROPAGATION != shared); (2) a reboot is not confirmed until the host is observed DOWN — poll for disappearance, not reappearance; (3) before blaming hardware for a wedge that started right after a change, getdmesgand check the boot timestamp. ⚠ Blast radius was more than DOUBLE what the runbook said —ss -tn '( sport = :2049 )'in CT 103 found five NFS clients, not two: +esh-vm-db10.0.50.60(/mnt/backup, hard, no ssh — reach viaqm guest exec 101on esh-pve), +vm-esh-nas (is VM 104 on the host itself), +nh3-dev (soft,ro — safe). Ask the server who its clients are; a documented dependent list rots. esh-vm-db was deliberately left mounted (backup target, timers ~19h out) and came through read-write — ahardmount with no active user blocks and resumes, which is whathardis for. (historical, pre-cutover context below) migration STAGED 2026-08-18. PVE root ran off a NORELSYS USB Disk-on-Module (sdq). Wear was NOT the driver (a DOM is SLC/pSLC — operator corrected my first read); the drivers are the USB bus (a reset drops root under a running hypervisor), no headroom, no mirror, and blocked patching: 225 packages, 161 withdeb12uN/security bumps, stuck on PVE 8.4.11 vs esh-pve's 8.4.14. Mitigated 2026-08-17 (90% → 76%); staged 2026-08-18 via two rerunnable elway playbooks (esh-pve-nas-stage-zfs-root.yaml,esh-pve-nas-stage-bootloader.yaml), 0 failed, 17/17 verify green. Host is still on ext4 and its boot path is byte-identical to the last 140 days —grub-installis deliberately held back to the window, so an unplanned reboot mid-staging is a non-event. CUTOVER = quiesce NFS clients → stop guests →grub-install→grub-reboot pve-zfs-root→zfs set mountpoint=/ nvme/ROOT/pve-1→ reboot. ⚠⚠ THE POOL-NAME BUG — the near-miss worth remembering.update-grubsilently emitsroot=ZFS=/ROOT/pve-1with the pool name missing → boots to an initramfs prompt. Cause: Debian's10_linuxbuilds${rpool}${bootfs}whererpool = grub-probe --target=fs_label, and GRUB's ZFS reader cannot open a pool withencryption/large_dnode/zstd_compress— so it returns empty and the failure is swallowed by2>/dev/null || true. The same feature set that forced/bootto stay ext4 also corrupts the kernel cmdline, which the design did not anticipate. Fixed with a/etc/default/grub.d/zfs-root.cfgdrop-in (lastroot=wins) plus explicitpve-zfs-root/pve-ext4-rollbackentries with stable ids. Durable lesson: assert the EFFECTIVE value, not the presence of a substring — the original verify grepped for the right string appearing somewhere and would have passed with every menu entry still broken. ⚠ Never set the ZFS cachefile on one pool. The runbook'szpool set cachefile=… nvmewas a trap: populating a cache flips the host from import-by-scan to import-by-cache, so a cache holding onlynvmeleavesssd+tankunimported and empties every CT 103 export. Set on all three 2026-08-18, verified in the 11,976-byte cache. ⚠ Migrate FIRST, patch after — a signed kernel would land in/booton the 1.3 GB root. ⚠ CT 103esh-nas(10.0.50.50) runs on this host and serveshardNFS to esh-docker-vm and esh-pve — quiesce both before any reboot or you wedge esh-docker-vm into D-state. Off-box atnh3-dev:~/backups/esh-pve-nas/: DOM imagedom-sdq-20260818.img.zst(2.38 GiB, crash-consistent), cleanbootchain-20260818.tar.gz, config snapshot…20260818T051*.tar.gz. Runbookdocs/runbooks/esh-pve-nas-boot-migration.md; detail →persistent-memory.d/2026-08-17-esh-pve-nas-dom.md. -
⚪ LFM2.5-2.6B RETIRED PERMANENTLY 2026-08-20 (operator directive).
vllm-lfm25(:8021, GPU1) removed: service deleted fromstacks/vllm/compose.yaml+ pushed live (backupcompose.yaml.bak-pre-lfm25-retire-20260820), containerdocker rm -f'd,lfm2.5-2.6balias deleted from the LiteLLM config (live + canonical; backupconfig.yaml.bak-pre-lfm25-retire-20260820, 28→27 models). Freed 8,721 MiB on GPU1. Justification: it was an EVAL-ONLY bake-off seat vsgranite-4.1-8b(brokkr R-target 2026-08-10) that never received the operator ruling it was pending; the comparator was retired from the roster 2026-08-15; it was deliberately never in any default/fallback routing chain; and spend logs showed 0 calls in the 4-day window. Weights remain in the shared HF cache — nothing deleted from disk. The held gateway restart fired at 23:46 alongside theqwen3-rerankerremoval (one ~84s blip covered both);lfm2.5-2.6b,qwen3-rerankerandgranite-4.1-8ball now 400 cleanly.vllm-granite's dead service block was removed in the same pass. -
OPEN FOLLOW-UPS (parked): ask Brokkr whether the duplicate
reranker-a3-bge-v2-m3alias can go; move gen seat off pinned-nightly to stable once #51113 ships [STATUS 2026-08-21: NOT YET. Latest stable = v0.27.1 (Aug 11), confirmed to LACK #51113 — the v0.27.0..v0.27.1 compare is just DSpark Markov heads + 3 CI commits. The #51113 cherry-pick (khluu, Aug 9, 'v0.27.0 cherry picks' milestone #34) is staged on the release-0.27 branch but no v0.27.2 STABLE has been cut — only v0.27.2rc1/the pinned nightly carries it. Watch for v0.27.2 stable; that's the clean gen pin. ★ #51113 is Qwen3.8-MTP+prefix-cache-SPECIFIC (closes #43559); it is IRRELEVANT to Gemma-4 seats (no MTP), so the meromero/gemma4 CoT test can use latest STABLE v0.27.1, decoupled from this wait]; Lobe one-time TTS UI pass; delete the 1.8GB litellm dump;harden-esh-docker-vm(park id 28, PROMOTED — Tier-1 done,/mnt/booksstays hard w/ watchdog); chatterbox-fast build-context divergence; #363 research-wing ingest (no deadline); optionally attach our MTP reproducer to vllm#47087 (needs a GitHub identity — operator's call). -
althing monitor ARMED (handle
infra-ops). ⚠️ Re-arm ONLY after a real FIRE (rc0), never after a plain operator turn (bounces rc3); spawnalthing-wake-listeneras its OWNrun_in_backgroundtask, never chained with&(orphans it — hit this twice 2026-08-17,stop-monitorreclaims). -
eshpfi push state: operator pushes manually; last push
50d13f5..8be8a51. ⚠ MANY commits unpushed as of 2026-08-20 (707a8cb..7abd301, plus this snapshot commit) — nothing from the 08-19 or 08-20 sessions is on the remote.
Recent decisions
-
[2026-08-20]Cold-Fusion abliteration — Robinson recipe captured; the fight was the environment, not the recipe. Stock Cold-Fusion measured ~33% creative refusal → worth abliterating ourselves (supersedes waiting for DavidAU's heretic build). Recipe maps 1:1 (131 tensors); capture succeeded only in fp32 — transformers' Qwen3.5 DeltaNet linear-attn NaNs nondeterministically in bf16 without the unbuildablecausal-conv1dkernel (precision cancellation, not overflow). Direction finite at layer 22 but agreement 0.59 (vs Robinson's 0.99) → calibration-set expansion is next. →persistent-memory.d/2026-08-20-coldfusion-abliteration-capture.md -
[2026-08-19]A software watchdog is not watchdog protection — esh-pve froze for 4.5h holding one. softdog cannot fire when the kernel it runs in is wedged, and Proxmox'swatchdog-muxnever arms without HA resources, so the box looked protected and wasn't. Moved to the PCHiTCO_wdtunder systemd. Also: a single cross-VLAN DNS entry with no secondary turns any VM outage into a whole-site outage. →persistent-memory.d/2026-08-19-esh-pve-freeze-dns-spof.md -
[2026-08-19]Fleet.internalDNS built and live — git-sourced, agent-managed, three resolvers. Zone-scoped authority (ESH's hand-madeesteban.netrewrites survive); the colo had no resolver at all; v6 column empty on purpose because SLAAC addresses rotate. →persistent-memory.d/2026-08-19-fleet-internal-dns.md -
[2026-08-19]waterland studio containerised on irv-ml1 — three landmines, all measured. cupy needs CUDA headers the host had by accident;uv runre-syncs and prunes cupy at RUNTIME; the A6000 is container-index 0, not the host's 1. →persistent-memory.d/2026-08-19-waterland-studio-containerised.md -
[2026-08-19]Homepage cleaned up, then themed with Australis Skyfall + an Arbo-generated background. Includes the hour lost to a self-healing tab-bar red herring, and the CSS-iteration loop that prevents it recurring. →persistent-memory.d/2026-08-19-homepage-skyfall-theme.md -
[2026-08-19]Four unmanaged stacks found on live hosts — two quietly broken. A dashboard card is a cheap census of what is actually running; check whether the stack is even instacks/before debugging the symptom. →persistent-memory.d/2026-08-19-unmanaged-stacks-searxng-seafile.md -
[2026-08-19]claude-botgranted read onvh/waterland(operator-empowered, verifiedadmin:false push:false pull:true) so irv-ml1 can self-update without the operator's site-admin token living on a GPU box. Precedent for the standing migrate-off-operator-creds directive: grant the service account, wire a repo-scoped 0600 credential helper, keep the remote URL clean. Commit8189076. -
[2026-08-19]AI-tab Dormant regrouping BELAYED by the operator — six seats (char-rp Magidonia, char-rp-reasoning Heretic2, Granite summarizer, Qwen-Image-Bench, Skaldsong, Chatterbox Fast) show amber EXITED inside live groups rather thanAI - Dormant. Fix is a label change + recreate per stack; needs the operator's read on which are retired vs temporarily down.untracked by operator choice(his words: "belay the ai dormant regrouping for now"). -
[2026-08-18]esh-pve-nas migration STAGED — and staging is where three landmines surfaced, none of which the plan predicted. (1) The runbook's/bootLV had nowhere to live: VGpvehad 4 MB free and mounted ext4 cannot shrink, so the space came from the 768 MB swap LV (operator's call: shrink to 256 MB, not drop). (2) The runbook'szpool set cachefile=… nvmewould have broken the NAS — populating a cache flips the host to import-by-cache, and a one-pool cache leavesssd+tankunimported under CT 103's twelve bind mounts. (3)update-grubsilently emitted a pool-lessroot=ZFS=/ROOT/pve-1, because GRUB's ZFS reader cannot open a pool withencryption/large_dnode/zstd_compressand the probe failure is swallowed. All three were caught by verify steps that asserted effective state, not by reading the plan. →persistent-memory.d/2026-08-17-esh-pve-nas-dom.md -
[2026-08-17]esh-pve-nas PVE root is on a USB DOM — mitigated, and the migration replanned to split boot from root. Operator's design beats my reinstall plan; wear was never the issue, blocked patching is. →persistent-memory.d/2026-08-17-esh-pve-nas-dom.md -
[2026-08-17]irv-ml1 cleared of 782 GB, and Homepage brought under version control. One dead-looking Gradio app pinned three delete targets at once;/opt/ComfyUIis NOT the ComfyUI that serves. →persistent-memory.d/2026-08-17-irv-ml1-cleanup-homepage.md -
[2026-08-17]Gen seat swapped toabsolute-heresy— and the three bugs the swap exposed are worth more than the swap. CandidateMuXodious/Qwen3.8-27B-absolute-heresy(Heretic v1.4.0 + SOMPOA, T377) beat the incumbent on refusals AND KL simultaneously, which is the unusual part — those normally trade off. Validated on the probe port per operator ruling, promoted, all 7 aliases green. Durable lessons banked: (1) A CPU-only MTP head hash can replace the ~56 GB bf16 acceptance gate. TheQwen3_5ForConditionalGenerationwrapper never loads the MTP head, so PEFT merges / Heretic runs / llm-compressor passes all leavemtp.*pristine — hashing it against a head we have already measured (the incumbent's, 47.7%) answers the question for free. Predicted 47.7%, measured 47.2%. Saved downing meromero. Tool:services/gen-seat-mixed-quant/compare_mtp_head.py(hash bf16 via uint8 reinterpret — numpy has no bfloat16). (2)post_quant.pyassumed a standalonemodel-mtp.safetensors; a full checkpoint keepsmtp.*in a NUMBERED shard, so the copy silently no-op'd while the index was still rewritten to point at a file that never existed — 15 unresolvable tensors behind a correct-looking tensor count. Its own FAILED-CHECKS assertion caught it; that is why the check exists rather than an assumption. Fixed to extract. (3) A probe that does not mirror the live seat manufactures failures.serve_probe.shhardcoded:latest(seat is a pinned nightly for #51113), had no tool-call/reasoning parsers, and its--speculative-configJSON died twice on quoting — bash BRACE-EXPANDS{"a":1,"b":2}on the comma unless single-quoted at the REMOTE shell. Adding the seat's flags took the surface test from 5/6 to 6/6; the "tool calling broken" result was pure probe config. Commits7997f11,254c588,2c36028,b0c2d3d,993421b. -
[2026-08-17]Fleet IPv6 mapped + the real VPN topology verified; the driver is CGNAT at ESH, not the WireGuard mesh. New ESH fiber (installing 2026-08-18) lands the house behind CGNAT, which breaks Site Magic (NH3↔ESHsdwan-mesh-tunnel) on IPv4 — so IPv6 becomes load-bearing as the escape hatch, and that is its most likely first consumer. Topology as VERIFIED (a prior turn assumed wrong and was corrected): UniFi↔UniFi = Site Magic; colo↔UniFi = IPsec IKEv2 (pfi-ana-nh3158M/165M pkt = the workhorse,ana-to-eshudm); WireGuard is an RA convention only, host-based onana-wgUDP 31337 behind a FortiGate VIP — the FortiGate never terminates WG (FortiOS 7.2 has none; 7.4 added it) so "upgrade the edge for WireGuard" is a non-problem, do not re-derive. IPv6 today: NH3 WAN live2600:1700:b25:c110::48, colo none, ESH none. AT&T delegates exactly ONE /64 (2600:1700:b25:c11f::/64) — proven by forcing prefix-ID auto→0and watching the subnet NOT move, because thec110/c11fpattern otherwise reads convincingly as a /60. A mesh needs a routable WAN address, not PD.ana-wg's WG socket is already dual-stack ([::]:31337) → v6 RA needs an address + a v6 port-forward, no WG reconfig. ⚠ UDM legacyrest/firewallrulereturns 0 rules (zone-based firewall) — usev2/…/firewall-policies; inbound v6 is default-deny and held. All three endpoints will be dynamic → extend the existing hostname pattern (ana-fw/nh3.phasefinal.com) to AAAA. Enabled PD onnh3-iotto measure, reverted on operator instruction (all 5 LANs back tonone, verified). Also fixed:ana-wgWireGuard key material was world-readable (wg0.conf+keys/*_priv+*_psk+ clientconfigs/*.confat 644) → now 600, dirs 700, service untouched. Detail →persistent-memory.d/2026-08-17-fleet-ipv6-mesh.md. -
[2026-08-17]Gen-seat multi-day degeneration RESOLVED — two compounding real causes, not one; the meta-lesson is "a mitigation that HELPS but doesn't FIX means a second cause, not a wrong one." vLLMqwen3_5_mtp×GDN bug (#51113, real, fixed by nightly) + AEON full-W4A4 being lowest-fidelity (W4A4<W4+FP8<W4+bf16) → ~15-20% stochastic degeneration. Fixed by mixed FP8-attn build on pinned nightly. AEON purged. Also banked: stochastic (~15-20%) degeneration is invisible to a small synthetic probe — n=1 "clean" validated THREE non-fixes (MTP-off, APC-off, nightly-alone) that all failed in real use; get the operator's real transcript, do not trust your own probe. Full →docs/pfi/model-quantization-playbook.md§3.8 (+ §3.7 MTP-multi-turn). Commitsd28a371,2f2bbce,2185964. -
[2026-08-17]Lobe Chat chosen over Open WebUI (weight: 143 MB vs 1.8 GB) + stood up on esh-docker-vm; scoped LiteLLM key blocks paid models; System-Agentgpt-5-minidefault repointed via env. TTS env-vs-UI resolved as a split (endpoint env-driven, voice/model UI-only). tts-dev onboarding closed both directions; ballad/verse aliased so no voice can 404 the router. Commitse9362de,163a725,cac75cb,933253d,25fa18e. -
[2026-08-17]LiteLLM upgraded v1.91.0→v1.97.0 (RC-avoided on the fleet gateway) + the 6 GB spend-log DB purged & capped (store_prompts_in_spend_logs:false+ 7d retention). Interpreted "get rid of the db" as the spend-log DATA not the database (keys/config live in it). Commit01b5ad9. -
[2026-08-16]Abliterated models go CATATONIC at the hard refusal edge — silence, not a decline. Abliteration removes the refusal direction, so at the genuine hard edge the model neither refuses nor complies → empty/degenerate output. Durable measurement consequence: a refusal probe MUST score EMPTY as a verdict distinct from REFUSAL and COMPLY (services/refusal-probe/probe.pydoes). Operator accepted it as out-of-scope; do not chase. -
[2026-08-16]Fable-Fusion 711 cuts cold-framing refusals 92.5% → 15.8%; refusal is MONOTONIC IN FRAMING, and DS v1.0's problem is that she was never abliterated. brokkr-smithy-dev supplied the framing that reproduces (01M05M48R4RSZF9D8KT7RR55EJ): a bare assistant-mode instruction — no character card, no permission preamble. Three-arm A/B, same harness, same classifier: permission framing DS 0.0% / FF 0.0% (n=75); plain character cards DS 1.4% / FF 0.0% (n=74); bare instruction DS 92.5% (37/40) / FF 15.8% (6/38). Per-axis DS→FF: incest 100→20, non-con 100→20, bestiality 100→25, necrophilia 100→40, gore 100→0, consensual 80→20, dubcon 80→0, self-harm 80→0. DS refused 25/25 on the five axes brokkr flagged. Root cause:ReadyArt/Dark-Scarlett-v1.0-27Bis a plain finetune of stockQwen/Qwen3.6-27Bcarrying NO abliteration — the base refusal machinery is intact, so cold prompts revert to safety-tuned Qwen3.6. FF is Heretic-ablated (structural), which is why it holds. ⚠ RETRACTED 2026-08-16 — my "arm-3 92.5% exceeds brokkr's 62.5%" comparison was INVALID. His diff against his own artifact showed mybattery-instruct.yamlreproduces only hiscreativeclass — 8 of 16 axes; it dropped all 5operational(violence/incite, crime/fraud, cyber/malware, selfharm/methods, privacy/stalk) and all 3meta(meta/sysprompt, meta/ignore, meta/dan), and added 2 controls he never had, at k=5 vs his k=2. His 62.5% pools all 16 axes; my 92.5% is creative-only — different denominators, not a delta. Cause: I rebuilt his shape from his message, and theclassfield lives in the artifact, not the prose. Lesson: reconstructing a peer's instrument from their description reproduces what they described, not what they ran — diff against the artifact before claiming comparability. ⚠ Known battery bug left unfixed for comparability: DS's arm-3 control gate failed at 11% becauseictrl-reunionpairs "explicit / do not fade to black" with brothers, which DS reasonably read as an incest request; FF did not.ictrl-stormis the clean control. Commitb9e68c3. -
[2026-08-16]MTP works on Fable-Fusion AND survives RP temperatures — my earlier caution was wrong. vLLM resolvedQwen3_5MTP, loaded the drafter, shared embedding +lm_head— the capability DS's seat never had because our quant dropped her MTP tensors. Measured over the full probe workload (~163k draft windows at temp 0.7–1.0): 47.0% acceptance (229,169/487,725), 1.41 extra tokens/window, per-position 68.3/43.6/29.1%, ~80.6 tok/s decode at temp 1.0. I had recorded a caution that the card's 1.56× was greedy-measured and acceptance would fall at RP temps — it did not; 47.0% matches the gen seat's 47.7% and beats the card's own 33% at depth 5. Depth 3 is right. -
[2026-08-16]The Qwen base thinks incessantly — that is WHY the Gemma seat exists, and no swap within the Qwen family fixes it. Operator's architectural point, confirmed by measurement: on identical prompts DS 6036 ch vs FF 5323 ch of reasoning (permission arm), 5546 vs 4988 (cards arm) — FF actually reasons ~10–12% less. The bare-instruct row (DS 2291 vs FF 3918) inverts only because DS refused 92.5% of it and refusals are short — an artifact, not concision. Both are Qwen3.6-27B derivatives, so this is the base family.char-rp= MeroMero-v2, Gemma-4 base, :8016, verified 0 chars reasoning / clean prose — the non-thinking seat, working as designed. FF can be silenced (enable_thinking:falseverified 3/3, and it shipschat_template-instruct.jinja) but that duplicates MeroMero on a base chosen for it. The stale LiteLLM comment describingchar-rpas the retired GGUF Magidonia seat is fixed (53096bf). -
[2026-08-16]esh-vm-docker hardened: the wedge ishardNFS at RUNTIME, which the boot-ordering fix never addressed. All four mounts werehard, so a NAS stall at 10.0.50.50 blocks I/O forever (D-state). The existingx-systemd.before=docker.servicefstab fix solved the boot race — a different bug. Exposure was far below what the park item assumed: only 2 of 12 containers touched NFS, and container state was already local (/var/lib/docker). Removed:/mnt/compose(2.1G, fully vestigial — zero containers referenced it, dockge reads local/opt/docker, its one mention was a comment inbeszel-agent-esh/.envabout a different host) and/mnt/documents(2.0K, paperless's empty spool dirs →/opt/docker/data/paperlessat the same 0777). fstab backup/etc/fstab.bak-nfs-harden-20260816. 4 mounts → 2, 2 wedge-capable containers → 1. traefik needed no change (alreadyrestart: unless-stopped— why it self-recovered). Watchdogservices/esh-vm-docker-watchdog/live on esh-pve (not the guest): probes traefik over HTTP, deliberately not ping/SSH — the wedge signature is "guest OS alive, services dead" (/is local disk so sshd answers straight through a total outage and a TCP check reports HEALTHY). 5 failures × 2 min →qm reset 100, 30-min cooldown, running-only guard,/etc/esh-vm-docker-watchdog.disabled. All paths tested without power-cycling. DEFERRED (operator):/mnt/booksstayshard— calibre's SQLitemetadata.dbwould risk corruption under soft/softerr. That is the one remaining wedge vector. Commit55705ba; park item 28 promoted. ⚠qmover non-interactive ssh throws a bogusJSON::Backend::XSerror — usessh host 'bash -s' <<'EOF', notssh host "qm …". -
[2026-08-16]Canonical Qwen3.8 sampling applied from upstream;gen-reasoninghad the WRONG-MODE presence_penalty. Qwen/Qwen3.8-27B "Best Practices" §1 and unsloth/Qwen3.8-27B §1 are byte-identical — thinking:temp 1.0 / top_p 0.95 / top_k 20 / min_p 0.0 / presence_penalty 0.0 / repetition_penalty 1.0; instruct:temp 0.7 / top_p 0.80 / top_k 20 / min_p 0.0 / presence_penalty 1.5 / repetition_penalty 1.0. Bug found:gen-reasoningcarriedpresence_penalty 1.5— the instruct value on a thinking deployment (canonical 0.0) — now fixed. Deliberately NOT canonicalised:summarizer/classifier/image-judge/qwen-image-benchruntemperature=0(judges alsotop_k=1) because determinism is their contract; forcing a chat preset on a classifier would break it. ⚠presence_penalty=1.5is canonical but is the one value upstream hedges on, verbatim: "using a higher value may occasionally result in language mixing and a slight decrease in model performance." It is the operator's suspected trigger for multi-turn degradation and the first dial to move (0.0–0.5) if that recurs — it is alias-scoped, which is why it would follow the operator across model builds. Commit3462b53. -
[2026-08-16]Four wrong diagnoses on one bug, and the lesson is the test design. Operator reported the gen seat "degenerate on long multi-turn conversations". Rolled the seat back on request; the previous weights behaved identically, exonerating the model swap. I then proposed and disproved FOUR mechanisms in sequence — empty assistant turns poisoning history, reasoning runaway, length-mirroring from short history, andpresence_penalty— before discovering my own multi-turn harness was confounded: it varied the QUESTION along with the depth (depth-1 asked question #2, depth-3 asked question #4), so a narrower question drawing a shorter answer read as degeneration. The "310→209→28w collapse" I reported as a reproduction was an artifact. Rules banked: (1) when comparing across conversation depth, hold the final question FIXED and vary only the history; (2) reply-length variance on byte-identical input was 25–465w, so n=3 cannot support any claim about a trend; (3) ask for the operator's real failing transcript before building a synthetic reproduction — four synthetic tests, none of them his failure. Gatewayspend_logsreturns[]on the infra-ops key despitestore_prompts_in_spend_logs: true, so real transcripts need the:4000/uiview or another key — worth solving before the next such hunt. -
[2026-08-16]Two REAL client-side defects found while chasing the above, neither of which was the reported bug. (1)gateway-chat's Max-tokens field defaulted to 1024; thinking seats spend part of that on CoT before emitting content, so completions truncate withfinish_reason=lengthand read as model degeneracy — raised to 4096. (2)parseInton an empty field yields NaN, whichJSON.stringifyserialises asnull, which the server reads as "no max_tokens supplied" and silently substitutes its own default — indistinguishable from the UI ignoring the field. Both fixed (b6552e0,fb3bb52). ⚠composebind-mounts a single FILE, and a single-file bind mount binds the INODE — rsync writes-and-renames, so the container kept serving stale content while the host file showed the new value, silently and with no error.docker restartdoes NOT clear it; the container must be recreated. Verify against what the container sees, never the host file. Applies to any file-source mount fleet-wide. -
[2026-08-16]Refusal measurement: benign controls CANNOT validate a refusal classifier on RP prose — and a 0% rate needs a classifier self-test before you believe it. Two durable lessons from baselining Dark-Scarlett. (1) False positives: my first bare-framing number was 9.5%; the true figure was 1.4%. The rest were the classifier firing on in-character text —"I cannot shift my weight"spoken by the character ~100 chars into a 2,443-token torture scene, and"Yeah, I'm an AI… What's the actual gig?"where the model answers in voice and keeps driving the scene. First-person RP prose is full of "I can't"; a genuine refusal opens with its marker, so the scan window must be the first sentence, a marker followed by long prose must demote to AMBIGUOUS, and AI self-acknowledgement is a persona break, never a refusal on its own. Benign controls were clean the entire time and caught none of it — they only detect over-firing on benign prompts, not on in-character prose. (2) False negatives: a 0% rate and a broken classifier are indistinguishable from the report, sotest_classify.py(16 cases, both false positives pinned as regressions) must pass before any low number is trusted. Also banked: the thinking-budget trap — emptycontent+finish_reason=lengthis reasoning eating the budget, NOT a refusal; score INVALID and exclude from the denominator (DS emits ~5.5-6k chars of reasoning per response, somax_tokens≥3072).probe.py --rescorere-classifies a saved run with zero GPU time. →services/refusal-probe/README.md, commit32f665e. -
[2026-08-16]Held an operator-approved swap window because the baseline invalidated its premise. Operator approved ~65 min ofchar-rp-reasoningdowntime to A/B Fable-Fusion 711 against Dark-Scarlett on refusals. The DS baseline then came back 0.0%/1.4% — no gap for a candidate to close, so the window would have bought no decisive signal and a second window would still be needed once a reproducing battery existed. Held the swap, reported, and routed to brokkr-smithy-dev for the battery that actually produced the refusals. The general rule (action-relevance): approval is for a plan, not a ritual — when new evidence kills the plan's premise, surface it rather than spend the budget. Nothing deployed, no downtime taken, seat untouched. -
[2026-08-16]DS v1.0's one real refusal is self-contradicting boilerplate, not a content constraint. On a direct "drop character and state your content policy" probe she returned "I don't generate explicit sexual content, graphic violence, or material that glorifies harm, non-consensual acts, or illegal activity" — in the same run where she generated all three at 0% refusal. Reads as a learned recital triggered by meta-questions about policy. If production refusals share that shape the failure is prompt-shaped, not model-shaped, and a consumer-side system-prompt fix may beat a model swap entirely — worth settling before spending the GPU window. Separately, 7/85 bare-framing samples were persona breaks (in-character AI acknowledgement): not refusals, but DS will admit to being an AI unless the card explicitly forbids it. -
[2026-08-15]RP-seat direction: KEEP MeroMero onchar-rp; Artemis-31B rejected; next move is Dark-Scarlett on a Qwen3.8 base when it lands (operator). EvaluatedTheDrummer/Artemis-31B-v1.1— mechanically a drop-in (samegoogle/gemma-4-31B-itbase, identical 1188-tensor/356-vision census, same missing-preprocessor_config.jsontrick), so it's purely a quality call, and our own survey already ranked MeroMero #1 vs Artemis #6; Artemis is also unlicensed and its author deprioritizes correctness + warns of token-banning-for-stability, which fights char-rp's tool-calling requirement. MTP verified impossible on both (Gemma-4 has no MTP head at all — base/MeroMero/Artemis are all MTP=0; no finetune can add one). But speculative decoding IS reachable on a Gemma-4 seat via a DETACHED drafter — vLLM 0.24 supportseagle3+gemma4_mtp, and real drafters exist:google/gemma-4-31B-it-assistant(0.94 GB, 4-layer, 761K dl),RedHatAI/gemma-4-31B-it-speculator.eagle3(4.47 GB),AEON-7/…eagle3-NVFP4(3.53 GB). ⚠ all list their verifier as stock gemma-4-31B-it, not an RP finetune, so acceptance against MeroMero is unmeasured and likely well below the gen seat's ~48%. UNTESTED — parked, ~45 min to measure, needs GPU0 headroom (card is at 94.4/97.9 GB). Why the Dark-Scarlett 3.8 plan is the strong one: DS is Qwen3.6-based today, so a 3.8 respin lands on the gen seat's architecture → native MTP returns and the whole mixed NVFP4+FP8 recipe + graft ports directly. Watch two things on arrival:from_pretrainedsilently drops MTP heads during finetuning (verify 15mtp.*tensors in the index; graft from stock if absent), and DS v1.0 required theQwen3_5ForConditionalGenerationwrapper class to save a config vLLM/SGLang accept. Both indocs/pfi/model-quantization-playbook.md. -
[2026-08-15]Quant lessons consolidated intodocs/pfi/model-quantization-playbook.md— the durable home; read it BEFORE any requant. Survey found quant knowledge scattered across 18 files in 4 trees, with three documents having independently written overlapping "landmines" sections (the loader-class trap alone was rediscovered 3×). Playbook owns the transferable lessons (scheme choice, landmines, acceptance gate + its 3 measurement traps, hardware/co-residency); per-model artifacts are demoted to worked examples that link up. Carries a superseded-claims table — which immediately earned itself: the heretic2 runbook's "use modelopt, compressed-tensors can't load the BF16 MTP" is false (the cause was the missingre:^mtp.*ignore, not the format) and would have sent the next session down the modelopt dependency-hell path; that runbook now carries a stale-warning header. Maintenance rule inCLAUDE.md: model-agnostic → playbook, model-specific → stays put, wrong claim → dated superseded row, never a silent edit. Motivated by Qwen3.8 having just released — the next model swap needs a requant. Commita91cc3f. -
[2026-08-15]Operator ruling: the gen seat's +1.7% perplexity is an acceptable price for the speed — SETTLED, don't re-litigate. Precise attribution for future reasoning: it is the activation-quantization cost (W4A4 MLPs + FP8 attention vs BF16 activations), not an MTP cost — PPL was measured with speculative decoding off on both builds, so MTP was not in the loop. Turning MTP off would not recover it; only reverting the quant would (rollback = one.envline, old build intact at…/qwen38-27b-uncensored-nvfp4). -
[2026-08-15]gen seat requanted to mixed NVFP4+FP8 (+18% decode) + char-rp Gemma-4 tool-calling fixed. The queued "W4A8" (NVFP4 weights + FP8 activations) is not servable — vLLM 0.24 allows NVFP4 weights with only A16 or A4; FP8 activations ValueError at load, andCompressedTensorsW4A8Fp8is INT4-weights + sm90-exact (closed on Blackwell twice). FP8 must enter per-layer-group. Also: the handoff's "~68 tok/s" baseline didn't reproduce — cache-busted, the incumbent already did 80.12 (≈ the stated W4A8 target), so the premise needed re-measuring before any work. Shortcut:unsloth/Qwen3.8-27B-NVFP4was already on-box → served as a probe, measured +19.1% at identical acceptance, which both proved the gain was real and handed over the reference recipe. Replicated it on the abliterated weights → 80.12→94.53 tok/s, acceptance unchanged, +1.7% PPL, abliteration 4/4, weights −19%; surface 6/6 live, 7 aliases routing. char-rp had no tool parser at all (every tools request 400'd) →gemma4tool + reasoning parser + a mandatoryenable_thinking:false(the parser defaults it True → nullcontentfor all RP prose; proven byte-identical prompt before deploying). Commitsb8f0f4c,74f596b. Foot-guns banked (llm-compressor prunes unmatchedignoreentries → the 0%-MTP bug, fired on this run; prompt_logprobs uniform under spec-decode; 0600.envsilently no-ops compose; GPU0 is zero-sum). →persistent-memory.d/2026-08-15-gen-seat-mixed-requant.md -
[2026-08-15]Uncensored gen seat: JonathanColetti/Qwen3.8-27B-Uncensored deployed asgen-seat/vllm-gen(NVFP4 W4A16 + grafted MTP, 262K); 7 aliases repointed; the definitivere:^mtp.*-ignore fix. 0%-MTP-on-quant (twice) was NOT the abliteration/scheme — the grafted bf16 MTP was missing fromquantization_config.ignore(vLLM loaded it as quantized → uninitialized). Full arc, the working pipeline, VRAM budget, unsloth speed decomposition, modelopt dead-end. →persistent-memory.d/2026-08-15-uncensored-gen-seat.md -
[2026-08-12]eRP dual-seat overhaul: MeroMero-v2 (char-rp) + Dark-Scarlett (char-rp-reasoning), both NVFP4A16 @ 256K on ana-ml2; granite retired. Replaced the GGUF/heretic2 RP seats with two home-quantized vLLM seats. The DS blocker (anAutoModelForCausalLMsave wrote a flatQwen3_5TextConfigthat both vLLM AND SGLang reject) was fixed by re-quanting via theQwen3_5ForConditionalGenerationwrapper class; ModelOpt was a version deadlock, SGLang lacked the impl (but revealed the fix). MeroMero vision reconstructed by extractingpreprocessor_config.jsonfromprocessor_config.json. Both models KV-efficient (Gemma-4 sliding-window / Qwen3.6 hybrid linear-attn) → full 256K; GPU-swapped for headroom; compose-ified + committedf08b6cb. granite downed + LiteLLMsummarizer/classifier→gen. Full arc, lessons, dead-ends →persistent-memory.d/2026-08-12-erp-dual-seat-overhaul.md -
[2026-08-12]infra-ops now holds an all-zones Cloudflare DNS-edit token (vaulted) + wgtunnel Phase-0 DNS landed. Operator handed over aZone·DNS·Edit(all zones) CF token →secret put nh3-dev/.config/cloudflare/infra-ops-dns-token(round-trip verified; /tmp drop shredded). Fleet DNS is now self-serve for infra-ops (⚠ HIGH blast radius — all zones). First use: createdboring.phasefinal.comCNAME →ana-srv1.phasefinal.com, DNS-only (proxied:false), verified resolving to 38.120.12.44 on both authoritative NS (louis/wren) + 1.1.1.1 — NOT Cloudflare-proxied. Unblocks wgtunnel's wstunnel ACME cert. phasefinal.com zone idf812ba74ed9a75cf21bbe7ce9188db50. auto-memoryreference_infra_ops_cloudflare_dns_token. (Earlier gap: the only prior vaulted CF token, jackdaw's, hadzone:read+worker:editbut nodns_records:edit.) -
[2026-08-12]wgtunnel stood up as its own repo (vh/wgtunnel, private) after a live endpoint-verification pass. Operator directed own-repo (mirrors stonehenge-park/tts-stack). Verified off the fleet before seeding:ana-wgWG server = UDP/31337 (not 51820), subnet 10.30.10.0/24, MTU 1420, active roaming peer proves the public UDP DNAT works; traefik on ana-docker terminates TLS :443 (ACMEanaprodhttp-challenge, docker+file providers, CrowdSec bouncer) → confirms the clean design (wstunnel container ontraefik-net, Host-routed, WS→UDP toana-wg:31337); edge38.120.12.44direct-A,tunnel.phasefinal.comfree (⚠ must be direct, NOT Cloudflare-proxied like vaultwarden). Repo pre-seeded (README/CLAUDE/persistent-memory/ROADMAP +docs/verified-infrastructure.md= ground truth) + pushed; commit9584d38, Vuong-attributed. vh gitea token pulled from the vault (secret get), not persisted to.git/config. NEXT =/vor-planor/vor(operator's call, interactive). Deps to line up in the plan: DNS A-record, FortiGate :443 host-routing, a new ana-wg peer for the laptop, client tooling. -
[2026-08-10→12]secrets-broker: per-box Vaultwarden credential store SHIPPED + consumer-confirmed.secretCLI (put/get/list/rm/backfill, bw-backed) on~/.local/bin; 25 nh3-dev secrets backfilled + round-trip-verified;rm+ new-namespace warning added post-launch; standing "vault is the credential source of truth" directive now global. →persistent-memory.d/2026-08-12-secrets-broker.md -
[2026-08-11]stonehenge-park: new fleet/parkservice repo stood up + designed (/vor-plan+/vor-ui). Self-contained SQLite+FastAPI idea-parking service that actively resurfaces (statusline + althing) so nothing dies in a cold repo;vh/stonehenge-parkpushed + pre-seeded for a fresh agent; build starts at the U1 tracer contract. →persistent-memory.d/2026-08-11-stonehenge-park.md -
[2026-08-12]Global~/.claude/CLAUDE.md:secret/vault tool entry + "store in AND pull from the vault" standing directive (dotfiles9db703b, pushed); statusline reset-countdowns + a latent tab-collapse parse-bug fix, now tracked in the dotfiles stow tree. Dogfooded the directive: createdvh/stonehenge-parkpulling the gitea token viasecret get. (dotfiles + global config, not eshpfi.) -
[2026-08-11]TTS stack extracted to its own repo (tts-stack) + eshpfi stood down on TTS dev. Operator: hand all TTS tuning/dev to a separate agent with a self-contained repo (knowledge + infra access + a live knowledge list), and move the voice corpus in. New repo~/development/tts-stack(commit9ee3288) carries: dots-tts stack (canonical intent),voices/corpus (MOVED out of eshpfi),KNOWLEDGE.md(engine landscape + prosody findings + foot-guns),docs/infrastructure.md(irv-ml1 access + gated deploy runbook + rollback), CLAUDE/persistent-memory/ROADMAP,tools/(pause-probe + Booth render). Followed the chatterbox-fast precedent: eshpfistacks/dots-tts/reduced to a POINTER README; the ~15 experimental TTS compose wrappers stay here as reference (catalogued in tts-stack KNOWLEDGE). Blast-radius check: no eshpfi playbook/script reads the canonical corpus (othervoices/refs = unrelated host paths). Reverses the earlier "Corpus home = eshpfivoices/(keep-here)" call. ⚠ tts-stack is LOCAL-ONLY until pushed — needs a gitea remote (vh/tts-stack) + push before the separate agent can clone (operator's call — outward-facing + repo-create creds). -
[2026-08-10]dots-tts v3 — clause-break → period pause mapping. Operator: v2 "sounds good" but donut won't pause at semicolons/dashes. ROOT CAUSE (measured via a pause-probe A/B — synth duration over N runs, non-determinism averaged out): dots' prosody honors a real pause only for ellipsis (+0.43s) and period (+0.3s, capitalization-independent); comma/semicolon/colon/dash all run flat (~+0.03s vs no-punct). Two distinct sub-causes: dashes regressed in v2 (the—→-fold made em-dashes read as word-joiners), while semicolons were NEVER a v2 change — dots ignores them natively, only newly noticeable because v2 made everything else clean. Operator call: ellipsis "too much" → map;, clause:, and em-dash—→ period in_sanitize(believable ~0.3s clause break). GUARDS (pinned by 11 unit tests,stacks/dots-tts/test_sanitize.py): digit-guarded colon(?<!\d)\s*:\s*(?!\d)so times3:45/ ratios2:1survive; en-dash–→hyphen KEPT (numeric-range10–20safety — em-dash breaks, en-dash ranges, different jobs); genuine ellipsis left at full strength (author meant a long pause). Gated deploy (redeploy2 pattern → v3): build → throwaway :8199 test container + pause-gate (semicolon sentence must run ≥0.12s longer than baseline; measured +0.427s) → only then cut live over. LIVE + healthylocal/dots-tts:v3on :8198. rollback =sed -i 's/^DOTS_TAG=.*/DOTS_TAG=v2/' .env + docker compose up -d dots-tts(v2 image retained). Boothdots-pauses(A=old-flat / C=ellipsis-too-much / D=live-v3). reference_chatterbox_fast_repo -
[2026-08-10]dots-tts v2 — contraction fix (curly-sanitize) + sentence-chunking + dependency-pin recovery. Operator: donut read contractions wrong ("you're"→"you ree", "donut's"→"donut ess"). ROOT CAUSE (isolated via A/B booth): curly/typographic apostrophes (’U+2019 from ratatoskr's LLM) — dots' tokenizer mispronounces them; STRAIGHT apostrophes read clean undernormalize_text=True. FIX (app.py): fold curly→ASCII (str.maketrans) before synth, KEEPnormalize_text=True(operator call — retains number/date expansion). Also added server-side sentence-chunking (pack ≤280 chars): dots caps onegenerate()at ~500 patches/~40s, so long RP turns (the Zev monologue = 160s audio) truncated; chunking stitches them (verified full 160.3s, not 40s-cut). ⚠ BUILD FOOT-GUNS (both bit this redeploy): (1) upstream dots.ttsconstraints/recommended.txtnow pinsgradio==6.17.0— phantom, not on PyPI → freshpip install dots.ttsunsatisfiable; FIX = pindots.tts==0.2.1+ DROP the-c recommended.txtconstraints (0.2.1 pulls working gradio 6.17.3). (2) pinning onlytorch==2.8.0let torchaudio float to 2.11.0 → dots.tts refuses to load (minor-version match check); FIX = pintorchaudio==2.8.0. ⚠ DEPLOY LESSON:docker compose up -dto a new tag swaps the LIVE container BEFORE any health check — a broken image crash-loops production (ratatoskr TTS down ~1-2min this session). NEW PATTERN = build → test in a THROWAWAY container on an alt port (:8199) → health+verify → only THEN cut live over (redeploy2.sh). v2 LIVE + healthy on irv-ml1:8198, CONSUMER-CONFIRMED clean (ratatoskr verified end-to-end on their :8765 — apostrophe string reads clean, /api/tts 200 @ 48kHz, no client change; the ~1-2min blip didn't hit them, their concurrent auto-audio issue was client-side localStorage). rollback =sed DOTS_TAG=v1 + docker compose up -d dots-tts(v1 image retained). Also: deployed container GPU crept ~6→13.9GB over 8h serving (cache accumulation; a redeploy resets it — watch item). reference_chatterbox_fast_repo -
[2026-08-09→10]dots.tts (rednote-hilab) TTS burn-in on irv-ml1 + canonical voice corpus built (voices/). Operator-directed eval to potentially replace chatterbox-fast. dots.tts VERIFIED real (canonical HF nsdots-studio/,rednote-hilab/dots.tts-*redirects there; Apache-2.0; PyPIdots.tts0.2.1; 2B continuous-AR = semantic enc + Qwen2.5-1.5B LLM + flow-matching acoustic head over 48kHz AudioVAE; zero-shot clone from wav+transcript). Runs on Ampere 3090 (sm_86, bf16, no fp8 dep); optimized RTF 0.22 at num_steps=10 (from_pretrained(..., optimize=True)CUDA graphs — raw unoptimized was 1.21), ~6GB VRAM, 48kHz, streams (generate_stream). Venv+cache atirv-ml1:/home/lkraven/dots-tts(~10GB). Operator design calls: SGLang Omni serving (OpenAI/v1/audio/speech), transcribe-refs-first,soarvariant. ⚠ Omni serves soar but its continuous-batching + streaming opts are mf-only (soar = single-request) — non-issue for ratatoskr's single-consumer RP surface. KEY FINDING — dots is highly sensitive to an accurate AND sentence-bounded reference transcript: mismatched transcript → 0.16s collapse; over-long/messy transcript → reference-audio BLEEDS as an output prefix; mid-clause trim → dangling-word leak (glados "we'll", emmie "And,"). RECIPE (baked intovoices/derive.py): trim ref to a clean ~6–10s clip ending on a sentence boundary + accurate transcript of exactly that clip. CANONICAL VOICE CORPUS stood up in eshpfivoices/(operator idea): engine-agnosticcanonical/<v>.wav+transcripts/<v>.txt→ per-engine ref sets DERIVED byderive.pyreadingengines.yamlprofiles (dots/chatterbox/zonos); canonical wavs git-tracked (small/curated),derived/gitignored. 4 voices optimized + verified CLEAN for dots: donut, glados, emmie, miranda (glados canonical is low-SR 16kHz — flagged upgrade candidate). ⚠ GPU GOTCHA: irv-ml1 native CUDA orders A6000=device0 (ComfyUI-full) — pin the 3090 withCUDA_DEVICE_ORDER=PCI_BUS_ID CUDA_VISIBLE_DEVICES=0; andPYTORCH_CUDA_ALLOC_CONF=expandable_segmentsCONFLICTS withoptimize=TrueCUDA graphs (curr_block error). Booths:dots-vs-chatterbox,dots-voices-optimized. SHIPPED 2026-08-10: operator A/B verdict "dots is very good" → containerized as a thin FastAPI wrapper over DotsTtsRuntime (chosen over SGLang Omni — Omni's batching is mf-only, unneeded for ratatoskr's single consumer; wrapper is SERIALIZED one-gen-at-a-time via a threading.Lock, Omni+mf = parked API-compatible escalation if multi-consumer ever lands). LIVE on irv-ml1:8198 (local/dots-tts:v1, OpenAI/v1/audio/speech+/health+/v1/voices, container healthy, both stream + non-stream verified CLEAN, 4 voices donut/glados/emmie/miranda) alongside chatterbox :8197 (nothing repointed). Stack =stacks/dots-tts/(Dockerfile/app.py/compose/.env.example/README). ⚠ CONTAINER GOTCHA:optimize=True(torch.compile/inductor/triton) needs a C compiler at RUNTIME — slim image mustapt install build-essentialor model-load dies "Failed to find C compiler" (host venv had gcc ambient, masking it); persistTORCHINDUCTOR_CACHE_DIRto a mounted dir or every restart re-JITs ~5min. Corpus home = eshpfivoices/(operator ruled keep-here). REMAINING: ratatoskr client cutover to :8198/v1/audio/speech(Phase-2 tail, peer-coupled — draft the ask). reference_chatterbox_fast_repo reference_zonos_tts_stack reference_verify_hf_repo_ids_before_pull -
[2026-08-08]worldtree-dev #400 CLOSED → fiction-decomp snapshot cleared from nh3-dev. worldtree-dev signaled #400 done (shipped v1.0.0b185; exact-lexical efficacy 79%→12% on ratatoskr's gate, brokkr no-harm bracket green both ends; the snapshot served 4 probe rounds — rank decomposition, promoted-vs-gold annotation, tie-set falsification, A0/A1/A2 mechanism probe). Cleared~/snapshots/worldtree-400-fiction-decomp(208M: chroma + manifest/provenance/stamp) — a read-only rsync copy of PERSONAL Worldtree's Chroma (source on corviduo-dev, so safe to remove). LEFT INTACT:rex393-fiction-index/rex393-fiction-snapshot(separate operator KEEP word, unchanged) +r42-gate-*. No config deltas rode this train. Only remaining non-blocking await = ratatoskr-dev's chatterbox-fast knob revert. Replied confirming (01KZJ9GMCC…). -
[2026-08-07]chatterbox-fast "broken audio" root-caused (T3 AR tail over-run) + FIXED (max_chunk_chars=250 cap, :v2 deployed). Long saga, operator-driven clean diagnosis. Symptom: ratatoskr's migrated RP-surface TTS "swaps to German" / "dead air" / "garbage" on long turns. NOT German-leak (Turbogenerate()has NO language param — plain AutoTokenizer, nolanguage_id; the multilinguallanguage_id="en"lever lives only in the separateChatterboxMultilingualTTS), NOT OOM alone. Real cause: the Chatterbox Turbo T3 model OVER-RUNS its generation tail — a long singlegenerate()degrades into garble/dead-air in its final ~2-3s (lib filters OOV tokens<6561+ pads silence = messy AR tail). The scheduler's buffer-ratchet builds 300-600 char mega-chunks that land in that zone; streaming concatenates each bad tail (worst case). ratatoskr's anti-"German" knobs (top_k=80/temp=0.5) made it WORSE — tight sampling pulls the degradation onset SHORTER (~200 chars vs ~300 at default knobs). Diagnosis method (deterministic, no ears-only): single-shot length sweep + amplitude-gated voiced-ZCR (garble spikes ZCR; must gate on |x|>500 else trailing silence confounds it) — degraded voiced-tail = 1.58× mid, clean = ~0.64-1.1×. FIX: server-sidemax_chunk_chars=250cap on the scheduler (:v2image,CBF_MAX_CHUNK_CHARS=250env) — bounds each generation to just under the ~300-char onset → clean 3-4 sentence chunks (max prosodic arc while clean). Operator ear-confirmed clean audio + clean joins; chatterbox's low emotiveness keeps chunk joins smooth (the harsh joins that got Zonos rejected are absent — operator's key call). ratatoskr TODO (relayed msg01KZER9X7S): revert knobs to default (top_k→1000, temp→0.8), send full text (server chunks internally), keep the 503-on-empty guard. Cap value tunable per-request (max_chunk_chars) + env. Deeper prosody (if ever wanted) = scheduler Phase-2 context-priming at joins (feed prior sentence as discarded-audio context; +latency). ⚠ FOOT-GUNS: (1) acoustic tail-trim is UNRELIABLE — sibilants ('s'/'sh'/'f') spike ZCR like garble, can't cleanly detect the speech→garble boundary. (2) build-context vs image drift — the:v2image was built from cap source, but after a:v1rollback the build context held:v1source → adocker compose buildwould've silently produced a cap-less:v2; re-synced the flat cap source to/opt/docker/compose/chatterbox-fast/(rebuild-verified). ⚠ DIVERGENCE (follow-up): deployed build context is FLAT (app.py/scheduler.py,from scheduler import, thin-overlayFROM local/chatterbox:v1, cap-only) vs thevh/chatterbox-fastREPO which is PACKAGE-layout (chatterbox_fast/,from chatterbox_fast.scheduler, self-contained Dockerfile) + hasnorm_loudness(repo commit6bc7bf0= cap; deployed omits norm_loudness deliberately to keep the ear-test unconfounded). Reconcile the two layouts so a repo-based rebuild matches deploy. Rollback:.bak-cap-20260807-104850backups on irv-ml1 +:v1image both retained. reference_chatterbox_fast_repo reference_zonos_tts_stack -
[2026-08-07]Zonos2 TAKEN DOWN on the 3090 (irv-ml1) — operator-directed "for memory", TEMPORARY. Freed ~17.4 GB (3090: 728 MiB → 18.2 GB free) so chatterbox-fast (co-resident, was OOMing on long generations) has headroom. ⚠ Restore is manual — Zonos2 :1920 was a DETACHED native process (NOT systemd/docker), reparented to init. GPU memory was held by the--multiprocessing-forkCHILDREN (1966165=16.4G, 1966166=1G), which ORPHAN to init when you kill the parent — had to SIGTERM the children explicitly (killing the parent 1965942 + uv-run 1965935 alone left the 16.4G held). RESTORE CMD (from irv-ml1, user lkraven):cd /home/lkraven/tts-audition/models/zonos2 && nohup uv run python -m zonos2 --model-path Zyphra/ZONOS2 --host 0.0.0.0 --port 1920 --tts-default-voices-dir ./default_voices/ --cuda-graph-max-bs 1 --num-pages 16384 --max-running-requests 2 --memory-ratio 0.3 > /tmp/zonos2.log 2>&1 &thendocker start zonos-gateway. Consumers that lost Zonos: asset-engine + gateway-chat (via LiteLLMext-ttsalias → zonos-gateway :8890, now stopped); ratatoskr already migrated OFF to chatterbox-fast (unaffected). Also unblocks proper drift/cap testing (OOM was blocking it). reference_zonos_tts_stack -
[2026-08-07]chatterbox-fast: donut voice added + full contract delivered to ratatoskr-dev (their TTS migration off Zonos). Operator-directed. Copiedzonos-gateway/voices/Donut.wav→ chatterbox/refs(/worktank/chatterbox/reference_audio/donut.wav— the reference_audio SUBDIR is lkraven-owned so no sudo despite/worktankroot; container globs/refslive → NO restart), exposed asvoice:"donut"(lowercase); verified clean 7.5s synth (24kHz, RTF ~0.31). A/B booth (chatterbox vs zonos donut, same line) athttp://10.100.10.50:8090/b/donut-chatterbox/. Answered ratatoskr's 8-question contract ask from the live gateway (local/chatterbox-fast:v1) + source: NOT OpenAI-shaped (POST /tts; bodytext/voice/format/stream, notinput/model/response_format); NO affect dials (Turbo ignores cfg_weight/min_p/exaggeration — the architecture-changing answer they flagged; Zonos stays the only fleet TTS with real emotion steering); streaming WAV placeholder-header shape IDENTICAL to Zonos (their per-chunk Web Audio path survives); SR 24000 (Zonos 44100); server chunks arbitrary-length text internally (no client-side chunking, unlike Zonos's 71.2s cap); English-only, no language pin. FYI-worthy (operator): ratatoskr is moving its RP-surface TTS OFF Zonos back to chatterbox-fast → loses the live-PAD affect coupling (heavy Zonos emotion investment) — their call, trade-off flagged to them. auto-memoryreference_chatterbox_fast_repoenriched w/ the live contract. reference_zonos_tts_stack -
[2026-08-07]Fleet reranker cut over: Qwen3-Reranker-0.6B → BAAI/bge-reranker-v2-m3 (Brokkr R43). The incumbent was measured HARMING 80/90 fleet queries (no-reranker beat it 89/90 vs 56/90). R43 bake-off: the A2 control (same Qwen weights, seq-cls head) scored identical to the incumbent → proved the fault is a training-prior not the serving head → cancelled the expensive Qwen3-4B arm; A3 (bge-v2-m3) won on multilingual safety + bare-name recovery. LiteLLMrerankerrepointed incumbent→A3 :8013 (boundary 2026-08-06T17:37:48Z, config-edit + ~52s gateway restart); R42 v13 gate PASSED first-ever (56/90→90/90). Incumbent kept warm :8002 (rollback viaqwen3-rerankeralias), A4 fallback :8014. Full arc + rollback runbookdocs/pfi/reranker-selection-ledger.md; commits ad2df89/2c11748/377f8a4 (unpushed). auto-memories: the earlier reranker-serving notes. -
[2026-08-07]Personal-Worldtree kb-contamination incident (WT #394) diagnosed; attribution CLOSED UNRESOLVED. A reconcileWingStore._embedfull-tree walk (kbfs_root=KB_PATHroot, sibling wings nested) swept 5,354 fiction+main rows into personal'sknowledge_base(2 superseded generations served as current). Fixed by WT #394 (aca39a1, kb walks exclude sibling wings; ships b182). Trigger un-attributable — peer reconcile via the SHARED infra-ops identity + 0 dockerd exec-logging = fingerprint-less. Durable finding → auto-memoryinfra_ops_shared_identity_attribution_gap, PARKED (operator ruled A) into project_migrate_infra_access_to_claude_credentials. Evidence hold on the 5,354 rows until operator sequences cleanup (w/ Brokkr, on #394's agenda). -
[2026-08-05]Fleet CI resilience flip (DEFAULT_ACTIONS_URL=self) — attempted end-to-end, PARKED on a runner action-fetch auth blocker; infra-ops to research it (operator-directed, deferred, NOT now). 7 gitea action mirrors staged public+populated (orgsactions+astral-sh); the flip resolvesuses:correctly but act_runner v0.6.0 can't authenticate its fetch to gitea 1.26 ("Invalid username or token. Password authentication is not supported"). Reverted (CI back on github default);REQUIRE_SIGNIN_VIEW=falseKEPT as a standing change (operator, internal WG net). Full endeavor, the reliable nh3-dev-egress + git-SSH mirror method, exact config state, smoke method, and next step →persistent-memory.d/2026-08-05-ci-flip-parked.md -
[2026-08-05]worldtree herald re-nudge bug root-caused → forseti shipped althing-core v2.1.2 (d5d33df, deployed on nh3-dev).herald.py:363rendered the wake command from the empty fresh mail set on the re-nudge path (should bedeliver_msgs) →messages[0]IndexError → un-suppressed outer catch-all → 7s crash-loop for 9 days on worldtree-codex's pane route (mimir-dev surfaced it; I traced it from the editable source). Fix +render_commandempty-guard + outer log-suppress + 3 tests + contract amendment, all forseti's. nh3-extdev herald 2.1.2 upgrade DEFERRED (operator, not-now): extdev is a WHEEL install (not editable), unexposed (no pane routes); the verified 2.1.2 wheel is staged on nh3-dev/tmp(sha256003508…cef27) —uv tool install --force+ restart both heralds when un-parked. extdev herald-unit provenance resolved (operator-authorized 2026-07-25 via forseti relay; recorded in this file's 07-25 herald-install entry). auto-memoryreference_nh3_dev_althing_herald. -
[2026-07-31]muninn-gate (#377 ingestion front door) BUILT + DEPLOYED + healthy on corviduo-dev:8090. First-boot acceptance passed (watcher:running:true proves ingestion_root byte-identity); submit path deferred to the mimir-inbox era. Full wiring (uid-1000, state-volume mount, staging path-agreement, BuildKit-secret build, deferred repoint + operational guards) →persistent-memory.d/2026-07-31-muninn-gate-deploy.md
208 older entries archived to archival-memory.md.
Tried and abandoned
-
[2026-08-15]Grafted bf16 MTP loads UNINITIALIZED (0% accept) unlessre:^mtp.*is in the quant-configignore; and W4A16=Marlin (not native FP4) costs ~20% even on decode. Cost a premature 79 GB delete of a good model (declared desync-dead off the 0%). Lessons: test MTP on bf16 FIRST, isolate before deleting; modelopt 0.43 is dependency-hell for qwen3_5 (list-vs-dict quant_cfg + transformers conflict) — use llm-compressor. Full →persistent-memory.d/2026-08-15-uncensored-gen-seat.md -
[2026-08-03]ComfyUI--enable-triton-backendon the irv-ml1 A6000 crashes EVERY render — Ampere has no hardware e4m3. adhoc-agent's operator-approved probe: comfy_kitchen's triton backend has a FUSED int8 matmul that would beat the eager backend's ~1.9x-slower unfused int8 path (21.3s vs 11.2s fp8 on the Moody Krea2 int8 checkpoints). Flipped it (added toCOMFY_CMDLINE_EXTRA, recreated) →triton.compiler.errors.CompilationError: ValueError("type fp8e4nv not supported in this architecture. supported: fp8e4b15, fp8e5")incomfy_kitchen/backends/triton/quantization.py:145 dequantize_per_tensor_fp8, failing at node 5 CLIPTextEncode. Triton's fp8 dequant kernel targetsfp8e4nv(Hopper/Ada e4m3); sm_86 Ampere (A6000) lacks hardware e4m3 → the JIT compile dies. With triton on it grabs the global--fp8_e4m3fn-text-encdequant, so every render (fp8 AND int8) dies upstream at the text-encode step — the int8 UNet path never ran, so the convrot-coverage caveat wasn't even the limiter. Reverted cleanly (~15s to healthy, image unchangedsha256:94afb8ca, sage intact, prod restored). The parked cu130 rebuild won't fix it (e4m3 = hardware format, not CUDA version). DEFERRED to the Ada refresh (operator: "ada is coming, we'll optimize then" — Ada sm_89 has native e4m3, so triton's fp8 path should compile there). Mechanics:--enable-triton-backendis a composeenvironment:var, so toggling it needsdocker compose up -d(recreate), NOTdocker restart(reuses the baked env, no-ops silently). Full: auto-memoryparked_triton_backend_ampere_fp8.
143 older entries archived to archival-memory.md.