Jump to content

The Principia Machina/TPC-PY/gen hold corpus.py: Difference between revisions

From The Invariance Itself
TPC-PY source gen_hold_corpus.py (-), SHA-256 2fcf9a53688f0124; conformed TPS 0.3.0; PROPOSED, not declared (CO-8)
 
m 1 revision imported
 
(2 intermediate revisions by the same user not shown)
Line 12: Line 12:
whose digests moved with HOLD_FORM "2"; the hold_scope, held_closure and
whose digests moved with HOLD_FORM "2"; the hold_scope, held_closure and
tpx_allocate cases are unchanged) and new cases carry a non-empty list.
tpx_allocate cases are unchanged) and new cases carry a non-empty list.
At 0.3.0 (PD-D-5; tpm_hold_scope 0.2.0) every release_record case carries
"tier", the fifth argument: null with a REPRODUCTION, the reproducer's
facts {in_tier, override_in_force, independent_matches} with a
LEDGER_MATCH; new cases exercise the gate and its order, and the
generator refuses to write unless the gate equals
tpc_score.tier_gate_release on the grid. The decode/ cases (C-MS-5) tell a
JSON {} from a JSON [] as both residences now read them. No digest moves: the RELEASE
record and its form are unchanged. The file is written with LF line ends
on every platform (S65).
Run: cd tpc && python3 gen_hold_corpus.py (Windows: py ...)."""
Run: cd tpc && python3 gen_hold_corpus.py (Windows: py ...)."""
import json, os, sys
import json, os, sys
Line 355: Line 364:
]
]
IND = {"account": "other", "snapshot": "model-2026-02-02", "origin": "REPRODUCTION BLOCK"}
IND = {"account": "other", "snapshot": "model-2026-02-02", "origin": "REPRODUCTION BLOCK"}
# 0.3.0 (PD-D-5): the trust-tier gate on a ledger MATCH as release_record's fifth parameter,
# the reproducer's facts in tpc_score.tier_gate_release's shape; null for a REPRODUCTION
TIER_OK = {"in_tier": True, "override_in_force": False, "independent_matches": 1}
def tier(in_tier, override, n):
    return {"in_tier": in_tier, "override_in_force": override, "independent_matches": n}




Line 367: Line 383:
D_REL_2 = "e2bf9d00ad4e81c3f04f574cafaa6c22866328ff70137eabc43c013454fd13d0"  # sha256sum of PRE_REL_2 (form 2)
D_REL_2 = "e2bf9d00ad4e81c3f04f574cafaa6c22866328ff70137eabc43c013454fd13d0"  # sha256sum of PRE_REL_2 (form 2)
case("release/seed-and-dependents", "release_record",
case("release/seed-and-dependents", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"]), "records": REG_REL},
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"]), "records": REG_REL, "tier": None},
     "[OK,[RR-900002,RELEASE,RR-900001," + D_HOLD + ",REPRODUCTION,B12,other,model-2026-02-02,"
     "[OK,[RR-900002,RELEASE,RR-900001," + D_HOLD + ",REPRODUCTION,B12,other,model-2026-02-02,"
     "[[RR-2,ESTABLISHED],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[RR-4],[]," + D_REL_2 + "]]",
     "[[RR-2,ESTABLISHED],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[RR-4],[]," + D_REL_2 + "]]",
Line 377: Line 393:
case("release/ledger-match-all", "release_record",
case("release/ledger-match-all", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-4"], kind="LEDGER_MATCH", rid="LE-40"),
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-4"], kind="LEDGER_MATCH", rid="LE-40"),
       "records": REG_REL},
       "records": REG_REL, "tier": TIER_OK},
     "[OK,[RR-900002,RELEASE,RR-900001," + D_HOLD + ",LEDGER_MATCH,LE-40,other,model-2026-02-02,"
     "[OK,[RR-900002,RELEASE,RR-900001," + D_HOLD + ",LEDGER_MATCH,LE-40,other,model-2026-02-02,"
     "[[RR-2,ESTABLISHED],[RR-4,PROVISIONAL],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[],[]," + D_REL_ALL + "]]",
     "[[RR-2,ESTABLISHED],[RR-4,PROVISIONAL],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[],[]," + D_REL_ALL + "]]",
Line 387: Line 403:
D_REL_BIB = "5ee5a938bb21ff1902f8d50532a7dbb79d302ce2b8bd3775a64fa5f088b8f18d"  # sha256sum of PRE_REL_BIB
D_REL_BIB = "5ee5a938bb21ff1902f8d50532a7dbb79d302ce2b8bd3775a64fa5f088b8f18d"  # sha256sum of PRE_REL_BIB
case("release/bibliography-carried", "release_record",
case("release/bibliography-carried", "release_record",
     {"release_id": "RR-900002", "hold": HOLD_BIB, "reproduction": rep(["RR-2"]), "records": REG_REL},
     {"release_id": "RR-900002", "hold": HOLD_BIB, "reproduction": rep(["RR-2"]), "records": REG_REL, "tier": None},
     "[OK,[RR-900002,RELEASE,RR-900001," + D_BIB + ",REPRODUCTION,B12,other,model-2026-02-02,"
     "[OK,[RR-900002,RELEASE,RR-900001," + D_BIB + ",REPRODUCTION,B12,other,model-2026-02-02,"
     "[[RR-2,ESTABLISHED],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[RR-4],"
     "[[RR-2,ESTABLISHED],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[RR-4],"
Line 393: Line 409:
     note="the HOLD's list is carried unchanged: entries are not held and none is released. Preimage: " + PRE_REL_BIB)
     note="the HOLD's list is carried unchanged: entries are not held and none is released. Preimage: " + PRE_REL_BIB)
case("release/bibliography-unsorted-in-hold", "release_record",
case("release/bibliography-unsorted-in-hold", "release_record",
     {"release_id": "RR-900002", "hold": dict(HOLD_BIB, biblio=list(reversed(BIB))), "reproduction": rep(["RR-2"]), "records": REG_REL},
     {"release_id": "RR-900002", "hold": dict(HOLD_BIB, biblio=list(reversed(BIB))), "reproduction": rep(["RR-2"]), "records": REG_REL, "tier": None},
     "[OK,[RR-900002,RELEASE,RR-900001," + D_BIB + ",REPRODUCTION,B12,other,model-2026-02-02,"
     "[OK,[RR-900002,RELEASE,RR-900001," + D_BIB + ",REPRODUCTION,B12,other,model-2026-02-02,"
     "[[RR-2,ESTABLISHED],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[RR-4],"
     "[[RR-2,ESTABLISHED],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[RR-4],"
Line 399: Line 415:
case("release/refused/hold-missing-biblio", "release_record",
case("release/refused/hold-missing-biblio", "release_record",
     {"release_id": "RR-900002", "hold": {k: v for k, v in HOLD.items() if k != "biblio"}, "reproduction": rep(["RR-2"]),
     {"release_id": "RR-900002", "hold": {k: v for k, v in HOLD.items() if k != "biblio"}, "reproduction": rep(["RR-2"]),
       "records": REG_REL},
       "records": REG_REL, "tier": None},
     "[REFUSED,hold: missing field biblio]", note="a form-1 HOLD object is not read at 0.2.0 (no UWC exists; fixtures only)")
     "[REFUSED,hold: missing field biblio]", note="a form-1 HOLD object is not read at 0.2.0 (no UWC exists; fixtures only)")
case("release/refused/hold-biblio-confirmed", "release_record",
case("release/refused/hold-biblio-confirmed", "release_record",
     {"release_id": "RR-900002", "hold": dict(HOLD_BIB, biblio=BIB + [["RR-BIB1", "CONFIRMED"]]), "reproduction": rep(["RR-2"]),
     {"release_id": "RR-900002", "hold": dict(HOLD_BIB, biblio=BIB + [["RR-BIB1", "CONFIRMED"]]), "reproduction": rep(["RR-2"]),
       "records": REG_REL},
       "records": REG_REL, "tier": None},
     "[REFUSED,hold: biblio: entry RR-BIB1 is CONFIRMED; the list holds what is not]")
     "[REFUSED,hold: biblio: entry RR-BIB1 is CONFIRMED; the list holds what is not]")
case("release/refused/hold-biblio-digest-moved", "release_record",
case("release/refused/hold-biblio-digest-moved", "release_record",
     {"release_id": "RR-900002", "hold": dict(HOLD_BIB, biblio=BIB[:2]), "reproduction": rep(["RR-2"]), "records": REG_REL},
     {"release_id": "RR-900002", "hold": dict(HOLD_BIB, biblio=BIB[:2]), "reproduction": rep(["RR-2"]), "records": REG_REL, "tier": None},
     "[REFUSED,hold: digest does not match its fields]", note="the list is inside the HOLD's digest")
     "[REFUSED,hold: digest does not match its fields]", note="the list is inside the HOLD's digest")
case("release/dependent-matched-stays-held", "release_record",
case("release/dependent-matched-stays-held", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-5"]), "records": REG_REL},
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-5"]), "records": REG_REL, "tier": None},
     "[REFUSED,no held record is released by this reproduction]",
     "[REFUSED,no held record is released by this reproduction]",
     note="RR-5 reproduced but its derivation cites RR-2, still held: nothing is released")
     note="RR-5 reproduced but its derivation cites RR-2, still held: nothing is released")
case("release/refused/same-account", "release_record",
case("release/refused/same-account", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], account="acct"), "records": REG_REL},
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], account="acct"), "records": REG_REL, "tier": None},
     "[REFUSED,reproduction by the held account is not independent]")
     "[REFUSED,reproduction by the held account is not independent]")
case("release/refused/same-model-flag", "release_record",
case("release/refused/same-model-flag", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], same_model=True), "records": REG_REL},
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], same_model=True), "records": REG_REL, "tier": None},
     "[REFUSED,reproduction is SAME-MODEL]")
     "[REFUSED,reproduction is SAME-MODEL]")
case("release/refused/same-snapshot", "release_record",
case("release/refused/same-snapshot", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], snapshot="model-2026-01-01"), "records": REG_REL},
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], snapshot="model-2026-01-01"), "records": REG_REL, "tier": None},
     "[REFUSED,reproduction is SAME-MODEL]", note="the reproducing snapshot equals the original's (D42)")
     "[REFUSED,reproduction is SAME-MODEL]", note="the reproducing snapshot equals the original's (D42)")
