- .claude/agents/planer.md - .claude/skills/plan-executer-pruefung/SKILL.md - .claude/workflows/plankritik.js - .claude/workflows/planung.js - .claude/workflows/pruefung.js - .claude/workflows/verbrauch.js - .claude/workflows/welle-mit-pruefung.js - .vault-tools/plan-kopie/LIESMICH.md - .vault-tools/plan-kopie/plan_zeichen.py - .vault-tools/plan-kopie/rot_nachweis.py - .vault-tools/trading-plattform-pruefung/LIESMICH.md - .vault-tools/trading-plattform-pruefung/abendkontrolle.py - … und 34 weitere Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py. Co-Authored-By: Claude Opus 5 <[email protected]>
99 lines
6.8 KiB
Python
99 lines
6.8 KiB
Python
"""Mutanten der Abendkontrolle und des Rueckwegs: jeder muss seinen Angriffstreiber rot machen.
|
|
|
|
Koordinator-Werkzeug, nicht fuers Repo. Jeder Mutant laeuft auf einer Wegwerfkopie dieses Verzeichnisses.
|
|
In WSL (Venv) die Mutanten von abendkontrolle_wsl.py, unter Windows die von abendkontrolle.py und
|
|
rueckweg_aapl.py. Aufruf: python abendkontrolle_mutanten.py Exit 0, wenn keiner ueberlebt.
|
|
Ein Mutant, der das Verhalten nicht aendert, ist keine Luecke (AI/Regelwerk/pruefwerkzeuge.md, Abschnitt 8).
|
|
"""
|
|
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
HIER = Path(__file__).resolve().parent
|
|
|
|
WSL_MUTANTEN = [
|
|
("Exit-Vergleich verkehrt", "abendkontrolle_wsl.py", 'if satz["exit"] != "0":', 'if satz["exit"] == "9":'),
|
|
("Handelstag immer wahr", "abendkontrolle_wsl.py", 'return any(eintrag["date"] == tag for eintrag in liste)', "return True"),
|
|
("gesperrt nicht geprueft", "abendkontrolle_wsl.py", 'if zeile[0] == "gesperrt":', 'if zeile[0] == "nie":'),
|
|
("unbekannter Zustand still", "abendkontrolle_wsl.py", "elif zeile[0] not in KILLSWITCH_ZUSTAENDE:", "elif False:"),
|
|
("Broker-Schwelle", "abendkontrolle_wsl.py", "if offen[-1] != 0:", "if offen[-1] > 5:"),
|
|
("Probe zaehlt mit", "abendkontrolle_wsl.py", 'glob(f"{tag}T*-paper.jsonl")', 'glob(f"{tag}T*.jsonl")'),
|
|
("Maske aus", "abendkontrolle_wsl.py", " text = muster.sub(ersatz, text)", " pass"),
|
|
("nie-aktiv aus", "abendkontrolle_wsl.py", 'if satz.get("killswitch") == "aktiv":', "if True:"),
|
|
("Bericht nicht geprueft", "abendkontrolle_wsl.py", "if not bericht.is_file():\n k.befund", "if False:\n k.befund"),
|
|
("Failed-Zeile aus", "abendkontrolle_wsl.py", 'if "Failed with result" in text:', 'if "nie da" in text:'),
|
|
("nur letzter Lauf im Journal", "abendkontrolle_wsl.py", "for nummer, satz in enumerate(enden, start=1):",
|
|
"for nummer, satz in list(enumerate(enden, start=1))[-1:]:"),
|
|
("Melder-Rueckgabe verworfen", "abendkontrolle_wsl.py",
|
|
'return "gesendet" if fehler is None else f"nicht gesendet: {fehler}"', 'return "gesendet"'),
|
|
("Ende je Protokoll nicht bewertet", "abendkontrolle_wsl.py",
|
|
" if ende.get(\"grund\") != \"boersenschluss\":\n k.befund(f\"{lauf['datei']}",
|
|
" if False:\n k.befund(f\"{lauf['datei']}"),
|
|
("wartezeit im Journal mitgezaehlt", "abendkontrolle_wsl.py",
|
|
'enden = [satz for satz in alle if satz["grund"] != "wartezeit"]', "enden = alle"),
|
|
("Lauf nach Schluss als Handelslauf", "abendkontrolle_wsl.py",
|
|
'return bool(lauf["ende"]) and lauf["ende"].get("grund") == "wartezeit" and lauf["takte"] == 0', "return False"),
|
|
("Fragen nicht voneinander getrennt", "abendkontrolle_wsl.py",
|
|
" except Exception as ausnahme:\n self.befund(f\"{name} nicht geprueft",
|
|
" except ZeroDivisionError as ausnahme:\n self.befund(f\"{name} nicht geprueft"),
|
|
]
|
|
WIN_MUTANTEN = [
|
|
("keine Ergebnisdatei", "abendkontrolle.py", '(ablage / f"{tag}.json").write_text(', '(ablage / f"{tag}.nix").write_text('),
|
|
("Wochenende mit", "abendkontrolle.py", "if tag < ERSTER_TAG or tag.weekday() >= 5:", "if tag < ERSTER_TAG:"),
|
|
("heute vor 22:30", "abendkontrolle.py", "if tag == jetzt.date() and jetzt.time() < FRUEHESTENS:", "if False:"),
|
|
("Befund ohne Markierung", "abendkontrolle.py", "**{len(befunde)} Befund(e)** #needs-review", "{len(befunde)} Befund(e)"),
|
|
("CRLF vergessen", "abendkontrolle.py", 'cr = "\\r" if any(z.endswith("\\r") for z in zeilen) else ""', 'cr = ""'),
|
|
("Formpruefung aus", "abendkontrolle.py",
|
|
'if not isinstance(ergebnis, dict) or not isinstance(ergebnis.get("befunde"), list):', "if False:"),
|
|
("Ueberschrift nur exakt", "abendkontrolle.py",
|
|
"if z == UEBERSCHRIFT or z.startswith(UEBERSCHRIFT + \" \")), None)", "if z == UEBERSCHRIFT), None)"),
|
|
("Abbruch gilt als erledigt", "abendkontrolle.py", 'if ergebnis.get("exit") != 2:', "if True:"),
|
|
("nicht atomar", "abendkontrolle.py", " os.replace(neu, notiz)", " notiz.write_bytes(text.encode(\"utf-8\"))"),
|
|
("Zeit egal", "rueckweg_aapl.py", "if jetzt < FRUEHESTENS:", "if False:"),
|
|
("Runner egal", "rueckweg_aapl.py", " if runner_aktiv(runner_vorgabe):", " if False and runner_aktiv(runner_vorgabe):"),
|
|
("unlesbar gilt als steht", "rueckweg_aapl.py",
|
|
'raise RuntimeError(f"Zustand des Runners nicht lesbar: {zustand!r}")', "return False"),
|
|
("schmutziger Ordner egal", "rueckweg_aapl.py", " else:\n if geaendert:", " else:\n if False:"),
|
|
("folge egal", "rueckweg_aapl.py", 'if MEHRERE not in ziel.read_text(encoding="utf-8"):', "if False:"),
|
|
("Ergebnisdatei egal", "rueckweg_aapl.py", 'if (ablage / "rueckweg.json").exists():', "if False:"),
|
|
("kein Commit", "rueckweg_aapl.py", '("add", ZIEL.as_posix()), ("commit", "-m", NACHRICHT)', '("add", ZIEL.as_posix()),'),
|
|
("halb getauscht gilt als fertig", "rueckweg_aapl.py",
|
|
" if not geaendert:\n return \"config/paper.toml ist schon",
|
|
" if True:\n return \"config/paper.toml ist schon"),
|
|
("Schluesselvergleich aus", "rueckweg_aapl.py", " if fehlend:", " if False:"),
|
|
("Zweig egal", "rueckweg_aapl.py", " if zweig != ZWEIG:", " if False:"),
|
|
("Wertevergleich aus", "rueckweg_aapl.py", " elif neu[name] != alt[name]:", " elif False:"),
|
|
("Gegenrichtung aus", "rueckweg_aapl.py", " elif name not in alt:", " elif False:"),
|
|
]
|
|
TREIBER = {
|
|
"abendkontrolle_wsl.py": "abendkontrolle_angriffe.py",
|
|
"abendkontrolle.py": "abendkontrolle_angriffe.py",
|
|
"rueckweg_aapl.py": "rueckweg_aapl_angriffe.py",
|
|
}
|
|
|
|
mutanten = WIN_MUTANTEN if sys.platform == "win32" else WSL_MUTANTEN
|
|
ueberlebt = []
|
|
for name, datei, alt, neu in mutanten:
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
ziel = Path(tmp) / "pruefung"
|
|
shutil.copytree(HIER, ziel, ignore=shutil.ignore_patterns("__pycache__"))
|
|
pfad = ziel / datei
|
|
text = pfad.read_text(encoding="utf-8")
|
|
if text.count(alt) != 1:
|
|
print(f"ANKER {text.count(alt)}-mal: {name}")
|
|
ueberlebt.append(name)
|
|
continue
|
|
pfad.write_text(text.replace(alt, neu), encoding="utf-8", newline="\n")
|
|
lauf = subprocess.run([sys.executable, str(ziel / TREIBER[datei])], capture_output=True, text=True,
|
|
timeout=1800, encoding="utf-8", errors="replace", cwd=tmp)
|
|
faelle = [z for z in lauf.stdout.splitlines() if z.startswith("FEHL")]
|
|
rot = lauf.returncode != 0
|
|
print(f"{'ROT (gefangen)' if rot else 'GRUEN (UEBERLEBT)'} {name}: {[f[:110] for f in faelle[:2]]}")
|
|
if not rot:
|
|
ueberlebt.append(name)
|
|
print(f"ERGEBNIS: {len(ueberlebt)} ueberlebt von {len(mutanten)} {ueberlebt}")
|
|
sys.exit(1 if ueberlebt else 0)
|