docs(memory): voice-studio is retired not broken; agent.disabled_toolsets is global

Two corrections and one finding from the same night.

voice-studio: operator ruled the stack out of service. It existed for the dots
mint/audition loop and dots was decommissioned 2026-09-06 when Breeze took the
fleet seat, so its reason to exist went with it - which is also why nine days of
breakage alerted nobody. No v11 rebuild. The gate one-liner was applied minutes
before the retraction landed and was left in place rather than reverted, since
the value it replaced was a dead address and reverting is another recreate of a
stack that is going away. Container not stopped: it was already running, and
'down for now' arrived as a relayed paraphrase rather than an instruction.

The two host-level facts survive the stack. Containers on irv-ml1 cannot resolve
nh3.internal at all, so on that host the DNS name is the WRONG fix for a dead-IP
bug - it swaps a dead address for an unresolvable one. Confirm resolution from
inside the container before recommending a name. And a stale link can have more
than one drift behind it: voice-studio had three stacked, two of them invisible
from the host compose file.

Hermes: svos_miranda is installed and enabled in config but the gateway was NOT
restarted, so it is not live. agent.disabled_toolsets as specified by svos-dev is
not scoped to api_server - it is a strict end-of-pipeline subtraction applied to
every session on every platform. Measured: a default session goes 46 tools to 20,
losing memory, file, terminal, web, browser and more. It is also unnecessary:
platform_toolsets.api_server alone resolves an api_server session to exactly the
8 svos_miranda tools. The line buys only SVOS's startup check, which reads a
global endpoint to verify a per-platform property. Left commented out with the
measurement inline so an incidental restart cannot gut the assistant.
This commit is contained in:
vh
2026-09-15 02:08:00 -07:00
parent 2fccaf7128
commit 1f98a1be32
2 changed files with 90 additions and 3 deletions
@@ -17,6 +17,24 @@ cutover** — appears **96 times** under `/opt/docker` on irv-ml1. The address i
`tts-gateway`, `arbo`, `dockge`, `waterland-studio`, `comfyui`, `parakeet`,
`kokoro`.
## ⚠ UPDATE 2026-09-15 02:05 — voice-studio is RETIRED, not broken
Operator ruling relayed by tts-dev: **voice-studio is out of service.** It existed for
the dots mint/audition loop; dots was decommissioned 2026-09-06 when Breeze took the
fleet seat. Its reason to exist went with it — and nobody noticed for nine days
precisely because nothing needs it. **No v11 rebuild.** The voice-studio row is
cancelled from the sweep.
The `STUDIO_GATE_URL` one-liner was applied minutes before the retraction arrived and
was **left in place, not reverted** — the value it replaced was a dead address, and
reverting means another recreate of a stack that is going away. Its compose comment now
records the retirement. The container was NOT stopped: it was already running before the
fix, and "down for now" arrived as a relayed paraphrase rather than an instruction.
Stopping it is an explicit question in front of the operator.
⭐ **The two host-level facts below survive the stack's retirement** and are the reason
this entry is still worth keeping.
## ⚠ One LIVE breakage, not just dead links
- **`voice-studio` cannot reach `studio-gate`.** Its running container carries
@@ -45,6 +63,28 @@ rather than config — somebody else's code. Broken nine days already; it wants
scheduled pass, not a 02:00 improvisation. Surfaced to the operator with this
evidence.
## ⭐ Host fact that outlives all of this: irv-ml1 containers cannot resolve `nh3.internal`
Measured from inside a running container on irv-ml1, three addresses for the same
service:
irv-ml1.nh3.internal:8217 -> Name or service not known
10.100.79.3:8217 -> No route to host (retired wg0 lifeline)
10.6.110.50:8217 -> OK
The internal zone is not in the container resolver's search path on that host. **Any
container on irv-ml1 reaching a sibling service BY NAME needs an `extra_hosts` entry** —
`talk` already carries one, and dots, the foundry scripts and voice-studio each hit this
independently. The durable shape:
extra_hosts:
- "irv-ml1.nh3.internal:${IRV_ML1_IP:-10.6.110.50}"
…which resolves the name in-container and keeps the IP in ONE place a single `.env`
line can move. ⚠ Corollary: on this host the DNS name is the WRONG fix for a dead-IP
bug — it swaps a dead address for an unresolvable one. Confirm resolution from inside
the container before recommending a name.
## The pattern this belongs to
Third instance of the same shape. The 2026-09-13 ana-ml2→fv-ml1 renumber left 16
@@ -54,5 +94,11 @@ outside it **by construction**. Same failure here, different cutover.
⭐ **A retired address needs a repo-wide grep by ADDRESS, not by hostname, and it
needs to cover running container labels — which live in no file the sweep reads
unless the container is recreated.** Labels apply at creation, so a fixed compose
unless the container is recreated.**
⭐ **And a "stale link" can have more than one drift behind it.** voice-studio had
three stacked: a hand-edited host compose (which this repo's convention forbids), a
stale image carrying the dead address baked in at three places, and a container that
could not resolve the name the obvious fix would have used. Each alone looks like the
whole story. Two of the three were invisible from the host compose file. Labels apply at creation, so a fixed compose
with a stale container still serves the stale label.
@@ -59,6 +59,47 @@ expected refusal — which looked like the plugin's collision reading was wrong.
was not: doctor's sandbox holds no built-ins, so nothing was claimed and **my
positive case was not positive.** Reported as untested rather than as a finding.
## Where enabling stands
## ENABLED in config 2026-09-15 (operator-directed) — but NOT activated
Blocked on the operator only. See the OPEN row in the index for the sequence.
Installed to `~/.hermes/plugins/svos_miranda`; `plugins.enabled`, the settings block
(dispatch key pulled from the vault, verified byte-equal), and
`platform_toolsets.api_server: [svos_miranda]` all set. Config backed up to
`config.yaml.bak-20260915-svos-miranda-enable`; diffed against it, only the intended
non-comment lines changed. `hermes plugins list` → `svos_miranda enabled 0.1.0 user`.
**The Hermes gateway was NOT restarted**, so the plugin is not live: the running
process loaded its plugin set at 2026-09-14 12:35 and `/v1/toolsets` still reports 28
without `svos_miranda`.
## ⚠⚠ `agent.disabled_toolsets` is GLOBAL — it would have cost 26 tools fleet-wide
svos-dev's install instructions specify `agent.disabled_toolsets = <the 28 rows minus
svos_miranda>`. **That key is not scoped to api_server.** It is a strict
end-of-pipeline subtraction applied to every session on every platform
(`model_tools.py:216` "subtracted after enabling", applied `:332`; `cli.py:2743` reads
the same key for the CLI).
Measured, not derived:
default session WITHOUT the line : 46 tools
default session WITH the line : 20 tools
lost 26: memory, read_file, write_file, patch, search_files, terminal,
process_manage, web_search, web_extract, browser_exec, execute_code,
computer_use, delegate_task, vision_analyze, video_analyze,
session_search, skills_*, todo_list, text_to_speech, image_generate, ha_*
⭐ **And it is not needed for the security property.** Measured:
`enabled_toolsets=['svos_miranda'], disabled_toolsets=None` resolves to **exactly the
8** svos_miranda tools. `platform_toolsets.api_server: [svos_miranda]` already scopes
Miranda correctly on its own; the global subtraction adds no safety on top.
The only thing it buys is satisfying **SVOS's startup roster check, which reads the
GLOBAL `GET /v1/toolsets` to verify a PER-PLATFORM property.** Raised with svos-dev
with three options (verify against the api_server surface; accept the cost with
explicit operator sign-off; or relax the check to "svos_miranda present, write-klass
five absent"). Left **commented out** in the config with the measurement inline, so an
incidental Hermes restart cannot gut the operator's assistant.
⚠ Minor: `stt` appears in `/v1/toolsets`'s 28 rows but resolving it logs
`Unknown toolset: stt` — an exact-set comparison pinned to that endpoint can fail for
reasons unrelated to the plugin.