[FIX] Discrimination gate: a mechanical answer to the check-certifies-code class
Steward asked whether we can do something about the recurring class other than
name it. This is the mechanical part of the answer.
THE CLASS: four times in three days a passing check certified a property of the
CODE while claiming a property of the RESULT, each found by a person looking.
Every one tested a predicate NECESSARY but not SUFFICIENT for the property —
quotes-present ⊂ inference-survives; answer-non-empty ⊂ answer-produced;
no-heading-says-limitations ⊂ no-collected-limitations-section.
WHY THE POSITIVE CONTROLS MISSED IT: the fixtures were derived from the CHECK
('what makes this regex fail?') rather than from the PROPERTY ('what makes this
claim false?'). A control built from the check's own vocabulary inherits its
blind spot by construction — same shape as the recorded drift-pattern that a
control built by EXTRACTION leaks by construction.
THE GATE: a check must return DIFFERENT verdicts on two REAL artifacts, one known
to have the property and one known to lack it. Same verdict on both means it has
discriminated nothing, however many synthetic fixtures it passes. Real artifacts,
because a synthetic negative is written by the same hand as the check.
DEMONSTRATED, not asserted: the gate is run against the §3.3 pattern AS SHIPPED,
and rejects it — flagged=False on both the package (which has a collected
limitations section, Part VII) and the ruling (which has none). It discriminated
nothing while passing five synthetic fixtures. The current pattern passes.
Residue stated in the code rather than implied: a heading naming no topic
('## Part VII') defeats every wordlist, and the gate prints that it does. Passing
is not a §2a verdict; §2a stays in Kernel §4's judgement.
This commit is contained in:
+130
@@ -0,0 +1,130 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Discrimination gate — the answer to a class, not to an instance.
|
||||||
|
|
||||||
|
THE CLASS
|
||||||
|
Four times in three days a passing check certified a property of the CODE
|
||||||
|
while claiming a property of the RESULT, and every one was found by a person
|
||||||
|
looking at the output rather than by any check:
|
||||||
|
|
||||||
|
· vignette — a field colour bound to a class no element carried
|
||||||
|
· trial 03 — `degraded: null` on a run that produced no answer at all
|
||||||
|
· splitter — five defects, all found by contact with a real document
|
||||||
|
· §3.3 — a FALSE PASS on a package whose Part VII is a collected
|
||||||
|
limitations section
|
||||||
|
|
||||||
|
Each check tested a predicate NECESSARY but not SUFFICIENT for the property.
|
||||||
|
Quotes-present is a subset of inference-survives. Answer-non-empty is a subset
|
||||||
|
of answer-produced. No-heading-says-"limitations" is a subset of no-collected-
|
||||||
|
limitations-section.
|
||||||
|
|
||||||
|
WHY THE EXISTING POSITIVE CONTROLS DID NOT CATCH IT
|
||||||
|
Because the fixtures were derived from the CHECK ("what makes this regex
|
||||||
|
fail?") instead of from the PROPERTY ("what makes this claim false?"). A
|
||||||
|
control built out of the check's own vocabulary inherits its blind spot by
|
||||||
|
construction — the same shape as the recorded drift-pattern that a control
|
||||||
|
built by EXTRACTION leaks by construction.
|
||||||
|
|
||||||
|
THE GATE
|
||||||
|
A check must return DIFFERENT verdicts on two REAL artifacts, one known to
|
||||||
|
have the property and one known to lack it. Same verdict on both means the
|
||||||
|
check has discriminated nothing, however many synthetic fixtures it passes.
|
||||||
|
|
||||||
|
Real artifacts, not synthetic — a synthetic negative is written by the same
|
||||||
|
hand as the check and shares its assumptions.
|
||||||
|
|
||||||
|
Usage: ./test_discrimination.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||||
|
from reduce import FORBIDDEN_HEADING_RE, TAGGABLE, split_spans # noqa: E402
|
||||||
|
|
||||||
|
GOV = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
# Two real governance documents, and the ground truth about them established by
|
||||||
|
# READING, not by running the check.
|
||||||
|
#
|
||||||
|
# RULING — has no section collecting the author's own caveats. Its
|
||||||
|
# qualifications are woven into the determinations themselves.
|
||||||
|
# PACKAGE — Part VII, "Disconfirming evidence, which the steward specifically
|
||||||
|
# asked to be carried", collects them. Trial 03 is the evidence that
|
||||||
|
# this matters: the model located that section, classified it as
|
||||||
|
# author-named limitation, and skipped its contents wholesale.
|
||||||
|
RULING = GOV / "skill-harvest-fix-lane-JURIST-RULING-2026-08-01.md"
|
||||||
|
PACKAGE = GOV / "differently-biased-checkers-JURIST-PACKAGE-2026-08-01.md"
|
||||||
|
|
||||||
|
# The pattern as it shipped, before Reduction 02. Kept verbatim so the gate can be
|
||||||
|
# shown catching a defect that really occurred, rather than one invented for it.
|
||||||
|
PATTERN_BEFORE_FIX = re.compile(
|
||||||
|
r"limitation|caveat|assumption|what this does not|open question", re.IGNORECASE
|
||||||
|
)
|
||||||
|
|
||||||
|
failures: list[str] = []
|
||||||
|
|
||||||
|
|
||||||
|
def flags_collected_section(pattern: re.Pattern, doc: Path) -> bool:
|
||||||
|
"""Run the §3.3 screen over a document's headings."""
|
||||||
|
text = doc.read_text(encoding="utf-8")
|
||||||
|
for sp in split_spans(text):
|
||||||
|
if sp["kind"] == "heading" and sp["kind"] in TAGGABLE:
|
||||||
|
if pattern.search(text[sp["start"]:sp["end"]]):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def discriminates(pattern: re.Pattern, label: str) -> bool:
|
||||||
|
has = flags_collected_section(pattern, PACKAGE) # ground truth: HAS one
|
||||||
|
lacks = flags_collected_section(pattern, RULING) # ground truth: LACKS one
|
||||||
|
verdict = has and not lacks
|
||||||
|
print(f" {label}")
|
||||||
|
print(f" package (has a collected section) → flagged={has}")
|
||||||
|
print(f" ruling (has none) → flagged={lacks}")
|
||||||
|
print(f" discriminates: {verdict}")
|
||||||
|
return verdict
|
||||||
|
|
||||||
|
|
||||||
|
for p in (RULING, PACKAGE):
|
||||||
|
if not p.is_file():
|
||||||
|
failures.append(f"real artifact missing: {p.name} — the gate did not run")
|
||||||
|
|
||||||
|
if not failures:
|
||||||
|
print("§3.3 — collected-limitations screen, against two real documents:\n")
|
||||||
|
|
||||||
|
# 1. The gate must FAIL the pattern that actually shipped. If it passes this,
|
||||||
|
# the gate cannot catch the defect it was built for and is worthless.
|
||||||
|
if discriminates(PATTERN_BEFORE_FIX, "as shipped, before Reduction 02:"):
|
||||||
|
failures.append(
|
||||||
|
"THE GATE IS BLIND: the pre-fix pattern discriminated, but it is known "
|
||||||
|
"to have FALSE-PASSED the package. The gate proves nothing."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print(" → correctly REJECTED. The gate catches the real defect.\n")
|
||||||
|
|
||||||
|
# 2. The current pattern must pass.
|
||||||
|
if not discriminates(FORBIDDEN_HEADING_RE, "current:"):
|
||||||
|
failures.append("current §3.3 pattern does not discriminate on real documents")
|
||||||
|
else:
|
||||||
|
print(" → accepted.\n")
|
||||||
|
|
||||||
|
# 3. And the limit is stated rather than implied: a section titled only
|
||||||
|
# "Part VII" defeats any wordlist. Passing this gate is not a §2a verdict.
|
||||||
|
bare = re.compile(r"^## Part VII$", re.MULTILINE)
|
||||||
|
print(" residue, stated: a heading naming no topic defeats every wordlist —")
|
||||||
|
print(f" '## Part VII' matched by the current screen: "
|
||||||
|
f"{bool(FORBIDDEN_HEADING_RE.search('## Part VII'))}")
|
||||||
|
print(" so §3.3 is a SCREEN. §2a compliance stays in Kernel §4 judgement.")
|
||||||
|
assert bare # keep the illustration honest about what it is
|
||||||
|
|
||||||
|
if failures:
|
||||||
|
print(f"\nDISCRIMINATION GATE FAILED — {len(failures)}:")
|
||||||
|
for f in failures:
|
||||||
|
print(f" - {f}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print("\nDiscrimination gate passed, and shown rejecting the pattern that shipped.")
|
||||||
Reference in New Issue
Block a user