Repository navigation
Complete VeriSimDB hexad persistence (S1–S3) — campaign-driven #33
Description
Activity
- added 15 commits that reference this issue
on May 26, 2026 Temporal.chpl::writeTemporalHexadis the Chapel-side producer for
mass-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 the
chapel/tree and the Chapel↔Rust contract:Gate What it catches chapel-parse-checkChapel syntax regressions in any of 4 modules + smoke chapel-buildCross-module build break (stock ubuntu .deb, no toolbox) chapel-smokeRepoResult → SystemImage → JSONdata-flow regressionschapel-e2emass-panic full pipeline end-to-end (single-locale) chapel-cli-contractRust clap drift breaking Chapel's argv shape chapel-rust-diffAggregate divergence between rayon and Chapel paths The four silent-loss fixes (
path,high_count,error,
category_breakdownpreviously dropped bywriteNodeJson) mean
the 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:
- True multi-locale CI (
CHPL_COMM=gasnetinstall). - Subprocess kill-path on hang.
- NFS journal lock semantics.
- BoJ-estate scheduler benchmark to back the "~5–15% slower" claim.
See
docs/adr/0001-chapel-distributed-scanner.mdfor the full
rollout decision record.✅ 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).- Stable subject:
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.- Opt-in via env var
PANIC_ATTACK_STORE_FINDING_HEXADS(STORE_FINDING_HEXADS_ENV). Existing JSON output paths untouched, aggregate hexad still emitted in every VerisimDb run. - 7 unit tests: id stability/discrimination, one-per-WeakPoint, suppression skip, canonical PA-codes, file round-trip, env-default-off.
- Landed via feat(sweep-tracker): hierarchical estate-sweep Markdown report #62 (
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.- CLI:
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).
- Landed via feat(sweep-tracker): hierarchical estate-sweep Markdown report #62 (S2 register/dismiss/status scaffold absorbed) + feat(campaign): panic-attack campaign poll — GitHub PR transitions (issue #33 S2b) #60 (
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.- All three example query forms from the issue body now parse and run verbatim:
(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) ...)).
- Crosslang evaluator graduates from same-repo co-occurrence proxy to facts-backed FFI-endpoint reachability when crosslang hexads are persisted (env var
PANIC_ATTACK_STORE_CROSSLANG_HEXADS):- feat(storage): persist kanren CrossLangInteraction as hexads (issue #33 follow-up) #61 (
feat(storage): persist kanren CrossLangInteraction as hexads) —CrosslangSemantic+build_crosslang_hexads. - feat(query): facts-backed (crosslang :from :to) evaluator (issue #33 follow-up) #63 (
feat(query): facts-backed (crosslang :from :to) evaluator) — switches the evaluator to facts when available, falls back to co-occurrence proxy otherwise.
- feat(storage): persist kanren CrossLangInteraction as hexads (issue #33 follow-up) #61 (
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)
- HTTP push to a remote
verisim-api(VERISIMDB_URL) — listed as out-of-scope in the issue itself. - New PA-categories (PA026+) — explicitly out-of-scope in the issue.
- Replacing
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).- End-to-end smoke against
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).
- added 5 commits that reference this issue
on May 30, 2026
Problem
panic-attackalready has a VeriSimDB hexad storage mode (src/storage/mod.rs,StorageMode::VerisimDb) but it only wrapsAssaultReportfiles. 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[].reportis#[serde(skip)]src/assemblyline.rs:57skips the embeddedAssailReportwhen the assemblyline summary is serialized — sensible, because for 303 repos the fullweak_points[]would blow up to hundreds of MB. So today, the campaign has to do two passes: assemblyline for the repo list, then per-repoassail --output <repo>.jsonfor the WeakPoints. With a hexad store, the assemblyline pass could persist per-finding rows under arepo:<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:
audits/assail-classifications.a2ml(suppression)mass-panic-results/*.jsontimestamped scratchA hexad with
(finding-id, state, pr-url, classified-as, seen-in-runs[…])modalities would replace all three.panic-attack diffcould 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.rsderives FFI-boundary vulnerability chains but emits them as in-memory facts per scan. A persistent fact-base would letpanic-attack signaturesand a futurepanic-attack queryreason 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
StorageModepath:AssemblylineReportwrites one hexad perWeakPointinstead of one envelope per repo.finding:<repo>:<sha>:<file>:<line>:<category>(stable across runs).severity,description,language,framework,rule-id,first-seen-run,last-seen-run.--store-hexadsor env var.S2. Campaign state hexads
panic-attack campaign {start, register-pr, dismiss, status}.register-pr <finding-id> <pr-url>writes apr-state: openmodality.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.(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 baselineWhy 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
verisim-apiservice (VERISIMDB_URLenv var) — useful eventually, not part of this issue.audits/assail-classifications.a2mlfile format (the a2ml registry is human-reviewable; the hexad store is machine state).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