Commit c41905c
feat(query): panic-attack query subcommand (issue #33 S3)
Adds the third slice of issue #33: a panic-attack query subcommand that
evaluates a small S-expression query language over the persisted
per-finding hexads (S1) and campaign-state hexads (S2), joined by
finding_id.
Supported forms in this initial S3:
(category UnsafeCode)
(rule-id PA004)
(severity Critical)
(repo <name-substring>) ; case-insensitive substring
(file <path-substring>) ; case-insensitive substring
(pr-state pr-filed|pr-merged|pr-closed|dismissed|nil)
(and <expr> <expr> ...)
(or <expr> <expr> ...)
(not <expr>)
`pr-state nil` matches any finding without a campaign hexad — i.e. the
operationally important "open work not yet PR'd" view that the
estate-sweep campaign needs most.
CLI:
panic-attack query "(and (category UnsafeCode) (pr-state nil))"
panic-attack query "(severity Critical)" --format json
panic-attack query "(repo alpha)" --verisimdb-dir verisimdb-data
Output: fixed-width table by default, JSON via `--format json`.
Deferred to S3 follow-ups (recorded in the module header):
- (crosslang :from FFI :to ProofDrift) — needs integration with
src/kanren/crosslang.rs.
- (diff :since <date> :category <X>) — needs an explicit baseline-run
cursor beyond created_at.
Implementation notes:
- Small hand-rolled S-expression tokenizer/parser in src/query/mod.rs
(~170 lines including escape handling for quoted strings and `;`
line comments). Doesn't depend on the a2ml parser since the query
surface is narrower.
- Evaluator pre-joins findings with their latest campaign event
(newest-by-created_at wins per finding_id) before filtering. That
keeps `(pr-state ...)` a free clause inside `and`/`or` rather than
forcing a special-case in the loop.
Tests: 19 new in src/query/ — 8 parser (positive + 3 rejection cases),
9 evaluator (each filter, and/or/not, pr-state nil/filed/excluded), 2
renderer. Full lib suite: 239 green. Clippy clean.
CLI smoke validated: writing a hand-crafted finding hexad + invoking
campaign register-pr + query returns the expected JSON with the
pr-filed state joined in.
Refs #33. Stacked on #56 (S2). Diff against main includes S1+S2
changes until they land; this PR rebases cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent d6e41dc commit c41905c
3 files changed
Lines changed: 759 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| 30 | + | |
30 | 31 | | |
31 | 32 | | |
32 | 33 | | |
| |||
753 | 754 | | |
754 | 755 | | |
755 | 756 | | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
756 | 779 | | |
757 | 780 | | |
758 | 781 | | |
| |||
2404 | 2427 | | |
2405 | 2428 | | |
2406 | 2429 | | |
| 2430 | + | |
| 2431 | + | |
| 2432 | + | |
| 2433 | + | |
| 2434 | + | |
| 2435 | + | |
| 2436 | + | |
| 2437 | + | |
| 2438 | + | |
| 2439 | + | |
| 2440 | + | |
| 2441 | + | |
| 2442 | + | |
| 2443 | + | |
| 2444 | + | |
| 2445 | + | |
| 2446 | + | |
| 2447 | + | |
2407 | 2448 | | |
2408 | 2449 | | |
2409 | 2450 | | |
| |||
0 commit comments