Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/causal-temporal-transition-graph.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Causal-temporal transition graph

on:
pull_request:
paths:
- "scripts/check_causal_temporal_graph.py"
- "conformance/guardrail-decision-v1/causal-temporal/**"
- "docs/CAUSAL_TEMPORAL_TRANSITION_GRAPH.md"
- "docs/CAUSAL_TEMPORAL_TRACE_SEAL.md"
- ".github/workflows/causal-temporal-transition-graph.yml"
push:
branches:
- main
paths:
- "scripts/check_causal_temporal_graph.py"
- "conformance/guardrail-decision-v1/causal-temporal/**"
- "docs/CAUSAL_TEMPORAL_TRANSITION_GRAPH.md"
- "docs/CAUSAL_TEMPORAL_TRACE_SEAL.md"
- ".github/workflows/causal-temporal-transition-graph.yml"

permissions:
contents: read

jobs:
conformance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Validate causal transition vectors
run: |
python3 scripts/check_causal_temporal_graph.py \
conformance/guardrail-decision-v1/causal-temporal/graph.json \
conformance/guardrail-decision-v1/causal-temporal/vectors.json
- name: Validate sealed trace completeness
run: |
python3 scripts/check_causal_temporal_graph.py \
conformance/guardrail-decision-v1/causal-temporal/graph.json \
conformance/guardrail-decision-v1/causal-temporal/sealed-vectors.json
61 changes: 61 additions & 0 deletions conformance/guardrail-decision-v1/causal-temporal/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Causal-temporal transition conformance

This corpus verifies a product-state graph for one immutable subject hash across
three independent axes:

- origin: `UNCOMMITTED → COMMITTED → REPRODUCIBLE`;
- freshness: `UNKNOWN ↔ FRESH ↔ STALE`;
- temporal: `UNANCHORED → PENDING → ANCHORED` with bounded failure states.

The design prevents one fact from overwriting another. A source can be stale
while its historical bytes remain reproducible and temporally anchored.

## Run

```bash
python3 scripts/check_causal_temporal_graph.py \
conformance/guardrail-decision-v1/causal-temporal/graph.json \
conformance/guardrail-decision-v1/causal-temporal/vectors.json

python3 scripts/check_causal_temporal_graph.py \
conformance/guardrail-decision-v1/causal-temporal/graph.json \
conformance/guardrail-decision-v1/causal-temporal/sealed-vectors.json
```

Expected results:

```text
Causal-temporal graph conformance passed: 12
Causal-temporal graph conformance passed: 6
```

## What the unsealed corpus catches

- illegal or undeclared transitions;
- sequence gaps and duplicates;
- broken parent links;
- event-byte mutation;
- subject-hash drift;
- local observation-time regression;
- undeclared mutation of a second state axis;
- missing evidence;
- temporal-anchor success without block/time bounds;
- attempted `ANCHORED → PENDING` rollback.

## What the sealed corpus adds

A trace seal commits to:

```text
subject_hash + total_events + terminal_event_id + sealed_at
```

This catches a silently dropped suffix inside the declared boundary. Without a
seal, a complete-looking prefix cannot prove that no tail was removed.

## Scope

