VOICE-2: /architect/transcribe/health probe endpoint #774

Closed
opened 2026-05-02 21:41:52 +00:00 by code-lead · 0 comments
Collaborator

As an operator, I want a small /architect/transcribe/health probe the dashboard and the composer can call to find out whether speaches is enabled, reachable, and which model + languages it's serving — so the mic button can hide itself gracefully when STT is off and the settings group can render a live status pill.

This is the carve-out half of the spec's P3 section. Splitting it from the settings-group story keeps the composer (VOICE-3) unblocked while the SVC-3 dependency (#752) ripens.

Acceptance criteria

  • New GET /architect/transcribe/health returns { enabled: boolean, reachable: boolean, model: string, default_language: string, allowed_languages: string[] }.
  • reachable comes from a cached HEAD/GET to ${transcribe_url}/v1/models (or /health if speaches exposes one) — cache 30 s to avoid hammering the upstream.
  • ?refresh=1 query param bypasses the cache (used later by the "Test connection" button in the settings group).
  • All values come from getSpeechConfig(). No service.json reads.
  • Auth: same operator-session middleware as the rest of /architect/*.
  • When speech.enabled === false, the endpoint still answers 200 with enabled: false, reachable: false so the composer can decide what to do; do not 503 here (the gate semantics are already on POST /architect/transcribe).
  • Probe failures (timeout, refused, non-2xx) map to reachable: false with the upstream's status code surfaced in a sibling last_error field; never throw.
  • Used by VOICE-3 (composer) to decide whether to render the mic and by VOICE-4 (settings group) to render status.

Tests

  • Unit: enabled=falsereachable=false, no upstream call made.
  • Unit: cache hit within 30 s does not re-issue the upstream probe; ?refresh=1 does.
  • Unit: upstream timeout → reachable=false, last_error: "timeout", returns 200.

Out of scope

  • The settings-group UI itself — that lands in VOICE-4 (blocked on #752).
  • Surfacing transcript text or any request-level telemetry beyond reachability.

References

  • specs/workspace-chat-voice-input.md — full spec (P3 section, "Health probe" sub-block).
  • VOICE-1 (#773) — the proxy endpoint whose config + resolver this probe shares.

Dependencies

  • Blocked by VOICE-1 (#773)getSpeechConfig() and the speaches base URL plumbing land in VOICE-1 (#773). Native dep edge written against VOICE-1 (#773)'s issue number.
As an operator, I want a small `/architect/transcribe/health` probe the dashboard and the composer can call to find out whether speaches is enabled, reachable, and which model + languages it's serving — so the mic button can hide itself gracefully when STT is off and the settings group can render a live status pill. This is the carve-out half of the spec's P3 section. Splitting it from the settings-group story keeps the composer (VOICE-3) unblocked while the SVC-3 dependency (#752) ripens. ## Acceptance criteria - [ ] New `GET /architect/transcribe/health` returns `{ enabled: boolean, reachable: boolean, model: string, default_language: string, allowed_languages: string[] }`. - [ ] `reachable` comes from a cached HEAD/GET to `${transcribe_url}/v1/models` (or `/health` if speaches exposes one) — cache 30 s to avoid hammering the upstream. - [ ] `?refresh=1` query param bypasses the cache (used later by the "Test connection" button in the settings group). - [ ] All values come from `getSpeechConfig()`. No `service.json` reads. - [ ] Auth: same operator-session middleware as the rest of `/architect/*`. - [ ] When `speech.enabled === false`, the endpoint still answers 200 with `enabled: false, reachable: false` so the composer can decide what to do; do **not** 503 here (the gate semantics are already on `POST /architect/transcribe`). - [ ] Probe failures (timeout, refused, non-2xx) map to `reachable: false` with the upstream's status code surfaced in a sibling `last_error` field; never throw. - [ ] Used by VOICE-3 (composer) to decide whether to render the mic and by VOICE-4 (settings group) to render status. ### Tests - [ ] Unit: `enabled=false` → `reachable=false`, no upstream call made. - [ ] Unit: cache hit within 30 s does not re-issue the upstream probe; `?refresh=1` does. - [ ] Unit: upstream timeout → `reachable=false, last_error: "timeout"`, returns 200. ## Out of scope - The settings-group UI itself — that lands in VOICE-4 (blocked on #752). - Surfacing transcript text or any request-level telemetry beyond reachability. ## References - `specs/workspace-chat-voice-input.md` — full spec (P3 section, "Health probe" sub-block). - VOICE-1 (#773) — the proxy endpoint whose config + resolver this probe shares. ## Dependencies - **Blocked by VOICE-1 (#773)** — `getSpeechConfig()` and the speaches base URL plumbing land in VOICE-1 (#773). Native dep edge written against VOICE-1 (#773)'s issue number.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
charles/claude-hooks#774
No description provided.