Takes the port branch up to77320d5e-- the state the human play-tested on 2026-09-02 -- for SOURCE paths only. Not a branch merge: `auto/port-p6-audio` is 366 commits and 938 files, and most of that must not land. WHAT COMES IN (76 files, all human-confirmed working): * the logo splash animation.08ed3dd1found it: `pose_at` ASSIGNED the settle instant instead of clamping to it, so the splash never animated at all -- and the same bug manufactured a passing harness result, because the harness photographed t past the settle. Confirmed by play-test: "cannot notice any obvious difference from the actual game." * gamepad input -- (A)/(B) bound additively (`ui_accept` ships with NO joypad binding), stick latched with hysteresis at the game's own 61% digitise threshold. This is what made (A), video-skip and Extras work at all. * menu navigation and flow, menu audio, the exporter, the authored declarations, and 23 verification tools under tools/port/. WHAT IS DELIBERATELY LEFT ON THE BRANCH: * everything afterc0ae460a-- the F5/F6 title-timing investigation, whose own tip commit calls itself a "hand-off for one-minute human checks". Unchecked by definition; it goes through the new review gate like anything else. * the OPTIONS menu work of 2026-09-03. Real, probably good, NOT play-tested. * the F1 repeat mechanism, which its own commit calls "deliberately inert". WHAT MUST NOT LAND, AND WHY THE .gitignore CHANGED: 545 MB of extracted game content was committed on that branch -- 850 sprite, audio and transcoded video files under `export-probe/` and `export-probe2/`, plus 246 MB of loose .wav and .tsv at the repo root. This repository's own rule, in this file, is "never game content". The rule was not missing. It was written, and it was tightened on that very branch, with a careful comment explaining why BOTH `export/` and `data/base/` had to be listed -- while the exporter was writing to a third name that nobody had thought to list. Enumerating names is the thing that failed. So the ignore rules now describe the SHAPE: any top-level `export*/`, game media by extension, and loose capture output at the root. Verified both ways -- it catches all four offenders and ignores nothing currently tracked. Verified: `cargo check --workspace` clean; all nine GDScript files parse in project context, with a positive control (an injected syntax error is detected, 3 lines) so the clean result means something. `tools/port/check-all` was NOT run -- it needs the container, the export tree and a display.
227 lines
10 KiB
Python
Executable File
227 lines
10 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Date every open row in BLOCKED.md from history, instead of guessing.
|
|
|
|
`BLOCKED.md` is required to record the HANDOFF commit each row derives from, and
|
|
none of the rows in the two open tables do. The file itself says why: nobody
|
|
knows when most of them were written, and inventing a sha would be worse than
|
|
admitting there is none.
|
|
|
|
But git does know. A row's derivation is not a memory, it is the commit that
|
|
introduced the row -- recoverable with a pickaxe over the file's own history.
|
|
This prints, per row:
|
|
|
|
introduced the oldest commit whose diff added the row's key phrase
|
|
HANDOFF@ `git log -1 -- docs/port/HANDOFF.md` as of that commit
|
|
unread commits touching docs/re/ ON ANY REF that are not ancestors of
|
|
that commit -- decoding the row has never been read against
|
|
|
|
`--all`, not my own ancestry, and that distinction is the whole finding. Counted
|
|
against my checkout every row scores ZERO, which is true and useless: the
|
|
Decoder's live decoding sits on `origin/auto/no-disc-and-menu-captures`, `main`
|
|
is a hundred-odd commits behind it, and HANDOFF has not moved in four
|
|
milestones [refuted] -- 🔴 corrected 2026-09-01: **on `main`**. Flat, that
|
|
sentence is the claim this port WITHDREW in `BLOCKED.md` on 2026-08-30, where the
|
|
missing qualifier was recorded as carrying the whole meaning: HANDOFF has moved
|
|
over a hundred times, just not on the branch this checkout reads. The reasoning
|
|
below needs the qualifier to work at all -- the sha is constant BECAUSE `main`'s
|
|
copy is frozen, not because the document is. So a row can be derived from the
|
|
newest HANDOFF `main` has and still
|
|
be a day behind the decoding -- and the instruction to record the HANDOFF sha
|
|
CANNOT DETECT THAT, because the sha it asks for is constant.
|
|
|
|
That is the rot mechanism the 2026-08-30 audit found three instances of, and it
|
|
is not the one the header of BLOCKED.md describes.
|
|
|
|
Nothing here is authored. Every field is read out of git, and a row whose key
|
|
phrase has been rewritten since it was introduced reports `?` rather than a
|
|
plausible-looking sha.
|
|
"""
|
|
import re, subprocess, sys
|
|
|
|
DOC = "docs/port/BLOCKED.md"
|
|
|
|
|
|
def git(*a):
|
|
return subprocess.run(["git", *a], capture_output=True, text=True).stdout.strip()
|
|
|
|
|
|
TOP = 3
|
|
|
|
|
|
def idf_of(commits):
|
|
"""log(N / how many subjects use the word) -- rarity, from the corpus itself."""
|
|
import collections, math
|
|
df = collections.Counter()
|
|
for _, subj in commits:
|
|
df.update(tokens(subj))
|
|
n = len(commits)
|
|
return collections.defaultdict(lambda: math.log(n), {w: math.log(n / c) for w, c in df.items()})
|
|
|
|
|
|
def key_of(cell):
|
|
"""The longest markdown-free fragment -- what to pickaxe for.
|
|
|
|
Cells get struck through and re-emphasised as they are resolved, so the cell
|
|
as it stands today is not what was committed. The inner text survives that.
|
|
"""
|
|
frags = [f.strip(" ?.") for f in re.split(r"[*~`]+", cell)]
|
|
frags = [f for f in frags if len(f) >= 20]
|
|
return max(frags, key=len) if frags else None
|
|
|
|
|
|
def rows():
|
|
"""Every table row in the open sections, in file order."""
|
|
open_only, out = False, []
|
|
for line in open(DOC, encoding="utf-8"):
|
|
if line.startswith("## "):
|
|
open_only = line.startswith("## Still open")
|
|
continue
|
|
if not open_only or not line.startswith("| "):
|
|
continue
|
|
cells = [c.strip() for c in line.strip().strip("|").split(" | ")]
|
|
if len(cells) < 4 or cells[0] in ("Milestone", "---"):
|
|
continue
|
|
out.append(cells)
|
|
return out
|
|
|
|
|
|
STOP = set("""this that with from what which when does than the and are was were
|
|
have has been will would could should port game screen menu audio does not any
|
|
each only its it's whether where else same both very more most into onto over
|
|
under about after before still open blocked answered measured wrong right first
|
|
second third disc file files commit branch docs main head sha row rows table
|
|
mission handoff decoder agent claim claims""".split())
|
|
|
|
|
|
def stem(w):
|
|
"""Crudest possible stemmer, and it earns its place with a control.
|
|
|
|
Without it `looping` does not match `loop` and the P6 row whose answer is
|
|
sitting in an unread commit scores zero -- which is what happened.
|
|
"""
|
|
for suf in ("ping", "ing", "ted", "ed", "es", "s"):
|
|
if w.endswith(suf) and len(w) - len(suf) >= 4:
|
|
return w[: -len(suf)]
|
|
return w
|
|
|
|
|
|
def tokens(text):
|
|
ws = re.findall(r"[a-z0-9_]{4,}", text.lower())
|
|
return {stem(w) for w in ws if w not in STOP}
|
|
|
|
|
|
def rank(rt, commits, idf):
|
|
"""Score every unread commit against one row, rarest words first.
|
|
|
|
A COUNT of shared words is the wrong instrument: `menu` and `loop` shared
|
|
scores the same as `plate` and `pulse`, and in this corpus almost everything
|
|
says `menu`. Weighting each shared stem by log(N / commits containing it)
|
|
lets one rare word outrank two common ones -- and it removes the threshold,
|
|
which was the part that could be tuned. The list is RANKED, fixed length,
|
|
so nothing is decided by a cutoff nobody can justify.
|
|
"""
|
|
out = []
|
|
for sha, subj in commits:
|
|
shared = rt & tokens(subj)
|
|
if shared:
|
|
out.append((sum(idf[w] for w in shared), sha, subj, shared))
|
|
return sorted(out, reverse=True)
|
|
|
|
|
|
def overlap(rs):
|
|
"""Which unread commits NAME something an open row is about.
|
|
|
|
Crude on purpose, and it says so: word overlap between a row and a commit
|
|
SUBJECT, ranked by rarity, top few printed with the words that earned the
|
|
rank so the reader judges rather than trusting the match. It cannot tell
|
|
relevance from coincidence -- it narrows 196 commits to a short list worth
|
|
opening, and nothing more.
|
|
"""
|
|
log = git("log", "--all", "--not", "HEAD", "--format=%h\t%s", "--", "docs/re/")
|
|
commits = [l.split("\t", 1) for l in log.splitlines() if "\t" in l]
|
|
print(f" {len(commits)} unread docs/re/ commit(s) exist on other refs.")
|
|
print(" Crude word overlap with the open rows -- a reading list, not a verdict:\n")
|
|
idf = idf_of(commits)
|
|
hits = struck = dropped = 0
|
|
for cells in rs:
|
|
if cells[0].startswith("~~"):
|
|
struck += 1 # already struck; re-reading it settles nothing
|
|
continue
|
|
scored = rank(tokens(cells[0] + " " + cells[1]), commits, idf)
|
|
dropped += max(0, len(scored) - TOP)
|
|
for score, sha, subj, shared in scored[:TOP]:
|
|
hits += 1
|
|
print(f" {re.sub(r'[*~`]', '', cells[0])[:36]:<36} {sha} {score:5.1f} {subj[:58]}")
|
|
print(f" {'':<36} {'':<8} via {', '.join(sorted(shared))}")
|
|
if not hits:
|
|
print(" (no row shares a word with any unread commit)")
|
|
# Every discard, counted. A detector that can drop a candidate in silence
|
|
# has an unfalsifiable clean run -- which is how the P6 looping row stayed
|
|
# marked open for a day while its answer sat in `712cac8`, and how the same
|
|
# class of miss went unnoticed in the Decoder's checker on the same day.
|
|
print(f"\n suppressed: {struck} struck row(s) not scanned; {dropped} scoring")
|
|
print(f" pair(s) ranked below top-{TOP} and not shown; {len(STOP)} word(s)")
|
|
print(" stoplisted and unable to match at any rank.")
|
|
print()
|
|
|
|
|
|
def control():
|
|
"""Known positive: the row whose answer is demonstrably in an unread commit.
|
|
|
|
`P6 looping` asks where the menu loop restarts. `712cac8` measures it at
|
|
9.44 s and the port has since shipped that value, so the pair MUST match. It
|
|
did not, until stemming -- the check exists so that regression is loud.
|
|
"""
|
|
log = git("log", "--all", "--not", "HEAD", "--format=%h\t%s", "--", "docs/re/")
|
|
commits = [l.split("\t", 1) for l in log.splitlines() if "\t" in l]
|
|
scored = rank(tokens("P6 looping where a menu loop restarts"), commits, idf_of(commits))
|
|
at = next((i for i, r in enumerate(scored) if r[1].startswith("712cac8")), None)
|
|
ok = at is not None and at < TOP
|
|
print(f" control: P6-looping vs 712cac8 -> rank {at} of {len(scored)} scoring "
|
|
f"{'✅' if ok else f'🔴 OUTSIDE TOP-{TOP}, THE KNOWN POSITIVE IS MISSED'}")
|
|
return ok
|
|
|
|
|
|
def main():
|
|
if "--control" in sys.argv:
|
|
sys.exit(0 if control() else 1)
|
|
rs = rows()
|
|
if not rs:
|
|
sys.exit(f"{DOC}: no rows found under a '## Still open' heading")
|
|
head_handoff = git("log", "-1", "--format=%h", "--", "docs/port/HANDOFF.md")
|
|
print(f" {DOC}: {len(rs)} rows in the open tables")
|
|
print(f" HANDOFF is at {head_handoff} today\n")
|
|
print(f" {'row':<44} {'introduced':<12} {'date':<11} {'HANDOFF@':<9} unread")
|
|
unknown = 0
|
|
for cells in rs:
|
|
milestone, needs = cells[0], cells[1]
|
|
label = re.sub(r"[*~`]", "", milestone)[:43]
|
|
key = key_of(needs) or key_of(milestone)
|
|
sha = date = handoff = "?"
|
|
since = "-"
|
|
if key:
|
|
# oldest commit whose diff changed the number of occurrences
|
|
log = git("log", "--format=%h %ad", "--date=short", "-S", key, "--", DOC)
|
|
if log:
|
|
sha, date = log.splitlines()[-1].split()
|
|
handoff = git("log", "-1", "--format=%h", sha, "--", "docs/port/HANDOFF.md")
|
|
unread = git("log", "--all", "--not", sha, "--format=%h", "--", "docs/re/")
|
|
since = str(len(unread.splitlines())) if unread else "0"
|
|
if sha == "?":
|
|
unknown += 1
|
|
flag = ""
|
|
if since not in ("-", "0") and not milestone.startswith("~~"):
|
|
flag = f" <- never read against {since} docs/re/ commit(s)"
|
|
print(f" {label:<44} {sha:<12} {date:<11} {handoff:<9} {since:>3}{flag}")
|
|
print()
|
|
overlap(rs)
|
|
if unknown:
|
|
print(f" ⚠️ {unknown} row(s) could not be dated: the key phrase has been")
|
|
print(" rewritten since it was introduced, so history cannot place it.")
|
|
print(" Not a staleness verdict. A high `unread` is not a wrong row -- most of")
|
|
print(" that decoding is irrelevant to most rows. It is the size of the surface")
|
|
print(" nobody has looked at, and it is what the HANDOFF sha was supposed to be.")
|
|
|
|
|
|
main()
|