port: adopt the game's 61% stick threshold, and find my verify-screen numbers were llvmpipe-specific
Two things, and both are about a hidden parameter nobody was recording. 1. THE STICK THRESHOLD IS DECODED NOW, and it replaces an authored value. The Decoder measured that the game digitises the left stick to four direction bits at 61 % deflection, so it never sees a velocity. Gamepad.ENTER moves 0.5 -> 0.61. The 0.5 was never a chosen value: it was a FLOOR, because Godot's `ui_*` action deadzone is 0.50 and the latch must not arm below it. Between 0.50 and 0.61 Godot reports a direction the real game does not, and at 0.5 this port stepped there. The mechanism also corroborates the human's latch fix rather than merely agreeing with it: a control that digitises to bits cannot express a rate, so "one step per deflection" is what the hardware layer CAN produce. ⚠️ The 0.11 hysteresis gap stays AUTHORED -- nothing says the game has hysteresis at all. And a human chose 0.5, so this changes feel: revert the one constant if 0.61 reads as needing too much push. 🔴 AND THE CONTROL CAUGHT MY FIRST ATTEMPT AT ASSERTING IT. I added the new device-level row as subject "latch", and `verify-input --control` failed immediately with "a check did not invert -- it is not testing what it claims to test". It was right: removing the latch does not remove the THRESHOLD, the unlatched path tests `>= Gamepad.ENTER` too, so 0.55 counts 0 either way and the row could never invert. It is a NEGATIVE, and its positive control is the 0.70 row on the same shape. Reclassified. That also exposed a smaller thing: ok()'s negative branch HARDCODED "positive control is the stick row", so a second negative would have borrowed someone else's green line. It now takes the control's name, defaulting to the original text so the d-pad row is unchanged. ✅ I never consumed the pad bit table they have just corrected -- checked by grep over port/, authored/ and tools/port/, not remembered. 2. MY verify-screen NUMBERS WERE llvmpipe-SPECIFIC, and the prediction failed. Pre-registered: both renderers blend in encoded 8-bit space, so the diffs should be identical or within 1 level on the GPU. They are not -- every mean rose 3-35 %: title 0.4431 -> 0.5936, main_menu 3.9363 -> 4.1449, extras 6.7422 -> 6.9757, title_jp 2.7715 -> 2.9448, main_menu_jp 0.7885 -> 1.0157, extras_jp 0.6592 -> 0.8906, build_12/15 0.0368 -> 0.0454. But the MAXIMA are unchanged -- 41, 97, 113, 233, 17 identical, 26 -> 27 on one row. That is a rounding population growing, not content moving: two rasterisers round the last bit of a blend differently while the elements that genuinely differ do not move. Survives: the additive diagnosis, because it rests on an ORDERING and the ordering holds (9 elements > 5 > 0); the pgloading_loop5 localisation; the build_00/01 agreement; the derived allowance, same four failing rows. Does not, and is now labelled: the histogram (53 % within 1 level, 16 844 over 40); every absolute mean; and the RMSE-vs-capture pair 3151.96 / 3769.61 -- that ORDERING claim is not re-derived on the GPU and is not claimed until it is. The rule this earns: a renderer comparison carries its RASTERISER as a hidden parameter. Nothing here recorded which one produced a diff, and for months there was only one so it never mattered. Same discipline TEMPORAL-VERIFICATION already demands for capture rate, applied to what rasterises rather than what clocks. Not settled: H1's repeat half; H6's +0x04 exposure; the four red verify-screen rows; whether the port is still nearer the capture than the reference on the GPU. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AHUQvXGyNcKonSEWsgWcX
This commit is contained in:
@@ -104,7 +104,7 @@ method finding that applies to the Decoder's harness as much as this one:
|
||||
|
||||
| # | ask | why the port cannot answer it |
|
||||
|---|---|---|
|
||||
| **H1** | **Does a held direction REPEAT in the menus, and at what rate?** Initial delay and repeat interval, for the d-pad and for the left stick separately if they differ. | Behavioural. The port now does **one step per deflection** — `authored`, and deliberately the conservative half: it cannot run away and it invents no rate. If the game repeats, a human will feel it as *"I have to flick it again"*. |
|
||||
| **H1** | 🟢 **PARTLY ANSWERED 2026-09-01 and the port has adopted the half that landed.** The game **digitises the left stick to four direction bits at 61 % deflection** and never sees a velocity (`input-button-numbering-is-remapped.md`). `Gamepad.ENTER` moves **0.5 → 0.61**: 0.5 was a *floor* (Godot's `ui_*` action deadzone), 0.61 is the game's own threshold, and between them Godot reports a direction the real game does not. Asserted at the device level in `tools/port/verify-input`. **Still open: does a held direction REPEAT, and at what rate** — one step per deflection remains authored, and the digitise-to-bits mechanism corroborates that a rate cannot come from this layer. | 🔴 **The 0.11 hysteresis gap stays AUTHORED** — nothing measured says the game has hysteresis at all. ⚠️ **A human chose 0.5 and 0.61 changes how the stick feels**; revert that one constant if it reads as needing too much push. ✅ And I never consumed the mislabelled pad bit table — checked by grep over `port/`, `authored/` and `tools/port/`, not remembered. |
|
||||
| **H2** | ✅ **ANSWERED 2026-09-01, and the port's own premise was wrong.** The Decoder found **no post-process pass** on either splash (`auto/frame-blend-draw-path` `3cc1b51`). The blur is **in the asset**: every logo ships a pre-blurred copy ~21×20 px larger and concentric, drawn alone first and crossfaded out as the sharp logo fades in — which is the human's *"blurred to clear/sharp, in about a second"*, with no shader. | 🔴 **"The port applies no blur at all" was FALSE and this page said it.** The port draws all seven quads of the developer splash, the three companions included, and always has. Verified by a frozen sweep, 3 units a step: companions alone at u=3–15, all seven at u=18–42, sharp only from u=45. Writing down what the renderer was *believed* to do instead of running it is what produced the claim. What remains is the **extent**, and it is the same unit question as H3 — asked there, once. See [`plate-arrival-halves.md`](plate-arrival-halves.md). |
|
||||
| **H3** | ✅ **CLOSED 2026-09-01. ALL FOUR NAMED CAUSES ARE DEAD AND THE HUMAN'S OBSERVATION IS NOT — recorded that way deliberately rather than left green.** The rate is **56.8 units per guest second**, measured, control at 1.15 %, two elements agreeing at one clock (`units-per-second-measured.md`). 30 and 120 both excluded. At 56.8 the plate's t=236 lands at **4.15 s** against the port's 3.93 s — the port is fractionally **early**. | Eliminated in order: `rest.t` (the arrival is a declared keyframe), the clock origin (85/85 filmed frames share one clock), the anchor (answered t=160, and `clock: "shared"` survives it), the unit constant (56.8). 🔴 **`units = 2 × frames` is dead as a route** — the same animation takes 21 labels in one capture and 33 in another. ✅ Audited: this port never used it; `boot.gd` integrates `delta * units_per_second`, so the retirement cost a *justification* in `authored/timing.json` and not a behaviour, and that file's second leg (12 declared units against a 0.14–0.30 s black plateau = 40–86 units/s) has no frames in the chain. **60 units/s is KEPT** — 56.8 is 5.6 % away against ~5 % quantisation and the Decoder did not ask for a move. ⚠️ Reach is the **title**; the splashes are a different `GamePart`. What the human saw is now unattributed — see [`plate-arrival-halves.md`](plate-arrival-halves.md) for the two remaining candidates, of which the strongest is that **Ⓐ was unbound on the play-test build so that human could not skip the 137 s intro**, and the run they judged is not the run any of these measurements describes. |
|
||||
|
||||
|
||||
@@ -255,3 +255,72 @@ express, and the allowance cannot go stale against the map it is computed from.
|
||||
* That the port's additive set is complete. It covers three screens; nobody has
|
||||
logged the register on the rest.
|
||||
* Anything about the four undiagnosed rows.
|
||||
|
||||
|
||||
---
|
||||
|
||||
# 🔴 Re-validated on the GPU, and my prediction failed: these numbers are rasteriser-specific
|
||||
|
||||
The human activated a hardware GPU on 2026-09-01. **Every number on this page
|
||||
above was measured under `llvmpipe`**, so they needed re-deriving before anyone
|
||||
builds on them.
|
||||
|
||||
## Pre-registered (R2)
|
||||
|
||||
> Both renderers blend in encoded 8-bit space, so if the port's drawing is
|
||||
> rasteriser-independent the diffs should be **identical, or within 1 level**.
|
||||
> Anything materially different means a published conclusion here was
|
||||
> GPU-specific.
|
||||
|
||||
## It failed
|
||||
|
||||
| screen | llvmpipe mean | **GPU mean** | change | max (llvmpipe → GPU) |
|
||||
|---|---|---|---|---|
|
||||
| `title` | 0.4431 | **0.5936** | **+34 %** | 41 → 41 |
|
||||
| `main_menu` | 3.9363 | **4.1449** | +5.3 % | 97 → 97 |
|
||||
| `extras` | 6.7422 | **6.9757** | +3.5 % | 113 → 113 |
|
||||
| `title_jp` | 2.7715 | **2.9448** | +6.3 % | 233 → 233 |
|
||||
| `main_menu_jp` | 0.7885 | **1.0157** | **+29 %** | 26 → 27 |
|
||||
| `extras_jp` | 0.6592 | **0.8906** | **+35 %** | 26 → 26 |
|
||||
| `build_12` / `build_15` | 0.0368 | **0.0454** | +23 % | 17 → 17 |
|
||||
|
||||
**Every mean rose, by 3–35 %.** So the diffs are *not* rasteriser-independent
|
||||
and the prediction was wrong.
|
||||
|
||||
## What survives, and what does not
|
||||
|
||||
🔴 **The maxima are unchanged** — 41, 97, 113, 233, 17 identical, and 26 → 27 on
|
||||
one row. The large differences are exactly where they were.
|
||||
|
||||
That is the shape of a **rounding population growing, not content moving**:
|
||||
llvmpipe and the NVIDIA rasteriser round the last bit of a blend differently, so
|
||||
the ≤1-level tier grows while the elements that genuinely differ do not move at
|
||||
all. Consistent with both still blending in encoded space — which the control on
|
||||
this page established for Godot generally, not for one rasteriser.
|
||||
|
||||
**What survives:**
|
||||
|
||||
* the **additive diagnosis**, because it rests on an *ordering*, and the ordering
|
||||
holds on the GPU: `extras` 6.98 > `main_menu` 4.14 > `extras_jp` 0.89 and
|
||||
`main_menu_jp` 1.02 > `title` 0.59 — nine additive elements, then five, then
|
||||
none;
|
||||
* the **`pgloading_loop5` localisation**, which is a bounding box;
|
||||
* the **`build_00`/`build_01` agree** result — still 0 pixels over the bar;
|
||||
* the **derived allowance**: the failing set is the same four rows.
|
||||
|
||||
**What does not, and is now labelled:**
|
||||
|
||||
* the histogram (*53 % within 1 level, 16 844 over 40*) was llvmpipe-specific and
|
||||
the ≤1 tier is larger on the GPU;
|
||||
* every absolute **mean** quoted above this section;
|
||||
* the **RMSE-vs-capture** pair (3151.96 / 3769.61) was llvmpipe. The *ordering*
|
||||
claim — the port is nearer than the reference — has not been re-derived on the
|
||||
GPU and is not claimed here until it is.
|
||||
|
||||
## The rule this earns
|
||||
|
||||
**A renderer comparison carries its rasteriser as a hidden parameter.** Nothing
|
||||
in this corpus recorded which one produced a diff, and for eight months there was
|
||||
only one so it never mattered. Any diff quoted from here on should say what drew
|
||||
it — the same discipline `TEMPORAL-VERIFICATION.md` already demands for capture
|
||||
rate, applied to the thing that rasterises rather than the thing that clocks.
|
||||
|
||||
Reference in New Issue
Block a user