JS-Syntaxpruefung: node --check als Stufe B in check_nfalle

CLAUDE.md behauptete "kein node im Env" - das stimmte nicht mehr, Node
v24.18.0 ist installiert. Die Zeile hat die Frage jahrelang falsch
beantwortet.

Gemessen an 5 realistischen Fehlern findet die alte Klammern-Balance 1,
node --check findet 5 (86 ms):
  Klammer zu viel        Balance ok   node ok
  const x = ;            Balance blind
  let doppelt            Balance blind
  const doppelt          Balance blind
  return ausserhalb Fkt. Balance blind

Ein Syntaxfehler in app.js bricht den GESAMTEN Render - das Dashboard
friert auf Altwerten ein. Bei 95 direkt dereferenzierten $("id")-Zugriffen
(0 davon mit ?.) ist das kein theoretisches Risiko.

Geprueft wird als MODUL (.mjs), nicht als CommonJS: als CJS haelt Node ein
top-level return fuer legal, der Browser laedt app.js aber als klassisches
Script, wo es ein Syntaxfehler ist. Verifiziert, dass das echte app.js den
strengeren Modus ohne Anpassung besteht.

Kein npm, keine package.json, kein node_modules - node --check ist die
Laufzeit selbst. Damit entsteht NICHT die Divergenz "Pruefumgebung ist nicht
die Laufumgebung" (der .ps1-BOM-Fehler, das pre-commit-Framework): Node und
Chrome benutzen denselben Parser (V8).

Drei Richtungen verifiziert:
  sauber                -> gruen
  mit eingebautem Fehler-> Exit 1, Commit gestoppt
  ohne node im PATH     -> Rueckfall auf alte Pruefung, Exit 0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Axel Hocks
