Files
rune/scripts/gen_execution_trace_truth.py
T
Nick 4bda61cdc5 feat(execution_trace): port to FULL Rust — dichotomy wave
Language verdict: RUST per docs/language-dichotomy-ledger.md (W6 law —
deterministic record assembly with many fields; the journal FILE I/O
stays host-side per Law 7, the parse + receipt-assembly laws cross FFI).

- et_read_outcome_events/et_build_receipt/et_trace_task doc-envelope FFI
  (et_* symbols; free via capability_scoring cs_free_string — no free
  re-export); et_loader mirroring broker_loader.py.
- Facade delegation with RUNE_ET_CORE=python pin; kernel floor on any
  kernel error.
- Python laws replicated: malformed-line skip, falsy task_id skip,
  duplicate task_id last-wins, assigned_model→payload.model falsy
  chain, payload-status-key-present (even null) law, completed_at
  fallback, task_record or {task_id} falsy replacement, None-None→null.
- Fuzz divergence caught pre-landing: the oracle CRASHES (AttributeError)
  on non-object journal lines ([1,2], 5, "x") — kernel now errors
  (AttributeError envelope) so the facade reproduces the oracle crash
  identically instead of silently skipping.
- 20-case frozen oracle truth (RUNE_ET_CORE=python pinned, deep-copied
  inputs, every public function + branch) embedded in the crate and
  replayed VERBATIM by the branch battery; live parity 820/820 (20
  frozen + 800 fuzz, seed 2479); pytest 24 passed BOTH ways
  (RUNE_ET_CORE=python and auto); clippy -D warnings clean.
2026-10-13 03:06:44 +01:00

180 lines
7.0 KiB
Python

