docs(08): create phase plan
This commit is contained in:
@@ -35,7 +35,7 @@ Full details: `.planning/milestones/v1.1-ROADMAP.md`
|
|||||||
|
|
||||||
**Milestone Goal:** Expand traffic classification with grouped protocol families that share recognizable sound signatures — from 14 classes to ~35, organized into frequency bands by family.
|
**Milestone Goal:** Expand traffic classification with grouped protocol families that share recognizable sound signatures — from 14 classes to ~35, organized into frequency bands by family.
|
||||||
|
|
||||||
- [ ] **Phase 8: Test and Constant Cleanup** - Remove stale constants and update test bounds that would block all subsequent v1.2 work
|
- [ ] **Phase 8: Test and Constant Cleanup** - 1 plan — Remove stale constants and update test bounds that would block all subsequent v1.2 work
|
||||||
- [ ] **Phase 9: Frequency Design and Group Architecture** - Design complete Hz allocation for all ~35 classes in family bands and add Group field to FreqConfig
|
- [ ] **Phase 9: Frequency Design and Group Architecture** - Design complete Hz allocation for all ~35 classes in family bands and add Group field to FreqConfig
|
||||||
- [ ] **Phase 10: Classification Layer** - Add ~21 new TrafficClass constants and port rules covering all new protocol families
|
- [ ] **Phase 10: Classification Layer** - Add ~21 new TrafficClass constants and port rules covering all new protocol families
|
||||||
- [ ] **Phase 11: Synthesis and Config Layer** - Add ClassFreqConfigs entries for all new classes, update auto-assign range, and add group-header output to --print-config
|
- [ ] **Phase 11: Synthesis and Config Layer** - Add ClassFreqConfigs entries for all new classes, update auto-assign range, and add group-header output to --print-config
|
||||||
@@ -50,7 +50,9 @@ Full details: `.planning/milestones/v1.1-ROADMAP.md`
|
|||||||
1. `go test ./...` passes on main with no modifications to the new v1.2 code path
|
1. `go test ./...` passes on main with no modifications to the new v1.2 code path
|
||||||
2. The stale `NumLayers`/`GainPerLayer` exported constant no longer exists in the synth package — callers cannot accidentally use it
|
2. The stale `NumLayers`/`GainPerLayer` exported constant no longer exists in the synth package — callers cannot accidentally use it
|
||||||
3. `TestFrequenciesInRange` accepts the new extended Hz range without manual test surgery when new classes are added in Phase 10
|
3. `TestFrequenciesInRange` accepts the new extended Hz range without manual test surgery when new classes are added in Phase 10
|
||||||
**Plans**: TBD
|
**Plans:** 1 plan
|
||||||
|
Plans:
|
||||||
|
- [ ] 08-01-PLAN.md — Delete stale constants, future-proof test bounds, rename/consolidate tests
|
||||||
|
|
||||||
### Phase 9: Frequency Design and Group Architecture
|
### Phase 9: Frequency Design and Group Architecture
|
||||||
**Goal**: A complete, documented frequency allocation table for all ~35 traffic classes exists and the FreqConfig struct carries a Group field — design decisions are locked in before any protocol code is written
|
**Goal**: A complete, documented frequency allocation table for all ~35 traffic classes exists and the FreqConfig struct carries a Group field — design decisions are locked in before any protocol code is written
|
||||||
@@ -97,7 +99,7 @@ Full details: `.planning/milestones/v1.1-ROADMAP.md`
|
|||||||
| 5. Waveform Types and Bank Decoupling | v1.1 | 2/2 | Complete | 2026-03-26 |
|
| 5. Waveform Types and Bank Decoupling | v1.1 | 2/2 | Complete | 2026-03-26 |
|
||||||
| 6. Config Package and Sound Overrides | v1.1 | 2/2 | Complete | 2026-03-26 |
|
| 6. Config Package and Sound Overrides | v1.1 | 2/2 | Complete | 2026-03-26 |
|
||||||
| 7. Custom Rules and Print-Config | v1.1 | 2/2 | Complete | 2026-03-26 |
|
| 7. Custom Rules and Print-Config | v1.1 | 2/2 | Complete | 2026-03-26 |
|
||||||
| 8. Test and Constant Cleanup | v1.2 | 0/? | Not started | - |
|
| 8. Test and Constant Cleanup | v1.2 | 0/1 | Planning | - |
|
||||||
| 9. Frequency Design and Group Architecture | v1.2 | 0/? | Not started | - |
|
| 9. Frequency Design and Group Architecture | v1.2 | 0/? | Not started | - |
|
||||||
| 10. Classification Layer | v1.2 | 0/? | Not started | - |
|
| 10. Classification Layer | v1.2 | 0/? | Not started | - |
|
||||||
| 11. Synthesis and Config Layer | v1.2 | 0/? | Not started | - |
|
| 11. Synthesis and Config Layer | v1.2 | 0/? | Not started | - |
|
||||||
|
|||||||
@@ -0,0 +1,214 @@
|
|||||||
|
---
|
||||||
|
phase: 08-test-and-constant-cleanup
|
||||||
|
plan: 01
|
||||||
|
type: execute
|
||||||
|
wave: 1
|
||||||
|
depends_on: []
|
||||||
|
files_modified:
|
||||||
|
- synth/config.go
|
||||||
|
- synth/config_test.go
|
||||||
|
autonomous: true
|
||||||
|
requirements:
|
||||||
|
- CLEAN-01
|
||||||
|
must_haves:
|
||||||
|
truths:
|
||||||
|
- "NumLayers and GainPerLayer constants do not exist in the synth package"
|
||||||
|
- "go test ./... passes with zero failures after all edits"
|
||||||
|
- "TestFrequenciesInRange accepts any BaseHz in (0, Nyquist) without manual test surgery"
|
||||||
|
- "TestNumLayersMatchesAllClasses is renamed to TestClassFreqConfigsMatchAllClasses"
|
||||||
|
artifacts:
|
||||||
|
- path: "synth/config.go"
|
||||||
|
provides: "Cleaned constant block without NumLayers or GainPerLayer"
|
||||||
|
contains: "WhisperFloor"
|
||||||
|
- path: "synth/config_test.go"
|
||||||
|
provides: "Future-proof test assertions"
|
||||||
|
contains: "TestClassFreqConfigsMatchAllClasses"
|
||||||
|
key_links:
|
||||||
|
- from: "synth/bank.go"
|
||||||
|
to: "synth/config.go"
|
||||||
|
via: "gainPerLayer computed dynamically in NewBank — no longer any static constant to conflict with"
|
||||||
|
pattern: "1\\.0 / float64\\(len\\(cfgs\\)\\)"
|
||||||
|
- from: "synth/config_test.go"
|
||||||
|
to: "synth/config.go"
|
||||||
|
via: "TestFrequenciesInRange validates BaseHz against SampleRate-derived Nyquist"
|
||||||
|
pattern: "float64\\(synth\\.SampleRate\\)"
|
||||||
|
---
|
||||||
|
|
||||||
|
<objective>
|
||||||
|
Remove stale exported constants and hardcoded test bounds from the synth package so that subsequent v1.2 phases can add new traffic classes and frequencies without triggering false CI failures.
|
||||||
|
|
||||||
|
Purpose: Phase 8 is the gatekeeper for all v1.2 work. NumLayers=14 is dead code (NewBank computes gain dynamically), and TestFrequenciesInRange's [60, 1100] bound will reject any new class above 1100 Hz. Both must be cleaned up before Phase 9-11 proceed.
|
||||||
|
|
||||||
|
Output: Two edited files (synth/config.go, synth/config_test.go) with all tests green.
|
||||||
|
</objective>
|
||||||
|
|
||||||
|
<execution_context>
|
||||||
|
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
|
||||||
|
@$HOME/.claude/get-shit-done/templates/summary.md
|
||||||
|
</execution_context>
|
||||||
|
|
||||||
|
<context>
|
||||||
|
@.planning/PROJECT.md
|
||||||
|
@.planning/ROADMAP.md
|
||||||
|
@.planning/STATE.md
|
||||||
|
@.planning/phases/08-test-and-constant-cleanup/08-CONTEXT.md
|
||||||
|
@.planning/phases/08-test-and-constant-cleanup/08-RESEARCH.md
|
||||||
|
|
||||||
|
<interfaces>
|
||||||
|
<!-- Key constants and types the executor needs from synth/config.go -->
|
||||||
|
|
||||||
|
From synth/config.go (current constant block, lines 5-12):
|
||||||
|
```go
|
||||||
|
const (
|
||||||
|
SampleRate = 44100 // D-13: CD quality
|
||||||
|
WindowMs = 500 // matches aggregate.DefaultWindowMs
|
||||||
|
SamplesPerWindow = SampleRate * WindowMs / 1000 // 22050
|
||||||
|
NumLayers = 14 // <-- DELETE per D-01
|
||||||
|
GainPerLayer = 1.0 / float64(NumLayers) // D-10: ~0.0714 <-- DELETE per D-01
|
||||||
|
WhisperFloor = 0.03 // D-08/D-09: 3% of max amplitude
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
From synth/bank.go (line 21 — confirms constants are dead code):
|
||||||
|
```go
|
||||||
|
gainPerLayer: 1.0 / float64(len(cfgs)), // dynamic computation, no constant needed
|
||||||
|
```
|
||||||
|
|
||||||
|
From synth/config_test.go (current test functions to modify):
|
||||||
|
```go
|
||||||
|
// Lines 18-25: TestFrequenciesInRange — hardcoded [60, 1100] to replace
|
||||||
|
// Lines 53-59: TestClassFreqConfigsComplete — duplicate of TestAllClassesHaveConfig
|
||||||
|
// Lines 61-66: TestNumLayersMatchesAllClasses — rename to TestClassFreqConfigsMatchAllClasses
|
||||||
|
```
|
||||||
|
</interfaces>
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<tasks>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 1: Delete stale NumLayers and GainPerLayer constants from synth/config.go</name>
|
||||||
|
<files>synth/config.go</files>
|
||||||
|
<read_first>
|
||||||
|
- synth/config.go (see current constant block at lines 5-12)
|
||||||
|
- synth/bank.go (line 21 confirms gainPerLayer is computed dynamically)
|
||||||
|
</read_first>
|
||||||
|
<action>
|
||||||
|
Per D-01: Delete lines 9-10 from synth/config.go — the `NumLayers = 14` and `GainPerLayer = 1.0 / float64(NumLayers)` constants.
|
||||||
|
|
||||||
|
The resulting constant block must be:
|
||||||
|
|
||||||
|
```go
|
||||||
|
const (
|
||||||
|
SampleRate = 44100 // D-13: CD quality
|
||||||
|
WindowMs = 500 // matches aggregate.DefaultWindowMs
|
||||||
|
SamplesPerWindow = SampleRate * WindowMs / 1000 // 22050
|
||||||
|
WhisperFloor = 0.03 // D-08/D-09: 3% of max amplitude
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Do NOT modify any other lines in config.go. Do NOT touch bank.go — NewBank's dynamic `1.0 / float64(len(cfgs))` is already correct.
|
||||||
|
|
||||||
|
Optionally, add a traceability comment to synth/bank.go line 21:
|
||||||
|
`gainPerLayer: 1.0 / float64(len(cfgs)), // D-10: 1/N so all layers at full amplitude sum to 1.0`
|
||||||
|
This is low-priority — skip if it feels like noise.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
<automated>cd /home/dev/workspace/yoloyolo && grep -n "NumLayers\|GainPerLayer" synth/config.go; echo "EXIT:$?"</automated>
|
||||||
|
</verify>
|
||||||
|
<acceptance_criteria>
|
||||||
|
- `grep -c "NumLayers" synth/config.go` returns 0
|
||||||
|
- `grep -c "GainPerLayer" synth/config.go` returns 0
|
||||||
|
- `synth/config.go` still contains `SampleRate = 44100`
|
||||||
|
- `synth/config.go` still contains `WhisperFloor = 0.03`
|
||||||
|
- `go build ./synth/...` exits 0 (no compilation errors from removing the constants)
|
||||||
|
</acceptance_criteria>
|
||||||
|
<done>NumLayers and GainPerLayer constants no longer exist in synth/config.go. The constant block contains only SampleRate, WindowMs, SamplesPerWindow, and WhisperFloor. Code compiles cleanly.</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 2: Update synth/config_test.go — future-proof frequency bounds, rename test, remove duplicate</name>
|
||||||
|
<files>synth/config_test.go</files>
|
||||||
|
<read_first>
|
||||||
|
- synth/config_test.go (full file — see all 6 test functions)
|
||||||
|
- synth/config.go (after Task 1 edits — confirm SampleRate is exported)
|
||||||
|
</read_first>
|
||||||
|
<action>
|
||||||
|
Three changes to synth/config_test.go:
|
||||||
|
|
||||||
|
**Change 1 (per D-02):** Replace the body of `TestFrequenciesInRange` (lines 18-25) with Nyquist-based validation. The new function body:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func TestFrequenciesInRange(t *testing.T) {
|
||||||
|
const nyquist = float64(synth.SampleRate) / 2.0 // 22050 Hz
|
||||||
|
for class, cfg := range synth.ClassFreqConfigs {
|
||||||
|
if cfg.BaseHz <= 0 {
|
||||||
|
t.Errorf("class %q BaseHz=%.1f must be positive", class, cfg.BaseHz)
|
||||||
|
}
|
||||||
|
if cfg.BaseHz >= nyquist {
|
||||||
|
t.Errorf("class %q BaseHz=%.1f exceeds Nyquist (%.1f Hz)", class, cfg.BaseHz, nyquist)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This accepts any BaseHz in (0, 22050) — no manual edit needed when Phase 10 adds classes above 1100 Hz.
|
||||||
|
|
||||||
|
**Change 2 (per D-03):** Rename `TestNumLayersMatchesAllClasses` (line 61) to `TestClassFreqConfigsMatchAllClasses`. Keep the function body identical:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func TestClassFreqConfigsMatchAllClasses(t *testing.T) {
|
||||||
|
if len(synth.ClassFreqConfigs) != len(classify.AllClasses()) {
|
||||||
|
t.Errorf("ClassFreqConfigs has %d entries but AllClasses() has %d entries",
|
||||||
|
len(synth.ClassFreqConfigs), len(classify.AllClasses()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Change 3 (Claude's discretion — consolidation):** Delete `TestClassFreqConfigsComplete` (lines 53-59) entirely. It is a semantic duplicate of `TestAllClassesHaveConfig` (lines 10-16) — both iterate `AllClasses()` and check for a map entry. Removing it leaves three non-overlapping tests:
|
||||||
|
- `TestAllClassesHaveConfig` — every AllClasses() member has a map entry
|
||||||
|
- `TestClassFreqConfigsMatchAllClasses` — count parity (catches extra entries)
|
||||||
|
- `TestFrequenciesInRange` — all BaseHz positive and below Nyquist
|
||||||
|
|
||||||
|
The remaining tests (`TestFrequenciesUnique`, `TestHarmonicsNonEmpty`, `TestPanPositionsInRange`) are untouched.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
<automated>cd /home/dev/workspace/yoloyolo && go test ./synth/... -v -count=1 2>&1 | head -40</automated>
|
||||||
|
</verify>
|
||||||
|
<acceptance_criteria>
|
||||||
|
- `grep -c "TestNumLayersMatchesAllClasses" synth/config_test.go` returns 0
|
||||||
|
- `grep -c "TestClassFreqConfigsMatchAllClasses" synth/config_test.go` returns 1
|
||||||
|
- `grep -c "TestClassFreqConfigsComplete" synth/config_test.go` returns 0
|
||||||
|
- `grep "nyquist" synth/config_test.go` returns at least one match
|
||||||
|
- `grep "1100" synth/config_test.go` returns 0 matches (hardcoded bound removed)
|
||||||
|
- `go test ./synth/... -run TestFrequenciesInRange` exits 0
|
||||||
|
- `go test ./synth/... -run TestClassFreqConfigsMatchAllClasses` exits 0
|
||||||
|
- `go test ./...` exits 0 (full suite green)
|
||||||
|
</acceptance_criteria>
|
||||||
|
<done>TestFrequenciesInRange uses Nyquist-based validation (no hardcoded upper bound). TestNumLayersMatchesAllClasses renamed to TestClassFreqConfigsMatchAllClasses. Duplicate TestClassFreqConfigsComplete removed. Full test suite passes.</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
</tasks>
|
||||||
|
|
||||||
|
<verification>
|
||||||
|
After both tasks complete:
|
||||||
|
|
||||||
|
1. `grep -rn "NumLayers\|GainPerLayer" synth/*.go` — zero matches in production and test code
|
||||||
|
2. `grep -n "1100" synth/config_test.go` — zero matches (hardcoded bound gone)
|
||||||
|
3. `go test ./...` — all packages pass with zero failures
|
||||||
|
4. `go test ./synth/... -run TestFrequenciesInRange` — passes
|
||||||
|
5. `go test ./synth/... -run TestClassFreqConfigsMatchAllClasses` — passes
|
||||||
|
6. `go test ./synth/... -run TestClassFreqConfigsComplete` — no such test (removed)
|
||||||
|
</verification>
|
||||||
|
|
||||||
|
<success_criteria>
|
||||||
|
- NumLayers and GainPerLayer constants deleted from synth/config.go
|
||||||
|
- TestFrequenciesInRange validates against Nyquist (22050 Hz), not hardcoded 1100
|
||||||
|
- TestNumLayersMatchesAllClasses renamed to TestClassFreqConfigsMatchAllClasses
|
||||||
|
- Duplicate TestClassFreqConfigsComplete removed
|
||||||
|
- `go test ./...` passes with zero failures
|
||||||
|
- Adding a new class with BaseHz=2000 in a future phase would NOT require editing any test
|
||||||
|
</success_criteria>
|
||||||
|
|
||||||
|
<output>
|
||||||
|
After completion, create `.planning/phases/08-test-and-constant-cleanup/08-01-SUMMARY.md`
|
||||||
|
</output>
|
||||||
Reference in New Issue
Block a user