Command line
--registry, --lineage-peer and --profile reach rules that exist only under --schema 1.1-draft; they are accepted and inert otherwise. --spaces and --registry take different documents and each has its own loader: --spaces takes a registry of embedding space descriptors (VER402), --registry takes a VER Registry snapshot of governed value-space tokens (VER1205).
Exit codes. 0 every record is conformant · 1 at least one record has an error-severity issue · 2 the invocation was wrong (bad option, unreadable file, unloadable key, missing standards tree). Warnings never change the exit code: a record that only warns is conformant. An indeterminate run (VER001: a rule crashed) exits 1, because the run did not establish conformance — read status, not the exit code, to tell "this record is wrong" from "this validator could not say".
A bad invocation is never charged to a record. A --signature-key that cannot be parsed exits 2 with a message about the key — it is not reported as a failed signature, because "I could not attempt the check" and "this record was modified after signing" are findings about different parties. Same for an unrecognized --ignore code and an unknown level=.
A batch is not all-or-nothing. One unreadable file does not discard the reports already computed: every readable file is validated and printed, each unreadable one is listed (NOT VALIDATED, and on stderr), and the run exits 2 because the invocation named something that is not there. A CI sweep over a directory that loses all its output to one stale path is useless.
--ignore moves the exit code, never the verdict. Suppression is a deployment policy — "this fleet tolerates VER404 until Q4" — and a deployment does not get to decide what the standard says. So the report keeps its unfiltered issues, ok and status, records the policy beside them as ignored_codes and ok_after_policy_exceptions, and prints both answers; only the exit code follows the filtered one, because moving the exit code is the whole reason the flag exists. An unregistered code is a usage error, not a silent no-op.
An earlier version deleted the suppressed findings and recomputed ok. That made the report indistinguishable from one for a record with no such defect: the echo lived only in the CLI's own text, so a JSON report saved to an artifact store or piped onward travelled claiming the standard had cleared a record it had not. --ignore VER001 is the sharpest case — it buys an exit code and nothing else, because status keeps saying indeterminate.
--format json contract
Every key except unreadable is always present. The top-level ok, status, ok_after_policy_exceptions and ignored_codes aggregate the per-record reports, which carry the same four fields individually. A file in unreadable makes the aggregate status indeterminate and the run exit 2: nothing was established about it, so a batch verdict of "conformant" would be reporting on a smaller set of records than the invocation named. The exit code follows ok_after_policy_exceptions when it is not null, and ok otherwise.