case("release/refused/same-block-origin", "release_record",
case("release/refused/same-block-origin", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], origin="SAME BLOCK"), "records": REG_REL},
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], origin="SAME BLOCK"), "records": REG_REL, "tier": None},
     "[REFUSED,reproduction origin is not REPRODUCTION BLOCK]")
     "[REFUSED,reproduction origin is not REPRODUCTION BLOCK]")
case("release/refused/matched-not-held", "release_record",
case("release/refused/matched-not-held", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-7"]), "records": REG_REL},
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-7"]), "records": REG_REL, "tier": None},
     "[REFUSED,matched record RR-7 is not in the hold]")
     "[REFUSED,matched record RR-7 is not in the hold]")
case("release/refused/kind", "release_record",
case("release/refused/kind", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], kind="PARROT"), "records": REG_REL},
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], kind="PARROT"), "records": REG_REL, "tier": None},
     "[REFUSED,reproduction: kind is not REPRODUCTION or LEDGER_MATCH]")
     "[REFUSED,reproduction: kind is not REPRODUCTION or LEDGER_MATCH]")
case("release/refused/hold-digest", "release_record",
case("release/refused/hold-digest", "release_record",
     {"release_id": "RR-900002", "hold": dict(HOLD, digest="0" * 64), "reproduction": rep(["RR-2"]), "records": REG_REL},
     {"release_id": "RR-900002", "hold": dict(HOLD, digest="0" * 64), "reproduction": rep(["RR-2"]), "records": REG_REL, "tier": None},
     "[REFUSED,hold: digest does not match its fields]", note="a HOLD whose fields moved since its digest is refused")
     "[REFUSED,hold: digest does not match its fields]", note="a HOLD whose fields moved since its digest is refused")
case("release/refused/hold-field-missing", "release_record",
case("release/refused/hold-field-missing", "release_record",
     {"release_id": "RR-900002", "hold": {k: v for k, v in HOLD.items() if k != "seeds"}, "reproduction": rep(["RR-2"]),
     {"release_id": "RR-900002", "hold": {k: v for k, v in HOLD.items() if k != "seeds"}, "reproduction": rep(["RR-2"]),
       "records": REG_REL},
       "records": REG_REL, "tier": None},
     "[REFUSED,hold: missing field seeds]")
     "[REFUSED,hold: missing field seeds]")
case("release/refused/held-record-missing", "release_record",
case("release/refused/held-record-missing", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"]), "records": REG_REL[:4]},
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"]), "records": REG_REL[:4], "tier": None},
     "[REFUSED,held record RR-5 is not in records]")
     "[REFUSED,held record RR-5 is not in records]")
case("release/refused/independence-missing", "release_record",
case("release/refused/independence-missing", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": {"kind": "REPRODUCTION", "id": "B12", "matched": ["RR-2"]},
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": {"kind": "REPRODUCTION", "id": "B12", "matched": ["RR-2"]},
       "records": REG_REL},
       "records": REG_REL, "tier": None},
     "[REFUSED,reproduction: independence is not an object]")
     "[REFUSED,reproduction: independence is not an object]")
case("release/refused/same-model-not-bool", "release_record",
case("release/refused/same-model-not-bool", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], same_model="no"), "records": REG_REL},
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], same_model="no"), "records": REG_REL, "tier": None},
     "[REFUSED,reproduction: independence same_model is not a boolean]")
     "[REFUSED,reproduction: independence same_model is not a boolean]")
case("release/refused/matched-duplicate", "release_record",
case("release/refused/matched-duplicate", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-2"]), "records": REG_REL},
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-2"]), "records": REG_REL, "tier": None},
     "[REFUSED,reproduction: matched is not a list of distinct names]")
     "[REFUSED,reproduction: matched is not a list of distinct names]")
# ---- 0.3.0: the trust-tier gate (PD-D-5; TPS 3.3.15; CR11; D119.1, D123.1 T6) ----------------
# Expectations by hand from the rule: a ledger MATCH releases only when the reproducer is in
# the TRUST TIER and, while an OVERRIDE mark is in force, has at least two independent
# matches; the gate is one more refusal after the eligibility checks (account, SAME-MODEL,
# origin); tier's shape is checked with the reproduction's; a REPRODUCTION carries no tier.
OK_ALL = ("[OK,[RR-900002,RELEASE,RR-900001," + D_HOLD + ",LEDGER_MATCH,LE-40,other,model-2026-02-02,"
          "[[RR-2,ESTABLISHED],[RR-4,PROVISIONAL],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[],[]," + D_REL_ALL + "]]")
LM = rep(["RR-2", "RR-4"], kind="LEDGER_MATCH", rid="LE-40")
case("release/tier/override-two-matches", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, True, 2)},
    OK_ALL, note="an overridden account's match releases with a second independent match (D123.1 T6); "
                  "the tier's facts enter no field of the RELEASE, so its digest is the one of ledger-match-all")
case("release/tier/in-tier-many-matches", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, False, 1000000000)},
    OK_ALL, note="COUNT_MAX matches, no mark")
case("release/refused/tier-not-in-tier", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(False, False, 1)},
    "[REFUSED,trust-tier gate: NOT IN TIER]", note="only a TRUST TIER member's match releases (TPS 3.3.15; CR11)")
case("release/refused/tier-override-one-match", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, True, 1)},
    "[REFUSED,trust-tier gate: OVERRIDE MARK]", note="a sole match of an overridden account (D123.1 T6)")
case("release/refused/tier-override-zero", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, True, 0)},
    "[REFUSED,trust-tier gate: OVERRIDE MARK]")
case("release/refused/tier-not-in-tier-and-marked", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(False, True, 0)},
    "[REFUSED,trust-tier gate: NOT IN TIER]", note="NOT IN TIER is tested first, as tier_gate_release does")
case("release/refused/tier-null-for-ledger-match", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": None},
    "[REFUSED,tier is not an object]", note="a ledger MATCH needs the reproducer's facts")
case("release/refused/tier-list-for-ledger-match", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": []},
    "[REFUSED,tier is not an object]")
case("release/refused/tier-given-for-reproduction", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"]), "records": REG_REL, "tier": TIER_OK},
    "[REFUSED,tier is given for a REPRODUCTION]",
    note="the gate is a ledger MATCH's (TPS 3.3.15); a tier given with a REPRODUCTION is refused, so no caller "
          "believes it ran (RD-TP-7)")
case("release/refused/tier-unknown-field", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL,
      "tier": dict(TIER_OK, x=1, a=2)},
    "[REFUSED,tier: unknown field a]", note="the least unknown field in code point order")
case("release/refused/tier-missing-field", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL,
      "tier": {"override_in_force": False}},
    "[REFUSED,tier: missing field in_tier]", note="missing fields in the order in_tier, override_in_force, "
                                                  "independent_matches")
case("release/refused/tier-missing-count", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL,
      "tier": {"in_tier": True, "override_in_force": False}},
    "[REFUSED,tier: missing field independent_matches]")
case("release/refused/tier-in-tier-not-bool", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(1, False, 1)},
    "[REFUSED,tier: in_tier is not a boolean]")
case("release/refused/tier-override-not-bool", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, "no", 1)},
    "[REFUSED,tier: override_in_force is not a boolean]")
case("release/refused/tier-count-bool", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, False, True)},
    "[REFUSED,tier: independent_matches is not a count]", note="a boolean is not a count")
case("release/refused/tier-count-negative", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, False, -1)},
    "[REFUSED,tier: independent_matches is not a count]")
case("release/refused/tier-count-too-large", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL,
      "tier": tier(True, False, 1000000001)},
    "[REFUSED,tier: independent_matches is not a count]", note="past COUNT_MAX (tpc_score)")
case("release/refused/tier-count-float", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, False, 1.0)},
    "[REFUSED,tier: independent_matches is not a count]", note="1.0 is a JSON number that is not an integer text")
case("release/refused/tier-shape-before-eligibility", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-4"], kind="LEDGER_MATCH", rid="LE-40",
                                                                  account="acct"),
      "records": REG_REL, "tier": {"in_tier": True}},
    "[REFUSED,tier: missing field override_in_force]",
    note="tier's shape is read with the reproduction's shape, before eligibility")
case("release/refused/same-model-before-gate", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-4"], kind="LEDGER_MATCH", rid="LE-40",
                                                                  same_model=True),
      "records": REG_REL, "tier": tier(False, False, 1)},
    "[REFUSED,reproduction is SAME-MODEL]", note="the gate follows the eligibility checks (TPS 3.3.15)")
case("release/refused/gate-before-matched-check", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-7"], kind="LEDGER_MATCH", rid="LE-40"),
      "records": REG_REL, "tier": tier(False, False, 1)},
    "[REFUSED,trust-tier gate: NOT IN TIER]", note="the gate closes the eligibility check; matched ids are checked after")
# ---- 0.3.0 (C-MS-5; increment 11): a JSON {} and a JSON [] are told apart -------------
# Expectations by hand from tpc_hold's reading order; each case is one an assoc-array
# reading answered otherwise, or a valid empty object.
case("decode/scope-history-list", "hold_scope", {"history": [], "lookback_passes": 2},
    "[REFUSED,history is not an object]")
case("decode/scope-blocks-object", "hold_scope",
    {"history": {"account": "acct", "admission_block": "B1", "blocks": {}}, "lookback_passes": 2},
    "[REFUSED,history: blocks is not a non-empty list]")
case("decode/scope-blocks-zero-keyed", "hold_scope",
    {"history": {"account": "acct", "admission_block": "B1", "blocks": {"0": B(1, "FAIL")}}, "lookback_passes": 2},
    "[REFUSED,history: blocks is not a non-empty list]", note="it read as the list [B1] and held B1")
case("decode/scope-block-list", "hold_scope",
    {"history": {"account": "acct", "admission_block": "B1", "blocks": [[]]}, "lookback_passes": 2},
    "[REFUSED,history: block is not an object]")
case("decode/closure-records-object", "held_closure", {"records": {}, "seeds": SEEDS}, "[REFUSED,records is not a list]",
    note="it read as no record and answered OK with nothing held")
