Files
rune/scripts/gen_drift_cache_truth.py
T
Nick 501ca712b0 feat(drift_cache): port to FULL Rust — dichotomy wave
parity: every public function of DriftCache ported branch-for-branch —
compute_priority (log1p wash scaling capped at 1.0, rock/established
boosts, Python truthiness coercion of None/0/0.5 fields), qualifies_
for_cache (the wash>=1 OR imp>=0.8 admission boundary), add (admission
gate, stamping with verbatim rock_status incl. explicit None, the
strict >200 eviction trigger), access (int/float access_count
preservation, miss is a silent no-op), contains/get_priority (0.0 for
unknown ids), update_from_store (row[0] or 0 / row[1] or 0.5 /
row[2] or 'washable' coercions, deleted-row removal), get_stats
(empty lattice, missing-priority 0.0, missing rock_status is
washable). Dict-order law: entries are an insertion-ordered map
(serde_json preserve_order) and the eviction sort is stable — ties
evict in insertion order, exactly like the oracle's dict + sorted.
No-clock law: now is a kernel argument; the sqlite read and the cache
FILE IO stay in the facade. dc_loader mirrors broker_loader (doc-
envelope FFI, cs_free_string, DC_RUST_LIB override, int<->str entry-id
key round-trip); facade delegation with RUNE_DC_CORE=python pin and
the legacy _ms_core chain preserved as second fallback. Frozen-truth
freeze caught a REAL kernel diverge: serde_json's default float
parser is 1 ulp off on priority floats — fixed-first with the
float_roundtrip feature. Battery: 8 tests replay 48 frozen-oracle
cases VERBATIM (include_str!). Live parity 48/48 facade + 45/45
kernel (load group is facade-only); clippy 0.
2026-10-12 00:26:02 +01:00

563 lines
20 KiB
Python

