WolfDavid commited on
Commit
5c6321a
Β·
1 Parent(s): 4a095fc

docs(01-02): complete local foundations plan

Browse files
.planning/ROADMAP.md CHANGED
@@ -32,7 +32,7 @@ Decimal phases appear between their surrounding integers in numeric order.
32
  4. p50/p95 turn latency is measured and recorded on the deployed Space (cold and warm), and the full loop still completes with the GPU path forcibly disabled.
33
  5. LICENSES.md documents verified licenses for the exact VRM character and TTS voice that ship, including any per-character credit requirement.
34
  **Plans**: 10 plans in 7 waves
35
- - [ ] 01-02-PLAN.md β€” Toolchain, LFS arming, package skeleton, test scaffolding (local-only) [wave 1]
36
  - [ ] 01-01-PLAN.md β€” Hosting decision + Space creation + VRM sourcing (user-gated) [wave 2]
37
  - [ ] 01-04-PLAN.md β€” VOICEVOX TTS, requirements.txt, ground-truth AudioQuery fixtures [wave 2]
38
  - [ ] 01-03-PLAN.md β€” Avatar stage, shared facade + turn loop, both transports [wave 3]
@@ -109,7 +109,7 @@ Phases execute in numeric order: 1 β†’ 2 β†’ 3 β†’ 4 β†’ 5 β†’ 6
109
 
110
  | Phase | Plans Complete | Status | Completed |
111
  |-------|----------------|--------|-----------|
112
- | 1. Voice + Avatar Loop Skeleton | 0/10 | Planned | - |
113
  | 2. Japanese Language Core | 0/TBD | Not started | - |
114
  | 3. Tutoring Brain | 0/TBD | Not started | - |
115
  | 4. Accounts & Persistence | 0/TBD | Not started | - |
 
32
  4. p50/p95 turn latency is measured and recorded on the deployed Space (cold and warm), and the full loop still completes with the GPU path forcibly disabled.
33
  5. LICENSES.md documents verified licenses for the exact VRM character and TTS voice that ship, including any per-character credit requirement.
34
  **Plans**: 10 plans in 7 waves
35
+ - [x] 01-02-PLAN.md β€” Toolchain, LFS arming, package skeleton, test scaffolding (local-only) [wave 1]
36
  - [ ] 01-01-PLAN.md β€” Hosting decision + Space creation + VRM sourcing (user-gated) [wave 2]
37
  - [ ] 01-04-PLAN.md β€” VOICEVOX TTS, requirements.txt, ground-truth AudioQuery fixtures [wave 2]
38
  - [ ] 01-03-PLAN.md β€” Avatar stage, shared facade + turn loop, both transports [wave 3]
 
109
 
110
  | Phase | Plans Complete | Status | Completed |
111
  |-------|----------------|--------|-----------|
112
+ | 1. Voice + Avatar Loop Skeleton | 1/10 | In Progress | - |
113
  | 2. Japanese Language Core | 0/TBD | Not started | - |
114
  | 3. Tutoring Brain | 0/TBD | Not started | - |
115
  | 4. Accounts & Persistence | 0/TBD | Not started | - |
.planning/STATE.md CHANGED
@@ -1,3 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # Project State
2
 
3
  ## Project Reference
@@ -5,33 +19,41 @@
5
  See: .planning/PROJECT.md (updated 2026-08-08)
6
 
7
  **Core value:** A learner can hold a real, level-appropriate spoken Japanese conversation with an animated avatar that talks back β€” and measurably improve over time because the avatar remembers them.
8
- **Current focus:** Phase 1 β€” Voice + Avatar Loop Skeleton
9
 
10
  ## Current Position
11
 
12
- Phase: 1 of 6 (Voice + Avatar Loop Skeleton)
13
- Plan: 0 of TBD in current phase
14
- Status: Ready to plan
15
- Last activity: 2026-08-08 β€” Roadmap created (6 phases, 33/33 v1 requirements mapped)
16
 
17
- Progress: [β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘] 0%
 
 
18
 
19
  ## Performance Metrics
20
 
21
  **Velocity:**
22
- - Total plans completed: 0
23
- - Average duration: β€”
24
- - Total execution time: 0.0 hours
 
25
 
26
  **By Phase:**
27
 
28
  | Phase | Plans | Total | Avg/Plan |
29
  |-------|-------|-------|----------|
