Usage
What it does
1
Builds the scenario
Loads config, constructs the chain adapter and facilitator client, and registers all eight
invariants via
buildScenario().2
Runs every invariant sequentially
runInvariants(invariants, ctx, { concurrent: false }) executes U1, U4, U2, U3,
A1, U5, A2, A3 in that order (see D6
for why), catching and recording a failure per-invariant rather than aborting the whole run on
one exception.3
Renders a terminal report
Prints a table grouped by category (
universal / algorand), each row showing a PASS/FAIL
badge, invariant id and name, duration, and a one-line evidence summary.4
Writes the JSON report
Writes both
reports/ward-report-<ISO-timestamp>.json (a permanent, timestamped record) and
reports/latest.json (always overwritten with the most recent run, read by ward report).5
Sets the exit code
Exits non-zero if any must-have invariant (
U1, U2, U3, U4, A1) failed — safe to
gate CI on. Stretch invariant failures (U5, A2, A3) are reported but don’t affect the
exit code.Example output
The written report’s shape
InvariantResult.evidence contains the complete, per-sub-case request/response trail for
that invariant — the same data ward fuzz prints for a single invariant, just for all eight at
once. Numeric values that are JavaScript bigints (e.g. microAlgo amounts) are serialized to
strings so the report is valid JSON.
Interpreting must-have failures in CI
U1, U2, U3, U4, or A1 failed — open the written
report and check that invariant’s evidenceSummary and evidence fields first; each cites its
source so you know exactly which guarantee was violated.
Isolate a single invariant
Once you know which invariant failed, re-run it alone with
ward fuzz <id> for the full,
verbose evidence trail.
