From c139d683520149d78927c8db44b679137caf2938 Mon Sep 17 00:00:00 2001 From: Markus Graf Date: Thu, 26 Mar 2026 14:42:33 +0100 Subject: [PATCH] docs(04-02): complete CLI flag wiring plan summary and state updates - 04-02-SUMMARY.md: --filter and --read flags wired, pcap mode, deriveOutputPath - STATE.md: advanced to plan 2/2, updated decisions, session record - ROADMAP.md: phase 4 marked Complete (2/2 plans) --- .planning/ROADMAP.md | 8 +- .planning/STATE.md | 18 +-- .../04-power-user-features/04-02-SUMMARY.md | 109 ++++++++++++++++++ 3 files changed, 124 insertions(+), 11 deletions(-) create mode 100644 .planning/phases/04-power-user-features/04-02-SUMMARY.md diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index b41673c..44048b6 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -15,7 +15,7 @@ Decimal phases appear between their surrounding integers in numeric order. - [x] **Phase 1: Capture and Classification** - Live packet capture, protocol identification, and CLI scaffolding — no audio yet (completed 2026-03-25) - [x] **Phase 2: Audio Synthesis Engine** - Oscillators, EMA amplitude smoothing, mixing, and MP3 encoding against synthetic inputs (completed 2026-03-26) - [x] **Phase 3: Pipeline Integration and MVP** - Wire capture into synthesis, Ctrl+C with valid MP3 output, auto-clustering of unknown traffic (completed 2026-03-26) -- [ ] **Phase 4: Power User Features** - BPF capture filter, offline pcap file input +- [x] **Phase 4: Power User Features** - BPF capture filter, offline pcap file input (completed 2026-03-26) ## Phase Details @@ -76,11 +76,11 @@ Plans: 1. User can run `netsynth -i eth0 --filter "port 53"` and only DNS traffic is captured and sonified 2. User can run `netsynth --read capture.pcap -o out.mp3` against an existing pcap file and receive a valid MP3 3. An invalid BPF filter expression produces a clear error message before any capture begins -**Plans:** 1/2 plans executed +**Plans:** 2/2 plans complete Plans: - [x] 04-01-PLAN.md — BPF validation, pcap file reading, timestamp-based aggregation (core library functions) -- [ ] 04-02-PLAN.md — Wire --filter and --read flags into CLI with branching run logic +- [x] 04-02-PLAN.md — Wire --filter and --read flags into CLI with branching run logic ## Progress @@ -92,4 +92,4 @@ Phases execute in numeric order: 1 -> 2 -> 3 -> 4 | 1. Capture and Classification | 4/4 | Complete | 2026-03-25 | | 2. Audio Synthesis Engine | 3/3 | Complete | 2026-03-26 | | 3. Pipeline Integration and MVP | 2/2 | Complete | 2026-03-26 | -| 4. Power User Features | 1/2 | In Progress| | +| 4. Power User Features | 2/2 | Complete | 2026-03-26 | diff --git a/.planning/STATE.md b/.planning/STATE.md index 9455a66..d583a13 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,14 +2,14 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone -status: Ready to execute -stopped_at: Completed 04-power-user-features 04-01-PLAN.md -last_updated: "2026-03-26T13:35:55.000Z" +status: Phase complete — ready for verification +stopped_at: Completed 04-power-user-features 04-02-PLAN.md +last_updated: "2026-03-26T13:42:19.484Z" progress: total_phases: 4 - completed_phases: 3 + completed_phases: 4 total_plans: 11 - completed_plans: 10 + completed_plans: 11 --- # Project State @@ -56,6 +56,7 @@ Plan: 2 of 2 | Phase 03-pipeline-integration-and-mvp P01 | 15min | 2 tasks | 6 files | | Phase 03 P02 | 5min | 1 tasks | 1 files | | Phase 04-power-user-features P01 | 3min | 2 tasks | 9 files | +| Phase 04-power-user-features P02 | 4min | 1 tasks | 2 files | ## Accumulated Context @@ -91,6 +92,9 @@ Recent decisions affecting current work: - [Phase 03-02]: Audio duration computed from snapshot count * DefaultWindowMs (not wall-clock) to avoid truncation for short captures - [Phase 04-power-user-features]: OpenCapture/StartCapture accept filter string; empty = no filter (backward compatible with live mode) - [Phase 04-power-user-features]: AggregatePcap: synchronous drain of events channel then assign to windows by Timestamp offset; gap windows pre-initialized with empty maps +- [Phase 04-02]: bpfFilter and readPath are package-level globals for Cobra flag binding (same pattern as other flags) +- [Phase 04-02]: runPcapMode checks for empty snapshots after PrintSummary so user sees zero-count table before error +- [Phase 04-02]: deriveOutputPath uses filepath.Ext (last extension only) matching tcpdump convention ### Pending Todos @@ -104,6 +108,6 @@ None yet. ## Session Continuity -Last session: 2026-03-26T13:35:54.993Z -Stopped at: Completed 04-power-user-features 04-01-PLAN.md +Last session: 2026-03-26T13:42:19.476Z +Stopped at: Completed 04-power-user-features 04-02-PLAN.md Resume file: None diff --git a/.planning/phases/04-power-user-features/04-02-SUMMARY.md b/.planning/phases/04-power-user-features/04-02-SUMMARY.md new file mode 100644 index 0000000..a7c0ae0 --- /dev/null +++ b/.planning/phases/04-power-user-features/04-02-SUMMARY.md @@ -0,0 +1,109 @@ +--- +phase: 04-power-user-features +plan: "02" +subsystem: cmd/netsynth +tags: [cli, bpf, pcap-reader, mutual-exclusion, output-derivation] +dependency_graph: + requires: [04-01] + provides: [--filter flag, --read flag, runPcapMode, deriveOutputPath] + affects: [cmd/netsynth] +tech_stack: + added: [path/filepath] + patterns: + - run() branches into runLiveMode/runPcapMode based on readPath flag + - BPF filter pre-validated before any capture begins + - Output filename derived from input pcap by replacing extension +key_files: + created: [] + modified: + - cmd/netsynth/main.go + - cmd/netsynth/main_test.go +decisions: + - bpfFilter and readPath are package-level globals (same pattern as other flags) for Cobra flag binding + - run() validates mutual exclusion before any I/O to give early clear errors + - runPcapMode checks for empty snapshots after PrintSummary so user sees zero-count table before error + - deriveOutputPath uses filepath.Ext (last extension only) matching tcpdump convention +metrics: + duration: "4 minutes" + completed_date: "2026-03-26" + tasks_completed: 1 + files_changed: 2 +--- + +# Phase 04 Plan 02: CLI wiring for --filter and --read flags + +**One-liner:** --filter and --read flags wired into Cobra CLI with mutual exclusion, BPF pre-validation, pcap file processing path, output filename derivation, and bookend messages. + +## What Was Built + +### cmd/netsynth/main.go + +**New global variables:** +- `bpfFilter string` — bound to `--filter` flag (BPF expression in tcpdump syntax) +- `readPath string` — bound to `--read` flag (pcap file path) + +**New `deriveOutputPath` function:** +Replaces file extension with `.mp3`. `capture.pcap` → `capture.mp3`, `noext` → `noext.mp3`. Uses `filepath.Ext` so only the last extension is replaced (e.g., `traffic.pcap.gz` → `traffic.pcap.mp3`). + +**Updated `run()` function:** +1. Validates `--read` and `-i` mutual exclusion with clear error (D-03) +2. Returns error mentioning `--read` when neither source is provided +3. Pre-validates BPF filter via `capture.ValidateBPFFilter` before any capture starts (CAPT-05) +4. Derives output path from input pcap if `--output` not given (D-05) +5. Branches to `runLiveMode` or `runPcapMode` + +**New `runLiveMode` function:** +Extracted from the original `run()`. Now passes `bpfFilter` to `capture.StartCapture(ctx, ifaceName, bpfFilter)`. + +**New `runPcapMode` function:** +- Prints `"Reading ..."` bookend start message (D-06) +- Opens pcap via `capture.ReadPcapFile(readPath, bpfFilter)` with optional software BPF +- Classifies packets, sets `cp.Timestamp = pkt.Metadata().CaptureInfo.Timestamp` for timestamp-based windowing (D-01) +- Aggregates via `aggregate.AggregatePcap` (offline, timestamp-based) +- `--verbose` supported via `onSnapshot` callback (D-07) +- Prints protocol summary before encoding (D-08 pattern preserved) +- Returns clear error if zero snapshots: `"pcap file %q contains no packets (after filtering)"` (Pitfall 4) +- Encodes and prints `"Saved..."` bookend end message (D-06) + +### cmd/netsynth/main_test.go + +New test functions: + +| Test | What it checks | +|------|---------------| +| `TestFlagMutualExclusion` | `--read` + `-i` together returns "mutually exclusive" error | +| `TestMissingSource` | No source returns "interface required" error mentioning `--read` | +| `TestDeriveOutputPath` | Path derivation: `.pcap`→`.mp3`, no ext→`.mp3`, `/tmp/net.pcap`→`/tmp/net.mp3` | +| `TestFilterFlagRegistered` | `--filter` flag is registered on rootCmd | +| `TestReadFlagRegistered` | `--read` flag is registered on rootCmd | +| `TestInvalidBPFFilter` | Invalid BPF expression returns error containing "invalid" | +| `TestHelpOutputNewFlags` | Usage string contains `--filter` and `--read` | + +Updated `newTestCmd()` helper to wire `bpfFilter`, `readPath`, `outputPath` globals. +Updated `TestMissingInterfaceFlag` to verify error also mentions `--read`. + +## Commits + +| Task | Commit | Description | +|------|--------|-------------| +| Task 1 (RED) | 09e78bf | test(04-02): add failing tests for --filter, --read flags | +| Task 1 (GREEN) | 4adb3c4 | feat(04-02): wire --filter and --read flags into CLI | + +## Deviations from Plan + +None — plan executed exactly as written. + +## Known Stubs + +None. All flags are fully wired and functional. The pcap mode end-to-end path is complete. + +## Self-Check: PASSED + +Files verified: +- /home/dev/workspace/yoloyolo/.claude/worktrees/agent-a90dedf3/cmd/netsynth/main.go: FOUND +- /home/dev/workspace/yoloyolo/.claude/worktrees/agent-a90dedf3/cmd/netsynth/main_test.go: FOUND + +Commits verified: 09e78bf, 4adb3c4 in git log. + +All tests green: `go test ./... -count=1` passed 6 packages. +Build succeeded: `go build ./...` clean.