case("decode/closure-records-zero-keyed", "held_closure", {"records": {"0": REG[1]}, "seeds": SEEDS},
    "[REFUSED,records is not a list]")
case("decode/closure-record-list", "held_closure", {"records": [[]], "seeds": SEEDS},
    "[REFUSED,records: entry is not an object]")
case("decode/closure-cites-object", "held_closure", {"records": [dict(REG[1], cites={})], "seeds": SEEDS},
    "[REFUSED,records: RR-2: cites is not a list of names]")
case("decode/closure-seeds-list", "held_closure", {"records": REG, "seeds": []}, "[REFUSED,seeds is not an object]")
case("decode/closure-seeds-blocks-zero-keyed", "held_closure",
    {"records": REG, "seeds": {"account": "acct", "blocks": {"0": "B2"}}},
    "[REFUSED,seeds: blocks is not a list of names]")
case("decode/allocate-range-list", "tpx_allocate", {"range": []}, "[REFUSED,range is not an object]")
case("decode/allocate-range-empty-object", "tpx_allocate", {"range": {}}, "[REFUSED,range: prefix is not an identifier]")
case("decode/hold-cause-list", "hold_record",
    {"hold_id": "RR-900001", "cause": [], "seeds": SEED_IDS, "held": HELD, "biblio": []},
    "[REFUSED,cause is not an object]")
case("decode/hold-seeds-object", "hold_record",
    {"hold_id": "RR-900001", "cause": CAUSE, "seeds": {}, "held": HELD, "biblio": []},
    "[REFUSED,seeds is not a list of distinct names]")
case("decode/hold-biblio-object", "hold_preimage", {"cause": CAUSE, "seeds": SEED_IDS, "held": HELD, "biblio": {}},
    "[REFUSED,biblio is not a list]")
case("decode/release-hold-list", "release_record",
    {"release_id": "RR-900002", "hold": [], "reproduction": rep(["RR-2"]), "records": REG_REL, "tier": None},
    "[REFUSED,hold is not an object]")
case("decode/release-reproduction-list", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": [], "records": REG_REL, "tier": None},
    "[REFUSED,reproduction is not an object]")
case("decode/release-independence-list", "release_record",
    {"release_id": "RR-900002", "hold": HOLD,
      "reproduction": {"kind": "REPRODUCTION", "id": "B12", "independence": [], "matched": ["RR-2"]},
      "records": REG_REL, "tier": None},
    "[REFUSED,reproduction: independence is not an object]")
case("decode/release-independence-empty-object", "release_record",
    {"release_id": "RR-900002", "hold": HOLD,
      "reproduction": {"kind": "REPRODUCTION", "id": "B12", "independence": {}, "matched": ["RR-2"]},
      "records": REG_REL, "tier": None},
    "[REFUSED,reproduction: independence account is not a name]")
case("decode/release-matched-zero-keyed", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": dict(rep(["RR-2"]), matched={"0": "RR-2"}),
      "records": REG_REL, "tier": None},
    "[REFUSED,reproduction: matched is not a list of distinct names]")
case("decode/release-tier-empty-object", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": {}},
    "[REFUSED,tier: missing field in_tier]", note="an empty tier object: every field missing, in_tier first")
case("decode/release-tier-zero-keyed", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": {"0": True}},
    "[REFUSED,tier: unknown field 0]")
