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)
This commit is contained in:
@@ -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 <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.
|
||||
Reference in New Issue
Block a user