agent-evidence-vectors v0.37.0

Evidence-state vectors

Cases for evidence-state/v1: one record declares where the evidence about one system stands, as one of nine codes from the vocabulary term evidence_state, beside the observations that ground it. The reader derives the code from the observations and refuses a declared code that differs. The headline case is a recurring misreading in incident records: a silence declared clean (ES1) over monitors whose coverage nobody measured (ES0).

Code Observable entry condition
ES0 No anomaly recorded; monitor coverage not measured
ES1 No anomaly recorded; coverage measured
ES2 At least one anomaly recorded; no declared change-detection threshold crossed
ES3 Recorded anomalies past a declared change-detection threshold
ES4 Propagation observed; pathway not identified
ES5 Pathway identified; scope not yet bounded with containment verified
ES6 Scope bounded; containment verified
ES7 Effects confirmed outside the organisation
ES8 Containment recorded; restart requested

A record's state is the highest code whose entry condition its observations meet.

Checked with Probity

For anyone who writes incident, monitoring or restart records and wants CI to refuse a declared state its own observations do not support.

pip install agent-evidence-vectors
python -m agent_evidence_vectors.evidencestate your-record.json --json
agent-evidence-vectors --corpus vectors-evidence-state
python3 corpora/vectors-evidence-state/check_vectors.py --verifier './verifier'

The second line judges your own records, one JSON line each with decision, reason and derivedState; it exits 1 when any record is denied. The third replays this corpus through the packaged reader, the fourth through your verifier. A verifier takes record.json --json, prints {"decision": ..., "reason": ...} and exits 0 for allow, 1 for deny.

The record

{
  "assessedAt": "2026-11-02T09:00:00Z",
  "contractId": "https://probityai.github.io/agent-evidence-vectors/predicate/v1/evidence-state",
  "evidenceState": "ES1",
  "observations": {
    "anomaliesRecorded": 0, "changeThreshold": 5, "containmentRecorded": false,
    "containmentVerified": false, "coverageMeasured": true,
    "externalEffectsConfirmed": false, "pathwayIdentified": false,
    "propagationObserved": false, "restartRequested": false, "scopeBounded": false
  },
  "recordId": "record-1",
  "system": "agent-system-1"
}

changeThreshold is a count of at least one, or null when none is declared.

What the cases force

The reader applies eight checks in order and names the first that fails: contract_id_missing, contract_id_unknown, record_malformed, evidence_state_unregistered, observations_inconsistent (a pathway with no observed propagation, propagation beside no anomaly, containment verified but never recorded), clean_without_coverage, evidence_state_unsupported (a code higher than the observations reach) and evidence_state_understated (a code lower than they reach). Each denied case fails exactly its named check, and every code from ES0 to ES8 has an accepting control. Counts are in MANIFEST.json.

Synthetic, and labelled so

Every member is synthetic. Systems are fixed labels, and no member records a real system or incident. The manifest says so in synthetic.

What it does not test

Whether the observations are true, which response a state calls for, or whether a restart should be admitted. The code says what was observed; a relying party decides what to do with it. Regenerate with python3 corpora/vectors-evidence-state/gen_vectors.py.

Record format: draft-gilda-audit-agent-audit-record-03, Section 4 (an in-toto Statement carried in a DSSE envelope).