fix(02): revise plans based on checker feedback
This commit is contained in:
@@ -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.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>go version && gcc --version && ffprobe -version && grep "go-lame" go.mod && CGO_ENABLED=1 go build ./...</automated>
|
||||
|
||||
@@ -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>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Wire -o output flag into CLI</name>
|
||||
<name>Task 2: Wire -o output flag and snapshot accumulator stub into CLI</name>
|
||||
<files>cmd/netsynth/main.go</files>
|
||||
<read_first>
|
||||
- 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-<time
|
||||
|
||||
4. Add `"time"` to the imports.
|
||||
|
||||
5. Add a comment in the snapshot consumption loop marking where Phase 3 will wire synthesis:
|
||||
5. Add a snapshot slice accumulator alongside the existing snapshot consumption loop, and a TODO for Phase 3 wiring. Replace the current `for snap := range snapshots` block to also collect snapshots into a slice:
|
||||
```go
|
||||
// TODO(phase-3): Pass snapshots to encode.RunSynthesis(snapshots, outputPath)
|
||||
// Accumulate snapshots for synthesis (Phase 3 will pass to encode.RunSynthesis)
|
||||
var collectedSnapshots []classify.WindowSnapshot
|
||||
for snap := range snapshots {
|
||||
collectedSnapshots = append(collectedSnapshots, snap)
|
||||
aggregate.AccumulateTotals(totals, snap)
|
||||
}
|
||||
|
||||
// TODO(phase-3): Pass collectedSnapshots to encode.RunSynthesis(collectedSnapshots, outputPath)
|
||||
```
|
||||
|
||||
Do NOT import the encode package yet — Phase 3 handles that. The flag must be functional (parseable, shows in --help) even though the synthesis pipeline isn't wired.
|
||||
@@ -271,10 +278,12 @@ Do NOT import the encode package yet — Phase 3 handles that. The flag must be
|
||||
- cmd/netsynth/main.go contains `netsynth-%s.mp3`
|
||||
- cmd/netsynth/main.go contains `time.Now().Format("20060102-150405")`
|
||||
- cmd/netsynth/main.go imports `"time"`
|
||||
- cmd/netsynth/main.go contains `var collectedSnapshots []classify.WindowSnapshot`
|
||||
- cmd/netsynth/main.go contains `TODO(phase-3)` referencing `encode.RunSynthesis`
|
||||
- `go build ./cmd/netsynth/` exits 0
|
||||
- `go run ./cmd/netsynth/ --help` output contains `-o, --output`
|
||||
</acceptance_criteria>
|
||||
<done>The -o/--output flag is registered in Cobra, defaults to netsynth-<timestamp>.mp3, visible in --help. Build succeeds. Phase 3 will wire it to RunSynthesis.</done>
|
||||
<done>The -o/--output flag is registered in Cobra, defaults to netsynth-<timestamp>.mp3, visible in --help. Snapshot slice accumulator stub is in place for Phase 3 wiring. Build succeeds.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
@@ -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
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- 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
|
||||
</success_criteria>
|
||||
|
||||
@@ -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 `<behavior>` 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 `<automated>` 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 `<behavior>` blocks
|
||||
- [x] No watch-mode flags
|
||||
- [x] Feedback latency < 5s
|
||||
- [x] `nyquist_compliant: true` set in frontmatter
|
||||
|
||||
**Approval:** ready
|
||||
@@ -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 |
|
||||
|
||||
Reference in New Issue
Block a user