Files
rune/scripts/gen_inference_trace_gap_truth.py
T
Nick a3b6544be8 feat(inference_trace): close PARTIAL gaps — dichotomy wave
audit 4/6 PARTIAL -> 8/8 FULL (RUST). The landed FULL port (b5228ace +
e41562aa) left record_trace/read_traces as facade-side IO by its strangler
verdict; this close ports them name-preserving with the file IO itself in
the kernel (mkdir, I1 source-guard rotation replace chain, O_APPEND write,
file reads; path RESOLUTION stays the _trace_path seam the tests pin, and
the facade passes module rotation knobs read at call time so the
TRACE_ROTATE_BYTES monkeypatch contract survives). FFI it_record_trace /
it_read_traces + it_loader wrappers + byte-identical _py_record_trace /
_py_read_traces fallbacks (RUNE_IT_CORE=python pin).

Fix-first (proved by frozen truth): (1) serialize/format_record ensure_ascii
divergence — json.dumps escapes non-ASCII as \uXXXX (astral = surrogate
pairs), serde emitted raw UTF-8; py_escape emitter added for both shapes
(quirk #24, extends the context_broker pyDumpsSorted law). (2) limit=0 —
Python lines[-0:] keeps ALL lines, rev().take(0) returned none; read_select
+ cli_tail fixed (quirk #25). (3) malformed JSONL line silently skipped by
read_select where the oracle raises ValueError — now an Err through the FFI
envelope so the facade fallback re-raises the AUTHENTIC exception (quirk
#26; crash class pinned in truth).

Frozen truth: 17-case gap corpus via the shared freeze_truth.py harness +
scripts/it_freeze_seams rig (RUNE_IT_CORE=python, relative RUNE_HOME,
cwd-is-the-rig, row-private it_t stores; record/read branches incl.
rotation matrix + unicode line law + limit 0/2/99 + missing stores +
ValueError class + round-trip). gen x2 + --verify x2 byte-identical.
Battery: gap_battery.rs replays rows VERBATIM in a throwaway cwd (cargo
test 9/9: old 6 + new 3). Live parity scripts/check_inference_trace_parity
.py: seam 17/17 + FFI composites 17/17. Landed PARITY=1 flow preserved
(byte-identical modulo the original freeze's baked worktree root). cargo
build/clippy -D warnings/fmt clean. Python suite both pins 108/108 live +
108/108 RUNE_IT_CORE=python (p1_03 memory_selection failures pre-exist at
pristine HEAD, outside this port's cone). Audit: FULL 65% (125/192).

Evidence: verification/it-*.exit + summary-inference_trace.md (logs local,
*.log gitignored).
2026-10-14 20:58:18 +01:00

159 lines
7.2 KiB
Python

#!/usr/bin/env python3
"""Freeze inference_trace GAP truth (dichotomy wave #2479 gap-close,
worktree rune-wave-dk; shared harness scripts/freeze_truth.py + rig
scripts/it_freeze_seams).
The landed port (b5228ace + e41562aa) froze the kernel-shaped surface
(price_for, path resolution, serialization, rotation verdicts, read
selection counts, CLI tail) in frozen_it_truth.json. This gap truth
covers the two audit-missing IO functions — record_trace and read_traces
— through the module's JSON row runners (record_trace_json /
read_traces_json), with REAL file IO in cwd-relative row-private stores:
record_trace_json rows
fresh explicit dir (auto-created), append onto an existing store,
default <rune_home>/state resolution, rotation at row-pinned
rotate_bytes (basic shift, full chain, exact-boundary no-rotate,
under-boundary no-rotate, source-guard when a middle slot is
missing), and the v5-full record with UNICODE field values (the
json.dumps ensure_ascii line-bytes law).
read_traces_json rows
all-lines selection across blank lines, limit trims (2, 0 — the
lines[-0:] == all-lines quirk, 99), missing explicit store, missing
default-dir store, the malformed-line ValueError crash class, and a
record→read round-trip.
Layout law: every row family gets its own it_t/<name> store (or its own
rune_home hole) so rows are order-independent replays. RUNE_HOME is the
relative "it_rig_home" (rig) — no absolute paths in truth. No clock: the
oracle has no time inputs.
Output: src/rust/inference_trace/src/frozen_it_gap_truth.json
(harness array schema: [{fn, args, kwargs, expected}] — embedded VERBATIM
by src/rust/inference_trace/src/gap_battery.rs).
"""
from __future__ import annotations
import json
import sys
from pathlib import Path
REPO = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO / "scripts"))
from freeze_truth import freeze, write # noqa: E402
OUT = REPO / "src" / "rust" / "inference_trace" / "src" / "frozen_it_gap_truth.json"
def mk(**over) -> dict:
base = dict(
schema_version=5, provider="ollama", model="qwen3:14b",
task_id="T42", channel="chat", resolved_context_window=32768,
input_budget=24000, model_calls=2, prompt_tokens_estimated=5150,
prompt_tokens_served=5102, output_tokens=733, latency_ms=8123.4,
model_time_ms=6210.9,
per_block_tokens={"constitution": 412, "project": 1300},
dropped_blocks=[{"name": "human", "tokens": 88}],
tools_exposed=["read", "edit"], memories_exposed=["constitution"],
memory_tokens=1712, degraded=[], cache=None, cost_usd=None,
cost_basis="local-unpriced", success=True, error="",
)
base.update(over)
return base
def seed(path: str, content: str) -> dict:
return {"op": "seed_file", "path": path, "content": content}
cases = []
# ── record_trace_json: append + resolution ──────────────────────────────
cases += [
("record_trace_json", [mk(), "it_t/r1"], {}),
("record_trace_json", [mk(task_id="R2"), "it_t/r2"], {
"prestate": [seed("it_t/r2/inference_traces.jsonl",
json.dumps(mk(task_id="R0"), sort_keys=True,
separators=(",", ":")) + "\n")]}),
("record_trace_json", [mk(task_id="R3"), None],
{"rune_home": "it_rig_home"}),
]
# ── record_trace_json: rotation (row-pinned rotate_bytes) ───────────────
cases += [
# basic: oversized live file shifts to .1, fresh file carries the line
("record_trace_json", [mk(task_id="R4"), "it_t/r4"],
{"rotate_bytes": 200,
"prestate": [seed("it_t/r4/inference_traces.jsonl", "x" * 250)]}),
# full chain: current→.1, .1→.2, .2→.3 (every source exists)
("record_trace_json", [mk(task_id="R5"), "it_t/r5"],
{"rotate_bytes": 200,
"prestate": [seed("it_t/r5/inference_traces.jsonl", "x" * 250),
seed("it_t/r5/inference_traces.jsonl.1", "AAA\n"),
seed("it_t/r5/inference_traces.jsonl.2", "BBB\n")]}),
# exact boundary: size == rotate_bytes is NOT greater → append, no shift
("record_trace_json", [mk(task_id="R6"), "it_t/r6"],
{"rotate_bytes": 200,
"prestate": [seed("it_t/r6/inference_traces.jsonl", "z" * 199 + "\n")]}),
# under boundary
("record_trace_json", [mk(task_id="R7"), "it_t/r7"],
{"rotate_bytes": 200,
"prestate": [seed("it_t/r7/inference_traces.jsonl", "y" * 150 + "\n")]}),
# source-guard: .2 exists but .1 missing → .2→.3 fires, .1→.2 skipped
# (dest .2 survives), current→.1 fires
("record_trace_json", [mk(task_id="R9"), "it_t/r9"],
{"rotate_bytes": 200,
"prestate": [seed("it_t/r9/inference_traces.jsonl", "x" * 250),
seed("it_t/r9/inference_traces.jsonl.2", "BBB\n")]}),
]
# ── record_trace_json: v5-full + unicode (ensure_ascii line law) ────────
cases += [
("record_trace_json", [mk(
task_id="Ür-42 🚀", routing_reason="tier:heiß", routing_mode="local",
task_family="Über-möde ✗", selected_tools=["read", "größer"],
capability_reason="allowlist-✓", find_capability_calls=1,
capsule_messages=[{"role": "user", "content": "héllo wörld — ✓"}],
capsule_content_hashes={"verfassung": "a" * 64},
capsule_token_count=5150,
memory_candidates=9, memory_selected=2, memory_abstained=False,
memory_types_queried=["projekt"],
error="zeitüberschreitung — ✗", success=False,
degraded=["speicher"], model_calls=1, output_tokens=0,
), "it_t/r8"], {}),
]
# ── read_traces_json: selection, limits, missing, crash class ───────────
LINES = [json.dumps(mk(task_id=f"W{i}"), sort_keys=True,
separators=(",", ":")) for i in range(5)]
RAW = "\n".join(LINES[:3]) + "\n\n\n" + "\n".join(LINES[3:]) + "\n"
STORE = "it_t/w1/inference_traces.jsonl"
PRE_RAW = [seed(STORE, RAW)]
cases += [
("read_traces_json", ["it_t/w1"], {"limit": None, "prestate": PRE_RAW}),
("read_traces_json", ["it_t/w2"], {"limit": 2, "prestate": [
seed("it_t/w2/inference_traces.jsonl", RAW)]}),
# limit=0: Python lines[-0:] == ALL lines (quirk row)
("read_traces_json", ["it_t/w3"], {"limit": 0, "prestate": [
seed("it_t/w3/inference_traces.jsonl", RAW)]}),
("read_traces_json", ["it_t/w4"], {"limit": 99, "prestate": [
seed("it_t/w4/inference_traces.jsonl", RAW)]}),
("read_traces_json", ["it_t/nowhere"], {"limit": None}),
("read_traces_json", [None], {"rune_home": "it_rig_hole", "limit": 2}),
# malformed line → ValueError crash class (message rides the fallback)
("read_traces_json", ["it_t/w7"], {"limit": None, "prestate": [
seed("it_t/w7/inference_traces.jsonl",
LINES[0] + "\n" + "not json {" + "\n" + LINES[1] + "\n")]}),
# round-trip: seeds written as the recorder would → parsed records
("read_traces_json", ["it_t/w8"], {"limit": None, "prestate": [
seed("it_t/w8/inference_traces.jsonl",
LINES[0] + "\n" + LINES[4] + "\n")]}),
]
truth = freeze("rune.inference_trace", cases,
oracle_module="rune.inference_trace")
write(truth, OUT)
print(f"wrote {len(truth)} cases -> {OUT}")