--- 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.