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
This commit is contained in:
2026-03-26 20:59:46 +01:00
parent 1f877e7574
commit 1986e8fc2e
4 changed files with 156 additions and 22 deletions
+8 -8
View File
@@ -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 |
+3 -3
View File
@@ -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 | - |
+15 -11
View File
@@ -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
@@ -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*