- .claude/agents/planer.md - .claude/workflows/plankritik.js - .vault-tools/plan-kopie/LIESMICH.md - .vault-tools/plan-kopie/mutanten_lauf.py - .vault-tools/plan-kopie/mutanten_lauf_ENTWURF.md - .vault-tools/plan-kopie/mutanten_lauf_kopie.sh - .vault-tools/plan-kopie/mutanten_lauf_treiber.py - .vault-tools/workflow-pruefung/faelle_workflows.mjs - .vault-tools/workflow-pruefung/mutanten_workflows.py - AI/Regelwerk/codeworkflow.md - CLAUDE.md Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py. Co-Authored-By: Claude Opus 5 <[email protected]>
16 KiB
type, status, title, summary, tags, created, updated
| type | status | title | summary | tags | created | updated | ||
|---|---|---|---|---|---|---|---|---|
| resource | active | Planwerkzeuge: Plan auf eine Kopie anwenden und jede Welle dagegen vergleichen | Skripte für die Standardschleife bei Plänen mit ausgeschriebenem Code — schlanke Kopie bauen, Plan auf die Kopie anwenden, je Welle Menge und Bytes vergleichen, Aus-wird-Blöcke prüfen, Codeblöcke auf unsichtbare Zeichen absuchen, Escape-Folgen per Codepunkt setzen. Entstanden 2026-09-17 in der Trading Plattform (Teil 3b). |
|
2026-09-17 | 2026-09-27 |
Planwerkzeuge für die Kopie mit angewendetem Plan
Die Regel dazu steht in AI/Regelwerk/codeworkflow („Die Kopie mit dem angewendeten Plan bleibt stehen …"). Hier steht nur, wie man die Skripte benutzt. Alle laufen mit dem Windows-Python: PYTHONIOENCODING=utf-8 python -X utf8 <skript> ….
Ablauf
-
Kopie bauen — erst, wenn der Planer fertig gemeldet hat. Den Projektbaum ohne
.git, ohne Geheimnisdateien und ohnenode_modulesin einen Wegwerfordner kopieren. Ausschlüsse als Pfade vom Wurzelordner angeben, nicht als Ordnernamen: Ein Ausschluss von „jedem Ordner namensdata" hat am 2026-09-17 auch das Pakettrading/datagetroffen, und die Suite der Kopie brach mit Sammelfehlern ab. Nach dem Kopieren die Paketliste gegen das Original halten. Beides erledigtkopie_bauen.py <projekt> <ziel> --ohne <relpfad> …: Es nimmt Ausschlüsse nur als Pfade vom Wurzelordner, meldet einen Ausschluss ohne Gegenstück („ein Name statt eines Pfads?"), überspringt Verknüpfungen und Junctions, lässt__pycache__weg, weigert sich bei einem vorhandenen Ziel und vergleicht am Ende die Python-Pakete beider Bäume. Für die Trading Plattform:--ohne .git dashboard/node_modules dashboard/dist data artifacts config/secrets.toml docs/plans. Braucht die Kopienode_modules, eine Junction setzen (mklink /J) — und sie vor dem Löschen der Kopie mitcmd //c rmdir <pfad>wieder lösen, sonst trifftrm -rfdas echtenode_modules. Nietsc -bdurch die Junction fahren (schreibt nachnode_modules/.tmp);npx tsc -p tsconfig.app.json --noEmitnehmen. -
Plan anwenden:
plan_materialisiere.py <planordner> <kopie> task-01.md task-02.md …in Wellenreihenfolge. Erkennt die MarkenAus:/wird:, „Die ganze Datei ist neu", „vollständig ersetzt" und „Häng diesen Block ans Ende"; Dateien, die## Zieldateienals „(gelöscht)" führt, löscht es in der Kopie. Prosa-Tasks („wird: ein neuer Abschnitt, er muss sagen …") lassen sich nicht anwenden. -
Auf der Kopie fahren: Suite, Typprüfung, Mutanten. Ein Mutantenlauf gibt je Mutant die Fehlerzeile aus, nicht nur den Exitcode.
-
Vor jeder Welle und nach jeder Plankorrektur:
plan_bloecke.py vor <tasks…> --projekt <projekt>(jeder Aus-Block steht genau einmal im echten Baum) undplan_zeichen.py <planordner>(keine Zeilen- und Absatztrenner, Format- und Steuerzeichen in Codeblöcken). -
Nach jeder Welle:
welle_vergleich.py --projekt <projekt> --mat <kopie> [--prosa <rel> …] -- <taskdateien der Welle>. Prüft, ob genau die Zieldateien geändert sind und ob jede byte-gleich mit der Kopie ist. Es zeigt je Datei nur die erste Abweichung — danachdiffauf die ganze Datei. Eigene Plankorrekturen im Baum meldet es zu Recht als „außerhalb der Zieldateien". -
Escape-Folgen setzen:
plan_escape.py <datei> <zeile> <codepunkt-hex> …ersetzt echte Zeichen in einer Zeile durch ihre Escape-Folge, ohne dass eine Schreibschicht mitredet. -
Rot-Nachweis je Task (seit 2026-09-18):
rot_nachweis.py <basis-kopie> <planordner> <arbeitsordner> <spec.json> [--fixturen <ordner>] [--node-modules <pfad>] [--conftest-als-test] [--venv <wsl-pfad>] [--frontend <ordner>] [--projektname <ordnername>]. Für ein anderes Projekt als die Trading Plattform braucht es die drei letzten Schalter (seit 2026-09-24): Ihre Vorgaben sind die der Trading Plattform (~/venvs/trading,dashboard,trading-plattform). Jedes andere Projekt nennt seine Werte, für den Nexhorizons Hub--venv '~/venvs/hub' --frontend frontend --projektname 'active - Nexhorizons Hub', das Venv in einfachen Anführungszeichen, sonst macht die Git-Bash aus~einen Windows-Pfad. Das Skript druckt die benutzten Werte in der ersten Zeile. Die Vorgabetrading-plattformpasst nur auf Pläne mit Arbeitsbaum-Pfaden; ältere Trading-Pläne mit absoluten Pfaden unteractive - Trading Plattformbrauchen--projektname 'active - Trading Plattform', sonst endet der Lauf mit einemValueError. Weiter fest verdrahtet bleiben die DistributionDebian, die Ordnertests/undtests/fixtures/, die Endungen.test.ts/.test.tsxundnpx.cmd vitest. Vorbedingung: Das Projekt ist im Venv nicht editierbar installiert (pip install -e); sonst löst der Finder von setuptools ein fehlendes Untermodul gegen das echte Projekt auf, und ein Test ohne Umsetzung läuft grün.tests/conftest.pygilt dabei als Produktivseite und wird zurückgesetzt; nur wenn die neue Fixture eines Tasks dort liegt, lässt--conftest-als-testsie stehen (Beleg unten, 2026-09-22).plan_materialisiere.pywendet eine Taskdatei immer ganz an; „erst der Test, dann die Umsetzung" lässt sich damit nicht beobachten. Das Skript stellt den Zustand dazwischen auf Wegwerfkopien her — Basis plus Voraussetzungstasks plus der Task, danach die produktiven Zieldateien zurück auf den Stand vor dem Task — und fährt die Testdateien des Tasks (pytest in WSL, vitest unter Windows über eine Junction, die es vor dem Löschen löst). Es meldet je TaskROTmit der ersten Fehlerzeile oderGRUEN; ein Test, der ohne Umsetzung grün ist, misst sie nicht. Die Basis-Kopie zieht man vor der ersten Welle.spec.jsonnennt je Task die Voraussetzungstasks. Erster Einsatz am 2026-09-18 an vier Plänen der Trading Plattform: 35 Tasks, alle rot an der gemeinten Stelle, keiner grün ohne Umsetzung. Die Executer brauchen den Tanz mit dem Beiseitelegen der Produktivdatei dann nicht mehr; ihr Auftrag sagt das ausdrücklich. -
Mutanten fahren (seit 2026-09-27):
mutanten_lauf.py --wurzel <wegwerfkopie> --mutanten <planordner>/mutanten.toml [--nur ID,…] [--nur-muster] [--bericht <datei.json>] [--zeitlimit <s>], in WSL mit einem Python ab 3.11. Die Mutanten stehen nicht mehr als Prosa im Plan, sondern inmutanten.tomlim Planordner. Das Format, die Status und die Abdichtung stehen inmutanten_lauf_ENTWURF.md. Das Skript verweigert eine Wurzel mit.gitund jeden Pfad ausohne. Es fährt zuerst die Grundlinie, dann je Mutant nur die genannten Tests, setzt die Datei zurück und prüft das per SHA-256. Je Test gibt es die Fehlermeldung mit aus; ob ein Test an der gemeinten Stelle fällt, liest man dort.--nur-musterprüft nur, ob jedes Muster genau einmal dasteht, ohne pytest. Die Kopie legt man in WSL unter/tmpan (cp -a, danach__pycache__löschen). Auf/mnt/dläuft es auch, nur langsamer. Aus der Git-Bash ein Skript nie mitwsl … bash /mnt/d/…starten: Die Git-Bash macht aus dem Pfad einen Windows-Pfad. Aus der PowerShell starten oderMSYS_NO_PATHCONV=1davorsetzen. Die Plankritik fährt die Mutanten selbst (seit 2026-09-27): Liegtmutanten.tomlim Planordner, startetplankritik.jsin der Vorbereitungmutanten_lauf_kopie.sh. Das Skript kopiert die Kopie mit angewendetem Plan nach/tmpin WSL, fährt dort den Läufer und gibt die Ausgabe an die Linsearithmetik. Der Argmutantenwähltvoll(Vorgabe),musteroderaus. Der ganze Lauf hat 540 s, weil das Bash-Werkzeug eines Hilfsagenten nach zehn Minuten endet; eine überschrittene Grenze meldet die ZeileZEITGRENZE. B1 mit 74 Mutanten brauchte 147 s. Pfade übergibt man mit Vorwärtsschrägstrichen:wsl -d Debian -- …reicht die Befehlszeile an die Linux-Shell, und die verschluckt Backslashes.
Was belegt ist
Seit 2026-09-27 gibt es mutanten_lauf.py und mutanten_lauf_treiber.py (Punkt 3 der Arbeitsweise vom 2026-09-26). Der Treiber fährt die 34 Angriffsfälle aus dem Entwurf auf einem kleinen Projekt unter /tmp und prüft nach jedem Fall, dass das Projekt byte-gleich zurückgesetzt ist. Am selben Tag hat der Koordinator neun Fehler in eine Kopie des Läufers eingebaut, und der Treiber hat jeden an seinem Fall gefangen:
- „passed“ zählt als rot
- kein Zurücksetzen
- keine
.git-Prüfung ausgleichwirderlaubt- HOME nicht abgedichtet
- Sammelfehler nicht rot
- Grundlinie lässt Übersprungenes durch
- Zeitlimit zählt als OK
- eine Teilzeile zählt als Treffer
Das Skript dazu liegt außerhalb des Vaults und ist nicht Teil der Werkzeuge. Erster echter Einsatz war am selben Tag B1 der Trading Plattform: 74 von 74 Mutanten getötet, alle Fehlschläge Zusicherungen, die Kopie danach unverändert. Eine Lehre aus der Übertragung: Nennt ein Plan einen parametrisierten Test ohne Fall, gehören nur die Fälle in rot_bei, die der Mutant umkippt. Bei D1 wären drei von fünf Fällen unter return False grün geblieben.
Seit 2026-09-18 nimmt welle_vergleich.py unter ## Zieldateien auch Pfade relativ zum Projekt (ohne Laufwerk und ohne Wurzel), weil Pläne für einen Git-Worktree keine absoluten Pfade nennen; ein .. darin ist ein Befund wie ein fremder absoluter Pfad. Jede Zeile braucht weiter die Klammer hinter dem Pfad ((neu), (geändert), (gelöscht)). plan_materialisiere.py erkennt eine Zieldatei ohne Schrägstrich nur mit den Endungen py, ts, tsx, toml, md, css und json — für compose.yaml in der Projektwurzel schreibt die Überschrift ./compose.yaml. Der Treiber fährt dazu drei weitere Fälle (relative Grundlinie, relative Abweichung, .. nach außen), zusammen 17.
Seit 2026-09-24 hat rot_nachweis.py die Schalter --venv, --frontend und --projektname; vorher waren ~/venvs/trading, dashboard und trading-plattform/ fest verdrahtet. Ein Hub-Lauf im Trading-Venv wäre für die Tasks mit argon2-cffi und pyotp rot aus einem fehlenden Paket gewesen, nicht aus der fehlenden Umsetzung. Fehlt das Venv in WSL, steht beim Task jetzt VORAUSSETZUNG FEHLT statt ROT, und die Schlusszeile zählt diese Läufe getrennt. Belegt am selben Tag: Der Vorgabe-Befehl ist byte-gleich mit der alten Fassung, falsche Schalterwerte enden mit Exit 3, und der erste echte Lauf über 38 Tasks des Hub meldete keinen grün ohne Umsetzung. Im selben Lauf zeigte sich eine zweite Lücke: Beim Zurücksetzen blieben Ordner stehen, die erst der Task angelegt hatte. Ein leeres hub/auth/ liest Python als Namespace-Paket, und die Fehlerzeile nannte hub.auth.passwort statt hub.auth. Jetzt gehen solche Ordner mit, sobald sie leer sind; derselbe Lauf für die Tasks 7, 9 und 11 zeigt danach genau die Zeile aus dem Plan. Die unabhängige Prüfung desselben Tages fand eine dritte Lücke: Ein vergessenes --venv fiel still auf das Trading-Venv zurück, und Task 7 stand als ROT … No module named 'argon2' da. Seitdem wird eine erste Fehlerzeile, die ein Modul außerhalb des Projekts und außerhalb der Zieldateien vermisst, als VORAUSSETZUNG FEHLT gemeldet. Das trifft auch den Ende-zu-Ende-Task des Hub, dessen Tests playwright brauchen. Mit den Vorgaben lieferte das Skript für die sieben Tasks des Trading-Pakets K vor und nach allen Änderungen dieselben Zeilen. Zwei weitere Lücken desselben Tages, beide ein ROT, das nichts misst: Ein Arbeitsordner mit Windows-Kurznamen (C:/Users/PASCAL~1/…) ließ vitest dort starten, die Dateien aber über den langen Namen auflösen, und jede Oberflächen-Testdatei endete als Cannot find module '/src/…'. Das Skript löst den Arbeitsordner jetzt auf den langen Namen auf; danach zeigte Trading-Task 395 wieder 9 failed | 52 passed statt no tests, und die Hub-Tasks 24, 25, 29 und 37 die Zeile aus dem Plan (Error: Failed to resolve import "./kontrast" …). Die erste Error:-Zeile steht seitdem mit in der Ergebniszeile, weil die FAIL-Zeile allein den Grund nicht zeigt. Ein Test, der über Vite eine Datei aus node_modules lädt (?raw), scheitert hinter der Junction mit Denied ID, weil Vite nichts außerhalb seines Wurzelordners ausliefert; das Skript meldet das als VORAUSSETZUNG FEHLT. Für solche Tasks läuft der Nachweis in einer Kopie mit echtem node_modules (242 MB, gut 20 Sekunden).
Seit 2026-09-22 behandelt rot_nachweis.py tests/conftest.py als Produktivseite. Vorher zählte alles unter tests/ als Testdatei — lag die Korrektur eines Tasks selbst in conftest.py (Trading Plattform, Task 369: die Ersatzfunktionen der Netzsperre trugen eine andere Vorgabe als die Originale), wendete der Lauf „ohne Umsetzung" sie mit an und meldete GRUEN pytest: 147 passed — der eine Zustand, in dem der Nachweis nichts misst, sah aus wie ein sauberer Befund. Gemessen an derselben Basis-Kopie und demselben Task, altes gegen neues Skript: GRUEN 147 passed → ROT 3 failed, 144 passed mit der gemeinten Fehlerzeile (assert ('', '') == ('probe-thema', '')). Die Gegenprobe für den anderen Fall — eine neue Fixture des Tasks liegt in conftest.py (Task 368) — mit --conftest-als-test ROT 1 failed, 11 passed wie vor der Änderung, ohne Schalter ROT 6 failed, 6 passed mit AttributeError: module 'conftest' has no attribute '_gesperrte_pfade' als erster Fehlerzeile: rot aus dem falschen Grund, aber sichtbar, und das Skript sagt je Task, wie es conftest.py behandelt hat. Was es weiter nicht sieht: ob ein Task beides in conftest.py legt, Fixture und Korrektur — dann ist keine der beiden Einstellungen richtig, und der Nachweis läuft von Hand.
Seit 2026-09-20 quotet rot_nachweis.py den Arbeitsordner für den WSL-Aufruf (shlex.quote). Ein Temp-Pfad mit Leerzeichen — der Benutzername steckt im Scratchpad-Pfad — ließ vorher das cd scheitern: Alle sieben Tasks eines Plans der Trading Plattform standen als „ROT pytest: keine Summenzeile" da, ohne dass ein einziger Test lief. Nach der Korrektur derselbe Lauf mit echten Summenzeilen (3 failed, 17 passed, 1 error, …). Wer „keine Summenzeile" bei jedem Task sieht, hat kein Rot gemessen, sondern ein kaputtes Werkzeug.
welle_vergleich_treiber.py fährt 14 Angriffsfälle gegen welle_vergleich.py (Grundlinie zuerst; fremde Datei, unveränderte Zieldatei, Abweichung in erster und letzter Zeile und in der letzten Zieldatei, CRLF, Datei fehlt in der Kopie, Task ohne Zieldateien, Kopie fehlt, Löschung nicht ausgeführt, Prosa-Datei unverändert, Zieldatei außerhalb des Projekts, Datei länger als der Plan). plan_zeichen.py hat am 2026-09-17 an einem echten Fund rot gezeigt (U+2028 im Plan). plan_materialisiere.py reproduziert Task 108 des Teil-3b-Plans aus dem Stand vor den Wellen byte-genau. kopie_bauen.py ist am 2026-09-17 an drei kaputten Eingaben rot gesehen: Ziel existiert schon (Exit 2, nichts kopiert), Ausschluss node_modules ohne Gegenstück im Wurzelordner (Befund), und ein aus der Kopie entferntes Paket trading/data (die Paketprüfung nennt es; nach dem Zurücklegen leer). Einen Treiber dazu gibt es noch nicht — die drei Fälle sind von Hand gefahren.
Offen seit 2026-09-23: plan_materialisiere.py stirbt mit FileNotFoundError, wenn die Zieldatei eines „Häng diesen Block ans Ende"-Blocks in der Kopie fehlt (Trading Plattform, Task 384 hängte einen Nachtrag an die Planübersicht an; die Kopie war ohne docs/plans gebaut). Ein Absturz mitten im Task lässt die davor angewendeten Blöcke halb drin. Bis das ein Befund ist: Kopien für Pläne, die Plandateien selbst anfassen, mit dem Planordner bauen — und eine Kopie nie nach dem Start der Welle ziehen (sie trägt dann den halben Stand des Arbeitsbaums).
Was die Skripte nicht sehen
Dateien, die .gitignore ausblendet; ob die Kopie selbst sauber ist (eine verschmutzte Kopie erzeugt Fehlalarm, kein falsches Grün); ob die Kopie älter ist als der Plan — wird eine Taskdatei nach dem Anwenden noch überarbeitet, meldet welle_vergleich.py eine Abweichung, die keine ist (2026-09-17, Teil 4c: der Planer lief noch, als die Kopie entstand). Dann entscheidet plan_bloecke.py nach gegen den echten Baum, und die betroffenen Dateien der Kopie werden aus git show HEAD:<pfad> neu aufgebaut und der Task erneut angewendet; verwechselbare sichtbare Zeichen (kyrillisches „с"). Sie sind ein Fangnetz, kein Nachweis — den liefert der Lauf mit echten Daten.
Das ältere .vault-tools/plan-diff/plan_diff.py vergleicht Ganzdatei-Blöcke einer früheren Plankonvention und bleibt dafür in Gebrauch.