Files
rune/scripts/gen_execution_trace_truth.py
Nick 0f4a3fce6f feat(execution_trace): literal-100% residue — dichotomy wave
Port the last audit-missing fn name-preserving: _journal_path, the
facade HOME-seam twin (expanduser env-read stays facade; the twin is
the posixpath join law over its output — exactly one separating
slash). Truth +5 journal_path cases (root-slash/empty/relative/
trailing-slash HOME quirks frozen from the live oracle); existing
groups byte-stable. Battery 4/4 green incl. replay_journal_path;
live parity 820/820; clippy -D warnings clean; adjacent pytest 9/9
BOTH pins. Fn coverage 3/4 -> 4/4.
2026-10-15 05:30:37 +01:00

209 lines
7.9 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)
# ── _journal_path: HOME seam + posixpath join law ──────────────────────────
# The oracle reads expanduser (HOME env); each case patches HOME, captures
# BOTH the expanduser output (the twin's input) and the oracle's full path.
cases_jp = []
def case_jp(name, home):
import posixpath
old = os.environ.get("HOME")
os.environ["HOME"] = home
try:
expanded = posixpath.expanduser("~/.rune")
got = et._journal_path()
finally:
if old is None:
os.environ.pop("HOME", None)
else:
os.environ["HOME"] = old
cases_jp.append({"name": name, "home": home, "input": expanded,
"expect": got})
case_jp("home-normal", "/home/nick")
case_jp("home-root-slash-double-slash-quirk", "/")
case_jp("home-empty-string", "")
case_jp("home-relative", "rel/base")
case_jp("home-trailing-slash", "/x/")
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,
"journal_path_cases": cases_jp,
}
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}")