Files
yoloyolo/.planning/phases/09-frequency-design-and-group-architecture/09-01-SUMMARY.md
T
gurix fe7ee0e797 docs(09-01): complete frequency-design and group-architecture plan
- 09-01-SUMMARY.md: plan execution complete, 2 tasks, oscillator bug documented
- STATE.md: decisions recorded (Group as string, oscillator fix), session updated
- REQUIREMENTS.md: FREQ-01, FREQ-02, FREQ-03, GRP-01, GRP-04 marked complete
2026-03-27 14:18:42 +01:00

6.6 KiB

phase, plan, subsystem, tags, dependency_graph, tech_stack, key_files, decisions, metrics
phase plan subsystem tags dependency_graph tech_stack key_files decisions metrics
09-frequency-design-and-group-architecture 01 synth
frequency-design
group-architecture
config
oscillator-fix
requires provides affects
08-01
FreqConfig.Group
rebalanced-ClassFreqConfigs
oscillator-normalization-fix
synth
config
bank_test
config_test
added patterns
Major-second ladder Hz allocation for family-band frequency design
math.Abs normalization for alternating-sign harmonic series in additive oscillator
created modified
synth/config.go
synth/config_test.go
synth/oscillator.go
synth/bank_test.go
config/config_test.go
Group field added to FreqConfig as a string (not enum) — extensible for Phase 10 new family names without code changes
Within-family spacing satisfies major second (1.122 ratio): 65->73 = 1.123, 73->82 = 1.123, 82->133 = 1.622 (Infrastructure skips slots reserved for Phase 10), 150->169 = 1.127 (Web), 771->866 = 1.123 (Unknown)
Oscillator normalization fixed to use math.Abs — alternating-sign harmonics (triangle wave) were causing output to exceed [-1,1] bounds when using WaveformPresetHarmonics
duration completed tasks_completed files_modified
6m 30s 2026-03-27 2 5

Phase 9 Plan 1: Frequency Design and Group Architecture Summary

FreqConfig gains a Group string field; all 14 ClassFreqConfigs entries rebalanced to major-second ladder in family frequency bands (65-1375 Hz), with family-specific waveforms. Oscillator normalization bug fixed for alternating-sign harmonic series.

What Was Built

Task 1: Add Group field to FreqConfig and rebalance ClassFreqConfigs

synth/config.go was updated with:

  1. Group string field added to FreqConfig struct after WaveformType
  2. Frequency allocation table comment block documenting all 32 designed slots (Phase 9 + Phase 10 placeholders)
  3. Stale NumLayers and GainPerLayer constants removed (Phase 8 cleanup carried forward)
  4. All 14 ClassFreqConfigs entries rebalanced to the major-second ladder:
    • Infrastructure (Triangle, 65-133 Hz): ICMP=65, NTP=73, DHCP=82, DNS=133
    • Web (Sawtooth, 150-169 Hz): HTTPS=150, HTTP=169
    • Mail (Triangle, 214 Hz): SMTP=214
    • Remote Access (Square, 343 Hz): SSH=343
    • Unknown (Custom harmonics, 771-1375 Hz): Unknown1=771, Unknown2=866, Unknown3=972, Unknown4=1091, OtherTCP=1225, OtherUDP=1375

Non-Unknown entries use WaveformPresetHarmonics; Unknown entries retain hand-tuned {1,1.0},{2,0.8},{3,0.4} with WaveformType left as zero value (WaveformCustom) so bank.go uses stored harmonics directly.

Task 2: Update synth tests and fix oscillator normalization bug

synth/config_test.go:

  • TestGroupFieldPopulated added: iterates all ClassFreqConfigs entries, fails if any have empty Group
  • TestHarmonicsNonEmpty threshold changed from < 2 to < 1 (accepts single-harmonic sine entries for Phase 10 SIP)

Auto-fix (Rule 1 - Bug): Oscillator normalization for alternating-sign harmonics

