Spaces:
Running on Zero
Running on Zero
chore(01-08): surface the synthesiser warm-up time in the app log and record the SC-4 guard
Browse filesapp.py configures INFO logging so the warm-up line blocks.warm_synthesizer emits on the
first page load is visible in the Space log (measured 2.12 s in a fresh process). Marks
the SC-4 static-guard row green in 01-VALIDATION.md and logs the deferred items found
during the plan.
.planning/phases/01-voice-avatar-loop-skeleton/01-VALIDATION.md
CHANGED
|
@@ -66,7 +66,7 @@ the planner MUST bind each row to a task and the executor MUST fill in Status.
|
|
| 66 |
| VOIC-05 | p50/p95 over β₯30 warm turns against the deployed Space β `docs/LATENCY.md` | harness (deployed) | `pytest tests/e2e/test_latency_harness.py --space-url=$SPACE_URL` | β W0 | β¬ pending |
|
| 67 |
| VOIC-05 | Cold-start turn measured after Space pause/restart | **manual (deployed)** | record in `docs/LATENCY.md` with Space revision SHA | β W0 | β¬ pending |
|
| 68 |
| SC-4 | Full loop completes with `DISABLE_GPU=1` on the Space | E2E (deployed) | `pytest tests/e2e/test_avatar_loop.py -x` against GPU-disabled Space | β W0 | β¬ pending |
|
| 69 |
-
| SC-4 | Static guard: no `@spaces.GPU` anywhere on the turn path | unit | `pytest tests/test_no_gpu_on_turn_path.py -x` (AST scan) |
|
| 70 |
| DPLY-01 | Public Space returns HTTP 200 and the app shell paints | E2E (deployed) | `pytest tests/e2e/test_avatar_loop.py::test_space_reachable -x` | β W0 | β¬ pending |
|
| 71 |
| DPLY-04 | Credit string `VOICEVOX:γγγ γγ` + flow-down terms notice present and visible | E2E | `pytest tests/e2e/test_avatar_loop.py::test_credits_visible -x` | β W0 | β¬ pending |
|
| 72 |
| DPLY-04 | `vrm.meta` embedded license matches the `LICENSES.md` entry | E2E | `pytest tests/e2e/test_avatar_loop.py::test_vrm_meta_matches_licenses -x` | β W0 | β¬ pending |
|
|
@@ -81,7 +81,7 @@ the planner MUST bind each row to a task and the executor MUST fill in Status.
|
|
| 81 |
- [ ] `tests/conftest.py` β canned `AudioQuery` JSON, golden timeline, silence/noise/speech WAV fixtures, `--space-url` option
|
| 82 |
- [ ] `tests/test_visemes.py` β AVTR-02, VOIC-03 (densest test file in the phase)
|
| 83 |
- [ ] `tests/test_tts_contract.py` β VOIC-01
|
| 84 |
-
- [
|
| 85 |
- [ ] `tests/e2e/test_avatar_loop.py` β AVTR-01, VOIC-02/03/04/05, DPLY-01/04
|
| 86 |
- [ ] `tests/e2e/test_latency_harness.py` β VOIC-05, emits `docs/LATENCY.md`
|
| 87 |
- [ ] Fixture audio β Japanese speech WAV, 30s silence, 30s cafΓ© noise
|
|
|
|
| 66 |
| VOIC-05 | p50/p95 over β₯30 warm turns against the deployed Space β `docs/LATENCY.md` | harness (deployed) | `pytest tests/e2e/test_latency_harness.py --space-url=$SPACE_URL` | β W0 | β¬ pending |
|
| 67 |
| VOIC-05 | Cold-start turn measured after Space pause/restart | **manual (deployed)** | record in `docs/LATENCY.md` with Space revision SHA | β W0 | β¬ pending |
|
| 68 |
| SC-4 | Full loop completes with `DISABLE_GPU=1` on the Space | E2E (deployed) | `pytest tests/e2e/test_avatar_loop.py -x` against GPU-disabled Space | β W0 | β¬ pending |
|
| 69 |
+
| SC-4 | Static guard: no `@spaces.GPU` anywhere on the turn path | unit | `pytest tests/test_no_gpu_on_turn_path.py -x` (AST scan) | β
01-08 | β
green (3 passed, 2026-09-06; the ZeroGPU probe in app.py is carved out by name and proven unreachable from `blocks.turn`) |
|
| 70 |
| DPLY-01 | Public Space returns HTTP 200 and the app shell paints | E2E (deployed) | `pytest tests/e2e/test_avatar_loop.py::test_space_reachable -x` | β W0 | β¬ pending |
|
| 71 |
| DPLY-04 | Credit string `VOICEVOX:γγγ γγ` + flow-down terms notice present and visible | E2E | `pytest tests/e2e/test_avatar_loop.py::test_credits_visible -x` | β W0 | β¬ pending |
|
| 72 |
| DPLY-04 | `vrm.meta` embedded license matches the `LICENSES.md` entry | E2E | `pytest tests/e2e/test_avatar_loop.py::test_vrm_meta_matches_licenses -x` | β W0 | β¬ pending |
|
|
|
|
| 81 |
- [ ] `tests/conftest.py` β canned `AudioQuery` JSON, golden timeline, silence/noise/speech WAV fixtures, `--space-url` option
|
| 82 |
- [ ] `tests/test_visemes.py` β AVTR-02, VOIC-03 (densest test file in the phase)
|
| 83 |
- [ ] `tests/test_tts_contract.py` β VOIC-01
|
| 84 |
+
- [x] `tests/test_no_gpu_on_turn_path.py` β SC-4 static AST scan (plan 01-08)
|
| 85 |
- [ ] `tests/e2e/test_avatar_loop.py` β AVTR-01, VOIC-02/03/04/05, DPLY-01/04
|
| 86 |
- [ ] `tests/e2e/test_latency_harness.py` β VOIC-05, emits `docs/LATENCY.md`
|
| 87 |
- [ ] Fixture audio β Japanese speech WAV, 30s silence, 30s cafΓ© noise
|
.planning/phases/01-voice-avatar-loop-skeleton/deferred-items.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Deferred items β Phase 01
|
| 2 |
+
|
| 3 |
+
Out-of-scope discoveries logged during execution, not fixed in the plan that found them.
|
| 4 |
+
|
| 5 |
+
## Logged by 01-08 (2026-09-06)
|
| 6 |
+
|
| 7 |
+
- **"Better accuracy" ASR toggle** (`MODELS.accurate` = whisper-large-v3-turbo q4f16, WebGPU only).
|
| 8 |
+
01-07 handed the control to 01-08; 01-08's task list does not include it and no VOIC-02 acceptance
|
| 9 |
+
row needs it. Building it means re-creating the ASR instance in `turn-loop.js` (the model is fixed
|
| 10 |
+
at `createAsr`), so it is a small turn-loop feature, not a host.js button. Candidate for 01-10 polish.
|
| 11 |
+
- **`tests/e2e/test_asr_standalone.py` under full-fleet load** β the pre-existing flake (fake-mic
|
| 12 |
+
`%noloop` WAV finishing before `getUserMedia` attaches). Passed 7/7 in both whole-suite runs today;
|
| 13 |
+
still watched.
|
| 14 |
+
- **Synthesis speed on this machine** β `synthesis_ms` for γγγ«γ‘γ― measured 1.6β1.7 s in a headed
|
| 15 |
+
browser session and 3.3β4.0 s in an idle bare process today, versus the 1.215 s recorded in
|
| 16 |
+
`docs/VOICEVOX-SETUP.md` on 2026-08-27. Not a code change; noted so 01-10's latency harness treats
|
| 17 |
+
the deployed Space's number as the only one that counts. Under headless SwiftShader rendering the
|
| 18 |
+
same call takes 14β29 s (CPU starvation), which is why the parity suite's `lastTurnMs` is not a
|
| 19 |
+
latency measurement.
|
| 20 |
+
- **`THREE.Clock` β `THREE.Timer` and `removeUnnecessaryJoints`** deprecations: unchanged, still
|
| 21 |
+
01-10's while vendoring.
|
app.py
CHANGED
|
@@ -1,16 +1,17 @@
|
|
| 1 |
"""Space entry point: assembly only. The layout and the turn live in japanese_avatar.ui.blocks."""
|
| 2 |
|
|
|
|
| 3 |
import os
|
| 4 |
import sys
|
| 5 |
from pathlib import Path
|
| 6 |
|
| 7 |
import spaces
|
| 8 |
|
| 9 |
-
# The Space
|
| 10 |
-
# repository, so the src/ layout is not on sys.path there (RUNTIME_ERROR on the first deploy).
|
| 11 |
_SRC = Path(__file__).resolve().parent / "src"
|
| 12 |
if str(_SRC) not in sys.path:
|
| 13 |
sys.path.insert(0, str(_SRC))
|
|
|
|
| 14 |
|
| 15 |
from japanese_avatar.ui.blocks import build_blocks # noqa: E402
|
| 16 |
|
|
@@ -20,9 +21,8 @@ def gpu_disabled() -> bool:
|
|
| 20 |
return os.environ.get("DISABLE_GPU", "0").strip().lower() in {"1", "true", "yes"}
|
| 21 |
|
| 22 |
|
| 23 |
-
# ZeroGPU refuses to run a Space with no @spaces.GPU function (
|
| 24 |
-
#
|
| 25 |
-
# not on the turn path, nothing calls it, and tests/test_no_gpu_on_turn_path.py proves both.
|
| 26 |
@spaces.GPU(duration=1)
|
| 27 |
def zerogpu_probe() -> str:
|
| 28 |
"""The GPU entry point ZeroGPU requires to exist. Deliberately unreachable in Phase 1."""
|
|
|
|
| 1 |
"""Space entry point: assembly only. The layout and the turn live in japanese_avatar.ui.blocks."""
|
| 2 |
|
| 3 |
+
import logging
|
| 4 |
import os
|
| 5 |
import sys
|
| 6 |
from pathlib import Path
|
| 7 |
|
| 8 |
import spaces
|
| 9 |
|
| 10 |
+
# The Space never pip-installs this repo, so the src/ layout is not on sys.path there.
|
|
|
|
| 11 |
_SRC = Path(__file__).resolve().parent / "src"
|
| 12 |
if str(_SRC) not in sys.path:
|
| 13 |
sys.path.insert(0, str(_SRC))
|
| 14 |
+
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s: %(message)s")
|
| 15 |
|
| 16 |
from japanese_avatar.ui.blocks import build_blocks # noqa: E402
|
| 17 |
|
|
|
|
| 21 |
return os.environ.get("DISABLE_GPU", "0").strip().lower() in {"1", "true", "yes"}
|
| 22 |
|
| 23 |
|
| 24 |
+
# ZeroGPU refuses to run a Space with no @spaces.GPU function (docs/HOSTING.md). This probe only
|
| 25 |
+
# satisfies that scan: nothing calls it, and tests/test_no_gpu_on_turn_path.py proves both.
|
|
|
|
| 26 |
@spaces.GPU(duration=1)
|
| 27 |
def zerogpu_probe() -> str:
|
| 28 |
"""The GPU entry point ZeroGPU requires to exist. Deliberately unreachable in Phase 1."""
|