The checker validates the consistency and bounded completeness of recorded
events. It cannot prove that the chosen seal boundary corresponds to every
real-world event that should have happened; boundary governance remains a
separate concern.
157 changes: 157 additions & 0 deletions conformance/guardrail-decision-v1/causal-temporal/graph.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
{
"schema": "proofpath.causal-temporal-graph.v0.1",
"canonicalization": "utf8-json-sort-keys-no-whitespace-v0.1",
"axes": {
"origin": {
"initial": "UNCOMMITTED",
"states": [
"UNCOMMITTED",
"COMMITTED",
"REPRODUCIBLE",
"INVALID"
]
},
"freshness": {
"initial": "UNKNOWN",
"states": [
"UNKNOWN",
"FRESH",
"STALE"
]
},
"temporal": {
"initial": "UNANCHORED",
"states": [
"UNANCHORED",
"PENDING",
"ANCHORED",
"UNAVAILABLE",
"INVALID"
]
}
},
"transitions": [
{
"event_type": "COMMIT_SOURCE_HASH",
"axis": "origin",
"from": [
"UNCOMMITTED"
],
"to": "COMMITTED",
"evidence_required": true
},
{
"event_type": "VERIFY_SOURCE_SNAPSHOT",
"axis": "origin",
"from": [
"COMMITTED"
],
"to": "REPRODUCIBLE",
"evidence_required": true
},
{
"event_type": "INVALIDATE_SOURCE_ORIGIN",
"axis": "origin",
"from": [
"UNCOMMITTED",
"COMMITTED",
"REPRODUCIBLE"
],
"to": "INVALID",
"evidence_required": true
},
{
"event_type": "CHECK_SOURCE_FRESH",
"axis": "freshness",
"from": [
"UNKNOWN",
"FRESH",
"STALE"
],
"to": "FRESH",
"evidence_required": true
},
{
"event_type": "CHECK_SOURCE_STALE",
"axis": "freshness",
"from": [
"UNKNOWN",
"FRESH",
"STALE"
],
"to": "STALE",
"evidence_required": true
},
{
"event_type": "SUBMIT_OTS",
"axis": "temporal",
"from": [
"UNANCHORED",
"UNAVAILABLE"
],
"to": "PENDING",
"evidence_required": true
},
{
"event_type": "VERIFY_OTS_PENDING",
"axis": "temporal",
"from": [
"UNANCHORED",
"PENDING",
"UNAVAILABLE"
],
"to": "PENDING",
"evidence_required": true
},
{
"event_type": "VERIFY_OTS_SUCCESS",
"axis": "temporal",
"from": [
"UNANCHORED",
"PENDING",
"UNAVAILABLE"
],
"to": "ANCHORED",
"evidence_required": true,
"required_fields": [
"temporal_bound.bitcoin_block_height",
"temporal_bound.attested_before"
]
},
{
"event_type": "REVERIFY_OTS_SUCCESS",
"axis": "temporal",
"from": [
"ANCHORED"
],
"to": "ANCHORED",
"evidence_required": true,
"required_fields": [
"temporal_bound.bitcoin_block_height",
"temporal_bound.attested_before"
]
},
{
"event_type": "VERIFY_OTS_UNAVAILABLE",
"axis": "temporal",
"from": [
"UNANCHORED",
"PENDING",
"UNAVAILABLE"
],
"to": "UNAVAILABLE",
"evidence_required": true
},
{
"event_type": "VERIFY_OTS_INVALID",
"axis": "temporal",
"from": [
"UNANCHORED",
"PENDING",
"UNAVAILABLE"
],
"to": "INVALID",
"evidence_required": true
}
]
}
109 changes: 109 additions & 0 deletions conformance/guardrail-decision-v1/causal-temporal/sealed-vectors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
{
"schema": "proofpath.causal-temporal-sealed-vectors.v0.2",
"require_seal": true,
"base_trace": {
"subject_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"events": [
{
"seq": 0,
"parent_event_id": null,
"event_type": "COMMIT_SOURCE_HASH",
"state_before": {"origin":"UNCOMMITTED","freshness":"UNKNOWN","temporal":"UNANCHORED"},
"state_after": {"origin":"COMMITTED","freshness":"UNKNOWN","temporal":"UNANCHORED"},
"subject_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"evidence_ref": "evidence:source-hash",
"observed_at": "2026-07-22T04:00:00Z",
"event_id": "sha256:829330b6c5b60e3774d6c55fe174092ae5ba0406198e93ff8efc17d77fc73962"
},
{
"seq": 1,
"parent_event_id": "sha256:829330b6c5b60e3774d6c55fe174092ae5ba0406198e93ff8efc17d77fc73962",
"event_type": "VERIFY_SOURCE_SNAPSHOT",
"state_before": {"origin":"COMMITTED","freshness":"UNKNOWN","temporal":"UNANCHORED"},
"state_after": {"origin":"REPRODUCIBLE","freshness":"UNKNOWN","temporal":"UNANCHORED"},
"subject_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"evidence_ref": "evidence:snapshot",
"observed_at": "2026-07-22T04:01:00Z",
"event_id": "sha256:f7325b13c1b69f4482ff2f743210e33a3d2c50e6f83fa4993a3a2b764cb680e0"
},
{
"seq": 2,
"parent_event_id": "sha256:f7325b13c1b69f4482ff2f743210e33a3d2c50e6f83fa4993a3a2b764cb680e0",
"event_type": "CHECK_SOURCE_FRESH",
"state_before": {"origin":"REPRODUCIBLE","freshness":"UNKNOWN","temporal":"UNANCHORED"},
"state_after": {"origin":"REPRODUCIBLE","freshness":"FRESH","temporal":"UNANCHORED"},
"subject_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"evidence_ref": "evidence:live-fetch",
"observed_at": "2026-07-22T04:02:00Z",
"event_id": "sha256:cd424af268762cc38b46a9b3bc14ebe51a8c615082847bae9100620c15525065"
},
{
"seq": 3,
"parent_event_id": "sha256:cd424af268762cc38b46a9b3bc14ebe51a8c615082847bae9100620c15525065",
"event_type": "SUBMIT_OTS",
"state_before": {"origin":"REPRODUCIBLE","freshness":"FRESH","temporal":"UNANCHORED"},
"state_after": {"origin":"REPRODUCIBLE","freshness":"FRESH","temporal":"PENDING"},
"subject_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"evidence_ref": "evidence:ots-proof-pending",
"observed_at": "2026-07-22T04:03:00Z",
"event_id": "sha256:5110d0131c3fe5eea49865ea467ed229c48f75763c5e50c1c6776db6d5cb7a18"
},
{
"seq": 4,
"parent_event_id": "sha256:5110d0131c3fe5eea49865ea467ed229c48f75763c5e50c1c6776db6d5cb7a18",
"event_type": "VERIFY_OTS_SUCCESS",
"state_before": {"origin":"REPRODUCIBLE","freshness":"FRESH","temporal":"PENDING"},
"state_after": {"origin":"REPRODUCIBLE","freshness":"FRESH","temporal":"ANCHORED"},
"subject_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"evidence_ref": "evidence:ots-verification",
"observed_at": "2026-07-22T05:00:00Z",
"temporal_bound": {"kind":"not_later_than","bitcoin_block_height":900001,"attested_before":"2026-07-22T04:55:00Z"},
"event_id": "sha256:d2db1fff41daa5b2656e72d0be097963d23085347059287b7fc2a43a5d58c8e8"
}
],
"seal": {
"subject_hash": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"total_events": 5,
"terminal_event_id": "sha256:d2db1fff41daa5b2656e72d0be097963d23085347059287b7fc2a43a5d58c8e8",
"sealed_at": "2026-07-22T05:01:00Z",
"seal_id": "sha256:cc765068061e280cf3ae88fef87b655d48ed2a8ee9523daa18cccb446780d5d5"
}
},
"cases": [
{
"name": "valid-sealed-trace",
"expected": {"ok":true,"error":null,"event_count":5}
},
{
"name": "reject-dropped-tail-against-seal",
"mutations": [{"op":"truncate_events","count":4}],
"expected": {"ok":false,"error":"TRACE_TOTAL_MISMATCH"}
},
{
"name": "reject-missing-trace-seal",
"mutations": [{"op":"delete","path":"seal"}],
"expected": {"ok":false,"error":"TRACE_SEAL_MISSING"}
},
{
"name": "reject-tampered-seal-id",
"mutations": [{"op":"set","path":"seal.seal_id","value":"sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}],
"expected": {"ok":false,"error":"TRACE_SEAL_ID_MISMATCH"}
},
{
"name": "reject-terminal-event-mismatch",
"mutations": [
{"op":"set","path":"seal.terminal_event_id","value":"sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
{"op":"recompute_seal_id"}
],
"expected": {"ok":false,"error":"TRACE_TERMINAL_EVENT_MISMATCH"}
},
{
"name": "reject-sealed-at-regression",
"mutations": [
{"op":"set","path":"seal.sealed_at","value":"2026-07-22T04:59:00Z"},
{"op":"recompute_seal_id"}
],
"expected": {"ok":false,"error":"SEALED_AT_REGRESSION"}
}
]
}
Loading
Loading