Automatischer Push: 6 Datei(en) geändert
- .vault-tools/plan-kopie/LIESMICH.md - .vault-tools/plan-kopie/rot_nachweis.py - .vault-tools/trading-plattform-pruefung/LIESMICH.md - .vault-tools/trading-plattform-pruefung/browser_r.py - .vault-tools/trading-plattform-pruefung/start_probe_w.py - .vault-tools/trading-plattform-pruefung/start_probe_zugang.py Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
1 parent
94116e5a32
commit
b7cc7433a9
2 files changed
+32
-5
No files matched your search
@@ -21,16 +21,20 @@ Die Regel dazu steht in [[AI/Regelwerk/codeworkflow|codeworkflow.md]] („Die Ko
|
|||||||
5. **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 — danach `diff` auf die ganze Datei. Eigene Plankorrekturen im Baum meldet es zu Recht als „außerhalb der Zieldateien".
|
5. **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 — danach `diff` auf die ganze Datei. Eigene Plankorrekturen im Baum meldet es zu Recht als „außerhalb der Zieldateien".
|
||||||
6. **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.
|
6. **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.
|
||||||
|
|
||||||
7. **Rot-Nachweis je Task (seit 2026-09-18):** `rot_nachweis.py <basis-kopie> <planordner> <arbeitsordner> <spec.json> [--fixturen <ordner>] [--node-modules <pfad>]`. `plan_materialisiere.py` wendet 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 Task `ROT` mit der ersten Fehlerzeile oder `GRUEN`; ein Test, der ohne Umsetzung grün ist, misst sie nicht. Die Basis-Kopie zieht man **vor** der ersten Welle. `spec.json` nennt 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.
|
7. **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]`. `tests/conftest.py` gilt dabei als Produktivseite und wird zurückgesetzt; nur wenn die neue Fixture eines Tasks dort liegt, lässt `--conftest-als-test` sie stehen (Beleg unten, 2026-09-22). `plan_materialisiere.py` wendet 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 Task `ROT` mit der ersten Fehlerzeile oder `GRUEN`; ein Test, der ohne Umsetzung grün ist, misst sie nicht. Die Basis-Kopie zieht man **vor** der ersten Welle. `spec.json` nennt 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.
|
||||||
|
|
||||||
## Was belegt ist
|
## Was belegt ist
|
||||||
|
|
||||||
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-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-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.
|
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.
|
`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
|
## 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.
|
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.
|
||||||
|
|||||||
@@ -12,6 +12,14 @@ Dann laufen die Testdateien des Tasks. Es tut etwas und berichtet; das Urteil fa
|
|||||||
Geltungsbereich und Luecken:
|
Geltungsbereich und Luecken:
|
||||||
- Testdateien sind Zieldateien unter tests/ sowie *.test.ts und *.test.tsx; alles unter tests/fixtures/
|
- Testdateien sind Zieldateien unter tests/ sowie *.test.ts und *.test.tsx; alles unter tests/fixtures/
|
||||||
gilt als Testseite und bleibt stehen. Alles andere ist produktiv.
|
gilt als Testseite und bleibt stehen. Alles andere ist produktiv.
|
||||||
|
- tests/conftest.py gilt als PRODUKTIVSEITE und wird zurueckgesetzt (Projektvorgabe seit 2026-09-22):
|
||||||
|
Liegt die Korrektur eines Tasks selbst in conftest.py (Trading Plattform, Task 369: die Ersatzfunktionen
|
||||||
|
der Netzsperre), wendete das Skript sie im Lauf "ohne Umsetzung" mit an und meldete GRUEN -- der eine
|
||||||
|
Zustand, in dem der Nachweis nichts misst, sah aus wie ein sauberer Befund. Liegt dagegen eine neue
|
||||||
|
Fixture des Tasks in conftest.py (Task 368), fehlt sie jetzt im Lauf und die neuen Tests enden als
|
||||||
|
Sammelfehler -- das ist ROT mit "fixture ... not found" in der ersten Fehlerzeile, also sichtbar.
|
||||||
|
Wer diesen Fall hat, ruft mit --conftest-als-test auf; dann gilt conftest.py wie frueher als Testdatei.
|
||||||
|
Das Skript sagt je Task, wie es conftest.py behandelt hat.
|
||||||
- Python-Tests laufen in WSL (Debian, ~/venvs/trading), Oberflaechentests unter Windows mit npx vitest;
|
- Python-Tests laufen in WSL (Debian, ~/venvs/trading), Oberflaechentests unter Windows mit npx vitest;
|
||||||
dafuer setzt das Skript eine Junction auf das node_modules des Projekts und loest sie vor dem Loeschen.
|
dafuer setzt das Skript eine Junction auf das node_modules des Projekts und loest sie vor dem Loeschen.
|
||||||
- Erzeugte Fixtures (der Plan laesst sie mit altem Code erzeugen) holt --fixturen aus einem Ordner nach,
|
- Erzeugte Fixtures (der Plan laesst sie mit altem Code erzeugen) holt --fixturen aus einem Ordner nach,
|
||||||
@@ -20,8 +28,9 @@ Geltungsbereich und Luecken:
|
|||||||
- Die Basis ist eine Kopie, die der Aufrufer VOR der ersten Welle gezogen hat; das Skript fasst das
|
- Die Basis ist eine Kopie, die der Aufrufer VOR der ersten Welle gezogen hat; das Skript fasst das
|
||||||
Projekt selbst nie an.
|
Projekt selbst nie an.
|
||||||
|
|
||||||
Aufruf: python rot_nachweis.py <basis-kopie> <planordner> <arbeitsordner> <spec.json> [--fixturen <ordner>] [--node-modules <pfad>]
|
Aufruf: python rot_nachweis.py <basis-kopie> <planordner> <arbeitsordner> <spec.json> [--fixturen <ordner>] [--node-modules <pfad>] [--conftest-als-test]
|
||||||
--node-modules nennt das node_modules des Projekts, wenn die Basis-Kopie keines traegt.
|
--node-modules nennt das node_modules des Projekts, wenn die Basis-Kopie keines traegt.
|
||||||
|
--conftest-als-test laesst tests/conftest.py als Testdatei stehen (nur, wenn die neue Fixture des Tasks dort liegt).
|
||||||
spec.json: [{"task": "task-141-....md", "vor": ["task-...md", ...]}, ...]
|
spec.json: [{"task": "task-141-....md", "vor": ["task-...md", ...]}, ...]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -37,6 +46,7 @@ from pathlib import Path
|
|||||||
HIER = Path(__file__).resolve().parent
|
HIER = Path(__file__).resolve().parent
|
||||||
ZIEL = re.compile(r"^- `(.+?)`")
|
ZIEL = re.compile(r"^- `(.+?)`")
|
||||||
PROJEKTNAME = "trading-plattform/"
|
PROJEKTNAME = "trading-plattform/"
|
||||||
|
CONFTEST = "tests/conftest.py"
|
||||||
|
|
||||||
|
|
||||||
def zieldateien(taskdatei: Path) -> list[str]:
|
def zieldateien(taskdatei: Path) -> list[str]:
|
||||||
@@ -59,7 +69,11 @@ def zieldateien(taskdatei: Path) -> list[str]:
|
|||||||
return ziele
|
return ziele
|
||||||
|
|
||||||
|
|
||||||
def ist_test(pfad: str) -> bool:
|
def ist_test(pfad: str, conftest_als_test: bool = False) -> bool:
|
||||||
|
if pfad == CONFTEST:
|
||||||
|
# Vorgabe: produktiv. Sonst wendet der Lauf "ohne Umsetzung" eine Korrektur an, die in
|
||||||
|
# conftest.py liegt, und meldet gruen (siehe Kopfkommentar).
|
||||||
|
return conftest_als_test
|
||||||
return pfad.startswith("tests/") or pfad.endswith((".test.ts", ".test.tsx"))
|
return pfad.startswith("tests/") or pfad.endswith((".test.ts", ".test.tsx"))
|
||||||
|
|
||||||
|
|
||||||
@@ -105,6 +119,10 @@ def main() -> int:
|
|||||||
stelle = argumente.index("--node-modules")
|
stelle = argumente.index("--node-modules")
|
||||||
node_modules_arg = Path(argumente[stelle + 1])
|
node_modules_arg = Path(argumente[stelle + 1])
|
||||||
del argumente[stelle : stelle + 2]
|
del argumente[stelle : stelle + 2]
|
||||||
|
conftest_als_test = False
|
||||||
|
if "--conftest-als-test" in argumente:
|
||||||
|
conftest_als_test = True
|
||||||
|
argumente.remove("--conftest-als-test")
|
||||||
if len(argumente) != 4:
|
if len(argumente) != 4:
|
||||||
print(__doc__)
|
print(__doc__)
|
||||||
return 3
|
return 3
|
||||||
@@ -134,9 +152,14 @@ def main() -> int:
|
|||||||
print(f"{task}: ANWENDEN GESCHEITERT: {fehler[-300:]}")
|
print(f"{task}: ANWENDEN GESCHEITERT: {fehler[-300:]}")
|
||||||
continue
|
continue
|
||||||
ziele = zieldateien(planordner / task)
|
ziele = zieldateien(planordner / task)
|
||||||
tests = [z for z in ziele if ist_test(z) and not z.startswith("tests/fixtures/")]
|
tests = [z for z in ziele if ist_test(z, conftest_als_test) and not z.startswith("tests/fixtures/")]
|
||||||
|
if CONFTEST in ziele:
|
||||||
|
# Sichtbar machen, was mit conftest.py geschah -- der Koordinator liest die erste Fehlerzeile
|
||||||
|
# anders, wenn eine Fixture fehlt, als wenn eine Korrektur zurueckgesetzt wurde.
|
||||||
|
wie = "als Testdatei stehen gelassen (--conftest-als-test)" if conftest_als_test else "als Produktivseite auf den Stand vor dem Task zurueckgesetzt"
|
||||||
|
print(f"{task}: Hinweis: {CONFTEST} {wie}")
|
||||||
for ziel in ziele:
|
for ziel in ziele:
|
||||||
if ist_test(ziel):
|
if ist_test(ziel, conftest_als_test):
|
||||||
if not (rot / ziel).exists() and fixturen is not None and (fixturen / Path(ziel).name).is_file():
|
if not (rot / ziel).exists() and fixturen is not None and (fixturen / Path(ziel).name).is_file():
|
||||||
(rot / ziel).parent.mkdir(parents=True, exist_ok=True)
|
(rot / ziel).parent.mkdir(parents=True, exist_ok=True)
|
||||||
shutil.copyfile(fixturen / Path(ziel).name, rot / ziel)
|
shutil.copyfile(fixturen / Path(ziel).name, rot / ziel)
|
||||||
|
|||||||
Reference in new issue
Block a user