port: my 12-unit bracket is withdrawn, and 41 % of my own doc citations did not resolve
Two things, and the first is a refutation of mine that lands.
1. THE 12-UNIT BRACKET IS WITHDRAWN. It excludes nothing.
I kept 60 units/s on the ground that "12 declared units measured at 0.14-0.30 s
gives 40-86 units/s, so 120 is excluded". The Decoder refuted it and I checked
the arithmetic myself:
120 units/s predicts 12 units in 0.100 s -- BELOW the sampler's own 0.125 s
resolution, which the source doc states in its own words ("at a sampling
resolution that cannot do better"). A 0.125 s sampler reports such an interval
as about one sample, ~0.125-0.14 s. So the 0.14 s low end is the INSTRUMENT'S
FLOOR, and 12/0.14 = 85.7 is an upper bound produced by dividing by a floored
duration. It is the value 120 predicts once the sampler is accounted for.
🔴 And the deeper error is mine rather than the arithmetic. I argued the leg
survived because it "never touched a frame count". True, and INSUFFICIENT: every
wall-clock duration off Canary is true/speed_factor, so apparent units/s = true x
speed, and the speed factor is precisely what makes the three routes disagree. I
checked the leg for the WRONG CONTAMINANT. Frame-free is not clock-free, and on
this emulator clock-free is the property that matters.
What survives is the half I did not lead with: the declared 12 units are
independently confirmed as SIX FRAMES by screen-transitions.md's 255/6-per-frame
ramp, with no wall clock in it. That is evidence about units per FRAME -- never in
dispute -- and silent about units per second.
So 60 has NO surviving bracket. It stays because nothing supports 120 either and
moving a shipped timeline on no evidence is worse. That is a default, not a
derivation, and the entry now says so. `kind` is already `authored`.
2. 41 % OF THE REPO PATHS CITED IN MY OWN docs/port/ PROSE DID NOT RESOLVE.
The Decoder observed that everything they hand me links into docs/re/ files that
live only on their branch, so every link they send dangles from here. I turned it
on myself and it was worse than I expected: 37 of 91, in two classes.
19 on their topic branch -- real files, not merged. Not errors, and no one in
this container can fix them; the fix is a merge.
7 resolve NOWHERE: docs/BLOCKED.md, docs/DECISIONS.md, docs/FORMAT.md,
port/manifest.json, port/screens/title/*.json. Left behind by the monorepo
move and the export/ rename. Simply wrong -- a reader following one gets
nothing, and nothing had ever told anyone.
All 7 fixed. audit-kinds checks citations in authored/; nothing checked the
PROSE, which is where this port explains itself.
New: tools/port/check-citations, wired into check-all with its control. It fails
ONLY on the resolve-nowhere class and reports the peer-branch class, because a
check that went red for a state nobody here can change is the shape the display
guard exists to prevent. The --selftest plants a dangling citation and requires it
caught, AND a real one and requires it passed -- both directions, since a scanner
that flagged everything would also "pass" the first.
Not settled: finding 3 has no surviving cause and 60 now has no surviving
derivation either; the ~1.0-1.2 menu residual; pgloading_loop5's residual; the
allowance still waits on its grep trigger.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AHUQvXGyNcKonSEWsgWcX
This commit is contained in:
@@ -132,7 +132,39 @@
|
||||
" confirmation. The cleanness may be the failure mode's own signature.",
|
||||
"",
|
||||
"Same family as this port's non-inverting latch check, which passed for the wrong",
|
||||
"reason until its control failed."
|
||||
"reason until its control failed.",
|
||||
"",
|
||||
"🔴 2026-09-01 — THE 12-UNIT BRACKET ABOVE IS WITHDRAWN. IT EXCLUDES NOTHING.",
|
||||
"",
|
||||
"I kept 60 on the ground that '12 declared units measured at 0.14-0.30 s gives",
|
||||
"40-86 units/s, so 120 is excluded'. The Decoder refuted it and the refutation",
|
||||
"holds on arithmetic I checked myself:",
|
||||
"",
|
||||
" the source doc says of that number, in its own words, 'at a sampling",
|
||||
" resolution (0.125 s) that cannot do better'. 120 units/s predicts 12 units in",
|
||||
" 0.100 s -- BELOW one sample interval. A 0.125 s sampler cannot resolve it and",
|
||||
" reports about one sample, ~0.125-0.14 s. The 0.14 s low end is the",
|
||||
" INSTRUMENT'S FLOOR, and 12/0.14 = 85.7 is an upper bound produced by dividing",
|
||||
" by a floored duration. It is the value 120 predicts once the sampler is",
|
||||
" accounted for.",
|
||||
"",
|
||||
"🔴 AND THE DEEPER ERROR IS MINE, NOT THE ARITHMETIC. I argued the leg survived",
|
||||
"because it 'never touched a frame count'. True, and INSUFFICIENT: every",
|
||||
"wall-clock duration off Canary is true/speed_factor, so apparent units/s =",
|
||||
"true x speed -- and the speed factor is precisely what makes the three routes",
|
||||
"disagree. I checked the leg for the WRONG CONTAMINANT. Frame-free is not",
|
||||
"clock-free, and on this emulator clock-free is the property that matters.",
|
||||
"",
|
||||
"What actually survives from that leg, and it is the half I did not lead with:",
|
||||
"the declared 12 units are independently confirmed as SIX FRAMES by",
|
||||
"screen-transitions.md's 255/6-per-frame ramp. No wall clock in it at all. That",
|
||||
"is evidence about units per FRAME -- which was never in dispute -- and silent",
|
||||
"about units per second.",
|
||||
"",
|
||||
"SO 60 HAS NO SURVIVING BRACKET. It stays because nothing supports 120 either and",
|
||||
"moving a shipped timeline on no evidence is worse than leaving it. That is a",
|
||||
"default, not a derivation, and this entry now says so. `kind` is already",
|
||||
"`authored`, which is the honest label for a default."
|
||||
],
|
||||
"kind": "authored",
|
||||
"source": "docs/re/ui-keyframe-time-unit.md, docs/port/HANDOFF.md",
|
||||
|
||||
@@ -627,7 +627,7 @@ settled title sits at sd ≤ 0.01. `loop*.rat` is a misleading name — these
|
||||
animate once during build-in and then rest off-screen.
|
||||
|
||||
The port's own error here was different and is fixed: it settled at the last
|
||||
*timed* keyframe rather than at the hold. See `docs/DECISIONS.md`.
|
||||
*timed* keyframe rather than at the hold. See `docs/port/DECISIONS.md`.
|
||||
|
||||
Kept for the record:
|
||||
|
||||
|
||||
@@ -12130,7 +12130,7 @@ fifth instance of that habit in this exchange — and most are not findings:
|
||||
| a hypothetical modding example | `data/mods/sprites/…` |
|
||||
|
||||
✅ **Genuine: five stale citations** from the `docs/` → `docs/port/`
|
||||
reorganisation — `docs/BLOCKED.md` ×4 and `docs/FORMAT.md` ×1. A reader following
|
||||
reorganisation — `docs/port/BLOCKED.md` ×4 and `docs/port/FORMAT.md` ×1. A reader following
|
||||
them fails. Rewritten.
|
||||
|
||||
### 🔴 And the one that reached a claim I made last iteration
|
||||
|
||||
@@ -147,7 +147,7 @@ for a long time.
|
||||
> grossly (`ptlogo_back2`, 1118×262, pivot 500,117 where half is 559,131). It is
|
||||
> not a problem for this port — the exporter emits the declared pivot and never
|
||||
> derives one — but it is a claim a consumer should not lean on. Raised in
|
||||
> `docs/BLOCKED.md`.
|
||||
> `docs/port/BLOCKED.md`.
|
||||
|
||||
**`sprite`** / **`focus_sprite`** are paths relative to `export/`. The highlight
|
||||
pairs **by name** on the sprite — `ptbtn01.t32` ↔ `ptbtn01f.t32` — which is 🟡 a
|
||||
@@ -272,7 +272,7 @@ keyframe *k* means the screen spends that time *arriving at* `k+1`.
|
||||
> A consumer that wants the pose after arrival should therefore take **the last
|
||||
> timed keyframe**, not `rest`. `rest` is kept in the format because it is what
|
||||
> the pinned decoders say and removing it would hide the disagreement — see
|
||||
> `docs/DECISIONS.md`. The format is unchanged at **v2**: no field changed
|
||||
> `docs/port/DECISIONS.md`. The format is unchanged at **v2**: no field changed
|
||||
> meaning, this is a warning about one of them.
|
||||
|
||||
**`paint_order`** is back-to-front, as declaration indices, and is a permutation
|
||||
|
||||
@@ -105,7 +105,7 @@ A milestone is done when its **artifact** exists, not when the code compiles.
|
||||
| **P7** | New-game intro video after NEW GAME | Plays, then returns to a defined state |
|
||||
|
||||
Work the lowest unfinished milestone. When one is blocked on an RE answer, say so
|
||||
in `docs/BLOCKED.md`, and take the next milestone that is not.
|
||||
in `docs/port/BLOCKED.md`, and take the next milestone that is not.
|
||||
|
||||
## 6. The video problem
|
||||
|
||||
|
||||
@@ -129,6 +129,14 @@ step input-control must-pass tools/port/verify-input --control
|
||||
# A stale index is worse than none: it answers "is this already decided?" with a
|
||||
# confident no. That is not hypothetical -- see the entry it was built after.
|
||||
step decisions-index must-pass tools/port/index-decisions --check
|
||||
# `audit-kinds` checks citations in `authored/`; nothing checked the PROSE, and
|
||||
# prose is where this port explains itself. A first run found 37 of 91
|
||||
# non-resolving -- 7 of them pointing at NOTHING on any ref, left behind by the
|
||||
# monorepo move and the `export/` rename. Only that class fails; a citation that
|
||||
# is merely on a peer's unmerged branch is reported, because the fix is a merge
|
||||
# and nobody in this container can make it.
|
||||
step doc-citations must-pass tools/port/check-citations
|
||||
step citations-control must-pass tools/port/check-citations --selftest
|
||||
# A refuted claim asserted outside its correction is a lie the corpus tells a
|
||||
# reader who greps for it. Registered claims must carry an explicit `[refuted]`.
|
||||
# 🔴 The register check had NO executable control until 2026-08-31 -- every
|
||||
|
||||
106
tools/port/check-citations
Executable file
106
tools/port/check-citations
Executable file
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Do the repo paths cited in `docs/port/*.md` actually resolve?
|
||||
|
||||
tools/port/check-citations # assert
|
||||
tools/port/check-citations --selftest # can it fail?
|
||||
|
||||
`audit-kinds` checks citations in `authored/`. Nothing checked the PROSE, and
|
||||
prose is where this port explains itself. A first run found **37 of 91**
|
||||
non-resolving, 41 %, in two very different classes:
|
||||
|
||||
* **19 on the Decoder's topic branch** — real files, not merged here. Not
|
||||
errors. A reader in this checkout still cannot follow them, which is worth
|
||||
reporting and not worth failing on; the fix is a merge, not an edit.
|
||||
* **7 that resolve NOWHERE** — `docs/BLOCKED.md`, `docs/FORMAT.md`,
|
||||
`port/manifest.json`, `port/screens/title/*.json`. Left behind by the
|
||||
monorepo move and the `export/` rename. Those are simply wrong: a reader
|
||||
following one gets nothing, and nothing had ever told anyone.
|
||||
|
||||
So the two classes are separated and only the second fails. A check that failed
|
||||
on the first would be red for a state nobody in this container can fix, which is
|
||||
the shape the display guard exists to prevent.
|
||||
|
||||
⚠️ THE PEER-BRANCH CLASS IS THE OTHER AGENT'S POINT, TURNED ON MYSELF. They
|
||||
observed that everything they hand over links into `docs/re/` files that live
|
||||
only on their branch, so every link they send is dangling from here. The same is
|
||||
true in reverse and neither of us was counting.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import glob
|
||||
|
||||
# A repo path with a file extension, optionally in backticks or a markdown link.
|
||||
CITE = re.compile(
|
||||
r"`?((?:docs|crates|port|tools|authored|export)/[\w./-]+"
|
||||
r"\.(?:md|rs|gd|json|txt|py|tsv|csv))`?"
|
||||
)
|
||||
PEER_REFS = ("origin/auto/frame-blend-draw-path", "origin/main")
|
||||
|
||||
|
||||
def on_a_ref(path: str) -> str | None:
|
||||
"""The first ref that carries `path`, or None."""
|
||||
for ref in PEER_REFS:
|
||||
if subprocess.run(["git", "cat-file", "-e", f"{ref}:{path}"],
|
||||
capture_output=True).returncode == 0:
|
||||
return ref
|
||||
return None
|
||||
|
||||
|
||||
def scan(files):
|
||||
resolves, peer, nowhere = 0, {}, {}
|
||||
for p in files:
|
||||
try:
|
||||
text = open(p, encoding="utf-8").read()
|
||||
except OSError:
|
||||
continue
|
||||
for m in sorted(set(CITE.findall(text))):
|
||||
if os.path.exists(m):
|
||||
resolves += 1
|
||||
elif (ref := on_a_ref(m)):
|
||||
peer.setdefault(m, (p, ref))
|
||||
else:
|
||||
nowhere.setdefault(m, p)
|
||||
return resolves, peer, nowhere
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if "--selftest" in sys.argv:
|
||||
# 🔴 A CHECK THAT CANNOT FAIL IS NOT A CHECK. This plants a citation of a
|
||||
# path that exists on no ref and requires the scanner to catch it, and a
|
||||
# citation of a real file and requires it NOT to. Both directions,
|
||||
# because a scanner that flagged everything would also "pass" the first.
|
||||
tmp = os.path.join(os.environ.get("TMPDIR", "/tmp"), "check-citations-selftest")
|
||||
os.makedirs(tmp, exist_ok=True)
|
||||
bad = os.path.join(tmp, "bad.md")
|
||||
open(bad, "w").write("see `docs/port/this-file-does-not-exist-anywhere.md`\n")
|
||||
good = os.path.join(tmp, "good.md")
|
||||
open(good, "w").write("see `docs/port/PORT-MISSION.md`\n")
|
||||
_, _, nb = scan([bad])
|
||||
r, _, ng = scan([good])
|
||||
ok = len(nb) == 1 and len(ng) == 0 and r == 1
|
||||
print("selftest: planted dangling caught=%s, real citation passed=%s -> %s"
|
||||
% (len(nb) == 1, len(ng) == 0 and r == 1, "ok" if ok else "🔴 BROKEN"))
|
||||
return 0 if ok else 2
|
||||
|
||||
files = sorted(glob.glob("docs/port/*.md"))
|
||||
resolves, peer, nowhere = scan(files)
|
||||
total = resolves + len(peer) + len(nowhere)
|
||||
print("citations of repo paths in docs/port/*.md: %d" % total)
|
||||
print(" resolve here : %d" % resolves)
|
||||
print(" on a peer branch, not merged: %d (reported, not failed)" % len(peer))
|
||||
for m, (src, ref) in sorted(peer.items()):
|
||||
print(" %-52s %s <- %s" % (m, ref.split("/")[-1], os.path.basename(src)))
|
||||
if nowhere:
|
||||
print(" 🔴 resolve NOWHERE : %d" % len(nowhere))
|
||||
for m, src in sorted(nowhere.items()):
|
||||
print(" %-52s <- %s" % (m, os.path.basename(src)))
|
||||
print("\n🔴 a reader following those gets nothing. Fix the path or drop the citation.")
|
||||
return 1
|
||||
print(" 🔴 resolve nowhere : 0")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user