2026-08-07 07:27:37 +02:00
co-authored by Claude Opus 5
parent fd3c7f57a5
commit e7112e1ab6
2 changed files with 83 additions and 6 deletions
+22 -2
View File
@@ -257,8 +257,28 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche:
(WR/PF/Verhältnis/Worst je KW, Ausrichtungs-Split mit/gegen/ohne) gegen die
Backtest-Erwartung (WR~68 % · PF~1,3 · Verh~0,55) und flaggt Leckagen (Gegen-Signal-
Anteil, WR-Verfall, PF<1, Einzelverlust). **Wöchentlich** laufen lassen (B4/B5).
- **Vor „fertig":** immer `python -m py_compile <datei>`; JS grob via Klammern-
Balance prüfen (kein node im Env).
- **Vor „fertig":** immer `python -m py_compile <datei>`; JS via **`node --check`**
(Stufe B in `tools/check_nfalle.py`, läuft im pre-commit-Hook mit).
⚠⚠ **KORREKTUR 2026-08-07: „kein node im Env" stimmte nicht mehr** — Node
**v24.18.0** ist installiert. Die Zeile hat die Frage „können wir Node nutzen?"
jahrelang falsch beantwortet.
**Gemessen, warum das zählt:** die alte Klammern-Balance findet **1 von 5**
realistischen Fehlern — `const x = ;`, doppeltes `let`/`const` und `return`
ausserhalb einer Funktion laufen glatt durch; `node --check` findet **5 von 5**
in **86 ms**. Ein Syntaxfehler in `app.js` bricht den **GESAMTEN** Render
(Dashboard friert auf Altwerten ein) — bei **95 direkt dereferenzierten**
`$("id")`-Zugriffen ist das kein theoretisches Risiko.
**Geprüft wird als MODUL (`.mjs`), nicht als CommonJS:** als CJS hält Node ein
top-level `return` für legal, der Browser lädt `app.js` aber als klassisches
Script, wo es ein Syntaxfehler ist. Verifiziert, dass das echte `app.js` den
strengeren Modus **ohne Anpassung** besteht.
**Kein npm, keine `package.json`, kein `node_modules`**`node --check` ist
die Laufzeit selbst. Damit entsteht NICHT die Divergenz „Prüfumgebung ≠
Laufumgebung" (die beim `.ps1`-BOM und beim `pre-commit`-Framework das Problem
war): Node und Chrome benutzen **denselben Parser (V8)**.
**Drei Richtungen verifiziert:** sauber → grün · mit eingebautem Fehler →
**Exit 1**, Commit gestoppt · **ohne Node im PATH** → Rückfall auf die alte
Prüfung, Exit 0 (eine frische Maschine darf am Hook nicht hängenbleiben).
- **✅ BOOT-LÜCKE GESCHLOSSEN: Auto-Logon AKTIV (2026-08-07).**
`OilTradingServer` und `HyperliquidDashboard` hängen an einem **Logon**-Trigger
— nach einem Update-Reboot läuft nichts bis zur Anmeldung (real 20.07.:
+61 -4
View File
@@ -190,18 +190,75 @@ def js_offene_strings(text: str):
print()
print("=" * 88)
print(" B) JAVASCRIPT — unabgeschlossene String-Literale")
print(" B) JAVASCRIPT — Syntax (node) + unabgeschlossene String-Literale")
print("=" * 88)
def node_pruefen(p: pathlib.Path):
"""Echte Syntaxpruefung mit `node --check`. Gibt die Fehlerzeile zurueck oder
None; `False` heisst „Node nicht verfuegbar".
⚠ WARUM DAS DAZUKAM (2026-08-07). Die Klammern-Balance findet gemessen nur
1 von 5 realistischen Fehlern — `const x = ;`, ein doppeltes `let`/`const`
und ein `return` ausserhalb einer Funktion laufen glatt durch. Ein
Syntaxfehler in `app.js` bricht aber den GESAMTEN Render: das Dashboard
friert auf Altwerten ein. Bei 95 direkten Element-Zugriffen ist das kein
theoretisches Risiko.
⚠ GEPRUEFT WIRD ALS MODUL (.mjs), NICHT ALS CommonJS. Als CJS haelt Node ein
top-level `return` fuer legal — der Browser laedt `app.js` aber als
klassisches Script, wo es ein Syntaxfehler ist. Der Modul-Modus liegt naeher
am Browser; verifiziert, dass das echte `app.js` ihn ohne Anpassung besteht.
⚠ Kein npm, keine package.json, kein node_modules — `node --check` ist die
Laufzeit selbst. Damit entsteht NICHT die Divergenz „Pruefumgebung ist nicht
die Laufumgebung", an der dieses Projekt schon zweimal aufgelaufen ist:
Node und Chrome benutzen denselben Parser (V8).
⚠ Fehlt Node, faellt die Stufe still auf die alte Prueflogik zurueck — eine
frische Maschine soll den Hook nicht blockieren.
"""
try:
with tempfile.NamedTemporaryFile("w", suffix=".mjs", delete=False,
encoding="utf-8") as f:
f.write(p.read_text(encoding="utf-8", errors="replace"))
tmp = f.name
try:
r = subprocess.run(["node", "--check", tmp],
capture_output=True, text=True, timeout=60)
finally:
try:
pathlib.Path(tmp).unlink()
except OSError:
pass
except (FileNotFoundError, OSError, subprocess.TimeoutExpired):
return False
if r.returncode == 0:
return None
for z in (r.stderr or "").splitlines():
if "Error" in z:
return z.strip()
return "node --check meldet einen Fehler"
for p in dateien(".js"):
if "lightweight-charts" in p.name:
continue
rel = p.relative_to(WURZEL)
nd = node_pruefen(p)
if nd is False:
print(f" ⚠ node fehlt — nur Ersatzpruefung fuer {rel}")
elif nd:
befunde.append(f"JS {rel} (node)")
print(f" FEHLER {rel} {nd}")
continue # bei kaputter Syntax ist die Zeilenheuristik sinnlos
tr = js_offene_strings(p.read_text(encoding="utf-8", errors="replace"))
if tr:
for nr, z in tr:
befunde.append(f"JS {p.relative_to(WURZEL)}:{nr}")
print(f" FEHLER {p.relative_to(WURZEL)}:{nr} {z}")
befunde.append(f"JS {rel}:{nr}")
print(f" FEHLER {rel}:{nr} {z}")
else:
print(f" OK {p.relative_to(WURZEL)}")
print(f" OK {rel}" + (" (node)" if nd is None else ""))
# ── C) literales \n als TEXT ─────────────────────────────────────────────