30
- | - | - | - | - |
 
 
 
 
 
 
31
 
32
  **Recent Trend:**
33
- - Last 5 plans: β€”
34
- - Trend: β€”
 
35
 
36
  *Updated after each plan completion*
37
 
@@ -46,6 +68,9 @@ Recent decisions affecting current work:
46
  - [Roadmap]: SudachiPy tokenization (Phase 2) lands before any level gating or grammar grounding β€” furigana, lookup, level gating, and vocab tracking all collapse without it.
47
  - [Roadmap]: Persistence (Phase 4) is deliberately after the tutor core so the event-sourced schema reflects what the assessment engine actually emits, avoiding a Phase 5 migration.
48
  - [Roadmap]: BYOK (LLMB-02) is owned by Phase 4, not Phase 3 β€” its session-only, never-leaked guarantee is verified by the same concurrent-session isolation gate as account data.
 
 
 
49
 
50
  ### Pending Todos
51
 
@@ -59,9 +84,10 @@ None yet.
59
  - **Asset licensing gates a design branch.** VOICEVOX character terms need a human read (third-party web synthesis, not just generated audio) before TTS is built around it β€” the fallback loses free mora timings and changes the lip-sync design. VRM model licenses vary per author; self-authored VRoid Studio character removes the question.
60
  - **Per-turn GPU-second cost is unmeasured.** The entire free-tier UX budget depends on this number β€” measure in Phase 1/3, do not assume.
61
  - **REQUIREMENTS.md originally miscounted v1 as 31.** Actual count is 33; traceability and coverage corrected during roadmap creation.
 
62
 
63
  ## Session Continuity
64
 
65
- Last session: 2026-08-08
66
- Stopped at: ROADMAP.md and STATE.md written; REQUIREMENTS.md traceability populated.
67
  Resume file: None
 
1
+ ---
2
+ gsd_state_version: 1.0
3
+ milestone: v1.0
4
+ milestone_name: milestone
5
+ status: unknown
6
+ stopped_at: Completed 01-02-PLAN.md (local foundations). Plan 01-01 still gated on the human hosting decision.
7
+ last_updated: "2026-08-27T00:02:37.063Z"
8
+ progress:
9
+ total_phases: 6
10
+ completed_phases: 0
11
+ total_plans: 10
12
+ completed_plans: 1
13
+ ---
14
+
15
  # Project State
16
 
17
  ## Project Reference
 
19
  See: .planning/PROJECT.md (updated 2026-08-08)
20
 
21
  **Core value:** A learner can hold a real, level-appropriate spoken Japanese conversation with an animated avatar that talks back β€” and measurably improve over time because the avatar remembers them.
22
+ **Current focus:** Phase 01 β€” voice-avatar-loop-skeleton
23
 
24
  ## Current Position
25
 
26
+ Phase: 01 (voice-avatar-loop-skeleton) β€” EXECUTING
27
+ Plan: 2 of 10 (1 complete)
 
 
28
 
29
+ **Completed:** 01-02 (local foundations β€” pytest/ruff on Python 3.12.12, Git LFS armed, `--space-url` plumbing, audio fixtures).
30
+ **Not started:** 01-01 β€” it is deliberately out of order. 01-02 is local-only and network-free precisely so it could run in parallel with 01-01's **human hosting checkpoint, which has NOT cleared**. Do not treat "Plan 2" as meaning 01-01 is done.
31
+ **Next actionable:** 01-03 (avatar transport seam) is unblocked β€” its dependencies are the test loop and package skeleton, both of which now exist. 01-01, 01-04 and 01-05 remain gated on the hosting decision and the VRM/VOICEVOX asset choices.
32
 
33
  ## Performance Metrics
34
 
35
  **Velocity:**
36
+
37
+ - Total plans completed: 1
38
+ - Average duration: 21 min
39
+ - Total execution time: 0.35 hours
40
 
41
  **By Phase:**
42
 
43
  | Phase | Plans | Total | Avg/Plan |
44
  |-------|-------|-------|----------|
45
+ | 01 | 1 | 21min | 21min |
46
+
47
+ **Per-plan detail:**
48
+
49
+ | Plan | Duration | Tasks | Files |
50
+ |------|----------|-------|-------|
51
+ | Phase 01 P02 | 21min | 3 tasks | 16 files |
52
 
53
  **Recent Trend:**