case("decode/release-records-object", "release_record",
    {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"]), "records": {}, "tier": None},
    "[REFUSED,records is not a list]")




Line 464: Line 635:
         return H.hold_record(i["hold_id"], i["cause"], i["seeds"], i["held"], i["biblio"])
         return H.hold_record(i["hold_id"], i["cause"], i["seeds"], i["held"], i["biblio"])
     if fn == "release_record":
     if fn == "release_record":
         return H.release_record(i["release_id"], i["hold"], i["reproduction"], i["records"])
         return H.release_record(i["release_id"], i["hold"], i["reproduction"], i["records"], i["tier"])
     raise KeyError(fn)
     raise KeyError(fn)


Line 482: Line 653:
     if bad:
     if bad:
         sys.exit("refusing to write: %d mismatches" % bad)
         sys.exit("refusing to write: %d mismatches" % bad)
    # PD-D-5: the gate in release_record is tpc_score.tier_gate_release's rule; checked on the grid
    import tpc_score as SC
    for t_in in (True, False):
        for t_ov in (True, False):
            for t_n in (0, 1, 2, 3):
                g = SC.tier_gate_release({"in_tier": t_in, "override_in_force": t_ov, "independent_matches": t_n})
                r = H.release_record("RR-900002", HOLD, LM, REG_REL, tier(t_in, t_ov, t_n))
                want = ["OK"] if g["status"] == "PASS" else ["REFUSED", "trust-tier gate: " + g["reason"]]
                if r[:len(want)] != want:
                    sys.exit("refusing to write: the gate differs from tier_gate_release at %r" % ((t_in, t_ov, t_n),))
     corpus = {
     corpus = {
         "meta": {
         "meta": {
             "name": "tpc_hold_corpus", "version": "0.2.0",
             "name": "tpc_hold_corpus", "version": "0.3.0",
             "status": "RE-ISSUED 2026-09-26 at HOLD_FORM 2 (D171 (j), taken by delegation; D111.1; charter CO-21); "
             "status": "RE-ISSUED 2026-09-28 for tpc_hold 0.3.0 (PD-D-5: the trust-tier gate as release_record's "
                       "awaiting the supervisor's verification",
                       "fifth parameter); increment 11 of TPC step 2, proposed with TPC-PY 0.2.0, unreleased",
             "conforms_tps": "0.1.0 revision 4; the hold of D111.1 (2026-09-23), text owed at revision 5 (3.3, 4.4, 5.14, 5.17); "
             "conforms_tps": "0.3.0 (3.3.11 HOLD form 2, 3.3.12 RELEASE, 3.3.13 propagation, 3.3.15 the gate on a "
                             "the bibliography list of D171 (j), text owed",
                             "ledger MATCH); the RELEASE digest's form number is the built \"2\" (DI-TP-1)",
             "module": "tpc_hold 0.2.0 (tpc_digest 0.1.0, tpc_zone 0.4.0)",
             "module": "tpc_hold 0.3.0 (tpc_digest 0.1.0, tpc_zone 0.5.1)",
             "note": ("Expectations hand-derived from tpm_hold_scope 0.1.0: scopes counted on paper, closures traced by "
             "note": ("Expectations hand-derived from tpm_hold_scope 0.2.0: scopes counted on paper, closures traced by "
                     "hand, refusals from the edge-case table. Every digest is an external sha256sum over the preimage "
                     "hand, refusals from the edge-case table and the gate's rule. Every digest is an external "
                    "its case shows. Deterministic; no randomness. Both residences MUST reproduce every expect.")
                    "sha256sum over the preimage its case shows. Deterministic; no randomness. Both residences "
                    "MUST reproduce every expect. 0.3.0 adds 21 tier cases (PD-D-5) and 23 decode/ cases "
                    "(C-MS-5: a JSON {} and [] and an object keyed 0 read as written in both residences); every "
                    "release_record case carries tier. No earlier answer moves.")
         },
         },
         "cases": cases,
         "cases": cases,
     }
     }
     open(os.path.join(HERE, "vectors", "hold_corpus.json"), "w", encoding="utf-8").write(
     open(os.path.join(HERE, "vectors", "hold_corpus.json"), "w", encoding="utf-8", newline="\n").write(
         json.dumps(corpus, indent=1, ensure_ascii=True) + "\n")
         json.dumps(corpus, indent=1, ensure_ascii=True) + "\n")
     print("wrote", len(cases), "hold cases; all match literal expectations")
     print("wrote", len(cases), "hold cases; all match literal expectations")



Latest revision as of 02:11, 30 September 2026

# -*- coding: utf-8 -*-
"""Generator for tpc/vectors/hold_corpus.json (the hold-scope function,
D111.1; charter CO-21; 0.2.0: the HOLD record's bibliography list, D171
(j), tpm_biblio_resolution 0.1.0 section 6.14). Expectations are written
literally below and hand-derived from tpm_hold_scope 0.1.0: block scopes
counted on paper, closures traced by hand, refusals named from the spec's
edge-case table. Every digest is SHA-256 over the preimage the case
shows, computed with an external sha256sum, never by the module.
Deterministic: no randomness. The generator refuses to write the corpus
if the module disagrees. At 0.2.0 every hold_preimage, hold_record and
release_record case carries "biblio" ([] for the re-issued 0.1.0 cases,
whose digests moved with HOLD_FORM "2"; the hold_scope, held_closure and
tpx_allocate cases are unchanged) and new cases carry a non-empty list.
At 0.3.0 (PD-D-5; tpm_hold_scope 0.2.0) every release_record case carries
"tier", the fifth argument: null with a REPRODUCTION, the reproducer's
facts {in_tier, override_in_force, independent_matches} with a
LEDGER_MATCH; new cases exercise the gate and its order, and the
generator refuses to write unless the gate equals
tpc_score.tier_gate_release on the grid. The decode/ cases (C-MS-5) tell a
JSON {} from a JSON [] as both residences now read them. No digest moves: the RELEASE
record and its form are unchanged. The file is written with LF line ends
on every platform (S65).
Run: cd tpc && python3 gen_hold_corpus.py (Windows: py ...)."""
import json, os, sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
import tpc_strike as S
import tpc_hold as H

cases = []


def case(cid, fn, inp, expect, **extra):
    c = {"id": cid, "fn": fn, "input": inp}
    c.update(extra)
    c["expect"] = expect
    cases.append(c)


def B(n, canary=None):
    return {"block_id": "B%d" % n, "canary": canary}


def hist(blocks, adm="B1", account="acct"):
    return {"account": account, "admission_block": adm, "blocks": blocks}


# ============================================================================
# hold_scope: the held block set
# ============================================================================
# the typical span: two canary intervals of four blocks, the anchoring block held
H11 = hist([B(1), B(2, "PASS"), B(3), B(4), B(5), B(6), B(7, "PASS"), B(8), B(9), B(10), B(11), B(12, "FAIL")])
case("scope/eleven-blocks", "hold_scope", {"history": H11, "lookback_passes": 2},
     "[OK,[B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12],PASS,B2,2]",
     note="two intervals of four blocks: the anchoring pass's block is held (D111.1 Option 1), eleven blocks")
case("scope/no-passes", "hold_scope",
     {"history": hist([B(1), B(2), B(3), B(4, "FAIL")]), "lookback_passes": 2},
     "[OK,[B1,B2,B3,B4],ADMISSION,B1,0]", note="no passed canary: back to the first block after admission")
case("scope/one-pass", "hold_scope",
     {"history": hist([B(1), B(2, "PASS"), B(3), B(4), B(5, "FAIL")]), "lookback_passes": 2},
     "[OK,[B1,B2,B3,B4,B5],ADMISSION,B1,1]", note="fewer passes than LOOKBACK PASSES: back to admission")
case("scope/two-passes-adjacent", "hold_scope",
     {"history": hist([B(1), B(2, "PASS"), B(3, "PASS"), B(4, "FAIL")]), "lookback_passes": 2},
     "[OK,[B2,B3,B4],PASS,B2,2]", note="the two passes are adjacent; the earlier one anchors")
case("scope/two-passes-spread", "hold_scope",
     {"history": hist([B(1), B(2, "PASS"), B(3), B(4), B(5, "PASS"), B(6), B(7, "FAIL")]), "lookback_passes": 2},
     "[OK,[B2,B3,B4,B5,B6,B7],PASS,B2,2]")
H3P = hist([B(1, "PASS"), B(2), B(3, "PASS"), B(4), B(5, "PASS"), B(6, "FAIL")])
case("scope/three-passes-lookback-2", "hold_scope", {"history": H3P, "lookback_passes": 2},
     "[OK,[B3,B4,B5,B6],PASS,B3,2]", note="the oldest pass, B1, lies outside the scope and is not held")
case("scope/lookback-1", "hold_scope", {"history": H3P, "lookback_passes": 1},
     "[OK,[B5,B6],PASS,B5,1]", note="the function is parameterized; the declared value is 2")
case("scope/lookback-3", "hold_scope", {"history": H3P, "lookback_passes": 3},
     "[OK,[B1,B2,B3,B4,B5,B6],PASS,B1,3]")
case("scope/lookback-3-fewer", "hold_scope",
     {"history": hist([B(1), B(2, "PASS"), B(3, "PASS"), B(4, "FAIL")]), "lookback_passes": 3},
     "[OK,[B1,B2,B3,B4],ADMISSION,B1,2]")
case("scope/anchor-is-admission-block", "hold_scope",
     {"history": hist([B(1, "PASS"), B(2, "PASS"), B(3, "FAIL")]), "lookback_passes": 2},
     "[OK,[B1,B2,B3],PASS,B1,2]", note="the second pass back is the admission block itself: kind PASS")
case("scope/failing-block-is-admission-block", "hold_scope",
     {"history": hist([B(1, "FAIL")]), "lookback_passes": 2},
     "[OK,[B1],ADMISSION,B1,0]", note="the first block after admission fails: one block held")
case("scope/passes-before-admission-do-not-anchor", "hold_scope",
     {"history": hist([B(0, "PASS"), B(1, "PASS"), B(2), B(3, "PASS"), B(4, "FAIL")], adm="B2"), "lookback_passes": 2},
     "[OK,[B2,B3,B4],ADMISSION,B2,1]",
     note="B0 and B1 belong to a lapsed certificate (a re-admission): outside the scope, their passes not counted")
case("scope/failure-before-admission-ignored", "hold_scope",
     {"history": hist([B(0, "FAIL"), B(1), B(2, "PASS"), B(3, "FAIL")], adm="B1"), "lookback_passes": 2},
     "[OK,[B1,B2,B3],ADMISSION,B1,1]", note="an earlier failure under the lapsed certificate was its own hold")
case("scope/lookback-parameter-large", "hold_scope", {"history": H11, "lookback_passes": 100},
     "[OK,[B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12],ADMISSION,B1,2]")
# refusals: the edge cases of the spec note, section 5
case("scope/refused/last-block-passed", "hold_scope",
     {"history": hist([B(1), B(2, "PASS")]), "lookback_passes": 2},
     "[REFUSED,history: the last block is not the failing block]",
     note="a pass in the failing block is impossible by construction: a block carries one canary outcome")
case("scope/refused/last-block-no-canary", "hold_scope",
     {"history": hist([B(1, "FAIL"), B(2)]), "lookback_passes": 2},
     "[REFUSED,history: the last block is not the failing block]")
case("scope/refused/earlier-failure-in-scope", "hold_scope",
     {"history": hist([B(1), B(2, "FAIL"), B(3), B(4, "FAIL")]), "lookback_passes": 2},
     "[REFUSED,history: block B2 failed a canary inside the scope; an earlier failure is its own hold]")
case("scope/refused/canary-value", "hold_scope",
     {"history": hist([B(1, "MAYBE"), B(2, "FAIL")]), "lookback_passes": 2},
     "[REFUSED,history: block B1: canary is not null, PASS or FAIL]")
case("scope/refused/canary-two-outcomes", "hold_scope",
     {"history": hist([B(1), B(2, ["PASS", "FAIL"])]), "lookback_passes": 2},
     "[REFUSED,history: block B2: canary is not null, PASS or FAIL]",
     note="a block carries at most one canary outcome")
case("scope/refused/empty-history", "hold_scope", {"history": hist([]), "lookback_passes": 2},
     "[REFUSED,history: blocks is not a non-empty list]")
case("scope/refused/duplicate-block", "hold_scope",
     {"history": hist([B(1), B(1, "FAIL")]), "lookback_passes": 2},
     "[REFUSED,history: duplicate block B1]")
case("scope/refused/admission-unknown", "hold_scope",
     {"history": hist([B(1), B(2, "FAIL")], adm="B9"), "lookback_passes": 2},
     "[REFUSED,history: admission block B9 is not in blocks]")
case("scope/refused/lookback-zero", "hold_scope", {"history": H11, "lookback_passes": 0},
     "[REFUSED,LOOKBACK PASSES is not an integer of at least 1]")
case("scope/refused/lookback-bool", "hold_scope", {"history": H11, "lookback_passes": True},
     "[REFUSED,LOOKBACK PASSES is not an integer of at least 1]")
case("scope/refused/lookback-string", "hold_scope", {"history": H11, "lookback_passes": "2"},
     "[REFUSED,LOOKBACK PASSES is not an integer of at least 1]")
case("scope/refused/block-id-not-text", "hold_scope",
     {"history": hist([{"block_id": 7, "canary": "FAIL"}]), "lookback_passes": 2},
     "[REFUSED,history: block_id is not a name]")
case("scope/refused/block-id-hidden-character", "hold_scope",
     {"history": hist([{"block_id": "B1\u202e", "canary": "FAIL"}]), "lookback_passes": 2},
     "[REFUSED,history: block_id is not a name]", note="text safety (zone schemas 6): refused, not echoed raw")
case("scope/refused/history-not-object", "hold_scope", {"history": "x", "lookback_passes": 2},
     "[REFUSED,history is not an object]")
case("scope/refused/account-missing", "hold_scope",
     {"history": {"admission_block": "B1", "blocks": [B(1, "FAIL")]}, "lookback_passes": 2},
     "[REFUSED,history: account is not a name]")

# ============================================================================
# held_closure: the HELD set of one register
# ============================================================================
def R(rid, block, author, cites=(), assumptions=(), kind="RESULT", status="PROVISIONAL", **flags):
    r = {"id": rid, "block_id": block, "author": author, "cites": list(cites),
         "assumptions": list(assumptions), "kind": kind, "status": status}
    r.update(flags)
    return r


HELD_BLOCKS = ["B2", "B3", "B4"]
SEEDS = {"account": "acct", "blocks": HELD_BLOCKS}
REG = [
    R("RR-1", "B1", "acct"),                              # the account's, before the scope
    R("RR-2", "B2", "acct", status="ESTABLISHED"),        # seed
    R("RR-3", "B3", "other"),                             # another account's, in a held block
    R("RR-4", "B4", "acct", cites=["RR-3"]),              # seed
    R("RR-5", "B9", "other", cites=["RR-2"]),             # depends on a seed
    R("RR-6", "B9", "other", cites=["RR-5"]),             # transitively
    R("RR-7", "B9", "other", cites=["RR-1"]),             # depends on unheld work only
]
case("closure/seeds-and-dependents", "held_closure", {"records": REG, "seeds": SEEDS},
     "[OK,[[RR-2,ESTABLISHED],[RR-4,PROVISIONAL],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[RR-2,RR-4]]",
     note="RR-1 is older work (reviewed, not held); RR-3 is another account's; RR-7 reaches no held record")
case("closure/no-seeds", "held_closure", {"records": REG, "seeds": {"account": "nobody", "blocks": HELD_BLOCKS}},
     "[OK,[],[]]")
case("closure/blocks-empty", "held_closure", {"records": REG, "seeds": {"account": "acct", "blocks": []}},
     "[OK,[],[]]")
A_REG = [
    R("A-1", "B2", "acct", kind="ASSUMPTION"),            # an assumption record the account allocated
    R("RR-8", "B9", "other", assumptions=["A-1", "TFK-A"]),   # ASSUMPTIONS closure reaches it; TFK-A is not a record
    R("RR-9", "B9", "other", assumptions=["TFK-A"]),
]
case("closure/assumptions-propagate", "held_closure", {"records": A_REG, "seeds": SEEDS},
     "[OK,[[A-1,PROVISIONAL],[RR-8,PROVISIONAL]],[A-1]]",
     note="an ASSUMPTIONS citation propagates; an identifier outside the register (the TFK's) is ignored")
CYC = [
    R("RR-1", "B2", "acct", cites=["RR-2"]),
    R("RR-2", "B9", "other", cites=["RR-1"]),
    R("RR-3", "B9", "other", cites=["RR-3"]),             # cites itself, unheld
]
case("closure/cycle-does-not-loop", "held_closure", {"records": CYC, "seeds": SEEDS},
     "[OK,[[RR-1,PROVISIONAL],[RR-2,PROVISIONAL]],[RR-1]]")
CORR = [
    R("RR-1", "B9", "other"),
    R("CO-1", "B3", "acct", cites=["RR-1"], kind="CORROBORATION"),                 # supplied in a held block
    R("CO-2", "B3", "TPX", cites=["RR-1"], kind="CORROBORATION", supplied_by="acct"),   # TPX-written on a ledger MATCH
    R("CO-3", "B1", "acct", cites=["RR-1"], kind="CORROBORATION"),                 # supplied before the scope
    R("CO-4", "B3", "other", cites=["RR-1"], kind="CORROBORATION"),                # another account's
]
case("closure/corroborations-supplied", "held_closure", {"records": CORR, "seeds": SEEDS},
     "[OK,[[CO-1,PROVISIONAL],[CO-2,PROVISIONAL]],[CO-1,CO-2]]",
     note="a corroboration the account supplied is held whether its author field is the account or TPX; RR-1, which it corroborates, is not")
RET = [
    R("RR-1", "B7", "co", vetted_by="acct", vetted_in="B3"),     # carried by a RETURN the account vetted as AI-LEAD, incorporated in B3
    R("RR-2", "B7", "co", vetted_by="acct", vetted_in="B8"),     # vetted outside the scope
    R("RR-3", "B3", "co", vetted_by="acct"),                     # vetted_in absent: the record's own block
    R("RR-4", "B3", "co", vetted_by="lead2"),                    # vetted by another lead
    R("RR-5", "B9", "other", cites=["RR-1"]),
]
case("closure/returns-vetted", "held_closure", {"records": RET, "seeds": SEEDS},
     "[OK,[[RR-1,PROVISIONAL],[RR-3,PROVISIONAL],[RR-5,PROVISIONAL]],[RR-1,RR-3]]")
STAT = [
    R("RR-1", "B2", "acct", status="HELD"),               # already held by another hold: listed with prior HELD
    R("RR-2", "B2", "acct", status="REFUTED"),
    R("RR-3", "B9", "other", cites=["RR-2"], status="ESTABLISHED"),
]
case("closure/prior-status-kept", "held_closure", {"records": STAT, "seeds": SEEDS},
     "[OK,[[RR-1,HELD],[RR-2,REFUTED],[RR-3,ESTABLISHED]],[RR-1,RR-2]]",
     note="the prior status is whatever the record carries; a RELEASE restores it")
ORD = [
    R("RR-10", "B2", "acct"), R("RR-2", "B2", "acct"), R("RR-1", "B9", "other", cites=["RR-10"]),
]
case("closure/sorted-by-code-point", "held_closure", {"records": ORD, "seeds": SEEDS},
     "[OK,[[RR-1,PROVISIONAL],[RR-10,PROVISIONAL],[RR-2,PROVISIONAL]],[RR-10,RR-2]]",
     note="identifiers sort in code point order: RR-1, RR-10, RR-2")
case("closure/refused/duplicate-id", "held_closure",
     {"records": [R("RR-1", "B2", "acct"), R("RR-1", "B3", "acct")], "seeds": SEEDS},
     "[REFUSED,records: duplicate id RR-1]")
case("closure/refused/missing-field", "held_closure",
     {"records": [{"id": "RR-1", "block_id": "B2", "author": "acct", "kind": "RESULT"}], "seeds": SEEDS},
     "[REFUSED,records: RR-1: status is not a name]")
case("closure/refused/cites-not-list", "held_closure",
     {"records": [dict(R("RR-1", "B2", "acct"), cites="RR-2")], "seeds": SEEDS},
     "[REFUSED,records: RR-1: cites is not a list of names]")
case("closure/refused/cites-hidden-character", "held_closure",
     {"records": [R("RR-1", "B2", "acct", cites=["RR-2\u200b"])], "seeds": SEEDS},
     "[REFUSED,records: RR-1: cites is not a list of names]")
case("closure/refused/records-not-list", "held_closure", {"records": "x", "seeds": SEEDS},
     "[REFUSED,records is not a list]")
case("closure/refused/seeds-blocks", "held_closure", {"records": REG, "seeds": {"account": "acct"}},
     "[REFUSED,seeds: blocks is not a list of names]")
case("closure/refused/seeds-account", "held_closure", {"records": REG, "seeds": {"blocks": HELD_BLOCKS}},
     "[REFUSED,seeds: account is not a name]")
case("closure/refused/optional-flag-type", "held_closure",
     {"records": [R("RR-1", "B2", "acct", vetted_by=5)], "seeds": SEEDS},
     "[REFUSED,records: RR-1: vetted_by is not a name]")

# ============================================================================
# tpx_allocate: the reserved range for TPX-written records
# ============================================================================
case("allocate/first", "tpx_allocate", {"range": {"prefix": "RR", "low": 900001, "high": 999999, "next": 900001}},
     "[OK,RR-900001,[RR,900001,999999,900002]]")
case("allocate/last", "tpx_allocate", {"range": {"prefix": "RR", "low": 900001, "high": 900003, "next": 900003}},
     "[OK,RR-900003,[RR,900001,900003,900004]]")
case("allocate/refused/exhausted", "tpx_allocate", {"range": {"prefix": "RR", "low": 900001, "high": 900003, "next": 900004}},
     "[REFUSED,range: the reserved range RR 900001-900003 is exhausted]")
case("allocate/refused/next-below-low", "tpx_allocate", {"range": {"prefix": "RR", "low": 10, "high": 20, "next": 9}},
     "[REFUSED,range: next is not an integer at or above low]")
case("allocate/refused/bounds", "tpx_allocate", {"range": {"prefix": "RR", "low": 20, "high": 10, "next": 20}},
     "[REFUSED,range: low and high are not integers with 1 <= low <= high]")
case("allocate/refused/prefix", "tpx_allocate", {"range": {"prefix": "R R", "low": 1, "high": 9, "next": 1}},
     "[REFUSED,range: prefix is not an identifier]")
case("allocate/refused/next-bool", "tpx_allocate", {"range": {"prefix": "RR", "low": 1, "high": 9, "next": True}},
     "[REFUSED,range: next is not an integer at or above low]")

# ============================================================================
# hold_record: the HOLD record and its digest
# ============================================================================
CAUSE = {"canary_id": "C-77", "account": "acct", "snapshot": "model-2026-01-01", "failing_block": "B4",
         "anchor_kind": "PASS", "anchor_block": "B2", "lookback_passes": 2, "held_blocks": HELD_BLOCKS}
HELD = [["RR-2", "ESTABLISHED"], ["RR-4", "PROVISIONAL"], ["RR-5", "PROVISIONAL"], ["RR-6", "PROVISIONAL"]]
SEED_IDS = ["RR-2", "RR-4"]
PRE_HOLD = ("8:TPC-HOLD1:24:C-774:acct16:model-2026-01-012:B44:PASS2:B21:21:32:B22:B32:B41:24:RR-24:RR-41:4"
            "4:RR-211:ESTABLISHED4:RR-411:PROVISIONAL4:RR-511:PROVISIONAL4:RR-611:PROVISIONAL1:0")
D_HOLD = "e0ae4de0810e8ce5c94a3fe8286c4d7782b3bd358fe0d28797e32b4fd32ae82b"   # sha256sum of PRE_HOLD (form 2)
case("hold/preimage", "hold_preimage", {"cause": CAUSE, "seeds": SEED_IDS, "held": HELD, "biblio": []}, "[OK," + PRE_HOLD + "]",
     note="netstring of [tag, form, canary, account, snapshot, failing block, anchor kind, anchor block, "
          "lookback, n blocks, blocks..., n seeds, seeds..., n held, (id, status)..., n biblio, (bib_id, check)...]; "
          "hold_id is the address, outside it; form 2 (0.2.0) with an empty bibliography list")
case("hold/record", "hold_record", {"hold_id": "RR-900001", "cause": CAUSE, "seeds": SEED_IDS, "held": HELD, "biblio": []},
     "[OK,[RR-900001,HOLD,C-77,acct,model-2026-01-01,B4,PASS,B2,2,[B2,B3,B4],[RR-2,RR-4],"
     "[[RR-2,ESTABLISHED],[RR-4,PROVISIONAL],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[]," + D_HOLD + "]]")
case("hold/record-unsorted-input-sorted-output", "hold_record",
     {"hold_id": "RR-900001", "cause": CAUSE, "seeds": ["RR-4", "RR-2"], "held": list(reversed(HELD)), "biblio": []},
     "[OK,[RR-900001,HOLD,C-77,acct,model-2026-01-01,B4,PASS,B2,2,[B2,B3,B4],[RR-2,RR-4],"
     "[[RR-2,ESTABLISHED],[RR-4,PROVISIONAL],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[]," + D_HOLD + "]]",
     note="the same HOLD, so the same digest, whatever order the lists arrive in")
CAUSE_ADM = dict(CAUSE, anchor_kind="ADMISSION", anchor_block="B1", held_blocks=["B1", "B2", "B3", "B4"], lookback_passes=2)
PRE_ADM = ("8:TPC-HOLD1:24:C-774:acct16:model-2026-01-012:B49:ADMISSION2:B11:21:42:B12:B22:B32:B41:14:RR-21:1"
           "4:RR-211:ESTABLISHED1:0")
D_ADM = "41d4d393186fa61a0b78a0ee77af2e7843f6615d4f352cefec2362fcbcfd4316"   # sha256sum of PRE_ADM (form 2)
case("hold/preimage-admission-anchor", "hold_preimage",
     {"cause": CAUSE_ADM, "seeds": ["RR-2"], "held": [["RR-2", "ESTABLISHED"]], "biblio": []}, "[OK," + PRE_ADM + "]")
case("hold/record-admission-anchor", "hold_record",
     {"hold_id": "RR-900001", "cause": CAUSE_ADM, "seeds": ["RR-2"], "held": [["RR-2", "ESTABLISHED"]], "biblio": []},
     "[OK,[RR-900001,HOLD,C-77,acct,model-2026-01-01,B4,ADMISSION,B1,2,[B1,B2,B3,B4],[RR-2],[[RR-2,ESTABLISHED]],[]," + D_ADM + "]]")
# 0.2.0: the bibliography list (D171 (j)); the list comes from tpc_biblio.biblio_hold_list
BIB = [["RR-BIB2", "NOT FOUND"], ["RR-BIB5", "FIELDS DIFFER"], ["RR-BIB10", "LOOKUP FAILED"]]
PRE_BIB = ("8:TPC-HOLD1:24:C-774:acct16:model-2026-01-012:B44:PASS2:B21:21:32:B22:B32:B41:24:RR-24:RR-41:4"
           "4:RR-211:ESTABLISHED4:RR-411:PROVISIONAL4:RR-511:PROVISIONAL4:RR-611:PROVISIONAL1:3"
           "8:RR-BIB1013:LOOKUP FAILED7:RR-BIB29:NOT FOUND7:RR-BIB513:FIELDS DIFFER")
D_BIB = "37d6e097c9334d5c1d4738673e9c2b5b6fe92274e28e0cd084083daaad2e9d7e"   # sha256sum of PRE_BIB
case("hold/preimage-bibliography", "hold_preimage", {"cause": CAUSE, "seeds": SEED_IDS, "held": HELD, "biblio": BIB},
     "[OK," + PRE_BIB + "]",
     note="the bibliography list after the held pairs: count, then (bib_id, check) pairs sorted by bib_id in code point order "
          "(RR-BIB10 before RR-BIB2); entries are not HELD (D171 (j))")
case("hold/record-bibliography", "hold_record",
     {"hold_id": "RR-900001", "cause": CAUSE, "seeds": SEED_IDS, "held": HELD, "biblio": BIB},
     "[OK,[RR-900001,HOLD,C-77,acct,model-2026-01-01,B4,PASS,B2,2,[B2,B3,B4],[RR-2,RR-4],"
     "[[RR-2,ESTABLISHED],[RR-4,PROVISIONAL],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],"
     "[[RR-BIB10,LOOKUP FAILED],[RR-BIB2,NOT FOUND],[RR-BIB5,FIELDS DIFFER]]," + D_BIB + "]]")
case("hold/record-bibliography-unsorted-input", "hold_record",
     {"hold_id": "RR-900001", "cause": CAUSE, "seeds": SEED_IDS, "held": HELD, "biblio": list(reversed(BIB))},
     "[OK,[RR-900001,HOLD,C-77,acct,model-2026-01-01,B4,PASS,B2,2,[B2,B3,B4],[RR-2,RR-4],"
     "[[RR-2,ESTABLISHED],[RR-4,PROVISIONAL],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],"
     "[[RR-BIB10,LOOKUP FAILED],[RR-BIB2,NOT FOUND],[RR-BIB5,FIELDS DIFFER]]," + D_BIB + "]]",
     note="the same HOLD, so the same digest, whatever order the list arrives in")
case("hold/refused/biblio-confirmed", "hold_record",
     {"hold_id": "RR-900001", "cause": CAUSE, "seeds": SEED_IDS, "held": HELD, "biblio": BIB + [["RR-BIB1", "CONFIRMED"]]},
     "[REFUSED,biblio: entry RR-BIB1 is CONFIRMED; the list holds what is not]",
     note="D171 (j): the HOLD lists the entries whose re-run CHECK is not CONFIRMED")
case("hold/refused/biblio-duplicate", "hold_record",
     {"hold_id": "RR-900001", "cause": CAUSE, "seeds": SEED_IDS, "held": HELD, "biblio": BIB + [["RR-BIB2", "LOOKUP FAILED"]]},
     "[REFUSED,biblio: duplicate entry RR-BIB2]")
case("hold/refused/biblio-shape", "hold_record",
     {"hold_id": "RR-900001", "cause": CAUSE, "seeds": SEED_IDS, "held": HELD, "biblio": [["RR-BIB2"]]},
     "[REFUSED,biblio: entry is not [bib_id, check]]")
case("hold/refused/biblio-not-list", "hold_record",
     {"hold_id": "RR-900001", "cause": CAUSE, "seeds": SEED_IDS, "held": HELD, "biblio": "RR-BIB2"},
     "[REFUSED,biblio is not a list]")
case("hold/refused/biblio-hidden-character", "hold_preimage",
     {"cause": CAUSE, "seeds": SEED_IDS, "held": HELD, "biblio": [["RR-BIB2\u200b", "NOT FOUND"]]},
     "[REFUSED,biblio: entry is not [bib_id, check]]")
case("hold/refused/empty", "hold_record", {"hold_id": "RR-900001", "cause": CAUSE, "seeds": [], "held": [], "biblio": []},
     "[REFUSED,nothing to hold: the held list is empty]",
     note="a HOLD is never written empty; a failing block that landed nothing holds nothing")
case("hold/refused/failing-block-mismatch", "hold_record",
     {"hold_id": "RR-900001", "cause": dict(CAUSE, failing_block="B9"), "seeds": SEED_IDS, "held": HELD, "biblio": []},
     "[REFUSED,cause: failing_block is not the last held block]")
case("hold/refused/anchor-mismatch", "hold_record",
     {"hold_id": "RR-900001", "cause": dict(CAUSE, anchor_block="B3"), "seeds": SEED_IDS, "held": HELD, "biblio": []},
     "[REFUSED,cause: anchor_block is not the first held block]")
case("hold/refused/anchor-kind", "hold_record",
     {"hold_id": "RR-900001", "cause": dict(CAUSE, anchor_kind="PARROT"), "seeds": SEED_IDS, "held": HELD, "biblio": []},
     "[REFUSED,cause: anchor_kind is not PASS or ADMISSION]", note="a passed parrot is not an anchor (handoff 4.5)")
case("hold/refused/seed-not-held", "hold_record",
     {"hold_id": "RR-900001", "cause": CAUSE, "seeds": ["RR-2", "RR-9"], "held": HELD, "biblio": []},
     "[REFUSED,seed RR-9 is not in the held list]")
case("hold/refused/held-shape", "hold_record",
     {"hold_id": "RR-900001", "cause": CAUSE, "seeds": SEED_IDS, "held": [["RR-2"]], "biblio": []},
     "[REFUSED,held: entry is not [id, prior_status]]")
case("hold/refused/held-duplicate", "hold_record",
     {"hold_id": "RR-900001", "cause": CAUSE, "seeds": SEED_IDS, "held": HELD + [["RR-2", "PROVISIONAL"]], "biblio": []},
     "[REFUSED,held: duplicate id RR-2]")
case("hold/refused/cause-missing", "hold_record",
     {"hold_id": "RR-900001", "cause": {"account": "acct"}, "seeds": SEED_IDS, "held": HELD, "biblio": []},
     "[REFUSED,cause: canary_id is not a name]")
case("hold/refused/lookback", "hold_record",
     {"hold_id": "RR-900001", "cause": dict(CAUSE, lookback_passes=0), "seeds": SEED_IDS, "held": HELD, "biblio": []},
     "[REFUSED,cause: lookback_passes is not an integer of at least 1]")
case("hold/refused/hold-id", "hold_record", {"hold_id": "", "cause": CAUSE, "seeds": SEED_IDS, "held": HELD, "biblio": []},
     "[REFUSED,hold_id is not a name]")

# ============================================================================
# release_record: the RELEASE record
# ============================================================================
HOLD = dict(CAUSE, hold_id="RR-900001", seeds=SEED_IDS, held=HELD, biblio=[], digest=D_HOLD)
HOLD_BIB = dict(CAUSE, hold_id="RR-900001", seeds=SEED_IDS, held=HELD, biblio=BIB, digest=D_BIB)
REG_REL = [
    R("RR-1", "B1", "acct"),
    R("RR-2", "B2", "acct", status="HELD"),
    R("RR-3", "B3", "other"),
    R("RR-4", "B4", "acct", cites=["RR-3"], status="HELD"),
    R("RR-5", "B9", "other", cites=["RR-2"], status="HELD"),
    R("RR-6", "B9", "other", cites=["RR-5"], status="HELD"),
    R("RR-7", "B9", "other", cites=["RR-1"]),
]
IND = {"account": "other", "snapshot": "model-2026-02-02", "origin": "REPRODUCTION BLOCK"}
# 0.3.0 (PD-D-5): the trust-tier gate on a ledger MATCH as release_record's fifth parameter,
# the reproducer's facts in tpc_score.tier_gate_release's shape; null for a REPRODUCTION
TIER_OK = {"in_tier": True, "override_in_force": False, "independent_matches": 1}


def tier(in_tier, override, n):
    return {"in_tier": in_tier, "override_in_force": override, "independent_matches": n}


def rep(matched, kind="REPRODUCTION", rid="B12", **ind):
    i = dict(IND)
    i.update(ind)
    return {"kind": kind, "id": rid, "independence": i, "matched": matched}


PRE_REL_2 = ("11:TPC-RELEASE1:29:RR-90000164:" + D_HOLD + "12:REPRODUCTION3:B125:other16:model-2026-02-021:3"
             "4:RR-211:ESTABLISHED4:RR-511:PROVISIONAL4:RR-611:PROVISIONAL1:14:RR-41:0")
D_REL_2 = "e2bf9d00ad4e81c3f04f574cafaa6c22866328ff70137eabc43c013454fd13d0"   # sha256sum of PRE_REL_2 (form 2)
case("release/seed-and-dependents", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"]), "records": REG_REL, "tier": None},
     "[OK,[RR-900002,RELEASE,RR-900001," + D_HOLD + ",REPRODUCTION,B12,other,model-2026-02-02,"
     "[[RR-2,ESTABLISHED],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[RR-4],[]," + D_REL_2 + "]]",
     note="RR-2 reproduced: RR-5 and RR-6, held only through it, are released with it; RR-4 stays held. "
          "Preimage: " + PRE_REL_2)
PRE_REL_ALL = ("11:TPC-RELEASE1:29:RR-90000164:" + D_HOLD + "12:LEDGER_MATCH5:LE-405:other16:model-2026-02-021:4"
               "4:RR-211:ESTABLISHED4:RR-411:PROVISIONAL4:RR-511:PROVISIONAL4:RR-611:PROVISIONAL1:01:0")
D_REL_ALL = "00c2a3056442721e10adbb22c9fbd05581822c491d5fddee75256b85892fc0fc"   # sha256sum of PRE_REL_ALL (form 2)
case("release/ledger-match-all", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-4"], kind="LEDGER_MATCH", rid="LE-40"),
      "records": REG_REL, "tier": TIER_OK},
     "[OK,[RR-900002,RELEASE,RR-900001," + D_HOLD + ",LEDGER_MATCH,LE-40,other,model-2026-02-02,"
     "[[RR-2,ESTABLISHED],[RR-4,PROVISIONAL],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[],[]," + D_REL_ALL + "]]",
     note="a community-ledger MATCH counts on the same independence check (handoff 5.3, 13.3). Preimage: " + PRE_REL_ALL)
