Regelwerk, Agenten, Skills und Werkzeuge veröffentlichen

Erster Stand des öffentlichen Ausschnitts aus dem Vault. Die .gitignore
arbeitet als Positivliste: ausgeschlossen ist alles, eingeschlossen nur,
was ausdrücklich wieder aufgenommen wird. Notizen, Projekte, Finanzen,
das Sitzungsgedächtnis und settings.local.json bleiben damit außen vor.

Der Kundenname in AI/Regelwerk/seo.md ist durch eine neutrale
Bezeichnung ersetzt; die Regeln selbst sind unverändert.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
Pascal MichelandClaude Opus 5 committed 2026-09-17 22:38:15 +02:00
commit 2c9a4475fc
97 files changed
+14627

No files matched your search

@@ -0,0 +1,115 @@
"""Wiederaufbau-Test im Browser: Backend weg, Backend wieder da -- ohne Neuladen der Seite.
Koordinator-Pruefskript (Windows-Python mit Playwright), nicht fuers Repo.
Frage: Zeigt die Kopfzeile "Backend getrennt", wenn das Backend stirbt, und von selbst wieder
"Backend verbunden", wenn es zurueck ist? Herkunft: Projektvorgabe (Spec, Abschnitt Frontend).
Statustexte aus dashboard/src/components/Kopfzeile.tsx (abgeschrieben am 2026-09-17).
Was es nicht sieht: die Wartezeiten 1/2/5/10 s im Einzelnen (dafuer api.test.ts), andere Browser als Chromium.
Regressionsnachweis: --ohne-neustart laesst das Backend unten; der Lauf muss dann mit Exit 2 am Schritt
"wieder verbunden" enden.
Aufruf: python -X utf8 wiederaufbau.py [--ohne-neustart]
"""
import subprocess
import sys
import time
import urllib.request
from pathlib import Path
from playwright.sync_api import TimeoutError as PlaywrightTimeout
from playwright.sync_api import sync_playwright
PORT = 8146
BASIS = f"http://localhost:{PORT}"
HIER = Path(__file__).parent
def starte_backend() -> subprocess.Popen:
skript = open(HIER / "start_probe.sh", "rb")
return subprocess.Popen(
["wsl", "-d", "Debian", "--", "bash", "-s", str(PORT), "1.0"],
stdin=skript, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
)
def beende_backend() -> None:
subprocess.run(["wsl", "-d", "Debian", "--", "pkill", "-f", f"start_probe_backend.py {PORT}"],
stdin=subprocess.DEVNULL, capture_output=True)
def warte_auf_backend(sekunden: float) -> bool:
ende = time.time() + sekunden
while time.time() < ende:
try:
with urllib.request.urlopen(BASIS + "/api/uebersicht", timeout=1) as antwort:
if antwort.status == 200:
return True
except OSError:
time.sleep(0.5)
return False
def main() -> int:
ohne_neustart = "--ohne-neustart" in sys.argv
beende_backend()
prozess = starte_backend()
schritte: list[str] = []
try:
if not warte_auf_backend(40):
print("BEFUND: Probe-Backend kommt nicht hoch -- der Lauf misst nichts")
return 2
with sync_playwright() as p:
browser = p.chromium.launch()
seite = browser.new_page(viewport={"width": 1280, "height": 800})
fehler: list[str] = []
seite.on("pageerror", lambda e: fehler.append(str(e)))
seite.goto(BASIS + "/", wait_until="domcontentloaded")
seite.evaluate("() => { window.__marke = 'nicht neu geladen'; }")
def erwarte(text: str, sekunden: float, name: str) -> bool:
start = time.time()
try:
seite.get_by_text(text, exact=True).first.wait_for(timeout=sekunden * 1000)
except PlaywrightTimeout:
print(f"BEFUND: Schritt '{name}': '{text}' erscheint nicht binnen {sekunden} s")
return False
schritte.append(f"{name}: '{text}' nach {time.time() - start:.1f} s")
return True
if not erwarte("Backend verbunden", 20, "erste Verbindung"):
return 2
beende_backend()
prozess.wait(timeout=20)
if not erwarte("Backend getrennt", 20, "nach dem Ende des Backends"):
return 2
if not ohne_neustart:
prozess = starte_backend()
if not warte_auf_backend(40):
print("BEFUND: Probe-Backend kommt nach dem Neustart nicht hoch")
return 2
if not erwarte("Backend verbunden", 30, "wieder verbunden"):
return 2
marke = seite.evaluate("() => window.__marke")
if marke != "nicht neu geladen":
print(f"BEFUND: Die Seite wurde neu geladen (Marke {marke!r})")
return 2
if fehler:
print(f"BEFUND: Seitenfehler: {fehler[:3]}")
return 2
browser.close()
for schritt in schritte:
print("ok " + schritt)
print("Kein Befund: Wiederaufbau ohne Neuladen.")
return 0
finally:
for schritt in schritte:
pass
beende_backend()
try:
prozess.wait(timeout=10)
except subprocess.TimeoutExpired:
prozess.kill()
if __name__ == "__main__":
sys.exit(main())