54
+
55
+ - Last 5 plans: 01-02 (21min)
56
+ - Trend: β€” (single data point)
57
 
58
  *Updated after each plan completion*
59
 
 
68
  - [Roadmap]: SudachiPy tokenization (Phase 2) lands before any level gating or grammar grounding β€” furigana, lookup, level gating, and vocab tracking all collapse without it.
69
  - [Roadmap]: Persistence (Phase 4) is deliberately after the tutor core so the event-sourced schema reflects what the assessment engine actually emits, avoiding a Phase 5 migration.
70
  - [Roadmap]: BYOK (LLMB-02) is owned by Phase 4, not Phase 3 β€” its session-only, never-leaked guarantee is verified by the same concurrent-session isolation gate as account data.
71
+ - [Phase 01]: Ruff excludes *.md: ruff 0.16 formats Python blocks embedded in Markdown, which made the phase's own planning docs fail the lint gate. Lint governs shipped Python, not prose.
72
+ - [Phase 01]: uv.lock is committed so a Space rebuild resolves the same dependency set that passed locally; requirements.txt (plan 01-04) remains the Space's contract.
73
+ - [Phase 01]: Git LFS armed for .vrm/.vvm/.wav/.onnx in Wave 1, before any binary exists - retires the 10 MiB non-LFS push rejection ahead of plans 01-01 and 01-04.
74
 
75
  ### Pending Todos
76
 
 
84
  - **Asset licensing gates a design branch.** VOICEVOX character terms need a human read (third-party web synthesis, not just generated audio) before TTS is built around it β€” the fallback loses free mora timings and changes the lip-sync design. VRM model licenses vary per author; self-authored VRoid Studio character removes the question.
85
  - **Per-turn GPU-second cost is unmeasured.** The entire free-tier UX budget depends on this number β€” measure in Phase 1/3, do not assume.
86
  - **REQUIREMENTS.md originally miscounted v1 as 31.** Actual count is 33; traceability and coverage corrected during roadmap creation.
87
+ - **Phase 1 plan frontmatter over-claims shared requirements β€” do not blind-run `requirements mark-complete`.** DPLY-01 appears in the `requirements:` field of plans 01-01, 01-02, 01-05, 01-09 and 01-10, but it is only *satisfied* by 01-05 (`test_space_reachable`). Executing 01-02 marked it Complete; this was reverted, and DPLY-01 is correctly `Pending`. The same over-claiming applies to AVTR-01/02, VOIC-02/03/04/05 and DPLY-04 across plans 01-09 and 01-10. Verify a requirement's actual acceptance test has run before checking it off.
88
 
89
  ## Session Continuity
90
 
91
+ Last session: 2026-08-27T00:02:37.058Z
92
+ Stopped at: Completed 01-02-PLAN.md (local foundations). Plan 01-01 still gated on the human hosting decision.
93
  Resume file: None
.planning/config.json CHANGED
@@ -22,7 +22,8 @@
22
  "node_repair_budget": 2,
23
  "ui_phase": true,
24
  "ui_safety_gate": true,
25
- "text_mode": false
 
26
  },
27
  "hooks": {
28
  "context_warnings": true
 
22
  "node_repair_budget": 2,
23
  "ui_phase": true,
24
  "ui_safety_gate": true,
25
+ "text_mode": false,
26
+ "_auto_chain_active": false
27
  },
