Pryne Frontend Debugging Playbook
Symptom→Triage für Pryne's Vanilla-JS-Demo-Builds: Einseitige HTML-Seiten, gesteuert durch ein window.Roll-Modulgerüst (design-demos/js/roll-*.js), einen WebGL-Korn-Shader mit 2D-Fallback, eine rAF-Render-Schleife, integrierten Lenis-Smooth-Scroll und GSAP asynchron von CDN als progressive Erweiterung geladen.
ERFORDERLICHER HINTERGRUND: superpowers:systematic-debugging besitzt die generische Root-Cause-Disziplin (keine Fixes ohne Untersuchung). Folge dieser; dieses Skill liefert nur die projektspezifische Symptomtabelle und Fallen.
Werkzeuge: für die Steuerung des Browsers, Konsolenerfassung, Emulation von reduzierter Bewegung und Aufnahme von Traces verwende pryne-browser-lab. Dieses Skill geht davon aus, dass du diese Befehle bereits ausführen kannst.
Lies zuerst den Kopfkommentar
Jede v4-Demo (v4-a bis v4-d in design-demos/) trägt ihren Audit-Verlauf als HTML-Kommentar ganz oben in der Datei – was wurde als defekt gefunden, was wurde behoben und warum. Verifiziert für alle vier Dateien zum Stand 22.07.2026. Bevor du etwas neu diagnostizierst, führe head -30 für die Demo aus, die du debuggen möchtest. Mehrere „Bugs“, die du finden wirst, sind als bereits behobene Regressionen dokumentiert; wenn einer zurückkommt, suchst du nach dem, was sie rückgängig gemacht hat, nicht nach einer neuen Ursache.
Kennt auch den Build-Layout (Stand 22.07.2026): nur v4-d-hybrid.html verwendet die gemeinsamen roll-*.js-Module. v4-a/b/c sind reduzierte Vergleichs-Builds mit eigenem Inline-JS – die Roll-spezifischen Checks dieser Tabelle gelten nicht für sie, aber die gleichen Fehlerklassen treten auf.
Null Konsolenfehler ist der Ruhezustand
Der Standard ist null Konsolenfehler (das CRITIQUE-Rubrik in design-demos/DECISIONS.md erfordert dies). v3 wurde gemäß dem Projektstatusprotokoll auf null verifiziert; die v4-Varianten sind unbekannt bis zur Richtungskampagne (pryne-design-direction-decision). Jeder Konsolenfehler ist ein zu triagierender Defekt, nie ein Rauschen, das überblättert werden kann.
Symptom → Triage-Tabelle
| Symptom | Wahrscheinliche Ursache | Unterscheidungscheck |
|---|---|---|
| Animation/Entwicklungs-Platte läuft (oder wird fertig), bevor ihr Abschnitt in den Viewport gescrollt ist | Regression der Sichtbarkeitsgatterung. Der v4-d-Kopfkommentar dokumentiert dies als den höchstpriorisierten Audit-Fix: Feature-Platten „liefen bedingungslos ab Seitenladevorgang und waren fertig, bevor jemand zu ihnen gescrollt hatte.“ Die Entwicklung muss auf der .in-Klasse des Panels gattert werden. | Experiment 1 unten |
| Reveal-Animation clippt falsch, springt oder wird nie ausgelöst | clip-path auf das Element angewendet, das der IntersectionObserver beobachtet, statt auf einen inneren Wrapper. Der Konzept-C-Fix (in v4-d übernommen, gemäß Kopfkommentar): Der Clip-Path-Reveal lebt auf einem inneren Wrapper, niemals auf dem beobachteten Element. | Inspiziere das Element: Ist der beobachtete Knoten und der geklippte Knoten derselbe Knoten? |
| OS-Cursor verschwindet, kein benutzerdefinierter Cursor ersetzt ihn | Sollte nicht wieder auftreten – behoben am 22.07.2026 (gefunden durch einen Cold-Test-Audit, am selben Tag behoben): Der Per-Event-Handler (roll-cursor.js:17-20) und sein pointermove-Aufrufort (roll-core.js:26-29) fangen nun beide ab und stellen wieder her (null Roll.cursorUpdate, entfernen .custom-cursor), zusätzlich zum ursprünglichen Setup-Zeitpunkt-Catch; #cur/#ring z-index auf 50→70 über #flash (60) erhöht, damit der Höhepunktsimpuls nicht über den Cursor malen kann. Wenn das Symptom wieder auftritt, ist eine dieser Absicherungen regrediert oder neuer Code versteckt den Cursor außerhalb dieses Vertrags. | document.body.classList.contains('custom-cursor') vs Roll.cursorUpdate – true/null zusammen ist der defekte Zustand; wenn beide intakt aussehen, überprüfe getComputedStyle(cur).opacity und ob es nur beim Höhepunktsblitz verschwindet |
| WebGL-Geisterbilder/Spuren oder Farben mischen falsch mit der Seite | Fehlender Frame-Clear oder Premultiplied-Alpha-Konflikt. roll-shader.js ruft gl.clear(gl.COLOR_BUFFER_BIT) jeden Frame auf und erstellt den Context mit { alpha: true, premultipliedAlpha: false } (beides Audit-Fixes, gemäß v4-d-Kopfkommentar). | Diff roll-shader.js gegen Git: git diff HEAD -- design-demos/js/roll-shader.js |
| Shader-Canvas leer, kein Korn | (a) Reduzierte Bewegung – GL wird absichtlich nie eingerichtet (useGL = !Roll.reduced && setupGL()); (b) WebGL-Kontext verloren – der webglcontextlost-Handler setzt das Canvas auf Opazität 0 und schlägt leise fehl; (c) Ein 2D-Kontext wurde erworben, bevor WebGL seine Chance bekam (ein Kontext pro Canvas, immer – dokumentiert oben in roll-shader.js). | Roll.reduced zuerst. Bei Kontextverlust überprüfe die beobachtbare Wirkung des Handlers: getComputedStyle(document.getElementById('tone')).opacity === '0'. Achtung: Roll.shader.useGL ist eine Setup-Zeitpunkt-Aufnahme (roll-shader.js:120-121) – der webglcontextlost-Handler kippt nur die Closure-Variable (roll-shader.js:130-132), also bleibt Roll.shader.useGL nach Kontextverlust true; verwende es nicht, um Verlust auszuschließen |
| Scroll-Choreographie tot, aber die Seite rendert und scrollt normal | Skript-Ladereihenfolge oder window.Roll-Namespace-Bruch. Die Skript-Reihenfolge ist tragend – die Kette und Check-Befehle leben in pryne-frontend-architecture. Jedes Modul ist ein IIFE, das nur über window.Roll Status teilt; ein geworfener Fehler in einem frühen Modul hungert alles danach aus. | Experiment 2 unten; die Konsole zeigt Roll.X is undefined und benennt das ausgehungerte Modul |
| Alle Bewegung tot für einen Benutzerbericht; funktioniert auf deinem Rechner | prefers-reduced-motion ist für sie aktiv. Dies ist korrektes Verhalten, kein Bug: roll-core.js setzt Roll.reduced aus der Media Query, und jedes Modul gattert darauf (Cover entfernt, Platten vollständig entwickelt sofort, Lenis übersprungen, Shader aus). Versuche nicht, es zu „beheben“. | Experiment 3 unten |
| Scroll-Gefühl inkonsistent zwischen Trackpad/Mausrad/Touch | Rohe Scroll-Delta-Varianz – die dokumentierte Begründung für die Integration von Lenis (siehe design-demos/DECISIONS.md). Lenis umschließt natives Scrollen, also bleibt window.scrollY gültig; es ist nur eine Gefühlsverbesserung, null bei reduzierter Bewegung. | typeof Lenis (geladen?), dann überprüfe, ob die Demo es in ihrem Scroll-Modul erstellt |
| Basis funktioniert, aber Hover/kinetische/Cursor-Polish fehlen | GSAP CDN fehlgeschlagen oder blockiert. GSAP lädt async von jsdelivr (SRI-gepinnt) und kippt Roll.enhanced = true über Roll.upgradeMotion() nur, wenn es ankommt. Progressive Verbesserung ist gewollt: Basis-Choreographie muss auch ohne funktionieren. Wenn die Basis auch kaputt ist, ist dies nicht deine Ursache. | Experiment 4 unten |
| Audio stumm | Stumm ist der Standard: roll-audio.js startet stumm, speichert die Auswahl in localStorage['ch001_muted'] und startet das Hintergrundsummen erst beim Klick auf #mute-toggle (eine Benutzergeste, die Autoplay-Richtlinie erfüllt). Alle Synthese ist try/catch-gewrappt und asset-frei. Überprüfe den SND-Schalterzustand, bevor du den Code verdächtigst. | Roll.audio.muted und localStorage.getItem('ch001_muted') |
| Festes HUD überlappt/verdeckt den Footer | Regression des Footer-Einblendungs-Fixes: Ein IntersectionObserver auf footer schaltet .faded auf dem Beat-Meter und der Stummschalt-Taste um (roll-scroll.js). | Scrolle zum Footer; überprüfe, ob .faded auf #beatmeter erscheint |
Unterscheidende Experimente
Führe diese in der Seitenkonsole oder über evaluate_script aus (siehe pryne-browser-lab). Jedes beantwortet eine Frage, bevor du Code anfasst.
1 – Ist die Platten-Entwicklung korrekt auf Sichtbarkeit gattert?
({ workVisible: document.getElementById('work').classList.contains('in'),
plate1: { d: Roll.featurePlate.d, done: !!Roll.featurePlate.done },
plate2: { d: Roll.featurePlate2.d, done: !!Roll.featurePlate2.done } })
Bei einem frischen Ladevorgang, bevor zum Arbeitsbereich gescrollt wird: workVisible: false und beide d-Werte nahe 0. Wenn d steigt (oder done: true), während workVisible false ist, ist die Gatterung regrediert.
2 – Ist das Roll-Gerüst intakt?
({ core: !!window.Roll, reduced: Roll?.reduced, enhanced: Roll?.enhanced,
shader: !!Roll?.shader, audio: !!Roll?.audio, plates: !!Roll?.plates,
cursorUpdate: Roll?.cursorUpdate === null ? 'null' : typeof Roll?.cursorUpdate })
Hinweis zu cursorUpdate: Es wird initialisiert null (roll-core.js:23) und ist auch null vor GSAP-Ladevorgang und auf Nicht-pointer: fine-Geräten – null allein beweist nichts. „Sicher fehlgeschlagen“ wird nur angezeigt, wenn document.body.classList.contains('custom-cursor') true und cursorUpdate null ist (siehe die Cursor-Zeile in der Triage-Tabelle).
Jedes false/undefined benennt das Modul, das nicht fertig wurde – überprüfe die Konsole auf den Fehler, den es geworfen hat, und überprüfe die Skript-Reihenfolge im HTML gegen die tragende Reihenfolge oben.
3 – Ist „alle Bewegung tot“ nur reduzierte Bewegung?
({ mediaQuery: matchMedia('(prefers-reduced-motion: reduce)').matches, roll: Roll.reduced })
Beide true → funktioniert wie vorgesehen; reproduziere den Bericht durch Emulation von reduzierte Bewegung (pryne-browser-lab). mediaQuery: true aber roll: false (oder umgekehrt) → ein Modul liest die falsche Wahrheitsquelle.
4 – Ist die GSAP-Erweiterungsebene geladen?
({ gsapLoaded: !!window.gsap, enhanced: Roll.enhanced, reduced: Roll.reduced })
gsapLoaded: false → CDN blockiert/fehlgeschlagen (überprüfe das Netzwerk-Panel auf jsdelivr-Anfrage; SRI-Konflikt landet auch hier). gsapLoaded: true, enhanced: false, reduced: false → upgradeMotion() wurde nicht ausgeführt – überprüfe den onload-Hook des Skript-Tags.
Fallen, die echte Zeit kosten
| Falle | Die Geschichte (eine Zeile) | Der Zaun |
|---|---|---|
| „Verifiziert funktionsfähig“ ≠ richtige Richtung | v3 NIGHT DRIVE war vollständig gebaut, null Konsolenfehler, verifiziert – dann ersetzt, weil das vereinheitlichende Konzept falsch war (vollständiger Bericht: pryne-failure-archaeology). | Verwende keine Polier-/Debugging-Mühe, um einen Build zu verteidigen, dessen Konzept noch nicht als aktuelle Richtung bestätigt wurde. Überprüfe zuerst DECISIONS.md und den Vault-Status. |
| Erneute Diagnose eines dokumentierten Fixes | Jeder v4-Kopfkommentar ist ein Änderungsprotokoll bereits gefundener, bereits behobener Defekte. | Lese den Kopfkommentar, bevor du die Entwicklertools öffnest. Wenn ein aufgelisteter Fix kaputt erscheint, jage die Regression, nicht das Symptom. |
| „Beheben“ von reduzierter Bewegung | Alle Bewegung aus ist das entworfene Verhalten für prefers-reduced-motion-Benutzer, an einer Stelle gattert (Roll.reduced). | Führe Experiment 3 aus, bevor du einen Bericht über fehlende Bewegung als Defekt behandelst. |
| Erwerb eines 2D-Kontexts „um etwas zu testen“ | Ein Canvas kann nur einen Kontexttyp haben; das Zuerst-Greifen von 2D macht WebGL auf diesem Canvas für immer unmöglich (dokumentiert in roll-shader.js). | Rufe niemals getContext('2d') auf #tone in Konsolenexperimenten auf. |
Wann dieses Skill NICHT verwenden
- Generische Debugging-Disziplin (Hypothesen, minimale Änderungen, Root-Cause-vor-Fix) → superpowers:systematic-debugging.
- Wie steuere ich den Browser/messe ich (MCP-Tool-Anatomie, Traces, Lighthouse, Screenshots) → pryne-browser-lab.
- Entscheidung, ob Verhalten gegen eine Design-Invariante verstößt (Reduzierte-Bewegung-Gatterung, Flüster-Persönlichkeit, Integration) → pryne-frontend-architecture.
- Die vollständige Geschichte, warum etwas gebaut/rückgängig gemacht wurde → pryne-failure-archaeology.
- Andere Stacks (React/Framework-Builds, Nicht-Pryne-Projekte): Die Tabelle oben ist spezifisch für die
window.Roll-Demo-Familie; nur die generische Disziplin überträgt sich.
Herkunft und Wartung
Führe scripts/verify.sh (im Verzeichnis dieses Skills) aus, um alle unten stehenden Punkte auf einmal zu überprüfen.
Fakten aktuell zum 22.07.2026, verifiziert gegen Repository ~/Documents/Coding Folder/Portfolio (test) bei Commit 457868a. Überprüfe erneut, bevor du vertraust:
- Modulliste und -größen:
wc -l design-demos/js/*.js - Skript-Ladereihenfolge:
grep -n "<script" design-demos/v4-d-hybrid.html - Welche Demos die gemeinsamen Module verwenden:
grep -l "roll-core.js" design-demos/*.html - Kopfkommentar-Konvention gilt noch:
for f in design-demos/v4-*.html; do echo "== $f"; head -5 "$f"; done - Reduzierte-Bewegung-Gatter:
grep -n "prefers-reduced-motion\|Roll.reduced" design-demos/js/*.js - Platten-Sichtbarkeit-Gatterung:
grep -n "classList.contains('in')" design-demos/js/roll-scroll.js - Lenis integriert und verdrahtet:
ls design-demos/js/vendor/ && grep -n "new Lenis" design-demos/js/roll-scroll.js - GSAP-Erweiterungs-Hook:
grep -n "upgradeMotion" design-demos/js/roll-core.js design-demos/v4-d-hybrid.html - Audio-Stumm-Standard & Speicher-Schlüssel:
grep -n "ch001_muted" design-demos/js/roll-audio.js - Null-Konsolenfehler-Bar:
grep -n "console errors" design-demos/DECISIONS.md