- 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
131 lines
5.8 KiB
Markdown
131 lines
5.8 KiB
Markdown
---
|
|
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*
|