# 0.2.0: a RELEASE carries the HOLD's bibliography list unchanged, before its digest
PRE_REL_BIB = ("11:TPC-RELEASE1:29:RR-90000164:" + D_BIB + "12:REPRODUCTION3:B125:other16:model-2026-02-021:3"
               "4:RR-211:ESTABLISHED4:RR-511:PROVISIONAL4:RR-611:PROVISIONAL1:14:RR-41:3"
               "8:RR-BIB1013:LOOKUP FAILED7:RR-BIB29:NOT FOUND7:RR-BIB513:FIELDS DIFFER")
D_REL_BIB = "5ee5a938bb21ff1902f8d50532a7dbb79d302ce2b8bd3775a64fa5f088b8f18d"   # sha256sum of PRE_REL_BIB
case("release/bibliography-carried", "release_record",
     {"release_id": "RR-900002", "hold": HOLD_BIB, "reproduction": rep(["RR-2"]), "records": REG_REL, "tier": None},
     "[OK,[RR-900002,RELEASE,RR-900001," + D_BIB + ",REPRODUCTION,B12,other,model-2026-02-02,"
     "[[RR-2,ESTABLISHED],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[RR-4],"
     "[[RR-BIB10,LOOKUP FAILED],[RR-BIB2,NOT FOUND],[RR-BIB5,FIELDS DIFFER]]," + D_REL_BIB + "]]",
     note="the HOLD's list is carried unchanged: entries are not held and none is released. Preimage: " + PRE_REL_BIB)
