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:
@@ -9,11 +9,11 @@ Requirements for custom sound mappings milestone. Each maps to roadmap phases.
|
|||||||
|
|
||||||
### Config Loading
|
### Config Loading
|
||||||
|
|
||||||
- [ ] **CFG-01**: User can create a TOML config file that overrides default sound mappings
|
- [x] **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-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-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)
|
- [x] **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-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
|
- [ ] **CFG-06**: User can run `netsynth --print-config` to see the effective config as commented TOML
|
||||||
|
|
||||||
### Waveforms
|
### Waveforms
|
||||||
@@ -56,11 +56,11 @@ Which phases cover which requirements. Updated during roadmap creation.
|
|||||||
|
|
||||||
| Requirement | Phase | Status |
|
| Requirement | Phase | Status |
|
||||||
|-------------|-------|--------|
|
|-------------|-------|--------|
|
||||||
| CFG-01 | Phase 6 | Pending |
|
| CFG-01 | Phase 6 | Complete |
|
||||||
| CFG-02 | Phase 6 | Pending |
|
| CFG-02 | Phase 6 | Complete |
|
||||||
| CFG-03 | Phase 6 | Pending |
|
| CFG-03 | Phase 6 | Pending |
|
||||||
| CFG-04 | Phase 6 | Pending |
|
| CFG-04 | Phase 6 | Complete |
|
||||||
| CFG-05 | Phase 6 | Pending |
|
| CFG-05 | Phase 6 | Complete |
|
||||||
| CFG-06 | Phase 7 | Pending |
|
| CFG-06 | Phase 7 | Pending |
|
||||||
| WAVE-01 | Phase 5 | Complete |
|
| WAVE-01 | Phase 5 | Complete |
|
||||||
| WAVE-02 | Phase 5 | Complete |
|
| WAVE-02 | Phase 5 | Complete |
|
||||||
|
|||||||
@@ -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
|
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
|
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
|
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:
|
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
|
- [ ] 06-02-PLAN.md — CLI wiring: --config flag, RunSynthesis signature change, main.go integration
|
||||||
|
|
||||||
### Phase 7: Custom Rules and Print-Config
|
### 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 |
|
| 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 |
|
| 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 |
|
| 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 | - |
|
| 7. Custom Rules and Print-Config | v1.1 | 0/? | Not started | - |
|
||||||
|
|||||||
+15
-11
@@ -3,15 +3,15 @@ gsd_state_version: 1.0
|
|||||||
milestone: v1.1
|
milestone: v1.1
|
||||||
milestone_name: Custom Sound Mappings
|
milestone_name: Custom Sound Mappings
|
||||||
status: verifying
|
status: verifying
|
||||||
stopped_at: Phase 6 context gathered
|
stopped_at: Completed 06-01-PLAN.md
|
||||||
last_updated: "2026-03-26T19:39:13.126Z"
|
last_updated: "2026-03-26T19:58:00.000Z"
|
||||||
last_activity: 2026-03-26
|
last_activity: 2026-03-26
|
||||||
progress:
|
progress:
|
||||||
total_phases: 3
|
total_phases: 3
|
||||||
completed_phases: 1
|
completed_phases: 1
|
||||||
total_plans: 2
|
total_plans: 3
|
||||||
completed_plans: 2
|
completed_plans: 1
|
||||||
percent: 0
|
percent: 33
|
||||||
---
|
---
|
||||||
|
|
||||||
# Project State
|
# Project State
|
||||||
@@ -26,11 +26,11 @@ See: .planning/PROJECT.md (updated 2026-03-26)
|
|||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 6
|
Phase: 6
|
||||||
Plan: Not started
|
Plan: 1 complete, 2 next
|
||||||
Status: Phase complete — ready for verification
|
Status: Plan 01 complete
|
||||||
Last activity: 2026-03-26
|
Last activity: 2026-03-26
|
||||||
|
|
||||||
Progress: [░░░░░░░░░░] 0%
|
Progress: [███░░░░░░░] 33%
|
||||||
|
|
||||||
## Performance Metrics
|
## Performance Metrics
|
||||||
|
|
||||||
@@ -52,6 +52,7 @@ Progress: [░░░░░░░░░░] 0%
|
|||||||
**Recent Trend:** Stable
|
**Recent Trend:** Stable
|
||||||
| Phase 05 P01 | 3min | 2 tasks | 3 files |
|
| Phase 05 P01 | 3min | 2 tasks | 3 files |
|
||||||
| Phase 05 P02 | 4 | 2 tasks | 4 files |
|
| Phase 05 P02 | 4 | 2 tasks | 4 files |
|
||||||
|
| Phase 06 P01 | 3min | 1 task | 4 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## 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]: 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]: 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 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
|
### Pending Todos
|
||||||
|
|
||||||
@@ -75,6 +79,6 @@ None.
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-03-26T19:39:13.119Z
|
Last session: 2026-03-26T19:58:00.000Z
|
||||||
Stopped at: Phase 6 context gathered
|
Stopped at: Completed 06-01-PLAN.md
|
||||||
Resume file: .planning/phases/06-config-package-and-sound-overrides/06-CONTEXT.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*
|
||||||
Reference in New Issue
Block a user