From 95b22e2add3b90ad910acfd044b78d8ae5e1cfb9 Mon Sep 17 00:00:00 2001 From: Axel Hocks Date: Wed, 19 Aug 2026 23:07:52 +0200 Subject: [PATCH] FIX: Render brach ab - RSI-Zeile griff im falschen Scope zu (Dashboard kaputt) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User-Screenshot: sechs leere "—"-Zeilen in der M15-Karte unter Gate ④ und eine komplett leere Breakout-Karte. URSACHE, mein Fehler von heute Abend: `renderM15(s)` bekommt NUR `m15_setup`. Meine RSI-Zeile griff aber auf `d.market.rsi_m15` zu - `d` existiert in diesem Scope nicht. ReferenceError mitten im Render: alles ab der Fehlerstelle blieb auf dem Initialwert "—", und die danach gerufenen Renderer (u.a. renderBrk) liefen gar nicht mehr. Genau die Signatur im Screenshot. ⚠⚠ WARUM DIE PIPELINE ES DURCHGELASSEN HAT: `node --check` prueft nur SYNTAX. Ein ReferenceError ist syntaktisch einwandfrei. Python hat dafuer ruff F821 - fuer JS gab es nichts Vergleichbares. Das ist die Luecke, nicht ein Einzelversehen: es ist der ZWEITE Fall derselben Klasse heute (vorhin `d5.m5` statt `s.m5`, den hatte ich beim Bauen selbst bemerkt). BEHOBEN: renderM15(s, snap) bekommt den vollen Snapshot mit, Aufrufer angepasst, Zugriff auf ((snap||{}).market||{}).rsi_m15. Ein Kommentar an der Signatur haelt fest, warum `d.` dort verboten ist. NEU: tools/render_check.mjs - laesst renderM15 und renderBrk gegen ein Minimal-DOM mit einem ECHTEN Snapshot laufen und meldet jede Exception. Mutationsprobe bestanden: Fehler zurueckgebaut -> "❌ d is not defined", zurueck -> gruen. Alle vier Zeilen rendern wieder korrekt (RSI, M5-Kontext, Gate ③b, BRK-Position). v=188, damit der Browser das Update sicher zieht. Co-Authored-By: Claude Opus 5 --- tools/render_check.mjs | 34 ++++++++++++++++++++++++++++++++++ web/app.js | 11 ++++++++--- web/index.html | 4 ++-- 3 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 tools/render_check.mjs diff --git a/tools/render_check.mjs b/tools/render_check.mjs new file mode 100644 index 0000000..197f1b8 --- /dev/null +++ b/tools/render_check.mjs @@ -0,0 +1,34 @@ +// Render-Probe: laesst renderM15 + renderBrk gegen ein Minimal-DOM laufen. +// +// ⚠⚠ WARUM ES DAS GIBT (2026-08-19): `node --check` prueft nur die SYNTAX. Ein +// ReferenceError (falsche Variable im falschen Scope) ist syntaktisch +// einwandfrei und faellt erst im Browser auf - dort bricht er aber den +// GESAMTEN Render ab: alles ab der Fehlerstelle bleibt auf "—", und die +// danach gerufenen Renderer laufen gar nicht mehr. Real passiert: die +// RSI-Zeile griff in `renderM15(s)` auf `d.market` zu; das Dashboard zeigte +// sechs leere Zeilen und eine komplett leere Breakout-Karte. +// Python hat dafuer `ruff F821` - fuer JS gab es nichts Vergleichbares. +// +// Aufruf: node tools/render_check.mjs +// Snapshot holen: curl -s http://127.0.0.1:8000/api/snapshot > snap.json +import fs from "fs"; +const snap = JSON.parse(fs.readFileSync(process.argv[2], "utf-8")); +const src = fs.readFileSync("web/app.js", "utf-8"); +const store = {}; +const mk = (id) => ({ id, set textContent(v){ store[id]=v; }, get textContent(){return store[id]||"";}, + set className(v){}, get className(){return "";}, classList:{add(){},remove(){},toggle(){}}, + style:{}, value:"", title:"", addEventListener(){}, blur(){}, focus(){} }); +const cache = {}; +global.document = { getElementById: (id) => (cache[id] ||= mk(id)), + querySelectorAll: () => [], querySelector: () => null, addEventListener(){}, + get activeElement(){return null;}, createElement: () => mk("_") }; +const m = src.match(/function renderM15\([\s\S]*?\n\}/); +const b = src.match(/function renderBrk\([\s\S]*?\n\}/); +const helfer = 'const _F=document.createElement("span");' + + 'const $=(id)=>document.getElementById(id)||_F; const $streng=(id)=>document.getElementById(id);'; +const fn = new Function("snapshot", helfer + "\n" + m[0] + "\n" + (b?b[0]:"function renderBrk(){}") + + "\nrenderM15(snapshot.m15_setup, snapshot); renderBrk(snapshot);"); +try { fn(snap); console.log(" ✅ renderM15 + renderBrk laufen OHNE Exception durch"); } +catch (e) { console.log(" ❌ EXCEPTION: " + e.message); process.exit(1); } +for (const k of ["m15-rsi","m15-m5","m15-motor","brk-pos","brk-state"]) + console.log(" " + k.padEnd(12) + " = " + (store[k] || "(leer)")); diff --git a/web/app.js b/web/app.js index 7948aed..1c39023 100644 --- a/web/app.js +++ b/web/app.js @@ -252,7 +252,12 @@ function renderBrk(d) { } } -function renderM15(s) { +function renderM15(s, snap) { + // ⚠⚠ `snap` = der VOLLE Snapshot. `s` ist nur `m15_setup` — wer hier auf + // `d.` zugreift, erzeugt einen ReferenceError, der den GESAMTEN Render + // abbricht: alles ab der Fehlerstelle bleibt auf "—" stehen, und die + // danach gerufenen Renderer (u. a. `renderBrk`) laufen gar nicht mehr. + // Genau das ist am 19.08. passiert (RSI-Zeile griff auf `d.market`). const st = $("m15-status"); if (!s) { st.className = "m15-status"; st.textContent = "— keine Daten"; return; } const f = (v, d = 2) => (v == null ? "—" : (+v).toFixed(d)); @@ -410,7 +415,7 @@ function renderM15(s) { // Ueberdehnungs-Anzeige, die aus demselben Grund "Ueberdehnung" heisst und // nicht "Bounce". const rsiEl = $("m15-rsi"); - const rv = (d.market || {}).rsi_m15; + const rv = ((snap || {}).market || {}).rsi_m15; if (rv == null) { rsiEl.textContent = "RSI · —"; } else { @@ -1079,7 +1084,7 @@ function render(d) { } // ── Gesamtempfehlung (aggregiert) ─────── - renderM15(d.m15_setup); + renderM15(d.m15_setup, d); renderBrk(d); renderKontext(d); renderCircuitBreaker(d.circuit_breaker); diff --git a/web/index.html b/web/index.html index 055011a..6f32ffd 100644 --- a/web/index.html +++ b/web/index.html @@ -12,7 +12,7 @@ ⚠ LOKAL eingebunden, kein CDN: die PWA laeuft ueber WireGuard und muss offline funktionieren. --> - + @@ -392,6 +392,6 @@ - +