- 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)
110 lines
4.6 KiB
Markdown
110 lines
4.6 KiB
Markdown
---
|
|
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 <file>..."` 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.
|