Every speak-aloud path in the harness gates `--voice` against the bundled
Kokoro enum, so the frank-tts cloned voices could only ever produce files.
`agent/extensions/` auto-loads, so one tracked extension adds the missing
transport: `/say <text>`, `/say on|off` (narrate the final answer at
`agent_end`, silent when the harness schedules a continuation),
`/say voice|voices|stop|status` — OpenAI speech POST plus playback through
pw-play/paplay/ffplay. The endpoint and served id come from the
`api: openai-speech` row of `agent/models.yml`, so the file carries no host
and no secret; markdown is stripped, over-long utterances are cut at a
sentence bound, and the temp WAV dir is always removed.
Verified live in a real TUI session on the workstation (roster
narrator1/narrator2/narrator3; 2.08 s and 1.44 s WAVs played; auto-speak
spoke each finished answer, 1.20 s WAV; unknown voice answers with the
roster). Black-box seam `tests/dankvoice.bats` (12 tests) drives the
extension against a fixture speech endpoint and a stub player.
cwd: /home/blank/.omp/wt/feat-21-dankvoice
session: wt-20261017-181502-6d1fc1f
Uncommitted machine/session edits (live config, models, docs drift) were
blocking the merge of origin/main. Committed as-is to preserve them; the
merge that follows resolves overlapping prose files toward upstream
canonical, with local variants recoverable from this commit. Pre-merge
copies also in .AGENTTRASH/pre-merge-2026-10-18/.
Copy of the legacy ~/.pi/agent/docs tree rebuilt as the command-center
knowledge base: concept files promoted to path identity, index listings
stripped of frontmatter, all wikilinks/relative links resolved, every
checkable claim verified against the live fleet (Dankserver = Ryzen 7
7700X + RTX 3090; Strix Halo is Dankclaw), unverifiable claims tagged.
kb-lint exits 0.