T04: deterministic semantic kernel
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
2026-08-22 23:21:07 +02:00
|
|
|
"""The orchestrator: executes a scenario and assembles its evidence.
|
|
|
|
|
|
|
|
|
|
The runner is the only component that sees everything. Actors see their own
|
|
|
|
|
credentials and memory; drivers see mechanics; observers see the system; oracles
|
|
|
|
|
see the observation snapshot. Keeping those views separate is what makes the
|
|
|
|
|
independence claim structural rather than procedural.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import uuid
|
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
from datetime import datetime, timezone
|
|
|
|
|
from typing import Any
|
|
|
|
|
|
|
|
|
|
from .actions import SurfaceNotPermitted
|
|
|
|
|
from .drivers import Driver
|
|
|
|
|
from .energy import EnergyEvent, EnergyEventType
|
|
|
|
|
from .evidence import EvidencePack, Observation, Stratum
|
|
|
|
|
from .observers import StateObserver
|
|
|
|
|
from .oracles import Judgment, Oracle, Verdict, overall
|
|
|
|
|
from .scenario import Scenario, VerificationAsset
|
|
|
|
|
from .world import World
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CollectorIndependenceError(Exception):
|
|
|
|
|
"""An actor was about to be recorded as the collector of S2/S3 evidence."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass(slots=True)
|
|
|
|
|
class RunResult:
|
|
|
|
|
run_id: str
|
|
|
|
|
verdict: Verdict
|
|
|
|
|
judgments: list[Judgment]
|
|
|
|
|
evidence: EvidencePack
|
|
|
|
|
|
|
|
|
|
def judgment(self, assertion_id: str) -> Judgment:
|
|
|
|
|
for j in self.judgments:
|
|
|
|
|
if j.assertion_id == assertion_id:
|
|
|
|
|
return j
|
|
|
|
|
raise KeyError(assertion_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Runner:
|
|
|
|
|
def __init__(
|
|
|
|
|
self,
|
|
|
|
|
world: World,
|
|
|
|
|
driver: Driver,
|
|
|
|
|
observer: StateObserver,
|
|
|
|
|
oracle: Oracle | None = None,
|
|
|
|
|
) -> None:
|
|
|
|
|
self._world = world
|
|
|
|
|
self._driver = driver
|
|
|
|
|
self._observer = observer
|
|
|
|
|
self._oracle = oracle or Oracle()
|
|
|
|
|
|
|
|
|
|
# -- independence guards ---------------------------------------------
|
|
|
|
|
|
2026-08-23 00:39:36 +02:00
|
|
|
def _isolation_violations(self) -> list[str]:
|
|
|
|
|
"""Does any actor hold another's canary?
|
|
|
|
|
|
|
|
|
|
Run on every scenario, not only on ones written to test isolation.
|
|
|
|
|
"""
|
|
|
|
|
canaries = {actor.canary: actor.id for actor in self._world.cast}
|
|
|
|
|
violations: list[str] = []
|
|
|
|
|
for actor in self._world.cast:
|
|
|
|
|
for key in actor.known_keys():
|
|
|
|
|
value = actor.recall(key)
|
|
|
|
|
owner = canaries.get(value) if isinstance(value, str) else None
|
|
|
|
|
if owner is not None and owner != actor.id:
|
|
|
|
|
violations.append(
|
|
|
|
|
f"actor {actor.id!r} holds the private marker of {owner!r} "
|
|
|
|
|
f"under key {key!r}"
|
|
|
|
|
)
|
|
|
|
|
return violations
|
|
|
|
|
|
T04: deterministic semantic kernel
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
2026-08-22 23:21:07 +02:00
|
|
|
def _assert_collector_independence(self, stratum: Stratum, collector: str) -> None:
|
|
|
|
|
"""S2 and S3 evidence may never be attributed to an actor.
|
|
|
|
|
|
|
|
|
|
This is the check that makes oracle independence falsifiable rather than
|
|
|
|
|
merely asserted: wiring an actor in as an observer fails loudly here.
|
|
|
|
|
"""
|
|
|
|
|
if stratum is Stratum.SURFACE:
|
|
|
|
|
return
|
|
|
|
|
if collector in self._world.cast.actors:
|
|
|
|
|
raise CollectorIndependenceError(
|
|
|
|
|
f"{stratum.value} evidence cannot be collected by actor "
|
|
|
|
|
f"{collector!r}; actors do not judge their own outcomes"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def _record(
|
|
|
|
|
self,
|
|
|
|
|
pack: EvidencePack,
|
|
|
|
|
stratum: Stratum,
|
|
|
|
|
collector: str,
|
|
|
|
|
kind: str,
|
|
|
|
|
data: dict[str, Any],
|
|
|
|
|
step_id: str | None,
|
|
|
|
|
) -> None:
|
|
|
|
|
self._assert_collector_independence(stratum, collector)
|
|
|
|
|
pack.record(
|
|
|
|
|
Observation(
|
|
|
|
|
id=f"obs-{len(pack.observations) + 1:04d}",
|
|
|
|
|
stratum=stratum,
|
|
|
|
|
collector=collector,
|
|
|
|
|
step_id=step_id,
|
|
|
|
|
kind=kind,
|
|
|
|
|
data=data,
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# -- execution --------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
def run(self, asset: VerificationAsset) -> RunResult:
|
|
|
|
|
scenario: Scenario = asset.scenario
|
|
|
|
|
run_id = f"run-{uuid.uuid4().hex[:12]}"
|
|
|
|
|
pack = EvidencePack(
|
|
|
|
|
run_id=run_id,
|
|
|
|
|
scenario_id=scenario.id,
|
|
|
|
|
use_case_id=scenario.use_case.id,
|
|
|
|
|
sut_version=self._world.sut_version,
|
|
|
|
|
)
|
|
|
|
|
pack.provenance_index = {
|
|
|
|
|
scenario.use_case.id: scenario.use_case.provenance.value,
|
|
|
|
|
**{c.id: c.provenance.value for c in scenario.use_case.claims},
|
|
|
|
|
**{i.id: i.provenance.value for i in scenario.use_case.invariants},
|
|
|
|
|
}
|
|
|
|
|
pack.energy_events.append(
|
|
|
|
|
EnergyEvent(asset.id, run_id, EnergyEventType.EXECUTED).as_dict()
|
|
|
|
|
)
|
|
|
|
|
|
2026-08-23 00:39:36 +02:00
|
|
|
isolation = self._isolation_violations()
|
|
|
|
|
self._record(
|
|
|
|
|
pack, Stratum.JUDGMENT, self._observer.name, "actor_isolation",
|
|
|
|
|
{"violations": isolation, "actors": sorted(self._world.cast.actors)}, None,
|
|
|
|
|
)
|
|
|
|
|
|
T04: deterministic semantic kernel
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
2026-08-22 23:21:07 +02:00
|
|
|
judgments: list[Judgment] = []
|
T08: the classifier, measured and attacked
False Adaptation Rate = 0/7 across the labelled catalogue and the three E-003
attacks. 11 of 12 mechanical mutations absorbed without a human, so the safety
result is not bought by escalating everything.
- classification.py: total function over three signals, rule order chosen so
every rule that could excuse a regression sits after the rule that reports
one. SAFE_TO_ACCEPT is a two-element closed set, asserted.
- CompositeDriver plus scenarios/full_journey.py: one asset crossing both
surfaces, so UI mutations are visible as surface differences while the
claims they do not touch stay green.
- E-003: surface substitution (new M23), concurrent mechanical+defect,
evidence starvation, provenance laundering. All held.
F-0006 (CONCEPT_DRIFT, resolved): the T02 design listed SEMANTIC_CHANGE as an
outcome the table could produce. It cannot - M12 and M19 are behaviourally
identical, as the lab has asserted since T05. PRODUCT_DEFECT and
SEMANTIC_CHANGE collapse into one escalating outcome, BEHAVIOUR_CHANGED, and
the distinction becomes a human adjudication. INTENT_CHANGED survives but is
detected by the claim fingerprint moving, not inferred from behaviour.
Two classifier defects found and fixed rather than reported: claims downstream
of a failed realization now yield INCONCLUSIVE rather than FAIL (a false
accusation is the mirror image of a false adaptation), and the browser driver
records a page signature so surface change is detectable when the interaction
path is unchanged.
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:02:58 +02:00
|
|
|
scenario_sound = True
|
T04: deterministic semantic kernel
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
2026-08-22 23:21:07 +02:00
|
|
|
claims_by_step: dict[str, list] = {}
|
|
|
|
|
for claim in scenario.use_case.claims:
|
|
|
|
|
claims_by_step.setdefault(claim.after_step, []).append(claim)
|
|
|
|
|
|
|
|
|
|
for step in scenario.steps:
|
|
|
|
|
actor = self._world.cast[step.actor_id]
|
|
|
|
|
|
|
|
|
|
# --- S1: how it was done -------------------------------------
|
|
|
|
|
try:
|
|
|
|
|
realization = self._driver.realize(actor, step.action)
|
|
|
|
|
except SurfaceNotPermitted as exc:
|
|
|
|
|
# D-05: routing around a control is a finding, not a recovery.
|
|
|
|
|
self._record(
|
|
|
|
|
pack, Stratum.REALIZATION, self._observer.name,
|
|
|
|
|
"surface_violation",
|
|
|
|
|
{"step": step.id, "action": step.action.describe(), "error": str(exc)},
|
|
|
|
|
step.id,
|
|
|
|
|
)
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
self._record(
|
|
|
|
|
pack, Stratum.SURFACE, actor.id, "realization",
|
|
|
|
|
{
|
|
|
|
|
"action": step.action.describe(),
|
|
|
|
|
"surface": realization.surface_id,
|
|
|
|
|
"mechanics": realization.mechanics,
|
|
|
|
|
"raised": realization.raised,
|
|
|
|
|
},
|
|
|
|
|
step.id,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# --- S3: what is now true ------------------------------------
|
|
|
|
|
snapshot = self._observer.snapshot()
|
|
|
|
|
self._record(
|
|
|
|
|
pack, Stratum.JUDGMENT, self._observer.name,
|
|
|
|
|
"state_snapshot", dict(snapshot), step.id,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# --- S2: did the action actually take effect ------------------
|
|
|
|
|
refused = realization.raised is not None
|
|
|
|
|
postcondition_met: bool | None = None
|
|
|
|
|
if step.action.postcondition is not None:
|
|
|
|
|
try:
|
|
|
|
|
postcondition_met = step.action.postcondition(snapshot)
|
|
|
|
|
except KeyError:
|
|
|
|
|
postcondition_met = None
|
|
|
|
|
self._record(
|
|
|
|
|
pack, Stratum.REALIZATION, self._observer.name, "realization_check",
|
|
|
|
|
{
|
|
|
|
|
"step": step.id,
|
|
|
|
|
"action": step.action.name,
|
|
|
|
|
"surface_used": realization.surface_id,
|
|
|
|
|
"refused_by_sut": refused,
|
|
|
|
|
"postcondition_met": postcondition_met,
|
|
|
|
|
},
|
|
|
|
|
step.id,
|
|
|
|
|
)
|
|
|
|
|
|
T08: the classifier, measured and attacked
False Adaptation Rate = 0/7 across the labelled catalogue and the three E-003
attacks. 11 of 12 mechanical mutations absorbed without a human, so the safety
result is not bought by escalating everything.
- classification.py: total function over three signals, rule order chosen so
every rule that could excuse a regression sits after the rule that reports
one. SAFE_TO_ACCEPT is a two-element closed set, asserted.
- CompositeDriver plus scenarios/full_journey.py: one asset crossing both
surfaces, so UI mutations are visible as surface differences while the
claims they do not touch stay green.
- E-003: surface substitution (new M23), concurrent mechanical+defect,
evidence starvation, provenance laundering. All held.
F-0006 (CONCEPT_DRIFT, resolved): the T02 design listed SEMANTIC_CHANGE as an
outcome the table could produce. It cannot - M12 and M19 are behaviourally
identical, as the lab has asserted since T05. PRODUCT_DEFECT and
SEMANTIC_CHANGE collapse into one escalating outcome, BEHAVIOUR_CHANGED, and
the distinction becomes a human adjudication. INTENT_CHANGED survives but is
detected by the claim fingerprint moving, not inferred from behaviour.
Two classifier defects found and fixed rather than reported: claims downstream
of a failed realization now yield INCONCLUSIVE rather than FAIL (a false
accusation is the mirror image of a false adaptation), and the browser driver
records a page signature so surface change is detectable when the interaction
path is unchanged.
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:02:58 +02:00
|
|
|
# Only an action that did not *happen* makes the scenario unsound.
|
|
|
|
|
# An action that was accepted but did not take effect did happen —
|
|
|
|
|
# and that is a statement about the system, judged below, not a
|
|
|
|
|
# reason to stop judging.
|
2026-08-23 00:39:36 +02:00
|
|
|
if refused:
|
T08: the classifier, measured and attacked
False Adaptation Rate = 0/7 across the labelled catalogue and the three E-003
attacks. 11 of 12 mechanical mutations absorbed without a human, so the safety
result is not bought by escalating everything.
- classification.py: total function over three signals, rule order chosen so
every rule that could excuse a regression sits after the rule that reports
one. SAFE_TO_ACCEPT is a two-element closed set, asserted.
- CompositeDriver plus scenarios/full_journey.py: one asset crossing both
surfaces, so UI mutations are visible as surface differences while the
claims they do not touch stay green.
- E-003: surface substitution (new M23), concurrent mechanical+defect,
evidence starvation, provenance laundering. All held.
F-0006 (CONCEPT_DRIFT, resolved): the T02 design listed SEMANTIC_CHANGE as an
outcome the table could produce. It cannot - M12 and M19 are behaviourally
identical, as the lab has asserted since T05. PRODUCT_DEFECT and
SEMANTIC_CHANGE collapse into one escalating outcome, BEHAVIOUR_CHANGED, and
the distinction becomes a human adjudication. INTENT_CHANGED survives but is
detected by the claim fingerprint moving, not inferred from behaviour.
Two classifier defects found and fixed rather than reported: claims downstream
of a failed realization now yield INCONCLUSIVE rather than FAIL (a false
accusation is the mirror image of a false adaptation), and the browser driver
records a page signature so surface change is detectable when the interaction
path is unchanged.
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:02:58 +02:00
|
|
|
scenario_sound = False
|
|
|
|
|
|
T04: deterministic semantic kernel
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
2026-08-22 23:21:07 +02:00
|
|
|
# --- invariants after every step -----------------------------
|
T08: the classifier, measured and attacked
False Adaptation Rate = 0/7 across the labelled catalogue and the three E-003
attacks. 11 of 12 mechanical mutations absorbed without a human, so the safety
result is not bought by escalating everything.
- classification.py: total function over three signals, rule order chosen so
every rule that could excuse a regression sits after the rule that reports
one. SAFE_TO_ACCEPT is a two-element closed set, asserted.
- CompositeDriver plus scenarios/full_journey.py: one asset crossing both
surfaces, so UI mutations are visible as surface differences while the
claims they do not touch stay green.
- E-003: surface substitution (new M23), concurrent mechanical+defect,
evidence starvation, provenance laundering. All held.
F-0006 (CONCEPT_DRIFT, resolved): the T02 design listed SEMANTIC_CHANGE as an
outcome the table could produce. It cannot - M12 and M19 are behaviourally
identical, as the lab has asserted since T05. PRODUCT_DEFECT and
SEMANTIC_CHANGE collapse into one escalating outcome, BEHAVIOUR_CHANGED, and
the distinction becomes a human adjudication. INTENT_CHANGED survives but is
detected by the claim fingerprint moving, not inferred from behaviour.
Two classifier defects found and fixed rather than reported: claims downstream
of a failed realization now yield INCONCLUSIVE rather than FAIL (a false
accusation is the mirror image of a false adaptation), and the browser driver
records a page signature so surface change is detectable when the interaction
path is unchanged.
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:02:58 +02:00
|
|
|
# Invariants are judged regardless: they are supposed to hold at all
|
|
|
|
|
# times, however far the scenario got.
|
T04: deterministic semantic kernel
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
2026-08-22 23:21:07 +02:00
|
|
|
for invariant in scenario.use_case.invariants:
|
|
|
|
|
judgments.append(self._oracle.judge(invariant, snapshot, step.id))
|
|
|
|
|
|
|
|
|
|
# --- claims attached to this step ----------------------------
|
T08: the classifier, measured and attacked
False Adaptation Rate = 0/7 across the labelled catalogue and the three E-003
attacks. 11 of 12 mechanical mutations absorbed without a human, so the safety
result is not bought by escalating everything.
- classification.py: total function over three signals, rule order chosen so
every rule that could excuse a regression sits after the rule that reports
one. SAFE_TO_ACCEPT is a two-element closed set, asserted.
- CompositeDriver plus scenarios/full_journey.py: one asset crossing both
surfaces, so UI mutations are visible as surface differences while the
claims they do not touch stay green.
- E-003: surface substitution (new M23), concurrent mechanical+defect,
evidence starvation, provenance laundering. All held.
F-0006 (CONCEPT_DRIFT, resolved): the T02 design listed SEMANTIC_CHANGE as an
outcome the table could produce. It cannot - M12 and M19 are behaviourally
identical, as the lab has asserted since T05. PRODUCT_DEFECT and
SEMANTIC_CHANGE collapse into one escalating outcome, BEHAVIOUR_CHANGED, and
the distinction becomes a human adjudication. INTENT_CHANGED survives but is
detected by the claim fingerprint moving, not inferred from behaviour.
Two classifier defects found and fixed rather than reported: claims downstream
of a failed realization now yield INCONCLUSIVE rather than FAIL (a false
accusation is the mirror image of a false adaptation), and the browser driver
records a page signature so surface change is detectable when the interaction
path is unchanged.
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:02:58 +02:00
|
|
|
# Claims describe the state a *completed* scenario should reach. If a
|
|
|
|
|
# step did not happen, a claim about the state after it is not
|
|
|
|
|
# failing — it is unevaluable. Reporting FAIL there would accuse the
|
|
|
|
|
# system of a defect on the strength of the test's own inability to
|
|
|
|
|
# act, which is the mirror image of a false adaptation and just as
|
|
|
|
|
# dishonest.
|
T04: deterministic semantic kernel
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
2026-08-22 23:21:07 +02:00
|
|
|
for claim in claims_by_step.get(step.id, ()):
|
T08: the classifier, measured and attacked
False Adaptation Rate = 0/7 across the labelled catalogue and the three E-003
attacks. 11 of 12 mechanical mutations absorbed without a human, so the safety
result is not bought by escalating everything.
- classification.py: total function over three signals, rule order chosen so
every rule that could excuse a regression sits after the rule that reports
one. SAFE_TO_ACCEPT is a two-element closed set, asserted.
- CompositeDriver plus scenarios/full_journey.py: one asset crossing both
surfaces, so UI mutations are visible as surface differences while the
claims they do not touch stay green.
- E-003: surface substitution (new M23), concurrent mechanical+defect,
evidence starvation, provenance laundering. All held.
F-0006 (CONCEPT_DRIFT, resolved): the T02 design listed SEMANTIC_CHANGE as an
outcome the table could produce. It cannot - M12 and M19 are behaviourally
identical, as the lab has asserted since T05. PRODUCT_DEFECT and
SEMANTIC_CHANGE collapse into one escalating outcome, BEHAVIOUR_CHANGED, and
the distinction becomes a human adjudication. INTENT_CHANGED survives but is
detected by the claim fingerprint moving, not inferred from behaviour.
Two classifier defects found and fixed rather than reported: claims downstream
of a failed realization now yield INCONCLUSIVE rather than FAIL (a false
accusation is the mirror image of a false adaptation), and the browser driver
records a page signature so surface change is detectable when the interaction
path is unchanged.
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:02:58 +02:00
|
|
|
if scenario_sound:
|
|
|
|
|
judgments.append(self._oracle.judge(claim, snapshot, step.id))
|
|
|
|
|
else:
|
|
|
|
|
judgments.append(Judgment(
|
|
|
|
|
claim.id, claim.text, Verdict.INCONCLUSIVE, step.id,
|
|
|
|
|
{"reason": "an earlier step in this scenario did not complete, "
|
|
|
|
|
"so the state this claim describes was never reached"},
|
|
|
|
|
))
|
T04: deterministic semantic kernel
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
2026-08-22 23:21:07 +02:00
|
|
|
|
|
|
|
|
pack.verdicts = [j.as_dict() for j in judgments]
|
|
|
|
|
pack.finished_at = datetime.now(timezone.utc).isoformat()
|
|
|
|
|
|
|
|
|
|
result_verdict = overall(judgments)
|
|
|
|
|
if result_verdict is Verdict.FAIL:
|
|
|
|
|
pack.energy_events.append(
|
|
|
|
|
EnergyEvent(asset.id, run_id, EnergyEventType.DEFECT_DETECTED).as_dict()
|
|
|
|
|
)
|
|
|
|
|
return RunResult(run_id, result_verdict, judgments, pack)
|