Files
rune/scripts/gen_drift_observability_truth.py
T
Nick 141c35ec9e feat(drift_observability): literal-100% residue — dichotomy wave
Port the last four audit-missing fns name-preserving into the crate:
* _do_core — the facade loader-probe twin (_cs_core law; 4 pin rows).
* _load_alerts — the METHOD's file law with the IO peeled off (text
  arg; None=missing → [], JSONDecodeError → [], valid doc VERBATIM —
  a non-array document rides through as-is); 5 rows incl. the
  non-array and corrupt branches.
* _save_alerts — the persisted bytes law: json.dumps(alerts, indent=2)
  (ensure-ascii escapes, integral-float law); 2 rows incl. unicode.
* main — the subparser CLI dispatcher (task_persist MainOutcome law):
  check/retrospective --days/alerts/acknowledge index/dashboard with
  the help-to-stdout + exit-1 no-cmd shape, exit-2 argparse classes
  (invalid choice, subparser usage with the per-sub prog prefix,
  missing/bad int index, bad --days), every print shape (Found N new
  alerts, the retrospective block, Unacknowledged (N) with [i] prefix,
  Alert N acknowledged., the full dashboard incl. .2% ratio and
  True/False bool str), and the in-memory alerts-file state (rendered
  bytes compared). 20 main rows frozen from the live oracle under a
  memory_store/drift_core seam rig.
serde_json gains preserve_order (dict-order rendering); the rig's
frozen stamp is deterministic and the truth keeps insertion order.

FIX-FIRST WITH PROOF (pre-existing kernel bug): dob_run_retrospective
returned the BARE local stamp as filename, but the facade joins it
directly — kernel-live wrote retrospectives/20261011_130000 while the
Python path wrote retrospective_20261011_130000.json. The kernel now
returns the full name; the replay pass PROVED the divergence pre-fix
(kernel 55/64 on the stale .so) and parity post-fix (facade 64/64,
kernel 64/64, both core modes writing identical file names).

Battery 9/9 green (was 5); drift-family pytest 20/20 BOTH pins; clippy
-D warnings clean; gen x2 byte-identical. Fn coverage 5/9 -> 9/9.
2026-10-15 08:03:18 +01:00