28
  "hooks": {
29
  "context_warnings": true
.planning/phases/01-voice-avatar-loop-skeleton/01-02-SUMMARY.md ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ phase: 01-voice-avatar-loop-skeleton
3
+ plan: 02
4
+ subsystem: testing
5
+ tags: [pytest, ruff, uv, playwright, git-lfs, python-3.12, numpy, wav-fixtures]
6
+
7
+ # Dependency graph
8
+ requires: []
9
+ provides:
10
+ - "pytest + ruff toolchain on Python 3.12.12, quick loop measured at ~1.0s"
11
+ - "Git LFS armed for .vrm / .vvm / .wav / .onnx before any binary exists in the repo"
12
+ - "src/japanese_avatar package skeleton (ui, voice, telemetry) every later plan writes into"
13
+ - "tests/conftest.py with the single --space-url option and deployed-marker skip behaviour"
14
+ - "Deterministic 30s silence and 30s cafe-noise WAV fixtures for VOIC-02"
15
+ - "uv.lock pinning the resolved dependency set for reproducible Space rebuilds"
16
+ affects: [01-01, 01-03, 01-04, 01-05, 01-06, 01-07, 01-08, 01-09, 01-10]
17
+
18
+ # Tech tracking
19
+ tech-stack:
20
+ added: [pytest 9.1.1, pytest-playwright 0.9.0, playwright 1.62.0, ruff 0.16.4, numpy 2.5.2, gradio 6.22.0, spaces 0.51.1, huggingface_hub 1.28.0]
21
+ patterns:
22
+ - "pythonpath = [\"src\", \".\"] so `import japanese_avatar` and `import app` both work under pytest with no editable install"
23
+ - "Deployed tests skip, never fail, when --space-url is absent"
24
+ - "Fixtures for later plans (speech_ja.wav, synth_meta.json) skip rather than error until those plans land"
25
+ - "Binary fixtures are generated by a committed deterministic script, not hand-placed"
26
+
27
+ key-files:
28
+ created:
29
+ - pyproject.toml
30
+ - .python-version
31
+ - .gitattributes
32
+ - .gitignore
33
+ - uv.lock
34
+ - src/japanese_avatar/__init__.py
35
+ - tests/conftest.py
36
+ - tests/test_scaffold.py
37
+ - tests/fixtures/make_fixtures.py
38
+ - tests/fixtures/silence_30s.wav
39
+ - tests/fixtures/cafe_noise_30s.wav
40
+ modified: []
41
+
42
+ key-decisions:
43
+ - "Excluded *.md from ruff: ruff 0.16 formats Python blocks embedded in Markdown, which made the phase's own planning docs fail the lint gate"
44
+ - "Committed uv.lock so a Space rebuild resolves the same dependency set that passed locally"
45
+ - "Recorded the cafe-noise fixture's measured RMS (0.0577) in the generator docstring so plan 01-07 tunes against a real number"
46
+
47
+ patterns-established:
48
+ - "Lint gate governs shipped Python only; prose and design snippets are out of ruff's scope"
49
+ - "Every E2E test reaches the Space through one --space-url option; no test hardcodes a URL"
50
+ - "LFS patterns are armed ahead of the binaries they protect, and asserted by a test that runs before those files exist"
51
+
52
+ requirements-completed: [] # DPLY-01 is listed in this plan's frontmatter but is NOT satisfied here β€” see "Requirement Status" below
53
+ requirements-advanced: [DPLY-01]
54
+
55
+ # Metrics
56
+ duration: 21min
57
+ completed: 2026-08-26
58
+ ---
59
+
60
+ # Phase 01 Plan 02: Local Foundations Summary
61
+
62
+ **A repo that lints and tests green on Python 3.12.12 in ~1.0s, with Git LFS armed for `.vrm`/`.vvm`/`.wav`/`.onnx` before the first binary lands and deterministic 30s silence/noise fixtures already committed as LFS pointers.**
63
+
64
+ ## Performance
65
+
66
+ - **Duration:** ~21 min
67
+ - **Started:** 2026-08-26T23:47Z
68
+ - **Completed:** 2026-08-27T00:08Z
69
+ - **Tasks:** 3 of 3
70
+ - **Files created:** 16 tracked (13 source/config + `uv.lock` + 2 LFS binaries), verified by `git diff --name-only 84055d7 HEAD`
71
+
72
+ ## Accomplishments
73
+
74
+ - Python pinned to **3.12.12** and actually installed via `uv python install`; `uv run python -c "import sys; assert sys.version_info[:2]==(3,12)"` reports `3.12.12 (main, Feb 12 2026)`. The machine's PATH Python is 3.11.0 and is now irrelevant to this project. This closes RESEARCH Pitfall 9 (the habit of copying `3.11` from the account's eight existing Spaces, which is valid on `cpu-basic` and invalid on ZeroGPU).
75
+ - **Git LFS armed before any binary existed anywhere in the repo.** `.gitattributes` was committed in Task 1; the first binaries arrived in Task 3 and landed as pointers automatically.
76
+ - Quick loop and lint gate both green and fast β€” the 15s Nyquist feedback budget from `01-VALIDATION.md` is met with ~14s of headroom.
77
+ - Package skeleton created at every location `01-RESEARCH.md` "Recommended Project Structure" specifies, so no later plan has to invent a path.
78
+ - `--space-url` plumbing verified end-to-end, including the skip path.
79
+ - Silence and cafe-noise fixtures generated, proven byte-reproducible, and committed through LFS.
80
+
81
+ ### Measured numbers required by the plan's `<output>` block
82
+
83
+ | Measurement | Value |
84
+ |---|---|
85
+ | **Quick-loop runtime** (`pytest tests/ -x -q --ignore=tests/e2e`) | **0.956 s** (three timed runs: 1151 ms, 1114 ms, 956 ms) β€” budget is 15 s |
86
+ | **Cafe-noise fixture RMS** | **0.057699** (= **-24.8 dBFS**); peak 0.135712 β€” plan 01-07 tunes its modulation threshold against this |
87
+ | **`git check-attr filter -- avatar/assets/tutor.vrm`** | `filter: lfs` β€” **confirmed while the file does not exist** |
88
+ | **`git check-attr filter -- voicevox/model/zundamon.vvm`** | `filter: lfs` β€” **confirmed while the file does not exist** |
89
+
90
+ Both fixtures: 24000 Hz, mono, 16-bit PCM, 720000 frames, **30.000000 s** exactly, 1 440 044 bytes each.
91
+
92
+ Regeneration is byte-identical. SHA-256 before and after a second `make_fixtures.py` run:
93
+
94
+ - `silence_30s.wav` β†’ `22a4da1b6841f7db580ce7f434cb659e7f7d4b0ec326c8ce3b0b8c333bc05e26`
95
+ - `cafe_noise_30s.wav` β†’ `fdaae2c7791b7b714e1da1f21dd4c46b8391a62e7adc86e98111f85e5dc0a797`
96
+
97
+ The LFS pointer's `oid sha256` for `cafe_noise_30s.wav` matches that hash exactly, confirming the clean filter ran rather than the raw blob being stored.
98
+
99
+ ## Task Commits
100
+
101
+ Each task was committed atomically:
102
+
103
+ 1. **Task 1: Python toolchain, LFS config, package skeleton, lint and test config** β€” `b0821c5` (chore)
104
+ 2. **Task 2: Shared fixtures and the `--space-url` plumbing** β€” `ccf5848` (test)
105
+ 3. **Task 3: Deterministic silence and noise fixtures** β€” `4a095fc` (test)
106
+
107
+ ## Files Created/Modified
108
+
109
+ - `.python-version` β€” `3.12.12`, the ZeroGPU-legal interpreter
110
+ - `.gitattributes` β€” LFS patterns for `.vrm`, `.vvm`, `.wav`, `.onnx` (4 lines, all `filter=lfs`)
111
+ - `.gitignore` β€” `.venv/`, `__pycache__/`, `*.pyc`, `.pytest_cache/`, `.ruff_cache/`, `node_modules/`, `.env`, `voicevox_runtime/`, `test-results/`
112
+ - `pyproject.toml` β€” pytest ini options (`testpaths`, `pythonpath`, `--strict-markers`, `deployed`/`slow` markers), ruff config, dev extra, hatchling wheel targeting `src/japanese_avatar`
113
+ - `uv.lock` β€” resolved dependency set
114
+ - `src/japanese_avatar/__init__.py` β€” `__version__ = "0.1.0"`
115
+ - `src/japanese_avatar/{ui,voice,telemetry}/__init__.py` β€” empty package markers for plans 01-03/04/06/08
116
+ - `tests/__init__.py`, `tests/e2e/__init__.py` β€” package markers
117
+ - `tests/test_scaffold.py` β€” 6 tests: interpreter version, package importability, config shape, LFS arming, fixture durations, fixture loudness
118
+ - `tests/conftest.py` β€” `--space-url` option, `deployed` skip hook, `space_url` / `fixtures_dir` / `silence_wav` / `cafe_noise_wav` / `speech_wav` / `synth_meta` fixtures, `wav_duration_seconds` helper
119
+ - `tests/fixtures/make_fixtures.py` β€” deterministic generator (seed `20260826`)
120
+ - `tests/fixtures/silence_30s.wav`, `tests/fixtures/cafe_noise_30s.wav` β€” LFS-tracked
121
+
122
+ ## Decisions Made
123
+
124
+ - **Ruff governs Python, not prose.** Ruff 0.16 lints and formats Python code blocks embedded in Markdown. `ruff format --check .` therefore wanted to reformat seven `.planning/**/*.md` files (design snippets in `01-03-PLAN.md`, `01-04-PLAN.md`, `01-06-PLAN.md`, `01-08-PLAN.md`, `01-RESEARCH.md`, `research/ARCHITECTURE.md`, `research/STACK.md`). Adding `*.md` to `extend-exclude` keeps the gate meaningful for shipped code and stops future `docs/*.md` (plans 01-01/04/05/07/10 all write one) from breaking it.
125
+ - **`uv.lock` is committed.** `CLAUDE.md` calls the lockfile the reason to use uv at all β€” it makes "works locally, breaks on Space rebuild" reproducible. Leaving it untracked would have discarded that. The Space still consumes `requirements.txt` (plan 01-04 owns it); the lock is the local source of truth.
126
+ - **The cafe-noise docstring now states the measured level.** It claimed `~-16 dBFS`; the fixture measures `-24.8 dBFS`. Since plan 01-07 reads this file to calibrate its gate, a 9 dB error in the comment was worth correcting. The generator's arithmetic was not touched, so the WAVs are unchanged.
127
+
128
+ ## Deviations from Plan
129
+
130
+ ### Auto-fixed Issues
131
+
132
+ **1. [Rule 3 - Blocking] `ruff format --check .` failed on Markdown planning documents**
133
+
134
+ - **Found during:** Task 1 (lint gate verification)
135
+ - **Issue:** Ruff 0.16.4 formats Python code fences inside Markdown. `ruff format --check .` exited 1 with "7 files would be reformatted", all of them `.planning/` docs and research notes. The plan's acceptance criterion requires exit 0, and the plan's `extend-exclude` only listed `avatar/vendor`. Left unfixed this would have blocked every subsequent plan's lint gate, exactly the "accumulated ruff debt" failure mode `CLAUDE.md` warns about.
136
+ - **Fix:** `extend-exclude = ["avatar/vendor", "*.md"]` in `[tool.ruff]`, with a comment explaining why.
137
+ - **Files modified:** `pyproject.toml`
138
+ - **Verification:** `uv run ruff check .` β†’ "All checks passed!" (exit 0); `uv run ruff format --check .` β†’ "9 files already formatted" (exit 0). No `.planning/` file was modified.
139
+ - **Committed in:** `b0821c5` (Task 1 commit)
140
+
141
+ **2. [Rule 2 - Missing Critical] `uv.lock` was not in the plan's `files_modified`**
142
+
143
+ - **Found during:** Task 1 (dependency install)
144
+ - **Issue:** `uv sync --extra dev` generates `uv.lock`. The plan neither listed it nor gitignored it, so it would have been left untracked β€” discarding the reproducibility guarantee that is `CLAUDE.md`'s stated reason for choosing uv.
145
+ - **Fix:** Committed `uv.lock` alongside `pyproject.toml`.
146
+ - **Files modified:** `uv.lock` (new)
147
+ - **Verification:** `git status --short` shows no untracked files.
148
+ - **Committed in:** `b0821c5` (Task 1 commit)
149
+
150
+ **3. [Rule 1 - Doc bug] Cafe-noise docstring overstated the fixture's level by ~9 dB**
151
+
152
+ - **Found during:** Task 3 (fixture measurement)
153
+ - **Issue:** The generator docstring supplied by the plan claims `~-16 dBFS`. Measured RMS is 0.057699 = -24.8 dBFS. Plan 01-07 reads this file to calibrate its speech/noise gate against the fixture, so the wrong number is actively misleading.
154
+ - **Fix:** Docstring now states the measured RMS and peak. Signal math untouched β€” fixtures are byte-identical to the first generation.
155
+ - **Files modified:** `tests/fixtures/make_fixtures.py`
156
+ - **Verification:** SHA-256 of both WAVs identical across regeneration; RMS assertion (`> 0.02`) passes at 0.0577.
157
+ - **Committed in:** `4a095fc` (Task 3 commit)
158
+
159
+ ### Acceptance criteria restated rather than skipped
160
+
161
+ Two of Task 2's acceptance criteria were literal `grep -c` counts that contradict the code the plan itself specifies. `grep -c` counts *matching lines*, not occurrences:
162
+
163
+ - `grep -c "addoption" tests/conftest.py` expected `1`, returns **`2`** β€” because the hook's own name, `def pytest_addoption(parser):`, contains the substring, in addition to the `parser.addoption(` call.
164
+ - `grep -c '"--space-url"' tests/conftest.py` expected `1`, returns **`3`** β€” the option is registered once and then read in `pytest_collection_modifyitems` and in the `space_url` fixture, exactly as the plan's own code listing does it.
165
+
166
+ The substantive property both criteria are reaching for β€” **one option, registered exactly once** β€” was verified directly: `grep -c 'parser\.addoption' tests/conftest.py` returns **`1`**. No code was contorted to satisfy a miscounted grep. The third criterion (`6` fixture/helper definitions) matched exactly as written.
167
+
168
+ ---
169
+
170
+ **Total deviations:** 3 auto-fixed (1 blocking, 1 missing-critical, 1 doc bug) + 2 acceptance criteria restated
171
+ **Impact on plan:** No scope creep. Deviation 1 was required for the plan's own lint criterion to be satisfiable at all; 2 and 3 protect later plans from the failure modes this plan exists to prevent.
172
+
173
+ ## Issues Encountered
174
+
175
+ - **The `deployed` skip path needed a temporary test to prove.** The plan asks for a throwaway `@pytest.mark.deployed` test. Created, exercised both ways, deleted. Observed output, as required for the record:
176
+ - Without the option: `SKIPPED [1] tests\test_tmp_deployed_probe.py:4: needs --space-url (deployed Space)` β€” **skipped, not failed**.
177
+ - With `--space-url=https://example.invalid`: `1 passed`. No network request is made; the fixture only normalises the string.
178
+ - `git status --short` confirms the probe left no trace.
179
+ - One transient `Failed to write cache file ... .ruff_cache ... Access is denied (os error 5)` warning on Windows during a concurrent ruff invocation. Cosmetic; the run itself reported "All checks passed!" and subsequent runs are clean.
180
+
181
+ ## Requirement Status
182
+
183
+ **DPLY-01 remains `Pending`. It was deliberately NOT marked complete.**
184
+
185
+ This plan's frontmatter carries `requirements: [DPLY-01]`, but DPLY-01 is *"App is live as a public Hugging Face Space on the WolfDavid profile"*, and `01-VALIDATION.md` binds it to `tests/e2e/test_avatar_loop.py::test_space_reachable`, which **plan 01-05 creates**. DPLY-01 is shared across plans 01-01, 01-02, 01-05, 01-09 and 01-10; this plan contributes the test infrastructure that requirement will eventually be verified through, and nothing more. A local-only plan that creates no Space cannot satisfy "the Space is live".
186
+
187
+ `requirements mark-complete DPLY-01` was run as part of the standard state-update sequence, flipped the checkbox and the traceability row, and was **reverted** (`git checkout -- .planning/REQUIREMENTS.md`). `REQUIREMENTS.md` line 60 reads `- [ ] **DPLY-01**` and line 131 reads `| DPLY-01 | Phase 1 | Pending |`, both verified after the revert. Marking it complete would have told the phase verifier a deployed Space exists when none does.
188
+
189
+ ## Constraint Compliance
190
+
191
+ The plan is local-only and parallel-safe with the un-cleared human hosting gate in plan 01-01. Verified:
192
+
193
+ - **No Space was created and no Hugging Face API was contacted.** No `hf` CLI call, no `huggingface_hub` call, no `README.md` front-matter written. Space manifest and deploy remain with plans 01-04 and 01-05, where the plan assigns them.
194
+ - **No `git push` occurred β€” and could not have.** `git remote -v` returns empty; this repo has **no remote configured at all**. `git reflog` shows only the three task commits.
195
+ - **No money was spent.** No PRO subscription, no paid resource.
196
+ - Network egress was limited to package/toolchain acquisition explicitly instructed by the plan's own `<action>` blocks: `uv python install 3.12.12` (20.8 MiB), `uv sync --extra dev` (PyPI), `uv run playwright install chromium`. These are the "Framework install" line item in `01-VALIDATION.md` Wave 0 Requirements. The prohibition is on HF/Space network dependency, which was fully honoured.
197
+ - **Zero AI tutoring in scope.** No LLM, no level gating, no grammar database, no accounts, no database.
198
+
199
+ ## Environment Note
200
+
201
+ Playwright's cached Chromium (`chromium-1223`, `chromium-1228`) was present, but Playwright 1.62.0 requires **build 1234**, so `playwright install chromium` did download (~114.5 MiB) into `chromium-1234` and `chromium_headless_shell-1234`. The pre-existing cache did not save the download. `uv run playwright --version` β†’ `Version 1.62.0`.
202
+
203
+ Resolved dev toolchain: pytest **9.1.1**, pytest-playwright 0.9.0, playwright 1.62.0, ruff 0.16.4, numpy **2.5.2**. Runtime pins resolved exactly as specified: gradio 6.22.0, spaces 0.51.1, huggingface_hub 1.28.0.
204
+
205
+ ## Known Stubs
206
+
207
+ The empty `__init__.py` files at `src/japanese_avatar/{ui,voice,telemetry}/` are intentional package markers, not stubs β€” the plan's `<interfaces>` block assigns each module to a specific later plan (`ui/blocks.py` β†’ 01-08, `ui/avatar_component.py` β†’ 01-03, `voice/tts.py` β†’ 01-04, `voice/visemes.py` β†’ 01-06, `voice/models.py` β†’ 01-04, `telemetry/timings.py` β†’ 01-08). Nothing renders from them and no data path depends on them yet.
208
+
209
+ `tests/conftest.py`'s `speech_wav` and `synth_meta` fixtures deliberately `pytest.skip` until plan 01-04 generates `speech_ja.wav` and `synth_meta.json`. This is the plan's explicit design: a Wave 1 plan must not leave the suite red for plans that have not run yet.
210
+
211
+ ## User Setup Required
212
+
213
+ None β€” no external service configuration required by this plan. The hosting decision and Space creation remain gated behind the human checkpoint in plan 01-01.
214
+
215
+ ## Next Phase Readiness
216
+
217
+ Ready for the rest of Phase 1:
218
+
219
+ - **Plan 01-01** can commit `avatar/assets/tutor.vrm` the moment the VRM exists β€” LFS is armed and verified for that exact path.
220
+ - **Plan 01-04** can commit the ~60 MB `.vvm` and the Open JTalk dictionary; `voicevox/model/*.vvm` already resolves to `filter: lfs`. This is RESEARCH Pitfall 6's "10 MiB non-LFS push rejection" retired before it could occur.
221
+ - **Plans 01-03/05/07/09/10** can write `tests/e2e/*` against `--space-url` with no further plumbing.
222
+ - **Plan 01-06** has a working pytest loop for `test_visemes.py`, the densest test file in the phase.
223
+ - **Plan 01-07** has both non-speech fixtures and the measured noise RMS (0.0577) to calibrate against.
224
+
225
+ Carried forward, unchanged by this plan:
226
+
227
+ - The hosting model is still unresolved (ZeroGPU eligibility vs PRO) β€” plan 01-01's human gate.
228
+ - VOICEVOX character terms still need a human read before TTS is built around them.
229
+ - Per-turn GPU-second cost remains unmeasured.
230
+
231
+ ## Self-Check: PASSED
232
+
233
+ All 16 files claimed created exist on disk. All 3 task commit hashes (`b0821c5`, `ccf5848`, `4a095fc`) resolve in `git log --all`. Dependency versions in the frontmatter were corrected against `importlib.metadata` (pytest 9.0.2 β†’ **9.1.1**, numpy 2.4.1 β†’ **2.5.2**) and the Playwright browser-build note was corrected against the on-disk cache (**1234**, not 1235) rather than left as an unverified assertion. File count corrected 17 β†’ **16** against `git diff --name-only`.
234
+
235
+ Full plan verification block re-run after the final task commit:
236
+
237
+ | Check | Result |
238
+ |---|---|
239
+ | `pytest tests/ -x -q --ignore=tests/e2e` | 6 passed, **0.956 s** |
240
+ | `ruff check . && ruff format --check .` | "All checks passed!" / "9 files already formatted", exit 0 |
241
+ | `git check-attr filter -- avatar/assets/tutor.vrm voicevox/model/zundamon.vvm` | both `filter: lfs` |
242
+ | `git lfs ls-files` | both WAV fixtures listed |
243
+ | `pytest tests/ -q --space-url=https://example.invalid --collect-only` | exit 0 |
244
+ | `git remote -v` | empty β€” no push was possible |
245
+
246
+ ---
247
+ *Phase: 01-voice-avatar-loop-skeleton*
248
+ *Completed: 2026-08-26*