Files
claude-regelwerk/.vault-tools/workflow-pruefung/LIESMICH.md
T
Pascal MichelandClaude Opus 5 22761eb186 Automatischer Push: 11 Datei(en) geändert
- .claude/agents/planer.md
- .claude/workflows/plankritik.js
- .claude/workflows/quorum.js
- .claude/workflows/welle-mit-pruefung.js
- .vault-tools/plan-kopie/LIESMICH.md
- .vault-tools/plan-kopie/plan_bloecke.py
- .vault-tools/plan-kopie/plan_materialisiere.py
- .vault-tools/plan-kopie/plan_zaun_treiber.py
- .vault-tools/workflow-pruefung/LIESMICH.md
- .vault-tools/workflow-pruefung/faelle_workflows.mjs
- .vault-tools/workflow-pruefung/mutanten_workflows.py

Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-11-03 03:00:01 +01:00

17 KiB

type, status, title, summary, tags, created, updated
type status title summary tags created updated
resource active Workflow-Prüfung: Attrappe, Fälle und Messreihe zum Verbrauch Node-Attrappe für die gespeicherten Workflows des Vaults mit Fällen je Workflow, dazu verbrauch_reihe.py, das aus den Workflow-Protokollen rechnet, wie viel vom 5-Stunden-Fenster und von der Woche zwischen zwei Verbrauchsablesungen verbraucht wurde. Entstanden 2026-09-24.
vault-tools
codeworkflow
2026-09-24 2026-11-02

Workflow-Prüfung

Die Regel dazu steht in AI/Regelwerk/codeworkflow, Abschnitt „Verbrauch und Opus-Plätze". Hier steht nur, wie man die Werkzeuge benutzt und was belegt ist. Der Plan, mit dem sie entstanden sind: docs/plans/2026-09-24-parallelitaet/00-uebersicht.md in diesem Ordner.

Ablauf

  1. Nach jeder Änderung an einem Workflow unter .claude/workflows/: node .vault-tools/workflow-pruefung/faelle_workflows.mjs im Vault-Wurzelordner. Mit einem Ordner als Argument prüft das Skript die Workflows dort, etwa eine Kopie mit angewendetem Plan. Jeder Workflow hat zuerst eine Grundlinie; scheitert sie, messen seine übrigen Fälle nichts.
  2. Ein neuer Fall braucht einen Rotlauf. Die Fälle gegen den Stand vor der Änderung fahren, oder den Mutanten nachstellen, den der Fall fangen soll. Grün allein belegt nichts.
  3. Mutanten: python .vault-tools/workflow-pruefung/mutanten_workflows.py (am 2026-10-16 knapp 50 Minuten, im Hintergrund fahren) und python .vault-tools/workflow-pruefung/mutanten_reihe.py. Ein veraltetes Muster bricht mit Exit 2 ab und muss an den neuen Code angepasst werden; ein wirkungsloser Mutant steht mit Grund in WIRKUNGSLOS. Wer einen Workflow ändert, ergänzt hier den Mutanten, den sein neuer Fall fangen soll.
  4. Messreihe: python .vault-tools/workflow-pruefung/verbrauch_reihe.py [--seit JJJJ-MM-TT]. Die Ausgabe ist eine Tabelle je Paar aufeinanderfolgender Ablesungen eines Laufs: Minuten, Agentenminuten je Modellfamilie, Differenz im 5-Stunden-Fenster und in der Woche. Darunter steht eine Näherung in Prozent des 5-Stunden-Fensters je Opus-Agentenstunde. Ein Reset zwischen zwei Ablesungen zählt nicht mit.

Was die Attrappe nachbildet

