# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference) # Canonical Residual: https://corpusfetch.com/c/how-must-an-instance-preserve-causal-links-between-actions-and-outcomes.md # Remnant Warrant: https://corpusfetch.com/c/how-must-an-instance-preserve-causal-links-between-actions-and-outcomes.warrant.json # Markdown SHA-256: 33230b62a28d31ce97bbc00a8264c8c29c0f35f52960bd67a756db43773138cc # Code AST SHA-256: 8ab88e41ca9e6c03dba7857b4472d7b60dc9c23e234358c1d280fa6eb3d7c9b3 # Verified Classes: DispatchedActionRecord, ObservedOutcomeEnvelope, CausalLinkageViolation, CausalProvenanceGate # Defensive Guards: 4 fail-closed invariants (zero external deps) from dataclasses import dataclass from typing import Final, FrozenSet import hashlib @dataclass(frozen=True) class DispatchedActionRecord: action_id: str target_resource: str pre_state_sha256: str logical_clock: int declared_scope: FrozenSet[str] @dataclass(frozen=True) class ObservedOutcomeEnvelope: correlation_action_id: str target_resource: str observed_parent_sha256: str post_state_sha256: str outcome_logical_clock: int mutated_paths: FrozenSet[str] class CausalLinkageViolation(Exception): """Raised when an observed outcome cannot be causally bound to the dispatched action.""" pass class CausalProvenanceGate: def verify_causal_link( self, action: DispatchedActionRecord, outcome: ObservedOutcomeEnvelope, ) -> str: # 1. Enforce explicit action-to-outcome correlation ID binding if outcome.correlation_action_id != action.action_id: raise CausalLinkageViolation( f"Correlation mismatch: expected {action.action_id}, got {outcome.correlation_action_id}" ) # 2. Enforce Lamport logical clock monotonicity (effect cannot precede or equal cause) if outcome.outcome_logical_clock <= action.logical_clock: raise CausalLinkageViolation( f"Causal clock inversion: outcome ({outcome.outcome_logical_clock}) <= action ({action.logical_clock})" ) # 3. Enforce unbroken state lineage (no unrecorded external mutation between dispatch and effect) if outcome.observed_parent_sha256 != action.pre_state_sha256: raise CausalLinkageViolation( "State lineage broken: concurrent external mutation intervened before outcome." ) # 4. Enforce causal scope containment if not outcome.mutated_paths.issubset(action.declared_scope): raise CausalLinkageViolation( "Out-of-scope side effect detected; refusing direct causal attribution." ) causal_edge = f"{action.action_id}:{action.pre_state_sha256}->{outcome.post_state_sha256}" return hashlib.sha256(causal_edge.encode("utf-8")).hexdigest()