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.
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).