1. Audiobookshelf gets its real mark. The card carried the improvised AB hex monogram — the fallback this page uses for apps with no icon. Simple Icons carries the Audiobookshelf brand mark (#82612C, same 24×24 shape as the jellyfin.svg / plex.svg marks already here), so art now points at /img/apps/audiobookshelf.svg. mono-ab.svg went to .AGENTTRASH/ (untracked, ignored, recoverable).
2. frank-tts joins the Model Information block. The Qwen3-TTS endpoint was an admin-only status tile, so the household read about five cloned voices in /docs and saw no sign of the door that speaks them. It is now a user-page model card beside the three chat models:
field
content
role
The fleet's voice — it speaks, it does not chat
spec
Qwen3-TTS 1.7 B base talker (Q4_K_M) + its 12 Hz tokenizer, qwentts.cpp on the gfx1151 iGPU, POST /v1/audio/speech with voice=<name>
inputs
text
use
Open Notebook episodes, the harness's spoken output, anything that should sound like a person
permission
Ask Frank for a voice — each pack is built from that person's own recording.
privacy note
cloned voices: output is not that person speaking and must never be passed off as them
HF link
Serveurperso/Qwen3-TTS-GGUF (the source the fetcher pins)
Facts come from serverAppConfigs-docs/Dankclaw/Frank TTS.md and Frank TTS Engine.md; the guide's And the voices table stays the owner of the five voice names — the card links /docs#models instead of restating them.
Supporting code
miCard() assumed every model card is a StarCraft unit. Three fallbacks, nothing else changed:
art: svc.art when present, else /img/unit-<unit>.jpg
accent: .mi-<unit>, else .mi-tool (amber #ffc86b — a tool, not a unit)
tagline: a play button when sfx[] exists, plain .mi-tag text when it does not
No audio asset ships with this card, deliberately. Every pack on that endpoint is a replica of a real person's voice, so a sample clip would put a synthetic, identifiable person's voice into the repo and on a public page. The three unit cards keep their StarCraft quotation buttons; the TTS card shows its tagline as text and its badge as the live signal.
Seams that moved
homepage_config.bats — the model-card contract split in two: a card with a unit (a chat model) must carry equivalence + supervision + a playable voice line whose file ships; a unit-less tool card must carry the permission note instead. Common invariants (role, spec, use, inputs, art exists) apply to all four. The fleet set and the render order gained frank-tts last.
frank_tts_engine.bats — pinned category == "admin" with the reason "not an app the user homepage should advertise" (2026-10-18). This PR overturns that half of the decision; the tile stays showLink: false (an API has no page to open), and the seam now pins category == "user" + section == "AI" + the presence of a model object, with the reason recorded in the test.
Checks
./tests/run.sh → ALL TESTS PASSED (841).
Rendered-page census (static copy + stub status.json, real browser): four .mi-cards in order zealot → dragoon → archon → frank-tts, the new one carrying mi-tool, the FT art, the HF link, Inputs: text, the permission callout and the privacy <details>; Audiobookshelf's card loads /img/apps/audiobookshelf.svg; zero broken images on either page.
Admin page after the move: UP 19 DOWN 0 WIP 4 (was 20), rosters unchanged, mi-cards: 0, no frank-tts panel.
Deploy note
shared/homepage/** is a planner path for homepage: after merge this needs ./scripts/deploy.sh dankclaw --service homepage, and the [3/3] gate still cannot run on Dankclaw (no tests/e2e/.env.local, no node_modules there) — run tests/e2e/run.sh from a dev checkout, which is what I'll do after merging.
## What changed
**1. Audiobookshelf gets its real mark.** The card carried the improvised `AB` hex monogram — the fallback this page uses for apps with no icon. Simple Icons carries the Audiobookshelf brand mark (`#82612C`, same 24×24 shape as the `jellyfin.svg` / `plex.svg` marks already here), so `art` now points at `/img/apps/audiobookshelf.svg`. `mono-ab.svg` went to `.AGENTTRASH/` (untracked, ignored, recoverable).
**2. `frank-tts` joins the Model Information block.** The Qwen3-TTS endpoint was an admin-only status tile, so the household read about five cloned voices in `/docs` and saw no sign of the door that speaks them. It is now a **user**-page model card beside the three chat models:
| field | content |
|---|---|
| role | *The fleet's voice — it speaks, it does not chat* |
| spec | Qwen3-TTS 1.7 B base talker (Q4_K_M) + its 12 Hz tokenizer, qwentts.cpp on the gfx1151 iGPU, `POST /v1/audio/speech` with `voice=<name>` |
| inputs | text |
| use | Open Notebook episodes, the harness's spoken output, anything that should sound like a person |
| permission | *Ask Frank for a voice — each pack is built from that person's own recording.* |
| privacy note | cloned voices: output is not that person speaking and must never be passed off as them |
| HF link | `Serveurperso/Qwen3-TTS-GGUF` (the source the fetcher pins) |
Facts come from `serverAppConfigs-docs/Dankclaw/Frank TTS.md` and `Frank TTS Engine.md`; the guide's *And the voices* table stays the owner of the five voice names — the card links `/docs#models` instead of restating them.
## Supporting code
`miCard()` assumed every model card is a StarCraft unit. Three fallbacks, nothing else changed:
- art: `svc.art` when present, else `/img/unit-<unit>.jpg`
- accent: `.mi-<unit>`, else `.mi-tool` (amber `#ffc86b` — a tool, not a unit)
- tagline: a play button when `sfx[]` exists, plain `.mi-tag` text when it does not
**No audio asset ships with this card, deliberately.** Every pack on that endpoint is a replica of a real person's voice, so a sample clip would put a synthetic, identifiable person's voice into the repo and on a public page. The three unit cards keep their StarCraft quotation buttons; the TTS card shows its tagline as text and its badge as the live signal.
## Seams that moved
- `homepage_config.bats` — the model-card contract split in two: a card with a `unit` (a chat model) must carry equivalence + supervision + a playable voice line whose file ships; a unit-less tool card must carry the permission note instead. Common invariants (role, spec, use, inputs, art exists) apply to all four. The fleet set and the render order gained `frank-tts` last.
- `frank_tts_engine.bats` — pinned `category == "admin"` with the reason *"not an app the user homepage should advertise"* (2026-10-18). This PR overturns that half of the decision; the tile stays `showLink: false` (an API has no page to open), and the seam now pins `category == "user"` + `section == "AI"` + the presence of a `model` object, with the reason recorded in the test.
## Checks
- `./tests/run.sh` → **ALL TESTS PASSED (841)**.
- Rendered-page census (static copy + stub `status.json`, real browser): four `.mi-card`s in order zealot → dragoon → archon → frank-tts, the new one carrying `mi-tool`, the `FT` art, the HF link, `Inputs: text`, the permission callout and the privacy `<details>`; Audiobookshelf's card loads `/img/apps/audiobookshelf.svg`; **zero broken images** on either page.
- Admin page after the move: `UP 19 DOWN 0 WIP 4` (was 20), rosters unchanged, `mi-cards: 0`, no `frank-tts` panel.
## Deploy note
`shared/homepage/**` is a planner path for `homepage`: after merge this needs `./scripts/deploy.sh dankclaw --service homepage`, and the `[3/3]` gate still cannot run on Dankclaw (no `tests/e2e/.env.local`, no `node_modules` there) — run `tests/e2e/run.sh` from a dev checkout, which is what I'll do after merging.
---
cwd: /home/blank/.omp/wt/wt-20261104-121037-6d1fc1f · session: 01a1a833-a2e6-76b6-8a67-d54ca993dcca
Audiobookshelf carried the improvised "AB" hex monogram — the fallback for
apps with no icon. Simple Icons carries its brand mark, so the card now
uses /img/apps/audiobookshelf.svg the way Plex and Jellyfin use theirs; the
monogram went to .AGENTTRASH.
frank-tts (Qwen3-TTS 1.7 B base talker on the gfx1151 iGPU) was an
admin-only status tile, so the household read about five cloned voices in
/docs and saw no sign of the door that speaks them. It is now a Model
Information card on the user page beside the three chat models, carrying
the ask-Frank permission note and a privacy note about cloned voices.
miCard grew the shape that requires: art falls back to the card's own `art`
when a card has no StarCraft `unit`, the accent falls back to `.mi-tool`,
and a `tagline` with no `sfx` renders as text instead of a play button that
plays nothing. No audio asset ships with the card on purpose: every pack on
that endpoint is a replica of a real person's voice, so a sample clip would
put a synthetic person's voice in the repo and on the page.
Seams: the model-card contract splits unit cards (equivalence, supervision,
playable voice line) from tool cards (permission note), and the voice
stack's homepage seam now pins category=user with the reason.
dank
merged commit b3eb9c6314 into main2026-11-04 13:50:50 -08:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What changed
1. Audiobookshelf gets its real mark. The card carried the improvised
ABhex monogram — the fallback this page uses for apps with no icon. Simple Icons carries the Audiobookshelf brand mark (#82612C, same 24×24 shape as thejellyfin.svg/plex.svgmarks already here), soartnow points at/img/apps/audiobookshelf.svg.mono-ab.svgwent to.AGENTTRASH/(untracked, ignored, recoverable).2.
frank-ttsjoins the Model Information block. The Qwen3-TTS endpoint was an admin-only status tile, so the household read about five cloned voices in/docsand saw no sign of the door that speaks them. It is now a user-page model card beside the three chat models:POST /v1/audio/speechwithvoice=<name>Serveurperso/Qwen3-TTS-GGUF(the source the fetcher pins)Facts come from
serverAppConfigs-docs/Dankclaw/Frank TTS.mdandFrank TTS Engine.md; the guide's And the voices table stays the owner of the five voice names — the card links/docs#modelsinstead of restating them.Supporting code
miCard()assumed every model card is a StarCraft unit. Three fallbacks, nothing else changed:svc.artwhen present, else/img/unit-<unit>.jpg.mi-<unit>, else.mi-tool(amber#ffc86b— a tool, not a unit)sfx[]exists, plain.mi-tagtext when it does notNo audio asset ships with this card, deliberately. Every pack on that endpoint is a replica of a real person's voice, so a sample clip would put a synthetic, identifiable person's voice into the repo and on a public page. The three unit cards keep their StarCraft quotation buttons; the TTS card shows its tagline as text and its badge as the live signal.
Seams that moved
homepage_config.bats— the model-card contract split in two: a card with aunit(a chat model) must carry equivalence + supervision + a playable voice line whose file ships; a unit-less tool card must carry the permission note instead. Common invariants (role, spec, use, inputs, art exists) apply to all four. The fleet set and the render order gainedfrank-ttslast.frank_tts_engine.bats— pinnedcategory == "admin"with the reason "not an app the user homepage should advertise" (2026-10-18). This PR overturns that half of the decision; the tile staysshowLink: false(an API has no page to open), and the seam now pinscategory == "user"+section == "AI"+ the presence of amodelobject, with the reason recorded in the test.Checks
./tests/run.sh→ ALL TESTS PASSED (841).status.json, real browser): four.mi-cards in order zealot → dragoon → archon → frank-tts, the new one carryingmi-tool, theFTart, the HF link,Inputs: text, the permission callout and the privacy<details>; Audiobookshelf's card loads/img/apps/audiobookshelf.svg; zero broken images on either page.UP 19 DOWN 0 WIP 4(was 20), rosters unchanged,mi-cards: 0, nofrank-ttspanel.Deploy note
shared/homepage/**is a planner path forhomepage: after merge this needs./scripts/deploy.sh dankclaw --service homepage, and the[3/3]gate still cannot run on Dankclaw (notests/e2e/.env.local, nonode_modulesthere) — runtests/e2e/run.shfrom a dev checkout, which is what I'll do after merging.cwd: /home/blank/.omp/wt/wt-20261104-121037-6d1fc1f · session: 01a1a833-a2e6-76b6-8a67-d54ca993dcca