Skip to content

Audio surface: real Parakeet readiness probe + realtime-pipeline docs + smoke (closes #39, #40) - #41

Merged
OriNachum merged 8 commits into
mainfrom
spec/audio-surface-ownership
Jun 12, 2026
Merged

Audio surface: real Parakeet readiness probe + realtime-pipeline docs + smoke (closes #39, #40)#41
OriNachum merged 8 commits into
mainfrom
spec/audio-surface-ownership

Conversation

@OriNachum

Copy link
Copy Markdown
Contributor

What & why

Works #39 (Parakeet STT 500s with CUDA error: unknown error while reporting "healthy") and #40 (deployed :8080 facade missing the REST /v1/audio/transcriptions route) — both blocking reachy-mini-cli's "hey reachy" wake-word.

This PR carries the full devague chain: a converged spec (docs/specs/…), a plan (docs/plans/…), and the implementation.

Reconnaissance changed the scope

The issues implied the audio route existed nowhere deployable. Reconnaissance found the repo was ~70% already built: templates/fleet/docker-compose.audio.yml (Magpie tts + Parakeet stt + the realtime facade on :8080 + a gateway /v1/audio/* route), both Dockerfiles, the vendored Parakeet server, model init --fleet --audio, and model fleet up auto-including the overlay — all already present. So this PR implements only the three real remaining gaps, rather than rebuilding what exists.

The three real gaps (implemented)

What is NOT closed by merging this — operational, on the box

The live acceptance is GPU/Docker/NGC-bound and cannot run in CI or a worktree:

Verification

  • 271 passed (full suite, incl. 8 new readiness tests).
  • black / isort / flake8 clean; markdownlint 0 errors on the new docs + CHANGELOG.
  • Rubric gate afi cli doctor . --strict passes.
  • Version bumped 0.19.0 → 0.20.0.

Did not touch

t2/t3/t4 (Dockerfiles, audio overlay compose, fleet wiring) — verified pre-existing, left as-is.

🤖 Generated with Claude Code

  • model-gear (Claude)

OriNachum and others added 4 commits June 12, 2026 12:28
Work issues #39 (Parakeet STT 500s, CUDA-unknown) and #40 (deployed
:8080 facade missing /v1/audio/transcriptions) backwards into one
converged spec: model-gear takes ownership of the audio stack, wiring
Parakeet STT + Magpie TTS + the vendored realtime facade into its
compose template and `model fleet up`.

Decisions captured: full-stack ownership (both /v1/audio/* routes),
cheap model-ready Parakeet healthcheck, restart-clears-stale-CUDA-context
runbook. Unblocks reachy-mini-cli's "hey reachy" wake-word.

Includes the converged spec + the .devague frame state (evidence trail).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lan)

Forward leg from the converged audio-ownership spec. Six file-disjoint,
TDD-gated tasks covering all 24 coverage targets:
  t1 vendor Parakeet server + cheap model-ready probe
  t2 build Dockerfiles (facade + parakeet)
  t3 wire the audio stack into the compose template (sole compose owner)
  t4 bring it up via `model fleet up`
  t5 docs/realtime-pipeline.md + README Audio I/O + CUDA restart runbook
  t6 smoke/acceptance harness (openapi, WAV 200, healthcheck flip)

Waves: [t1,t5] -> t2 -> t3 -> t4 -> t6 (serial after wave 0 by the
compose chokepoint). Risks carried: CUDA root-cause unconfirmed, fleet
gating on the GB10 budget, cheap-probe wording reconciliation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… smoke

Implements the three real gaps found after reconnaissance (t2/t3/t4 — the
audio overlay, Dockerfiles, fleet wiring — already existed in
templates/fleet/):

- t1: Parakeet /v1/health/ready now reflects REAL readiness (model loaded +
  a trivial CUDA op) instead of returning {"status":"ready"}
  unconditionally — the misleading-health bug behind #39. The pure decision
  lives in stdlib-only model_gear/realtime/_readiness.py (CI-unit-tested,
  8 cases), vendored into the Parakeet build context and COPY'd into the
  image so the container imports it without the wheel. (decision c16: a
  cheap probe, not a full transcription each interval.)
- t5: docs/realtime-pipeline.md — ownership of the live :8080 facade, fleet
  bring-up, the prior drift (#39/#40), health/readiness, and the stale-CUDA
  restart runbook.
- t6: scripts/audio-smoke.py — stdlib-only live smoke (openapi lists both
  routes; WAV POST -> 200 {text}); reproduces #39's repro. Live run is
  GPU-box-bound, not CI.

271 tests pass; black/isort/flake8 + markdownlint clean.

Refs #39 #40

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@qodo-code-review

qodo-code-review Bot commented Jun 12, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Context used
✅ Compliance rules (platform): 35 rules

Grey Divider


Action required

1. ~/.model-gear path in docs ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
docs/realtime-pipeline.md includes per-user dotfile paths like ~/.model-gear/.env, which
violates the policy against ~/.* references outside the allowed carve-outs. This can cause
non-portable instructions and breaks the documented compliance regex check.
Code

docs/realtime-pipeline.md[R62-76]

+# Locate ~/.model-gear/.env (or your --compose-dir) and edit:
+#   NGC_API_KEY=<your-key>
+
+# 3. Bring up the full audio stack (dry-run by default; --apply commits)
+model fleet up --apply
+
+# 4. Check status
+model fleet status
+```
+
+Each `model init` and `model fleet` verb defaults to **dry-run**; omit `--apply`
+to see what would happen, or add `--apply` to execute. This ensures safe-by-default
+operation (useful when agents call CLIs in loops).
+
+To customize the compose dir (default `$MODEL_GEAR_DIR` or `~/.model-gear`):
Evidence
Rule 796119 forbids ~/\.[A-Za-z] dotfile references in markdown unless they match a carve-out. The
doc includes ~/.model-gear/.env and ~/.model-gear, which match the forbidden pattern and are not
in an allowed carve-out.

Rule 796119: No per-user dotfile config references in docs/configs (with specified carve-outs)
docs/realtime-pipeline.md[62-76]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`docs/realtime-pipeline.md` contains per-user dotfile references matching the forbidden pattern `~/\.[A-Za-z]` (e.g., `~/.model-gear/.env`). These must be replaced with a compliant, portable representation (e.g., `$HOME/.model-gear/...` and/or wording that points to `$MODEL_GEAR_DIR` / `--compose-dir` without using `~/`).

## Issue Context
Compliance rule 796119 forbids `~/.*` dotfile references in `.md/.yml/.toml/.json*` files except for specific carve-outs (only `~/.claude/skills/<name>/scripts/` and `~/.culture/`). This doc is not within those carve-outs.

## Fix Focus Areas
- docs/realtime-pipeline.md[62-76]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Audio scaffold missing _readiness ✓ Resolved 🐞 Bug ≡ Correctness
Description
Dockerfile.parakeet now requires a root-level _readiness.py in the deployment directory build
context, but model init --fleet --audio scaffolding won’t write it because
_compose.AUDIO_TEMPLATES omits the fleet/_readiness.py template. Fresh audio deployments will
fail building the stt image at COPY _readiness.py.
Code

model_gear/templates/fleet/Dockerfile.parakeet[R23-27]

+# _readiness.py is a vendored copy of model_gear/realtime/_readiness.py (stdlib
+# only, no wheel needed).  Copied here so listen_server.py can import it as a
+# top-level module without requiring the model_gear wheel to be installed.
+COPY _readiness.py /app/_readiness.py
COPY listen_server.py /app/listen_server.py
Evidence
The Parakeet Dockerfile COPYs a root-level _readiness.py, but the init scaffolder only writes
templates enumerated in AUDIO_TEMPLATES, which currently does not include any _readiness.py
destination, and the existing init test confirms only the listed overlay files are written.

model_gear/templates/fleet/Dockerfile.parakeet[22-27]
model_gear/runtime/_compose.py[56-65]
model_gear/runtime/_compose.py[125-149]
model_gear/cli/_commands/init.py[21-27]
tests/test_init.py[129-142]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`Dockerfile.parakeet` now executes `COPY _readiness.py /app/_readiness.py`, which requires a file named `_readiness.py` to exist at the *root of the scaffolded deployment directory* (the docker build context used by `docker-compose.audio.yml`).

However, `model init --fleet --audio` only writes files listed in `_compose.AUDIO_TEMPLATES`, and that mapping does not include `fleet/_readiness.py -> _readiness.py`. So a clean init produces a deployment dir that lacks `_readiness.py`, making `docker compose build stt` fail.

## Issue Context
- The PR adds the packaged template file at `model_gear/templates/fleet/_readiness.py`, and updates the Parakeet Dockerfile to copy a *root-level* `_readiness.py`.
- The scaffolder writes only explicit mappings and currently doesn’t include this new file.

## Fix Focus Areas
- model_gear/runtime/_compose.py[56-66]
- model_gear/templates/fleet/Dockerfile.parakeet[22-27]
- tests/test_init.py[129-142]

## What to change
1. Add a mapping entry to `_compose.AUDIO_TEMPLATES`:
  - source: `fleet/_readiness.py`
  - dest: `_readiness.py`
2. Update `tests/test_init.py::test_init_fleet_audio_apply_writes_overlay_and_appends_env` to assert `_readiness.py` is scaffolded.
3. (Optional but recommended) Add a small test that `model_gear/templates/fleet/_readiness.py` stays identical to `model_gear/realtime/_readiness.py` to prevent drift.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Smoke script misses speech ✓ Resolved 🐞 Bug ≡ Correctness
Description
scripts/audio-smoke.py claims to test both /v1/audio/transcriptions and /v1/audio/speech, but
it never sends a request to /v1/audio/speech and can still report overall success. The unused
--stt-url flag also indicates incomplete/incorrect smoke coverage.
Code

scripts/audio-smoke.py[R170-186]

+    parser.add_argument(
+        "--stt-url",
+        help="Override STT URL for direct Parakeet testing (optional)",
+    )
+    args = parser.parse_args()
+
+    print(f"Testing audio surface at {args.base_url}")
+    print()
+
+    results = []
+
+    # Test 1: OpenAPI schema
+    results.append(("openapi.json", check_openapi(args.base_url)))
+
+    # Test 2: Transcription endpoint
+    results.append(("transcriptions", check_transcription(args.base_url)))
+
Evidence
The script docstring advertises speech coverage, but main() only runs OpenAPI and transcription
checks; it also parses --stt-url without using it.

scripts/audio-smoke.py[2-6]
scripts/audio-smoke.py[161-186]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The smoke script’s stated purpose is to validate the whole audio surface (transcriptions + speech), but it only:
- checks `/openapi.json` includes `/v1/audio/speech`
- performs a real POST only for `/v1/audio/transcriptions`

So it can pass even when the TTS route is broken.

## Issue Context
The realtime service’s `/v1/audio/speech` expects a JSON body with at least `input` (see `model_gear/realtime/audio_facade.py::parse_speech_request`).

## Fix Focus Areas
- scripts/audio-smoke.py[2-12]
- scripts/audio-smoke.py[161-186]
- model_gear/realtime/audio_facade.py[47-84]

## What to change
- Add `check_speech(base_url)` that POSTs JSON like `{ "input": "hello", "response_format": "wav" }` to `/v1/audio/speech`.
- Validate response: HTTP 200, `Content-Type` is audio, and WAV bodies start with `RIFF` when `response_format=wav`.
- Either implement `--stt-url` (use it to run the transcription check directly against Parakeet) or remove the flag to avoid misleading CLI UX.
- Update the module docstring to match the actual checks executed.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. CUDA probe failures unlogged ✓ Resolved 🐞 Bug ◔ Observability
Description
listen_server.health() suppresses all exceptions from the torch CUDA probe and returns 503 without
logging any details, so operators can’t see why the container is unhealthy. This makes diagnosing
readiness failures (driver down vs OOM vs stale context) unnecessarily difficult.
Code

model_gear/templates/fleet/listen_server.py[R83-90]

+    try:
+        import torch
+
+        torch.zeros(1, device="cuda")
+        torch.cuda.synchronize()
+        cuda_ok = True
+    except Exception:
+        cuda_ok = False
Evidence
The code sets cuda_ok=False on any exception but does not record/log the exception anywhere.

model_gear/templates/fleet/listen_server.py[71-93]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `/v1/health/ready` endpoint catches all exceptions during the CUDA probe and silently sets `cuda_ok = False`. When the container becomes unhealthy, logs won’t contain the underlying exception, which slows incident response.

## Issue Context
This endpoint is called by Docker healthcheck on an interval; logging on every failure could be noisy, so logging should be rate-limited or only on state transitions.

## Fix Focus Areas
- model_gear/templates/fleet/listen_server.py[81-93]

## What to change
- Capture the exception and log it (preferably with `exc_info=True`).
- Avoid log spam by logging only when the probe transitions from success->failure or when the exception class/message changes (store a module-level last-seen error).
- Optionally include the exception class in the 503 response `reason` (still keeping it short).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Readiness logic drift risk ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
Readiness decision logic is duplicated in two files plus an inline fallback in listen_server.py,
so future edits can change CI-tested behavior without changing the container behavior (or vice
versa). This increases the risk of inconsistent readiness semantics across environments.
Code

model_gear/templates/fleet/listen_server.py[R23-40]

+# Import the readiness decision logic.  The Dockerfile COPYs _readiness.py
+# next to listen_server.py (as a top-level module in /app), so this import
+# works whether or not the model_gear wheel is installed in the container.
+# Falls back gracefully if neither is present (shouldn't happen, but defensive).
+try:
+    from _readiness import evaluate_readiness  # container-local copy (top-level)
+except ImportError:
+    try:
+        from model_gear.realtime._readiness import evaluate_readiness  # wheel install
+    except ImportError:
+        # Last-resort inline fallback — keeps the container functional even if
+        # both import paths fail (e.g. a dev build without the COPY step).
+        def evaluate_readiness(model_loaded: bool, cuda_ok: bool):  # type: ignore[misc]
+            if not model_loaded:
+                return 503, {"status": "not_ready", "reason": "model not loaded"}
+            if not cuda_ok:
+                return 503, {"status": "not_ready", "reason": "CUDA not available"}
+            return 200, {"status": "ready"}
Evidence
There are three separate implementations/definitions of the same readiness decision function across
the repo and template code paths.

model_gear/realtime/_readiness.py[16-49]
model_gear/templates/fleet/_readiness.py[1-48]
model_gear/templates/fleet/listen_server.py[23-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The same `evaluate_readiness()` logic exists in:
- `model_gear/realtime/_readiness.py` (CI-tested canonical)
- `model_gear/templates/fleet/_readiness.py` (vendored for container)
- an inline fallback definition in `listen_server.py`

This creates multiple sources of truth that can drift.

## Issue Context
The inline fallback is defensive, but it still duplicates logic and makes it easier for future changes to become inconsistent.

## Fix Focus Areas
- model_gear/realtime/_readiness.py[16-49]
- model_gear/templates/fleet/_readiness.py[1-48]
- model_gear/templates/fleet/listen_server.py[23-40]

## What to change
- Prefer removing the inline fallback and failing fast if neither import works (once `_readiness.py` is reliably scaffolded/copied).
- Add a unit test that asserts the vendored template file matches the canonical file contents (or at least that function output matches across representative inputs) to prevent accidental drift.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Audio surface: Parakeet readiness probe + realtime pipeline docs + smoke tests
🐞 Bug fix 📝 Documentation 🧪 Tests ✨ Enhancement 🕐 40+ Minutes

Grey Divider

Walkthroughs

Description
• Make Parakeet /v1/health/ready reflect model-loaded + CUDA-ready (503 otherwise).
• Document :8080 audio facade ownership, fleet bring-up, and stale-CUDA restart runbook.
• Add audio smoke script and CI tests for readiness; bump version to 0.20.0.
Diagram
graph TD
  client(["Client / OpenAI SDK"]) --> gateway["Fleet gateway (:8000)"] --> realtime["Realtime facade (:8080)"]
  realtime -->|"/v1/audio/transcriptions"| stt["Parakeet STT (:9002)"]
  realtime -->|"/v1/audio/speech"| tts["Magpie TTS (:9000)"]
  dockerhc["Docker healthcheck"] --> readyep["GET /v1/health/ready"] --> stt --> readiness["evaluate_readiness()"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Install model-gear wheel in Parakeet image (no vendored _readiness.py)
  • ➕ Eliminates file duplication and “keep in sync” risk
  • ➕ Simplifies imports in listen_server.py (single canonical module path)
  • ➖ Increases image coupling to the wheel/runtime packaging
  • ➖ May pull in extra dependencies (or require careful extras) just to run a probe
2. Use a lightweight real inference probe (short fixed audio) for readiness
  • ➕ Directly validates end-to-end inference path, not just CUDA alloc/sync
  • ➕ Can catch failures where CUDA is ‘alive’ but model inference is broken
  • ➖ Higher GPU cost and latency; more likely to flap under load
  • ➖ Harder to keep “cheap” and deterministic across environments
3. Expose explicit internal readiness state (startup completes) and skip CUDA op

Recommendation: Current approach is the best tradeoff for #39/#40: a cheap, deterministic readiness probe (model-loaded + trivial CUDA op) catches the stale-CUDA failure mode without turning the healthcheck into a periodic inference workload. The only structural follow-up worth considering is eliminating the duplicated vendored _readiness.py by installing just the needed module in the Parakeet image, if packaging/coupling stays manageable.

Grey Divider

File Changes

Bug fix (3)
_readiness.py Introduce stdlib-only readiness decision helper for Parakeet probe +49/-0

Introduce stdlib-only readiness decision helper for Parakeet probe

• Adds evaluate_readiness(model_loaded, cuda_ok) returning (status_code, body) so readiness logic is testable in CI without torch/nemo/GPU.

model_gear/realtime/_readiness.py


_readiness.py Vendored readiness helper for Parakeet container runtime +48/-0

Vendored readiness helper for Parakeet container runtime

• Adds a container-local copy of evaluate_readiness mirroring model_gear/realtime/_readiness.py for use by the Parakeet server template.

model_gear/templates/fleet/_readiness.py


listen_server.py Make /v1/health/ready reflect model readiness + CUDA liveness +42/-2

Make /v1/health/ready reflect model readiness + CUDA liveness

• Replaces unconditional ready responses with a cheap probe: model loaded flag plus a trivial CUDA tensor alloc/synchronize; returns 503 when not ready.

model_gear/templates/fleet/listen_server.py


Tests (2)
audio-smoke.py Add stdlib-only smoke test for /openapi.json and /v1/audio/transcriptions +202/-0

Add stdlib-only smoke test for /openapi.json and /v1/audio/transcriptions

• Adds a live smoke script that asserts audio routes are present in OpenAPI and that a multipart WAV POST returns 200 with a text field (requires a running GPU fleet).

scripts/audio-smoke.py


test_realtime_readiness.py Unit test readiness decision matrix (no torch/nemo/GPU) +54/-0

Unit test readiness decision matrix (no torch/nemo/GPU)

• Adds pytest coverage for evaluate_readiness across ready/not-ready combinations, keeping readiness semantics stable and CI-friendly.

tests/test_realtime_readiness.py


Documentation (6)
model-gear-owns-the-audio-i-o-surface-end-to-end-m.json Add devague spec frame capturing audio-surface ownership decisions +280/-0

Add devague spec frame capturing audio-surface ownership decisions

• Introduces the exported devague frame describing the ownership shift to model-gear, readiness probe intent, and operational boundaries for #39/#40.

.devague/frames/model-gear-owns-the-audio-i-o-surface-end-to-end-m.json


model-gear-owns-the-audio-i-o-surface-end-to-end-m.json Add devague plan export for audio-surface ownership implementation +279/-0

Add devague plan export for audio-surface ownership implementation

• Adds the exported task plan (t1–t6) and risks for implementing readiness probing, docs, and smoke verification.

.devague/plans/model-gear-owns-the-audio-i-o-surface-end-to-end-m.json


CHANGELOG.md Document 0.20.0 release: readiness probe, pipeline docs, smoke test +32/-0

Document 0.20.0 release: readiness probe, pipeline docs, smoke test

• Adds a 0.20.0 entry describing the Parakeet readiness fix, new realtime-pipeline docs, and the new audio smoke script.

CHANGELOG.md


2026-06-12-model-gear-owns-the-audio-i-o-surface-end-to-end-m.md Add build plan for model-gear audio surface ownership +65/-0

Add build plan for model-gear audio surface ownership

• Adds a human-readable plan enumerating tasks, acceptance criteria, and risks for closing #39/#40.

docs/plans/2026-06-12-model-gear-owns-the-audio-i-o-surface-end-to-end-m.md


realtime-pipeline.md Document audio realtime topology, ownership, bring-up, and CUDA restart runbook +226/-0

Document audio realtime topology, ownership, bring-up, and CUDA restart runbook

• Adds end-to-end operational documentation for the audio surface behind the fleet gateway, including the prior drift, readiness probe behavior, and a stale-CUDA restart procedure.

docs/realtime-pipeline.md


2026-06-12-model-gear-owns-the-audio-i-o-surface-end-to-end-m.md Add spec defining audio surface ownership and success signals +63/-0

Add spec defining audio surface ownership and success signals

• Introduces a spec capturing before/after behavior, requirements, and scope boundaries for the owned /v1/audio/* facade and readiness semantics.

docs/specs/2026-06-12-model-gear-owns-the-audio-i-o-surface-end-to-end-m.md


Other (4)
current Track active devague frame for audio-surface ownership work +1/-0

Track active devague frame for audio-surface ownership work

• Adds the current devague frame pointer used by the planning/spec workflow for this change.

.devague/current


current_plan Track active devague plan for audio-surface ownership work +1/-0

Track active devague plan for audio-surface ownership work

• Adds the current devague plan pointer used by the planning/spec workflow for this change.

.devague/current_plan


Dockerfile.parakeet Copy vendored readiness helper into Parakeet container build context +4/-0

Copy vendored readiness helper into Parakeet container build context

• Ensures _readiness.py is present in the container so listen_server.py can import readiness logic without requiring the model-gear wheel.

model_gear/templates/fleet/Dockerfile.parakeet


pyproject.toml Bump project version to 0.20.0 +1/-1

Bump project version to 0.20.0

• Updates the package version to reflect the new release containing the readiness probe, docs, and smoke tooling.

pyproject.toml


Grey Divider

Qodo Logo

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The devague-exported spec/plan H1 is the verbatim announcement sentence,
which ends in a period (MD026/no-trailing-punctuation). These are generated
planning artifacts like docs/superpowers/** — ignore them in lint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread docs/realtime-pipeline.md Outdated
Comment thread model_gear/templates/fleet/Dockerfile.parakeet
- Scaffold _readiness.py via AUDIO_TEMPLATES so `model init --fleet --audio`
  writes it (Dockerfile.parakeet COPYs it — clean init would otherwise fail
  `docker compose build stt`). [Qodo #2, comment 3402397497]
- Remove the inline fallback copy of the readiness decision from
  listen_server.py and add a drift test asserting the vendored twin matches
  the canonical model_gear/realtime/_readiness.py. [Qodo #4]
- Log CUDA readiness-probe failures (type + message) before returning 503 so
  operators can tell driver-down / OOM / stale-context apart. [Qodo #3]
- audio-smoke.py now exercises /v1/audio/speech and wires --stt-url to a
  direct-Parakeet check (was claimed-but-untested). [Qodo #5]
- docs/realtime-pipeline.md uses $HOME/.model-gear, not ~/.model-gear
  (portability rule). [Qodo #1, comment 3402397490]

275 tests pass; black/isort/flake8 + markdownlint clean. Bump 0.20.0 -> 0.20.1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@OriNachum

Copy link
Copy Markdown
Contributor Author

Fixed in 81de86a — replaced ~/.model-gear with $HOME/.model-gear in docs/realtime-pipeline.md (both occurrences), matching the README's portable style. Thanks.

  • model-gear (Claude)

@OriNachum

Copy link
Copy Markdown
Contributor Author

Good catch — real bug. Fixed in 81de86a: added fleet/_readiness.py -> _readiness.py to _compose.AUDIO_TEMPLATES so model init --fleet --audio scaffolds it, and test_init.py now asserts it's written. Also added a drift test asserting the vendored twin matches the canonical model_gear/realtime/_readiness.py.

  • model-gear (Claude)

@OriNachum

Copy link
Copy Markdown
Contributor Author

Qodo review — all 5 findings addressed in 81de86a (4 bugs + 1 rule violation). The two inline threads have per-thread replies; the other three:

275 tests pass; black/isort/flake8 + markdownlint clean. Bumped 0.20.0 → 0.20.1.

  • model-gear (Claude)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant