feat(core,storage): add TraceQuery filtering, TraceView DTO, and store query/clear#9
Merged
Merged
Conversation
…e query/clear - phantom-core: TraceQuery (method/status/url/time-range/trace_id filters) with a pure matches() predicate; StatusRange parses "404", "4xx", "400-499"; TraceView + RenderOptions as the shared agent-facing JSON shape (max_body truncation, headers_only, header redaction, body size reporting); HttpMethod FromStr; SpanId/TraceId from_hex. - phantom-storage: TraceStore::query via bounded by_time range scan (by_trace_id prefix scan when trace_id is set) with offset applied after filtering; TraceStore::clear via batch removes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjmmAVFHuaU4Fb46QEd6ky
…code propagation
Breaking: the flat CLI is replaced by subcommands.
phantom run -- capture (old default behavior; same flags)
phantom list -- filtered listing (--method/--status 4xx/--url/--since 10m/
--until/--trace-id/--limit/--offset, --format jsonl|json|table,
--max-body/--headers-only/--redact-header)
phantom get -- single trace by span ID (exit 1 when not found)
phantom search -- positional URL-substring shorthand for list
phantom stats -- store statistics as JSON
phantom clear -- delete all traces (requires --yes)
phantom mcp -- reserved (stub, implemented next)
Agent/scripting fixes:
- Propagate the traced child's exit status (was discarded — phantom always
exited 0); Unix signal deaths map to 128+signal.
- tracing output now goes to stderr (was stdout, could corrupt JSONL).
- Machine-readable end-of-run summary on stderr in jsonl mode:
{"event":"exit","child_exit_code":N,"traces_captured":N}
- Global --quiet suppresses status lines; global --data-dir.
- run --max-body / --headers-only control JSONL body size.
phantom-storage: FjallTraceStore::open now takes an advisory flock on
phantom.lock — fjall itself does not lock across processes, so two phantom
instances (e.g. a query during a capture) could previously open the same
keyspace concurrently and risk corruption. Query commands surface a
lock hint pointing at the running process.
main.rs split into cli.rs, runner.rs, commands/{run,query}.rs.
Existing integration tests updated to the run subcommand; new
tests/cli_query_integration.rs covers exit codes, JSONL purity,
query filters, truncation, and the lock UX.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjmmAVFHuaU4Fb46QEd6ky
Serves the Model Context Protocol over stdio using the official rmcp SDK (v2.2). One process hosts both capture control and trace queries, so the store's single-process lock is never contended. Tools (7): - start_capture: spawn a command through the MITM proxy (Node/PHP/Java transparent HTTPS injection reused from the CLI runner), or a proxy-only session; auto-assigns a free port when none given - capture_status / stop_capture: session lifecycle, child exit codes, live trace counts - list_traces: filtered listing (method, status class/range, URL substring, time range, trace_id, pagination); bodies default to 256 bytes to protect agent context - get_trace: full detail by span ID (4 KiB default body cap, 0 = off) - get_stats / clear_traces (confirm-guarded) Sensitive headers (authorization, cookie, set-cookie, proxy-authorization) are redacted by default in tool output. Store calls run on spawn_blocking; sessions are torn down (children killed, proxies stopped) when the client disconnects. Register with: claude mcp add phantom -- phantom mcp tests/mcp_stdio_integration.rs drives the server with raw JSON-RPC over stdio: handshake, tools/list, a traced curl capture round-trip, filter and truncation checks, and clean shutdown on stdin EOF. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjmmAVFHuaU4Fb46QEd6ky
…nd MCP server AGENTS.md (= CLAUDE.md): new project layout (cli/runner/commands/mcp modules), run-subcommand build examples, CLI structure tables (global flags, run flags, query flags), exit-code and store-lock behavior, extended JSONL schema (*_body_bytes / *_body_truncated), new MCP Server section with tool table and Claude Code registration, test index and data-flow updates. GEMINI.md and crate AGENTS.md files aligned. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjmmAVFHuaU4Fb46QEd6ky
… MCP phantom-core (view.rs): - no truncation flag when the body fits max_body exactly - max_body 0 at the core layer empties the body and flags it - lossy UTF-8 decoding keeps the original byte size - redaction matches header names case-insensitively - sensitive_headers() covers all credential-carrying headers phantom-storage: - open-ended since-only / until-only time-range scans - limit 0 falls back to the default page size of 100 binary unit tests (commands/query.rs): - parse_time: RFC3339, relative durations (30s/10m/2h/1d = that long ago), garbage rejection - build_query rejects malformed --trace-id - render_options: 0 = unlimited, redact list lower-casing tests/cli_query_integration.rs: - SIGKILLed child maps to exit 137 (unix) - --quiet suppresses status lines and the exit summary while still propagating the exit code - run --max-body truncates the live JSONL stream and the stderr summary counts captured traces; run --headers-only reduces only the stream, the store keeps full bodies - list --method/--since/--until/--trace-id/--format json/--redact-header - invalid arguments fail fast: bad --status exits 2 via clap, bad span/trace IDs and bad --since exit 1 with clear messages tests/mcp_stdio_integration.rs: - tool error paths: unknown/malformed span_id, unknown session, bad method/status/trace_id filters, clear_traces without confirm - proxy-only session: no child, external curl through the returned proxy_url is captured, stop reports the final count - sensitive-header redaction on by default in list_traces/get_trace, raw value only with redact_sensitive_headers: false Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjmmAVFHuaU4Fb46QEd6ky
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
with a pure matches() predicate; StatusRange parses "404", "4xx",
"400-499"; TraceView + RenderOptions as the shared agent-facing JSON
shape (max_body truncation, headers_only, header redaction, body size
reporting); HttpMethod FromStr; SpanId/TraceId from_hex.
(by_trace_id prefix scan when trace_id is set) with offset applied
after filtering; TraceStore::clear via batch removes.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01BjmmAVFHuaU4Fb46QEd6ky