test-driver/src/testdriver/evidence.py
tegwick 1b9860a8ee T10: gate review and first compression pass
All four gate criteria met. False Adaptation Rate 0/7 with 12 of 13 mechanical
mutations absorbed. 178 tests pass. TD-WP-0002 finished.

Fitness loop closed via F-0003: actor isolation was a property of scenarios
written to expose it, not of runs. Actors now carry an automatic private
marker and the runner examines all of them on every scenario, with two
permanent regressions behind it.

Compression - six abstractions removed, each declared and never used:
Verdict.SUSPICIOUS (a verdict no oracle could emit), Step.expect_refusal,
ActorIsolationError, World.seed, EvidencePack.latest, Trajectory.method.

F-0008: Temperature may be redundant. Crystallization was built without it
ever being consulted; measured stability of realization did the work, and is
observed rather than declared. Gated for removal alongside energy.py.

INTENT_CHANGED and REALIZATION_FAILED had never run. Both now have
purpose-built cases and a test that fails if a seventh outcome is added
without one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1629012@bnt-lap001
Assistant-Session: 78d4fb13-8a1e-474b-87a3-9b9261c49a39
2026-08-23 00:39:36 +02:00

80 lines
2.4 KiB
Python

"""Stratified evidence — decision D-01.
S1 Surface how an action was performed (selectors, routes, payloads)
S2 Realization whether it happened, and through which surface
S3 Judgment whether that was correct
Each stratum has a different authority. Models may write S1. Nothing but an
independent Observer writes S2 or S3.
See docs/TestDriverClassificationDesign.md, Part A.
"""
from __future__ import annotations
import json
from dataclasses import dataclass, field, asdict
from datetime import datetime, timezone
from enum import Enum
from typing import Any
class Stratum(str, Enum):
SURFACE = "S1"
REALIZATION = "S2"
JUDGMENT = "S3"
def _now() -> str:
return datetime.now(timezone.utc).isoformat()
@dataclass(frozen=True, slots=True)
class Observation:
"""One recorded fact, attributed to a stratum and a collector.
`collector` is never an actor for S2/S3 observations. The runner enforces
this; see runner._assert_collector_independence.
"""
id: str
stratum: Stratum
collector: str
step_id: str | None
kind: str
data: dict[str, Any]
at: str = field(default_factory=_now)
@dataclass(slots=True)
class EvidencePack:
"""Everything retained from one run.
The pack must be sufficient to replay the run and to diagnose a finding
without the original process. An assertion that cannot be supported from the
pack is an EVIDENCE_FAILURE, not a defect in the system under test.
"""
run_id: str
scenario_id: str
use_case_id: str
sut_version: str
started_at: str = field(default_factory=_now)
finished_at: str | None = None
observations: list[Observation] = field(default_factory=list)
verdicts: list[dict[str, Any]] = field(default_factory=list)
energy_events: list[dict[str, Any]] = field(default_factory=list)
provenance_index: dict[str, str] = field(default_factory=dict)
def record(self, observation: Observation) -> None:
self.observations.append(observation)
def of_stratum(self, stratum: Stratum) -> list[Observation]:
return [o for o in self.observations if o.stratum is stratum]
def to_json(self) -> str:
payload = asdict(self)
payload["observations"] = [
{**asdict(o), "stratum": o.stratum.value} for o in self.observations
]
return json.dumps(payload, indent=2, sort_keys=True, default=str)