#!/usr/bin/env python3
"""Freeze the execution_trace oracle truth (dichotomy wave, #2479).
Generator law: RUNE_ET_CORE=python pinned, every input deep-copied, every
public function exercised across ALL branches:
* build_receipt — defaults, assigned_model vs payload.model,
outcome from payload.status vs task.status, completed_at fallbacks
* _read_outcome_events — empty journal, malformed lines, foreign events,
empty task_id, duplicate task_id (last wins), missing file
* trace_task — no outcome + no record (None), journal-only, record-only,
both, missing journal with record
"""
import copy
import json
import os
import sys
import tempfile
from pathlib import Path
REPO = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO / "src"))
sys.path.insert(0, str(REPO / "src" / "rune"))
os.environ["RUNE_ET_CORE"] = "python"
import execution_trace as et # noqa: E402
cases_build = []
cases_read = []
cases_trace = []
def case_build(name, task, payload):
task = copy.deepcopy(task)
payload = copy.deepcopy(payload)
cases_build.append({
"name": name,
"args": {"task": task, "outcome_payload": payload},
"expect": et.build_receipt(copy.deepcopy(task), copy.deepcopy(payload)),
})
def case_read(name, lines):
lines = copy.deepcopy(lines)
if lines is None:
# missing file branch (OSError) — facade-level, no kernel lines
fd, path = tempfile.mkstemp(suffix=".jsonl")
os.close(fd)
os.unlink(path)
expect = et._read_outcome_events(path)
else:
with tempfile.NamedTemporaryFile("w", suffix=".jsonl",
delete=False, encoding="utf-8") as f:
f.write("\n".join(lines) + "\n")
path = f.name
expect = et._read_outcome_events(path)
cases_read.append({
"name": name,
"lines": lines,
"expect": expect,
})
def case_trace(name, task_id, task_record, lines):
task_id = copy.deepcopy(task_id)
task_record = copy.deepcopy(task_record)
lines = copy.deepcopy(lines)
if lines is None:
fd, path = tempfile.mkstemp(suffix=".jsonl")
os.close(fd)
os.unlink(path)
else:
with tempfile.NamedTemporaryFile("w", suffix=".jsonl",
delete=False, encoding="utf-8") as f:
f.write("\n".join(lines) + "\n")
path = f.name
expect = et.trace_task(task_id, copy.deepcopy(task_record), path)
cases_trace.append({
"name": name,
"args": {"task_id": task_id, "task_record": task_record,
"lines": lines},
"expect": expect,
})
# ── build_receipt: every branch ─────────────────────────────────────────────
case_build("minimal-task", {}, None)
case_build("full-task-no-payload", {
"task_id": "t1", "description": "do the thing", "status": "running",
"assigned_model": "qwen2.5:3b", "memories_used": ["m1", "m2"],
"rules_used": ["r1"], "capability": "forge", "actions": ["a", "b"],
"completed_at": "2026-10-13T00:00:00Z",
}, None)
case_build("payload-fills-gaps", {
"task_id": "t2", "description": "", "status": "done",
}, {"model": "qwen2.5:7b", "status": "done", "completed_at": "2026-10-13T01:00:00Z"})
case_build("assigned-model-wins", {
"task_id": "t3", "status": "running", "assigned_model": "local",
}, {"model": "cloud", "status": "running"})
case_build("task-completed-at-wins", {
"task_id": "t4", "status": "done", "completed_at": "T-task",
}, {"status": "done", "completed_at": "T-payload"})
case_build("empty-payload", {"task_id": "t5", "status": "done"}, {})
case_build("empty-status-no-payload", {"task_id": "t6"}, None)
# ── _read_outcome_events: every branch ──────────────────────────────────────
case_read("empty-journal", [])
case_read("single-outcome", [
json.dumps({"event_type": "task.outcome",
"payload": {"task_id": "t1", "status": "done"}}),
])
case_read("malformed-lines-skipped", [
"{not json",
"",
json.dumps({"event_type": "task.outcome",
"payload": {"task_id": "t2", "status": "done"}}),
])
case_read("foreign-events-skipped", [
json.dumps({"event_type": "task.started",
"payload": {"task_id": "t3", "status": "running"}}),
json.dumps({"event_type": "task.outcome",
"payload": {"task_id": "t4", "status": "done"}}),
json.dumps({"event_type": "task.outcome"}),
])
case_read("empty-task-id-skipped", [
json.dumps({"event_type": "task.outcome",
"payload": {"task_id": "", "status": "done"}}),
json.dumps({"event_type": "task.outcome",
"payload": {"status": "done"}}),
json.dumps({"event_type": "task.outcome",
"payload": {"task_id": "t5", "status": "done"}}),
])
case_read("duplicate-task-id-last-wins", [
json.dumps({"event_type": "task.outcome",
"payload": {"task_id": "t6", "status": "first"}}),
json.dumps({"event_type": "task.outcome",
"payload": {"task_id": "t6", "status": "second"}}),
])
case_read("missing-file", None)
# ── trace_task: every branch ────────────────────────────────────────────────
JOURNAL = [
json.dumps({"event_type": "task.outcome",
"payload": {"task_id": "t1", "status": "done",
"model": "qwen2.5:3b",
"completed_at": "2026-10-13T02:00:00Z"}}),
json.dumps({"event_type": "task.outcome",
"payload": {"task_id": "t2", "status": "failed"}}),
]
case_trace("no-outcome-no-record", "t9", None, JOURNAL)
case_trace("journal-only", "t1", None, JOURNAL)
case_trace("record-only", "t9", {
"task_id": "t9", "description": "offline", "status": "running",
"assigned_model": "local", "memories_used": [], "rules_used": [],
"capability": "", "actions": [], "completed_at": "",
}, JOURNAL)
case_trace("both-record-and-journal", "t1", {
"task_id": "t1", "description": "both", "status": "running",
"assigned_model": "", "memories_used": ["m"], "rules_used": [],
"capability": "forge", "actions": ["go"], "completed_at": "",
}, JOURNAL)
case_trace("missing-journal-with-record", "t9", {
"task_id": "t9", "status": "done",
}, None)
case_trace("empty-record-falsy-law", "t2", {}, JOURNAL)
truth = {
"module": "execution_trace",
"core_pin": "RUNE_ET_CORE=python",
"build_receipt_cases": cases_build,
"read_outcome_events_cases": cases_read,
"trace_task_cases": cases_trace,
}
out = REPO / "src" / "rust" / "execution_trace" / "frozen_et_truth.json"
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(json.dumps(truth, indent=1, sort_keys=True) + "\n",
encoding="utf-8")
n = len(cases_build) + len(cases_read) + len(cases_trace)
print(f"frozen {n} cases -> {out}")