Skip to content

Invariants

Invariants are declared in YAML under invariants/, a path protected by CODEOWNERS. load_invariants("invariants") loads every *.yaml and *.yml file in the directory and rejects duplicate ids. Each invariant has an id, a version, a kind, params, and required_signals, which are event kinds that must be present for a verdict. When a required signal is absent, the result is UNKNOWN. For the model behind them, see Concepts: Invariants.

A scenario names the invariants it checks by default under invariants:. Adding a file doesn't change what an existing scenario evaluates. To change what an invariant means, bump its version. The kernel records invariant_version with every verdict it recomputes.

Generated

The tables below are generated by scripts/build_docs.py from invariants/*.yaml.

invariants/core.yaml

Id Kind Version Required signals What it checks
epistemic.no_future_knowledge epistemic 1.0 none Information-state separation. No role view holds an event received before its event_time_ns, and no decision cites a known_event_id that its actor's role had not received by at_ns. FAIL witness: offending view event ids, then each offending decision id followed by the ids it cited prematurely.
epistemic.label_isolation epistemic 1.0 none Role coast_guard never receives an event carrying policy label harbour_private. FAIL witness: the labelled event ids present in that role's view.
response.alert_ack response 1.0 alert G(alert -> F<=within_ns acknowledged) inside the harbour_ops view: every received alert is followed, within within_ns of its receipt, by an ack whose payload.acks is the alert id. FAIL witness: [alert id, latest event the role received before the deadline].
absence.no_corrupted_in_decision absence 1.0 decision No decision's known_event_ids includes a corrupted event (quality == 0.0 or provenance that cites the event itself, the marker set by interventions.corrupt). FAIL witness: [decision id, corrupted event id].
decision.consistent_with_truth decision 1.0 decision Each recorded decision equals the option its rule yields when evaluated over truth as of at_ns. A mismatch means stale or missing information caused a wrong decision. FAIL witness: truth events at or before at_ns that the actor's role had not received at at_ns, in canonical order. UNKNOWN (decision_rule_evaluator) when no scenario or evaluate_rule callable is supplied.
always.non_negative_capacity always 1.0 none State predicate over truth: no truth event reports payload.capacity below zero. UNKNOWN when no truth event carries payload.capacity. FAIL witness: the first offending truth event.

invariants/extended.yaml

Id Kind Version Required signals What it checks
latency.bound latency 1.0 none Every correction reaches harbour_ops within bound_ns of its event_time (received_time_ns - event_time_ns <= bound_ns). FAIL witness: every offending event id in canonical order. UNKNOWN when the role has no view or never received that kind.
ordering.causal ordering 1.0 none If event B references event A through a payload link field (corrects, acks, acknowledges, in_reply_to), every role receives A (or a copy of A) no later than B. Checked in every role view. FAIL witness: [A, B] for the first violation in receipt order. UNKNOWN when no view event carries a link field that resolves to a truth event.
duplicate.suppressed duplicate 1.0 none No decision's known_event_ids contains two copies of the same origin event (origin = id before '#dup', else the first provenance id, else the id). This is the duplicate-delivery mechanism random exploration found on port_alert. FAIL witness: [decision id, copy ids...] for the first duplicated origin. UNKNOWN when the trace has no decisions.
quorum.independent_sources quorum 1.0 none A duty_officer escalate rests on at least two distinct source_ids among the known, uncorrected sightings with confidence >= 0.6. FAIL witness: [decision id, supporting event ids...]; the explanation names the distinct sources counted. PASS when no decision chose the option. UNKNOWN when the trace has no matching decisions.
decision.fault_attributed decision 1.0 decision Same verdict as decision.consistent_with_truth. With a reference trace (check(..., reference=root_trace)) the FAIL witness is only the truth events missing at decision time in this trace but received in the reference: the information the fault took away. Without a reference the witness lists all missing information and the explanation says so. UNKNOWN (decision_rule_evaluator) when no evaluator is supplied.
epistemic.permitted_only epistemic 1.0 none Approximation of non-interference: no decision's known_event_ids includes an event whose policy_labels its actor's role may not see under the scenario's role visibility. FAIL witness: [decision id, offending event ids...]. UNKNOWN (scenario) without a scenario, (decision) without decisions, or (role:/event:) when a role or cited event cannot be resolved.

Parameters, witnesses and worked examples for each invariant are in the Invariant catalogue.

File shape

invariants:
  - id: response.alert_ack
    version: "1.0"
    kind: response
    description: >
      G(alert -> F<=within_ns acknowledged) inside the harbour_ops view ...
    params:
      role: harbour_ops
      trigger_kind: alert
      response_kind: ack
      within_ns: 300000000000
      link_field: acknowledges
    required_signals: [alert]

Verdict record

Each check returns a VerdictRecord with these fields: invariant_id, invariant_version, result (PASS, FAIL, or UNKNOWN), witness[], explanation, missing_data[], derived_at_ns (evaluator time, separate from event time), and trace_digest. The CLI writes them to verdicts/<trace>.json.