attrappe.mjs führt ein Workflow-Skript mit nachgebauten Globals aus, genauso streng wie das Laufzeitsystem: workflow() im Kind wirft, im Kind ist phase() wirkungslos und jeder Agent trägt die Phase ▸ <name> (ab dem zweiten Aufruf desselben Kindes ▸ <name> #<n>), ein unbekannter Workflow wirft, Date.now(), new Date() ohne Argument und Math.random() werfen. Ein Schema ohne properties wirft, ein Ergebnis ohne die required-Felder wird zu null, und ein agent() ohne model ist ein Verstoß. Ein agentType ohne Agentendatei unter D:/Claude/.claude/agents/ wirft vor dem Start, wie im Ziel (Echtlauf 2026-10-17); Fälle können die Liste über optionen.agenten vorgeben. Aufrufe über D:/Claude/.claude/workflows/... leitet sie in den Ordner unter Test um. Sie zählt, wie viele Agenten je Phase und Modell gleichzeitig laufen.

Was sie nicht sieht: die Obergrenze gleichzeitiger Agenten je Lauf, Budget, Resume und das Verhalten echter Modelle. Wie lange echte Linsen bei drei gleichzeitigen Opus-Agenten laufen und wie viel Verbrauch sie erzeugen, zeigt nur ein echter Lauf.

Was belegt ist

Stand 2026-09-24 nach Plankritik, Prüfung und Nachbesserung. Die Zahlen gelten für diesen Stand; wer Fälle oder Mutanten ergänzt, fährt die Läufe neu, statt die Zahlen hier nachzuziehen.

  • Rotlauf: Gegen die vier alten Workflows scheiterten 122 von 134 Fällen (Stand vor der letzten Nachbesserung). Grün blieben die elf Selbsttests der Attrappe und „kritisch hebt auf xhigh“, ein Verhalten, das sich nicht geändert hat.

  • Mutanten an den Workflows: 52 Mutanten, alle gefangen. Ausgenommen ist „harte Obergrenze fehlt“ in verbrauch.js: Er ist wirkungslos, solange keine Stufe mehr als vier Plätze gibt. Wer die Stufen anhebt, braucht dafür einen Fall.

  • Selbsttests der Attrappe: Ein Mutant, bei dem Date.now() nicht mehr wirft, fällt auf.

  • verbrauch_reihe.py: 27 Fälle, 18 Mutanten, alle gefangen. Die Plankritik fand den wichtigsten Fehler, den kein Fall gesehen hatte: resetsAt schwankt bei jeder Ablesung um Millisekunden und springt über Sekunden- und Datumsgrenzen. Das Skript hielt deshalb jedes echte Paar für einen Reset, weil die Testdaten denselben festen Zeitstempel annahmen wie der Code. Seitdem gilt eine Toleranz von fünf Minuten, und die Grundlinie trägt echte Zitterwerte.

  • verbrauch.js im echten Laufzeitsystem (wf_8746f9c7-f1f): Die Ablesung ergab 43 % und 12 %, genau den Wert, den der Koordinator zur selben Zeit selbst über get_usage las, und damit 3 Plätze. Mit probe bei 95 % kamen 0 Plätze und gebremst heraus; ein Lauf mit probe startet keinen Agenten und steht deshalb in keinem Journal.

  • Neue plankritik.js im echten Laufzeitsystem (wf_32edc4e9-501): Nach der Ablesung von 44 % starteten die drei Linsen innerhalb einer Sekunde; die Widerlegung lief zu zweit. Die Ablesungen stehen im Journal unter den Phasen ▸ verbrauch, ▸ verbrauch #2 und ▸ verbrauch #3. verbrauch_reihe.py wertet sie aus: erstes Paar Reset (das Fenster wurde um 18:30 UTC zurückgesetzt), zweites Paar 3 Punkte bei 19 Opus-Minuten.

  • Neue pruefung.js im echten Laufzeitsystem (wf_e0294c82-76c): Ablesungen 13 %/16 % vor und 18 %/18 % nach einem pruefer von 24 Minuten.

  • Neue planung.js im echten Laufzeitsystem (wf_5df09faa-a4d, Probe mit drei Tasks im Scratchpad): Task 1 lief allein, Task 2 und 3 starteten erst nach seinem Ende und liefen gleichzeitig; beide übernahmen die Zieldatei-Zeile aus Task 1, haben seine Taskdatei also gelesen.

  • Erster Eichwert am Abend des 2026-09-24, Plan laut App „Pro“: verbrauch_reihe.py --seit 2026-09-24 ergab 8,1 % des 5-Stunden-Fensters je Opus-Agentenstunde (5 Paare, 1,7 Opus-Stunden, darunter ein Plankritik-Lauf der Trading-Sitzung). Die Woche stieg in denselben Paaren um 5 Punkte. Der Verbrauch anderer Sitzungen und der Hauptsitzung steckt mit drin; die Zahl ist also eher zu hoch. Für das Nachstellen der Stufen reicht ein Abend nicht.

  • Ableser verlässt den Auftrag (2026-10-16, Plan docs/plans/2026-10-16-ableser-abweichung/): Zweimal bearbeitete der Haiku-Ableser die Nutzeranfrage statt get_usage zu lesen und schrieb seine Antwort in status und plan (wf_7ca17029-421, wf_80616e8e-0e3). verbrauch.js meldet diese Form jetzt als status: abgewichen mit einer Logzeile, die mit WARNUNG beginnt; Plätze wie ohne Ablesung. Neun neue Fälle, sieben davon gegen den alten Stand rot; die zwei Gegenproben (ehrlicher Fehlschlag, not_applicable) bleiben auf beiden Ständen grün. Acht neue Mutanten, alle gefangen; der volle Mutantenlauf brauchte knapp 50 Minuten. Die drei echten Antworten aus den Journalen ergaben abgewichen, abgewichen und nicht_gelesen. Ungemessen: ob der neue Brückensatz im Auftrag einen echten Ableser vom Abweichen abhält; der Fall misst nur, dass der Satz dasteht. Ein abweichender Ableser hat weiterhin alle Werkzeuge.

  • Ableser als Agententyp (2026-10-17, Task 02 desselben Plans): Der Ableser läuft als agentType: verbrauch-ableser (Haiku, effort: low, nur ToolSearch und get_usage). Ein Startfehler, etwa ein in der Sitzung noch unbekannter Typ, kommt als nicht_gelesen mit WARNUNG zurück, nie als Rückfall auf einen Agenten mit allen Werkzeugen. Echtläufe: Vor der Registrierung warf agent() „agent type 'verbrauch-ableser' not found“ ohne Agent (wf_63cb007d-71b); danach lasen vier von vier Ablesern richtig, mit Effort low und nur ToolSearch, get_usage und StructuredOutput (wf_1901f51f-dd3, wf_4d8a69f9-51a). Die Sitzung kannte die neue Agentendatei nach etwa zehn Minuten. 261 Fälle grün, drei neue gegen den alten Stand rot; 157 Mutanten, alle gefangen oder als wirkungslos geführt. Ungemessen: ein Ableser, der eine abweichende Nutzeranfrage sieht. Alle vier Echtläufe starteten in Zügen ohne Nutzernachricht, der Harness reichte keine Anfrage durch.

  • Eichung der Stufen (2026-10-30, Workflow-Review S-11): verbrauch_reihe.py über den ganzen Speicher ergab 1.245 Ablesungen und 647 Paare. Getrennt wurde mit einem Wegwerfskript, das die Funktionen von verbrauch_reihe.py importiert: Plan aus dem Feld plan der Ablesung, Konto aus Wochentag und Stunde des Wochen-resetsAt, auf die volle Stunde gerundet, weil der Wert über die Stundengrenze zittert. Zwei Konten: Reset montags 00:00 UTC (Pro bis 2026-09-30, Max ab 2026-10-05) und mittwochs 20:00 UTC (Max ab 2026-10-09). 340 Ablesungen ohne Plan waren gescheiterte oder abgewichene Ablesungen. Max: 9,2 bzw. 10,1 % des 5-Stunden-Fensters und 2,5 bzw. 2,6 % der Woche je Opus-Agentenstunde (187 und 205 Paare, 107 und 125 Opus-Stunden), Median je Paar ab 15 Opus-Minuten 8,6 bzw. 9,0, P90 rund 19. Pro: 14 Paare, zu wenig. Anstieg des Fensters je Paar nach gleichzeitig laufenden Opus-Agenten: einer Median 3, P90 13, Spitze 33 Punkte (211 Paare); zwei 4, 14, 42 (134); drei 5, 9, 18 (45); vier nur 2 Paare. Pascal hat die Stufen daraufhin unverändert bestätigt und Stufe 3 freigegeben. Ungemessen: Max zeigt je Opus-Stunde mehr Prozent als Pro; als reiner Planeffekt ist das unplausibel, wahrscheinlich liefen im Max-Zeitraum mehr Sitzungen parallel. Die Kontentrennung kann verbrauch_reihe.py selbst nicht.

  • planung mit effort (2026-10-30, für die Messung A2): Das Argument wird geprüft (low bis max), an jeden Planer neben agentType weitergereicht und in der Rückgabe genannt, ohne Argument (Frontmatter). Drei neue Fälle, alle drei gegen den alten Stand rot; drei neue Mutanten, einzeln gefahren und alle gefangen. Der volle Mutantenlauf ist dafür nicht gelaufen.

  • Exit 2 der Planwerkzeuge als Befund (2026-11-02, Auftrag der Startsitzung der Zaunprüfung, Pascal: „Ja, nachziehen“): welle-mit-pruefung hält vor executer-welle, wenn plan_materialisiere.py beim Bau der Kopie eine Zeile BEFUND <taskdatei>:<zeile>: meldet (status: plan_befund, die Zeilen in plan_befunde). plankritik zählt ein Planwerkzeug mit Exit 2 und Befundzeile als gelaufen, plan_bloecke auch mit Exit 3 und „Nichts geprueft:“. Die Ausgabe geht dann an die Linse bezeichner, die Zeilen stehen unter werkzeug_befunde. Exit 2 ohne Befundzeile nennt das Log mit Werkzeug und Exit statt „Hilfsagent ohne Ergebnis“. Beide lesen dafür alle laeufe des Hilfsagenten: Im Echtlauf wf_9ab7fd8e-ad1 gab werkzeug:planwerkzeuge je Werkzeug einen Lauf zurück, und laeufe[0] allein enthielt plan_bloecke nicht. 24 neue Fälle, gegen den alten Stand 19 rot; die 5 Gegenproben für den alten Weg sind auf beiden Ständen grün. 292 Fälle grün. 22 neue Mutanten, je an ihrem Pflichtfall gefangen; alle 188 Mutanten, parallel über ein Wegwerfskript: 187 gefangen, 1 wirkungslos wie bisher. Echtläufe auf einem Wegwerfprojekt mit klebendem Zaun: wf_63d99146-e89 hält mit plan_befund, ein Agent, kein Executer; die Mutante ohne Halt (wf_2b979130-800) endet mit bis_vergleich, ihr Executer schrieb den kaputten Plan ins Projekt; plankritik (wf_f1867091-dda) führt beide Befundzeilen unter werkzeug_befunde, und die Linse bekam die Werkzeugausgabe. Ungemessen: ein Hilfsagent, der Befundzeilen umformuliert oder weglässt; dann hält nichts.

  • Alle laeufe an fünf weiteren Stellen (2026-11-02, Folgeauftrag der Zaunprüfung): Der Erfolgspfad der Kopie in welle-mit-pruefung und in kopieAusLauf() von plankritik, der Vergleich für den pruefer, der Mutantenlauf in plankritik und ausgabe() in quorum lesen die Ausgabe aller laeufe, in ihrer Reihenfolge und mit Zeilenumbruch verbunden. Verwendbar ist eine Kopie nur, wenn jeder Lauf Exit 0 hat: Ihr Befehl ist eine Kette mit &&. Mit laeufe[0] allein galt ein erster Lauf mit 0 vor einem Absturz im zweiten als fertige Kopie, und im Quorum lief ein gestarteter Codex-Auftrag ungesehen weiter, während Haiku einsprang. KEINE_MUTANTEN_TOML zählt nur noch als ganze Zeile; sonst machte ein zusätzlicher Lauf mit dem Skripttext aus einem gefahrenen Mutantenlauf keine_toml (Befund der Gegenprüfung durch den pruefer). Die Antworten in faelle_workflows.mjs nehmen jetzt auch für werkzeug:vergleich, werkzeug:mutanten und die Quorum-Labels Listen von Läufen. 18 neue Fälle, gegen den alten Stand 16 rot; die 2 übrigen sichern Code, den erst dieser Auftrag braucht, und sind dort grün. 310 Fälle grün. 16 neue Mutanten und 3 alte mit angepasstem Muster, je an ihrem Pflichtfall gefangen; alle 204 Mutanten, parallel über ein Wegwerfskript: 203 gefangen, 1 wirkungslos wie bisher. Ungemessen: ein Echtlauf, in dem ein Hilfsagent an einer dieser Stellen seine Ausgabe verteilt; laeufe in anderer Reihenfolge als ausgeführt. An der Reihenfolge hängt bei einem langen Vergleich das Ergebnis der Suite für den pruefer; die jobId-Suche in quorum.js hängt seit dem Folgeauftrag zum Codex-Start nicht mehr daran.

  • Codex-Start unabhängig von Reihenfolge und Form der laeufe (2026-11-02, Folgeauftrag, Pascal: „Ja, hier bauen“; geplant mit Codex Sol gpt-6.1-sol, in vier Runden kritisiert von Codex Astra gpt-6-astra): codexStimme() in quorum.js nimmt die jobId nur noch am Objektanfang der Task-Antwort, { gefolgt von "jobId": "<id>", Komma und "status": "queued" bei beliebigem Leerraum, und nur innerhalb eines Laufs. Verfolgt wird ein Auftrag nur bei genau einer verschiedenen ID. Die alte Regel nahm die erste jobId hinter dem letzten EXIT status:. In 42 echten Rückgaben von codex:start aus Workflow-Transkripten (2026-09-30 bis 2026-10-31) wählte sie einmal einen früheren Job, weil der Hilfsagent EXIT status: 0 vor das Status-JSON gestellt hatte, und fand zweimal keine jobId, weil er die Task-Antwort kompakt neu serialisiert hatte. Zwei weitere Rückgaben verteilten die Ausgabe auf zwei laeufe, je Befehl einen; der Code vor dem Folgeauftrag „alle laeufe“ las nur den ersten. In allen fünf Läufen sprang Haiku ein, und der Codex-Auftrag lief ungesehen. Über den echten Code und die Attrappe gefahren, verfolgt der neue Stand in allen 42 die richtige ID. Kommt die Ausgabe nicht in Befehlsreihenfolge, steht ein Hinweis im Bericht; fehlt trotz EXIT task: 0 eine sichere ID, warnt der Grund vor einem womöglich ungesehen weiterlaufenden Auftrag. Abgesichert ist das Bedrohungsmodell M1 bis M4: Verteilung und beliebige Reihenfolge der laeufe, Leerraum und kompakte Form, Kürzung nach der Vorgabe im Hilfsagentenauftrag, verschobene EXIT-Zeilen mit kurzen Vorsätzen. Frei umgestellte Zeilen innerhalb eines Laufs oder erfundene Inhalte fängt nur der Lesebeleg in codexUngueltig(). 31 neue Fälle, gegen den alten Stand 27 rot; die 4 übrigen sichern die Umrechnung der Fundstellen und zwei Gründe ohne Warnung. 341 Fälle grün. 25 neue oder angepasste Mutanten an ihrem Pflichtfall gefangen; alle 227 Mutanten, parallel über ein Wegwerfskript: 226 gefangen, 1 wirkungslos wie bisher. Die Breitensuche des pruefer über die echte Funktion fand in 1.944.937 erzeugten Lagen keine alte ID, gegen den alten Stand 537.307. Ungemessen: ein Echtlauf mit vertauschten laeufe; unter den 42 war keiner.

Offen: Für ausgabe() im Quorum liegen echte Rückgaben mit zwei laeufe vor (2026-10-13, 2026-10-22); für die übrigen vier Stellen ist nur die Attrappe belegt, ein Echtlauf mit verteilten laeufe steht aus. Nicht gebaut: kopieAusLauf() in plankritik.js nennt den Temp-Ordner nicht, wenn die Kopie an einem Exit ungleich 0 scheitert. Am Codex-Start lehnt quorum.js mit Warnung ab, wenn die Task-Antwort zwischen { und "jobId" oder zwischen "jobId" und "status" auf zwei laeufe geteilt ist; ohne EXIT-Zeile am Zeilenanfang kommt der Reihenfolgehinweis auch bei richtiger Reihenfolge. Statuseinträge, die eine ältere Pluginversion in state.json geschrieben hat, sind nicht an Quellen geprüft; in den 42 Echtläufen trug keiner das Merkmal. codex:warten erkennt das Ende nur an "waitTimedOut": false mit Leerzeichen; so stand es in allen 54 echten Rückgaben, ob ein Hilfsagent mit kompaktem Start auch die Warte-Ausgabe kompakt liefert, ist ungemessen. Den Inhalt eines Hilfsagenten liest kein Workflow mehr nur aus laeufe[0]; plankritik.js fragt laeufe[0] bei den Planwerkzeugen nur ab, um „Hilfsagent ohne Ergebnis“ zu erkennen. Die Stelle „Ausgabe der Planwerkzeuge nur bei EXIT 0“ (Trading-Sitzung, 2026-09-24) hat seit 2026-11-02 Fälle.

Was die Skripte nicht sehen

Den Verbrauch anderer Sitzungen und der Hauptsitzung: Er steckt in jeder Differenz mit drin. Ablesungen über probe starten keinen Agenten und fehlen in der Messreihe. get_usage gibt es nur in der Desktop-App; anderswo gilt über den Rückfall die Zwei, und die Messreihe bleibt leer. Die Stufen in verbrauch.js sind am 2026-10-30 geeicht, aber an einer Messreihe mit dem Verbrauch paralleler Sitzungen. Sie sind ein Fangnetz und kein Nachweis dafür, dass ein Lauf das Fenster nicht reißt.