Abgleich mit dem Vault-Stand 22761eb
11 Datei(en) geändert. Erzeugt von .vault-tools/auto-push/werkzeuge_spiegel.py.
This commit is contained in:
1 parent
9e506ff588
commit
ae3ec3ca89
11 files changed
+1520
-65
No files matched your search
@@ -5,7 +5,7 @@ title: "Planwerkzeuge: Plan auf eine Kopie anwenden und jede Welle dagegen vergl
|
||||
summary: "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)."
|
||||
tags: [vault-tools, codeworkflow]
|
||||
created: 2026-09-17
|
||||
updated: 2026-10-17
|
||||
updated: 2026-11-02
|
||||
---
|
||||
|
||||
# Planwerkzeuge für die Kopie mit angewendetem Plan
|
||||
@@ -14,8 +14,8 @@ Die Regel dazu steht in [[AI/Regelwerk/codeworkflow|codeworkflow.md]] („Die Ko
|
||||
|
||||
## Ablauf
|
||||
|
||||
1. **Kopie bauen — erst, wenn der Planer fertig gemeldet hat.** Den Projektbaum ohne `.git`, ohne Geheimnisdateien und ohne `node_modules` in einen Wegwerfordner kopieren. **Ausschlüsse als Pfade vom Wurzelordner angeben, nicht als Ordnernamen:** Ein Ausschluss von „jedem Ordner namens `data`" hat am 2026-09-17 auch das Paket `trading/data` getroffen, und die Suite der Kopie brach mit Sammelfehlern ab. Nach dem Kopieren die Paketliste gegen das Original halten. **Beides erledigt `kopie_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 Kopie `node_modules`, eine Junction setzen (`mklink /J`) — **und sie vor dem Löschen der Kopie mit `cmd //c rmdir <pfad>` wieder lösen**, sonst trifft `rm -rf` das echte `node_modules`. Nie `tsc -b` durch die Junction fahren (schreibt nach `node_modules/.tmp`); `npx tsc -p tsconfig.app.json --noEmit` nehmen.
|
||||
2. **Plan anwenden:** `plan_materialisiere.py <planordner> <kopie> task-01.md task-02.md …` in Wellenreihenfolge. Erkennt die Marken `Aus:` / `wird:`, „Die ganze Datei ist neu", „vollständig ersetzt" und „Häng diesen Block ans Ende"; Dateien, die `## Zieldateien` als „(gelöscht)" führt, löscht es in der Kopie. Prosa-Tasks („wird: ein neuer Abschnitt, er muss sagen …") lassen sich nicht anwenden. Eine Datei ganz ohne Endung (`host/logrotate/edge-traefik`, `Dockerfile`, `.gitignore`) ist Ziel, wenn derselbe Pfad unter `## Zieldateien` steht. Fehlt der Eintrag, ist ihr Block ein Befund mit Exit 2, außer bei einer neuen Datei ohne Schrägstrich (unten, „Seit 2026-10-17").
|
||||
1. **Kopie bauen — erst, wenn der Planer fertig gemeldet hat.** Den Projektbaum ohne `.git`, ohne Geheimnisdateien und ohne `node_modules` in einen Wegwerfordner kopieren. **Ausschlüsse als Pfade vom Wurzelordner angeben, nicht als Ordnernamen:** Ein Ausschluss von „jedem Ordner namens `data`" hat am 2026-09-17 auch das Paket `trading/data` getroffen, und die Suite der Kopie brach mit Sammelfehlern ab. Nach dem Kopieren die Paketliste gegen das Original halten. **Beides erledigt `kopie_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 Kopie `node_modules`, eine Junction setzen (`mklink /J`) — **und sie vor dem Löschen der Kopie mit `cmd //c rmdir <pfad>` wieder lösen**, sonst trifft `rm -rf` das echte `node_modules`. Nie `tsc -b` durch die Junction fahren (schreibt nach `node_modules/.tmp`); `npx tsc -p tsconfig.app.json --noEmit` nehmen. Auch Vitest schreibt hinter die Junction: Vite legt beim Laden der Konfiguration `node_modules/.vite-temp` an und löscht die Datei danach, unabhängig von `cacheDir` (gemessen 2026-11-02 im Nexhorizons Hub, Vite 8.3.0); `cacheDir` in einer Wegwerf-Konfiguration hält nur den eigentlichen Cache aus dem fremden `node_modules` heraus.
|
||||
2. **Plan anwenden:** `plan_materialisiere.py <planordner> <kopie> task-01.md task-02.md …` in Wellenreihenfolge. Erkennt die Marken `Aus:` / `wird:`, „Die ganze Datei ist neu", „vollständig ersetzt" und „Häng diesen Block ans Ende"; Dateien, die `## Zieldateien` als „(gelöscht)" führt, löscht es in der Kopie. Prosa-Tasks („wird: ein neuer Abschnitt, er muss sagen …") lassen sich nicht anwenden. Vor dem ersten Schreibvorgang prüft es die Zäune aller übergebenen Taskdateien; ein kaputter Zaun ist ein Befund mit Exit 2, und der Lauf schreibt nichts (unten, „Seit 2026-11-02“). Eine Datei ganz ohne Endung (`host/logrotate/edge-traefik`, `Dockerfile`, `.gitignore`) ist Ziel, wenn derselbe Pfad unter `## Zieldateien` steht. Fehlt der Eintrag, ist ihr Block ein Befund mit Exit 2, außer bei einer neuen Datei ohne Schrägstrich (unten, „Seit 2026-10-17").
|
||||
3. **Auf der Kopie fahren:** Suite, Typprüfung, Mutanten. Ein Mutantenlauf gibt je Mutant die Fehlerzeile aus, nicht nur den Exitcode.
|
||||
4. **Vor jeder Welle und nach jeder Plankorrektur:** `plan_bloecke.py vor <tasks…> --projekt <projekt>` (jeder Aus-Block steht genau einmal im echten Baum) und `plan_zeichen.py <planordner>` (keine Zeilen- und Absatztrenner, Format- und Steuerzeichen in Codeblöcken).
|
||||
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". Eine Zieldatei, die git ignoriert (etwa Prüfdateien unter `tests/.work/`), vergleicht es seit 2026-10-17 ebenfalls byte-genau mit der Kopie und zählt sie in der Schlusszeile als „von git ignoriert"; vorher meldete es sie als „unveraendert gegenueber HEAD" und verglich sie nicht.
|
||||
@@ -62,6 +62,30 @@ Nachbesserung vom 2026-10-09 (Paket RB3 der Trading Plattform, Plan `docs/plans/
|
||||
|
||||
Seit 2026-10-11 schreibt `plan_materialisiere.py` nur noch innerhalb der Kopie. Vorher schlug ein absoluter Pfad in einer Überschrift unter Windows die Kopie (`kopie / "D:/…"` ist der absolute Pfad): Das Skript ersetzte dann die echte Datei, mit Exit 0 und „0 Befund(e)“. Gemessen an einer Probe-Datei im Scratchpad. Entdeckt beim Planen von Paket E9 der Trading Plattform, dessen Tasks 725 und 726 Dateien unter `D:/Claude/.vault-tools/` ändern. Jetzt ist ein Ziel außerhalb der Kopie (absolut oder mit `..`) ein Befund mit Exit 2, und nichts wird geschrieben. Belegt am selben Tag mit drei Fällen (Aus/wird absolut, ganze Datei absolut, `../`): je Befund, die Dateien draußen unverändert; und mit einer Gegenprobe: Die Tasks 723 und 724 von E9 ergeben in einer frischen Kopie dieselben Zählungen und byte-gleiche Dateien. Pläne für Dateien außerhalb des Projekts nennen sie deshalb relativ zu einem Wurzelordner (etwa `.vault-tools/trading-plattform-pruefung/abendkontrolle.py` gegen eine Kopie, die diesen Ordner enthält).
|
||||
|
||||
Seit 2026-11-02 prüfen `plan_materialisiere.py` und `plan_bloecke.py` die Zäune einer Taskdatei, bevor sie einen Block anfassen. Anlass war Auftrag 13 der Kette 050 (Trading Plattform) am 2026-11-01: In `task-1020` klebte der schließende Zaun zweimal an `])`. Der Block lief bis in den nächsten Task, das erste Aus/wird-Paar dort ging ohne eigene Meldung verloren, und das Werkzeug sagte nur „Aus-Block steht 0-mal“. Das sah nach einem falschen Anker aus. Unter „Die ganze Datei ist neu“ schrieb derselbe Fehler Planprosa in die Zieldatei, mit Exit 0 und „0 Befund(e)“. Die Regel jetzt, `n` ist die Zaunlänge des Blocks:
|
||||
- Ein Block schließt mit mindestens `n` Backticks in einer Zeile ohne weiteren Text, höchstens drei Spalten tiefer als der Öffner (CommonMark 0.31.2). Tiefer ist es Inhalt. Vorher schloss jeder Einzug, auch ein Zaun in einer eingerückten Zeichenkette, und auch zwei Zäune auf einer Zeile.
|
||||
- Befund ist eine Zeile im Block, die auf mindestens `n` Backticks endet und nicht schließt (klebender Zaun, auch ein zu tief eingerückter).
|
||||
- Befund ist eine Zeile im Block, die mit mindestens `n` Backticks beginnt und nicht schließt: Der Schlusszaun fehlt, oder der Außenzaun ist zu kurz.
|
||||
- Befund ist ein Block, der bis zum Dateiende nicht schließt, und eine Taskdatei, die sich nicht lesen lässt.
|
||||
- `plan_materialisiere.py` prüft alle übergebenen Taskdateien vor dem ersten Schreibvorgang. Bei einem Befund schreibt und löscht der ganze Lauf nichts und endet mit Exit 2, auch die heilen Taskdateien davor bleiben ungeschrieben. Die Zählzeile je Task entfällt dann.
|
||||
- `plan_bloecke.py` meldet denselben Befund und prüft die Blöcke dieser Taskdatei nicht, die übrigen Taskdateien prüft es weiter. Ein Zaunbefund endet immer mit Exit 2, auch wenn sonst nichts geprüft wurde. Die Blocksuche ist jetzt dieselbe wie in `plan_materialisiere.py` (`zaun()` und `schliesst()`), vorher sah es nur Zäune in Spalte 0.
|
||||
- Eine Zeile mit weiterem Backtick hinter dem Zaun öffnet nichts, sie ist Inline-Code (CommonMark 0.31.2: „Info strings for backtick code blocks cannot contain backticks“). Vorher schluckte so eine Zeile den nächsten Block.
|
||||
- Bewusst entschieden: Ein Text im Block, etwa eine Zeichenkette in einem Test, der auf `n` Backticks endet oder mit ihnen beginnt, ist derselbe Befund. Von einem klebenden Zaun ist er nicht zu unterscheiden. Abhilfe ist ein längerer Zaun um den Block. Beim Text am Zeilenende steht oft ein Folgebefund weiter hinten, weil der echte Schlusszaun für die Suche einen Block öffnet; der längere Zaun löst beide.
|
||||
- Nicht entscheidbar: Ein nackter Zaun als eigene Zeile im Text, höchstens drei Spalten tiefer als der Öffner, schließt den Block. Geht die Zahl der Zäune auf, wird der Rest Prosa, und es kommt kein Befund. Text mit Zäunen braucht deshalb immer einen längeren Zaun um den Block. Der Treiberfall „Luecke: nackter Zaun als Zeile im Text“ hält das fest.
|
||||
- Kein Befund sind Markdown-Vorlagen in längeren Zäunen mit `##`-Überschriften und kürzeren Zäunen darin, eingerückte Blöcke, Inline-Code und Zaunfolgen mitten in der Zeile oder in Anführungszeichen, Prosa außerhalb von Blöcken.
|
||||
- `welle_vergleich.py` liest keine Blöcke, nur `## Zieldateien`, und bleibt unverändert. `plan_zeichen.py` und `plan-diff/plan_diff.py` haben je eine eigene Blocksuche mit derselben Lücke. Sie schreiben nichts und bleiben unverändert; was ein kaputter Zaun dort bewirkt, ist nicht gefahren, nur am Quelltext gelesen.
|
||||
|
||||
Belegt am 2026-11-02 (Rohdaten und Messskripte: `AI/secondbrain/regelwerk-memory/2026-11-01-zaunpruefung/`):
|
||||
- `plan_zaun_treiber.py [--werkzeuge <ordner>] [--mutanten]` fährt 114 Fälle, die Grundlinie zuerst, und prüft je Fall Exit, jede Befundzeile samt Zeilennummer, die Zahl der Befunde, die Summenzeile und jede Datei der Kopie. Die Angriffe aus `paar()` haben ein geheiltes Gegenstück, das schreiben muss; sonst wäre „nichts geschrieben“ auch grün, wenn die Fixture nichts anwendet. Gefahren unter Windows und in WSL Debian.
|
||||
- Alte Fassung 65 von 114 Fällen rot, neue 0. `plan_ziel_treiber.py` bleibt bei 33 von 33.
|
||||
- `--mutanten` baut 39 Fehler ein, jeder ist an seinem Fall gefangen.
|
||||
- `task-1020` vor der Korrektur: genau zwei Befunde an den Zeilen 1678 und 1729, die Kopie bleibt unverändert. Die alte Fassung meldete dort 80 Folgefehler und schrieb fünf Dateien.
|
||||
- Alle Taskdateien im Vault und in den Jobordnern (2 253 verschiedene, 59 790 Blöcke): `bloecke()` alt und neu liefern dasselbe. Die Zaunprüfung meldet acht Zeilen in drei alten Doku-Tasks (`task-89` und `task-94` der Trading Plattform, `task-08` von After Install). Alle acht sind echt: Der Außenzaun war zu kurz, der Block endete zu früh. `plan_bloecke.py vor` weicht in genau diesen drei von 188 Planordnern ab.
|
||||
- Kette 050: alle 50 Lieferungen, angewendet wie in `kette_050.py` (Basis plus transitive Vorgänger), mit alter und neuer Fassung: gleiche Meldungen, gleiche Bäume. Die eingesetzte Fassung meldet in den 52 Taskdateien der Lieferungen keinen Zaunbefund, `zaun_scan.py` kein `KLEBT` und kein `OFFEN`. Seine `STRUKTUR`-Treffer sind Markdown-Überschriften als Inhalt geschlossener `markdown`- und `text`-Blöcke und bleiben ohne Befund.
|
||||
- Zustandssuche über die echten Funktionen (`messung/zaun_suche.py`, 40 000 zufällige heile Dateien, je ein Zaun beschädigt): keine heile Datei mit Befund, wobei der Generator in Dreierblöcken keine inneren Zäune erzeugt; alle 4 915 klebenden Zäune gefunden.
|
||||
- Ein `pruefer` fand keinen blockierenden Befund. Eingearbeitet sind der Einzug, die zwei Zäune auf einer Zeile, die weitere Regel für den Zeilenanfang und die Lücken seiner Treiberfälle.
|
||||
- Lücken: Ein nackter Zaun als Öffner ist von einem Schlusszaun nicht zu unterscheiden. Fehlt der Schlusszaun und kommt als Nächstes ein nackter Zaun derselben oder größerer Länge, schließt der den Block, und die Rollen tauschen bis zum nächsten Öffner mit Sprache oder bis zum Dateiende; zwei solche Fehler heben sich auf. In der Zufallssuche blieben rund 2 % der fehlenden Schlusszäune still, rund 13 % der fehlenden oder klebenden Öffner. Dasselbe gilt für einen Backtick in der Sprachangabe, für Zäune hinter Listenpunkt oder Zitatzeichen und für Backtick-Zäune in Tilde-Blöcken.
|
||||
|
||||
Seit 2026-10-17 geht ein Block nicht mehr still in die falsche Datei, wenn seine Überschrift eine Datei ohne Endung nennt. Beide Werkzeuge nutzen dafür `ordne()` in `plan_materialisiere.py`; `plan_bloecke.py` importiert die Funktion. Anlass war die Plankritik von Paket R1 im Edge-Stack (Befunde 1 und 5): Die Überschrift „Stelle 30 — `host/logrotate/edge-traefik`" setzte kein Ziel, das Ziel blieb bei `tests/systemd/test-units.sh` aus Stelle 29, und der Block „Die ganze Datei ist neu" überschrieb diese Datei, mit Exit 0 und „0 Befund(e)". Die Regel jetzt:
|
||||
- Ziel ist der letzte PFAD-Treffer der Überschrift. Ohne ihn ist Ziel der letzte Token, der (ohne `./`) genau so unter `## Zieldateien` derselben Taskdatei steht. So wird eine Datei ohne Endung planbar: `host/logrotate/edge-traefik`, `Dockerfile`, `.gitignore`.
|
||||
- Ein absoluter Eintrag unter Zieldateien zählt relativ zum Projekt. Das ist in `plan_bloecke.py` `--projekt`, wie in `welle_vergleich.py`, und in `plan_materialisiere.py` der Ordner vor `docs/plans` im Pfad des Planordners. Ordner, Muster mit `*` und Pfade mit `..` unter Zieldateien sind kein Ziel.
|
||||
@@ -96,6 +120,6 @@ Offen seit 2026-09-23: `plan_materialisiere.py` stirbt mit `FileNotFoundError`,
|
||||
|
||||
## Was die Skripte nicht sehen
|
||||
|
||||
Dateien, die `.gitignore` ausblendet und die keine Zieldatei sind; bei einer ignorierten Zieldatei, ob sie vor der Welle schon so aussah; 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 „с"); eine neue Zieldatei ohne Endung und ohne Schrägstrich, die nicht unter `## Zieldateien` steht — ihr Block geht still ins vorige Ziel. Sie sind ein Fangnetz, kein Nachweis — den liefert der Lauf mit echten Daten.
|
||||
Dateien, die `.gitignore` ausblendet und die keine Zieldatei sind; bei einer ignorierten Zieldatei, ob sie vor der Welle schon so aussah; 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 „с"); eine neue Zieldatei ohne Endung und ohne Schrägstrich, die nicht unter `## Zieldateien` steht — ihr Block geht still ins vorige Ziel; ein nackter Zaun als Zeile im Text, ein fehlender Schlusszaun vor einem nackten Zaun und ein fehlender Öffner. 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.
|
||||
Reference in new issue
Block a user