729 lines
28 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""gen_drift_observability_truth.py — freeze/replay parity truth for
drift_observability (dichotomy wave, #2479 tranche).
Freeze mode (default): exercises EVERY public function of the LIVE Python
oracle (src/rune/drift_observability.py) across every branch and records
(kernel_input, expected_kernel_output) pairs into
src/rust/drift_observability/src/frozen_do_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_DO_CORE=python BEFORE any import.
No-clock law: the wall clock is frozen by patching the datetime symbol in
BOTH drift_observability and drift_core, so every kernel payload carries
its own `now` and replay is deterministic regardless of run date.
"""
import copy
import json
import os
import sqlite3
import sys
import tempfile
from datetime import datetime, timedelta, timezone
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TRUTH_PATH = os.path.join(
REPO, "src", "rust", "drift_observability", "src", "frozen_do_truth.json"
)
REPLAY = "--replay" in sys.argv
if not REPLAY:
os.environ["RUNE_DO_CORE"] = "python" # poisoned-truth law
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_core # noqa: E402
import drift_observability as oracle_mod # noqa: E402
if REPLAY:
import do_loader # noqa: E402 (kernel-level replay side)
FROZEN_UTC = datetime(2026, 10, 11, 12, 0, 0, 123456, tzinfo=timezone.utc)
FROZEN_LOCAL = datetime(2026, 10, 11, 13, 0, 0, 123456) # +01:00 wall clock
FROZEN_NOW = FROZEN_UTC.isoformat()
FROZEN_LOCAL_ISO = FROZEN_LOCAL.isoformat()
class FrozenDatetime(datetime):
@classmethod
def now(cls, tz=None):
if tz is not None:
return FROZEN_UTC.astimezone(tz)
return FROZEN_LOCAL
oracle_mod.datetime = FrozenDatetime
drift_core.datetime = FrozenDatetime
def ago(**kw):
return (FROZEN_UTC - timedelta(**kw)).isoformat()
def row(rock="washable", created=None, washed=None, accessed=None, status="active"):
return (status, rock, created, washed, accessed)
def make_db(rows):
db = sqlite3.connect(":memory:")
db.execute(
"CREATE TABLE entries (status TEXT, rock_status TEXT, created_at TEXT,"
" last_washed TEXT, last_accessed TEXT)"
)
db.executemany("INSERT INTO entries VALUES (?,?,?,?,?)", rows)
return db
_MAX_LAST_WASHED_SQL = (
"SELECT MAX(last_washed) FROM entries "
"WHERE rock_status != 'washable' AND status = 'active'"
)
class Case:
def __init__(self, name, fn):
self.name = name
self.fn = fn
def fresh_obs(alerts_pre=None):
tmp = tempfile.mkdtemp(prefix="do_truth_")
oracle_mod.ALERTS_FILE = os.path.join(tmp, "drift_alerts.json")
oracle_mod.RETROSPECTIVES_DIR = os.path.join(tmp, "retrospectives")
obs = oracle_mod.DriftObservability()
if alerts_pre is not None:
obs.alerts = copy.deepcopy(alerts_pre)
return obs
def _stamped(alert_type, message, severity):
return {
"type": alert_type,
"message": message,
"severity": severity,
"timestamp": FROZEN_NOW,
"acknowledged": False,
}
# ── add_alert ────────────────────────────────────────────────────────────────
def c_add_default(rec):
obs = fresh_obs()
rec("add-default-severity", {"alerts": [], "alert_type": "high_velocity",
"message": "v up", "severity": "info", "now": FROZEN_NOW},
obs.add_alert("high_velocity", "v up"), {"alerts": obs.alerts})
def c_add_warning(rec):
obs = fresh_obs()
rec("add-warning-severity", {"alerts": [], "alert_type": "negative_drift",
"message": "m", "severity": "warning", "now": FROZEN_NOW},
obs.add_alert("negative_drift", "m", "warning"), {"alerts": obs.alerts})
def c_add_critical(rec):
obs = fresh_obs()
rec("add-critical-severity", {"alerts": [], "alert_type": "promotion_stall",
"message": "stalled", "severity": "critical", "now": FROZEN_NOW},
obs.add_alert("promotion_stall", "stalled", "critical"), {"alerts": obs.alerts})
def c_add_onto_existing(rec):
pre = [{"type": "old", "message": "m0", "severity": "info",
"timestamp": ago(days=1), "acknowledged": True}]
obs = fresh_obs(pre)
rec("add-onto-existing", {"alerts": pre, "alert_type": "velocity",
"message": "second", "severity": "info", "now": FROZEN_NOW},
obs.add_alert("velocity", "second"), {"alerts": obs.alerts})
# ── get_unacknowledged_alerts ────────────────────────────────────────────────
def _pre_mixed():
return [
{"type": "a", "message": "m1", "severity": "info",
"timestamp": ago(days=3), "acknowledged": True},
{"type": "b", "message": "m2", "severity": "warning",
"timestamp": ago(days=2), "acknowledged": False},
{"type": "c", "message": "m3", "severity": "critical",
"timestamp": ago(days=1)}, # missing key → unacknowledged
]
def c_unacked_empty(rec):
obs = fresh_obs([])
rec("unacked-empty", {"alerts": []},
obs.get_unacknowledged_alerts(), {"unacked": []})
def c_unacked_mixed(rec):
pre = _pre_mixed()
obs = fresh_obs(pre)
rec("unacked-mixed", {"alerts": pre},
obs.get_unacknowledged_alerts(), {"unacked": obs.get_unacknowledged_alerts()})
def c_unacked_all_open(rec):
pre = [dict(_stamped("t", "m", "info"), timestamp=ago(days=1)) for _ in range(3)]
obs = fresh_obs(pre)
rec("unacked-all-open", {"alerts": pre},
obs.get_unacknowledged_alerts(), {"unacked": obs.get_unacknowledged_alerts()})
# ── acknowledge_alert ────────────────────────────────────────────────────────
def _ack_case(rec, name, index):
pre = _pre_mixed()
obs = fresh_obs(pre)
obs.acknowledge_alert(index)
changed = 0 <= index < len(pre)
rec(name, {"alerts": pre, "index": index},
None, {"alerts": obs.alerts, "changed": changed})
def c_ack_first(rec):
_ack_case(rec, "ack-first", 0)
def c_ack_second(rec):
_ack_case(rec, "ack-second", 1)
def c_ack_negative(rec):
_ack_case(rec, "ack-negative", -1)
def c_ack_at_len(rec):
_ack_case(rec, "ack-at-len", 3)
def c_ack_beyond(rec):
_ack_case(rec, "ack-beyond", 8)
# ── check_alerts ─────────────────────────────────────────────────────────────
def _check_case(rec, name, rows):
db = make_db(rows)
velocity = drift_core.compute_drift_velocity(db)
direction = drift_core.compute_drift_direction(db)
last = db.execute(_MAX_LAST_WASHED_SQL).fetchone()[0]
obs = fresh_obs([])
new = obs.check_alerts(db)
rec(name,
{"alerts": [], "velocity": velocity, "direction": direction,
"last_washed": last, "now": FROZEN_NOW},
new, {"new_alerts": new, "alerts": obs.alerts})
def c_check_empty_db(rec):
# Empty db: stability_ratio 0.0 < 0.1 — the negative-drift alert FIRES.
_check_case(rec, "check-empty-db-negative-drift", [])
def c_check_all_clear(rec):
rows = [row(rock="established", created=ago(days=30), washed=ago(days=1),
accessed=ago(hours=1)) for _ in range(10)]
_check_case(rec, "check-all-clear", rows)
def c_check_velocity_only(rec):
rows = [row(created=ago(days=1), washed=ago(days=1)) for _ in range(71)]
rows += [row(rock="established", created=ago(days=30), washed=ago(days=1))
for _ in range(30)]
_check_case(rec, "check-velocity-only", rows)
def c_check_negative_drift_only(rec):
rows = [row(rock="established", created=ago(days=30), washed=ago(days=1))]
rows += [row(created=ago(days=1), washed=ago(days=1)) for _ in range(19)]
_check_case(rec, "check-negative-drift-only", rows)
def c_check_stall_only(rec):
rows = [row(rock="established", created=ago(days=40), washed=ago(days=20))
for _ in range(10)]
_check_case(rec, "check-stall-only", rows)
def c_check_stall_boundary(rec):
rows = [row(rock="established", created=ago(days=40), washed=ago(days=14))
for _ in range(10)]
_check_case(rec, "check-stall-boundary-14d-no-alert", rows)
def c_check_stall_15(rec):
rows = [row(rock="established", created=ago(days=40), washed=ago(days=15))
for _ in range(10)]
_check_case(rec, "check-stall-15d-fires", rows)
def c_check_malformed_last_washed(rec):
# MAX picks "garbage" ('g' > '2'); oracle fromisoformat → ValueError skip.
rows = [row(rock="established", created=ago(days=30), washed="garbage")]
rows += [row(rock="established", created=ago(days=30), washed=ago(days=30))
for _ in range(9)]
_check_case(rec, "check-malformed-last-washed-skipped", rows)
def c_check_naive_last_washed(rec):
# Naive (no offset) MAX(last_washed): aware − naive → TypeError skip.
naive = (FROZEN_UTC - timedelta(days=14)).replace(tzinfo=None).isoformat()
rows = [row(rock="established", created=ago(days=30), washed=naive)]
rows += [row(rock="established", created=ago(days=30), washed=ago(days=30))
for _ in range(9)]
_check_case(rec, "check-naive-last-washed-skipped", rows)
def c_check_null_last_washed(rec):
# All-NULL MAX → falsy → skip.
rows = [row(rock="established", created=ago(days=30)) for _ in range(10)]
_check_case(rec, "check-null-last-washed-skipped", rows)
def c_check_empty_string_last_washed(rec):
# MAX = "" → falsy → the oracle's `if last_promo and last_promo[0]` skips.
rows = [row(rock="established", created=ago(days=30), washed="")
for _ in range(10)]
_check_case(rec, "check-empty-string-last-washed-skipped", rows)
def c_check_all_three(rec):
rows = [row(created=ago(days=1), washed=ago(days=1)) for _ in range(100)]
rows += [row(rock="established", created=ago(days=30), washed=ago(days=20))
for _ in range(3)]
_check_case(rec, "check-all-three", rows)
# ── run_retrospective ────────────────────────────────────────────────────────
def _retro_case(rec, name, rows, days):
db = make_db(rows)
cutoff = (FROZEN_UTC - timedelta(days=days)).isoformat()
counts = {
"new_entries": db.execute(
"SELECT COUNT(*) FROM entries WHERE created_at > ? AND status = 'active'",
(cutoff,)).fetchone()[0],
"washed_entries": db.execute(
"SELECT COUNT(*) FROM entries WHERE last_washed > ? AND status = 'active'",
(cutoff,)).fetchone()[0],
"promoted_entries": db.execute(
"SELECT COUNT(*) FROM entries WHERE rock_status != 'washable'"
" AND last_washed > ? AND status = 'active'",
(cutoff,)).fetchone()[0],
"decayed_entries": db.execute(
"SELECT COUNT(*) FROM entries WHERE status = 'deleted'"
" AND last_accessed > ?", (cutoff,)).fetchone()[0],
}
velocity = drift_core.compute_drift_velocity(db, days)
direction = drift_core.compute_drift_direction(db)
obs = fresh_obs([])
report = obs.run_retrospective(db, days)
inp = dict(counts, velocity=velocity, direction=direction, days=days,
now=FROZEN_NOW, now_local=FROZEN_LOCAL_ISO)
rec(name, inp, report,
{"report": report,
"filename": f"retrospective_{FROZEN_LOCAL.strftime('%Y%m%d_%H%M%S')}.json"})
def c_retro_positive(rec):
rows = [row(rock="established", created=ago(days=30), washed=ago(days=1))
for _ in range(10)]
rows.append(row(created=ago(days=30), status="deleted", accessed=ago(hours=2)))
_retro_case(rec, "retro-positive", rows, 7)
def c_retro_neutral_high_velocity(rec):
rows = [row(created=ago(days=1), washed=ago(days=1)) for _ in range(71)]
rows += [row(rock="established", created=ago(days=30), washed=ago(days=1))
for _ in range(40)]
_retro_case(rec, "retro-neutral-high-velocity", rows, 7)
def c_retro_neutral_low_velocity(rec):
rows = [row(rock="established", created=ago(days=30), washed=ago(days=30))
for _ in range(2)]
rows += [row(created=ago(days=30), washed=ago(days=30)) for _ in range(8)]
rows.append(row(status="deleted", accessed=ago(days=1)))
_retro_case(rec, "retro-neutral-low-velocity", rows, 7)
def c_retro_concerning(rec):
rows = [row(rock="established", created=ago(days=30), washed=ago(days=30))]
rows += [row(created=ago(days=30), washed=ago(days=30)) for _ in range(19)]
_retro_case(rec, "retro-concerning", rows, 7)
def c_retro_concerning_boundary(rec):
rows = [row(rock="established", created=ago(days=30), washed=ago(days=30))]
rows += [row(created=ago(days=30), washed=ago(days=30)) for _ in range(9)]
_retro_case(rec, "retro-concerning-boundary-ratio-0.1", rows, 7)
def c_retro_velocity_boundary(rec):
rows = [row(created=ago(days=1), washed=ago(days=1)) for _ in range(70)]
rows += [row(rock="established", created=ago(days=30), washed=ago(days=30))
for _ in range(40)]
_retro_case(rec, "retro-positive-velocity-boundary-10", rows, 7)
def c_retro_custom_days(rec):
rows = [row(created=ago(days=1), washed=ago(days=1)) for _ in range(5)]
rows += [row(rock="established", created=ago(days=30), washed=ago(days=2))
for _ in range(2)]
rows.append(row(status="deleted", accessed=ago(days=2)))
_retro_case(rec, "retro-custom-days-3", rows, 3)
def c_retro_empty_db(rec):
_retro_case(rec, "retro-empty-db-concerning", [], 7)
def c_retro_default_days(rec):
rows = [row(created=ago(days=2), washed=ago(days=2)) for _ in range(3)]
_retro_case(rec, "retro-default-days-7", rows, 7)
# ── driver ───────────────────────────────────────────────────────────────────
# ── residue groups: _load_alerts / _save_alerts / _do_core / main ──────────
def c_load_alerts(rec):
"""The oracle's `_load_alerts` METHOD law via the ALERTS_FILE seam:
missing → [], JSONDecodeError → [], valid document → the list."""
import tempfile as _tf
def with_file(text):
tmp = _tf.mkdtemp(prefix="do_load_")
oracle_mod.ALERTS_FILE = os.path.join(tmp, "drift_alerts.json")
if text is not None:
with open(oracle_mod.ALERTS_FILE, "w") as f:
f.write(text)
return oracle_mod.DriftObservability()._load_alerts()
got = with_file(None)
rec("load-missing-file", {"text": None}, got, got)
got = with_file("{corrupt json")
rec("load-corrupt-json", {"text": "{corrupt json"}, got, got)
got = with_file("[]")
rec("load-empty-array", {"text": "[]"}, got, got)
doc = json.dumps([
_stamped("high_velocity", "v up", "warning"),
{"type": "old", "message": "m0", "severity": "info",
"timestamp": ago(days=1), "acknowledged": True},
], indent=2)
got = with_file(doc)
rec("load-two-alerts", {"text": doc}, got, got)
got = with_file("{}")
rec("load-non-array-doc", {"text": "{}"}, got, got)
def c_save_alerts(rec):
"""The oracle's `_save_alerts` bytes law: json.dumps(alerts, indent=2);
the FILE write stays facade-side — the rig reads the file back."""
import tempfile as _tf
def save_and_read(alerts):
tmp = _tf.mkdtemp(prefix="do_save_")
oracle_mod.ALERTS_FILE = os.path.join(tmp, "drift_alerts.json")
obs = oracle_mod.DriftObservability()
obs.alerts = copy.deepcopy(alerts)
obs._save_alerts()
with open(oracle_mod.ALERTS_FILE) as f:
return f.read()
alerts = [
_stamped("high_velocity", "café ✓ unicode", "warning"),
{"type": "old", "message": "m0", "severity": "info",
"timestamp": ago(days=1), "acknowledged": True},
]
got = save_and_read(alerts)
rec("save-two-alerts-indent2", {"alerts": alerts}, None, got)
got = save_and_read([])
rec("save-empty-list", {"alerts": []}, None, got)
def c_probe(rec):
for name, pin in [("pin-python", "python"), ("pin-auto", "auto"),
("pin-other-resolves", "rust"),
("pin-unset-defaults-auto", None)]:
old = os.environ.get("RUNE_DO_CORE")
if pin is None:
os.environ.pop("RUNE_DO_CORE", None)
else:
os.environ["RUNE_DO_CORE"] = pin
try:
resolved = oracle_mod._do_core() is not None
finally:
if old is None:
os.environ.pop("RUNE_DO_CORE", None)
else:
os.environ["RUNE_DO_CORE"] = old
rec(f"probe-{name}", {"pin": pin}, resolved, {"resolved": resolved})
# main-rig seam constants (deterministic; the Rust replay input mirrors
# them one-for-one)
M_VEL_HOT = {"changes_per_day": 12, "promotions_per_day": 3, "alert": True}
M_VEL_CALM = {"changes_per_day": 4.5, "promotions_per_day": 1.5, "alert": False}
M_DIR_STABLE = {"total_entries": 21, "established_count": 9, "rock_count": 5,
"stability_ratio": 2 / 3, "direction": "stabilizing"}
M_DIR_WOBBLY = {"total_entries": 20, "established_count": 1, "rock_count": 1,
"stability_ratio": 0.05, "direction": "destabilizing"}
M_COUNTS = {"new_entries": 4, "washed_entries": 2, "promoted_entries": 1,
"decayed_entries": 0}
M_LAST_WASHED = ago(days=20) # > PROMOTION_STALL_DAYS → stall alert fires
class _FakeCursor:
def __init__(self, row):
self._row = row
def fetchone(self):
return self._row
class _FakeDB:
def __init__(self, last_washed, counts):
self._lw = last_washed
self._c = counts
def execute(self, sql, params=()):
if sql.strip().upper().startswith("SELECT MAX("):
return _FakeCursor((self._lw,))
if "created_at >" in sql:
return _FakeCursor((self._c["new_entries"],))
if "status = 'deleted'" in sql or "status = \"deleted\"" in sql:
return _FakeCursor((self._c["decayed_entries"],))
if "rock_status != 'washable'" in sql:
return _FakeCursor((self._c["promoted_entries"],))
if "last_washed >" in sql:
return _FakeCursor((self._c["washed_entries"],))
return _FakeCursor((0,))
def close(self):
pass
def _run_oracle_main(argv, alerts_seed, velocity, direction, last_washed,
counts):
"""Patch the seams (memory_store/drift_core modules, ALERTS_FILE,
RETROSPECTIVES_DIR, clock already frozen), run the REAL oracle main(),
return (exit, stdout, stderr, state)."""
import contextlib
import io
import types
tmp = tempfile.mkdtemp(prefix="do_main_")
oracle_mod.ALERTS_FILE = os.path.join(tmp, "drift_alerts.json")
oracle_mod.RETROSPECTIVES_DIR = os.path.join(tmp, "retrospectives")
if alerts_seed is not None:
with open(oracle_mod.ALERTS_FILE, "w") as f:
f.write(alerts_seed)
fake_ms = types.ModuleType("memory_store")
fake_ms.connect = lambda: _FakeDB(last_washed, counts)
fake_dc = types.ModuleType("drift_core")
fake_dc.compute_drift_velocity = lambda db, days=None: copy.deepcopy(velocity)
fake_dc.compute_drift_direction = lambda db: copy.deepcopy(direction)
saved = {k: sys.modules.get(k) for k in ("memory_store", "drift_core")}
sys.modules["memory_store"] = fake_ms
sys.modules["drift_core"] = fake_dc
old_argv = sys.argv
sys.argv = ["drift_observability.py"] + list(argv)
buf_out, buf_err = io.StringIO(), io.StringIO()
code = 0
try:
with contextlib.redirect_stdout(buf_out), contextlib.redirect_stderr(buf_err):
try:
oracle_mod.main()
except SystemExit as e:
code = e.code if isinstance(e.code, int) else 0
finally:
sys.argv = old_argv
for k, v in saved.items():
if v is None:
sys.modules.pop(k, None)
else:
sys.modules[k] = v
alerts_after = None
if os.path.exists(oracle_mod.ALERTS_FILE):
with open(oracle_mod.ALERTS_FILE) as f:
alerts_after = f.read()
retro = None
if os.path.isdir(oracle_mod.RETROSPECTIVES_DIR):
names = sorted(os.listdir(oracle_mod.RETROSPECTIVES_DIR))
if names:
with open(os.path.join(oracle_mod.RETROSPECTIVES_DIR, names[0])) as f:
retro = {"filename": names[0], "report": json.load(f)}
return {"exit": code, "stdout": buf_out.getvalue(),
"stderr": buf_err.getvalue(), "alerts_file": alerts_after,
"retro": retro}
_SEED_ALERTS = json.dumps([
_stamped("high_velocity", "v up", "warning"),
{"type": "old", "message": "m0", "severity": "info",
"timestamp": ago(days=1), "acknowledged": True},
], indent=2)
def _main_case(rec, name, argv, seed=None, velocity=None, direction=None,
last_washed=None, counts=None):
velocity = M_VEL_CALM if velocity is None else velocity
direction = M_DIR_STABLE if direction is None else direction
counts = M_COUNTS if counts is None else counts
got = _run_oracle_main(argv, seed, velocity, direction, last_washed,
counts)
rec(f"main-{name}",
{"argv": list(argv), "alerts_text": seed, "velocity": velocity,
"direction": direction, "last_washed": last_washed,
"counts": counts, "now": FROZEN_NOW, "now_local": FROZEN_LOCAL_ISO},
None, got)
def c_main(rec):
_main_case(rec, "no-cmd-help-exit-1", [])
_main_case(rec, "help-flag-exit-0", ["--help"])
_main_case(rec, "invalid-choice-exit-2", ["bogus"])
_main_case(rec, "check-two-alerts-velocity-and-stall", ["check"],
velocity=M_VEL_HOT, last_washed=M_LAST_WASHED)
_main_case(rec, "check-no-alerts", ["check"])
_main_case(rec, "check-negative-drift", ["check"], direction=M_DIR_WOBBLY)
_main_case(rec, "check-onto-seeded-alerts", ["check"], seed=_SEED_ALERTS,
velocity=M_VEL_HOT, last_washed=M_LAST_WASHED)
_main_case(rec, "retrospective-default-days", ["retrospective"])
_main_case(rec, "retrospective-days-30", ["retrospective", "--days", "30"])
_main_case(rec, "retrospective-days-eq", ["retrospective", "--days=14"])
_main_case(rec, "retrospective-bad-days-exit-2",
["retrospective", "--days", "zz"])
_main_case(rec, "alerts-empty", ["alerts"])
_main_case(rec, "alerts-two-unacked", ["alerts"], seed=_SEED_ALERTS)
_main_case(rec, "alerts-all-acked", ["alerts"], seed=json.dumps([
{"type": "a", "message": "m", "severity": "info",
"timestamp": ago(days=1), "acknowledged": True}], indent=2))
_main_case(rec, "acknowledge-first", ["acknowledge", "0"],
seed=_SEED_ALERTS)
_main_case(rec, "acknowledge-beyond-len-noop", ["acknowledge", "9"],
seed=_SEED_ALERTS)
_main_case(rec, "acknowledge-missing-index-exit-2", ["acknowledge"])
_main_case(rec, "acknowledge-bad-int-exit-2", ["acknowledge", "z"])
_main_case(rec, "dashboard", ["dashboard"], velocity=M_VEL_HOT)
_main_case(rec, "dashboard-unicode-trim", ["dashboard"], seed=_SEED_ALERTS,
velocity=M_VEL_CALM, direction=M_DIR_WOBBLY)
ADD = [c_add_default, c_add_warning, c_add_critical, c_add_onto_existing]
UNACKED = [c_unacked_empty, c_unacked_mixed, c_unacked_all_open]
ACK = [c_ack_first, c_ack_second, c_ack_negative, c_ack_at_len, c_ack_beyond]
CHECK = [c_check_empty_db, c_check_all_clear, c_check_velocity_only,
c_check_negative_drift_only, c_check_stall_only, c_check_stall_boundary,
c_check_stall_15, c_check_malformed_last_washed, c_check_naive_last_washed,
c_check_null_last_washed, c_check_empty_string_last_washed,
c_check_all_three]
RETRO = [c_retro_positive, c_retro_neutral_high_velocity,
c_retro_neutral_low_velocity, c_retro_concerning,
c_retro_concerning_boundary, c_retro_velocity_boundary,
c_retro_custom_days, c_retro_empty_db, c_retro_default_days]
GROUPS = [("add_alert", ADD), ("get_unacknowledged_alerts", UNACKED),
("acknowledge_alert", ACK), ("check_alerts", CHECK),
("run_retrospective", RETRO),
("load_alerts", [c_load_alerts]), ("save_alerts", [c_save_alerts]),
("probe", [c_probe]), ("main", [c_main])]
# lib-level twins + the CLI dispatcher: no FFI symbol (the facade owns the
# file IO / argparse surface); battery-replayed from the frozen oracle rows
BATTERY_ONLY_GROUPS = {"load_alerts", "save_alerts", "probe", "main"}
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 json.dumps(got, sort_keys=True) != json.dumps(want, sort_keys=True):
print(f"FACADE DIVERGE [{group}] {name} {key}")
print(" got: ", json.dumps(got, sort_keys=True)[:600])
print(" want:", json.dumps(want, sort_keys=True)[: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)
# Kernel-level: the Rust core must reproduce the frozen expected
# from the frozen input even WITHOUT the facade in the loop. The
# loader unwraps the doc-envelope for the list-returning calls.
unwrap_want = {
"add_alert": lambda w: w["alerts"],
"get_unacknowledged_alerts": lambda w: w["unacked"],
"acknowledge_alert": lambda w: w,
"check_alerts": lambda w: w,
"run_retrospective": lambda w: w,
}
failures = 0
for group, cases in frozen.items():
if group in BATTERY_ONLY_GROUPS:
continue
for case in cases:
got = getattr(do_loader, group)(**copy.deepcopy(case["input"]))
want = unwrap_want[group](case["expected"])
if json.dumps(got, sort_keys=True) != json.dumps(want, sort_keys=True):
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 {total - failures}/{total}")
return 1 if (failures or facade_failures) else 0
doc = {
# deterministic stamp (regen x2 must be byte-identical)
"frozen": FROZEN_NOW,
"oracle": "src/rune/drift_observability.py",
"pin": "RUNE_DO_CORE=python",
"note": "Frozen via scripts/gen_drift_observability_truth.py against "
"the live Python oracle; wall clock frozen at "
+ FROZEN_NOW + ". Battery embeds this VERBATIM.",
"cases": groups,
}
os.makedirs(os.path.dirname(TRUTH_PATH), exist_ok=True)
with open(TRUTH_PATH, "w") as f:
# insertion order preserved: alert/row dict key order IS the truth
# the _save_alerts renderer replays (sort_keys would lie about it)
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())