Flags ohne Setzer, Zustände ohne Leser: toter Code in CORE, INPUT und GAME (Folgebefund zu #9) #21

Closed
opened 2026-09-02 15:40:26 +02:00 by gilli · 3 comments
Owner

⁨⁩⁨Flags ohne Setzer, Zustände ohne Leser: toter Code in CORE, INPUT und GAME (Folgebefund zu #9)⁩ ⁨⁩#⁨21⁩⁨⁩"
By ⁨⁩⁨gilli⁩⁨⁩ — ⁨⁨⁩Open⁨⁩⁩
cleanup
low
maintainability

Komponente: CORE (hitTest, testBox, stepBody, buildPattern, releaseHook, generateAhead),
INPUT (state, init), GAME (S, update), RENDER (hintGrab)
Betroffene Version: main @ 42f3cce, index.html (3.333 Zeilen, MD5 aae5f94c1dc05903f2c214d255d2fe9d)

Beschreibung

Issue #9 hat mit hook.disabled / hook.grabs bereits die Regel etabliert: ein Flag ohne
Setzer ist keine Funktion
(tests/issue9.mjs). Derselbe Befund findet sich an weiteren Stellen,
die bei #9 nicht erfasst wurden. Alle folgenden Felder sind im ausgelieferten Dokument
geschrieben, aber nie gelesen oder gelesen, aber nie geschrieben:

Fundstelle Zeile(n) Befund
obstacle.dead 630, 640 von testBox()/hitTest() als Ausnahmeflag gelesen – niemand setzt ihn. Ein Hindernis kann daher nie aus der Kollision genommen werden
body.dead 654, 885 wird beim Sturz gesetzt, aber nirgends gelesen; das Spiel benutzt S.dying
S.paused 2515 deklariert, nie gelesen und nie geschrieben; Pausenzustand ist S.state === "PAUSED". tests/browser_issue11.py Zeile 48 schreibt das Feld wirkungslos
INPUT.state.anyPointerDown 2324, 2433, 2471 Produktcode liest es nie; einziger Leser ist tests/browser_issue8.py Zeile 87/222. Entweder als Testbeobachter dokumentieren oder durch Object.keys(pointers).length === 0 im Test ersetzen
pit.platform, pit.double 1056, 1072 Gruben-Metadaten ohne jeden Leser – „Saubere Linie“ hängt an usedHook/touchedGround, der Solver an Bodensegmenten
ev.releaseTheta 721 gesetzt, kein Leser
ev.leftGround 801 gesetzt, kein Leser
ev.assistedLanding 758 kein Leser im Produkt; in tests/issue3.mjs Zeile 50 nur als Diagnose-Feld mitgeschleift, nie geprüft
gen.stats.attempted 1475 Zähler direkt neben gen.stats.tried (Zeile 1473), immer um denselben Wert erhöht – redundante Statistik
hooks.onPointer 2378 (Doku), 2440, 2464 wird defensiv aufgerufen, aber boot() liefert den Hook nicht; die Doku-Zeile 2378 nennt ihn nicht, dafür fehlt dort das Pflicht-Hook onGesture, das an sechs Stellen ungeprüft gerufen wird
S.newRecord 2513, 2627, 2705 dreimal geschrieben, nie gelesen (isRecord wird lokal entschieden)
RENDER.hintGrab(… reduced) 2158 reduced ? "GREIFEN" : "GREIFEN" – beide Zweige identisch; der Aufrufer (Zeile 3159) überspringt den Text bei reduced ohnehin
simStep(K.FIXED_TIMESTEP, false) 2982 zweites Argument, das simStep(dt) gar nicht annimmt
testBox() / hitTest() 626–646 zwei inhaltlich identische Schleifen; hitTest ist testBox ohne Marge

Nicht gemeint: ev.rollEnd – das liest tests/issue14.mjs (Zeile 76, 169) und ist damit
gebundene Test-API.

Auswirkung

  • Irreführende API: hitTest(…, o.dead) suggeriert, Hindernisse könnten deaktiviert werden
    (z. B. nach Kassieren), was es nicht gibt. Wer es versucht, arbeitet gegen eine Bedingung,
    die immer false ist.
  • Doppelte Zustandsquellen für denselben Sachverhalt (S.paused vs. S.state,
    body.dead vs. S.dying) – genau die Klasse, die in Issue #3 und #9 zu echten Fehlern
    geführt hat.
  • Testschreibarbeit ins Leere: browser_issue11.py pflegt S.paused, ohne dass es eine
    Wirkung hätte.
  • hooks.onPointer ist ein Vertrag, den niemand erfüllt; die Doku-Zeile an der Stelle ist
    zudem unvollständig (onGesture fehlt), was beim nächsten Umbau der Eingabe direkt zu
    einem TypeError führen kann, weil onGesture() ungeschützt gerufen wird.
  • gen.stats.attempted und gen.stats.tried erwecken den Eindruck zweier Messpunkte
    (Versuche vs. Versuche inkl. Fallback), sind aber dieselbe Zahl.

Lösungsvorschlag

  1. Streichen: o.dead (beide Schleifen), body.dead (makeBody-Initialisierung und
    Zeile 885 – ev.fell bleibt), S.paused, S.newRecord, pit.platform, pit.double,
    ev.releaseTheta, ev.leftGround, gen.stats.attempted, das zweite Argument von
    simStep(...), den reduced-Zweig in hintGrab (Zeile 2158, Aufruf 3159) (bzw. das ganze Argument, wenn es sonst
    nirgends gebraucht wird).
  2. ev.assistedLanding behalten und prüfen: die assistierte Landung ist ein eigener Fall
    (Seil los, Boden erreicht) – entweder einen Test nachrüsten, der ihn erwartet, oder streichen.
  3. INPUT-Hook-Vertrag vervollständigen: Kommentarzeile 2378 auf
    {onPause, onRestart, onMute, onFocus, onGesture, onHookPoint} stellen; onPointer
    entweder in boot() liefern (dann ist die Halbzonen-Logik dort sichtbar) oder die beiden
    Aufrufstellen entfernen.
  4. hitTest auf testBox zurückführen: function hitTest(b, obstacles, tSec, worstCase) { return testBox(b, obstacles, tSec, worstCase, 0); }
    – eine Geometrie, ein Ort.
  5. tests/issue9.mjs erweitern, damit die Regel nicht erneut wegbricht (s. Tests).

Tests

tests/issue9.mjs (Suite „tote APIs“) um Schreib-/Lesekontrolle ergänzen, damit das Weg-
Räumen überprüfbar ist und nicht zurückkommt:

  • Der Quelltext von index.html enthält an den oben genannten Stellen keine Lesezugriffe mehr:
    z. B. /\.dead\b/, /S\.paused/, /anyPointerDown/, /platform:\s*true/,
    /releaseTheta/, /leftGround/, /stats\.attempted/ treffen jeweils 0-mal.
  • INPUT.init wird im Test mit einem Hook-Objekt aufgerufen, das exakt die dokumentierten
    Namen enthält; fehlt onGesture, muss ein TypeError sichtbar sein (der aktuelle Code ruft
    ihn ungeschützt auf – das ist gewollt und muss durch die Doku gedeckt sein).
  • Gegenprobe, dass nichts Lebendes erwischt wurde: ev.rollEnd, ev.landed, ev.fell,
    ev.grabbed, ev.grabCancelled, ev.released, ev.slack, ev.jumped, ev.rollStart
    kommen im Produkt- oder Testpfad weiterhin als Lesestelle vor.

Dokumentiert in issues/21-flags-ohne-setzer-zustaende-ohne-leser.md (Commit 42f3cce).

⁨0⁩ comments

⁨⁩⁨Flags ohne Setzer, Zustände ohne Leser: toter Code in CORE, INPUT und GAME (Folgebefund zu #9)⁩ ⁨⁩#⁨21⁩⁨⁩" By ⁨⁩⁨gilli⁩⁨⁩ — ⁨⁨⁩Open⁨⁩⁩ cleanup low maintainability > **Komponente:** CORE (`hitTest`, `testBox`, `stepBody`, `buildPattern`, `releaseHook`, `generateAhead`), > INPUT (`state`, `init`), GAME (`S`, `update`), RENDER (`hintGrab`) > **Betroffene Version:** `main` @ `42f3cce`, `index.html` (3.333 Zeilen, MD5 `aae5f94c1dc05903f2c214d255d2fe9d`) > > ## Beschreibung > > Issue #9 hat mit `hook.disabled` / `hook.grabs` bereits die Regel etabliert: *ein Flag ohne > Setzer ist keine Funktion* (`tests/issue9.mjs`). Derselbe Befund findet sich an weiteren Stellen, > die bei #9 nicht erfasst wurden. Alle folgenden Felder sind im ausgelieferten Dokument > **geschrieben, aber nie gelesen** oder **gelesen, aber nie geschrieben**: > > | Fundstelle | Zeile(n) | Befund | > |---|---|---| > | `obstacle.dead` | 630, 640 | von `testBox()`/`hitTest()` als Ausnahmeflag gelesen – **niemand setzt ihn**. Ein Hindernis kann daher nie aus der Kollision genommen werden | > | `body.dead` | 654, 885 | wird beim Sturz gesetzt, aber nirgends gelesen; das Spiel benutzt `S.dying` | > | `S.paused` | 2515 | deklariert, nie gelesen und nie geschrieben; Pausenzustand ist `S.state === "PAUSED"`. `tests/browser_issue11.py` Zeile 48 schreibt das Feld wirkungslos | > | `INPUT.state.anyPointerDown` | 2324, 2433, 2471 | Produktcode liest es nie; einziger Leser ist `tests/browser_issue8.py` Zeile 87/222. Entweder als Testbeobachter dokumentieren oder durch `Object.keys(pointers).length === 0` im Test ersetzen | > | `pit.platform`, `pit.double` | 1056, 1072 | Gruben-Metadaten ohne jeden Leser – „Saubere Linie“ hängt an `usedHook`/`touchedGround`, der Solver an Bodensegmenten | > | `ev.releaseTheta` | 721 | gesetzt, kein Leser | > | `ev.leftGround` | 801 | gesetzt, kein Leser | > | `ev.assistedLanding` | 758 | kein Leser im Produkt; in `tests/issue3.mjs` Zeile 50 nur als Diagnose-Feld mitgeschleift, nie geprüft | > | `gen.stats.attempted` | 1475 | Zähler direkt neben `gen.stats.tried` (Zeile 1473), immer um denselben Wert erhöht – redundante Statistik | > | `hooks.onPointer` | 2378 (Doku), 2440, 2464 | wird defensiv aufgerufen, aber `boot()` liefert den Hook nicht; die Doku-Zeile 2378 nennt ihn nicht, dafür fehlt dort das **Pflicht**-Hook `onGesture`, das an sechs Stellen ungeprüft gerufen wird | > | `S.newRecord` | 2513, 2627, 2705 | dreimal geschrieben, nie gelesen (`isRecord` wird lokal entschieden) | > | `RENDER.hintGrab(… reduced)` | 2158 | `reduced ? "GREIFEN" : "GREIFEN"` – beide Zweige identisch; der Aufrufer (Zeile 3159) überspringt den Text bei `reduced` ohnehin | > | `simStep(K.FIXED_TIMESTEP, false)` | 2982 | zweites Argument, das `simStep(dt)` gar nicht annimmt | > | `testBox()` / `hitTest()` | 626–646 | zwei inhaltlich identische Schleifen; `hitTest` ist `testBox` ohne Marge | > > Nicht gemeint: `ev.rollEnd` – das liest `tests/issue14.mjs` (Zeile 76, 169) und ist damit > gebundene Test-API. > > ## Auswirkung > > * Irreführende API: `hitTest(…, o.dead)` suggeriert, Hindernisse könnten deaktiviert werden > (z. B. nach Kassieren), was es nicht gibt. Wer es versucht, arbeitet gegen eine Bedingung, > die immer `false` ist. > * Doppelte Zustandsquellen für denselben Sachverhalt (`S.paused` vs. `S.state`, > `body.dead` vs. `S.dying`) – genau die Klasse, die in Issue #3 und #9 zu echten Fehlern > geführt hat. > * Testschreibarbeit ins Leere: `browser_issue11.py` pflegt `S.paused`, ohne dass es eine > Wirkung hätte. > * `hooks.onPointer` ist ein Vertrag, den niemand erfüllt; die Doku-Zeile an der Stelle ist > zudem unvollständig (`onGesture` fehlt), was beim nächsten Umbau der Eingabe direkt zu > einem `TypeError` führen kann, weil `onGesture()` ungeschützt gerufen wird. > * `gen.stats.attempted` und `gen.stats.tried` erwecken den Eindruck zweier Messpunkte > (Versuche vs. Versuche inkl. Fallback), sind aber dieselbe Zahl. > > ## Lösungsvorschlag > > 1. Streichen: `o.dead` (beide Schleifen), `body.dead` (`makeBody`-Initialisierung und > Zeile 885 – `ev.fell` bleibt), `S.paused`, `S.newRecord`, `pit.platform`, `pit.double`, > `ev.releaseTheta`, `ev.leftGround`, `gen.stats.attempted`, das zweite Argument von > `simStep(...)`, den `reduced`-Zweig in `hintGrab` (Zeile 2158, Aufruf 3159) (bzw. das ganze Argument, wenn es sonst > nirgends gebraucht wird). > 2. `ev.assistedLanding` behalten **und** prüfen: die assistierte Landung ist ein eigener Fall > (Seil los, Boden erreicht) – entweder einen Test nachrüsten, der ihn erwartet, oder streichen. > 3. `INPUT`-Hook-Vertrag vervollständigen: Kommentarzeile 2378 auf > `{onPause, onRestart, onMute, onFocus, onGesture, onHookPoint}` stellen; `onPointer` > entweder in `boot()` liefern (dann ist die Halbzonen-Logik dort sichtbar) oder die beiden > Aufrufstellen entfernen. > 4. `hitTest` auf `testBox` zurückführen: `function hitTest(b, obstacles, tSec, worstCase) { return testBox(b, obstacles, tSec, worstCase, 0); }` > – eine Geometrie, ein Ort. > 5. `tests/issue9.mjs` erweitern, damit die Regel nicht erneut wegbricht (s. Tests). > > ## Tests > > `tests/issue9.mjs` (Suite „tote APIs“) um Schreib-/Lesekontrolle ergänzen, damit das Weg- > Räumen überprüfbar ist und nicht zurückkommt: > > * Der Quelltext von `index.html` enthält an den oben genannten Stellen keine Lesezugriffe mehr: > z. B. `/\.dead\b/`, `/S\.paused/`, `/anyPointerDown/`, `/platform:\s*true/`, > `/releaseTheta/`, `/leftGround/`, `/stats\.attempted/` treffen jeweils 0-mal. > * `INPUT.init` wird im Test mit einem Hook-Objekt aufgerufen, das exakt die dokumentierten > Namen enthält; fehlt `onGesture`, muss ein `TypeError` sichtbar sein (der aktuelle Code ruft > ihn ungeschützt auf – das ist gewollt und muss durch die Doku gedeckt sein). > * Gegenprobe, dass nichts Lebendes erwischt wurde: `ev.rollEnd`, `ev.landed`, `ev.fell`, > `ev.grabbed`, `ev.grabCancelled`, `ev.released`, `ev.slack`, `ev.jumped`, `ev.rollStart` > kommen im Produkt- oder Testpfad weiterhin als Lesestelle vor. > > --- > > *Dokumentiert in `issues/21-flags-ohne-setzer-zustaende-ohne-leser.md` (Commit `42f3cce`).* ⁨0⁩ comments
Author
Owner

Behoben in e4952a0, Doku in 86a481d (issues/README.md, Befund 21).

Gestrichen (jeder Bezeichner jetzt 0-mal im Dokument, geprüft in tests/issue9.mjs):

  • o.dead aus beiden Kollisionsschleifen; hitTest() delegiert auf testBox(…, 0) – eine Geometrie, ein Ort
  • body.dead (makeBody-Initialisierung und Sturz-Zweig) – ev.fell bleibt; die Tests (harness, issue2, issue14, issue15, issue17) lesen jetzt ev.fell bzw. y > K.FALL_DEATH_Y statt des toten Feldes
  • S.paused (Pausenzustand ist S.state), S.newRecord (dreimal geschrieben, isRecord wird lokal entschieden)
  • ev.releaseTheta, ev.leftGround (gesetzt, nie gelesen)
  • gen.stats.attempted (immer dieselbe Zahl wie tried)
  • Zusatzfund derselben Klasse: gen.lastPitHook (gesetzt, nie gelesen)
  • pit.double (kein Leser)
  • die beiden hooks.onPointer-Aufrufstellen (Vertrag, den niemand erfüllt) und der dadurch tote toLogical-Aufruf in endPointer
  • das zweite Argument von simStep(K.FIXED_TIMESTEP, false)
  • der identische reduced ? "GREIFEN" : "GREIFEN"-Zweig; hintGrab trägt den Parameter gar nicht mehr (der Aufrufer zeichnet bei reduced ohnehin keinen Text)

Behalten als gebundene Test-API, im Code dokumentiert:

  • pit.platform – tests/soak.mjs liest es für die Grubenbreiten-Invariante (Plattform-Gruben dürfen per Design breiter als jeder Sprung sein). Der Befund „kein Leser“ trifft nur pit.double.
  • INPUT.state.anyPointerDown – dokumentierter Test-Beobachter für tests/browser_issue8.py („kein halboffener Zeiger“); tests/issue9.mjs prüft jetzt sein beobachtbares Verhalten.

Hook-Vertrag: die Doku-Zeile von INPUT.init nennt jetzt den tatsächlichen Satz {onPause, onRestart, onMute, onFocus, onPrimary, onGesture, onHookPoint(logischer Punkt)} – onGesture war undokumentiert und wird ungeschützt gerufen; tests/issue9.mjs beweist den TypeError bei fehlendem Hook und dass der dokumentierte Satz sauber läuft.

ev.assistedLanding bleibt: seit #22 hat es einen Produktleser (landAssisted im Solver, verifyContent verwirft assistierte Ketten-Landungen) und eine Prüfung in tests/issue22.mjs – der Befund galt für den Stand von 42f3cce.

Verifikation: tests/issue9.mjs 22 → 41 Prüfungen (12 gestrichene Bezeichner 0-mal, Gegenprobe, dass keine lebenden Event-Felder erwischt wurden: ev.rollEnd/landed/fell/grabbed/grabCancelled/released/slack/jumped/rollStart/assistedLanding). Vorher waren issue2/issue14/issue15/issue17 rot (sie lasen body.dead) und der Soak rot (pit.double über die weggefallene Plattform-Markierung); danach alle 15 Node-Suiten und alle 12 Browser-Suiten grün (browser_flow-Einzelwert einmal über der bildratenabhängigen Schranke – bekanntes Messartefakt, 3/3 Wiederholungen grün, die verbindliche deterministische Referenz tests/issue2.mjs grün).

Behoben in `e4952a0`, Doku in `86a481d` (issues/README.md, Befund 21). **Gestrichen** (jeder Bezeichner jetzt 0-mal im Dokument, geprüft in `tests/issue9.mjs`): - `o.dead` aus beiden Kollisionsschleifen; `hitTest()` delegiert auf `testBox(…, 0)` – eine Geometrie, ein Ort - `body.dead` (`makeBody`-Initialisierung und Sturz-Zweig) – `ev.fell` bleibt; die Tests (harness, issue2, issue14, issue15, issue17) lesen jetzt `ev.fell` bzw. `y > K.FALL_DEATH_Y` statt des toten Feldes - `S.paused` (Pausenzustand ist `S.state`), `S.newRecord` (dreimal geschrieben, `isRecord` wird lokal entschieden) - `ev.releaseTheta`, `ev.leftGround` (gesetzt, nie gelesen) - `gen.stats.attempted` (immer dieselbe Zahl wie `tried`) - Zusatzfund derselben Klasse: `gen.lastPitHook` (gesetzt, nie gelesen) - `pit.double` (kein Leser) - die beiden `hooks.onPointer`-Aufrufstellen (Vertrag, den niemand erfüllt) und der dadurch tote `toLogical`-Aufruf in `endPointer` - das zweite Argument von `simStep(K.FIXED_TIMESTEP, false)` - der identische `reduced ? "GREIFEN" : "GREIFEN"`-Zweig; `hintGrab` trägt den Parameter gar nicht mehr (der Aufrufer zeichnet bei `reduced` ohnehin keinen Text) **Behalten als gebundene Test-API, im Code dokumentiert:** - `pit.platform` – `tests/soak.mjs` liest es für die Grubenbreiten-Invariante (Plattform-Gruben dürfen per Design breiter als jeder Sprung sein). Der Befund „kein Leser“ trifft nur `pit.double`. - `INPUT.state.anyPointerDown` – dokumentierter Test-Beobachter für `tests/browser_issue8.py` („kein halboffener Zeiger“); `tests/issue9.mjs` prüft jetzt sein beobachtbares Verhalten. **Hook-Vertrag:** die Doku-Zeile von `INPUT.init` nennt jetzt den tatsächlichen Satz `{onPause, onRestart, onMute, onFocus, onPrimary, onGesture, onHookPoint(logischer Punkt)}` – `onGesture` war undokumentiert und wird ungeschützt gerufen; `tests/issue9.mjs` beweist den `TypeError` bei fehlendem Hook und dass der dokumentierte Satz sauber läuft. **`ev.assistedLanding` bleibt:** seit #22 hat es einen Produktleser (`landAssisted` im Solver, `verifyContent` verwirft assistierte Ketten-Landungen) und eine Prüfung in `tests/issue22.mjs` – der Befund galt für den Stand von `42f3cce`. **Verifikation:** `tests/issue9.mjs` 22 → 41 Prüfungen (12 gestrichene Bezeichner 0-mal, Gegenprobe, dass keine lebenden Event-Felder erwischt wurden: `ev.rollEnd/landed/fell/grabbed/grabCancelled/released/slack/jumped/rollStart/assistedLanding`). Vorher waren issue2/issue14/issue15/issue17 rot (sie lasen `body.dead`) und der Soak rot (`pit.double` über die weggefallene Plattform-Markierung); danach alle 15 Node-Suiten und alle 12 Browser-Suiten grün (`browser_flow`-Einzelwert einmal über der bildratenabhängigen Schranke – bekanntes Messartefakt, 3/3 Wiederholungen grün, die verbindliche deterministische Referenz `tests/issue2.mjs` grün).
Author
Owner

Behoben in e4952a0, Doku in 86a481d (issues/README.md, Befund 21).

Gestrichen (jeder Bezeichner jetzt 0-mal im Dokument, geprüft in tests/issue9.mjs):

  • o.dead aus beiden Kollisionsschleifen; hitTest() delegiert auf testBox(…, 0) – eine Geometrie, ein Ort
  • body.dead (makeBody-Initialisierung und Sturz-Zweig) – ev.fell bleibt; die Tests (harness, issue2, issue14, issue15, issue17) lesen jetzt ev.fell bzw. y > K.FALL_DEATH_Y statt des toten Feldes
  • S.paused (Pausenzustand ist S.state), S.newRecord (dreimal geschrieben, isRecord wird lokal entschieden)
  • ev.releaseTheta, ev.leftGround (gesetzt, nie gelesen)
  • gen.stats.attempted (immer dieselbe Zahl wie tried)
  • Zusatzfund derselben Klasse: gen.lastPitHook (gesetzt, nie gelesen)
  • pit.double (kein Leser)
  • die beiden hooks.onPointer-Aufrufstellen (Vertrag, den niemand erfüllt) und der dadurch tote toLogical-Aufruf in endPointer
  • das zweite Argument von simStep(K.FIXED_TIMESTEP, false)
  • der identische reduced ? "GREIFEN" : "GREIFEN"-Zweig; hintGrab trägt den Parameter gar nicht mehr (der Aufrufer zeichnet bei reduced ohnehin keinen Text)

Behalten als gebundene Test-API, im Code dokumentiert:

  • pit.platform – tests/soak.mjs liest es für die Grubenbreiten-Invariante (Plattform-Gruben dürfen per Design breiter als jeder Sprung sein). Der Befund „kein Leser“ trifft nur pit.double.
  • INPUT.state.anyPointerDown – dokumentierter Test-Beobachter für tests/browser_issue8.py („kein halboffener Zeiger“); tests/issue9.mjs prüft jetzt sein beobachtbares Verhalten.

Hook-Vertrag: die Doku-Zeile von INPUT.init nennt jetzt den tatsächlichen Satz {onPause, onRestart, onMute, onFocus, onPrimary, onGesture, onHookPoint(logischer Punkt)} – onGesture war undokumentiert und wird ungeschützt gerufen; tests/issue9.mjs beweist den TypeError bei fehlendem Hook und dass der dokumentierte Satz sauber läuft.

ev.assistedLanding bleibt: seit #22 hat es einen Produktleser (landAssisted im Solver, verifyContent verwirft assistierte Ketten-Landungen) und eine Prüfung in tests/issue22.mjs – der Befund galt für den Stand von 42f3cce.

Verifikation: tests/issue9.mjs 22 → 41 Prüfungen (12 gestrichene Bezeichner 0-mal, Gegenprobe, dass keine lebenden Event-Felder erwischt wurden: ev.rollEnd/landed/fell/grabbed/grabCancelled/released/slack/jumped/rollStart/assistedLanding). Vorher waren issue2/issue14/issue15/issue17 rot (sie lasen body.dead) und der Soak rot (pit.double über die weggefallene Plattform-Markierung); danach alle 15 Node-Suiten und alle 12 Browser-Suiten grün (browser_flow-Einzelwert einmal über der bildratenabhängigen Schranke – bekanntes Messartefakt, 3/3 Wiederholungen grün, die verbindliche deterministische Referenz tests/issue2.mjs grün).

Behoben in `e4952a0`, Doku in `86a481d` (issues/README.md, Befund 21). **Gestrichen** (jeder Bezeichner jetzt 0-mal im Dokument, geprüft in `tests/issue9.mjs`): - `o.dead` aus beiden Kollisionsschleifen; `hitTest()` delegiert auf `testBox(…, 0)` – eine Geometrie, ein Ort - `body.dead` (`makeBody`-Initialisierung und Sturz-Zweig) – `ev.fell` bleibt; die Tests (harness, issue2, issue14, issue15, issue17) lesen jetzt `ev.fell` bzw. `y > K.FALL_DEATH_Y` statt des toten Feldes - `S.paused` (Pausenzustand ist `S.state`), `S.newRecord` (dreimal geschrieben, `isRecord` wird lokal entschieden) - `ev.releaseTheta`, `ev.leftGround` (gesetzt, nie gelesen) - `gen.stats.attempted` (immer dieselbe Zahl wie `tried`) - Zusatzfund derselben Klasse: `gen.lastPitHook` (gesetzt, nie gelesen) - `pit.double` (kein Leser) - die beiden `hooks.onPointer`-Aufrufstellen (Vertrag, den niemand erfüllt) und der dadurch tote `toLogical`-Aufruf in `endPointer` - das zweite Argument von `simStep(K.FIXED_TIMESTEP, false)` - der identische `reduced ? "GREIFEN" : "GREIFEN"`-Zweig; `hintGrab` trägt den Parameter gar nicht mehr (der Aufrufer zeichnet bei `reduced` ohnehin keinen Text) **Behalten als gebundene Test-API, im Code dokumentiert:** - `pit.platform` – `tests/soak.mjs` liest es für die Grubenbreiten-Invariante (Plattform-Gruben dürfen per Design breiter als jeder Sprung sein). Der Befund „kein Leser“ trifft nur `pit.double`. - `INPUT.state.anyPointerDown` – dokumentierter Test-Beobachter für `tests/browser_issue8.py` („kein halboffener Zeiger“); `tests/issue9.mjs` prüft jetzt sein beobachtbares Verhalten. **Hook-Vertrag:** die Doku-Zeile von `INPUT.init` nennt jetzt den tatsächlichen Satz `{onPause, onRestart, onMute, onFocus, onPrimary, onGesture, onHookPoint(logischer Punkt)}` – `onGesture` war undokumentiert und wird ungeschützt gerufen; `tests/issue9.mjs` beweist den `TypeError` bei fehlendem Hook und dass der dokumentierte Satz sauber läuft. **`ev.assistedLanding` bleibt:** seit #22 hat es einen Produktleser (`landAssisted` im Solver, `verifyContent` verwirft assistierte Ketten-Landungen) und eine Prüfung in `tests/issue22.mjs` – der Befund galt für den Stand von `42f3cce`. **Verifikation:** `tests/issue9.mjs` 22 → 41 Prüfungen (12 gestrichene Bezeichner 0-mal, Gegenprobe, dass keine lebenden Event-Felder erwischt wurden: `ev.rollEnd/landed/fell/grabbed/grabCancelled/released/slack/jumped/rollStart/assistedLanding`). Vorher waren issue2/issue14/issue15/issue17 rot (sie lasen `body.dead`) und der Soak rot (`pit.double` über die weggefallene Plattform-Markierung); danach alle 15 Node-Suiten und alle 12 Browser-Suiten grün (`browser_flow`-Einzelwert einmal über der bildratenabhängigen Schranke – bekanntes Messartefakt, 3/3 Wiederholungen grün, die verbindliche deterministische Referenz `tests/issue2.mjs` grün).
Author
Owner

Behoben in e4952a0, Doku in 86a481d – Details im Kommentar oben; tests/issue9.mjs führt die Schreib-/Lesekontrolle (41 Prüfungen).

Behoben in e4952a0, Doku in 86a481d – Details im Kommentar oben; tests/issue9.mjs führt die Schreib-/Lesekontrolle (41 Prüfungen).
gilli closed this issue 2026-09-04 06:56:51 +02:00
Sign in to join this conversation.
No description provided.