SODL

Evidence

You can prove what verified,
against what, and when.

A test run that scrolls off the terminal is not evidence of anything. Every sodl run writes an immutable record instead — and every downstream claim SODL makes cites one.

The record

Five questions, answered on disk

Written temp-file-and-rename, then never reopened. Re-running writes a new timestamped file — it never edits an old one. There is no mechanism in SODL for revising history.

What ranEvery scenario, its state, its duration, its position in the tree.
Against whatThe contract sources and a digest of them, so a claim is anchored to a version.
WhereThe environment name, the endpoints, the routing table actually used.
WhenStart and finish, as timestamps you can cite.
By whatThe exact sodl version that produced the record.

.sodl/ belongs in your .gitignore. It is local evidence, not source — and the CI job that produced a record is the one that should publish it.

where evidence lives
$ sodl run
$ ls .sodl/runs/
20260801T093012Z.json
20260801T141955Z.json

$ sodl report -open      # latest record → a shareable page
$ sodl report -pdf out.pdf
$ sodl report -junit results.xml

explain walks any single failure back to the observations it rests on. inspect shows a fact with its authority and provenance — where it came from, and how strongly the contract states it.

The artifact

The page you hand to someone who was not there

One self-contained HTML file, rendered from the record — not re-derived. It prints cleanly, follows your light or dark theme, and needs no server to read.

Anatomy of the page

The headline is the counts, as a sentence
passed failed skipped not served
Provenance headerproject · environment · contracts digest · started · version
Verdict bannerone lawful sentence, and nothing else
Finding cardsposition, then the message verbatim — never truncated
Suite ledgerthe folder tree, each scenario, state and duration
Coverage
operations exercised
Attributionwho acted, and in whose context

What this record does not prove.

The structure, named. Proportions are illustrative — no run is being reported here.

One law governs every word on it

The page may point, never explain. Every string it shows is evidence: a count, a name, a file:line:col, an operation, a failure message verbatim, a timestamp.

It never editorialises — no “critical”, no “concerning”, no “probably caused by”. It never speculates about causes and never summarises a failure in its own words, because the verbatim message next to its position is the summary.

The section most products would delete. Every report ends with what the record does not prove — and that section is prominent, not fine print. A record that overstated its reach would be worse than no record, because someone would rely on it.

Drift & release gating

It fails your deploy for a change no test covered

A removed field breaks consumers whether or not you happened to write a test for it. SODL compares contracts, so the blind spot is covered by construction.

The two-step shape

Bundle the release. sodl bundle snapshots the resolved contract, the environments and the whole scenario tree into one directory that needs nothing outside itself. It is a project: run, check, inspect all work against it offline, by construction.

Then diff on every pull request. sodl drift re-checks the bundle’s own scenarios against today’s contracts and diffs the two contract snapshots.

the whole CI integration
# once, at release
$ sodl bundle scenarios -o release-bundle

# on every pull request
$ sodl drift release-bundle -against . -sarif drift.sarif

-sarif writes the breaking changes as SARIF 2.1.0, so a code-scanning UI annotates them on the contract line they concern. sodl report -junit is the run-record counterpart for your CI’s test tab.

What counts as breaking

OpRemovedAn operation the release depended on is gone.
FieldRemovedA request or response field is gone.
FieldTypeChangedType changed, or repeated became singular.
EnumStateRemovedA lifecycle state a consumer could observe no longer exists.
EntityRemovedAn entity disappeared from the surface.

Additions are reported as informational and do not fail anything. And a change whose position in the baseline is unknown is reported without a location — never with a guessed one.

The release question

“Is it safe to deploy?” — answered with a citation

sodl can-deploy gives one of two words, and it always names the evidence it used. A verdict you cannot trace is an opinion.

DEPLOYABLE

There is a verified run for this environment, its counts are clean, and the contract it verified against still matches the one you are shipping.

BLOCKED

No run evidence for this environment, a real failure in it, or a contract that has moved since. The reason line says which.

sodl can-deploy
$ sodl can-deploy -env staging

DEPLOYABLE
evidence: .sodl/runs/20260801T093012Z.json (started 2026-08-01T09:30:12Z, 14 pass, 0 fail, 0 skipped, 0 not served, 0 unsupported, 0 uncompilable)

The citation line is SODL’s own format, verbatim — all six counts, always. A count missing from a citation is evidence silently discarded.

Note what is not here: no score, no confidence percentage, no “probably fine”. Where SODL uses AI at all, it is a read-model over derived evidence — it may surface observations and ask questions, and it never gets a voice on the attestation. A probabilistic verdict on the one artifact that carries don’t assume, prove it would betray it.

Next

The boundaries page states what SODL cannot do, which formats it claims versus merely reads, and exactly what is shippable today.