Alice/Bob/Carol runs end to end, deterministically, replayable from seed. 16 tests pass, no third-party dependencies. - src/testdriver: intent, provenance, world, actions, drivers, observers, oracles, evidence, energy, scenario, runner - lab/minimal.py: the SUT, exposing the independent observation channel required by D-07 - evidence is stratified S1/S2/S3; Runner refuses to attribute S2/S3 to an actor; claims are frozen and provenance-checked at construction - missing evidence yields INCONCLUSIVE, which outranks PASS in the run verdict - EnergyEvents captured, no scoring (H-005 dormant) The observation channel records both stored state and an out-of-band enforcement probe; their disagreement is an invariant and is what detects an authorization defect that leaves the audit trail intact. A seeded RevokeIsCosmetic lab fails the run via both the claim and that invariant. Also closes TD-WP-0001-T02 (stack and commands now exist). 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
76 lines
2.5 KiB
Python
76 lines
2.5 KiB
Python
"""Drivers realize semantic actions against a surface.
|
|
|
|
A driver knows mechanics. It emits S1 evidence describing *how* it acted and
|
|
reports which surface it used, but it never reports whether the action was
|
|
correct — that is S2/S3 and belongs to the observer and the oracle.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Any, Protocol
|
|
|
|
from .actions import SemanticAction, Surface
|
|
from .world import Actor
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class Realization:
|
|
"""What a driver did, mechanically. Pure S1."""
|
|
|
|
surface_id: str
|
|
mechanics: dict[str, Any]
|
|
raised: str | None = None
|
|
|
|
|
|
class Driver(Protocol):
|
|
surface: Surface
|
|
|
|
def realize(self, actor: Actor, action: SemanticAction) -> Realization: ...
|
|
|
|
|
|
class UnsupportedAction(Exception):
|
|
"""The driver has no mechanical implementation for this semantic action."""
|
|
|
|
|
|
class DirectDriver:
|
|
"""Deterministic driver against the lab's enforcement path.
|
|
|
|
This is the T5 Deterministic end of the maturity continuum: a fixed mapping
|
|
from semantic action to mechanics, with no discovery and no model.
|
|
"""
|
|
|
|
def __init__(self, lab: Any, tokens: dict[str, str]) -> None:
|
|
self._lab = lab
|
|
self._tokens = tokens
|
|
self.surface = Surface(
|
|
id="api", kind="http-like", description="lab enforcement path"
|
|
)
|
|
|
|
_MAPPING = {
|
|
"create_resource": ("create_resource", ("resource_id", "content")),
|
|
"grant_access": ("grant", ("resource_id", "subject_id", "permission")),
|
|
"revoke_access": ("revoke", ("resource_id", "subject_id")),
|
|
"read_resource": ("read_resource", ("resource_id",)),
|
|
}
|
|
|
|
def realize(self, actor: Actor, action: SemanticAction) -> Realization:
|
|
if action.name not in self._MAPPING:
|
|
raise UnsupportedAction(action.name)
|
|
action.check_surface(self.surface.id)
|
|
|
|
op, arg_names = self._MAPPING[action.name]
|
|
args = {name: action.args[name] for name in arg_names if name in action.args}
|
|
token = self._tokens[actor.id]
|
|
|
|
mechanics: dict[str, Any] = {
|
|
"operation": op,
|
|
"arguments": args,
|
|
"actor": actor.id,
|
|
}
|
|
try:
|
|
result = self._lab.request(token, op, **args)
|
|
except Exception as exc: # the SUT refusing is data, not a framework error
|
|
return Realization(self.surface.id, mechanics, raised=f"{type(exc).__name__}: {exc}")
|
|
mechanics["result"] = result
|
|
return Realization(self.surface.id, mechanics)
|