Repository navigation
Complete VeriSimDB hexad persistence (S1–S3) — campaign-driven #33
Description
Problem
panic-attack already has a VeriSimDB hexad storage mode (src/storage/mod.rs, StorageMode::VerisimDb) but it only wraps AssaultReport files. The TOPOLOGY dashboard lists "VerisimDB Storage ██████░░░░ 60% — File I/O works, API planned" and the Patch Bridge section says "Phase 2 adds VeriSimDB hexad persistence and auto-retire on upstream fix".
Running the estate sweep campaign (#32) surfaces three concrete places this gap hurts:
1. AssemblylineReport.results[].report is #[serde(skip)]
src/assemblyline.rs:57 skips the embedded AssailReport when the assemblyline summary is serialized — sensible, because for 303 repos the full weak_points[] would blow up to hundreds of MB. So today, the campaign has to do two passes: assemblyline for the repo list, then per-repo assail --output <repo>.json for the WeakPoints. With a hexad store, the assemblyline pass could persist per-finding rows under a repo:<name> partition and queries like "all PA001 in repos with critical count > 0" would be a single DB call instead of N JSON parses.
2. Cross-run state has no native home
The campaign needs to remember: which findings have been turned into PRs, which were classified as legitimate, which are parked. Today this lives in:
- Per-repo
audits/assail-classifications.a2ml(suppression) mass-panic-results/*.jsontimestamped scratch- A GitHub tracker issue checklist (manual)
A hexad with (finding-id, state, pr-url, classified-as, seen-in-runs[…]) modalities would replace all three. panic-attack diff could then natively answer "what's new since 2026-04-12" instead of being a JSON-vs-JSON delta.
3. Cross-repo taint chains can't be queried
src/kanren/crosslang.rs derives FFI-boundary vulnerability chains but emits them as in-memory facts per scan. A persistent fact-base would let panic-attack signatures and a future panic-attack query reason across the whole estate without re-scanning.
Proposal
Complete the 60% → 100% on VeriSimDB integration in three slices (one PR each):
S1. Persist per-finding rows from assemblyline
- New
StorageModepath:AssemblylineReportwrites one hexad perWeakPointinstead of one envelope per repo. - Subject =
finding:<repo>:<sha>:<file>:<line>:<category>(stable across runs). - Modalities:
severity,description,language,framework,rule-id,first-seen-run,last-seen-run. - Backwards-compatible: existing JSON output paths unchanged; hexad write is additive behind
--store-hexadsor env var.
S2. Campaign state hexads
- New subcommand:
panic-attack campaign {start, register-pr, dismiss, status}. register-pr <finding-id> <pr-url>writes apr-state: openmodality.- Polls GitHub (with
httpfeature) to update modalities as PRs merge/close. statusrenders a Markdown report identical to the manual tracker checklist used in panic-attack estate sweep — 2026-05-26 #32.
S3. Cross-repo query
panic-attack query <relational-expr>evaluates kanren over the persisted hexads.- Examples:
(crosslang :from FFI :to ProofDrift)— proof code reachable from FFI(category PA001 :severity Critical :pr-state nil)— open work(diff :since 2026-04-12 :category PA022)— new CryptoMisuse since baseline
Why now
The estate sweep #32 is the first real consumer at scale: ~300 repos × tens-to-hundreds of findings each = the regime where JSON files become friction. If S1 lands during the sweep, the campaign becomes its own validation.
Out of scope
- HTTP push to a remote
verisim-apiservice (VERISIMDB_URLenv var) — useful eventually, not part of this issue. - Replacing the
audits/assail-classifications.a2mlfile format (the a2ml registry is human-reviewable; the hexad store is machine state). - New PA-categories (PA026+).
References
src/storage/mod.rs— current StorageMode::{Filesystem, VerisimDb}src/assemblyline.rs:57—report: Option<AssailReport>with#[serde(skip)]verisimdb-data/— two prior AssaultReport hexads (2026-02-09, 2026-02-11)TOPOLOGY.md— "VerisimDB Storage 60%" line- #32 — campaign tracker
Activity
docs(campaigns): add 2026-05-26 estate sweep report (human + machine)
fix(storage): env var alone now opts run into VerisimDb mode (issue #33…
feat(sweep-tracker): hierarchical estate-sweep Markdown report (#62)
docs(campaigns): add 2026-05-26 estate sweep report (human + machine) (…
feat(query): panic-attack query subcommand (issue #33 S3)
feat(query): panic-attack query subcommand (issue #33 S3) (#57)
feat(query): (crosslang ...) + (since ...) forms (issue #33 S3b+c)
feat(query): (crosslang ...) + (since ...) forms (issue #33 S3b+c) (#58)
feat(campaign): panic-attack campaign poll — GitHub PR transitions (i…
feat(campaign): panic-attack campaign poll — GitHub PR transitions (i…
feat(storage): persist kanren CrossLangInteraction as hexads (issue #33…
feat(storage): persist kanren CrossLangInteraction as hexads (issue #33…
feat(query): facts-backed (crosslang :from :to) evaluator (issue #33 …
feat(query): facts-backed (crosslang :from :to) evaluator (issue #33 …
feat(chapel): wire MassPanic CI + cross-rust contract checks (refs #33)…
hyperpolymath commentedon May 30, 2026
Temporal.chpl::writeTemporalHexadis the Chapel-side producer formass-panic temporal snapshots, which feed the VeriSimDB hexad readers
this issue tracks (S1 per-finding, S2 campaign-state, S3 query).
PR
feat/chapel-ci-strict-gateslands six strict CI gates on thechapel/tree and the Chapel↔Rust contract:chapel-parse-checkchapel-buildchapel-smokeRepoResult → SystemImage → JSONdata-flow regressionschapel-e2echapel-cli-contractchapel-rust-diffThe four silent-loss fixes (
path,high_count,error,category_breakdownpreviously dropped bywriteNodeJson) meanthe producer side now preserves every ImageNode field the hexad
consumer can persist. Mapping of Chapel writers → hexad facets:
provenance←Temporal.chpl(tool, version, locales, scan_surface)temporal←Temporal.chpl(timestamp, sequence_number, label)semantic←Imaging.chpl(global_health, global_risk, totals)structural←Imaging.chpl(totalFiles, totalLines, riskDistribution)document←Imaging.chpl::writeSystemImageJson(full SystemImage)Out of scope here, tracked for Wave 2:
CHPL_COMM=gasnetinstall).See
docs/adr/0001-chapel-distributed-scanner.mdfor the fullrollout decision record.
hyperpolymath commentedon May 30, 2026
✅ Resolution
All three slices specified in the issue body have shipped to
main. The full closure trail (verified against the code inmainat2d35425):S1. Persist per-finding rows from assemblyline — DONE
FindingSemanticstruct insrc/storage/mod.rscarries every modality the issue specified:finding_id,repo_name,file,line,category,rule_id(canonical PA-code, mirrors SARIF),rule_name,severity,description,first_seen_run,last_seen_run,framework.languagelives onHexadProvenancefor every hexad (shared across the facets).finding:<repo>:<file>:<line>:<category>—build_finding_idatsrc/storage/mod.rs:471. (Dropped the<sha>component from the original sketch because two scans of the sameHEADneed to converge on the samefinding_idfor S2/S3 to join across runs without a commit step.)build_finding_hexadsatsrc/storage/mod.rs:505emits one hexad perWeakPoint, skipping suppressed findings.PANIC_ATTACK_STORE_FINDING_HEXADS(STORE_FINDING_HEXADS_ENV). Existing JSON output paths untouched, aggregate hexad still emitted in every VerisimDb run.feat(sweep-tracker): hierarchical estate-sweep Markdown report) which absorbed the S1 scaffold staged by the original feat(storage): per-finding hexad emission (issue #33 S1) #55. Feat/issue 33 s1 finding hexads #80 (re-file) closed as superseded on 2026-05-30.S2. Campaign state hexads — DONE
CampaignSemanticstruct insrc/storage/mod.rs:finding_id(matches the S1 subject),state(free-form for forward-compatibility — canonical valuesopen,pr-filed,pr-merged,pr-closed,dismissed),pr_url,reason,last_polled. Append-only — the current state per finding is the newest hexad with that subject.panic-attack campaign {register-pr, dismiss, status, poll}. Module atsrc/campaign/mod.rs:register_pr(finding_id, pr_url)writesstate = pr-fileddismiss(finding_id, reason)writesstate = dismissedcurrent_state()reduces to the newest-per-finding_idstatus_markdown()renders the tracker matching the shape of #32's manual checklist (summary line, finding-id/repo/rule/location/state/PR/last-event table with[x]/[ ]column for merged/closed/dismissed vs open).poll()queries GitHub for PR-state transitions and writes promotion hexads (S2b).feat(campaign): panic-attack campaign poll) for the GitHub polling layer. Feat/issue 33 s2 campaign state #79 (re-file) closed as superseded on 2026-05-30.S3. Cross-repo query — DONE
panic-attack query <expr>evaluates the S-expression DSL atsrc/query/mod.rs.(crosslang :from FFI :to ProofDrift)— shipped in feat(query): panic-attack query subcommand (issue #33 S3) #57 (parser) + feat(query): (crosslang ...) + (since ...) forms (issue #33 S3b+c) #58 (crosslangkeyword form +(since ...)).(category PA001 :severity Critical :pr-state nil)— shipped in feat(query): accept issue #33 literal examples — diff head + inline kwargs + PA-id auto-route #88 (inline:keyword VALUEkwargs on every unary head +(category PA…)auto-routing torule-id). PR open with auto-merge armed.(diff :since 2026-04-12 :category PA022)— shipped in feat(query): accept issue #33 literal examples — diff head + inline kwargs + PA-id auto-route #88 (newdiffhead as keyword-only sugar for(and (kw VALUE) ...)).PANIC_ATTACK_STORE_CROSSLANG_HEXADS):feat(storage): persist kanren CrossLangInteraction as hexads) —CrosslangSemantic+build_crosslang_hexads.feat(query): facts-backed (crosslang :from :to) evaluator) — switches the evaluator to facts when available, falls back to co-occurrence proxy otherwise.Bonus surface
panic-attack sweep-trackersubcommand (src/sweep_tracker/mod.rs) joins S1 + S2 hexads into a hierarchical (by_repo/by_category/ both) Markdown report, in addition to the flat per-finding table fromcampaign status.Out of scope (deferred — not blocking close)
verisim-api(VERISIMDB_URL) — listed as out-of-scope in the issue itself.audits/assail-classifications.a2ml— explicitly out-of-scope in the issue.Verification
cargo test --lib --no-default-features: 300 passed (was 288 before feat(query): accept issue #33 literal examples — diff head + inline kwargs + PA-id auto-route #88; 12 new tests cover the issue's three literal example expressions).target/release/panic-attack: all three issue-example queries parse + run cleanly against a populated hexad store.Closing — TOPOLOGY's "VerisimDB Storage 60%" line can move to 100%, and the Patch Bridge "Phase 2 adds VeriSimDB hexad persistence" note can be marked complete for the campaign-state path (auto-retire-on-upstream-fix is the next slice on the bridge registry side, tracked separately).
feat(query): accept issue #33 literal examples — `diff` head + inline…
feat(query): accept issue #33 literal examples — diff head + inline k…
chore(fmt): apply rustfmt drift cleanup (mechanical, no behaviour cha…
chore(fmt): apply rustfmt drift cleanup (#89)
docs: wrap up issue #33 closure — consolidate CHANGELOG + sync CLAUDE…