--- phase: 06-config-package-and-sound-overrides plan: 02 type: execute wave: 2 depends_on: ["06-01"] files_modified: - encode/mp3.go - encode/mp3_test.go - cmd/netsynth/main.go autonomous: true requirements: - CFG-03 must_haves: truths: - "User passes --config /path/to/file.toml and the tool uses that file for sound overrides" - "User passes --config /nonexistent.toml and the tool exits with a clear error before capture" - "User runs without --config and auto-discovery kicks in (or defaults used silently)" - "RunSynthesis uses the merged config map instead of hardcoded ClassFreqConfigs" artifacts: - path: "cmd/netsynth/main.go" provides: "--config flag, config.Load call, passing merged map to RunSynthesis" contains: "configPath" - path: "encode/mp3.go" provides: "RunSynthesis with freqCfgs parameter" contains: "freqCfgs map[classify.TrafficClass]synth.FreqConfig" - path: "encode/mp3_test.go" provides: "Updated tests for new RunSynthesis signature" key_links: - from: "cmd/netsynth/main.go" to: "config/config.go" via: "config.Load(configPath)" pattern: "config\\.Load" - from: "cmd/netsynth/main.go" to: "encode/mp3.go" via: "encode.RunSynthesis(snapshots, outputPath, freqCfgs)" pattern: "encode\\.RunSynthesis.*freqCfgs" - from: "encode/mp3.go" to: "synth/bank.go" via: "synth.NewBank(1.0, freqCfgs) using passed-in config" pattern: "synth\\.NewBank.*freqCfgs" --- Wire the config package into the CLI and synthesis pipeline. Add `--config` flag to Cobra, call `config.Load` at startup, change `RunSynthesis` signature to accept the merged config map, and update all call sites. Purpose: Completes CFG-03 (explicit --config flag) and D-10 (RunSynthesis signature change). After this plan, the end-to-end flow works: user creates TOML -> tool loads it -> synthesis uses overridden frequencies/waveforms. Output: Updated `cmd/netsynth/main.go`, `encode/mp3.go`, `encode/mp3_test.go` @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/06-config-package-and-sound-overrides/06-CONTEXT.md @.planning/phases/06-config-package-and-sound-overrides/06-01-SUMMARY.md From config/config.go (created in Plan 01): ```go // Load finds, parses, validates, and merges a config file. // configPath is the --config flag value; empty string triggers auto-discovery. func Load(configPath string) (map[classify.TrafficClass]synth.FreqConfig, error) ``` From encode/mp3.go (current signature to change): ```go // Current: func RunSynthesis(snapshots []classify.WindowSnapshot, outputPath string) error // New: func RunSynthesis(snapshots []classify.WindowSnapshot, outputPath string, freqCfgs map[classify.TrafficClass]synth.FreqConfig) error ``` From cmd/netsynth/main.go (existing flags pattern): ```go var ( ifaceName string listIfaces bool verbose bool outputPath string bpfFilter string readPath string ) // Flag registration pattern: rootCmd.Flags().StringVar(&bpfFilter, "filter", "", "BPF filter expression") ``` From synth/config.go: ```go var ClassFreqConfigs = map[classify.TrafficClass]FreqConfig{ /* 14 entries */ } ``` Task 1: Change RunSynthesis signature and update encode tests encode/mp3.go, encode/mp3_test.go encode/mp3.go (current RunSynthesis signature and body) encode/mp3_test.go (current test calls to RunSynthesis) synth/config.go (ClassFreqConfigs, FreqConfig type) classify/types.go (TrafficClass type) **encode/mp3.go changes:** 1. Add `freqCfgs map[classify.TrafficClass]synth.FreqConfig` as third parameter to RunSynthesis: ``` func RunSynthesis(snapshots []classify.WindowSnapshot, outputPath string, freqCfgs map[classify.TrafficClass]synth.FreqConfig) error ``` 2. Change line 57 from: ``` bank := synth.NewBank(1.0, synth.ClassFreqConfigs) ``` to: ``` bank := synth.NewBank(1.0, freqCfgs) ``` 3. No other changes to encode/mp3.go. **encode/mp3_test.go changes:** 4. Update `TestMP3Valid` (line 56): change `RunSynthesis(snaps, tmpPath)` to `RunSynthesis(snaps, tmpPath, synth.ClassFreqConfigs)`. 5. Update `TestZeroPacketError` (line 101): change `RunSynthesis([]classify.WindowSnapshot{}, tmpPath)` to `RunSynthesis([]classify.WindowSnapshot{}, tmpPath, synth.ClassFreqConfigs)`. 6. Update `TestZeroPacketError` (line 121): change `RunSynthesis(zeroSnaps, tmpPath2)` to `RunSynthesis(zeroSnaps, tmpPath2, synth.ClassFreqConfigs)`. The `synth` import is already present in mp3_test.go. cd /home/dev/workspace/yoloyolo && go build ./encode/... && go test ./encode/... -count=1 -run TestZeroPacketError - encode/mp3.go contains `func RunSynthesis(snapshots []classify.WindowSnapshot, outputPath string, freqCfgs map[classify.TrafficClass]synth.FreqConfig) error` - encode/mp3.go contains `synth.NewBank(1.0, freqCfgs)` (not synth.ClassFreqConfigs) - encode/mp3_test.go contains `RunSynthesis(snaps, tmpPath, synth.ClassFreqConfigs)` - encode/mp3_test.go contains `RunSynthesis([]classify.WindowSnapshot{}, tmpPath, synth.ClassFreqConfigs)` - encode/mp3_test.go contains `RunSynthesis(zeroSnaps, tmpPath2, synth.ClassFreqConfigs)` - `go build ./encode/...` exits 0 - `go test ./encode/... -count=1 -run TestZeroPacketError` exits 0 RunSynthesis accepts injected config map. All encode tests updated and passing. Task 2: Add --config flag and wire config.Load into main.go cmd/netsynth/main.go cmd/netsynth/main.go (full file — flag definitions, run function, runLiveMode, runPcapMode) config/config.go (Load function signature) encode/mp3.go (updated RunSynthesis signature from Task 1) **cmd/netsynth/main.go changes:** 1. Add `configPath` to the var block (after `readPath`): ```go configPath string // NEW: --config flag (CFG-03) ``` 2. Add import for config package in the import block: ```go "github.com/netsynth/netsynth/config" ``` Also add import for `synth` package (needed for ClassFreqConfigs fallback reference — though config.Load handles this internally): No — `synth` is NOT needed in main.go. `config.Load` returns the full map. Only add `config` import. 3. Add flag registration in main() after the `readPath` flag line (line 44): ```go rootCmd.Flags().StringVar(&configPath, "config", "", "Path to TOML config file (default: auto-discover)") ``` 4. In the `run` function, add config loading AFTER the BPF filter validation block (after line 80) and BEFORE output path resolution (before line 83). This is per D-11 (fail fast on config errors before capture): ```go // Load config (CFG-01 through CFG-05, D-11: fail fast) freqCfgs, err := config.Load(configPath) if err != nil { return err } ``` 5. The `freqCfgs` variable must be accessible in both `runLiveMode` and `runPcapMode`. Two approaches: - Option A: Pass freqCfgs to both functions (cleanest). - Option B: Store in a package-level var (simpler change). Use Option A. Change signatures: - `runLiveMode(cmd *cobra.Command) error` -> `runLiveMode(cmd *cobra.Command, freqCfgs map[classify.TrafficClass]synth.FreqConfig) error` - `runPcapMode(cmd *cobra.Command) error` -> `runPcapMode(cmd *cobra.Command, freqCfgs map[classify.TrafficClass]synth.FreqConfig) error` This requires adding `synth` import after all: ```go "github.com/netsynth/netsynth/synth" ``` Update call sites in `run()`: - Line 92: `return runPcapMode(cmd)` -> `return runPcapMode(cmd, freqCfgs)` - Line 94: `return runLiveMode(cmd)` -> `return runLiveMode(cmd, freqCfgs)` 6. In `runLiveMode`, change the RunSynthesis call (line 147): From: `encode.RunSynthesis(collectedSnapshots, outputPath)` To: `encode.RunSynthesis(collectedSnapshots, outputPath, freqCfgs)` 7. In `runPcapMode`, change the RunSynthesis call (line 215): From: `encode.RunSynthesis(collectedSnapshots, outputPath)` To: `encode.RunSynthesis(collectedSnapshots, outputPath, freqCfgs)` After all changes, run `go build ./cmd/netsynth/...` to verify compilation. cd /home/dev/workspace/yoloyolo && go build ./cmd/netsynth/... && go vet ./cmd/netsynth/... && go test ./... -count=1 2>&1 | tail -20 - cmd/netsynth/main.go contains `configPath string` - cmd/netsynth/main.go contains `rootCmd.Flags().StringVar(&configPath, "config", ""` - cmd/netsynth/main.go contains `config.Load(configPath)` - cmd/netsynth/main.go contains `"github.com/netsynth/netsynth/config"` in imports - cmd/netsynth/main.go contains `encode.RunSynthesis(collectedSnapshots, outputPath, freqCfgs)` (two occurrences — one in runLiveMode, one in runPcapMode) - cmd/netsynth/main.go contains `runLiveMode(cmd, freqCfgs)` and `runPcapMode(cmd, freqCfgs)` - `go build ./cmd/netsynth/...` exits 0 - `go vet ./cmd/netsynth/...` exits 0 - `go test ./... -count=1` exits 0 (full suite green) --config flag registered in Cobra. config.Load called at startup before capture. Merged config map flows through to RunSynthesis in both live and pcap modes. Full test suite passes. - `go build ./...` compiles entire project - `go test ./... -count=1` all tests pass - `go vet ./...` no issues - `./netsynth --help` shows `--config` flag in output - --config flag appears in CLI help output (CFG-03) - Explicit --config with missing file produces error before capture (CFG-03) - RunSynthesis uses injected config map, not hardcoded ClassFreqConfigs (D-10) - Full test suite passes including encode and config package tests After completion, create `.planning/phases/06-config-package-and-sound-overrides/06-02-SUMMARY.md`