Automatischer Push: 19 Datei(en) geändert

- .vault-tools/plan-kopie/LIESMICH.md
- .vault-tools/plan-kopie/rot_nachweis.py
- .vault-tools/plan-kopie/welle_vergleich.py
- .vault-tools/plan-kopie/welle_vergleich_treiber.py
- .vault-tools/trading-plattform-pruefung/LIESMICH.md
- .vault-tools/trading-plattform-pruefung/angriffe.py
- .vault-tools/trading-plattform-pruefung/browserlauf.py
- .vault-tools/trading-plattform-pruefung/browserlauf_zugang.py
- .vault-tools/trading-plattform-pruefung/c_eigenlauf.py
- .vault-tools/trading-plattform-pruefung/d_eigenlauf.py
- .vault-tools/trading-plattform-pruefung/handelstag_auswertung.py
- .vault-tools/trading-plattform-pruefung/ntfy_probe_server.py
- … und 7 weitere

Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
Pascal MichelandClaude Opus 5 committed 2026-09-19 04:00:01 +02:00
1 parent 371a1f5d2a
commit 395642c480
19 files changed
+1636 -32

No files matched your search

@@ -1,21 +1,41 @@
"""Browser-Lauf zu Teil 3b mit Playwright (Windows-Python), gegen ein laufendes Backend.
Koordinator-Pruefskript, nicht fuers Repo. Aufruf:
python -X utf8 browserlauf.py <basis-url> <ausgabeordner>
python -X utf8 browserlauf.py <basis-url> <ausgabeordner> [<zugang.json>]
Mit zugang.json (aus der Ablage von start_probe_zugang.py) meldet sich der Lauf einmal an und nutzt die
Sitzung fuer alle Breiten (seit 2026-09-18, weil das Dashboard Anmeldung verlangt); dazu kommt je Breite die
Agenten-Ansicht mit der Walk-Forward-Zeichnung, wenn das Register die Kampagne aus HISTORIE_MARKE traegt.
Prueft je Breite: kein waagerechter Scroll, keine Konsolenfehler, Ansicht "Laeufe" zeigt Zeilen,
Ansicht "Markt" zeichnet (Canvas nicht leer). Schreibt Screenshots und eine ergebnis.json.
Was es nicht sieht: ob die Zahlen stimmen (dafuer pruef_teil3b.py) und wie es aussieht (dafuer
die Screenshots, die der Koordinator selbst ansieht).
"""
import base64
import hashlib
import hmac
import json
import re
import struct
import sys
import time
from pathlib import Path
from playwright.sync_api import TimeoutError as PlaywrightTimeout
from playwright.sync_api import sync_playwright
BREITEN = [375, 768, 1024, 1440]
# aria-label aus Agenten.tsx: `Historie ${agent}/${version}`; die Kampagne mit Verhaltensblock.
HISTORIE_MARKE = "Historie aapl-minute-ppo/v20260914-132555"
def totp(geheimnis: str, zeit_s: float) -> str:
"""Eigener Nachbau nach RFC 6238, wie in angriffe.py."""
schluessel = base64.b32decode(geheimnis.upper() + "=" * (-len(geheimnis) % 8))
mac = hmac.new(schluessel, struct.pack(">Q", int(zeit_s // 30)), hashlib.sha1).digest()
versatz = mac[-1] & 0x0F
zahl = struct.unpack(">I", mac[versatz : versatz + 4])[0] & 0x7FFFFFFF
return f"{zahl % 1_000_000:06d}"
# Je ein Minuten- und ein Tagesdatensatz; die Namen stehen so im Katalog (gemessen 2026-09-17).
MARKT_DATENSAETZE = [
@@ -56,10 +76,28 @@ def main() -> int:
ziel.mkdir(parents=True, exist_ok=True)
ergebnis: dict = {"basis": basis, "breiten": {}, "befunde": []}
zugang = json.loads(Path(sys.argv[3]).read_text(encoding="utf-8")) if len(sys.argv) > 3 else None
with sync_playwright() as spiel:
browser = spiel.chromium.launch()
# Ein Kontext fuer alle Breiten: Ein TOTP-Code gilt einmal, vier Anmeldungen in einer Minute gingen
# also nicht. Die Sitzung haengt am Cookie des Kontexts.
kontext = browser.new_context()
if zugang is not None:
seite = kontext.new_page()
seite.goto(basis + "/", wait_until="networkidle")
seite.get_by_label("Benutzer").fill(zugang["benutzer"])
seite.get_by_label("Passwort").fill(zugang["passwort"])
seite.get_by_label("Code").fill(totp(zugang["geheimnis"], time.time()))
seite.get_by_role("button", name="Anmelden").click()
try:
seite.get_by_role("button", name="Abmelden").wait_for(timeout=10000)
except PlaywrightTimeout:
ergebnis["befunde"].append("Anmeldung: die App erscheint nicht")
seite.close()
for breite in BREITEN:
seite = browser.new_page(viewport={"width": breite, "height": 900})
seite = kontext.new_page()
seite.set_viewport_size({"width": breite, "height": 900})
meldungen: list[str] = []
seite.on("console", lambda m, liste=meldungen: liste.append(f"{m.type}: {m.text}") if m.type in ("error", "warning") else None)
seite.on("pageerror", lambda f, liste=meldungen: liste.append(f"pageerror: {f}"))
@@ -112,6 +150,20 @@ def main() -> int:
ergebnis["befunde"].append(f"{breite}px Laeufe/{kurz}: die Einzelansicht zeigt keine eigene Tabelle")
messe(f"laeufe-{kurz}")
# Seit 2026-09-18: die Agenten-Ansicht mit der Walk-Forward-Zeichnung (verkettete Episoden).
# Nur mit einem Register, das Versionen traegt; sonst bleibt es beim Bildschirmfoto der leeren Ansicht.
seite.get_by_role("button", name="Agenten", exact=True).click()
seite.wait_for_timeout(1500)
historie = seite.get_by_role("button", name=HISTORIE_MARKE, exact=True)
if historie.count() == 1:
historie.click()
try:
seite.get_by_role("img", name="Kapitalkurven Fenster 1", exact=True).wait_for(timeout=15000)
eintrag["walkforward_zeichnungen"] = seite.get_by_role("img", name=re.compile("^Kapitalkurven Fenster")).count()
except PlaywrightTimeout:
ergebnis["befunde"].append(f"{breite}px Agenten: keine Walk-Forward-Zeichnung")
messe("agenten")
eintrag["konsole"] = meldungen
if any(m.startswith(("error", "pageerror")) for m in meldungen):
ergebnis["befunde"].append(f"{breite}px: Konsolenfehler {meldungen[:3]}")