open-notebook's embedding default now points at qwen3-embedding-0.6b on frank-dragoon's XDNA2 lane, proven through the app's own paths (model test 1024 dims, worker 'Successfully embedded', vector search ranking two unrelated notes 0.659/0.292 and 0.906/0.318). Records the two app-side traps: defaults store the model ID and a name is accepted then fails in the worker, and POST /api/embed 500s on an upstream RecordID typing bug after the vector is already written. frank-dragoon's lane section moves from 'off until the mount fix' to armed-and-serving with the boot-ledger contract and the measured idle RSS; the page's stale 'not on dankclaw_default' reachability claims are retired.
- frank-dragoon: measured the response_format contract. json_schema and json_object answer
schema-valid JSON at temperature 0 and draw a 400 at any sampled temperature, and because
the sampler default is server-side an absent temperature is sampled. The page claimed
"response_format is unsupported", which sends the next agent past a working feature.
- frank-dragoon: new "The NPU lane" section. The pinned 0.16.2 image already ships the
five-program AIE catalog including qwen3-embedding-0.6b, so /v1/embeddings is one env var
plus the accel device, the distro-XRT mount and the fabric-clock hold; embeddinggemma-2
needs 0.18.3+, the stock-kernel-driver memory-budget fix 0.18.8+. Host census recorded:
no /opt/xilinx/xrt, distro XRT 1:2.21.75 with libxrt_driver_xdna, clocks unheld.
- Open Notebook: scriptwriter probe verdict — greedy-only, and open-notebook's model record
is {credential, name, provider, type} with no per-row config, so it cannot ask for greedy;
frank-archon stays the writer. The embedding gap now has a named door instead of "build a
new llama.cpp slot".
- Frank TTS: "the NPU is not a door at all" was too broad. It is not a door for the TTS
family; halogen's precompiled catalog is a door on the same device.
- System Specs: NPU runtime row corrected to the distro XRT actually installed, and the
stale "frank-zealot serves 27B" line retired in favour of [[frank-zealot]] as sole owner.
Tests: ./tests/run.sh, 455 passed.
The page described an undeployed service whose scriptwriter was going to be
frank-zealot. Both halves are now false, and the reason is worth more than the
correction.
- Status, ports, coordinates: deployed 2026-10-19, guarded vhost, API published
on loopback only. The first episode is the proof: 747 s of speech in 301 s of
wall clock (2.5x real time, knobs at 1), download route 200 with the bearer
and 401 without.
- New section for the guard chain: provider-before-route, one upstream because
the image rewrites /api/* itself, and the API_URL law — autodetect appends
:5055, which is seerr's port on this host, so an unset API_URL yields a UI
that loads and an app that cannot call itself.
- Provisioned records table (credentials, model rows, dank-duo, dank-daily) and
the two contract traps measured on the live API: generate takes profile
NAMES, and the fleet has no /v1/embeddings, so every note save fails its
embed_note command while renders from content work fine.
- Why frank-archon writes the scripts: frank-zealot is reachable from this
netns only at 169.254.1.2, and open-notebook's URL guard refuses to store a
link-local base URL with no override. Census lands on [[Container Network
Namespaces]], which also gains the root-vs-rootless publish rule — a
root-published port is invisible to a rootless container, so "publish the
port" was the wrong remedy as written there.
- Frank TTS: the request's model field is ignored; only voice selects a pack.
Tests: ./tests/run.sh, 455 passed.
- frank-archon KV dtype law: `bf16|fp8` is a **radiance** restriction. Stock
vLLM advertises `auto|fp8|fp8_e5m2|fp8_e4m3` (docs.vllm.ai engine args), and
even there the advertised set is not the usable set — several accepted
values crash engine init at the attention layer's own dtype check
(vllm-project/vllm#42587). The page stated the restriction as if upstream
had it.
- Open Notebook: re-censused 2026-10-19 — no unit file, no installed quadlet,
no container. The page already said NOT deployed; it now says what was
checked, so the claim is re-checkable instead of remembered.
Structural repair:
- 13 pages were the same document twice (each exactly 2x its HEAD size),
a second frontmatter block whose closing fence had been glued onto a body
line by a frontmatter rewrite that re-read its own output. Un-doubled by
cutting at the second frontmatter and keeping the copy whose body is a
superset; the orphan census reports 0 lost tokens against HEAD.
- log.md: one entry per date, bare `## YYYY-MM-DD` headings, newest first —
66 dated headings merged into 34, titles demoted to bold leads, every
content line verified present. The file had been descending at the head
and ascending at the tail.
Ownership moves:
- New `LLM/frank-medium.md` is the locator for the retired Dankserver
endpoint: era windows quoted from each era page's own banner, no numbers
restated, and the two unresolved date conflicts recorded instead of
silently resolved. `frank-archon.md` links to it instead of restating the
pre-rename window.
- The four Pipeline-Parallelism stubs (frontmatter only, no body) are gone;
`Multi-Node Runtimes.md` owns runtime construction, launch, mixed-vendor
verdicts and cross-split spec decode, and the four links that pointed at
the stubs were repointed at it or at the drafter page.
- Authentik's three stub pages fold into `Authentik.md`, with the process
detail and the outpost reference split out so the parent stays under the
length hint.
Verified corrections (host census + live probe, 2026-10-19):
- The MXFP4 checkpoint two pages called the "on-disk rollback" is gone:
/home/dank/models/ holds StillDeadcode, rad and tpl.jinja. Stated once, on
the era page that owns that payload; the swap page now links to it.
- frank-medium-radiance-mxfp4: the 4.24/7 accept rate belongs to the DFlash2
arm measured on the FP8 target, not to the MXFP4 era; the 3-family soak run
census is kept once (155 requests) instead of twice (~120 and 155).
- Fleet shapes re-confirmed against the live endpoints before touching any
page: 3x200000 fp8 KV, 2x200704, 2x262144.
Index rows are regenerated, not hand-carved. Net -1,849 vault lines.
18 pages cut their per-endpoint shape, payload, port and window claims and
link [[frank-archon]] / [[frank-dragoon]] / [[frank-zealot]] instead. Several
of the cut claims had already drifted -- the stack page still described the
kingjones ROCmFP4 era on ROCmFPX, OpenWebUI carried the 27B/3-slot bench
narrative, Hermes named a retired max_model_len and the old service name, and
the OMP harness page's live-window block had drifted off frank-zealot's real
262,144 (it is now labelled a dated worked example whose authority is the
endpoint page).
Two facts gain a single owner instead of two: the up{job=~"frank-.*"} scope
lives in Infrastructure/Prometheus.md, and the blackbox/Anubis probe form in
Architecture/Stale Signal Audit.md, each cited from the other page.
Voice Packs and Frank TTS carried live-state claims that contradicted the
engine page's 2026-10-18 deploy record (nothing listening on 7772/8880, model
dir absent); they now point at the pages that own host state.
Six statements still claimed the endpoint did not exist: both vault descriptions, the two index.md bullets, the Open Notebook blocker, and the engine page deploy order that opened with "Nothing below has been run". All re-keyed to the deployed state, with the ledger the deploys printed: engine healthy 31 s after the build at 4.0 GiB resident, three voices warm, the ladder measured at 1883 ms then 1226-1283 ms (not the retired 6.2-8.0 s), and two voices rendering the same sentence into different bytes.
Adds a The harness speech role section to the endpoint page with the three wiring laws measured the day of the flip: speech.voice is the forwarded key (tts.localVoice belongs to Kokoro), an explicit speech role has no fallback candidate, and models.yml loads at process start while config.yml is read live - so a session older than the frank-tts row fails exactly like a dead endpoint. Fresh-process proof: omp -p --tools tts saved 180524 bytes with voice=narrator1 while the facade logged the matching speech line.
The env file first landed with ESPERANTO_TTS_TIMEOUT equal to SHIM_TIMEOUT=600.
Equality is a race: both budgets expire at the same instant, so the case the
number existed to prevent — the worker abandoning a synthesis frank-tts is still
finishing — is exactly what happens on the tail of a long line. Nested budgets
go inside-out, which is the rule scripts/frank-tts.env states for its own
LLAMA_TIMEOUT; the client waits one round-trip longer than the server, so a
frank-tts give-up arrives labelled as frank-tts's error. 660.
The seam's assertion moves from equality to `>` for the same reason, and now
also holds ESPERANTO_LLM_TIMEOUT under upstream's 600 s web-UI patience — above
it the failure surfaces as a UI timeout with no name on it. The scriptwriting
number itself stays at the app's 180 s default: frank-zealot answers an outline
or a transcript well inside it, which corrects the earlier commit message's
claim that both timeouts were raised past upstream's 300 s.
Page registered in the vault index (the docs-completeness seam fails an
unregistered page) and logged in the bundle change log.
What the page owes the reader: the provider contract (frank-zealot for scripts
with a /v1 base URL, frank-tts for voices with 1-4 speakers mapped to the
narrator1/2/3 voice packs typed as free text), why Test Connection and Discover
Models fail cosmetically against frank-tts rather than being a fault, the
encryption key as the precondition for saving any credential, and the honest
blocker — frank-tts is not deployed and nothing listens on 7772, so a generation
run writes its script and fails on the first voice.
Episode destination is stated as interim and cites Gitea issue #7 (human-only,
agents must not work it): the app keeps its named volume, one bind mount puts
finished MP3s under /home/dank/media/podcasts, and deleting that one line is the
whole rollback. Rollback section also covers the full undo, including that the
podman network only disappears once the units are gone.