DemoCommand Protocol + thin adapters retrofit shipped tours to a
typed composition contract. Composability becomes a structural
property: the ADR-0099 showcase will consume DemoResult through one
stable type rather than special-casing each tour. No demo behavior
changes — adapters wrap underlying run_tour() entry points.
- new core/demos/ package:
- contract.py: frozen Claim / DemoResult dataclasses, runtime-checkable
DemoCommand Protocol, canonical_json() sanctioned serializer
(sorted keys, 2-space indent, trailing newline), CLAIM_CONTRACT_VERSION
- audit_tour_adapter.py: AuditTourDemo (5 claims from ADR-0042 scenes
1-4: identity_pack_swaps_visible, safety_typed_refusal,
ethics_opt_in_deployment_fires, ethics_default_silent,
replay_byte_identical)
- tour_adapters.py: shared pattern for register/anchor-lens/orthogonality
tours; _extract_claims walks the dict tree for *_supported booleans
and builds Claim objects in deterministic sorted order
- global-state-mutation detector (ADR-0098 invariant #2):
capture_state() snapshots a load-bearing subset of process state
(CORE_* env vars + module identities for chat.telemetry,
chat.runtime, language_packs.compiler);
verify_no_global_state_mutation() ignores None→id transitions
(benign lazy import) and only flags env-var changes or module
identity rebindings
- new evals/demo_composition/ lane (ADR-0098 invariant proving):
- 6 cases asserting byte-equality + no-state-mutation across the
three fast adapters (audit-tour, register-tour, orthogonality-tour)
- composition_read_only: confirms two adapter results compose into
a composite claim set without mutating either
- stateful_fixture_rejected: negative control — a deliberately
stateful adapter MUST trigger divergence detection
- anchor-lens-tour adapter is exercised by tests, not the lane,
to keep wall time bounded
- byte-identical across runs (sha256 27d838241bf3..)
- 26 unit tests covering Claim/DemoResult validation, canonical_json
determinism, state-mutation detector (including the lazy-import
benign case), Protocol conformance (isinstance check + claim
contract version) for all four adapters, seed-rejection per
adapter (all current adapters are fully deterministic), and an
audit-tour integration smoke verifying 5 claims + byte-equality +
no state mutation across two consecutive runs
- smoke 67/67, cognition eval byte-identical 100/100/100/100, all
five lanes byte-identical (reviewer_registry 681a2aab..,
miner_loop_closure 9f071733.., domain_contract_validation f9c06cde..,
fabrication_control summary 01e1b6b7.., demo_composition 27d83824..)
1.9 KiB
1.9 KiB
evals/demo_composition — Lane Contract
ADR: ADR-0098 Invariants:
demo_json_byte_equalitydemo_composition_no_side_effects
Purpose
Prove that every adapter conforming to :class:core.demos.DemoCommand
satisfies ADR-0098's two structural rules:
- Deterministic JSON. Running an adapter twice in the same process with identical inputs produces byte-identical JSON output.
- No global state mutation. Running an adapter does not mutate
load-bearing process state (telemetry sink module identity,
CORE_*env vars, runtime module identity). Lazy imports of previously-unloaded modules are not considered mutations.
Cases
The runner exercises each shipped adapter and asserts both invariants hold:
audit_tour_byte_equality— audit-tour adapter byte-equality across two runs.audit_tour_no_state_mutation— global state snapshot identical across the audit-tour run.register_tour_byte_equality— register-tour adapter byte-equality.register_tour_no_state_mutation— global state snapshot identical.orthogonality_tour_byte_equality— orthogonality-tour adapter byte-equality.orthogonality_tour_no_state_mutation— global state snapshot identical.composition_read_only— the showcase reads two adapter results and produces a composite claim set without mutating either.stateful_fixture_rejected— a deliberately-stateful fixture produces a non-zero divergence list (negative control).
The anchor-lens tour is the slowest shipped tour; its adapter is
exercised by tests/test_demo_composition.py rather than the lane
runner to keep the lane fast.
Determinism
The lane emits results/v1_dev.json. Two consecutive runs against
the same in-tree code produce byte-identical bytes (SHA-256 pinned).
Exit code
Non-zero on any case whose actual outcome diverges from the case spec.