port: audit every kind label, and seven rested on a neighbour's argument
tools/port/audit-kinds reports what each in authored/ rests on. Nothing had ever checked them, which is the point -- the disciplines that fail this way are the ones that never visibly failed. Seven of fifteen labels, every goto_name_kind, had no of their own. Four scored ok on the first run because the audit fell back to the parent's , which argues the DESTINATION while the label is about where the NAME came from. That is the same error I was corrected for the previous iteration, one level down: crediting a claim with evidence that does not bear on it. Borrowed evidence is now its own outcome, and all seven carry a why citing HANDOFF Q4's own words and stating that the port never branches on the field. The audit refuted itself twice first. It counted only paths, shas and filenames as citations, so HANDOFF Q1 and PORT-MISSION section 7 read as citing nothing -- four false positives, and an audit that invents defects is worse than none because its false positives are indistinguishable from its true ones until each is opened. It also resolved paths against committed refs only, failing on a citation to the tool being written. Both fixed. It still cannot read a cited page to confirm it says what the why claims, and prints that every run. MEASURED and measured both existed; a consumer comparing == measured misses the other, and a label that fails to match reads as ABSENT rather than wrong. Normalised. Refutation attempt on HANDOFF Q2's map of GP_TITLE. The headline survives and is exactly right: 4 UI states + 2 loading variants + 2 boot splashes = 8 states shipped twice = the 16 entries the archive holds, confirmed against my export's entry map. But the row enumerates six of those eight -- entries 10, 11, 13 and 14, publisher_logo and developer_logos, appear nowhere in it. A reader counting Q2 gets twelve, and this is the row already corrected once for an ordinal-versus- entry error, which is the mistake four unlisted entries feed. The port is unaffected; both splashes are exported, named and verified at RMSE 2.17 and 3.05. Every asserting check passes, audit-kinds included. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N7FiFFFwbvG2uxdcEh8HyF
This commit is contained in:
173
tools/port/audit-kinds
Executable file
173
tools/port/audit-kinds
Executable file
@@ -0,0 +1,173 @@
|
||||
#!/usr/bin/env python3
|
||||
"""What does each `kind` label in `authored/` actually REST on?
|
||||
|
||||
Every authored entry carries a `kind` -- `measured`, `authored`, `name match,
|
||||
not measured` -- and a `why`. The label is the load-bearing part: `measured`
|
||||
means the port is repeating something observed off the running game, and a
|
||||
reader downstream will treat it as fact.
|
||||
|
||||
Nothing has ever checked them. That is the point: **a discipline that has never
|
||||
visibly failed is the one nothing directs attention at.** The Decoder reached
|
||||
this from the input side -- Ⓐ and Ⓑ were delivery-confirmed because they had
|
||||
once broken, so the d-pad never was -- and on the same day a `measured` label of
|
||||
mine turned out to rest on a single entry that may have been measuring history.
|
||||
|
||||
So this checks what is checkable about a label, and is explicit that the rest is
|
||||
not:
|
||||
|
||||
citations resolvable references in the `why` -- a `docs/` path that exists on
|
||||
some ref, a commit sha that resolves, a capture filename
|
||||
BARE a label whose `why` cites nothing a reader could go and open
|
||||
DANGLING a citation that does not resolve anywhere in the repository
|
||||
|
||||
🔴 What it CANNOT do is read the cited page and confirm it says what the `why`
|
||||
claims. A label with three resolvable citations can still be wrong. This narrows
|
||||
"which labels rest on nothing" from unknown to a list; it does not audit meaning.
|
||||
"""
|
||||
import json, glob, os, re, subprocess, sys
|
||||
|
||||
REFS = None
|
||||
|
||||
|
||||
def known_paths():
|
||||
"""Every path in the repo, across ALL refs -- docs/re/ lives on a branch.
|
||||
|
||||
Checked against the working tree as well: a file added this iteration is not
|
||||
in any ref yet, and reporting a citation to it as unresolvable would make the
|
||||
audit fail every time it is itself referenced.
|
||||
"""
|
||||
global REFS
|
||||
if REFS is None:
|
||||
out = subprocess.run(["git", "rev-list", "--all", "--objects"],
|
||||
capture_output=True, text=True).stdout
|
||||
REFS = {l.split(" ", 1)[1] for l in out.splitlines() if " " in l}
|
||||
return REFS
|
||||
|
||||
|
||||
HANDOFF_TEXT = None
|
||||
|
||||
|
||||
def handoff():
|
||||
"""The live HANDOFF, so a cited Q number is checked against the real table."""
|
||||
global HANDOFF_TEXT
|
||||
if HANDOFF_TEXT is None:
|
||||
sha = subprocess.run(["git", "log", "--all", "--format=%h", "--",
|
||||
"docs/port/HANDOFF.md"], capture_output=True,
|
||||
text=True).stdout.split()[0]
|
||||
HANDOFF_TEXT = subprocess.run(["git", "show", f"{sha}:docs/port/HANDOFF.md"],
|
||||
capture_output=True, text=True).stdout
|
||||
return HANDOFF_TEXT
|
||||
|
||||
|
||||
def sha_ok(s):
|
||||
r = subprocess.run(["git", "cat-file", "-e", s + "^{commit}"], capture_output=True)
|
||||
return r.returncode == 0
|
||||
|
||||
|
||||
def text_of(why):
|
||||
if isinstance(why, str):
|
||||
return why
|
||||
if isinstance(why, list):
|
||||
return " ".join(str(x) for x in why)
|
||||
return ""
|
||||
|
||||
|
||||
def citations(t):
|
||||
"""References a reader could actually follow."""
|
||||
out = []
|
||||
for p in re.findall(r"\b(?:docs|crates|port|tools|authored)/[\w./-]+\w", t):
|
||||
out.append(("path", p.rstrip(".,")))
|
||||
for s in re.findall(r"\b([0-9a-f]{7,40})\b", t):
|
||||
out.append(("sha", s))
|
||||
for p in re.findall(r"\b([\w-]+\.(?:png|txt|tsv|wav))\b", t):
|
||||
out.append(("file", p))
|
||||
# The corpus cites two things that are not paths and are still followable:
|
||||
# a HANDOFF question number, and a MISSION section. Leaving these out made
|
||||
# the first run report four labels as resting on nothing when they rest on
|
||||
# the two documents the mission names -- an audit inventing defects is worse
|
||||
# than no audit, because its false positives are indistinguishable from its
|
||||
# true ones until each is opened.
|
||||
for q in re.findall(r"HANDOFF Q(\d+)", t):
|
||||
out.append(("handoff", "Q" + q))
|
||||
for m in re.findall(r"(PORT-MISSION|MISSION)[ ]section[ ](\d+)", t):
|
||||
out.append(("mission", m[1]))
|
||||
for r in re.findall(r"MODDING rule (\d+)", t):
|
||||
out.append(("modding", r))
|
||||
return out
|
||||
|
||||
|
||||
def walk(o, f, path, out):
|
||||
if isinstance(o, dict):
|
||||
for k, v in o.items():
|
||||
if (k == "kind" or k.endswith("_kind")) and isinstance(v, str):
|
||||
stem = "" if k == "kind" else k[: -len("_kind")]
|
||||
own = o.get((stem + "_why") if stem else "why")
|
||||
# 🔴 An earlier version fell back to the parent's `why` when a
|
||||
# label had none of its own, and reported the result as `ok`.
|
||||
# That credits a label with evidence for a DIFFERENT claim:
|
||||
# every `goto_name_kind` scored on a sibling `why` about the
|
||||
# DESTINATION, while the label is about where the NAME came
|
||||
# from. Borrowed evidence is now its own outcome, because a
|
||||
# label resting on a neighbour's argument is exactly the case
|
||||
# this audit exists to surface.
|
||||
out.append((f, path + "/" + k, v, text_of(own),
|
||||
own is None and bool(text_of(o.get("why")))))
|
||||
walk(v, f, path + "/" + k, out)
|
||||
elif isinstance(o, list):
|
||||
for x in o:
|
||||
walk(x, f, path, out)
|
||||
|
||||
|
||||
def main():
|
||||
rows = []
|
||||
for f in sorted(glob.glob("authored/*.json")):
|
||||
walk(json.load(open(f)), f, "", rows)
|
||||
paths = known_paths()
|
||||
bare = dangling = 0
|
||||
kinds = {}
|
||||
print(f" {len(rows)} kind label(s) in authored/\n")
|
||||
for f, where, kind, why, borrowed in rows:
|
||||
kinds.setdefault(kind, 0)
|
||||
kinds[kind] += 1
|
||||
cites = citations(why)
|
||||
bad = []
|
||||
for typ, c in cites:
|
||||
if typ == "handoff":
|
||||
if not re.search(rf"\|\s*{c}\s*\|", handoff()):
|
||||
bad.append(f"HANDOFF {c} (no such row)")
|
||||
elif typ == "path" and c not in paths and not os.path.exists(c):
|
||||
bad.append(c)
|
||||
elif typ == "sha" and not sha_ok(c):
|
||||
bad.append(c)
|
||||
mark = "ok "
|
||||
if not cites and borrowed:
|
||||
mark, bare = "🔴 BORROW", bare + 1
|
||||
elif not cites:
|
||||
mark, bare = "🔴 BARE", bare + 1
|
||||
elif bad:
|
||||
mark, dangling = "🔴 DANGL", dangling + 1
|
||||
print(f" {mark} {kind:<24} {f.split('/')[-1]}{where}")
|
||||
if not cites and borrowed:
|
||||
print(" no `why` of its own; a sibling `why` argues a"
|
||||
" DIFFERENT claim")
|
||||
elif not cites:
|
||||
print(f" cites nothing openable -- {len(why)} chars of prose")
|
||||
elif bad:
|
||||
print(f" unresolvable: {', '.join(sorted(set(bad))[:4])}")
|
||||
else:
|
||||
print(f" {len(cites)} citation(s), all resolve")
|
||||
print()
|
||||
# Casing is checked because a consumer comparing == "measured" silently
|
||||
# misses "MEASURED", and a label that fails to match reads as absent.
|
||||
variants = [k for k in kinds if k.lower() == "measured"]
|
||||
if len(variants) > 1:
|
||||
print(f" ⚠️ {len(variants)} spellings of the same label: {variants}")
|
||||
print(" A consumer comparing == 'measured' misses the others, and a")
|
||||
print(" label that fails to match reads as ABSENT, not as wrong.\n")
|
||||
print(f" {bare} bare or borrowed, {dangling} dangling, {len(rows) - bare - dangling} with resolving citations")
|
||||
print(" 🔴 A resolving citation is not a verified label. Nothing here reads")
|
||||
print(" the cited page to confirm it says what the `why` claims.")
|
||||
return 1 if (bare or dangling) else 0
|
||||
|
||||
|
||||
sys.exit(main())
|
||||
@@ -45,6 +45,10 @@ step format-validator must-pass "$BIN" check
|
||||
step contract-values must-pass tools/port/contract-check
|
||||
step contract-control must-pass tools/port/contract-check --control
|
||||
step modding-rules must-pass tools/port/check-modding
|
||||
# Every `kind` in authored/ is a claim about where a value came from, and until
|
||||
# 2026-08-30 nothing checked what any of them rested on -- seven were resting on
|
||||
# a sibling `why` that argued a different claim.
|
||||
step authored-kinds must-pass tools/port/audit-kinds
|
||||
step capture-controls must-pass tools/port/check-capture-controls
|
||||
step menu-audio must-pass env OUT="$OUT/audio" tools/port/verify-menu-audio
|
||||
# A stale index is worse than none: it answers "is this already decided?" with a
|
||||
|
||||
Reference in New Issue
Block a user