Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Command reference

Every code block below is veredictum <command> --help from the binary itself: this page is rendered by scripts/render/commands-md.sh out of clap’s own output, so a flag cannot land in the binary and go missing here. The sections follow the order veredictum --help lists them in, and the prose under each one is written by hand and lives in website/book/commands/.

Three commands make the conformance record (validate, run, verdicts), three measure (perf, stress, bench), replay re-judges a recorded run out of its own transcript, evidence carves the exchanges behind a red run’s rows out of that transcript, verify-record checks a sealed bundle, and the rest render or explore.

emit-schemas

Write the published JSON-Schema set (byte-deterministic)

Usage: veredictum emit-schemas --out <OUT>

Options:
      --out <OUT>  Output directory (created if missing)
  -h, --help       Print help

Byte-deterministic. The schemas in the repository’s schemas/ directory are this command’s output, drift-tested against it, which is how the published format and the code that reads it stay one thing. Author against these if you are writing your own catalogue or your own harness.

run

Execute the catalogue against a live SUT (from its ixit topology) and emit results.json + the run report

Usage: veredictum run [OPTIONS] --root <ROOT> --ixit <IXIT> --out <OUT>

Options:
      --root <ROOT>
          The artifact root

      --ixit <IXIT>
          The ixit topology file (JSON)

      --out <OUT>
          Output directory for results.json + the run summary

      --sut-name <SUT_NAME>
          SUT display name
          
          [default: ferroehr]

      --sut-version <SUT_VERSION>
          SUT version label
          
          [default: dev]

      --filter <FILTER>
          Only run cases whose id contains this substring

      --statement <STATEMENT>
          The party statement (ICS) — the list ISO/IEC 9646 test selection selects from. Supplied, an option-gated case whose arm the ICS does not declare is recorded N/A at drive time; absent, NO arm of a mutually exclusive branch is selected, so every such case and every extension route is recorded N/A with its citation and the run says so once

      --sign-key <SIGN_KEY>
          An armored OpenPGP secret key — when supplied, the emitted documents are sealed with `record-manifest.json` and its detached signature, which `verify-record` and `gpg --verify` both check

      --sign-passphrase <SIGN_PASSPHRASE>
          The passphrase unlocking `--sign-key`. Supply it through the environment: a passphrase on the command line is visible to every process on the host
          
          [env: VEREDICTUM_SIGN_PASSPHRASE]

      --record-exchanges
          Persist the wire exchanges beside results.json as transcript.json.
          
          OFF by default. The artifact can carry real patient data — a SUT's response body is recorded verbatim — so it is operator-controlled output, never a log: store it where the record itself is stored. The `authorization` request header's value is withheld; everything else lands exactly as it went out and came back.

      --progress
          Print one machine-parseable line per processed case: `progress: <k>/<n> <case-id>` after `progress: 0/<n>` — a stable grammar a driver may parse. Off by default, so existing output is byte-identical without it

  -h, --help
          Print help (see a summary with '-h')

Drives every applicable case and records the exchange. Exits 1 if any case failed or errored.

validate

Validate one artifact tree through every machine gate

Usage: veredictum validate [OPTIONS] --root <ROOT>

Options:
      --root <ROOT>
          The artifact root (schedule/, bindings/, vocab/, corpus/, registers/)

      --specs <SPECS>
          The vendored openEHR spec tree; enables SM-operation and spec-ref resolution

      --write-report
          Also refresh `<ROOT>/coverage-report.md` from `--specs`.
          
          OFF by default: `validate` is a check verb, and a check that mutates the working tree is a trap for read-only and fenced invocations. The pipeline scripts that publish the report pass this explicitly.

      --statement <STATEMENT>
          A submitted declaration (`statement.json`) to hold to the static conformance review, with the `ixit.json` beside it.
          
          ISO/IEC 9646-7 assigns an ICS proforma's support and supported-values columns to the supplier of the implementation, so no declaration is committed here and none is swept from the tree.

  -h, --help
          Print help (see a summary with '-h')

Every machine check over the catalogue: identifier uniqueness, citation resolution, binding completeness, coverage of the enumerated wire surface, and the per-capability case-count floors. It prints one line per finding and a summary line, and exits 1 if the finding count is not zero.

