Files
gurixandClaude Opus 4.6 494385b528 chore: archive v1.2 milestone — Extended Protocol Coverage
35 traffic classes across 9 protocol families shipped. Archives
ROADMAP, REQUIREMENTS, and phase directories to milestones/v1.2-*.
Updates README with new protocol families, sound design table,
and [groups] TOML config documentation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 16:48:53 +01:00

9.4 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
08-test-and-constant-cleanup 01 execute 1
synth/config.go
synth/config_test.go
true
CLEAN-01
truths artifacts key_links
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
path provides contains
synth/config.go Cleaned constant block without NumLayers or GainPerLayer WhisperFloor
path provides contains
synth/config_test.go Future-proof test assertions TestClassFreqConfigsMatchAllClasses
from to via pattern
synth/bank.go synth/config.go gainPerLayer computed dynamically in NewBank — no longer any static constant to conflict with 1.0 / float64(len(cfgs))
from to via pattern
synth/config_test.go synth/config.go TestFrequenciesInRange validates BaseHz against SampleRate-derived Nyquist float64(synth.SampleRate)
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.

<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_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

From synth/config.go (current constant block, lines 5-12):

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):

gainPerLayer: 1.0 / float64(len(cfgs)),  // dynamic computation, no constant needed

From synth/config_test.go (current test functions to modify):

// Lines 18-25: TestFrequenciesInRange — hardcoded [60, 1100] to replace
// Lines 53-59: TestClassFreqConfigsComplete — duplicate of TestAllClassesHaveConfig
// Lines 61-66: TestNumLayersMatchesAllClasses — rename to TestClassFreqConfigsMatchAllClasses
Task 1: Delete stale NumLayers and GainPerLayer constants from synth/config.go synth/config.go - synth/config.go (see current constant block at lines 5-12) - synth/bank.go (line 21 confirms gainPerLayer is computed dynamically) 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:

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. cd /home/dev/workspace/yoloyolo && grep -n "NumLayers|GainPerLayer" synth/config.go; echo "EXIT:$?" <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> NumLayers and GainPerLayer constants no longer exist in synth/config.go. The constant block contains only SampleRate, WindowMs, SamplesPerWindow, and WhisperFloor. Code compiles cleanly.

Task 2: Update synth/config_test.go — future-proof frequency bounds, rename test, remove duplicate synth/config_test.go - synth/config_test.go (full file — see all 6 test functions) - synth/config.go (after Task 1 edits — confirm SampleRate is exported) 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:

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:

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. cd /home/dev/workspace/yoloyolo && go test ./synth/... -v -count=1 2>&1 | head -40 <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> TestFrequenciesInRange uses Nyquist-based validation (no hardcoded upper bound). TestNumLayersMatchesAllClasses renamed to TestClassFreqConfigsMatchAllClasses. Duplicate TestClassFreqConfigsComplete removed. Full test suite passes.

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)

<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>
After completion, create `.planning/phases/08-test-and-constant-cleanup/08-01-SUMMARY.md`