#!/usr/bin/env python3
"""gen_drift_cache_truth.py — freeze/replay parity truth for drift_cache
(dichotomy wave, #2479 tranche).
Freeze mode (default): exercises EVERY public function of the LIVE Python
oracle (src/rune/drift_cache.py) across every branch and records
(kernel_input, expected_kernel_output) pairs into
src/rust/drift_cache/src/frozen_dc_truth.json.
Replay mode (--replay): re-runs the SAME scenarios with the Rust core
delegation active and asserts both kernel-level (loader direct) and
facade-level (oracle methods delegate) parity against the frozen file.
Poisoned-truth law: freeze pins RUNE_DC_CORE=python AND
RUNE_MEMORY_CORE=python BEFORE any import (the module-level helpers carry
an older _ms_core delegation chain that must never poison the truth).
No-clock law: the wall clock is frozen by patching the datetime symbol in
drift_cache, so every kernel payload carries its own `now` and replay is
deterministic regardless of run date.
Boundary law: the sqlite read (update_from_store's per-id SELECT) and the
cache FILE IO (_load/_save, malformed-JSON reset) stay in the Python
facade — the kernel is a pure function of their results. The `load`
truth group is facade-only (no kernel symbol) and is skipped by the
kernel-level replay pass.
"""
import copy
import json
import os
import sqlite3
import sys
import tempfile
from datetime import datetime, timezone
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TRUTH_PATH = os.path.join(REPO, "src", "rust", "drift_cache", "src", "frozen_dc_truth.json")
REPLAY = "--replay" in sys.argv
os.environ["RUNE_DC_CORE"] = "python" # poisoned-truth law (no-op pre-port, load-bearing post-port)
os.environ["RUNE_MEMORY_CORE"] = "python"
sys.path.insert(0, os.path.join(REPO, "src"))
sys.path.insert(0, os.path.join(REPO, "src", "rune"))
import drift_cache as oracle_mod # noqa: E402
if REPLAY:
from rune import dc_loader # noqa: E402 (kernel-level replay side)
FROZEN_UTC = datetime(2026, 10, 11, 12, 0, 0, 123456, tzinfo=timezone.utc)
FROZEN_NOW = FROZEN_UTC.isoformat()
class FrozenDatetime(datetime):
@classmethod
def now(cls, tz=None):
return FROZEN_UTC
oracle_mod.datetime = FrozenDatetime
class Case:
def __init__(self, name, fn):
self.name = name
self.fn = fn
def fresh_cache(entries_pre=None):
tmp = tempfile.mkdtemp(prefix="dc_truth_")
oracle_mod.CACHE_DIR = tmp
oracle_mod.CACHE_FILE = os.path.join(tmp, "drift_cache.json")
cache = oracle_mod.DriftCache()
if entries_pre is not None:
cache.entries = copy.deepcopy(entries_pre)
return cache
def stamped(priority, wash=0, rock="washable", access_count=0):
return {"priority": priority, "added_at": FROZEN_NOW, "last_accessed": FROZEN_NOW,
"access_count": access_count, "wash_count": wash, "rock_status": rock}
# ── compute_priority ─────────────────────────────────────────────────────────
def c_prio_default(rec):
rec("prio-default-empty-entry", {"entry": {}}, oracle_mod.compute_priority({}),
{"priority": oracle_mod.compute_priority({})})
def c_prio_wash20_imp1(rec):
e = {"wash_count": 20, "importance": 1.0}
rec("prio-wash20-imp1-washfactor-1", {"entry": e}, oracle_mod.compute_priority(e),
{"priority": oracle_mod.compute_priority(e)})
def c_prio_typical(rec):
e = {"wash_count": 7, "importance": 0.6}
rec("prio-wash7-imp06", {"entry": e}, oracle_mod.compute_priority(e),
{"priority": oracle_mod.compute_priority(e)})
def c_prio_rock(rec):
e = {"wash_count": 3, "importance": 0.7, "rock_status": "rock"}
rec("prio-rock-boost", {"entry": e}, oracle_mod.compute_priority(e),
{"priority": oracle_mod.compute_priority(e)})
def c_prio_established(rec):
e = {"wash_count": 3, "importance": 0.7, "rock_status": "established"}
rec("prio-established-boost", {"entry": e}, oracle_mod.compute_priority(e),
{"priority": oracle_mod.compute_priority(e)})
def c_prio_none_wash(rec):
e = {"wash_count": None, "importance": 0.9}
rec("prio-none-wash-coerced-0", {"entry": e}, oracle_mod.compute_priority(e),
{"priority": oracle_mod.compute_priority(e)})
def c_prio_none_imp(rec):
e = {"wash_count": 4, "importance": None}
rec("prio-none-imp-coerced-05", {"entry": e}, oracle_mod.compute_priority(e),
{"priority": oracle_mod.compute_priority(e)})
def c_prio_zero_imp(rec):
# falsy 0 → `or 0.5` coerces to 0.5
e = {"wash_count": 4, "importance": 0}
rec("prio-zero-imp-coerced-05", {"entry": e}, oracle_mod.compute_priority(e),
{"priority": oracle_mod.compute_priority(e)})
def c_prio_int_importance(rec):
e = {"wash_count": 2, "importance": 1}
rec("prio-int-importance", {"entry": e}, oracle_mod.compute_priority(e),
{"priority": oracle_mod.compute_priority(e)})
def c_prio_wash_beyond_20(rec):
# log1p scaling caps at 1.0 via min()
e = {"wash_count": 1000, "importance": 0.5}
rec("prio-wash1000-capped", {"entry": e}, oracle_mod.compute_priority(e),
{"priority": oracle_mod.compute_priority(e)})
def c_prio_unknown_status(rec):
e = {"wash_count": 2, "importance": 0.5, "rock_status": "muddy"}
rec("prio-unknown-status-no-boost", {"entry": e}, oracle_mod.compute_priority(e),
{"priority": oracle_mod.compute_priority(e)})
# ── qualifies_for_cache ──────────────────────────────────────────────────────
def _q_case(rec, name, entry):
rec(name, {"entry": entry}, oracle_mod.qualifies_for_cache(entry),
{"qualifies": oracle_mod.qualifies_for_cache(entry)})
def c_qual_below_both(rec):
_q_case(rec, "qual-wash0-imp05-denied", {"wash_count": 0, "importance": 0.5})
def c_qual_imp_boundary(rec):
_q_case(rec, "qual-imp-079-denied", {"wash_count": 0, "importance": 0.79})
def c_qual_imp_08_admitted(rec):
_q_case(rec, "qual-imp-08-admitted", {"wash_count": 0, "importance": 0.8})
def c_qual_wash_boundary(rec):
_q_case(rec, "qual-wash1-imp0-admitted", {"wash_count": 1, "importance": 0.0})
def c_qual_defaults(rec):
_q_case(rec, "qual-defaults-denied", {})
def c_qual_none_fields(rec):
_q_case(rec, "qual-none-fields-denied", {"wash_count": None, "importance": None})
def c_qual_proven(rec):
_q_case(rec, "qual-wash5-admitted", {"wash_count": 5, "importance": 0.3})
# ── add ──────────────────────────────────────────────────────────────────────
def _add_case(rec, name, entries_pre, entry_id, entry):
cache = fresh_cache(entries_pre)
cache.add(entry_id, entry)
admitted = entry_id in cache.entries
evicted = sorted(set(entries_pre) - set(cache.entries))
rec(name,
{"entries": entries_pre, "entry_id": entry_id, "entry": entry, "now": FROZEN_NOW},
None, {"entries": cache.entries, "admitted": admitted, "evicted": evicted})
def c_add_denied(rec):
_add_case(rec, "add-denied-unproven-unimportant", {}, 1,
{"wash_count": 0, "importance": 0.5})
def c_add_denied_important_but_unwashed(rec):
_add_case(rec, "add-denied-imp-below-08", {}, 2,
{"wash_count": 0, "importance": 0.5, "text": "x"})
def c_add_washable(rec):
_add_case(rec, "add-washable-admitted", {}, 3,
{"wash_count": 2, "importance": 0.5, "rock_status": "washable"})
def c_add_high_importance_unwashed(rec):
_add_case(rec, "add-important-unwashed-admitted", {}, 4,
{"wash_count": 0, "importance": 0.95})
def c_add_rock(rec):
_add_case(rec, "add-rock-stamped", {}, 5,
{"wash_count": 3, "importance": 0.7, "rock_status": "rock"})
def c_add_overwrites(rec):
pre = {7: stamped(0.9, wash=9, rock="rock", access_count=4)}
_add_case(rec, "add-overwrites-existing", pre, 7,
{"wash_count": 1, "importance": 0.4})
def c_add_rock_status_none(rec):
# explicit None rock_status is stored verbatim (entry.get returns None)
_add_case(rec, "add-rock-status-none-verbatim", {}, 8,
{"wash_count": 2, "importance": 0.5, "rock_status": None})
def c_add_boundary_200_no_evict(rec):
pre = {i: {"priority": (i + 1) / 200.0} for i in range(199)}
_add_case(rec, "add-at-200-no-evict", pre, 199,
{"wash_count": 20, "importance": 1.0})
def c_add_evict_lowest_20(rec):
pre = {i: {"priority": (i + 1) / 200.0} for i in range(200)}
_add_case(rec, "add-evicts-lowest-20", pre, 999,
{"wash_count": 20, "importance": 1.0, "rock_status": "rock"})
def c_add_evict_tie_stable_order(rec):
pre = {i: {"priority": 0.5} for i in range(196)}
for i in range(196, 200):
pre[i] = {"priority": 9.0}
_add_case(rec, "add-evict-tie-stable-insertion-order", pre, 999,
{"wash_count": 20, "importance": 1.0})
# ── access ───────────────────────────────────────────────────────────────────
def _access_case(rec, name, entries_pre, entry_id):
cache = fresh_cache(entries_pre)
cache.access(entry_id)
changed = entry_id in entries_pre
rec(name,
{"entries": entries_pre, "entry_id": entry_id, "now": FROZEN_NOW},
None, {"entries": cache.entries, "changed": changed})
def c_access_hit(rec):
pre = {11: stamped(0.5, access_count=3)}
_access_case(rec, "access-hit-reinforces", pre, 11)
def c_access_miss(rec):
pre = {11: stamped(0.5)}
_access_case(rec, "access-miss-noop", pre, 12)
def c_access_zero_count(rec):
pre = {13: stamped(0.5, access_count=0)}
_access_case(rec, "access-from-zero", pre, 13)
# ── contains / get_priority ──────────────────────────────────────────────────
def c_contains_hit(rec):
pre = {21: stamped(0.5)}
cache = fresh_cache(pre)
rec("contains-hit", {"entries": pre, "entry_id": 21},
cache.contains(21), {"contains": cache.contains(21)})
def c_contains_miss(rec):
cache = fresh_cache({})
rec("contains-miss", {"entries": {}, "entry_id": 21},
cache.contains(21), {"contains": cache.contains(21)})
def c_getprio_hit(rec):
pre = {31: stamped(0.625)}
cache = fresh_cache(pre)
rec("getprio-hit", {"entries": pre, "entry_id": 31},
cache.get_priority(31), {"priority": cache.get_priority(31)})
def c_getprio_miss(rec):
cache = fresh_cache({})
rec("getprio-miss-zero", {"entries": {}, "entry_id": 31},
cache.get_priority(31), {"priority": cache.get_priority(31)})
# ── update_from_store ────────────────────────────────────────────────────────
def make_db(rows):
db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE entries (id INTEGER PRIMARY KEY, wash_count INTEGER,"
" importance REAL, rock_status TEXT)")
db.executemany("INSERT INTO entries VALUES (?,?,?,?)", rows)
return db
def _sync_case(rec, name, entries_pre, db_rows):
db = make_db(db_rows)
cache = fresh_cache(entries_pre)
rows = {}
for entry_id in list(cache.entries.keys()):
row = db.execute(
"SELECT wash_count, importance, rock_status FROM entries WHERE id = ?",
(entry_id,)).fetchone()
rows[str(entry_id)] = list(row) if row else None
cache.update_from_store(db)
rec(name, {"entries": entries_pre, "rows": rows}, None,
{"entries": cache.entries})
def c_sync_updates_priority(rec):
pre = {41: stamped(0.1, wash=1)}
_sync_case(rec, "sync-updates-priority-wash-rock", pre,
[(41, 15, 0.8, "rock")])
def c_sync_null_fields(rec):
pre = {42: stamped(0.9, wash=5, rock="rock")}
_sync_case(rec, "sync-null-row-fields-coerced", pre,
[(42, None, None, None)])
def c_sync_deleted_row_removed(rec):
pre = {43: stamped(0.5), 44: stamped(0.7)}
_sync_case(rec, "sync-deleted-row-removed", pre,
[(44, 2, 0.5, "washable")])
def c_sync_empty_cache(rec):
_sync_case(rec, "sync-empty-cache-noop", {}, [])
def c_sync_downgrade(rec):
pre = {45: stamped(1.0, wash=20, rock="rock")}
_sync_case(rec, "sync-downgrade-washable", pre,
[(45, 0, 0.1, "washable")])
# ── get_stats ────────────────────────────────────────────────────────────────
def _stats_case(rec, name, entries_pre):
cache = fresh_cache(entries_pre)
stats = cache.get_stats()
rec(name, {"entries": entries_pre}, stats, {"stats": stats})
def c_stats_empty(rec):
_stats_case(rec, "stats-empty", {})
def c_stats_mixed(rec):
pre = {
51: stamped(0.2, rock="rock"),
52: stamped(0.5, rock="established"),
53: stamped(0.9),
}
_stats_case(rec, "stats-mixed", pre)
def c_stats_all_washable(rec):
pre = {54: stamped(0.3), 55: stamped(0.4)}
_stats_case(rec, "stats-all-washable", pre)
def c_stats_missing_priority(rec):
pre = {56: {"rock_status": "rock"}, 57: stamped(0.8)}
_stats_case(rec, "stats-missing-priority-zero", pre)
def c_stats_missing_rock_status(rec):
pre = {58: {"priority": 0.5}}
_stats_case(rec, "stats-missing-rock-status-washable", pre)
# ── _load branches (facade-only: FILE IO stays in Python) ────────────────────
def c_load_missing(rec):
cache = fresh_cache()
rec("load-missing-file-empty", {"path": "missing"}, None,
{"entries": cache.entries})
def c_load_valid(rec):
tmp = tempfile.mkdtemp(prefix="dc_truth_")
oracle_mod.CACHE_DIR = tmp
oracle_mod.CACHE_FILE = os.path.join(tmp, "drift_cache.json")
pre = {61: stamped(0.5), 62: stamped(0.9, rock="rock")}
with open(oracle_mod.CACHE_FILE, "w") as f:
json.dump({str(k): v for k, v in pre.items()}, f, indent=2)
cache = oracle_mod.DriftCache()
rec("load-valid-int-keys", {"path": "valid"}, None,
{"entries": cache.entries})
def c_load_malformed(rec):
tmp = tempfile.mkdtemp(prefix="dc_truth_")
oracle_mod.CACHE_DIR = tmp
oracle_mod.CACHE_FILE = os.path.join(tmp, "drift_cache.json")
with open(oracle_mod.CACHE_FILE, "w") as f:
f.write("{not json")
cache = oracle_mod.DriftCache()
rec("load-malformed-reset", {"path": "malformed"}, None,
{"entries": cache.entries})
# ── driver ───────────────────────────────────────────────────────────────────
PRIO = [c_prio_default, c_prio_wash20_imp1, c_prio_typical, c_prio_rock,
c_prio_established, c_prio_none_wash, c_prio_none_imp, c_prio_zero_imp,
c_prio_int_importance, c_prio_wash_beyond_20, c_prio_unknown_status]
QUAL = [c_qual_below_both, c_qual_imp_boundary, c_qual_imp_08_admitted,
c_qual_wash_boundary, c_qual_defaults, c_qual_none_fields, c_qual_proven]
ADD = [c_add_denied, c_add_denied_important_but_unwashed, c_add_washable,
c_add_high_importance_unwashed, c_add_rock, c_add_overwrites,
c_add_rock_status_none, c_add_boundary_200_no_evict,
c_add_evict_lowest_20, c_add_evict_tie_stable_order]
ACCESS = [c_access_hit, c_access_miss, c_access_zero_count]
CONTAINS = [c_contains_hit, c_contains_miss]
GETPRIO = [c_getprio_hit, c_getprio_miss]
SYNC = [c_sync_updates_priority, c_sync_null_fields, c_sync_deleted_row_removed,
c_sync_empty_cache, c_sync_downgrade]
STATS = [c_stats_empty, c_stats_mixed, c_stats_all_washable,
c_stats_missing_priority, c_stats_missing_rock_status]
LOAD = [c_load_missing, c_load_valid, c_load_malformed]
GROUPS = [("compute_priority", PRIO), ("qualifies_for_cache", QUAL),
("add", ADD), ("access", ACCESS), ("contains", CONTAINS),
("get_priority", GETPRIO), ("update_entries", SYNC),
("get_stats", STATS), ("load", LOAD)]
# kernel symbol per group (None → facade-only group, skipped kernel-side)
KERNEL = {
"compute_priority": "dcc_compute_priority",
"qualifies_for_cache": "dcc_qualifies_for_cache",
"add": "dcc_add",
"access": "dcc_access",
"contains": "dcc_contains",
"get_priority": "dcc_get_priority",
"update_entries": "dcc_update_entries",
"get_stats": "dcc_get_stats",
"load": None,
}
# kernel-level replay: which slice of `expected` the unwrapped FFI value is
UNWRAP = {
"compute_priority": lambda w: w["priority"],
"qualifies_for_cache": lambda w: w["qualifies"],
"add": lambda w: w,
"access": lambda w: w,
"contains": lambda w: w["contains"],
"get_priority": lambda w: w["priority"],
"update_entries": lambda w: w["entries"],
"get_stats": lambda w: w["stats"],
}
def canon(x) -> str:
"""Content canonicalization: int dict keys become strings through the
JSON round-trip (the frozen file stores string keys), then a sorted
dump makes the comparison key-order independent."""
return json.dumps(json.loads(json.dumps(x)), sort_keys=True)
def main():
frozen = None
if REPLAY:
with open(TRUTH_PATH) as f:
frozen = json.load(f)["cases"]
groups = {}
for group, cases in GROUPS:
recs = []
def rec(name, inp, oracle_ret, expected, _r=recs):
entry = {"name": name, "input": inp, "return": oracle_ret,
"expected": expected}
if REPLAY:
old = next(c for c in frozen[group] if c["name"] == name)
for key in ("input", "return", "expected"):
got, want = entry[key], old[key]
if canon(got) != canon(want):
print(f"FACADE DIVERGE [{group}] {name} {key}")
print(" got: ", json.dumps(got, sort_keys=True, default=str)[:600])
print(" want:", json.dumps(want, sort_keys=True, default=str)[:600])
recs.append({"name": name, "diverged": key})
return
_r.append(entry)
for c in cases:
c(rec)
groups[group] = recs
total = sum(len(v) for v in groups.values())
if REPLAY:
facade_failures = sum(1 for v in groups.values() for c in v if "diverged" in c)
failures = 0
checked = 0
for group, cases in frozen.items():
sym = KERNEL[group]
if sym is None:
continue
for case in cases:
checked += 1
got = getattr(dc_loader, group)(**copy.deepcopy(case["input"]))
want = UNWRAP[group](case["expected"])
if canon(got) != canon(want):
failures += 1
print(f"KERNEL DIVERGE [{group}] {case['name']}")
print(" got: ", json.dumps(got, sort_keys=True)[:600])
print(" want:", json.dumps(want, sort_keys=True)[:600])
print(f"replay: facade {total - facade_failures}/{total}, "
f"kernel {checked - failures}/{checked}")
return 1 if (failures or facade_failures) else 0
doc = {
"frozen": datetime.now(timezone.utc).isoformat(),
"oracle": "src/rune/drift_cache.py",
"pin": "RUNE_DC_CORE=python + RUNE_MEMORY_CORE=python",
"note": "Frozen via scripts/gen_drift_cache_truth.py against the live "
"Python oracle; wall clock frozen at " + FROZEN_NOW +
". Battery embeds this VERBATIM. Group `load` is facade-only "
"(FILE IO stays in Python).",
"cases": groups,
}
os.makedirs(os.path.dirname(TRUTH_PATH), exist_ok=True)
with open(TRUTH_PATH, "w") as f:
# NO sort_keys: the entries maps are Python dicts whose INSERTION
# order is load-bearing (stable eviction tie-breaks) — sorting
# keys here would freeze a re-ordered kernel input.
json.dump(doc, f, indent=1)
f.write("\n")
print(f"frozen {total} cases → {os.path.relpath(TRUTH_PATH, REPO)}")
return 0
if __name__ == "__main__":
sys.exit(main())