Files
command-center/agent/managed-skills/frank-tts-voice-pack-audit/SKILL.md
T
Frank 8af40c402b chore(agent): commit the machine tier and the doctrine text the checkout was already running
Landing blocker for #61 and #63: the deployment checkout is 12 commits behind and
`merge --ff-only` refuses while tracked paths are dirty. Discard is not available here
(workspace policy: no `checkout`/`stash` on shared state), so the dirt is committed.

- `agent/APPEND_SYSTEM.md`: the point-of-use / one-work-log / PR-link doctrine, already
  byte-identical to `origin/main` (`cmp` against the trunk blob: no difference). No new
  prose — the commit exists so the trunk merge can proceed.
- `agent/config.yml` and `agent/managed-skills/**`: the machine-live tier the heartbeat
  owns (AGENTS.md § Live-sync tiers).

`ALLOW_SECRETS=1` was used, deliberately and after auditing the staged diff by hand: the
only credential-shaped strings in it are two copies of `AKIA0000000000000EXAMPLE` — the
inert all-zero AWS example id — and they appear inside the two skill pages that teach
that exact placeholder shape. This checkout is still running the pre-#61 hook; the merged
gate (value-scoped placeholder filter, `71601f7`) exempts this value, so the refusal
dies with this landing. No `--no-verify` was used: the gate ran and its verdict is
recorded here.

Refs #61
2026-10-21 01:44:51 -07:00

4.3 KiB

name, description
name description
frank-tts-voice-pack-audit Census live frank-tts voice packs against scripts/voice-packs.env to catch name-drift (renamed/retired packs) and untracked CLI-built packs; use after any voice add/rename when reconciling the builder recipe with what is actually on disk.

frank-tts voice-pack audit (builder ↔ live census)

Read-only census answering: does scripts/voice-packs.env still describe the packs that actually exist, and is every live pack reproducible from the repo? Run it after anyone adds or renames a voice. The runtime being healthy (all voices synthesize) does NOT mean the builder is honest — the gap is reproducibility, not serving.

Why this exists

Packs are host state under /home/dank/voices (never in git). A voice can be:

  • built by the env (a VOICE_PACK_<NAME>_* block exists), or
  • built by CLI override (build-voice-pack.sh <name> <dir> --source --offset --duration --sha256 with NO env block) — then its only provenance is /home/dank/voices/<name>/manifest.json, and --all silently skips it.

Renaming a pack directory (e.g. narrator1 → wilwheaton) preserves the crop bytes and its source sha256, so the env recipe stays correct but keyed under a dead name. build-voice-pack.sh --all then rebuilds the dead names and skips the live ones.

Procedure (on Dankclaw)

  1. Live set + which builder made each — the manifest kind field tells them apart:
    • kind: "voice-pack" → built by scripts/build-voice-pack.sh (env or CLI override).
    • kind: "voice-reference-pack" → the older trial pipeline.sh.
    for d in /home/dank/voices/*/; do n=$(basename "$d"); [ -f "$d/reference.wav" ] \
      && printf '%-16s %8sB  %s\n' "$n" "$(stat -c%s "$d/reference.wav")" "$(stat -c %y "$d/reference.wav" | cut -d. -f1)"; done
    
  2. Per-voice provenance — manifest.json is the sole record for CLI-built packs. Read name/voice, kind, source.path, source.sha256, crop.offset_seconds, crop.duration_seconds. Use python3 -c 'import json,...', NOT a jq '{a,b,c}' object — the brace form gets brace-expanded by the remote zsh and errors.
  3. Builder tracked list:
    grep -E '^VOICE_PACKS=|^VOICE_PACK_[A-Z0-9_]+_(SOURCE|OFFSET|DURATION|SHA256)=' /home/dank/serverAppConfigs/scripts/voice-packs.env
    
    Diff the names in VOICE_PACKS against the live dirs. Three findings to report:
    • env keys that have no live dir (renamed/retired),
    • live dirs with no env block (CLI-built, unreproducible from repo),
    • matching source sha256 between a dead env key and a live dir = that live pack is the renamed crop (safe to re-key the env, don't recompute).
  4. Distinguish CLI-built from uncommitted env drift — check the deployed env matches the repo:
    cd /home/dank/serverAppConfigs && git diff --stat HEAD -- scripts/voice-packs.env   # empty = no drift
    
    Empty diff + a kind: "voice-pack" manifest with no env block ⇒ built via CLI overrides (correct, just untracked), NOT a rogue remote edit.

Repoint the consumers (separate concern)

If voices were renamed/retired, the runtime consumers still point at dead names — see the frank-tts-repoint-voice-consumers skill. Consumers that name a voice: scripts/frank-tts.env DEFAULT_VOICE, Open Notebook dank-duo speaker profile (voice_id, app-side REST), OpenWebUI audio.tts.voice (config DB). A voice-less request to frank-tts 400s naming DEFAULT_VOICE, so a dead default is a live break, not just cosmetic.

Gotchas

  • A published port is reachable at host.containers.internal too. OpenWebUI's docs say use the LAN IP because that name "doesn't resolve on the bridge" — true only for non-published ports. frank-tts 7772 IS published, so host.containers.internal:7772 answers 200 from the open-webui container. Verify before calling a URL the cause; the real break is usually the dead voice name.
  • Source custody is split: audiosample*.mp3/m4b live on the workstation (/home/blank), newer sources on Dankclaw (/home/dank/voice-sources). --all is only reproducible once each env SOURCE path points at where the file actually is.
  • Do NOT edit voice-packs.env to add CLI-built voices without confirming each source path + offset + sha against its manifest, then run ./tests/run.sh (the pack-list invariant in voice_pack_unit.bats walks VOICE_PACKS).