Supplying --statement adds the static conformance review of ISO/IEC 9646-1 and -7 over that one declaration: a claimed capability the catalogue holds no verdict-bearing case for, a Signing claim the ixit beside it declares no posture for, and a served-extension family the catalogue’s wire surface does not carry.

--write-report is off by default on purpose. A check verb that rewrites a file on every run is a trap for read-only invocations, so the pipelines that publish the coverage report ask for it explicitly. The report lands at <ROOT>/coverage-report.md, beside the artifact families it measures.

perf

Execute the performance schedule's open-loop measured run(s) against a live SUT and merge the §8.10 measurement records into an existing results.json (conformance-by-measurement)

Usage: veredictum perf [OPTIONS] --root <ROOT> --ixit <IXIT> --results <RESULTS> --class <CLASS>

Options:
      --root <ROOT>                  The artifact root
      --ixit <IXIT>                  The ixit topology file (JSON) — its environment block is mandatory for a measured run
      --results <RESULTS>            The results.json to merge the measurement records into (written by a prior `run`)
      --class <CLASS>                Select the performance case(s) of this class (POC | S | L | R)
      --seed-workers <SEED_WORKERS>  Parallel seeding workers [default: 16]
      --hours <HOURS>                The sustained-window ladder: hours to hold the offered load — 1 (default, the case's normative window) | 2 | 4 | 6 | 8 | 12. A longer window is a STRICTER demonstration and persists like any measured run; nothing shorter than the case exists [default: 1]
  -h, --help                         Print help

Conformance by measurement. Latency is measured from the planned arrival instant under open-loop offered load, so a stall shows up as latency instead of disappearing into a slowed-down request rate. A longer --hours window is a stricter demonstration and persists like any measured run; nothing shorter than the case exists.

The environment block is mandatory rather than optional because a latency number is a claim about a deployment, and a claim with no deployment described cannot be checked or reproduced.

stress

Run the step-load STRESS instrument: geometric load steps to the maximum sustainable throughput — where the system breaks (exploration only; never a conformance record, and class-free by design)

Usage: veredictum stress [OPTIONS] --root <ROOT> --ixit <IXIT> --out <OUT>

Options:
      --root <ROOT>                  The artifact root
      --ixit <IXIT>                  The ixit topology file (JSON) — its environment block is mandatory (a throughput number without the deployment described is meaningless)
      --out <OUT>                    Where to write the stress report (stress.json)
      --corpus-class <CORPUS_CLASS>  The class-scale corpus the stress runs on (POC | S | L | R — the standardized corpus selector): data volume + workload mix only; no class floor enters the stress report or chart [default: POC]
      --seed-workers <SEED_WORKERS>  Parallel seeding workers [default: 16]
      --step-secs <STEP_SECS>        Each load step's recorded hold, seconds (short + intense by design) [default: 120]
      --bisections <BISECTIONS>      Post-breach bisection refinements [default: 3]
      --max-rate <MAX_RATE>          The climb cap (arrivals/s) [default: 4096]
  -h, --help                         Print help

Exploration only, and class-free by design: no class floor enters the stress report or its chart. A stress.json is never a conformance record, and quoting one as if it were is a misuse of the tool.

bench

Run the universal SPEED benchmark: an embedded pack against any reachable CDR over its base URL, seeded once and measured N times open-loop (comparative speed only; never a conformance record, a certificate, or a performance-class rating)

Usage: veredictum bench [OPTIONS] --base-url <BASE_URL> --out <OUT>

Options:
      --base-url <BASE_URL>
          The system's base URL, up to and including the openEHR REST base (for example `https://cdr.example/openehr/v1`)

      --auth <AUTH>
          How the client presents itself: `none`, `basic` or `bearer`.
          
          The secret never rides argv: `basic` reads `VEREDICTUM_BENCH_PASSWORD` and `bearer` reads `VEREDICTUM_BENCH_TOKEN`.
          
          [default: none]

      --user <USER>
          The user `--auth basic` presents

      --pack <PACK>
          The embedded pack to drive
          
          [default: smoke]

      --posture <POSTURE>
          The posture profile to declare, out of the set the pack defines. Omit to take the pack's first, which is always `minimal`.
          
          The run's canaries check the declaration against the running system before and after the measured window, and a contradiction refuses the run.

      --repetitions <REPETITIONS>
          How many times to repeat the measured phases. A result with fewer than three is recorded as not submittable, and names that as one of its unmet requirements
          
          [default: 3]

      --scale <SCALE>
          Multiply the pack's EHR count by this factor, for a shorter run. Anything but `1.0` takes the run off the pack's pinned configuration, and the record says so
          
          [default: 1]

      --seed-workers <SEED_WORKERS>
          Override the worker count every seed phase declares. Omit to run the pack's own value, which is what its reference figures describe

      --with-baselines
          After the target's run, compose each pinned reference CDR on this host from its own digest-pinned images, drive the same pack at the same seed against it, and record the relative index. Needs the docker CLI; a record without a baseline is not submittable

      --out <OUT>
          Output directory for the result document and its summary

      --label <LABEL>
          A label for this run, which names its column in a comparison and distinguishes its file name in a shared output directory

  -h, --help
          Print help (see a summary with '-h')

A bench run needs no artifact root, no IXIT and no party statement. The pack is compiled into the binary with a sha256 pin on every fixture, and the pins are recorded in the result.

The embedded packs

smoke proves the engine: one blood-pressure template, a small EHR corpus, and one mixed open-loop phase over the read, write and query surface.

community-vitals reproduces the openEHR community’s vital-signs benchmark harness (thread 17224) and measures the same work a second way. Its write phase creates 100 EHRs and commits the same Vital signs composition 1,000 times into each with Prefer: return=identifier, on one worker, reporting bulk-load throughput plus the whole-loop milliseconds-per-composition average the thread quotes. Its read phase then runs twice over that population. read_walk is the sequential walk the harness performs, seven GETs against every committed composition: the latest version, the same at an instant, the VERSIONED_COMPOSITION, its latest version, its version at that instant, one version by id, and the revision history. It reports the whole-loop microseconds-per-request average. read_open_loop offers the same seven reads as an arrival schedule pinned at 200/s for 60s after a 15s warmup, which is where the coordinated-omission-free percentiles come from. The pinned rate is part of the pack version.

Every number in the record carries the discipline that produced it: a closed-loop whole-loop average and an open-loop percentile answer different questions and are never read against one another. The two fixtures are embedded byte-identically, the operational template from the vendored CKM export for template id Vital signs and the composition from the attachment on post 8 of that thread, both pinned by sha256 and verified at load.

aql-mix measures query speed over that same population, from the same two pinned fixtures, so a query figure and a read figure describe the same corpus. Its seed phase creates 50 EHRs and commits the composition 20 times into each, on a pool of 8 workers. The pack version pins that population, and it is sized for query shapes: large enough that a query has to choose an access path, small enough to load before a measured window opens. The measured phase is open-loop at 24 arrivals a second for 60s after a 15s warmup, over six query classes at equal share, so each class is offered at 4 arrivals a second and every class returns the same number of samples.

ClassWhat it probes
adhoc_query_point_lookupThe indexed-read floor: one composition addressed by its own uid inside one EHR, the cheapest query a server can answer
adhoc_query_ehr_scanThe loaded-database shape: every composition in one EHR projected by uid, so the cost follows how much that EHR holds
adhoc_query_filteredThe value index: a systolic magnitude threshold over the observation leaves of one EHR
adhoc_query_populationThe cross-EHR planner: the same threshold with no EHR scope and a fetch bound, so the server picks an access path over the whole population
adhoc_query_aggregateThe columnar shape: one COUNT over the population that threshold matches, which returns a single row and reads every value behind it
adhoc_query_ordered_pageSorting and pagination: an ORDER BY over composition start time read through a moving fetch window

Each class posts its own AQL statement to /query/aql, accepts only 200, and counts every other answer in its own error class, so a server that refuses one shape leaves the other five classes’ percentiles alone. The systolic threshold, the page offset, and the EHR or composition each arrival addresses all draw from the run’s seeded streams, so no arrival repeats the previous one’s result set and the whole draw is reproducible from the seed the record discloses. Why each class exists travels with the pack definition, so a rendered view explains a column without knowing anything about the pack’s internals.

--scale shrinks the EHR count for a quick run and changes nothing else. Anything but 1.0, or a --seed-workers override, takes the run off the pack’s pinned configuration; the record says so in its scale block, the summary says so in prose, and bench-compare names it in the header.

Credentials never ride the command line: --auth basic reads its password from VEREDICTUM_BENCH_PASSWORD and --auth bearer reads its token from VEREDICTUM_BENCH_TOKEN.

Before anything is measured, a preflight reads the template list, uploads the pack’s template, then creates one scratch EHR, commits a composition into it and reads that composition back. A failure at any of those refuses the run and names the exchange, so a half-measured document never exists.

The run then seeds its corpus once and repeats the measured phases. Measured phases are open-loop: arrivals fire at their planned instants whatever the system is doing, and every latency is measured from the planned instant, so a stall shows up in every arrival queued behind it.

Posture profiles

A CDR running without an audit trail and unsigned versions is a different system from the same CDR with both switched on, and a speed number that does not say which one it measured cannot be compared with anything. Every pack therefore defines named posture profiles, and a run declares exactly one.

minimal is the bare spec-conformant surface, and every pack defines it: no audit trail, unsigned versions, commits validated against the operational template, uncompressed responses, one tenant. Validation sits at template rather than at nothing because the specification puts it there: ITS-REST specifications/responses/422.yaml defines the commit refusal as the case where the template “is not validating the supplied resource”. A server that accepts anything is below the floor rather than lightly configured. community-vitals also defines clinical-default, which is the same surface with an audit trail written.

The record’s posture block carries the profile, its summary, and one line per disclosed item: the audit sink, the version-signing scheme, the commit-validation depth, the authentication mode, TLS, response compression and tenancy. Each item is a closed vocabulary, so an unknown token is refused rather than read as a default.

Posture canaries

A declaration is a promise, so each item is also probed black-box and labelled verified or declared-only, with the exchange behind the label recorded beside it.

ItemHow it is checked
version_signingVersions committed by the run’s OWN seed traffic are read back and their signature inspected. Sampling the measured population means a scheme switched on around a probe never reaches it. The openPGP armor header separates pgp from digest
commit_validationThe pack’s pinned invalid twin (that pack’s own composition with the mandatory COMPOSITION.composer removed) is committed inside the run window, and the answer read
authnOne read with no Authorization header at all, which is the only way to see whether the declared mode is enforced
compressionOne read stating Accept-Encoding explicitly, over a client that does not decompress, so Content-Encoding survives to be read
tlsThe recorded base URL’s own scheme
audit, tenancyDeclared-only. Released ITS-REST surfaces no read resource for either, so the record carries the claim and says it is one

The canaries run before the measured window and again after it. A reading that contradicts the declaration refuses the run, naming the item, the declared value, the observed one and the exchange. So does a pair of brackets that disagree with each other, because a posture that moved mid-run leaves the numbers straddling two systems. Neither is recorded as a footnote beside a published figure.

Baselines run under the profile the target declared and carry their own verified block, so both sides of a ratio disclose what was switched on behind them. bench-compare states a posture disagreement between columns in the header, above the numbers.

Same-machine baselines

--with-baselines anchors the run. After the target’s own measurement, the instrument composes each pinned reference CDR on this host, drives the same pack at the same seed for the same number of repetitions against it, and tears the stack down with its volumes so the next baseline starts from an empty database. The record then carries a baseline block per reference, each a full per-operation summary exactly like the target’s, beside the digest-pinned images, the upstream deployment recipe the topology follows, and the container ceilings both stacks ran under. Every image is pinned by digest rather than by tag, so two submitters measure the same bytes.

The flag needs the docker CLI. On a host where it does not answer the run is refused before the target is touched, with the missing binary named; a run without the flag needs no container runtime at all.

The relative index

An absolute millisecond describes the system and the machine together, so two records taken on different hosts cannot be read against one another. The relative index can. For every phase, operation and metric it is the target’s cross-repetition median divided by the baseline’s, both measured on the same host in the same session, so the machine cancels. On a latency metric a value below 1.0 means the target answered faster than the baseline and above 1.0 slower; on throughput the sense inverts, because there a larger number is the faster system. Each ratio is serialized with the two medians it came from.

Where no ratio can be formed the record says so and why: an operation only one side measured, a phase only one side ran, or a baseline median of zero. A gap is recorded rather than omitted, because a missing row in a comparison reads as agreement.

Submittability

A record is submittable when it carries at least three repetitions, at least one same-machine baseline, and no operation that lost more of its arrivals than the pack’s ceiling allows. That ceiling is part of the versioned pack definition and the record discloses it as pack.max_failed_share; every embedded pack pins 0.01. The check reads every repetition, phase and operation, on the target and on every baseline block, because an index divides by a baseline median and a divisor taken from arrivals that failed describes the failure. A record that misses any requirement stays valid for local exploration and names the ones it misses, in the submittable_unmet list, in the rendered summary and in every bench-compare column header.

The rendered summary carries a failed-arrival table: one row per side, repetition and phase, with the phase’s own share and the worst operation inside it, followed by a sentence per reading above the ceiling naming where it went. The environment fingerprint prints on the summary header and in every comparison column, so no number is read without the machine it came from.

A bench result is a benchmark record for comparative speed. It is not a conformance record, not a certificate, and not a performance-class rating; a bench result may motivate a class run, never substitute for one.

bench-compare

Align two or more committed bench results into one table, one column per file, with every pack or host mismatch stated in the header

Usage: veredictum bench-compare --result <RESULTS> --out <OUT>

Options:
      --result <RESULTS>  A committed bench result. Repeat the flag once per file; at least two are needed
      --out <OUT>         Output directory for the rendered comparison
  -h, --help              Print help

One column per file, one row per phase, operation and metric. Each cell carries the cross-repetition median with the inter-quartile range beside it, so a reader sees the spread as well as the number.

Every column header carries the machine the run was generated on, the worst failed-arrival share the run recorded beside the ceiling its pack pins, and a column that is not submittable names the requirements it misses rather than printing one bare false. Where the columns carry a relative index, it gets its own table below the header, at p50 and p99 per baseline: that is the part which survives a change of host.

A mismatch is stated above the table, never under it: columns that ran different pack versions, columns generated from different hosts, columns that ran at different scale factors or off the pack’s pinned configuration, and columns whose runs are not submittable are all named in the header, and the command exits 1 when any of them applies. Columns from different hosts where at least one carries no relative index are named too, because nothing in that table is comparable across them. Each row also names the discipline its numbers came from.

bench-packs

Write the embedded benchmark pack manifest: every pack's phases with their load discipline, its operation mix with what each entry probes, its posture profiles, its fixture pins with their provenance, its seed, and the submission requirements (byte-deterministic)

Usage: veredictum bench-packs --out <OUT>

Options:
      --out <OUT>  Output directory (created if missing)
  -h, --help       Print help

A pack is versioned data compiled into the binary, so the binary is the only honest source for a description of one. This command writes that description: per pack the id, the version, the seed every arrival stream draws from, the failed-arrival ceiling a record is judged against, each phase with its load discipline and its counts, each measured phase’s operation mix with the share and the probe rationale of every entry, each posture profile the pack defines with what it declares item by item, and each embedded fixture with its sha256 pin, its size and where the bytes came from. The document also carries the boundary statement, the methodology, how a relative index is derived, what the seed and the posture canaries govern, and the requirements a record meets before it may be ranked.

Emission is byte-deterministic and every collection is ordered, so regenerating the file and diffing it is a build gate. The public page at veredictum.eu/benchmark-methodology.html is generated from the committed copy of this document, and CI refuses a pack change that leaves either of them stale.

aql-probe

Run the AQL optimization probe: fire the measurement machinery's AQL vocabulary against a live, freshly seeded SUT, record wire percentiles, and attribute the DB-side cost per probe via `pg_stat_statements` (exploration evidence for the optimization loop — never a conformance record)

Usage: veredictum aql-probe [OPTIONS] --root <ROOT> --ixit <IXIT> --out <OUT>

Options:
      --root <ROOT>                  The artifact root
      --ixit <IXIT>                  The ixit topology file (JSON) — the `containers` block enables DB-side attribution and maintenance settling
      --out <OUT>                    Where to write the probe report (aql-probe.json)
      --corpus-class <CORPUS_CLASS>  The class-scale corpus the probes run against (POC | S | L | R) [default: POC]
      --seed-workers <SEED_WORKERS>  Parallel seeding workers [default: 16]
      --requests <REQUESTS>          Requests fired per probe [default: 20]
  -h, --help                         Print help

Fires the measurement machinery’s AQL vocabulary, records wire percentiles per probe, and attributes the database-side cost through pg_stat_statements. This is evidence for someone optimizing a server, and it is never a conformance record.

stress-compare

Render the cross-SUT stress overlay (both systems' latency-throughput curves on one canvas) FROM two committed stress reports — deterministic, both directions on equal footing

Usage: veredictum stress-compare --left <LEFT> --left-label <LEFT_LABEL> --right <RIGHT> --right-label <RIGHT_LABEL> --out <OUT>

Options:
      --left <LEFT>                The primary SUT's committed stress.json
      --left-label <LEFT_LABEL>    The primary SUT's display label
      --right <RIGHT>              The comparison SUT's committed stress.json
      --right-label <RIGHT_LABEL>  The comparison SUT's display label
      --out <OUT>                  Where to write the overlay SVG
  -h, --help                       Print help

Deterministic, and both directions on equal footing: the two curves are drawn by the same code from the same kind of file, so neither side gets a rendering advantage.

perf-assets

Render the published performance SVG assets FROM a committed results.json (deterministic; CI regenerates and diffs — hand-drawn numbers are a build failure)

Usage: veredictum perf-assets [OPTIONS] --root <ROOT> --results <RESULTS> --out <OUT>

Options:
      --root <ROOT>        The artifact root (for the class-ladder floors)
      --results <RESULTS>  The committed results.json carrying the measurement records
      --out <OUT>          Output directory for the SVG files
      --summary <SUMMARY>  Also write the generated Markdown summary (class ladder + measured detail) to this path — the book's build-time include
      --stress <STRESS>    A committed stress report (stress.json) to render the latency-throughput curve from, when one exists
  -h, --help               Print help

conformance-assets

Render the conformance visuals (the capability heat grid + the per-chapter outcome bars) deterministically FROM the committed party artifacts — the perf-assets pattern for functional conformance

Usage: veredictum conformance-assets [OPTIONS] --root <ROOT> --results <RESULTS> --verdicts <VERDICTS> --out <OUT>

Options:
      --root <ROOT>          The artifact root (for the capability matrix)
      --results <RESULTS>    The committed results.json
      --verdicts <VERDICTS>  The committed verdicts.json
      --out <OUT>            Output directory for the SVG files
      --suffix <SUFFIX>      A suffix appended to the SVG file stems (`-ehrbase` for the comparison SUT's copies) [default: ""]
  -h, --help                 Print help

Both renderers are deterministic over files already committed, so a build job can regenerate them and diff the result. A hand-drawn number in a published chart is a build failure rather than a review comment.

verdicts

Compute the verdicts from a statement + results against an artifact tree (the pure pipeline) and write the rendered submission documents

Usage: veredictum verdicts [OPTIONS] --statement <STATEMENT> --results <RESULTS> --root <ROOT> --out <OUT>

Options:
      --statement <STATEMENT>
          The party statement (`statement.json`)
      --results <RESULTS>
          The party results (`results.json`)
      --root <ROOT>
          The artifact root (schedule/, vocab/, registers/)
      --out <OUT>
          Output directory for the rendered documents + verdicts.json
      --sign-key <SIGN_KEY>
          An armored OpenPGP secret key — when supplied, the rendered documents are sealed with `record-manifest.json` and its detached signature, which `verify-record` and `gpg --verify` both check
      --sign-passphrase <SIGN_PASSPHRASE>
          The passphrase unlocking `--sign-key`. Supply it through the environment: a passphrase on the command line is visible to every process on the host [env: VEREDICTUM_SIGN_PASSPHRASE]
  -h, --help
          Print help

The pure step. It reaches no network and reads nothing but its inputs, which is what makes a published verdict re-derivable by anyone who has the same four files.

replay

Re-judge a recorded run from its transcript, answering every composed request out of the recording instead of a server, and optionally refuse a results document the recorded exchanges do not support

Usage: veredictum replay [OPTIONS] --root <ROOT> --ixit <IXIT> --transcript <TRANSCRIPT>

Options:
      --root <ROOT>              The artifact root (schedule/, bindings/, corpus/, vocab/)
      --ixit <IXIT>              The ixit topology the recorded run was driven under
      --transcript <TRANSCRIPT>  The transcript of that run (`transcript.json`)
      --statement <STATEMENT>    The party statement ISO/IEC 9646 test selection re-applies: it decides which option arm, extension route, claimed capability and release floor the re-judgement selects. Omitting it re-derives a whole-catalogue sweep stamped `selection_basis: statement_blind`, which `--against` refuses to hold against a record an ICS selected
      --filter <FILTER>          Re-judge only cases whose id contains this substring
      --out <OUT>                Where the re-judged `results.json` is written
      --against <AGAINST>        The submitted `results.json` the re-judgement is held against: any row whose status or row counts differ fails the command
      --progress                 Print `progress: <k>/<n> <case>` lines while re-judging
  -h, --help                     Print help

Only the transport changes. The catalogue is driven again through the same request composition, the same response classification and the same assertion evaluators the live run used, with the recorded response standing in for the server’s. A case whose recording runs out, or whose replay composes a request the recording does not carry, records a transport failure: a verdict is never reproduced over evidence nobody has.

With --against, every row is compared on its status and its two row counts, and any disagreement exits 1 naming the case. The reason text is not compared, because a replay reaches a recording rather than a server and identical judgements can carry different words.

Omitting --statement re-derives a sweep of the whole catalogue. The replay says so on stderr, in the words a live run uses, and stamps selection_basis: statement_blind on the document it writes. With --against the selection facts a results.json records are compared before any row is: a record an ICS selected, re-judged blind, under a statement the record does not name, or under one declaring different its-rest formats, exits 2 rather than reporting agreement, because a re-derivation under another claim re-derives another campaign. The statement is named by statement_digest, the leading 8 bytes of the SHA-256 over the declaration’s own bytes, so the refusal prints the recorded value and the applied one and a reader checks either with sha256sum statement.json | cut -c1-16. A record written before selection_basis or statement_digest existed identifies nothing about what selected it, and the replay reports that instead of refusing.

What this establishes is that the judgement follows from the evidence. It does not establish the evidence: a transcript is what the instrument says it sent and received.

evidence

Export a finished run's recorded exchanges for a named set of cases: the triage input, carved out of the run's own transcript. No statement is read, and a bundle that would carry nothing is refused

Usage: veredictum evidence [OPTIONS] --transcript <TRANSCRIPT> --out <OUT> <--failing|--only <ONLY>|--filter <FILTER>>

Options:
      --transcript <TRANSCRIPT>  The run's `transcript.json` (written by `run --record-exchanges`)
      --results <RESULTS>        The run's `results.json`. Required by `--failing`, and otherwise optional: supplying it puts each exported case's outcome row beside its exchanges
      --failing                  Export the red rows the results record names — every `failed` and every `errored` case. The one-command triage input
      --only <ONLY>              Export this case, by id. Repeat the flag once per case
      --filter <FILTER>          Export cases whose id contains this substring
      --out <OUT>                Where the bundle is written
  -h, --help                     Print help

At least one of --failing, --only and --filter is required, and the three union: a case is exported when any of them names it. The unfiltered document is the transcript itself.

The red rows of a run become a triage input in one command:

veredictum evidence --transcript run/transcript.json \
    --results run/results.json --failing --out run/evidence.json

No statement is read. Sealing a record needs a claim; reading the exchanges a run recorded does not, and a run that went red is exactly when they are needed.

An export that would carry nothing is refused, exit 2, with no file written. A selection matching no recorded case names what was asked for and what the transcript actually carries; a selection whose every case recorded no exchange names those cases and says that recording is opt-in. A selection that half-matched still exports, and the bundle’s without_exchanges names every case it could not carry, so a partial answer never reads as a complete one.

The authorization request header’s value is withheld by the export itself, whatever the transcript held. Response bodies are the wire’s own bytes and can carry real patient data, so the bundle is operator-controlled output like the transcript it comes from.

verify-record

Verify a sealed bundle: recompute every digest its record manifest names, and check the detached signature over that manifest

Usage: veredictum verify-record --record <RECORD> --key <KEY>

Options:
      --record <RECORD>  The bundle directory holding the emitted documents, the record manifest and its detached signature
      --key <KEY>        The armored OpenPGP public key the signature is checked against
  -h, --help             Print help

Prints the signer fingerprint, the signing time, and one line per file with its digest verdict. Zero findings is the only passing result: a digest mismatch, a file the manifest names but the bundle does not carry, or a signature no component of the supplied key verifies, each exits 1 naming what failed.

The bundle is ordinary files, so the check does not depend on this tool. gpg --verify record-manifest.json.asc record-manifest.json establishes the same signature, and sha256sum re-derives the same digests.

A verified bundle is one link in the chain and not the whole of it. A valid signature proves integrity and origin since signing, and says nothing about the conditions the run executed under. The published instrument, the verification pack and the citation-carrying record are the rest, which is why that sentence prints on every verification.