case("release/bibliography-unsorted-in-hold", "release_record",
     {"release_id": "RR-900002", "hold": dict(HOLD_BIB, biblio=list(reversed(BIB))), "reproduction": rep(["RR-2"]), "records": REG_REL, "tier": None},
     "[OK,[RR-900002,RELEASE,RR-900001," + D_BIB + ",REPRODUCTION,B12,other,model-2026-02-02,"
     "[[RR-2,ESTABLISHED],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[RR-4],"
     "[[RR-BIB10,LOOKUP FAILED],[RR-BIB2,NOT FOUND],[RR-BIB5,FIELDS DIFFER]]," + D_REL_BIB + "]]")
case("release/refused/hold-missing-biblio", "release_record",
     {"release_id": "RR-900002", "hold": {k: v for k, v in HOLD.items() if k != "biblio"}, "reproduction": rep(["RR-2"]),
      "records": REG_REL, "tier": None},
     "[REFUSED,hold: missing field biblio]", note="a form-1 HOLD object is not read at 0.2.0 (no UWC exists; fixtures only)")
case("release/refused/hold-biblio-confirmed", "release_record",
     {"release_id": "RR-900002", "hold": dict(HOLD_BIB, biblio=BIB + [["RR-BIB1", "CONFIRMED"]]), "reproduction": rep(["RR-2"]),
      "records": REG_REL, "tier": None},
     "[REFUSED,hold: biblio: entry RR-BIB1 is CONFIRMED; the list holds what is not]")
