Files
rune/scripts/gen_construction_pattern_harness_truth.py
Nick 2c273574a4 feat(construction_pattern): close PARTIAL gaps to FULL — dichotomy wave
Audit PARTIAL 7/13 -> FULL 13/13 (headline 74/192, fn 1358/2278).

Ported: _need_dict (FFI need envelope, wired into cp_evaluate/cp_derive),
_surface_text (evidence token union, set semantics). Renamed to exact
Python names per the name-preserving law: _path_matches, _entity_matches,
_obligation_when_hit (were path_matches/entity_matches/obligation_when_hit)
and the evaluate_applicability _check closure — same bodies, exact names;
precedent: structural_store _sorted/_ss_core, construction_decision _sc_core.

Truth: frozen_cp_truth.json 70->96 cases (path_match/entity_match/
need_dict/surface_text/when_hit families, incl. re.split empty-quirk and
truthy-not-True always cases); harness surface frozen_truth.json 18 cases
(from_dict/revise stay in the bespoke battery — bare instances are not
harness-serializable). Battery 14 tests replay all 96 VERBATIM.

Verification (verification/summary.md, all exit 0): battery 14/14, clippy
0 warnings, harness verify 18/18, live parity 192/192 both pins (new
check_construction_pattern_parity.py; class ops via cp_loader under the
kernel pin), pytest 30/30 module + 20/20 consumers under
RUNE_CP_CORE=python and auto.
2026-10-13 18:30:24 +01:00

111 lines
4.7 KiB
Python

#!/usr/bin/env python3
"""Freeze construction_pattern oracle truth through the SHARED harness
(scripts/freeze_truth.py) — dichotomy wave #2479 gap-close, worktree
rune-wave-cb.
Complements frozen_cp_truth.json (the full bespoke battery incl.
evaluate/derive, which need live duck-typed Need objects the bare harness
cannot rebuild). This file pins the harness-freezable surface:
_path_matches / _entity_matches (the new audit-named kernels, directly)
record_pattern_proposal (valid rows — bounds errors crash the
harness and stay in the bespoke file)
combine_pattern_obligations
ConstructionPattern.to_dict (recv-rebuilt; from_dict/revise return
bare instances the harness cannot
serialize — bespoke battery covers them)
Verify byte-identical against the live oracle:
PYTHONPATH=src python3 scripts/freeze_truth.py --verify \
src/rust/construction_pattern/frozen_truth.json \
--module rune.construction_pattern
"""
from __future__ import annotations
import os
import sys
from pathlib import Path
os.environ["RUNE_CP_CORE"] = "python" # POISONED-TRUTH LAW: freeze the ORACLE
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
from freeze_truth import freeze, write # noqa: E402
from rune import construction_pattern as cp # noqa: E402
OUT = Path(__file__).resolve().parents[1] / "src" / "rust" / "construction_pattern" / "frozen_truth.json"
MATCHERS = [
("_path_matches", ("tui", "src/rune/rune_tui.py")),
("_path_matches", ("ui", "src/rune/rune_tui.py")),
("_path_matches", ("ui", "src/rune/builtin.py")),
("_path_matches", ("deploy", "scripts/deploy_stage.py")),
("_path_matches", ("", "/abc")),
("_path_matches", ("", "abc")),
("_entity_matches", ("ui:", "ui:chat")),
("_entity_matches", ("ui:", "region:left")),
("_entity_matches", ("ui", "ui:chat")),
("_entity_matches", ("chat", "ui:chat")),
("_entity_matches", ("", ":abc")),
("_entity_matches", ("", "")),
]
def derivation(pattern_id, rows, revision=1):
out = {"pattern": pattern_id, "revision": revision, "accepted": [], "rejected": [], "unresolved": []}
for oid, verdict, text in rows:
entry = {"id": oid, "obligation": text, "pattern": pattern_id, "revision": revision,
"provenance": "PATTERN", "pattern_provenance": [f"prov:{pattern_id}"],
"verdict": verdict, "reason": "reason"}
out[{"REQUIRED": "accepted", "APPLICABLE": "accepted",
"NOT_APPLICABLE": "rejected"}.get(verdict, "unresolved")].append(entry)
return out
RECV_FULL = {
"cls": "ConstructionPattern",
"pattern_id": "p.recv",
"purpose": "receiver pattern",
"revision": 2,
"maturity": "UNIT-PROVEN",
"signals": {"path_contains": ["deploy"]},
"obligations": [{"id": "o1", "obligation": "first duty", "when": {"always": True}}],
"provenance": ["contract:c9"],
"exclusions": ["queue-only"],
"toolchain_notes": [],
"runtime_effects": [],
"ext": {"wibble": "kept"},
}
cases = [
# matchers — the audit-named kernels, exercised verbatim
*[{"fn": fn, "args": list(args)} for fn, args in MATCHERS],
# proposal (valid bounds; error rows live in the bespoke battery)
{"fn": "record_pattern_proposal", "args": ["some-pattern"],
"kwargs": {"provider": "local", "model": "m1",
"evidence": ["z-hunch", "a-hunch"], "confidence": 0.5}},
{"fn": "record_pattern_proposal", "args": ["x"],
"kwargs": {"provider": "p", "model": "m", "evidence": [], "confidence": 1.0}},
# combine
{"fn": "combine_pattern_obligations", "args": [[]]},
{"fn": "combine_pattern_obligations", "args": [[
derivation("a", [("shared", "REQUIRED", "regression proof")]),
derivation("b", [("shared", "REQUIRED", "regression proof")]),
]]},
{"fn": "combine_pattern_obligations", "args": [[
derivation("x", [("bad", "REQUIRED", "text one"), ("ok", "REQUIRED", "fine")]),
derivation("y", [("bad", "REQUIRED", "text two")]),
]]},
# class surface via rebuilt receivers. from_dict/revise return bare
# ConstructionPattern instances — the shared harness serializes only
# dataclasses, so those two stay in the bespoke battery (construct/revise
# case families) and the Python test suite; to_dict is serializable.
{"fn": "ConstructionPattern.to_dict", "recv": RECV_FULL, "args": []},
]
truth = freeze("rune.construction_pattern", cases, oracle_module="rune.construction_pattern")
write(truth, OUT)
print(f"{len(truth)} harness cases -> {OUT}")