diff --git a/.planning/phases/02-audio-synthesis-engine/02-01-PLAN.md b/.planning/phases/02-audio-synthesis-engine/02-01-PLAN.md index aeddffc..8d6c2dd 100644 --- a/.planning/phases/02-audio-synthesis-engine/02-01-PLAN.md +++ b/.planning/phases/02-audio-synthesis-engine/02-01-PLAN.md @@ -127,7 +127,7 @@ type WindowSnapshot struct { 6. Verify CGo build works by running `CGO_ENABLED=1 go build ./...` — should succeed with no errors. -NOTE: Do NOT add go-audio/wav. Per research recommendation, skip the WAV intermediate and write PCM bytes directly to LameWriter. This eliminates a dependency and avoids the io.WriteSeeker complication. +NOTE: Skipping go-audio/wav — per CONTEXT.md Claude's Discretion grant for "WAV intermediate format usage," the WAV intermediate is unnecessary. Phase 2 research (Pitfall 4) confirmed go-audio/wav requires io.WriteSeeker which bytes.Buffer does not satisfy. Writing interleaved int16 PCM bytes directly to go-lame's LameWriter.Write() is simpler and eliminates one dependency. CLAUDE.md updated to reflect this decision. go version && gcc --version && ffprobe -version && grep "go-lame" go.mod && CGO_ENABLED=1 go build ./... diff --git a/.planning/phases/02-audio-synthesis-engine/02-03-PLAN.md b/.planning/phases/02-audio-synthesis-engine/02-03-PLAN.md index 890b049..9438a47 100644 --- a/.planning/phases/02-audio-synthesis-engine/02-03-PLAN.md +++ b/.planning/phases/02-audio-synthesis-engine/02-03-PLAN.md @@ -25,7 +25,7 @@ must_haves: provides: "Integration test with ffprobe validation and zero-packet guard test" contains: "TestMP3Valid" - path: "cmd/netsynth/main.go" - provides: "-o flag wiring with timestamp default" + provides: "-o flag wiring with timestamp default, snapshot slice accumulator stub" contains: "outputPath" key_links: - from: "encode/mp3.go" @@ -225,7 +225,7 @@ Write tests FIRST, using `os.CreateTemp` for output files and `exec.Command("ffp - Task 2: Wire -o output flag into CLI + Task 2: Wire -o output flag and snapshot accumulator stub into CLI cmd/netsynth/main.go - cmd/netsynth/main.go (current Cobra flag setup, run function) @@ -255,9 +255,16 @@ Add the `-o` / `--output` flag to main.go. Per D-15: defaults to `netsynth- @@ -284,12 +293,14 @@ Do NOT import the encode package yet — Phase 3 handles that. The flag must be - `ffprobe` validates the test-generated MP3 (within encode test) - `go run ./cmd/netsynth/ --help` shows `-o, --output` flag - `grep "no packets captured" encode/mp3.go` confirms zero-packet error message +- `grep "collectedSnapshots" cmd/netsynth/main.go` confirms snapshot accumulator stub - encode/mp3.go produces valid MP3 files from synthetic WindowSnapshots (validated by ffprobe) - Zero-packet guard prevents file creation and returns descriptive error (OUT-03) - -o flag registered in CLI with timestamp default (OUT-01) +- Snapshot slice accumulator ready for Phase 3 wiring - Full test suite passes: `CGO_ENABLED=1 go test ./...` - Complete Phase 2 audio pipeline validated end-to-end against synthetic data diff --git a/.planning/phases/02-audio-synthesis-engine/02-VALIDATION.md b/.planning/phases/02-audio-synthesis-engine/02-VALIDATION.md new file mode 100644 index 0000000..aec6cd6 --- /dev/null +++ b/.planning/phases/02-audio-synthesis-engine/02-VALIDATION.md @@ -0,0 +1,97 @@ +--- +phase: 2 +slug: audio-synthesis-engine +status: draft +nyquist_compliant: true +wave_0_complete: true +tdd_model: co-creation +created: 2026-03-26 +--- + +# Phase 2 — Validation Strategy + +> Per-phase validation contract for feedback sampling during execution. + +--- + +## Test Infrastructure + +| Property | Value | +|----------|-------| +| **Framework** | go test (stdlib) | +| **Config file** | none — existing Go test infrastructure | +| **Quick run command** | `go test ./synth/... ./encode/...` | +| **Full suite command** | `go test ./...` | +| **Estimated runtime** | ~5 seconds | + +--- + +## TDD Model + +This phase uses **co-creation TDD**: tests are written within the same task as the implementation, following RED-GREEN-REFACTOR within each task. All TDD tasks are marked with `tdd="true"` in their plan XML. Test files are created as part of the task, not as a separate Wave 0 plan. + +This is explicitly chosen over pre-existing stub TDD because: +1. Each task's `` block defines expected test cases before implementation begins +2. The executor writes tests FIRST (RED), then implementation (GREEN) within the same task +3. No test file exists before the task starts — the task creates both test and implementation + +Wave 0 requirements are limited to environment/tooling setup (gcc, ffprobe, go-lame dependency), handled by Plan 01 Task 1. + +--- + +## Sampling Rate + +- **After every task commit:** Run `go test ./synth/... ./encode/...` +- **After every plan wave:** Run `go test ./...` +- **Before `/gsd:verify-work`:** Full suite must be green +- **Max feedback latency:** 5 seconds + +--- + +## Per-Task Verification Map + +| Task ID | Plan | Wave | Requirement | Test Type | Automated Command | TDD | Status | +|---------|------|------|-------------|-----------|-------------------|-----|--------| +| 02-01-01 | 01 | 1 | SYNTH-01 | setup | `go version && gcc --version && ffprobe -version && grep "go-lame" go.mod && CGO_ENABLED=1 go build ./...` | n/a | ⬜ pending | +| 02-01-02 | 01 | 1 | SYNTH-01, SYNTH-02 | unit | `cd /home/dev/workspace/yoloyolo && go test ./synth/... -v -count=1` | co-creation | ⬜ pending | +| 02-02-01 | 02 | 2 | SYNTH-03 | unit | `cd /home/dev/workspace/yoloyolo && go test ./synth/... -run "TestPan\|TestStereo\|TestClamp" -v -count=1` | co-creation | ⬜ pending | +| 02-02-02 | 02 | 2 | SYNTH-03 | unit | `cd /home/dev/workspace/yoloyolo && go test ./synth/... -run "TestNewBank\|TestRenderWindow\|TestMixerNoClip\|TestStereoPan\|TestMultipleWindows" -v -count=1` | co-creation | ⬜ pending | +| 02-03-01 | 03 | 3 | OUT-02, OUT-03 | integration | `cd /home/dev/workspace/yoloyolo && CGO_ENABLED=1 go test ./encode/... -v -count=1` | co-creation | ⬜ pending | +| 02-03-02 | 03 | 3 | OUT-01 | build | `cd /home/dev/workspace/yoloyolo && go build -o /dev/null ./cmd/netsynth/ && go run ./cmd/netsynth/ --help 2>&1 \| grep -q "\-o.*output" && echo "OK"` | n/a | ⬜ pending | + +*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky* + +--- + +## Wave 0 Requirements + +- [x] `gcc` — C compiler required for go-lame CGo compilation (Plan 01, Task 1) +- [x] `ffprobe` — MP3 validation in acceptance tests (Plan 01, Task 1) +- [x] `go get github.com/sjzar/go-lame@v0.0.9` — MP3 encoding dependency (Plan 01, Task 1) +- [x] `go-audio/wav` — **Skipped.** Per CONTEXT.md Claude's Discretion grant; write PCM bytes directly to LameWriter (CLAUDE.md updated). + +*Test stubs are co-created with implementation in each TDD task (see TDD Model section above).* + +--- + +## Manual-Only Verifications + +| Behavior | Requirement | Why Manual | Test Instructions | +|----------|-------------|------------|-------------------| +| Perceptually distinct drone tones per traffic class | SYNTH-01 | Subjective audio quality | Play output MP3, verify each class sounds distinct | +| Amplitude rises/falls audibly with traffic volume | SYNTH-02 | Subjective perception | Listen for volume changes across windows with varying traffic | +| Stereo panning creates spatial separation | SYNTH-03 | Subjective audio quality | Listen with headphones, verify bass center and highs spread | + +--- + +## Validation Sign-Off + +- [x] All tasks have `` verify commands matching plan blocks +- [x] Sampling continuity: no 3 consecutive tasks without automated verify (all tasks have automated verify) +- [x] Wave 0 covers environment/tooling setup (Plan 01, Task 1) +- [x] Co-creation TDD model documented; test expectations defined in `` blocks +- [x] No watch-mode flags +- [x] Feedback latency < 5s +- [x] `nyquist_compliant: true` set in frontmatter + +**Approval:** ready diff --git a/CLAUDE.md b/CLAUDE.md index 5ba20f7..9e17f02 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -30,7 +30,7 @@ A Go CLI tool that captures live network traffic on an interface, clusters and c | Library | Version | Purpose | When to Use | |---------|---------|---------|-------------| | `github.com/muesli/kmeans` | v0.3.1 | K-means clustering for unrecognized traffic patterns | Use to auto-cluster packets that don't match known protocol rules. Feed feature vectors: [port, protocol_num, packet_size_bin, direction]. Last release July 2022 but mathematically stable; the algorithm doesn't change. Alternatively, implement a simple incremental classifier directly (see Architecture notes below). | -| `github.com/go-audio/wav` | latest | WAV file I/O as intermediate format | Use to write synthesized PCM as WAV before MP3 encoding pass. "Battle tested" per maintainer. Simplifies the PCM → encoder pipeline: synthesize float64 samples → write WAV → re-read as PCM → LAME encode. | +| `github.com/go-audio/wav` | latest | WAV file I/O as intermediate format | **Optional.** Originally recommended for PCM intermediate buffering, but Phase 2 research found that go-audio/wav requires `io.WriteSeeker` (which `bytes.Buffer` does not satisfy) and adds unnecessary complexity. The simpler approach is writing interleaved int16 PCM bytes directly to go-lame's `LameWriter.Write()`. Skip unless a WAV debug output feature is needed. Decision made under CONTEXT.md Claude's Discretion grant for "WAV intermediate format usage." | | `golang.org/x/sys/unix` | stdlib | Raw socket / CAP_NET_RAW privilege checks | Use for detecting if the process has required privileges and for signaling (SIGINT for clean shutdown). Part of Go extended stdlib — no external version pinning needed. | ### Development Tools | Tool | Purpose | Notes |