case("release/refused/hold-biblio-digest-moved", "release_record",
     {"release_id": "RR-900002", "hold": dict(HOLD_BIB, biblio=BIB[:2]), "reproduction": rep(["RR-2"]), "records": REG_REL, "tier": None},
     "[REFUSED,hold: digest does not match its fields]", note="the list is inside the HOLD's digest")
case("release/dependent-matched-stays-held", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-5"]), "records": REG_REL, "tier": None},
     "[REFUSED,no held record is released by this reproduction]",
     note="RR-5 reproduced but its derivation cites RR-2, still held: nothing is released")
case("release/refused/same-account", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], account="acct"), "records": REG_REL, "tier": None},
     "[REFUSED,reproduction by the held account is not independent]")
case("release/refused/same-model-flag", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], same_model=True), "records": REG_REL, "tier": None},
     "[REFUSED,reproduction is SAME-MODEL]")
case("release/refused/same-snapshot", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], snapshot="model-2026-01-01"), "records": REG_REL, "tier": None},
     "[REFUSED,reproduction is SAME-MODEL]", note="the reproducing snapshot equals the original's (D42)")
case("release/refused/same-block-origin", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], origin="SAME BLOCK"), "records": REG_REL, "tier": None},
     "[REFUSED,reproduction origin is not REPRODUCTION BLOCK]")
case("release/refused/matched-not-held", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-7"]), "records": REG_REL, "tier": None},
     "[REFUSED,matched record RR-7 is not in the hold]")
case("release/refused/kind", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], kind="PARROT"), "records": REG_REL, "tier": None},
     "[REFUSED,reproduction: kind is not REPRODUCTION or LEDGER_MATCH]")
case("release/refused/hold-digest", "release_record",
     {"release_id": "RR-900002", "hold": dict(HOLD, digest="0" * 64), "reproduction": rep(["RR-2"]), "records": REG_REL, "tier": None},
     "[REFUSED,hold: digest does not match its fields]", note="a HOLD whose fields moved since its digest is refused")
case("release/refused/hold-field-missing", "release_record",
     {"release_id": "RR-900002", "hold": {k: v for k, v in HOLD.items() if k != "seeds"}, "reproduction": rep(["RR-2"]),
      "records": REG_REL, "tier": None},
     "[REFUSED,hold: missing field seeds]")
case("release/refused/held-record-missing", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"]), "records": REG_REL[:4], "tier": None},
     "[REFUSED,held record RR-5 is not in records]")
case("release/refused/independence-missing", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": {"kind": "REPRODUCTION", "id": "B12", "matched": ["RR-2"]},
      "records": REG_REL, "tier": None},
     "[REFUSED,reproduction: independence is not an object]")
case("release/refused/same-model-not-bool", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"], same_model="no"), "records": REG_REL, "tier": None},
     "[REFUSED,reproduction: independence same_model is not a boolean]")
case("release/refused/matched-duplicate", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-2"]), "records": REG_REL, "tier": None},
     "[REFUSED,reproduction: matched is not a list of distinct names]")


# ---- 0.3.0: the trust-tier gate (PD-D-5; TPS 3.3.15; CR11; D119.1, D123.1 T6) ----------------
# Expectations by hand from the rule: a ledger MATCH releases only when the reproducer is in
# the TRUST TIER and, while an OVERRIDE mark is in force, has at least two independent
# matches; the gate is one more refusal after the eligibility checks (account, SAME-MODEL,
# origin); tier's shape is checked with the reproduction's; a REPRODUCTION carries no tier.
OK_ALL = ("[OK,[RR-900002,RELEASE,RR-900001," + D_HOLD + ",LEDGER_MATCH,LE-40,other,model-2026-02-02,"
          "[[RR-2,ESTABLISHED],[RR-4,PROVISIONAL],[RR-5,PROVISIONAL],[RR-6,PROVISIONAL]],[],[]," + D_REL_ALL + "]]")
LM = rep(["RR-2", "RR-4"], kind="LEDGER_MATCH", rid="LE-40")
case("release/tier/override-two-matches", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, True, 2)},
     OK_ALL, note="an overridden account's match releases with a second independent match (D123.1 T6); "
                  "the tier's facts enter no field of the RELEASE, so its digest is the one of ledger-match-all")
case("release/tier/in-tier-many-matches", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, False, 1000000000)},
     OK_ALL, note="COUNT_MAX matches, no mark")
case("release/refused/tier-not-in-tier", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(False, False, 1)},
     "[REFUSED,trust-tier gate: NOT IN TIER]", note="only a TRUST TIER member's match releases (TPS 3.3.15; CR11)")
case("release/refused/tier-override-one-match", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, True, 1)},
     "[REFUSED,trust-tier gate: OVERRIDE MARK]", note="a sole match of an overridden account (D123.1 T6)")
case("release/refused/tier-override-zero", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, True, 0)},
     "[REFUSED,trust-tier gate: OVERRIDE MARK]")
case("release/refused/tier-not-in-tier-and-marked", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(False, True, 0)},
     "[REFUSED,trust-tier gate: NOT IN TIER]", note="NOT IN TIER is tested first, as tier_gate_release does")
case("release/refused/tier-null-for-ledger-match", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": None},
     "[REFUSED,tier is not an object]", note="a ledger MATCH needs the reproducer's facts")
case("release/refused/tier-list-for-ledger-match", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": []},
     "[REFUSED,tier is not an object]")
case("release/refused/tier-given-for-reproduction", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"]), "records": REG_REL, "tier": TIER_OK},
     "[REFUSED,tier is given for a REPRODUCTION]",
     note="the gate is a ledger MATCH's (TPS 3.3.15); a tier given with a REPRODUCTION is refused, so no caller "
          "believes it ran (RD-TP-7)")
case("release/refused/tier-unknown-field", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL,
      "tier": dict(TIER_OK, x=1, a=2)},
     "[REFUSED,tier: unknown field a]", note="the least unknown field in code point order")
case("release/refused/tier-missing-field", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL,
      "tier": {"override_in_force": False}},
     "[REFUSED,tier: missing field in_tier]", note="missing fields in the order in_tier, override_in_force, "
                                                   "independent_matches")
case("release/refused/tier-missing-count", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL,
      "tier": {"in_tier": True, "override_in_force": False}},
     "[REFUSED,tier: missing field independent_matches]")
case("release/refused/tier-in-tier-not-bool", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(1, False, 1)},
     "[REFUSED,tier: in_tier is not a boolean]")
case("release/refused/tier-override-not-bool", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, "no", 1)},
     "[REFUSED,tier: override_in_force is not a boolean]")
case("release/refused/tier-count-bool", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, False, True)},
     "[REFUSED,tier: independent_matches is not a count]", note="a boolean is not a count")
