From 1986e8fc2ec598cb0c72d259052f1774c5ef4529 Mon Sep 17 00:00:00 2001 From: Markus Graf Date: Thu, 26 Mar 2026 20:59:46 +0100 Subject: [PATCH] docs(06-01): complete config package plan summary and state updates - 06-01-SUMMARY.md: TOML config loader with partial merge and unknown-key detection - STATE.md: advanced to Plan 1 complete, added Phase 06-01 decisions and metrics - ROADMAP.md: updated Phase 6 plan progress (1/2 plans complete) - REQUIREMENTS.md: marked CFG-01, CFG-02, CFG-04, CFG-05 complete --- .planning/REQUIREMENTS.md | 16 +-- .planning/ROADMAP.md | 6 +- .planning/STATE.md | 26 ++-- .../06-01-SUMMARY.md | 130 ++++++++++++++++++ 4 files changed, 156 insertions(+), 22 deletions(-) create mode 100644 .planning/phases/06-config-package-and-sound-overrides/06-01-SUMMARY.md diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index acb511f..e34d7fe 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -9,11 +9,11 @@ Requirements for custom sound mappings milestone. Each maps to roadmap phases. ### Config Loading -- [ ] **CFG-01**: User can create a TOML config file that overrides default sound mappings -- [ ] **CFG-02**: Tool auto-discovers config from `./netsynth.toml` or `~/.config/netsynth/config.toml` (silent if absent) +- [x] **CFG-01**: User can create a TOML config file that overrides default sound mappings +- [x] **CFG-02**: Tool auto-discovers config from `./netsynth.toml` or `~/.config/netsynth/config.toml` (silent if absent) - [ ] **CFG-03**: User can specify an explicit config path via `--config` flag (error if file missing) -- [ ] **CFG-04**: User can override individual values without replicating the entire default config (partial override) -- [ ] **CFG-05**: Unknown keys in config file produce a clear error with the typo'd key name +- [x] **CFG-04**: User can override individual values without replicating the entire default config (partial override) +- [x] **CFG-05**: Unknown keys in config file produce a clear error with the typo'd key name - [ ] **CFG-06**: User can run `netsynth --print-config` to see the effective config as commented TOML ### Waveforms @@ -56,11 +56,11 @@ Which phases cover which requirements. Updated during roadmap creation. | Requirement | Phase | Status | |-------------|-------|--------| -| CFG-01 | Phase 6 | Pending | -| CFG-02 | Phase 6 | Pending | +| CFG-01 | Phase 6 | Complete | +| CFG-02 | Phase 6 | Complete | | CFG-03 | Phase 6 | Pending | -| CFG-04 | Phase 6 | Pending | -| CFG-05 | Phase 6 | Pending | +| CFG-04 | Phase 6 | Complete | +| CFG-05 | Phase 6 | Complete | | CFG-06 | Phase 7 | Pending | | WAVE-01 | Phase 5 | Complete | | WAVE-02 | Phase 5 | Complete | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 014d8fa..a00455b 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -53,10 +53,10 @@ Plans: 3. User passes `--config /path/to/custom.toml` and the tool uses that file; if the file does not exist, the tool exits with a clear error before capture begins 4. User types `frequncy = 440` in their config file and the tool exits at startup with an error naming `frequncy` as an unrecognized key 5. User sets waveform for one class in TOML and leaves all other classes at their defaults — the unspecified classes are unchanged -**Plans:** 2 plans +**Plans:** 1/2 plans executed Plans: -- [ ] 06-01-PLAN.md — Config package: TOML load, validate, merge with TDD (config/config.go, config/config_test.go) +- [x] 06-01-PLAN.md — Config package: TOML load, validate, merge with TDD (config/config.go, config/config_test.go) - [ ] 06-02-PLAN.md — CLI wiring: --config flag, RunSynthesis signature change, main.go integration ### Phase 7: Custom Rules and Print-Config @@ -79,5 +79,5 @@ Plans: | 3. Pipeline Integration and MVP | v1.0 | 2/2 | Complete | 2026-03-26 | | 4. Power User Features | v1.0 | 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 | 0/2 | Planning complete | - | +| 6. Config Package and Sound Overrides | v1.1 | 1/2 | In Progress| | | 7. Custom Rules and Print-Config | v1.1 | 0/? | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index ce8dd74..48ffd4b 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,15 +3,15 @@ gsd_state_version: 1.0 milestone: v1.1 milestone_name: Custom Sound Mappings status: verifying -stopped_at: Phase 6 context gathered -last_updated: "2026-03-26T19:39:13.126Z" +stopped_at: Completed 06-01-PLAN.md +last_updated: "2026-03-26T19:58:00.000Z" last_activity: 2026-03-26 progress: total_phases: 3 completed_phases: 1 - total_plans: 2 - completed_plans: 2 - percent: 0 + total_plans: 3 + completed_plans: 1 + percent: 33 --- # Project State @@ -26,11 +26,11 @@ See: .planning/PROJECT.md (updated 2026-03-26) ## Current Position Phase: 6 -Plan: Not started -Status: Phase complete — ready for verification +Plan: 1 complete, 2 next +Status: Plan 01 complete Last activity: 2026-03-26 -Progress: [░░░░░░░░░░] 0% +Progress: [███░░░░░░░] 33% ## Performance Metrics @@ -52,6 +52,7 @@ Progress: [░░░░░░░░░░] 0% **Recent Trend:** Stable | Phase 05 P01 | 3min | 2 tasks | 3 files | | Phase 05 P02 | 4 | 2 tasks | 4 files | +| Phase 06 P01 | 3min | 1 task | 4 files | ## Accumulated Context @@ -64,6 +65,9 @@ Progress: [░░░░░░░░░░] 0% - [Phase 05]: WaveformType zero value is WaveformCustom — all 14 existing ClassFreqConfigs entries retain hand-tuned harmonics without modification - [Phase 05]: NewBank accepts injected config map instead of reading ClassFreqConfigs global — injection seam for Phase 6 config loading - [Phase 05]: gainPerLayer computed as 1.0/float64(len(cfgs)) — correct for any class count, no-clip guarantee preserved +- [Phase 06-01]: BurntSushi/toml v1.6.0 chosen over pelletier/go-toml v2 — Undecoded() returns structured []Key not formatted string, easier key name extraction for error messages +- [Phase 06-01]: Shallow copy in copyDefaults() safe because merge always reconstructs Harmonics via WaveformPresetHarmonics rather than mutating original slice +- [Phase 06-01]: Unknown class names produce stderr warning (not error) per D-09 — Phase 7 user-defined classes will make arbitrary names valid ### Pending Todos @@ -75,6 +79,6 @@ None. ## Session Continuity -Last session: 2026-03-26T19:39:13.119Z -Stopped at: Phase 6 context gathered -Resume file: .planning/phases/06-config-package-and-sound-overrides/06-CONTEXT.md +Last session: 2026-03-26T19:58:00.000Z +Stopped at: Completed 06-01-PLAN.md +Resume file: .planning/phases/06-config-package-and-sound-overrides/06-01-SUMMARY.md diff --git a/.planning/phases/06-config-package-and-sound-overrides/06-01-SUMMARY.md b/.planning/phases/06-config-package-and-sound-overrides/06-01-SUMMARY.md new file mode 100644 index 0000000..670127c --- /dev/null +++ b/.planning/phases/06-config-package-and-sound-overrides/06-01-SUMMARY.md @@ -0,0 +1,130 @@ +--- +phase: 06-config-package-and-sound-overrides +plan: 01 +subsystem: config +tags: [toml, BurntSushi/toml, config-loading, partial-merge, validation] + +# Dependency graph +requires: + - phase: 05-waveform-types-and-bank-decoupling + provides: WaveformType enum, WaveformPresetHarmonics, FreqConfig.WaveformType field + - phase: 01-capture-and-classification + provides: classify.TrafficClass, classify.AllClasses, 14 class constants + +provides: + - config.Load(configPath string) returns map[classify.TrafficClass]synth.FreqConfig + - SoundOverride struct with pointer fields for partial-merge semantics + - TOML file parsing with unknown-key detection via BurntSushi/toml Undecoded() + - Auto-discovery of ./netsynth.toml and ~/.config/netsynth/config.toml + - Per-field overlay merge preserving unspecified defaults + - Waveform string validation before merge (fail fast) + +affects: + - 06-02 (CLI flag wiring: --config flag passes configPath to config.Load) + - encode package (RunSynthesis will accept merged config map from config.Load) + +# Tech tracking +tech-stack: + added: ["github.com/BurntSushi/toml v1.6.0 — TOML parsing with MetaData.Undecoded() for unknown-key detection"] + patterns: + - "Pointer fields (*float64, *string) in decode struct for partial-override semantics (nil = not set)" + - "parseFile → validate → merge pipeline for fail-fast config loading (D-11)" + - "Dedicated config package for testable isolation from Cobra/CLI concerns" + +key-files: + created: + - config/config.go + - config/config_test.go + modified: + - go.mod + - go.sum + +key-decisions: + - "Used BurntSushi/toml v1.6.0 over pelletier/go-toml v2 — Undecoded() returns structured []Key (not formatted string), easier to extract key name for error messages" + - "Shallow copy in copyDefaults() is safe because merge reconstructs Harmonics via WaveformPresetHarmonics rather than mutating the original slice" + - "Unknown class names produce stderr warning (not error) per D-09, preparing for Phase 7 user-defined classes" + +patterns-established: + - "Config package is independent of cmd/ — no Cobra imports, fully unit-testable" + - "Merge functions take defaults map by value and modify in place, returning it" + +requirements-completed: [CFG-01, CFG-02, CFG-04, CFG-05] + +# Metrics +duration: 3min +completed: 2026-03-26 +--- + +# Phase 6 Plan 01: Config Package Summary + +**TOML-based config loader with pointer-field partial merge, BurntSushi/toml Undecoded() unknown-key detection, and XDG auto-discovery at ./netsynth.toml and ~/.config/netsynth/config.toml** + +## Performance + +- **Duration:** ~3 min +- **Started:** 2026-03-26T19:55:08Z +- **Completed:** 2026-03-26T19:57:45Z +- **Tasks:** 1 (TDD: red → green) +- **Files modified:** 4 (config/config.go, config/config_test.go, go.mod, go.sum) + +## Accomplishments + +- Created `config` package with single `Load(configPath string)` public API +- Implemented pointer-field partial merge: only non-nil fields override defaults (CFG-04) +- Added BurntSushi/toml Undecoded() for field-level typo detection (CFG-05) +- Auto-discovery of netsynth.toml in working dir and ~/.config/netsynth/config.toml (CFG-02) +- Explicit file missing returns clear error; auto-discovery missing is silent (CFG-02/CFG-03) +- Harmonics regenerated via WaveformPresetHarmonics when waveform or frequency is overridden +- All 9 tests pass; go vet clean + +## Task Commits + +Each task committed atomically via TDD: + +1. **RED - Failing tests** - `b9ec05a` (test): 9 test functions for CFG-01 through CFG-05 +2. **GREEN - Full implementation** - `1f877e7` (feat): config.Load, merge, validate, discover + +_Note: TDD task has two commits (RED test stub → GREEN implementation)_ + +## Files Created/Modified + +- `config/config.go` - Load(), SoundOverride, rawConfig, merge, validate, discoverPath +- `config/config_test.go` - 9 test functions covering all CFG requirements +- `go.mod` - Added github.com/BurntSushi/toml v1.6.0 +- `go.sum` - Updated checksum for new dependency + +## Decisions Made + +- **BurntSushi/toml over pelletier/go-toml v2**: Undecoded() returns `[]toml.Key` ([]string slices) — structured, allowing exact key name extraction for error messages. pelletier's DisallowUnknownFields returns a formatted string (harder to extract just the key name). +- **Shallow copy in copyDefaults()**: Safe because merge code always replaces `Harmonics` with a freshly generated slice from WaveformPresetHarmonics rather than mutating the original. Documented with comment for future maintainers. +- **Unknown class warning (not error)**: Following D-09 to emit `fmt.Fprintf(os.Stderr, "Warning: ...")` for unknown class names. Phase 7 user-defined classes will be valid, so this is by design. + +## Deviations from Plan + +None - plan executed exactly as written. The worktree needed a rebase onto master to include phase 05 code (WaveformType, WaveformPresetHarmonics) before starting — this was a prerequisite resolution, not a deviation. + +## Issues Encountered + +- Worktree was based on remote origin/master (pre-phase-05). Rebased onto local master to get WaveformType and WaveformPresetHarmonics before implementation. No code conflicts. + +## User Setup Required + +None - no external service configuration required. BurntSushi/toml is fetched automatically via `go get`. + +## Next Phase Readiness + +- `config.Load()` is ready for wiring into `cmd/netsynth/main.go` via `--config` flag (Plan 06-02) +- `encode.RunSynthesis` signature change (accept `freqCfgs map[classify.TrafficClass]synth.FreqConfig`) is needed in Plan 06-02 +- All 14 default classes always present in result map — safe to pass directly to `synth.NewBank()` + +## Self-Check: PASSED + +- FOUND: config/config.go +- FOUND: config/config_test.go +- FOUND: .planning/phases/06-config-package-and-sound-overrides/06-01-SUMMARY.md +- FOUND: b9ec05a (RED commit — failing tests) +- FOUND: 1f877e7 (GREEN commit — full implementation) + +--- +*Phase: 06-config-package-and-sound-overrides* +*Completed: 2026-03-26*