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
This commit is contained in:
tegwick 2026-08-23 00:39:36 +02:00
parent 4f4219d8f7
commit 1b9860a8ee
40 changed files with 1074 additions and 46 deletions

View file

@ -194,3 +194,98 @@ def test_safe_to_accept_is_a_closed_set():
assert SAFE_TO_ACCEPT == {
Classification.UNCHANGED, Classification.MECHANICAL_ADAPTATION,
}
# --- classifications that no lab mutation happens to produce ---------------
#
# Two outcomes were declared at T08 and exercised by nothing. Left that way they
# are decoration: code that has never run is code nobody has checked. Rather than
# delete meaningful outcomes or trust them untested, both are given a case.
def test_intent_change_is_detected_when_the_claim_set_moves(baseline):
"""`INTENT_CHANGED` is a fact about the recorded use case, not an inference.
It fires because a human edited what is being asserted which is why it is
detectable at all, where `SEMANTIC_CHANGE` was not (F-0006).
"""
import copy
altered = copy.deepcopy(baseline)
altered["provenance_index"]["c-newly-added-claim"] = "human"
outcome = classify(baseline, altered)
assert outcome.classification is Classification.INTENT_CHANGED
assert not outcome.safe_to_accept
def test_realization_failure_is_distinguishable_from_ambiguity():
"""`REALIZATION_FAILED` says "we could not act"; `AMBIGUOUS` says "we do not know".
Every lab mutation that breaks realization also strands a claim, so the
catalogue only ever produces `AMBIGUOUS`. This builds the case the catalogue
cannot: a step that fails while every assertion in the run still holds and
none of them depended on it.
Note that a run asserting *nothing at all* is `AMBIGUOUS`, not
`REALIZATION_FAILED` a use case with no claims cannot conclude anything,
however well its steps ran.
"""
from testdriver import (
Actor, Cast, Invariant, Oracle, Runner, Scenario, SemanticAction,
StateObserver, Step, UseCase, VerificationAsset, World,
)
from testdriver.agentic import DiscoveryRuntime
from testdriver.browser import BrowserDriver
from testdriver.observers import Watch
from testdriver.provenance import Provenance
from lab.mutations import ObservationChannel
use_case = UseCase(
"uc-audit-only", "Sharing leaves an ordered audit trail",
"Alice shares R with Bob; the audit trail stays ordered.",
Provenance.HUMAN,
invariants=(Invariant(
"i-audit-ordered", "The audit trail is append-only", Provenance.HUMAN,
lambda obs: [e["sequence"] for e in obs["audit:R"]]
== sorted(e["sequence"] for e in obs["audit:R"]),
),),
)
def run(*mutations):
with journey_lab_server(*mutations) as (app, tokens, base_url):
app.request(tokens["alice"], "create_resource",
resource_id="R", content="x")
cast = Cast()
cast.add(Actor("alice", "Alice", credentials={"token": tokens["alice"]}))
scenario = Scenario(
"sc-audit-only", use_case,
watches=(Watch("bob", "R"),),
steps=(Step("s1", "alice", SemanticAction(
"grant_access", {"subject_id": "bob", "permission": "READ"},
permitted_surfaces=frozenset({"browser"}),
)),),
)
driver = BrowserDriver(base_url, tokens, DiscoveryRuntime(), "R")
observer = StateObserver(ObservationChannel(app), scenario.watches)
world = World("w-audit", app, app.version, cast=cast)
return json.loads(
Runner(world, driver, observer, Oracle())
.run(VerificationAsset("va-audit-only", scenario))
.evidence.to_json()
)
outcome = classify(run(), run("M23")) # the control is gone from the UI
assert outcome.classification is Classification.REALIZATION_FAILED
assert not outcome.safe_to_accept
def test_no_classification_is_unreachable():
"""Every declared outcome must be produced somewhere in this suite.
An outcome nothing can emit is the same kind of dead promise `SUSPICIOUS`
was before T10 removed it.
"""
exercised = set(EXPECTED.values()) | {
Classification.INTENT_CHANGED, Classification.REALIZATION_FAILED,
}
assert exercised == set(Classification)