diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 277ae2c..977be57 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -23,9 +23,9 @@ Requirements for custom sound mappings milestone. Each maps to roadmap phases. ### Custom Rules -- [ ] **RULE-01**: User can define custom classification rules in TOML (match by port and/or protocol, assign class name and sound) -- [ ] **RULE-02**: User-defined rules take priority over built-in rules (prepend before defaults) -- [ ] **RULE-03**: User-defined class names automatically get a synthesis layer (no silent gaps) +- [x] **RULE-01**: User can define custom classification rules in TOML (match by port and/or protocol, assign class name and sound) +- [x] **RULE-02**: User-defined rules take priority over built-in rules (prepend before defaults) +- [x] **RULE-03**: User-defined class names automatically get a synthesis layer (no silent gaps) ## Future Requirements @@ -64,9 +64,9 @@ Which phases cover which requirements. Updated during roadmap creation. | CFG-06 | Phase 7 | Pending | | WAVE-01 | Phase 5 | Complete | | WAVE-02 | Phase 5 | Complete | -| RULE-01 | Phase 7 | Pending | -| RULE-02 | Phase 7 | Pending | -| RULE-03 | Phase 7 | Pending | +| RULE-01 | Phase 7 | Complete | +| RULE-02 | Phase 7 | Complete | +| RULE-03 | Phase 7 | Complete | **Coverage:** - v1.1 requirements: 11 total diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 356abe1..47e6846 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -68,10 +68,10 @@ Plans: 2. User-defined rules fire before built-in protocol rules — a custom rule for port 443 overrides the default HTTPS classification for packets on that port 3. A user-defined class name gets its own synthesis layer automatically — no silence or missing audio for traffic matched by a custom rule 4. User runs `netsynth --print-config` and sees the full effective config (defaults merged with their overrides) as commented TOML, without starting a capture -**Plans:** 2 plans +**Plans:** 1/2 plans executed Plans: -- [ ] 07-01-PLAN.md — Config extension: RawRule, LoadResult, rule validation, auto-freq assignment (TDD) +- [x] 07-01-PLAN.md — Config extension: RawRule, LoadResult, rule validation, auto-freq assignment (TDD) - [ ] 07-02-PLAN.md — CLI wiring: --print-config flag, user rule prepend, PrintConfig output ## Progress @@ -84,4 +84,4 @@ Plans: | 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 | 2/2 | Complete | 2026-03-26 | -| 7. Custom Rules and Print-Config | v1.1 | 0/2 | Not started | - | +| 7. Custom Rules and Print-Config | v1.1 | 1/2 | In Progress| | diff --git a/.planning/STATE.md b/.planning/STATE.md index d839ab3..d85ee21 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,14 +3,14 @@ gsd_state_version: 1.0 milestone: v1.1 milestone_name: Custom Sound Mappings status: executing -stopped_at: Phase 7 context gathered -last_updated: "2026-03-26T20:27:34.725Z" +stopped_at: Completed 07-01-PLAN.md +last_updated: "2026-03-26T20:45:59.826Z" last_activity: 2026-03-26 progress: total_phases: 3 completed_phases: 2 - total_plans: 4 - completed_plans: 4 + total_plans: 6 + completed_plans: 5 percent: 0 --- @@ -21,12 +21,12 @@ progress: See: .planning/PROJECT.md (updated 2026-03-26) **Core value:** Network traffic patterns are instantly recognizable as distinct sounds — a ping sounds different from HTTPS noise, which sounds different from a port scan. -**Current focus:** Phase 06 — config-package-and-sound-overrides +**Current focus:** Phase 07 — custom-rules-and-print-config ## Current Position -Phase: 7 -Plan: Not started +Phase: 07 (custom-rules-and-print-config) — EXECUTING +Plan: 2 of 2 Status: Ready to execute Last activity: 2026-03-26 @@ -53,6 +53,7 @@ Progress: [░░░░░░░░░░] 0% | Phase 05 P01 | 3min | 2 tasks | 3 files | | Phase 05 P02 | 4 | 2 tasks | 4 files | | Phase 06 P02 | 2 | 2 tasks | 3 files | +| Phase 07 P01 | 3 | 1 tasks | 3 files | ## Accumulated Context @@ -67,6 +68,8 @@ Progress: [░░░░░░░░░░] 0% - [Phase 05]: gainPerLayer computed as 1.0/float64(len(cfgs)) — correct for any class count, no-clip guarantee preserved - [Phase 06]: Option A for freqCfgs propagation: pass as parameter to runLiveMode/runPcapMode — cleaner data flow vs package-level var - [Phase 06]: config.Load positioned after BPF validation, before output path resolution — ensures fail-fast before any I/O (D-11) +- [Phase 07]: addAutoFreqEntries runs before merge so [sounds.X] overrides apply to user-defined classes +- [Phase 07]: LoadResult struct chosen over tuple return for config.Load() -- cleaner API contract for Plan 02 CLI wiring ### Pending Todos @@ -78,6 +81,6 @@ None. ## Session Continuity -Last session: 2026-03-26T20:27:34.717Z -Stopped at: Phase 7 context gathered -Resume file: .planning/phases/07-custom-rules-and-print-config/07-CONTEXT.md +Last session: 2026-03-26T20:45:59.819Z +Stopped at: Completed 07-01-PLAN.md +Resume file: None diff --git a/.planning/phases/07-custom-rules-and-print-config/07-01-SUMMARY.md b/.planning/phases/07-custom-rules-and-print-config/07-01-SUMMARY.md new file mode 100644 index 0000000..d9e893c --- /dev/null +++ b/.planning/phases/07-custom-rules-and-print-config/07-01-SUMMARY.md @@ -0,0 +1,94 @@ +--- +phase: 07-custom-rules-and-print-config +plan: "01" +subsystem: config +tags: [config, rules, tdd, classification, auto-freq] +dependency_graph: + requires: [] + provides: [LoadResult, RawRule, validateRules, convertRules, autoAssignFreq, addAutoFreqEntries] + affects: [cmd/netsynth/main.go] +tech_stack: + added: ["hash/fnv"] + patterns: [LoadResult-struct, FNV-32a-deterministic-hash, TDD-red-green] +key_files: + created: [] + modified: + - config/config.go + - config/config_test.go + - cmd/netsynth/main.go +decisions: + - "addAutoFreqEntries runs before merge so [sounds.X] overrides apply to user-defined classes" + - "merge() warning for unknown class names still fires for [sounds.X] where X is neither built-in nor in [[rules]] -- acceptable harmless warning" + - "main.go call site updated to use LoadResult.FreqCfgs -- minimal fix to keep compile; full wiring deferred to Plan 02" +metrics: + duration: 3min + completed: "2026-03-26T20:45:08Z" + tasks_completed: 1 + files_modified: 3 +--- + +# Phase 7 Plan 01: Config Rule Parsing and LoadResult Summary + +Extend config package to parse `[[rules]]` TOML blocks, validate them, auto-assign frequencies for new class names using FNV-32a, and return a `LoadResult` struct from `Load()`. + +## What Was Built + +`config.Load()` now returns `LoadResult{FreqCfgs, UserRules, ConfigPath}` instead of a bare map. The new struct is the data contract for Plan 02's CLI wiring and `--print-config` output. + +**New types and functions in config/config.go:** +- `RawRule` struct: `Port *uint16`, `Protocol string`, `Class string` — pointer Port to distinguish missing vs zero +- `LoadResult` struct: `FreqCfgs`, `UserRules []classify.Rule`, `ConfigPath string` +- `validateRules()`: checks protocol required, class required, valid protocols (tcp/udp/icmp) +- `convertRules()`: converts `[]RawRule` to `[]classify.Rule` +- `autoAssignFreq()`: FNV-32a hash → deterministic Hz in [1200, 2350] range (24 steps of 50Hz) +- `addAutoFreqEntries()`: creates `FreqConfig` entries for new class names, skips built-ins +- Import: `hash/fnv` + +**Key operation order:** `addAutoFreqEntries` runs before `merge` so that `[sounds.MyApp]` sound overrides apply to user-defined classes that were added by auto-freq. + +## Tasks Completed + +| Task | Name | Commit | Files | +|------|------|--------|-------| +| 1 | RawRule, LoadResult, validation, conversion, auto-freq with TDD | 4b365cd | config/config.go, config/config_test.go, cmd/netsynth/main.go | + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] Operation order: addAutoFreqEntries must run before merge** +- **Found during:** Task 1 GREEN phase +- **Issue:** Plan's action section said "merge first, then addAutoFreqEntries" but this caused [sounds.MyApp] overrides to be ignored for user-defined classes (merge only applies to classes already in the map) +- **Fix:** Reversed the order — addAutoFreqEntries first (creates the entry), then merge (applies sound overrides) +- **Files modified:** config/config.go +- **Commit:** 4b365cd + +**2. [Rule 3 - Blocking] main.go call site updated to use LoadResult** +- **Found during:** Task 1 GREEN phase +- **Issue:** Plan notes this break is expected but tests wouldn't compile without it +- **Fix:** Minimal one-line update: `loadResult, err := config.Load(...)` + `freqCfgs := loadResult.FreqCfgs` +- **Files modified:** cmd/netsynth/main.go +- **Commit:** 4b365cd + +## Test Coverage + +21 tests total (8 existing + 13 new): +- `TestLoadCustomRules` - TOML [[rules]] block with port/protocol/class +- `TestLoadCustomRuleNoPort` - optional port field, DstPort=0 when absent +- `TestLoadCustomRuleMissingProtocol` - validation error "protocol is required" +- `TestLoadCustomRuleMissingClass` - validation error "class is required" +- `TestLoadCustomRuleInvalidProtocol` - validation error "invalid protocol" +- `TestLoadCustomRuleUnknownField` - undecoded TOML field error +- `TestUserRulesPrepend` - UserRules field usable for prepend pattern +- `TestAutoFreqAssignment` - BaseHz in [1200, 2350], WaveformSine +- `TestAutoFreqDeterministic` - same class name produces same Hz +- `TestAutoFreqSkipsBuiltins` - HTTPS stays at 175.0 default +- `TestLoadResultConfigPath` - ConfigPath populated correctly +- `TestLoadNoConfigReturnsLoadResult` - returns LoadResult with empty UserRules +- All 8 existing tests updated to use `result.FreqCfgs` + +## Known Stubs + +None. All new functions are fully implemented and tested. + +## Self-Check: PASSED