- .claude/agents/verbrauch-ableser.md - .claude/workflows/verbrauch.js - .vault-tools/workflow-pruefung/LIESMICH.md - .vault-tools/workflow-pruefung/attrappe.mjs - .vault-tools/workflow-pruefung/docs/plans/2026-10-16-ableser-abweichung/00-uebersicht.md - .vault-tools/workflow-pruefung/docs/plans/2026-10-16-ableser-abweichung/task-01-erkennung.md - .vault-tools/workflow-pruefung/docs/plans/2026-10-16-ableser-abweichung/task-02-agententyp.md - .vault-tools/workflow-pruefung/faelle_workflows.mjs - .vault-tools/workflow-pruefung/mutanten_workflows.py - AI/Regelwerk/haiku-5-5.md - CLAUDE.md Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py. Co-Authored-By: Claude Opus 5 <[email protected]>
10 KiB
type, title, status, summary, tags, created, updated, modell, modell_begruendung
| type | title | status | summary | tags | created | updated | modell | modell_begruendung | |||
|---|---|---|---|---|---|---|---|---|---|---|---|
| plan-task | Task 01 — verbrauch.js: Abweichung erkennen, Brückensatz, Fälle und Mutanten | draft | verbrauch.js bekommt den Brückensatz im Auftrag, die Erkennung abgewichen mit Warnzeile und den neuen Status in meta; faelle_workflows.mjs bekommt die Fälle dazu, mutanten_workflows.py die Mutanten. Alles in Kopien im Scratchpad. |
|
2026-10-16 | 2026-10-16 | sonnet | verbrauch.js ist Abschrift, die Fälle sind nur als Eingabe und Erwartung vorgegeben und brauchen Autorschaft. |
Übersicht: 00-uebersicht.md
Task 01 — Abweichung erkennen
Arbeitsorte
S ist D:/ClaudeData/claude/D--Claude/8a6a0a87-ddcf-462b-90e2-83ab3ba2be28/scratchpad. Du schreibst nur diese drei Dateien:
S/wf-neu/verbrauch.js(Kopie vonD:/Claude/.claude/workflows/verbrauch.js)S/wp-neu/faelle_workflows.mjs(Kopie ausD:/Claude/.vault-tools/workflow-pruefung/)S/wp-neu/mutanten_workflows.py(Kopie, ebenda)
Nichts unter D:/Claude/ anfassen. Keine Hilfsdateien. Kein Commit.
1 verbrauch.js
Ersetze genau diese Stellen, Zeichen für Zeichen. Die Datei hat LF-Zeilenenden; behalte sie.
1a, in meta.whenToUse: Rückgabe {status: ok|nicht_gelesen|unbekannte_fenster, wird zu Rückgabe {status: ok|nicht_gelesen|abgewichen|unbekannte_fenster,. Und Ohne lesbare Ablesung gilt die alte Obergrenze zwei. wird zu Ohne lesbare Ablesung gilt die alte Obergrenze zwei; abgewichen heißt, der Ableser hat statt get_usage etwas anderes getan, und kommt mit einer WARNUNG im Log.
1b, Kopfkommentar: Vor der Zeile // Was das Skript nicht sieht: Agenten, die nach der Ablesung in anderen Sitzungen starten; kommen diese Zeilen:
// - Ob der Ableser abgelesen hat: Quelle. Der Auftrag schreibt im Fehlerfall status "fehler",
// plan "" und fenster [] vor; get_usage kennt laut Werkzeugbeschreibung (gelesen 2026-10-16)
// nur die Status ok, not_applicable und unavailable. Am 2026-10-14 und 2026-10-16 hat der
// Ableser stattdessen die Nutzeranfrage bearbeitet und status "beantwortet: ..." bzw.
// "blockiert: ..." mit einem Bericht in plan zurückgegeben (wf_7ca17029-421, wf_80616e8e-0e3).
// Grund laut CLI-Abbild 2.1.299: Jeder Workflow-Agent liest zuerst die Nutzeranfrage mit dem
// Satz, dass sie im Konflikt mit dem Auftrag gewinnt. Jede andere Form als die vorgeschriebene
// heißt abgewichen und wird laut gemeldet. Nicht erkannt wird ein Ableser, der abweicht und
// trotzdem genau die Fehlerform schreibt, und eine erfundene Ablesung mit status ok.
1c, Auftrag: Die erste Zeile des Template-Strings AUFTRAG ist bisher const AUFTRAG = \Lade mit dem Werkzeug ToolSearch ...`. Davor, als neue erste Zeile im String, kommt dieser Satz; der Rest bleibt unverändert:
const AUFTRAG = `Diese Ablesung gehört zur Nutzeranfrage und widerspricht ihr nicht: Sie entscheidet, wie viele Prüfagenten für die Anfrage gleichzeitig laufen dürfen. Die Anfrage selbst bearbeiten andere Agenten nach dir; du bearbeitest sie nicht, auch nicht teilweise, und liest dafür keine Dateien.
Lade mit dem Werkzeug ToolSearch das Werkzeug mcp__ccd_session_mgmt__get_usage (Abfrage "select:mcp__ccd_session_mgmt__get_usage") und rufe es einmal ohne Parameter auf.
1d, Erkennung: Direkt nach der Funktion einordnen (nach ihrer schließenden } und vor der Leerzeile, auf die pruefeArgs(args) folgt) kommt:
// Form eines Ablesers, der den Auftrag verlassen hat (Geltungsbereich oben).
const STATUS_BEKANNT = ['ok', 'not_applicable', 'unavailable', 'fehler']
function abgewichen(a) {
if (!STATUS_BEKANNT.includes(a.status)) return true
return a.status === 'fehler' && typeof a.plan === 'string' && a.plan.trim() !== ''
}
const kurz = t => String(t).replace(/\s+/g, ' ').trim().slice(0, 160)
1e, Rückgabe: Nach der Zeile if (!ablesung || typeof ablesung !== 'object') return ohneAblesung('nicht_gelesen', 'kein Ergebnis vom Ableseagenten') und vor der Zeile if (ablesung.verfuegbar !== true || ablesung.status !== 'ok') ... kommt:
if (abgewichen(ablesung)) {
log(`WARNUNG Verbrauch ${args.anlass}: Der Ableser hat get_usage nicht gelesen und den Auftrag verlassen; die Bremse misst nicht. Seine Werkzeugaufrufe im Journal unter ▸ verbrauch ansehen.`)
return ohneAblesung('abgewichen', `Ableser hat den Auftrag verlassen: status ${kurz(ablesung.status)}${ablesung.fehler ? ', fehler ' + kurz(ablesung.fehler) : ''}`)
}
Sonst änderst du an verbrauch.js nichts.
2 faelle_workflows.mjs
Neue Fälle im Abschnitt verbrauch, nach dem Fall Agent ohne Ergebnis: .... Feste Testdaten, gekürzt und neutral, in der Form der echten Abweichungen:
// Form der echten Abweichungen vom 2026-10-14 und 2026-10-16, Texte gekürzt und neutral.
const abweichung = (status, fehler) => ({ verfuegbar: false, status, plan: '**Stand:** Bericht zur Nutzeranfrage statt Ablesung.\n- Punkt 1\n- Punkt 2', fenster: [], fehler })
const BEANTWORTET = abweichung('beantwortet: offene Punkte im Projekt X, Stand 2026-10-10', 'Kein get_usage-Aufruf und kein Planverbrauch abgelesen: Die Benutzeranfrage hat laut Harness Vorrang vor dem Verbrauchsauftrag.')
const BLOCKIERT = abweichung('blockiert: Folgesitzung nicht abgeschlossen; nichts geaendert', 'Blockade: Workflow- und Agent-Werkzeug fehlen. Kein get_usage-Aufruf, siehe plan.')
const warnung = p => p.logs.filter(l => /^WARNUNG/.test(l))
Fälle, je mit pruefe() und soll wie die Nachbarn; die Abweichung kommt als Antwort des Ablesers (V({ anlass: 't', wunsch: 3 }, { ablesungen: [X] })), nicht über probe:
| Name | Eingabe | Erwartung |
|---|---|---|
Ableser beantwortet die Nutzeranfrage: abgewichen, Warnung, zwei Plätze |
BEANTWORTET, wunsch: 3 |
status 'abgewichen', plaetze 2, gebremst false, quelle 'agent', grund passt auf /Auftrag verlassen/ und enthält beantwortet:, genau eine Warnzeile |
Ableser meldet blockiert: abgewichen, Warnung |
BLOCKIERT, wunsch: 1 |
status 'abgewichen', plaetze 1, grund enthält blockiert:, genau eine Warnzeile |
status fehler mit Bericht in plan: abgewichen |
{ verfuegbar: false, status: 'fehler', plan: 'Bericht', fenster: [], fehler: 'x' } |
status 'abgewichen', eine Warnzeile |
ehrlicher Fehlschlag bleibt nicht_gelesen, ohne Warnung |
{ verfuegbar: false, status: 'fehler', plan: '', fenster: [], fehler: 'No matching deferred tools found' } |
status 'nicht_gelesen', plaetze 2, keine Warnzeile |
not_applicable bleibt nicht_gelesen, ohne Warnung |
{ verfuegbar: true, status: 'not_applicable', plan: '', fenster: [], fehler: '' } |
status 'nicht_gelesen', keine Warnzeile |
grund kürzt einen langen status auf 160 Zeichen, ohne Zeilenumbruch |
abweichung('beantwortet:\n' + 'x'.repeat(400), '') |
status 'abgewichen'; der Teil von grund hinter status ist höchstens 160 Zeichen lang und enthält kein \n |
Auftrag ordnet die Ablesung der Nutzeranfrage zu |
Grundlinie ohne Abweichung | p.agents[0].prompt enthält gehört zur Nutzeranfrage und bearbeiten andere Agenten. Kommentar über dem Fall: misst nur, dass der Satz da ist, nicht, ob er wirkt |
Zwei neue Fälle im Abschnitt plankritik, nach Ablesung ohne Ergebnis: Linsen zu zweit (alte Obergrenze) (Reihenfolge: derselbe Schaden an erster und letzter Ablesung):
| Name | Eingabe | Erwartung |
|---|---|---|
Abweichung bei der ersten Ablesung: Linsen zu zweit, Status abgewichen im Ergebnis |
PK(PK_ARGS, { ablesungen: [BEANTWORTET] }) |
e.status 'fertig', Spitze Plankritik/opus gleich 2, e.verbrauch[0].status 'abgewichen', eine Warnzeile im Protokoll |
Abweichung bei der letzten Ablesung: Status abgewichen im Ergebnis |
PK(PK_ARGS, { ablesungen: [undefined, undefined, BLOCKIERT] }) |
e.status 'fertig', e.verbrauch[2].status 'abgewichen', e.verbrauch[0].status 'ok', eine Warnzeile |
Sonst änderst du an faelle_workflows.mjs nichts.
3 mutanten_workflows.py
Diese Einträge in MUTANTEN, direkt nach ("verbrauch", "5-Stunden-Regex unverankert", ...):
("verbrauch", "Abweichung nicht erkannt", "if (abgewichen(ablesung)) {", "if (false) {"),
("verbrauch", "unbekannter Status gilt als bekannt", " if (!STATUS_BEKANNT.includes(a.status)) return true\n", ""),
("verbrauch", "Bericht in plan bei status fehler uebersehen", "return a.status === 'fehler' && typeof a.plan === 'string' && a.plan.trim() !== ''", "return false"),
("verbrauch", "ehrlicher Fehler gilt als Abweichung", "'unavailable', 'fehler']", "'unavailable']"),
("verbrauch", "Abweichung als nicht_gelesen", "return ohneAblesung('abgewichen',", "return ohneAblesung('nicht_gelesen',"),
("verbrauch", "Warnzeile fehlt", "log(`WARNUNG Verbrauch ${args.anlass}: Der Ableser", "String(`WARNUNG Verbrauch ${args.anlass}: Der Ableser"),
("verbrauch", "status ungekuerzt im grund", ".trim().slice(0, 160)", ".trim()"),
("verbrauch", "Brueckensatz fehlt", "Diese Ablesung gehört zur Nutzeranfrage und widerspricht ihr nicht: Sie entscheidet, wie viele Prüfagenten für die Anfrage gleichzeitig laufen dürfen. Die Anfrage selbst bearbeiten andere Agenten nach dir; du bearbeitest sie nicht, auch nicht teilweise, und liest dafür keine Dateien.\n", ""),
Prüfen
Mit S wie oben, je Befehl Ausgabe und Exit-Code in den Bericht:
# Neue Fälle gegen den neuen Stand: alle grün
node "$S/wp-neu/faelle_workflows.mjs" "$S/wf-neu"; echo "EXIT $?"
# Rotlauf: neue Fälle gegen den alten Stand; die Gegenproben ehrlicher Fehlschlag und not_applicable bleiben grün, die übrigen neuen Fälle scheitern
node "$S/wp-neu/faelle_workflows.mjs" "D:/Claude/.claude/workflows" | grep -v "^OK"; echo "EXIT ${PIPESTATUS[0]}"
# Mutanten gegen den neuen Stand: kein UEBERLEBT, kein VERALTET (läuft einige Minuten)
python "$S/wp-neu/mutanten_workflows.py" "$S/wf-neu" | grep -v "^GEFANGEN"; echo "EXIT ${PIPESTATUS[0]}"
Melde am Ende: geänderte Dateien, die drei Ausgaben, und was du anders gemacht hast als beauftragt und warum.