# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference) # Canonical Residual: https://corpusfetch.com/c/what-invariants-prevent-delayed-feedback-from-being-misinterpreted-as-independent-events.md # Remnant Warrant: https://corpusfetch.com/c/what-invariants-prevent-delayed-feedback-from-being-misinterpreted-as-independent-events.warrant.json # Markdown SHA-256: b7f3e33791c6ab8a55295f424838a43c2b037cdc3572c24b32b16d722ae0cc88 # Code AST SHA-256: 20edfdfae1e64a4858f04f12a7b7a9f782d2eb6c763d60ff3db7409747d91f20 # Verified Classes: DelayedAttributionVerdict, DelayedAction, ObservedEffect, AttributionState, AttributionPolicy, AttributionManifest, DelayedFeedbackGuard # Defensive Guards: 0 fail-closed invariants (zero external deps) from dataclasses import dataclass from enum import Enum, auto import hashlib import json class DelayedAttributionVerdict(Enum): IMMEDIATE_EFFECT = auto() ATTRIBUTION_VERIFIED = auto() CONFOUNDER_DETECTED = auto() ATTRIBUTION_AMBIGUOUS = auto() @dataclass(frozen=True) class DelayedAction: action_id: str action_epoch: float expected_effect_epoch: float effect_window_sec: float @dataclass(frozen=True) class ObservedEffect: effect_id: str observed_epoch: float effect_description: str candidate_causes: tuple[str, ...] # action_ids or "EXTERNAL" @dataclass(frozen=True) class AttributionState: action: DelayedAction effect: ObservedEffect intervening_events_documented: bool confounders_identified: bool @dataclass(frozen=True) class AttributionPolicy: require_confounder_analysis_for_medium_plus: bool is_medium_plus_stakes: bool @dataclass(frozen=True) class AttributionManifest: verdict: DelayedAttributionVerdict attributed_to: str | None directive: str manifest_digest: str class DelayedFeedbackGuard: @staticmethod def _hash(data: str) -> str: return hashlib.sha256(data.encode("utf-8")).hexdigest() @classmethod def evaluate_attribution( cls, state: AttributionState, policy: AttributionPolicy ) -> AttributionManifest: # Gate 1: Immediate effect if state.effect.observed_epoch <= state.action.action_epoch + state.action.effect_window_sec: digest = cls._hash(json.dumps({ "action": state.action.action_id, "effect": state.effect.effect_id }, sort_keys=True)) return AttributionManifest( verdict=DelayedAttributionVerdict.IMMEDIATE_EFFECT, attributed_to=state.action.action_id, directive=f"PROCEED: Effect {state.effect.effect_id} within immediate window.", manifest_digest=digest ) # Gate 2: Confounder requirement if policy.is_medium_plus_stakes and policy.require_confounder_analysis_for_medium_plus: if not state.confounders_identified: return AttributionManifest( verdict=DelayedAttributionVerdict.ATTRIBUTION_AMBIGUOUS, attributed_to=None, directive=f"HALT: Medium-plus stakes effect {state.effect.effect_id} requires confounder analysis.", manifest_digest=cls._hash(f"NO_CONFOUNDER_ANALYSIS:{state.effect.effect_id}") ) # Gate 3: Single candidate cause if len(state.effect.candidate_causes) == 1: digest = cls._hash(json.dumps({ "action": state.action.action_id, "effect": state.effect.effect_id, "cause": state.effect.candidate_causes[0] }, sort_keys=True)) return AttributionManifest( verdict=DelayedAttributionVerdict.ATTRIBUTION_VERIFIED, attributed_to=state.effect.candidate_causes[0], directive=f"PROCEED: Effect {state.effect.effect_id} attributed to {state.effect.candidate_causes[0]}.", manifest_digest=digest ) # Gate 4: Multiple candidates if state.action.action_id in state.effect.candidate_causes: return AttributionManifest( verdict=DelayedAttributionVerdict.CONFOUNDER_DETECTED, attributed_to=None, directive=f"HALT: Multiple candidate causes {state.effect.candidate_causes}, cannot attribute unambiguously.", manifest_digest=cls._hash(f"CONFOUNDED:{state.effect.effect_id}") ) # Gate 5: Not our effect digest = cls._hash(json.dumps({ "action": state.action.action_id, "effect": state.effect.effect_id, "candidates": state.effect.candidate_causes }, sort_keys=True)) return AttributionManifest( verdict=DelayedAttributionVerdict.ATTRIBUTION_AMBIGUOUS, attributed_to=None, directive=f"PROCEED: Effect {state.effect.effect_id} not attributable to {state.action.action_id}.", manifest_digest=digest )