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.
487 lines
25 KiB
Python
487 lines
25 KiB
Python
#!/usr/bin/env python3
|
|
"""Freeze construction_pattern oracle truth for the Rust port battery
|
|
(dichotomy wave #2479 tranche, batch: construction_pattern).
|
|
|
|
Exercises EVERY public function and branch of
|
|
src/rune/construction_pattern.py:
|
|
|
|
ConstructionPattern.__init__ (defaults, sorting, ext, all validation errors)
|
|
ConstructionPattern.to_dict / from_dict (roundtrip incl. ext)
|
|
ConstructionPattern.revise (changes, history accumulation, 200-char
|
|
reason truncation, sorted evidence/changed)
|
|
record_pattern_proposal (bounds errors, evidence sorting, 0/1 bounds)
|
|
evaluate_applicability (exclusions by objective-substring and by
|
|
constraint membership, first-match-wins,
|
|
no-signals UNKNOWN, no-groups UNKNOWN,
|
|
surface_kinds via surface lists AND via
|
|
resolutions, short-token vs containment path
|
|
and entity matching, ':'-prefix entities,
|
|
objective_any '/' splitting (dashes NOT
|
|
split), contracts_match via authorities
|
|
(implements/exposes/provides/serves),
|
|
APPLIES / PARTIAL / DOES_NOT_APPLY,
|
|
evidence [:5] truncation)
|
|
derive_pattern_obligations (when None, always True vs truthy-not-True,
|
|
path_contains hit/miss + [:3] truncation,
|
|
entities_match via paths/ui/regions,
|
|
contracts_touched via need constraints and
|
|
via authority relationships, unrecognized
|
|
shapes, EXCEPTED with defaults,
|
|
accepted/rejected/unresolved routing)
|
|
combine_pattern_obligations (duplicate collapse + also_from, same-id
|
|
different-text conflicts, id sort, empty)
|
|
_need_dict (envelope shape: objective/affected_surface/
|
|
constraints only — extras dropped)
|
|
_surface_text (5 surface lists + affected_surface +
|
|
objective / and - word tokens, deduped)
|
|
_path_matches / _entity_matches (boundary discipline: short tokens,
|
|
containment, ':' prefixes, empty-signal
|
|
re.split leading/trailing-empty quirks)
|
|
_obligation_when_hit (every when shape incl. truthy-not-True
|
|
always, path [:3] truncation, contracts via
|
|
need constraints and authorities,
|
|
unrecognized shapes, empty when dict)
|
|
|
|
Each case records its INPUT and the oracle's EXPECTED output/error; replayed
|
|
VERBATIM by src/rust/construction_pattern/src/branch_battery.rs.
|
|
|
|
Output: src/rust/construction_pattern/src/frozen_cp_truth.json
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
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"))
|
|
|
|
from rune import construction_pattern as cp # noqa: E402
|
|
|
|
OUT = Path(__file__).resolve().parents[1] / "src" / "rust" / "construction_pattern" / "src" / "frozen_cp_truth.json"
|
|
|
|
cases = []
|
|
|
|
|
|
def need(objective="repair the deploy promotion ordering",
|
|
affected_surface=("scripts/deploy_stage.py", "scripts/deploy_promotion.py"),
|
|
constraints=None):
|
|
class N:
|
|
pass
|
|
n = N()
|
|
n.objective = objective
|
|
n.affected_surface = list(affected_surface)
|
|
n.constraints = dict(constraints if constraints is not None else {"contracts": ["contract:monotonic_promotion"]})
|
|
return n
|
|
|
|
|
|
def serialize_need(n):
|
|
return {"objective": n.objective, "affected_surface": n.affected_surface, "constraints": n.constraints}
|
|
|
|
|
|
SPINE = {
|
|
"entities": [
|
|
{"id": "module:deploy_stage", "kind": "module"},
|
|
{"id": "contract:monotonic_promotion", "kind": "contract"},
|
|
{"id": "module:deploy_qualify", "kind": "module"},
|
|
{"id": "contract:fail_closed_deployment", "kind": "contract"},
|
|
],
|
|
"relationships": [
|
|
{"type": "implements", "from": "module:deploy_stage", "to": "contract:monotonic_promotion"},
|
|
{"type": "exposes", "from": "module:deploy_stage", "to": "contract:exposed_api"},
|
|
{"type": "serves", "from": "module:deploy_stage", "to": "contract:served_edge"},
|
|
{"type": "implements", "from": "module:deploy_qualify", "to": "contract:fail_closed_deployment"},
|
|
{"type": "provides", "from": "module:deploy_qualify", "to": "contract:provided_gate"},
|
|
{"type": "serves", "from": "module:deploy_qualify", "to": "contract:second_edge"},
|
|
{"type": "depends_on", "from": "module:deploy_stage", "to": "module:deploy_qualify"},
|
|
],
|
|
}
|
|
AUTH = {"rune_spine": SPINE}
|
|
|
|
SURFACE = {
|
|
"affected_paths": [
|
|
"scripts/deploy_stage.py", "scripts/deploy_promotion.py",
|
|
"src/rune/rune_tui.py", "src/rune/builtin.py",
|
|
],
|
|
"affected_existing_entities": ["module:deploy_stage", "module:deploy_qualify", "ui:chat"],
|
|
"affected_ui_surfaces": ["ui:version_display"],
|
|
"affected_regions": ["region:left"],
|
|
"workflow_config_surfaces": [".gitea/workflows/deploy.yml"],
|
|
"resolutions": [
|
|
{"id": "module:deploy_stage", "kind": "source_path", "verdict": "FOUND"},
|
|
{"id": "ui:version_display", "kind": "ui_component", "verdict": "FOUND"},
|
|
{"id": "region:left", "kind": "layout_region", "verdict": "FOUND"},
|
|
{"id": "cfg:deploy", "kind": "workflow_config", "verdict": "FOUND"},
|
|
{"id": "module:deploy_stage", "kind": "structural_entity", "verdict": "FOUND"},
|
|
],
|
|
}
|
|
|
|
|
|
def case(name, op, inp, fn):
|
|
import copy as _copy
|
|
# Deep-copy the input BEFORE running the oracle: to_dict() shares
|
|
# nested references (ext) with the live object, and revise() mutates
|
|
# revision_history in place — without the copy the recorded input
|
|
# aliases oracle-mutated state.
|
|
inp = _copy.deepcopy(inp)
|
|
try:
|
|
expected = fn()
|
|
except ValueError as e:
|
|
expected = {"error": str(e)}
|
|
cases.append({"name": name, "op": op, "input": inp, "expected": expected})
|
|
|
|
|
|
# ── ConstructionPattern.__init__ / to_dict / from_dict ──────────────────────
|
|
|
|
FULL_KW = dict(
|
|
revision=3, maturity="EXERCISED",
|
|
signals={"path_contains": ["deploy"], "objective_any": ["promotion"]},
|
|
obligations=[
|
|
{"id": "o2", "obligation": "second duty", "when": {"always": True}},
|
|
{"id": "o1", "obligation": "first duty", "when": {"path_contains": ["deploy"]}},
|
|
],
|
|
provenance=["incident:zeta", "incident:alpha"],
|
|
exclusions=["queue-only-project", "no-deploy-zone"],
|
|
toolchain_notes=["zinc", "amber"],
|
|
runtime_effects=["r2", "r1"],
|
|
)
|
|
|
|
|
|
def construct_case(name, kwargs):
|
|
case(name, "construct", {"kwargs": kwargs},
|
|
lambda: cp.ConstructionPattern.from_dict(kwargs).to_dict())
|
|
|
|
|
|
construct_case("construct-full", {"pattern_id": "p.full", "purpose": "full pattern",
|
|
"wibble": "future-data", **FULL_KW})
|
|
construct_case("construct-minimal", {"pattern_id": "p.min", "purpose": "minimal pattern"})
|
|
construct_case("construct-ext-open-world", {"pattern_id": "p.ext", "purpose": "open world",
|
|
"wibble": "future-data", "count": 7})
|
|
construct_case("construct-empty-id", {"pattern_id": "", "purpose": "purpose"})
|
|
construct_case("construct-empty-purpose", {"pattern_id": "p", "purpose": ""})
|
|
construct_case("construct-obl-missing-id",
|
|
{"pattern_id": "p", "purpose": "purpose",
|
|
"obligations": [{"obligation": "x", "when": {}}]})
|
|
construct_case("construct-obl-missing-text",
|
|
{"pattern_id": "p", "purpose": "purpose", "obligations": [{"id": "x", "when": {}}]})
|
|
construct_case("construct-obl-missing-when",
|
|
{"pattern_id": "p", "purpose": "purpose", "obligations": [{"id": "x", "obligation": "x"}]})
|
|
construct_case("construct-from-dict-roundtrip",
|
|
cp.ConstructionPattern("p.rt", "roundtrip", wibble={"deep": [1, 2]}, **FULL_KW).to_dict())
|
|
|
|
# ── revise ───────────────────────────────────────────────────────────────────
|
|
|
|
REV_BASE = dict(revision=2, maturity="UNIT-PROVEN",
|
|
provenance=["contract:c9"], exclusions=["b-ex", "a-ex"])
|
|
|
|
|
|
def revise_case(name, base_kwargs, reason, evidence, changes, ext=None):
|
|
base = cp.ConstructionPattern("p.rev", "revisable", **(ext or {}), **base_kwargs)
|
|
case(name, "revise",
|
|
{"pattern": base.to_dict(), "reason": reason, "evidence": evidence, "changes": changes},
|
|
lambda: base.revise(reason=reason, evidence=evidence, changes=changes).to_dict())
|
|
|
|
|
|
revise_case("revise-with-changes", REV_BASE, "new incident evidence",
|
|
["z-evidence", "a-evidence"], {"maturity": "EXERCISED"})
|
|
revise_case("revise-history-accumulates", {"revision": 2, "revision_history": [
|
|
{"prior_revision": 1, "reason": "initial correction", "evidence": ["old-evidence"], "changed": ["signals"]}]},
|
|
"second revision", ["new-evidence"], {})
|
|
revise_case("revise-reason-truncated-200", {}, "r" * 250, ["e"], None)
|
|
revise_case("revise-open-world-ext-carried", {}, "carries ext", ["e"], {"purpose": "revised purpose"},
|
|
ext={"wibble": "kept"})
|
|
|
|
# ── record_pattern_proposal ─────────────────────────────────────────────────
|
|
|
|
def propose_case(name, pattern_id="x", provider="p", model="m", evidence=(), confidence=0.5):
|
|
case(name, "propose",
|
|
{"pattern_id": pattern_id, "provider": provider, "model": model,
|
|
"evidence": list(evidence), "confidence": confidence},
|
|
lambda: cp.record_pattern_proposal(pattern_id, provider=provider, model=model,
|
|
evidence=list(evidence), confidence=confidence))
|
|
|
|
|
|
propose_case("propose-valid", pattern_id="some-pattern", provider="local", model="m1",
|
|
evidence=["z-hunch", "a-hunch"], confidence=0.5)
|
|
case("propose-bounds-zero-one", "propose",
|
|
{"pattern_id": "x", "provider": "p", "model": "m", "evidence": [], "confidence": [0.0, 1.0]},
|
|
lambda: [cp.record_pattern_proposal("x", provider="p", model="m", evidence=[], confidence=0.0),
|
|
cp.record_pattern_proposal("x", provider="p", model="m", evidence=[], confidence=1.0)])
|
|
propose_case("propose-empty-provider", provider="")
|
|
propose_case("propose-empty-model", model="")
|
|
propose_case("propose-confidence-above-1", confidence=1.5)
|
|
propose_case("propose-confidence-below-0", confidence=-0.1)
|
|
|
|
# ── evaluate_applicability ──────────────────────────────────────────────────
|
|
|
|
def eval_case(name, pattern_kwargs, n=None, surface=None, authorities=None):
|
|
p = cp.ConstructionPattern("p.eval", "evaluated pattern", **pattern_kwargs)
|
|
nn = n or need()
|
|
s = surface or SURFACE
|
|
a = authorities or AUTH
|
|
case(name, "evaluate",
|
|
{"pattern": p.to_dict(), "need": serialize_need(nn), "surface_result": s, "authorities": a},
|
|
lambda: cp.evaluate_applicability(p, nn, s, a))
|
|
|
|
|
|
eval_case("eval-all-groups-applies",
|
|
{"signals": {"surface_kinds": ["source_path", "ui_component", "layout_region",
|
|
"workflow_config", "structural_entity"],
|
|
"path_contains": ["deploy"], "entities_match": ["module:"],
|
|
"objective_any": ["promotion"],
|
|
"contracts_match": ["contract:monotonic_promotion"]}})
|
|
eval_case("eval-partial",
|
|
{"signals": {"path_contains": ["deploy"], "entities_match": ["nope-never", "zzz"],
|
|
"objective_any": ["zzzneverword"]}})
|
|
eval_case("eval-none-declared-does-not-apply",
|
|
{"signals": {"path_contains": ["/nonexistent/xyz/"], "objective_any": ["zzznever"]}})
|
|
eval_case("eval-no-signals-unknown", {})
|
|
eval_case("eval-no-groups-declared-unknown", {"signals": {"surface_kinds": [], "path_contains": []}})
|
|
eval_case("eval-exclusion-objective-substring",
|
|
{"signals": {"path_contains": ["deploy"]}, "exclusions": ["no deployment system in this project"]})
|
|
eval_case("eval-exclusion-constraint-membership",
|
|
{"signals": {"path_contains": ["deploy"]}, "exclusions": ["message-queue-only"]},
|
|
n=need(constraints={"contracts": [], "pattern_exclusions": ["message-queue-only"]}))
|
|
eval_case("eval-exclusion-first-match-wins",
|
|
{"signals": {"path_contains": ["deploy"]},
|
|
"exclusions": ["no deployment system in this project", "message-queue-only"]},
|
|
n=need(constraints={"contracts": [], "pattern_exclusions": ["message-queue-only"]}))
|
|
eval_case("eval-exclusion-declared-but-unmatched",
|
|
{"signals": {"path_contains": ["deploy"]}, "exclusions": ["totally-unrelated-exclusion"]},
|
|
n=need(constraints={"contracts": [], "pattern_exclusions": ["another-unrelated"]}))
|
|
eval_case("eval-surface-kinds-via-resolutions",
|
|
{"signals": {"surface_kinds": ["structural_entity", "nope_kind"]}})
|
|
eval_case("eval-path-short-token",
|
|
{"signals": {"path_contains": ["ui", "tui", "cfg", "deploy"]}})
|
|
eval_case("eval-entity-prefix-and-tokens",
|
|
{"signals": {"entities_match": ["ui:", "module:", "ui", "spine", "zzz"]}})
|
|
eval_case("eval-objective-slash-split",
|
|
{"signals": {"objective_any": ["deploy", "release", "widget"]}},
|
|
n=need(objective="adjust the release/deploy widget", constraints={"contracts": []}))
|
|
eval_case("eval-objective-dash-not-split",
|
|
{"signals": {"objective_any": ["deploy", "pre-deploy"]}},
|
|
n=need(objective="verify the pre-deploy check", constraints={"contracts": []}))
|
|
eval_case("eval-contracts-all-rel-kinds",
|
|
{"signals": {"contracts_match": ["contract:monotonic_promotion", "contract:exposed_api",
|
|
"contract:served_edge", "contract:fail_closed_deployment",
|
|
"contract:provided_gate", "contract:second_edge"]}})
|
|
eval_case("eval-contracts-miss-non-rel-type",
|
|
{"signals": {"contracts_match": ["module:deploy_qualify"]}})
|
|
eval_case("eval-contracts-second-authority",
|
|
{"signals": {"contracts_match": ["contract:scaffold_only"]}},
|
|
authorities={"rune_spine": SPINE,
|
|
"project_scaffold": {"relationships": [
|
|
{"type": "implements", "from": "module:deploy_stage", "to": "contract:scaffold_only"}]}})
|
|
eval_case("eval-empty-entity-id-quirk",
|
|
{"signals": {"contracts_match": ["contract:monotonic_promotion"]}},
|
|
surface={**SURFACE, "affected_existing_entities": ["", "module:deploy_qualify"]})
|
|
|
|
# ── derive_pattern_obligations ──────────────────────────────────────────────
|
|
|
|
O = lambda oid, text, when: {"id": oid, "obligation": text, "when": when}
|
|
|
|
|
|
def derive_case(name, obligations, n=None, exceptions=None, surface=None, authorities=None):
|
|
p = cp.ConstructionPattern("p.derive", "deriving pattern",
|
|
provenance=["incident:prov-1", "contract:prov-0"],
|
|
obligations=obligations)
|
|
nn = n or need()
|
|
s = surface or SURFACE
|
|
a = authorities or AUTH
|
|
case(name, "derive",
|
|
{"pattern": p.to_dict(), "need": serialize_need(nn), "surface_result": s,
|
|
"authorities": a, "project_exceptions": exceptions},
|
|
lambda: cp.derive_pattern_obligations(p, nn, s, a, project_exceptions=exceptions))
|
|
|
|
|
|
derive_case("derive-when-none-unknown", [O("mystery", "do the unconditioned thing", None)])
|
|
derive_case("derive-always-required", [O("always-ob", "regression proof", {"always": True})])
|
|
derive_case("derive-always-truthy-not-true",
|
|
[O("truthy-ob", "truthy always is not always", {"always": 1})])
|
|
derive_case("derive-path-hit-truncation",
|
|
[O("path-ob", "touch the deploy paths", {"path_contains": ["deploy", "rune"]})])
|
|
derive_case("derive-path-miss", [O("path-ob", "touch nothing real", {"path_contains": ["/absent/xyz/"]})])
|
|
derive_case("derive-entities-via-ui-and-regions",
|
|
[O("ui-ob", "respect the ui surface", {"entities_match": ["version_display"]}),
|
|
O("region-ob", "respect the region", {"entities_match": ["left"]}),
|
|
O("entity-ob", "respect the module", {"entities_match": ["module:"]}),
|
|
O("miss-ob", "matches nothing", {"entities_match": ["zzz-never"]})])
|
|
derive_case("derive-contracts-from-need-constraints",
|
|
[O("ct-ob", "honor the explicit contract",
|
|
{"contracts_touched": ["contract:explicit_need", "contract:absent"]})],
|
|
n=need(constraints={"contracts": ["contract:explicit_need"]}))
|
|
derive_case("derive-contracts-from-authorities",
|
|
[O("ct-ob", "honor the authority-implied contract",
|
|
{"contracts_touched": ["contract:provided_gate", "contract:served_edge", "contract:nowhere"]})])
|
|
derive_case("derive-contracts-miss",
|
|
[O("ct-ob", "cannot honor the unknown contract", {"contracts_touched": ["contract:not_anywhere"]})])
|
|
derive_case("derive-unrecognized-shape", [O("weird-ob", "do the unknown thing", {"unsupported_shape": True})])
|
|
derive_case("derive-mixed-routing",
|
|
[O("acc-ob", "always applies", {"always": True}),
|
|
O("rej-ob", "path never matches", {"path_contains": ["/absent/xyz/"]}),
|
|
O("unres-ob", "unknown shape", {"weird": 1})])
|
|
derive_case("derive-exception-with-defaults",
|
|
[O("exc-ob", "suppressed obligation", {"always": True}),
|
|
O("kept-ob", "surviving obligation", {"always": True})],
|
|
exceptions=[{"obligation": "exc-ob"}])
|
|
derive_case("derive-exception-full",
|
|
[O("exc-ob", "suppressed obligation", {"always": True})],
|
|
exceptions=[{"obligation": "exc-ob", "reason": "project policy documented",
|
|
"evidence": "policy doc", "authority": "user"}])
|
|
|
|
# ── combine_pattern_obligations ─────────────────────────────────────────────
|
|
|
|
def derivation(pattern_id, rows, revision=1):
|
|
"""rows: (id, verdict, text) — mirrors derive_pattern_obligations output."""
|
|
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
|
|
|
|
|
|
def combine_case(name, derivs):
|
|
case(name, "combine", {"derivations": derivs}, lambda: cp.combine_pattern_obligations(derivs))
|
|
|
|
|
|
combine_case("combine-empty", [])
|
|
combine_case("combine-single", [derivation("a", [("shared", "REQUIRED", "regression proof"),
|
|
("z-only", "APPLICABLE", "z duty")])])
|
|
combine_case("combine-duplicate-collapse", [
|
|
derivation("a", [("shared", "REQUIRED", "regression proof")]),
|
|
derivation("b", [("shared", "REQUIRED", "regression proof")]),
|
|
derivation("c", [("shared", "REQUIRED", "regression proof")])])
|
|
combine_case("combine-conflict-different-text", [
|
|
derivation("x", [("shared", "REQUIRED", "version A of the rule")]),
|
|
derivation("y", [("shared", "REQUIRED", "version B of the rule")])])
|
|
combine_case("combine-sort-by-id", [
|
|
derivation("p1", [("zz", "REQUIRED", "last"), ("aa", "REQUIRED", "first")]),
|
|
derivation("p2", [("mm", "APPLICABLE", "middle")])])
|
|
combine_case("combine-conflict-then-continue", [
|
|
derivation("x", [("bad", "REQUIRED", "text one"), ("ok", "REQUIRED", "fine duty")]),
|
|
derivation("y", [("bad", "REQUIRED", "text two")])])
|
|
|
|
# ── _path_matches / _entity_matches (boundary discipline + split quirks) ───
|
|
|
|
|
|
def path_case(signal, path):
|
|
case(f"path-match:{signal!r}@{path!r}", "path_match",
|
|
{"signal": signal, "path": path},
|
|
lambda: cp._path_matches(signal, path))
|
|
|
|
|
|
path_case("tui", "src/rune/rune_tui.py") # short signal, real token
|
|
path_case("ui", "src/rune/rune_tui.py") # rune_tui is ONE token — miss
|
|
path_case("ui", "src/rune/builtin.py") # 'ui'-in-'builtin' FP class
|
|
path_case("deploy", "scripts/deploy_stage.py") # >=4 chars: containment
|
|
path_case("xyz", "scripts/deploy_stage.py") # containment miss
|
|
path_case("abc", "abc") # 3-char: whole-token only
|
|
path_case("AbC", "a/abc/b") # case folding, token hit
|
|
path_case("", "abc") # no empties in split — miss
|
|
path_case("", "/abc") # leading sep — leading empty
|
|
path_case("", "abc/") # trailing sep — trailing empty
|
|
path_case("", "") # re.split('') == ['']
|
|
|
|
|
|
def entity_case(signal, entity_id):
|
|
case(f"entity-match:{signal!r}@{entity_id!r}", "entity_match",
|
|
{"signal": signal, "entity_id": entity_id},
|
|
lambda: cp._entity_matches(signal, entity_id))
|
|
|
|
|
|
entity_case("ui:", "ui:chat") # ':'-prefix namespace hit
|
|
entity_case("ui:", "region:left") # prefix miss
|
|
entity_case("ui", "ui:chat") # colon glues the token — short miss
|
|
entity_case("chat", "ui:chat") # 4 chars: containment hit
|
|
entity_case("ui", "ui chat") # space separator — token hit
|
|
entity_case("spine", "module:spine") # long containment
|
|
entity_case("", "abc") # no empties — miss
|
|
entity_case("", ":abc") # colon is a token char — leading empty
|
|
entity_case("", "") # [''] — hit
|
|
|
|
|
|
# ── _need_dict (the FFI need envelope) ───────────────────────────────────────
|
|
|
|
|
|
def need_dict_case(name, n, extra=None):
|
|
payload = serialize_need(n)
|
|
if extra:
|
|
payload.update(extra)
|
|
case(name, "need_dict", {"need": payload}, lambda: cp._need_dict(n))
|
|
|
|
|
|
need_dict_case("need-dict-basic", need())
|
|
need_dict_case("need-dict-drops-extras", need(),
|
|
extra={"need_id": "need-x", "origin": "builder"})
|
|
|
|
|
|
# ── _surface_text (evidence token union; sorted projection of the set) ──────
|
|
|
|
|
|
def surface_text_case(name, n=None, surface=None):
|
|
nn = n or need()
|
|
s = surface or SURFACE
|
|
case(name, "surface_text",
|
|
{"need": serialize_need(nn), "surface_result": s},
|
|
lambda: sorted(cp._surface_text(nn, s)))
|
|
|
|
|
|
surface_text_case("surface-text-all-lists")
|
|
surface_text_case("surface-text-objective-splits",
|
|
n=need(objective="adjust the release/deploy widget"))
|
|
surface_text_case("surface-text-dash-split",
|
|
n=need(objective="verify the pre-deploy check"))
|
|
surface_text_case("surface-text-dedup-and-fold",
|
|
surface={"affected_paths": ["scripts/Deploy_Stage.py"],
|
|
"affected_existing_entities": ["module:deploy_stage"],
|
|
"affected_ui_surfaces": [], "affected_regions": [],
|
|
"workflow_config_surfaces": []})
|
|
|
|
|
|
# ── _obligation_when_hit (every when shape) ─────────────────────────────────
|
|
|
|
|
|
def when_case(name, when, n=None, surface=None, authorities=None):
|
|
nn = n or need()
|
|
s = surface or SURFACE
|
|
a = authorities or AUTH
|
|
o = {"id": "ob-1", "obligation": "duty", "when": when}
|
|
case(name, "when_hit",
|
|
{"obligation": o, "need": serialize_need(nn),
|
|
"surface_result": s, "authorities": a},
|
|
lambda: list(cp._obligation_when_hit(o, nn, s, a)))
|
|
|
|
|
|
when_case("when-none", None)
|
|
when_case("when-always-true", {"always": True})
|
|
when_case("when-always-truthy-not-true", {"always": 1})
|
|
when_case("when-always-false-key-present", {"always": False})
|
|
when_case("when-path-hit-truncated",
|
|
{"path_contains": ["py"]}) # 4 affected .py paths -> [:3]
|
|
when_case("when-path-miss", {"path_contains": ["/absent/xyz/"]})
|
|
when_case("when-path-empty-list", {"path_contains": []})
|
|
when_case("when-entities-via-ui-and-regions",
|
|
{"entities_match": ["version_display", "left"]})
|
|
when_case("when-entities-miss", {"entities_match": ["zzz-never"]})
|
|
when_case("when-contracts-from-need",
|
|
{"contracts_touched": ["contract:explicit_need", "contract:absent"]},
|
|
n=need(constraints={"contracts": ["contract:explicit_need"]}))
|
|
when_case("when-contracts-from-authorities",
|
|
{"contracts_touched": ["contract:provided_gate"]})
|
|
when_case("when-contracts-miss",
|
|
{"contracts_touched": ["contract:not_anywhere"]})
|
|
when_case("when-unrecognized-shape", {"unsupported_shape": True})
|
|
when_case("when-empty-dict", {})
|
|
|
|
|
|
# ── write truth ──────────────────────────────────────────────────────────────
|
|
|
|
OUT.write_text(json.dumps({"generator": "scripts/gen_construction_pattern_truth.py",
|
|
"module": "src/rune/construction_pattern.py", "cases": cases}, indent=1) + "\n")
|
|
print(f"{len(cases)} cases -> {OUT}")
|