The Principia Machina/TPC-PY/gen sr3 scope corpus.py
Appearance
# -*- coding: utf-8 -*-
"""Generator for tpc/vectors/sr3_scope_corpus.json (tpc_strike 0.2.0,
proposed: sr3_scope, the interim SR3 and SR8 scope of D180.3; TPS 4.4.13
and 4.2.13 as staged for revision 6, provisional numbers;
tpm_d179_d180_d181_texts 0.1.0 section 2, T-C3 and T-C4).
A corpus of its own beside strike_corpus.json, as sr8_order_corpus.json
was at tpc_strike 0.1.1: strike_corpus.json is written by hand, carries no
TFK and stays byte-identical at its tpc_strike 0.1.0 label; these cases
carry whole TFKs, which the tree's TFK corpora (zone, tests, form, hold)
build in a generator with literal expectations.
THE RULE (fixed by the supervising thread's brief; not widened here):
sr3_scope(tfk, quantity) is "MECHANICAL" when the TrM entry whose NAME
is quantity exists and its DOF is the TARGET of a TPK CONSTRAINT whose
ACTION is FIX; "INSPECTION" when the entry exists and no FIX CONSTRAINT
targets its DOF (a REMOVE constraint does not count; the time DOF is an
ordinary DOF); ["REFUSED", reason] when no TrM entry has that NAME or
the input is not of the shape read. Matching is exact.
Every expectation is HAND-DERIVED and written literally below, from the
rule and from the tree's zone wording (tpc_zone's trm_well_formed and
t1_well_formed); the generator refuses to write the corpus if the module
disagrees with any of them. The fixtures are the tree's own kernels: the
spring with its forms (examples/spring_draft.json; tests corpus TFK_F),
the toy of the zone corpus, and the tests corpus's FIX fixture
(t3/laws-ground-fragment); under schema 0.5.0 (D176.1, D177.1) every fixture
LAW carries its ROLE, which sr3_scope does not read. Deterministic; no randomness.
Run: cd tpc && python3 gen_sr3_scope_corpus.py (Windows: py ...)."""
import copy, json, os, sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
import tpc_strike as S
cases = []
def case(cid, tfk, quantity, expect, **extra):
cs = {"id": "sr3_scope/" + cid, "fn": "sr3_scope", "input": {"tfk": tfk, "quantity": quantity}}
cs.update(extra)
cs["expect"] = expect
cases.append(cs)
def c(o):
return copy.deepcopy(o)
def R(reason):
return "[REFUSED," + reason + "]"
M, I = "MECHANICAL", "INSPECTION"
# ---- the toy TFK of the zone corpus: a mass on a linear spring, z fixed at 0 --------
TPK = {
"DOF": [
{"NAME": "x", "DIMENSION": "L1"},
{"NAME": "v", "DIMENSION": "L1 T-1"},
{"NAME": "z", "DIMENSION": "L1"}],
"CONSTANT": [
{"NAME": "m", "DIMENSION": "M1"},
{"NAME": "k_s", "DIMENSION": "M1 T-2"},
{"NAME": "x_max", "DIMENSION": "L1", "VALUE": "0.05", "UNIT": "m", "UNCERTAINTY": "0.001"}],
"LAW": [
{"NAME": "N2", "STATEMENT": "m dv/dt = -k_s x", "REFS": ["m", "v", "k_s", "x"], "ROLE": "EOM(v)"},
{"NAME": "KIN", "STATEMENT": "dx/dt = v", "REFS": ["x", "v"], "ROLE": "EOM(x)"},
{"NAME": "FREE_Z", "STATEMENT": "d2z/dt2 = 0", "REFS": ["z"], "ROLE": "CONSTRAINT"}],
"ASSUMPTION": [
{"NAME": "A_lin", "PROPOSITION": "the restoring force is linear in x (Hooke régime)", "REFS": ["x"]}],
"CONSTRAINT": [
{"NAME": "C_NOZ", "TARGET": "z", "ACTION": "FIX", "VALUE": "0", "UNIT": "m", "STATEMENT": "motion confined to z = 0"}],
"BOUNDARY": [
{"NAME": "B_small", "PREDICATE": "|x| < x_max", "REFS": ["x", "x_max"]}],
}
TRM = {
"HEADER": {
"ENVIRONMENT_INVENTORY": [
{"ENVIRONMENT_QUANTITY": "position", "DIMENSION": "L1"},
{"ENVIRONMENT_QUANTITY": "velocity", "DIMENSION": "L1 T-1"},
{"ENVIRONMENT_QUANTITY": "height", "DIMENSION": "L1"}],
"SIGNATURE": [
{"NAME": "time_derivative", "OVER": ["x", "v"], "IMAGE": "d/dt maps position to velocity"}],
"TRANSFORMATIONS": [
{"NAME": "time_translation", "STATEMENT": "t -> t + t0"}]},
"ENTRIES": [
{"NAME": "E_x", "DOF": "x", "DOMAIN": "|x| < x_max", "ENVIRONMENT_QUANTITY": "position",
"IDENTIFICATION": "x is the displacement from equilibrium along the spring axis",
"FALSIFIER": "a measured restoring force not proportional to x inside the domain",
"FALSIFIER_CLASS": "F3", "BEARS": ["N2", "KIN"], "DIMENSION": "L1"},
{"NAME": "E_v", "DOF": "v", "DOMAIN": "|x| < x_max", "ENVIRONMENT_QUANTITY": "velocity",
"IDENTIFICATION": "v is the time derivative of x",
"FALSIFIER": "a measured velocity differing from dx/dt beyond uncertainty",
"FALSIFIER_CLASS": "F2", "BEARS": ["KIN"], "DIMENSION": "L1 T-1"},
{"NAME": "E_z", "DOF": "z", "DOMAIN": "always", "ENVIRONMENT_QUANTITY": "height",
"IDENTIFICATION": "z is the height above the track",
"FALSIFIER": "any measured z different from 0",
"FALSIFIER_CLASS": "F3", "BEARS": ["FREE_Z", "C_NOZ"], "DIMENSION": "L1"}],
}
TMS = {
"PARAMETERS": {"STEP_CONVENTION": "one application of an inference rule or algebraic identity is one step",
"K": "2", "N_X": 2, "S_MAX": 10},
"CONSTANTS": [{"NAME": "w_a", "VALUE": "1"}, {"NAME": "w_s", "VALUE": "0.5"}],
"YARDSTICKS": [{"NAME": "combined_distance", "KEY": ["SR1", "WSUM:w_a*A;w_s*S", "S"], "LIMITING": []}],
}
TOY = {"TPK": TPK, "TrM": TRM, "TMS": TMS}
# ---- the spring with its forms: examples/spring_draft.json, the tests corpus's TFK_F --------
TPK_F = c(TPK)
TPK_F["DOF"].append({"NAME": "t", "DIMENSION": "T1"})
TPK_F["LAW"] = [
{"NAME": "N2", "STATEMENT": "m dv/dt = -k_s x", "REFS": ["m", "v", "k_s", "x", "t"], "ROLE": "EOM(v)",
"EQUATION": "m * D(v, t) = -k_s * x"},
{"NAME": "KIN", "STATEMENT": "dx/dt = v", "REFS": ["x", "v", "t"], "ROLE": "EOM(x)", "EQUATION": "D(x, t) = v"},
{"NAME": "FREE_Z", "STATEMENT": "d2z/dt2 = 0", "REFS": ["z", "t"], "ROLE": "CONSTRAINT", "EQUATION": "D(z, t, 2) = 0"}]
TPK_F["BOUNDARY"] = [{"NAME": "B_small", "PREDICATE": "|x| < x_max", "REFS": ["x", "x_max"], "CONDITION": "abs(x) < x_max"}]
TRM_F = c(TRM)
TRM_F["HEADER"]["ENVIRONMENT_INVENTORY"].append({"ENVIRONMENT_QUANTITY": "time", "DIMENSION": "T1"})
TRM_F["HEADER"]["SIGNATURE"] = [{"NAME": "time_derivative", "OVER": ["x", "v", "t"], "IMAGE": "d/dt maps position to velocity",
"FORM": "D(x, t) = v", "IMAGE_FORM": "D(position, time) = velocity"}]
TRM_F["ENTRIES"].append({"NAME": "E_t", "DOF": "t", "DOMAIN": "always", "ENVIRONMENT_QUANTITY": "time",
"IDENTIFICATION": "t is the laboratory clock reading",
"FALSIFIER": "two laboratory clocks that disagree beyond their stated uncertainty",
"FALSIFIER_CLASS": "F3", "BEARS": [], "DIMENSION": "T1"})
SPRING = {"TPK": TPK_F, "TrM": TRM_F, "TMS": TMS}
def fix(name, target, value, unit):
return {"NAME": name, "TARGET": target, "ACTION": "FIX", "VALUE": value, "UNIT": unit,
"STATEMENT": target + " = " + value + " " + unit}
def remove(name, target):
return {"NAME": name, "TARGET": target, "ACTION": "REMOVE", "STATEMENT": "no " + target}
C_NOZ = TPK["CONSTRAINT"][0]
# S33 (2026-09-26): EOM(q) is the ROLE of a law for the DOF it moves; a law restating the
# motion of a DOF the kernel FIXes (or REMOVEs, the like case) takes ROLE CONSTRAINT. MOTION
# names the DOF each law of the spring family moves; s33_roles sets those ROLEs from the
# TPK's constraints wherever a fixture's constraints change. Only the spring family's
# fixtures pass through it; a vector whose subject is the ROLE sets its ROLE after it.
MOTION = {"N2": "v", "EOM_X": "v", "KIN": "x", "FREE_Z": "z", "EOM_Z": "z"}
def s33_roles(tpk):
cons = tpk.get("CONSTRAINT", [])
held = set(e["TARGET"] for e in (cons if isinstance(cons, list) else [])
if isinstance(e, dict) and e.get("ACTION") in ("FIX", "REMOVE") and isinstance(e.get("TARGET"), str))
for l in tpk["LAW"]:
q = MOTION.get(l.get("NAME"))
if q is not None:
l["ROLE"] = "CONSTRAINT" if q in held else "EOM(" + q + ")"
return tpk
def with_cons(tfk, *cons):
t = c(tfk)
t["TPK"]["CONSTRAINT"] = [c(x) for x in cons]
s33_roles(t["TPK"])
return t
def entry_index(tfk, name):
for i, e in enumerate(tfk["TrM"]["ENTRIES"]):
if e["NAME"] == name:
return i
raise KeyError(name)
# ============================================================================
# A. the rule over the tree's kernels
# ============================================================================
case("spring/E_z-fixed", SPRING, "E_z", M,
note="C_NOZ FIXes z: a FIXed DOF is tested as TPS 4.4.4 and 4.4.8 state (T-C3)")
case("spring/E_x-free", SPRING, "E_x", I,
note="no FIX CONSTRAINT targets x: a trajectory value, row 21 INSPECTION until C-16 (T-C3, T-C4)")
case("spring/E_v-free", SPRING, "E_v", I, note="no FIX CONSTRAINT targets v")
case("spring/E_t-time", SPRING, "E_t", I,
note="the time DOF t, the independent variable, is an ordinary DOF here: no FIX targets it")
case("toy/E_z-fixed", TOY, "E_z", M, note="the zone corpus's toy TFK, without forms and without t")
case("toy/E_x-free", TOY, "E_x", I)
# the tests corpus's FIX fixture (t3/laws-ground-fragment): x and v FIXed, the constants valued
TPK_B = c(TPK_F)
TPK_B["CONSTANT"][0]["VALUE"] = "2"; TPK_B["CONSTANT"][0]["UNIT"] = "kg"
TPK_B["CONSTANT"][1]["VALUE"] = "3"; TPK_B["CONSTANT"][1]["UNIT"] = "N m-1"
TPK_B["CONSTRAINT"] += [fix("C_X", "x", "0.1", "m"), fix("C_V", "v", "0", "m s-1")]
s33_roles(TPK_B) # x and v FIXed: N2 and KIN restate their motion (S33)
TESTS_FIX = {"TPK": TPK_B, "TrM": TRM_F, "TMS": TMS}
case("tests-fix/E_x-fixed", TESTS_FIX, "E_x", M,
note="the tests corpus's FIX fixture; its TPK fails T3 over the laws at the final pass (N2 evaluates 0 = -0.3), "
"which sr3_scope does not read")
case("tests-fix/E_v-fixed", TESTS_FIX, "E_v", M)
case("tests-fix/E_t-time", TESTS_FIX, "E_t", I)
FIX_X = with_cons(SPRING, C_NOZ, fix("C_X", "x", "0.1", "m"))
case("spring-fix-x/E_x-fixed", FIX_X, "E_x", M, note="the spring with x also FIXed; passes the final pass")
case("spring-fix-x/E_v-free", FIX_X, "E_v", I)
# ============================================================================
# B. REMOVE does not count
# ============================================================================
REM_ONLY = with_cons(SPRING, remove("C_ZR", "z"))
case("remove-only/E_z", REM_ONLY, "E_z", I,
note="a REMOVE constraint does not count. Reachable only before the final pass: the gate refuses an entry "
"on a REMOVEd DOF (CODOMAIN, D107.1)")
case("remove-only/E_x", REM_ONLY, "E_x", I)
REM_GONE = with_cons(SPRING, remove("C_ZR", "z"))
del REM_GONE["TrM"]["ENTRIES"][entry_index(REM_GONE, "E_z")]
REM_GONE["TrM"]["HEADER"]["ENVIRONMENT_INVENTORY"] = [
q for q in REM_GONE["TrM"]["HEADER"]["ENVIRONMENT_INVENTORY"] if q["ENVIRONMENT_QUANTITY"] != "height"]
case("removed-no-entry/E_z", REM_GONE, "E_z", R("QUANTITY E_z names no TrM entry"),
note="after the gate a REMOVEd DOF carries no entry (D107.1), so no QUANTITY names it; passes the final pass")
case("removed-no-entry/E_x", REM_GONE, "E_x", I)
# ============================================================================
# C. a FIX beside another constraint
# ============================================================================
case("fix-and-fix-same-value/E_z", with_cons(SPRING, C_NOZ, fix("C_Z2", "z", "0", "cm")), "E_z", M,
note="two FIX of z at one value (tests corpus t3/same-value); passes the final pass")
case("fix-and-remove/E_z", with_cons(SPRING, C_NOZ, remove("C_ZR", "z")), "E_z", M,
note="a FIX targets z, so MECHANICAL; the gate refuses this TFK (T3: z is both removed and fixed; CODOMAIN)")
case("remove-then-fix/E_z", with_cons(SPRING, remove("C_ZR", "z"), C_NOZ), "E_z", M,
note="the order of the constraints does not matter")
case("fix-and-fix-two-values/E_z", with_cons(SPRING, C_NOZ, fix("C_Z2", "z", "1", "m")), "E_z", M,
note="the gate refuses this TFK (T3: z fixed at 0 m and at 1 m)")
t = with_cons(SPRING, fix("C_X", "x", "0.1", "m"))
t["TrM"]["ENTRIES"][entry_index(t, "E_z")]["BEARS"] = ["FREE_Z"]
case("fix-other-dof/E_z", t, "E_z", I,
note="a FIX of another DOF does not count: z free, x FIXed; passes the final pass")
# ============================================================================
# D. a QUANTITY that names no TrM entry
# ============================================================================
case("unknown/E_w", SPRING, "E_w", R("QUANTITY E_w names no TrM entry"))
case("unknown/constant-k_s", SPRING, "k_s", R("QUANTITY k_s names no TrM entry"),
note="a CONSTANT is not a TrM entry; an M record's QUANTITY names a TrM entry (PMP-TPM VOCABULARY)")
case("unknown/constant-x_max", SPRING, "x_max", R("QUANTITY x_max names no TrM entry"),
note="a CONSTANT with VALUE, UNIT and UNCERTAINTY is still not a TrM entry")
case("unknown/dof-name-z", SPRING, "z", R("QUANTITY z names no TrM entry"),
note="the DOF's NAME is not its entry's NAME, even for the FIXed DOF")
case("unknown/law-N2", SPRING, "N2", R("QUANTITY N2 names no TrM entry"))
case("unknown/constraint-C_NOZ", SPRING, "C_NOZ", R("QUANTITY C_NOZ names no TrM entry"))
case("unknown/environment-quantity-height", SPRING, "height", R("QUANTITY height names no TrM entry"),
note="an ENVIRONMENT_QUANTITY is not an entry's NAME")
t = c(SPRING); t["TrM"]["ENTRIES"] = []
case("empty-entries/E_z", t, "E_z", R("QUANTITY E_z names no TrM entry"))
t = c(SPRING); t["TrM"]["ENTRIES"].append(c(TRM_F["ENTRIES"][entry_index(SPRING, "E_z")]))
case("duplicate/E_z", t, "E_z", R("TrM: duplicate entry name E_z"),
note="two entries of the NAME asked: the answer would be ambiguous (trm_well_formed's words)")
t = c(SPRING); t["TrM"]["ENTRIES"].append(c(TRM_F["ENTRIES"][entry_index(SPRING, "E_x")]))
case("duplicate-other/E_z", t, "E_z", M,
note="a duplicate of another NAME does not change the answer and is trm_well_formed's to report")
# ============================================================================
# E. exact matching
# ============================================================================
case("case/e_z", SPRING, "e_z", R("QUANTITY e_z names no TrM entry"))
case("case/E_Z", SPRING, "E_Z", R("QUANTITY E_Z names no TrM entry"))
TWO = c(SPRING)
TWO["TrM"]["ENTRIES"].append({"NAME": "e_z", "DOF": "x", "DOMAIN": "|x| < x_max", "ENVIRONMENT_QUANTITY": "position",
"IDENTIFICATION": "x read on a second scale", "FALSIFIER": "the two scales disagree",
"FALSIFIER_CLASS": "F2", "BEARS": [], "DIMENSION": "L1"})
case("case/two-entries/e_z", TWO, "e_z", I, note="entries E_z (DOF z) and e_z (DOF x): NAMEs match exactly")
case("case/two-entries/E_z", TWO, "E_z", M)
t = c(SPRING); t["TPK"]["CONSTRAINT"][0]["TARGET"] = "Z"
case("case/target-Z", t, "E_z", I, note="TARGET Z is not the DOF z (T1 refuses it: TARGET Z is not a DOF)")
t = c(SPRING); t["TPK"]["CONSTRAINT"][0]["ACTION"] = "fix"
case("case/action-fix-lower", t, "E_z", I,
note="only ACTION FIX counts (T1 refuses it: ACTION fix is not REMOVE or FIX)")
# ============================================================================
# F. the QUANTITY's shape: an identifier, never echoed otherwise
# ============================================================================
QI = R("QUANTITY is not an identifier")
case("quantity/integer", SPRING, 5, QI)
case("quantity/null", SPRING, None, QI)
case("quantity/empty", SPRING, "", QI)
case("quantity/space", SPRING, "E z", QI)
case("quantity/zero-width", SPRING, "E_z", QI, note="a hidden character: refused, not echoed")
case("quantity/trailing-newline", SPRING, "E_z\n", QI)
case("quantity/leading-digit", SPRING, "1E", QI)
case("quantity/non-ascii", SPRING, "É_z", QI, note="NAMEs are ASCII identifiers")
case("quantity/list", SPRING, ["E_z"], QI)
case("quantity/first", "x", 5, QI, note="the QUANTITY is read before the TFK")
# ============================================================================
# G. the TFK's shape: what sr3_scope reads is the TrM ENTRIES (each entry's NAME
# and DOF) and the TPK CONSTRAINT kind (each constraint's TARGET and ACTION)
# ============================================================================
case("tfk/string", "x", "E_z", R("TFK is not an object"))
case("tfk/null", None, "E_z", R("TFK is not an object"))
case("tfk/list", [1], "E_z", R("TFK is not an object"))
case("tfk/integer", 7, "E_z", R("TFK is not an object"))
case("tfk/empty-object", {}, "E_z", R("TrM: zone is not an object"))
t = c(SPRING); del t["TrM"]
case("trm/missing", t, "E_z", R("TrM: zone is not an object"))
t = c(SPRING); t["TrM"] = "E_z"
case("trm/string", t, "E_z", R("TrM: zone is not an object"))
t = c(SPRING); del t["TrM"]["ENTRIES"]
case("entries/missing", t, "E_z", R("TrM: missing part ENTRIES"))
t = c(SPRING); t["TrM"]["ENTRIES"] = "E_z"
case("entries/string", t, "E_z", R("TrM ENTRIES is not a list"))
t = c(SPRING); t["TrM"]["ENTRIES"] = {"E_z": c(TRM_F["ENTRIES"][entry_index(SPRING, "E_z")])}
case("entries/object", t, "E_z", R("TrM ENTRIES is not a list"))
t = c(SPRING); t["TrM"]["ENTRIES"] = None
case("entries/null", t, "E_z", R("TrM ENTRIES is not a list"))
t = c(SPRING); t["TrM"]["ENTRIES"].append("E_w")
case("entry/string", t, "E_z", R("TrM ENTRIES: entry is not an object"))
t = c(SPRING); t["TrM"]["ENTRIES"].append(["E_w"])
case("entry/list", t, "E_z", R("TrM ENTRIES: entry is not an object"))
t = c(SPRING); del t["TrM"]["ENTRIES"][0]["NAME"]
case("entry/name-missing", t, "E_z", R("ENTRY:?: missing field NAME"))
t = c(SPRING); t["TrM"]["ENTRIES"][0]["NAME"] = 5
case("entry/name-integer", t, "E_z", R("ENTRY:?: field NAME has the wrong type"))
t = c(SPRING); t["TrM"]["ENTRIES"][0]["NAME"] = None
case("entry/name-null", t, "E_z", R("ENTRY:?: field NAME has the wrong type"))
t = c(SPRING); del t["TrM"]["ENTRIES"][entry_index(SPRING, "E_z")]["DOF"]
case("entry/dof-missing", t, "E_z", R("ENTRY:E_z: missing field DOF"))
t = c(SPRING); t["TrM"]["ENTRIES"][entry_index(SPRING, "E_z")]["DOF"] = ["z"]
case("entry/dof-list", t, "E_z", R("ENTRY:E_z: field DOF has the wrong type"))
t = c(SPRING); del t["TrM"]["ENTRIES"][entry_index(SPRING, "E_x")]["DOF"]
case("entry/other-dof-missing", t, "E_z", R("ENTRY:E_x: missing field DOF"),
note="every entry's NAME and DOF is read, not only the matched entry's")
t = c(SPRING); t["TrM"]["ENTRIES"].append({"NAME": "E_w", "DOMAIN": "always"})
case("entry/after-match", t, "E_z", R("ENTRY:E_w: missing field DOF"),
note="every entry is read before the answer, those after the matched one included")
t = c(SPRING); t["TrM"]["ENTRIES"].append({"NAME": "Ew"})
case("entry/hidden-character-escaped", t, "E_z", R("ENTRY:E<U+202E>w: missing field DOF"),
note="a reason that quotes input escapes disallowed code points (zone schemas 6.3)")
t = c(SPRING); del t["TPK"]
case("tpk/missing", t, "E_z", R("TPK: zone is not an object"))
t = c(SPRING); t["TPK"] = [1]
case("tpk/list", t, "E_z", R("TPK: zone is not an object"))
t = c(SPRING); del t["TPK"]["CONSTRAINT"]; s33_roles(t["TPK"])
case("constraint/kind-absent", t, "E_z", I,
note="an absent kind holds no entry, as T1 reads a TPK: no FIX, so INSPECTION")
case("constraint/kind-empty", with_cons(SPRING), "E_z", I)
t = c(SPRING); t["TPK"]["CONSTRAINT"] = "C_NOZ"
case("constraint/kind-string", t, "E_z", R("TPK kind CONSTRAINT is not a list"))
t = c(SPRING); t["TPK"]["CONSTRAINT"] = None
case("constraint/kind-null", t, "E_z", R("TPK kind CONSTRAINT is not a list"))
t = c(SPRING); t["TPK"]["CONSTRAINT"] = ["C_NOZ"]
case("constraint/entry-string", t, "E_z", R("TPK kind CONSTRAINT: entry is not an object"))
t = c(SPRING); del t["TPK"]["CONSTRAINT"][0]["TARGET"]
case("constraint/target-missing", t, "E_z", R("CONSTRAINT:C_NOZ: missing field TARGET"))
t = c(SPRING); t["TPK"]["CONSTRAINT"][0]["ACTION"] = 1
case("constraint/action-integer", t, "E_z", R("CONSTRAINT:C_NOZ: field ACTION has the wrong type"))
t = c(SPRING); del t["TPK"]["CONSTRAINT"][0]["NAME"]; del t["TPK"]["CONSTRAINT"][0]["TARGET"]
case("constraint/unnamed-target-missing", t, "E_z", R("CONSTRAINT:?: missing field TARGET"))
t = with_cons(SPRING, C_NOZ, remove("C_R", "x")); t["TPK"]["CONSTRAINT"][1]["TARGET"] = None
case("constraint/other-target-null", t, "E_z", R("CONSTRAINT:C_R: field TARGET has the wrong type"),
note="every constraint's TARGET and ACTION is read, a REMOVE of another DOF included")
t = c(SPRING); del t["TMS"]
case("tms/not-read", t, "E_z", M, note="the TMS is not read")
t = c(SPRING); t["TPK"] = "x"
case("order/trm-before-tpk", t, "E_w", R("QUANTITY E_w names no TrM entry"),
note="the TrM is read, and the QUANTITY resolved, before the TPK")
def dispatch(fn, i):
if fn == "sr3_scope":
return S.sr3_scope(i["tfk"], i["quantity"])
raise KeyError(fn)
if __name__ == "__main__":
bad = 0
for cs in cases:
try:
got = S.canon(dispatch(cs["fn"], cs["input"]))
except Exception as e:
got = "ERROR: %s" % e
if got != cs["expect"]:
bad += 1
print("MISMATCH", cs["id"], "\n expect", cs["expect"], "\n got ", got)
if bad:
sys.exit("refusing to write: %d mismatches" % bad)
corpus = {
"meta": {
"name": "tpc_sr3_scope_corpus", "version": "0.1.2",
"status": "PROPOSED 2026-09-26 (D180.3, taken 2026-09-26; the interim of TPS 4.4.13 and 4.2.13 as staged "
"for revision 6, provisional numbers); awaiting the supervisor's verification",
"conforms_tps": "0.2.0 (v15), with D180.3's texts T-C3 and T-C4 as staged (tpm_d179_d180_d181_texts 0.1.0)",
"module": "tpc_strike 0.2.0 (proposed; reads with tpc_zone 0.5.0's helpers, proposed, schema 0.5.0)",
"note": ("Every expectation is hand-derived from the rule and the zone wording. The fixtures are the spring "
"with its forms (examples/spring_draft.json), the zone corpus's toy and the tests corpus's FIX "
"fixture, and one-change variants of them; test fixtures, not physics under research. Where a case "
"is reachable only before the final pass its note says so. Both residences MUST reproduce every "
"expect. 0.1.1 (schema 0.5.0; D176.1, D177.1): every fixture LAW carries a ROLE chosen by its "
"physics (N2 EOM(v), KIN EOM(x), FREE_Z EOM(z)); sr3_scope reads no ROLE, so no expectation "
"changed, and every final-pass status a note states holds under schema 0.5.0. 0.1.2 (S33, "
"2026-09-26): a LAW restating the motion of a FIXed or REMOVEd DOF carries ROLE CONSTRAINT "
"(FREE_Z under C_NOZ; N2 and KIN where v or x is FIXed); a variant whose constraints leave z "
"free gives FREE_Z EOM(z). No expectation moves.")
},
"cases": cases,
}
open(os.path.join(HERE, "vectors", "sr3_scope_corpus.json"), "w", encoding="utf-8").write(
json.dumps(corpus, indent=1, ensure_ascii=True) + "\n")
print("wrote", len(cases), "sr3_scope cases; all match hand-derived expectations")