The DuckDB warehouse
corral stores every audit as a signed, hash-linked record plus per-model execution telemetry — natively in DuckDB. The DuckDB integration page (“DuckDB integration” in the site nav) makes that layer tangible: it runs DuckDB itself, compiled to WebAssembly, in your browser, over corral’s real audit dataset. Real SQL, no backend.
What you can query
Section titled “What you can query”Four real DuckDB tables, shipped as parquet extracts and queried client-side — corral’s own historical stores, hand-exported from the machine that produced them:
audit_ledger— the signed verdict records. Every audit is a tamper-evident, hash-linked row:repo,commit,record_head(the signature head),certified(the verdict),actor.bug_catches— per-model, per-role, per-region execution telemetry: which model planted or graded,mutants_planted/mutants_killed/mutants_survived,region_complexity, and more.scans— whole-repo scan runs:total_files,candidates,audited,kill_rateper scan.scan_files— every candidate file a scan considered, audited or rejected, withdisposition,reason,kill_rate,survivors, andproven_missed.
The page ships eight preset queries — which files keep shipping demonstrated gaps, whether a file’s kill rate is drifting or just noisy sampling, which model catches bugs in which role, every signed verdict by repo, every audited file’s proven gap, one file’s replicate series, the honest denominator of what a scan rejected and why, and the scan-level receipts — plus a live query box so you can write your own. Open the page to see the current set; it’s likely to keep moving.
It’s grounded, not marketing
Section titled “It’s grounded, not marketing”The point is that a claim is one click from the SQL that grounds it. A
?q=<sql> deep-link
pre-fills and runs a query, so the recordings cockpit links straight to the numbers
behind a run. The verdicts you see (more-itertools certified at 90%, a Ruby
edit-distance suite sent back at 60%) are the same signed records the
recordings come from.
Two shapes, and which is which
Section titled “Two shapes, and which is which”The page on this site queries corral’s own historical stores —
audit_ledger, bug_catches, scans, scan_files — hand-exported from the
machine that produced them.
--push writes something newer: a five-table bundle — corral_scans,
corral_audits (one row per audited file), corral_mutants, corral_model_calls,
and corral_events — auto-created on first push, plus a corral_seal view that
cross-references the pushed statement’s hash against the rows it produced. Same
subject, different shape, and everything below describes that bundle, because
that is what you get. The published page has not been backfilled into it.
Getting your own
Section titled “Getting your own”The page on this site queries our audit data. The point is that you can have
the same table of your own, because certify --repo takes a target and appends
every run’s per-file verdict to it:
corral certify --repo . --push md:my_database -- pytest -q# or a plain file, if you would rather not involve anyonecorral certify --repo . --push ./audits.duckdb -- pytest -qFrom the Action, the same thing is push: plus a
motherduck-token: secret when the target is md:.
There is no hosted tier and nothing is collected: your key, your runner, your warehouse. Any DuckDB works, so MotherDuck is a destination rather than a requirement.
Rows are append-only — overwriting is how a trend is lost — and each carries
the sha256 of the signed statement it came from plus the run URL, so any row
traces back to an attestation a third party can verify. The qualifier columns
(timed_out, test_writer_failed, pool_test_unsound) sit beside the numbers
rather than in another table, because aggregation is exactly where a
proven_missed of 0 that means nothing could be proven gets read as clean.
The queries that need a warehouse
Section titled “The queries that need a warehouse”A single run cannot answer these, and that is the whole reason to keep the rows:
-- Which files keep shipping DEMONSTRATED gaps. Countable across repos, unlike-- kill rates: a dense function and a small accessor are not the same-- measurement, so averaging their rates says nothing.SELECT repo, path, count(*) AS runs, sum(proven_missed) AS demonstrated_gapsFROM corral_auditsGROUP BY 1, 2HAVING demonstrated_gaps > 0ORDER BY demonstrated_gaps DESC;
-- Drift, or sampling? Mutants are generated fresh per run, so one number is a-- sample. A spread tells you whether a change is real.SELECT path, count(*) AS runs, round(avg(kill_rate), 2) AS mean, round(min(kill_rate), 2) AS worst, round(max(kill_rate), 2) AS bestFROM corral_auditsGROUP BY 1 ORDER BY mean;
-- The honest denominator: how much of what changed could be audited at all.SELECT repo, sum(audited) AS audited, sum(candidates) AS candidatesFROM corral_audits GROUP BY 1;Why in the browser
Section titled “Why in the browser”The DuckDB runtime loads from a CDN (the WebAssembly build is larger than a static host’s per-file cap, and loading the runtime from a CDN is standard); the data is self-hosted parquet. Because DuckDB runs client-side in a WebAssembly sandbox over public, read-only data, there is no server-side SQL — so there is nothing to inject into. The query runs in your browser, on public data, in a sandbox; that’s precisely why the query box can be handed to anyone.
Where it goes
Section titled “Where it goes”The public page proves the model on one project’s data. The same schema federates to MotherDuck (a DSN flip): signed records from every dev, CI runner, and project into one shared, queryable warehouse — read-only shares hand a client or an auditor a live, verifiable slice with zero infra. See Multi-model herds and the roadmap.