case("release/refused/tier-count-negative", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, False, -1)},
     "[REFUSED,tier: independent_matches is not a count]")
case("release/refused/tier-count-too-large", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL,
      "tier": tier(True, False, 1000000001)},
     "[REFUSED,tier: independent_matches is not a count]", note="past COUNT_MAX (tpc_score)")
case("release/refused/tier-count-float", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": tier(True, False, 1.0)},
     "[REFUSED,tier: independent_matches is not a count]", note="1.0 is a JSON number that is not an integer text")
case("release/refused/tier-shape-before-eligibility", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-4"], kind="LEDGER_MATCH", rid="LE-40",
                                                                   account="acct"),
      "records": REG_REL, "tier": {"in_tier": True}},
     "[REFUSED,tier: missing field override_in_force]",
     note="tier's shape is read with the reproduction's shape, before eligibility")
case("release/refused/same-model-before-gate", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-4"], kind="LEDGER_MATCH", rid="LE-40",
                                                                   same_model=True),
      "records": REG_REL, "tier": tier(False, False, 1)},
     "[REFUSED,reproduction is SAME-MODEL]", note="the gate follows the eligibility checks (TPS 3.3.15)")
case("release/refused/gate-before-matched-check", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2", "RR-7"], kind="LEDGER_MATCH", rid="LE-40"),
      "records": REG_REL, "tier": tier(False, False, 1)},
     "[REFUSED,trust-tier gate: NOT IN TIER]", note="the gate closes the eligibility check; matched ids are checked after")



# ---- 0.3.0 (C-MS-5; increment 11): a JSON {} and a JSON [] are told apart -------------
# Expectations by hand from tpc_hold's reading order; each case is one an assoc-array
# reading answered otherwise, or a valid empty object.
case("decode/scope-history-list", "hold_scope", {"history": [], "lookback_passes": 2},
     "[REFUSED,history is not an object]")
case("decode/scope-blocks-object", "hold_scope",
     {"history": {"account": "acct", "admission_block": "B1", "blocks": {}}, "lookback_passes": 2},
     "[REFUSED,history: blocks is not a non-empty list]")
case("decode/scope-blocks-zero-keyed", "hold_scope",
     {"history": {"account": "acct", "admission_block": "B1", "blocks": {"0": B(1, "FAIL")}}, "lookback_passes": 2},
     "[REFUSED,history: blocks is not a non-empty list]", note="it read as the list [B1] and held B1")
case("decode/scope-block-list", "hold_scope",
     {"history": {"account": "acct", "admission_block": "B1", "blocks": [[]]}, "lookback_passes": 2},
     "[REFUSED,history: block is not an object]")
case("decode/closure-records-object", "held_closure", {"records": {}, "seeds": SEEDS}, "[REFUSED,records is not a list]",
     note="it read as no record and answered OK with nothing held")
case("decode/closure-records-zero-keyed", "held_closure", {"records": {"0": REG[1]}, "seeds": SEEDS},
     "[REFUSED,records is not a list]")
case("decode/closure-record-list", "held_closure", {"records": [[]], "seeds": SEEDS},
     "[REFUSED,records: entry is not an object]")
case("decode/closure-cites-object", "held_closure", {"records": [dict(REG[1], cites={})], "seeds": SEEDS},
     "[REFUSED,records: RR-2: cites is not a list of names]")
case("decode/closure-seeds-list", "held_closure", {"records": REG, "seeds": []}, "[REFUSED,seeds is not an object]")
case("decode/closure-seeds-blocks-zero-keyed", "held_closure",
     {"records": REG, "seeds": {"account": "acct", "blocks": {"0": "B2"}}},
     "[REFUSED,seeds: blocks is not a list of names]")
case("decode/allocate-range-list", "tpx_allocate", {"range": []}, "[REFUSED,range is not an object]")
case("decode/allocate-range-empty-object", "tpx_allocate", {"range": {}}, "[REFUSED,range: prefix is not an identifier]")
case("decode/hold-cause-list", "hold_record",
     {"hold_id": "RR-900001", "cause": [], "seeds": SEED_IDS, "held": HELD, "biblio": []},
     "[REFUSED,cause is not an object]")
case("decode/hold-seeds-object", "hold_record",
     {"hold_id": "RR-900001", "cause": CAUSE, "seeds": {}, "held": HELD, "biblio": []},
     "[REFUSED,seeds is not a list of distinct names]")
case("decode/hold-biblio-object", "hold_preimage", {"cause": CAUSE, "seeds": SEED_IDS, "held": HELD, "biblio": {}},
     "[REFUSED,biblio is not a list]")
case("decode/release-hold-list", "release_record",
     {"release_id": "RR-900002", "hold": [], "reproduction": rep(["RR-2"]), "records": REG_REL, "tier": None},
     "[REFUSED,hold is not an object]")
case("decode/release-reproduction-list", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": [], "records": REG_REL, "tier": None},
     "[REFUSED,reproduction is not an object]")
case("decode/release-independence-list", "release_record",
     {"release_id": "RR-900002", "hold": HOLD,
      "reproduction": {"kind": "REPRODUCTION", "id": "B12", "independence": [], "matched": ["RR-2"]},
      "records": REG_REL, "tier": None},
     "[REFUSED,reproduction: independence is not an object]")
case("decode/release-independence-empty-object", "release_record",
     {"release_id": "RR-900002", "hold": HOLD,
      "reproduction": {"kind": "REPRODUCTION", "id": "B12", "independence": {}, "matched": ["RR-2"]},
      "records": REG_REL, "tier": None},
     "[REFUSED,reproduction: independence account is not a name]")
case("decode/release-matched-zero-keyed", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": dict(rep(["RR-2"]), matched={"0": "RR-2"}),
      "records": REG_REL, "tier": None},
     "[REFUSED,reproduction: matched is not a list of distinct names]")
case("decode/release-tier-empty-object", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": {}},
     "[REFUSED,tier: missing field in_tier]", note="an empty tier object: every field missing, in_tier first")
case("decode/release-tier-zero-keyed", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": LM, "records": REG_REL, "tier": {"0": True}},
     "[REFUSED,tier: unknown field 0]")
case("decode/release-records-object", "release_record",
     {"release_id": "RR-900002", "hold": HOLD, "reproduction": rep(["RR-2"]), "records": {}, "tier": None},
     "[REFUSED,records is not a list]")


def dispatch(fn, i):
    if fn == "hold_scope":
        return H.hold_scope(i["history"], i["lookback_passes"])
    if fn == "held_closure":
        return H.held_closure(i["records"], i["seeds"])
    if fn == "tpx_allocate":
        return H.tpx_allocate(i["range"])
    if fn == "hold_preimage":
        return H.hold_preimage(i["cause"], i["seeds"], i["held"], i["biblio"])
    if fn == "hold_record":
        return H.hold_record(i["hold_id"], i["cause"], i["seeds"], i["held"], i["biblio"])
    if fn == "release_record":
        return H.release_record(i["release_id"], i["hold"], i["reproduction"], i["records"], i["tier"])
    raise KeyError(fn)


if __name__ == "__main__":
    if len(sys.argv) > 1 and sys.argv[1] == "--preimages":
        for name, pre in (("PRE_HOLD", PRE_HOLD), ("PRE_ADM", PRE_ADM), ("PRE_BIB", PRE_BIB), ("PRE_REL_2", PRE_REL_2),
                          ("PRE_REL_ALL", PRE_REL_ALL), ("PRE_REL_BIB", PRE_REL_BIB)):
            print(name, pre)
        sys.exit(0)
    bad = 0
    for c in cases:
        got = S.canon(dispatch(c["fn"], c["input"]))
        if got != c["expect"]:
            bad += 1
            print("MISMATCH", c["id"], "\n  expect", c["expect"], "\n  got   ", got)
    if bad:
        sys.exit("refusing to write: %d mismatches" % bad)
    # PD-D-5: the gate in release_record is tpc_score.tier_gate_release's rule; checked on the grid
    import tpc_score as SC
    for t_in in (True, False):
        for t_ov in (True, False):
            for t_n in (0, 1, 2, 3):
                g = SC.tier_gate_release({"in_tier": t_in, "override_in_force": t_ov, "independent_matches": t_n})
                r = H.release_record("RR-900002", HOLD, LM, REG_REL, tier(t_in, t_ov, t_n))
                want = ["OK"] if g["status"] == "PASS" else ["REFUSED", "trust-tier gate: " + g["reason"]]
                if r[:len(want)] != want:
                    sys.exit("refusing to write: the gate differs from tier_gate_release at %r" % ((t_in, t_ov, t_n),))
    corpus = {
        "meta": {
            "name": "tpc_hold_corpus", "version": "0.3.0",
            "status": "RE-ISSUED 2026-09-28 for tpc_hold 0.3.0 (PD-D-5: the trust-tier gate as release_record's "
                      "fifth parameter); increment 11 of TPC step 2, proposed with TPC-PY 0.2.0, unreleased",
            "conforms_tps": "0.3.0 (3.3.11 HOLD form 2, 3.3.12 RELEASE, 3.3.13 propagation, 3.3.15 the gate on a "
                            "ledger MATCH); the RELEASE digest's form number is the built \"2\" (DI-TP-1)",
            "module": "tpc_hold 0.3.0 (tpc_digest 0.1.0, tpc_zone 0.5.1)",
            "note": ("Expectations hand-derived from tpm_hold_scope 0.2.0: scopes counted on paper, closures traced by "
                     "hand, refusals from the edge-case table and the gate's rule. Every digest is an external "
                     "sha256sum over the preimage its case shows. Deterministic; no randomness. Both residences "
                     "MUST reproduce every expect. 0.3.0 adds 21 tier cases (PD-D-5) and 23 decode/ cases "
                     "(C-MS-5: a JSON {} and [] and an object keyed 0 read as written in both residences); every "
                     "release_record case carries tier. No earlier answer moves.")
        },
        "cases": cases,
    }
    open(os.path.join(HERE, "vectors", "hold_corpus.json"), "w", encoding="utf-8", newline="\n").write(
        json.dumps(corpus, indent=1, ensure_ascii=True) + "\n")
    print("wrote", len(cases), "hold cases; all match literal expectations")