#!/usr/bin/env python3 """Freeze the parity truth for the behaviour_ledger Rust port (dichotomy wave #2479 tranche). Runs the LIVE oracle (src/rune/behaviour_ledger.py — the Phase G shim serving the evidence_provenance `bl_*` core, retired as the Python oracle by this port) across EVERY public function and EVERY branch: define (minimal/full/prefixed id/duplicate/unicode), get (hit both id forms/miss/empty), record_auto_verification (pass/fail/unknown/200-char detail truncation/reverify-confirmed), record_real_world (user confirmation/other-confirmer/fail/unknown), accept_limitation (ok/ custom approver/unknown), invalidate_for_change (dependency overlap with the default sorted-list-repr reason / owner hit / no overlap → preserved / custom reasons / reasons key miss / auto-verified-only skip / mixed multi-behaviour), retest_history (populated generations/ unknown/empty), outstanding (mixed states with the TEST_FAILED-first sort / component filter / project filter / combined / excluded states), summary (empty/mixed integer counts). The clock is pinned (bl._now) so truth is deterministic and regenerable byte-for-byte. Case input docs are deep-copied BEFORE the oracle runs (poisoned-truth law). Output: src/rust/behaviour_ledger/src/frozen_bl_truth.json — embedded VERBATIM by the cfg(test) branch battery (include_str!). """ from __future__ import annotations import copy import json import sys import tempfile from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) from rune import behaviour_ledger as bl # noqa: E402 TRUTH_PATH = Path(__file__).resolve().parents[1] / ( "src/rust/behaviour_ledger/src/frozen_bl_truth.json") class Clock: """Pinned clock: %Y-%m-%dT%H:%M:%SZ stamps incrementing by second (the oracle's _now format), reset per case.""" def __init__(self): self.n = 0 def now(self) -> str: self.n += 1 return f"2026-10-11T23:00:{self.n:02d}Z" CLOCK = Clock() bl._now = CLOCK.now # pin the facade's clock (the kernel takes `now` in) def fresh() -> bl.BehaviourLedger: CLOCK.n = 0 tmp = tempfile.mkdtemp(prefix="bl_truth_") return bl.BehaviourLedger(Path(tmp) / "store") def envelope_ok(value) -> dict: return {"ok": True, "value": value} def envelope_err(msg: str) -> dict: return {"ok": False, "err": msg} CASES: dict[str, list] = {} def add(group: str, case: dict) -> None: CASES.setdefault(group, []).append(case) def snap(led: bl.BehaviourLedger) -> dict: return copy.deepcopy(led.doc) def next_now() -> str: """The stamp the NEXT pinned _now() call will return.""" return f"2026-10-11T23:00:{CLOCK.n + 1:02d}Z" def run_mutation(group: str, name: str, led: bl.BehaviourLedger, params: dict, op) -> None: """Run one mutating op (kwargs only); record {input: {doc, now, **params}, expected: {ok, value: {doc, rec | recs}}} or the ValueError envelope. The op under test stamps via the pinned clock; its stamp is recorded in the input (no-clock law — the kernel takes `now` in).""" doc_in = snap(led) stamp = next_now() try: out = op(**params) except ValueError as e: add(group, {"name": name, "input": {"doc": doc_in, "now": stamp, **params}, "expected": envelope_err(str(e))}) return value_key = "recs" if isinstance(out, list) else "rec" add(group, {"name": name, "input": {"doc": doc_in, "now": stamp, **params}, "expected": envelope_ok({"doc": led.doc, value_key: out})}) def seed_confirmed(led: bl.BehaviourLedger, bid: str, owner: str, deps: list[str]) -> None: led.define(behaviour_id=bid, owning_project="demo", intended_behaviour=f"{bid} behaves", owner_component=owner, dependencies=deps) led.record_auto_verification(bid, passed=True, generation="gen-1") led.record_real_world(bid, passed=True, detail="user confirmed", generation="gen-1") # ── define ──────────────────────────────────────────────────────────────── led = fresh() run_mutation("define", "minimal", led, { "behaviour_id": "MIN-1", "owning_project": "demo", "intended_behaviour": "does the thing"}, led.define) led = fresh() run_mutation("define", "full_kwargs", led, { "behaviour_id": "FULL-1", "owning_project": "demo", "intended_behaviour": "bridge completes events", "origin_intent": "issue #19F", "pass_criteria": "events done", "fail_criteria": "events dropped", "procedure": "run the suite", "owner_component": "component:event_bridge", "dependencies": ["component:event_bridge", "interface:event_completion"], "automated_ref": "tests/test_bridge.py", "environment": "ci"}, led.define) led = fresh() run_mutation("define", "prefixed_id_preserved", led, { "behaviour_id": "behaviour:PRE-1", "owning_project": "demo", "intended_behaviour": "already prefixed"}, led.define) led = fresh() run_mutation("define", "unicode_fields", led, { "behaviour_id": "UNI-1", "owning_project": "démø", "intended_behaviour": "completes événements — ✓ ünïcode", "origin_intent": "»quoted«", "pass_criteria": "✓ pass", "owner_component": "component:kafé", "dependencies": ["component:kafé", "interface:ünï"], "environment": "prod-ü"}, led.define) led = fresh() led.define(behaviour_id="DUP-1", owning_project="demo", intended_behaviour="first") run_mutation("define", "duplicate_err", led, { "behaviour_id": "DUP-1", "owning_project": "demo", "intended_behaviour": "second"}, led.define) led = fresh() run_mutation("define", "none_dependencies", led, { "behaviour_id": "NODEP-1", "owning_project": "demo", "intended_behaviour": "no deps given", "dependencies": None}, led.define) # ── get ─────────────────────────────────────────────────────────────────── led = fresh() led.define(behaviour_id="GET-1", owning_project="demo", intended_behaviour="gettable") rec = led.get("GET-1") add("get", {"name": "hit_bare_id", "input": {"doc": snap(led), "behaviour_id": "GET-1"}, "expected": envelope_ok(rec)}) add("get", {"name": "hit_prefixed_id", "input": {"doc": snap(led), "behaviour_id": "behaviour:GET-1"}, "expected": envelope_ok(rec)}) add("get", {"name": "miss", "input": {"doc": snap(led), "behaviour_id": "behaviour:NOPE"}, "expected": envelope_ok(None)}) add("get", {"name": "empty_doc", "input": {"doc": snap(fresh()), "behaviour_id": "GET-1"}, "expected": envelope_ok(None)}) # ── record_auto_verification ────────────────────────────────────────────── led = fresh() led.define(behaviour_id="AUTO-1", owning_project="demo", intended_behaviour="auto verifiable") run_mutation("record_auto_verification", "pass_to_auto_verified", led, { "behaviour_id": "AUTO-1", "passed": True, "detail": "suite green", "generation": "gen-1"}, led.record_auto_verification) led = fresh() led.define(behaviour_id="AUTO-2", owning_project="demo", intended_behaviour="fails") run_mutation("record_auto_verification", "fail_to_test_failed", led, { "behaviour_id": "AUTO-2", "passed": False, "detail": "assert crashed", "generation": "gen-1"}, led.record_auto_verification) led = fresh() run_mutation("record_auto_verification", "unknown_behaviour_err", led, { "behaviour_id": "GHOST", "passed": True}, led.record_auto_verification) led = fresh() led.define(behaviour_id="AUTO-3", owning_project="demo", intended_behaviour="long detail") run_mutation("record_auto_verification", "detail_truncated_200", led, { "behaviour_id": "AUTO-3", "passed": True, "detail": "x" * 250}, led.record_auto_verification) led = fresh() seed_confirmed(led, "AUTO-4", "component:c", ["component:c"]) run_mutation("record_auto_verification", "reverify_confirmed", led, { "behaviour_id": "AUTO-4", "passed": True, "detail": "regression suite", "generation": "gen-2"}, led.record_auto_verification) # ── record_real_world ───────────────────────────────────────────────────── led = fresh() led.define(behaviour_id="RW-1", owning_project="demo", intended_behaviour="user confirmed") run_mutation("record_real_world", "user_pass_confirmed", led, { "behaviour_id": "RW-1", "passed": True, "detail": "manual test ok", "generation": "gen-1", "confirmed_by": "user"}, led.record_real_world) led = fresh() led.define(behaviour_id="RW-2", owning_project="demo", intended_behaviour="robot verified") run_mutation("record_real_world", "other_confirmer_real_world_passed", led, { "behaviour_id": "RW-2", "passed": True, "detail": "bot checked", "generation": "gen-1", "confirmed_by": "ci-robot"}, led.record_real_world) led = fresh() led.define(behaviour_id="RW-3", owning_project="demo", intended_behaviour="fails in the field") run_mutation("record_real_world", "fail_to_test_failed", led, { "behaviour_id": "RW-3", "passed": False, "detail": "user saw breakage", "generation": "gen-1"}, led.record_real_world) led = fresh() run_mutation("record_real_world", "unknown_behaviour_err", led, { "behaviour_id": "RW-GHOST", "passed": True}, led.record_real_world) # ── accept_limitation ───────────────────────────────────────────────────── led = fresh() led.define(behaviour_id="LIM-1", owning_project="demo", intended_behaviour="known gap") run_mutation("accept_limitation", "ok", led, { "behaviour_id": "LIM-1", "note": "edge case accepted for v1", "approved_by": "user"}, led.accept_limitation) led = fresh() led.define(behaviour_id="LIM-2", owning_project="demo", intended_behaviour="approved gap") run_mutation("accept_limitation", "custom_approver", led, { "behaviour_id": "LIM-2", "note": "signed off by maintainer", "approved_by": "nick"}, led.accept_limitation) led = fresh() run_mutation("accept_limitation", "unknown_behaviour_err", led, { "behaviour_id": "LIM-GHOST", "note": "x"}, led.accept_limitation) # ── invalidate_for_change ───────────────────────────────────────────────── led = fresh() seed_confirmed(led, "INV-1", "component:bridge", ["component:bridge", "interface:completion"]) doc_in = snap(led) stamp = next_now() recs = led.invalidate_for_change(changed_entities={"component:bridge"}, generation="gen-2") add("invalidate_for_change", { "name": "dep_overlap_default_reason", "input": {"doc": doc_in, "now": stamp, "changed_entities": sorted({"component:bridge"}), "generation": "gen-2", "reasons": None}, "expected": envelope_ok({"doc": led.doc, "recs": recs})}) led = fresh() seed_confirmed(led, "INV-2", "component:bridge", []) doc_in = snap(led) stamp = next_now() recs = led.invalidate_for_change(changed_entities={"component:bridge"}, generation="gen-2") add("invalidate_for_change", { "name": "owner_hit_only", "input": {"doc": doc_in, "now": stamp, "changed_entities": sorted({"component:bridge"}), "generation": "gen-2", "reasons": None}, "expected": envelope_ok({"doc": led.doc, "recs": recs})}) led = fresh() seed_confirmed(led, "INV-3", "component:unrelated", ["component:unrelated"]) doc_in = snap(led) stamp = next_now() recs = led.invalidate_for_change(changed_entities={"component:bridge"}, generation="gen-2") add("invalidate_for_change", { "name": "no_overlap_preserved", "input": {"doc": doc_in, "now": stamp, "changed_entities": sorted({"component:bridge"}), "generation": "gen-2", "reasons": None}, "expected": envelope_ok({"doc": led.doc, "recs": recs})}) led = fresh() seed_confirmed(led, "INV-4", "component:bridge", ["component:bridge", "interface:completion"]) doc_in = snap(led) stamp = next_now() recs = led.invalidate_for_change( changed_entities={"component:bridge", "interface:completion"}, generation="gen-2", reasons={"behaviour:INV-4": "bridge rewrite (issue #42)"}) add("invalidate_for_change", { "name": "custom_reason", "input": {"doc": doc_in, "now": stamp, "changed_entities": sorted({"component:bridge", "interface:completion"}), "generation": "gen-2", "reasons": {"behaviour:INV-4": "bridge rewrite (issue #42)"}}, "expected": envelope_ok({"doc": led.doc, "recs": recs})}) led = fresh() led.define(behaviour_id="INV-5", owning_project="demo", intended_behaviour="never confirmed") doc_in = snap(led) stamp = next_now() recs = led.invalidate_for_change(changed_entities={"component:bridge"}, generation="gen-2") add("invalidate_for_change", { "name": "unconfirmed_skipped", "input": {"doc": doc_in, "now": stamp, "changed_entities": sorted({"component:bridge"}), "generation": "gen-2", "reasons": None}, "expected": envelope_ok({"doc": led.doc, "recs": recs})}) led = fresh() seed_confirmed(led, "INV-6", "component:bridge", ["component:bridge", "interface:completion"]) seed_confirmed(led, "INV-7", "component:consumer", ["component:consumer", "interface:completion"]) seed_confirmed(led, "INV-8", "component:unrelated", ["component:unrelated"]) doc_in = snap(led) stamp = next_now() recs = led.invalidate_for_change( changed_entities={"interface:completion"}, generation="gen-2") add("invalidate_for_change", { "name": "mixed_multi_behaviour", "input": {"doc": doc_in, "now": stamp, "changed_entities": sorted({"interface:completion"}), "generation": "gen-2", "reasons": None}, "expected": envelope_ok({"doc": led.doc, "recs": recs})}) led = fresh() seed_confirmed(led, "INV-9", "component:bridge", ["component:bridge"]) doc_in = snap(led) stamp = next_now() recs = led.invalidate_for_change(changed_entities={"component:bridge"}, generation="gen-2", reasons={"behaviour:NOPE": "x"}) add("invalidate_for_change", { "name": "reasons_key_miss_falls_back", "input": {"doc": doc_in, "now": stamp, "changed_entities": sorted({"component:bridge"}), "generation": "gen-2", "reasons": {"behaviour:NOPE": "x"}}, "expected": envelope_ok({"doc": led.doc, "recs": recs})}) # ── retest_history ──────────────────────────────────────────────────────── led = fresh() seed_confirmed(led, "HIST-1", "component:bridge", ["component:bridge"]) led.invalidate_for_change(changed_entities={"component:bridge"}, generation="gen-2") hist = led.retest_history("HIST-1") add("retest_history", {"name": "populated_generations", "input": {"doc": snap(led), "behaviour_id": "HIST-1"}, "expected": envelope_ok(hist)}) add("retest_history", {"name": "unknown_behaviour_empty", "input": {"doc": snap(led), "behaviour_id": "behaviour:GHOST"}, "expected": envelope_ok([])}) led = fresh() led.define(behaviour_id="HIST-2", owning_project="demo", intended_behaviour="no events yet") add("retest_history", {"name": "empty_history", "input": {"doc": snap(led), "behaviour_id": "HIST-2"}, "expected": envelope_ok([])}) # ── outstanding ─────────────────────────────────────────────────────────── led = fresh() add("outstanding", {"name": "empty_doc", "input": {"doc": snap(led), "component": "", "project": ""}, "expected": envelope_ok(led.outstanding())}) led = fresh() led.define(behaviour_id="OUT-1", owning_project="demo", intended_behaviour="failed", owner_component="component:a") led.record_auto_verification("OUT-1", passed=False, generation="g") led.define(behaviour_id="OUT-2", owning_project="demo", intended_behaviour="unvalidated", owner_component="component:b") led.define(behaviour_id="OUT-3", owning_project="other", intended_behaviour="other project", owner_component="component:a") led.define(behaviour_id="OUT-4", owning_project="demo", intended_behaviour="confirmed", owner_component="component:b") led.record_real_world("OUT-4", passed=True, generation="g") led.define(behaviour_id="OUT-5", owning_project="demo", intended_behaviour="accepted", owner_component="component:c") led.accept_limitation("OUT-5", note="known gap") led.define(behaviour_id="OUT-6", owning_project="demo", intended_behaviour="n/a", owner_component="component:c") led.doc["behaviours"]["behaviour:OUT-6"]["state"] = "NOT_APPLICABLE" doc = snap(led) add("outstanding", {"name": "mixed_sort_failed_first", "input": {"doc": doc, "component": "", "project": ""}, "expected": envelope_ok(led.outstanding())}) add("outstanding", {"name": "component_filter", "input": {"doc": doc, "component": "component:a", "project": ""}, "expected": envelope_ok( led.outstanding(component="component:a"))}) add("outstanding", {"name": "project_filter", "input": {"doc": doc, "component": "", "project": "other"}, "expected": envelope_ok(led.outstanding(project="other"))}) add("outstanding", {"name": "combined_filters", "input": {"doc": doc, "component": "component:a", "project": "demo"}, "expected": envelope_ok( led.outstanding(component="component:a", project="demo"))}) # ── summary ─────────────────────────────────────────────────────────────── led = fresh() add("summary", {"name": "empty_doc", "input": {"doc": snap(led)}, "expected": envelope_ok(led.summary())}) led = fresh() led.define(behaviour_id="SUM-1", owning_project="demo", intended_behaviour="confirmed") led.record_real_world("SUM-1", passed=True, generation="g") led.define(behaviour_id="SUM-2", owning_project="demo", intended_behaviour="failed") led.record_auto_verification("SUM-2", passed=False, generation="g") led.define(behaviour_id="SUM-3", owning_project="demo", intended_behaviour="unvalidated") led.define(behaviour_id="SUM-4", owning_project="demo", intended_behaviour="confirmed too") led.record_real_world("SUM-4", passed=True, generation="g") add("summary", {"name": "mixed_integer_counts", "input": {"doc": snap(led)}, "expected": envelope_ok(led.summary())}) truth = {"frozen": "2026-10-11T23:00:00Z clock, oracle = live " "src/rune/behaviour_ledger.py shim (ep bl_* core)", "cases": CASES} TRUTH_PATH.write_text(json.dumps(truth, indent=1, ensure_ascii=False) + "\n") n = sum(len(v) for v in CASES.values()) print(f"frozen {n} cases across {len(CASES)} groups -> {TRUTH_PATH}")