Found during Task 2 verification: TestNewBankCustomConfigNoClip was failing with L=-1.023. Root cause: oscillator.go Advance() accumulated totalWeight += h.Amplitude (signed sum), but WaveformPresetHarmonics(WaveformTriangle, ...) produces alternating-sign amplitudes. The signed sum (~0.916 for 65 Hz triangle with 170 harmonics) is much smaller than the absolute sum (~1.232), causing the normalization denominator to be deflated, which inflated output amplitude beyond [-1, 1].

Fix: changed to totalWeight += math.Abs(h.Amplitude) in oscillator.go. The old config used positive-only amplitudes {k, 1/k} so the bug was latent. The new WaveformPresetHarmonics(WaveformTriangle, ...) exposed it.

Test updates (Rule 1 - Bug):

  • synth/bank_test.go: TestStereoPan updated from ClassDHCP (new pan=0.1, right-biased) to ClassSSH (pan=-0.7, wide-left); TestNewBankCustomConfigNoClip passes after oscillator fix
  • config/config_test.go: TestLoadPartialOverrideFrequency changed from hardcoded WaveformCustom to synth.ClassFreqConfigs[classify.ClassICMP].WaveformType (ICMP is now WaveformTriangle); TestAutoFreqSkipsBuiltins changed from hardcoded 175.0 to synth.ClassFreqConfigs[classify.ClassHTTPS].BaseHz (now 150.0)

Verification Results

go build ./synth/...                     → exit 0
go test ./synth/... -v -count=1          → 42 tests PASS
go test ./...                            → all 7 packages PASS
grep -c 'Group:' synth/config.go         → 14
grep 'Group        string' synth/config.go → FOUND
grep -c 'BaseHz:       65.0' synth/config.go  → ICMP confirmed
grep '// Frequency Allocation Table' synth/config.go → FOUND

Deviations from Plan

Auto-fixed Issues

1. [Rule 1 - Bug] Fixed oscillator normalization for alternating-sign harmonic amplitudes

  • Found during: Task 2 verification (go test ./synth/...)
  • Issue: oscillator.Advance() used totalWeight += h.Amplitude (signed sum). Triangle wave harmonics from WaveformPresetHarmonics alternate signs (1, -1/9, 1/25, -1/49...), making signed total ~0.916 vs absolute total ~1.232. This caused 34% undercount, so output exceeded [-1, 1] bounds.
  • Fix: Changed to totalWeight += math.Abs(h.Amplitude) in synth/oscillator.go
  • Files modified: synth/oscillator.go, synth/bank_test.go, config/config_test.go
  • Commit: c97682d

2. [Rule 1 - Bug] Updated TestStereoPan for new ClassDHCP pan value

  • Found during: Task 2 verification
  • Issue: TestStereoPan expected ClassDHCP to be left-panned (old pan=-0.75) but new config has pan=0.1 (right-biased)
  • Fix: Changed test to use ClassSSH (pan=-0.7, clearly left-biased in new config)
  • Files modified: synth/bank_test.go
  • Commit: c97682d

3. [Rule 1 - Bug] Updated config_test.go for new default values

  • Found during: Task 2 running go test ./...
  • Issue: Two config tests had hardcoded values from old defaults (ICMP WaveformCustom, HTTPS BaseHz=175.0)
  • Fix: Changed assertions to derive expected values from synth.ClassFreqConfigs defaults
  • Files modified: config/config_test.go
  • Commit: c97682d

Known Stubs

None. All 14 ClassFreqConfigs entries have populated Group, Hz, waveform, and harmonics. Phase 10 slot placeholders are documented in comments only.

Self-Check: PASSED

  • synth/config.go: FOUND
  • synth/config_test.go: FOUND
  • synth/oscillator.go: FOUND
  • 09-01-SUMMARY.md: FOUND
  • Commit 812f0de: FOUND (feat: Group field + rebalanced ClassFreqConfigs)
  • Commit c97682d: FOUND (fix: TestGroupFieldPopulated + oscillator normalization + test updates)