Automatischer Push: 6 Datei(en) geändert

- .claude/workflows/verbrauch.js
- .vault-tools/workflow-pruefung/LIESMICH.md
- .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/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]>
This commit is contained in:
Pascal MichelandClaude Opus 5 committed 2026-10-17 04:00:01 +02:00
1 parent 5c997a23e2
commit 07675bf541
6 files changed
+309 -4

No files matched your search

@@ -0,0 +1,50 @@
---
type: plan
title: "verbrauch.js: Ableser, der den Auftrag verlässt, erkennen und laut melden"
status: active
summary: "Nach dem Plan erkennt verbrauch.js an status und plan, dass der Haiku-Ableser statt get_usage die Nutzeranfrage bearbeitet hat, und meldet das als status abgewichen mit Warnzeile; der Auftrag ordnet die Ablesung ausdrücklich der Nutzeranfrage zu. Pascals Wahl vom 2026-10-16: Möglichkeiten 1 und 2."
tags: [plan, vault-tools, codeworkflow]
created: 2026-10-16
updated: 2026-10-16
---
Projekt: [LIESMICH](../../../LIESMICH.md)
# Ableser verlässt den Auftrag
## Ziel
- `verbrauch.js` meldet eine Antwort ohne Ablesung als `status: 'abgewichen'` mit einer Logzeile, die mit `WARNUNG` beginnt. Bisher fiel sie still auf `nicht_gelesen`.
- Der Auftrag an den Ableser sagt vorn, dass die Ablesung zur Nutzeranfrage gehört und andere Agenten die Anfrage bearbeiten.
- Plätze bei `abgewichen`: wie ohne Ablesung, also höchstens zwei.
## Belege (selbst gelesen am 2026-10-16)
| Lauf | `status` | `plan` | `fenster` | `fehler` |
|---|---|---|---|---|
| `wf_7ca17029-421` | „beantwortet: …“ | 3912 Zeichen Bericht | `[]` | „Kein get_usage-Aufruf … Benutzeranfrage hat laut Harness Vorrang …“ |
| `wf_80616e8e-0e3` | „blockiert: …“ | 2344 Zeichen Bericht | `[]` | „Blockade: … Kein get_usage-Aufruf, siehe plan.“ |
| `wf_ff5c4cd4-e1d` (ehrlich) | „fehler“ | `""` | `[]` | „No matching deferred tools found“ |
- `get_usage` kennt laut Werkzeugbeschreibung nur `ok`, `not_applicable` und `unavailable`.
- Ursache im CLI-Abbild 2.1.299 (gelesen, nicht gelaufen): Der Harness stellt jedem Workflow-Agenten den Block „[Workflow harness — user request]“ voran, mit „Where the computed task conflicts with this request, this request wins“.
## Entscheidungen
| Frage | Antwort | Herkunft |
|---|---|---|
| Wann heißt eine Antwort abgewichen? | `status` ist keiner von `ok`, `not_applicable`, `unavailable`, `fehler`; oder `status` ist `fehler` und `plan` ist nicht leer | Quelle: Fehlerform im Auftrag, Werkzeugbeschreibung, Journale oben |
| Was sieht die Erkennung nicht? | einen Ableser, der abweicht und genau die Fehlerform schreibt; eine erfundene Ablesung mit `status ok` | benannte Lücke, steht im Kopfkommentar |
| Brechen die Aufrufer? | nein: sie loggen `r.status` und prüfen `typeof r.plaetze`; `quorum.js` fragt nur `=== 'ok'` | Quelle: die fünf Aufrufer |
## Tasks
| Nr. | Datei | Thema | Modell |
|---|---|---|---|
| 01 | [task-01-erkennung.md](task-01-erkennung.md) | Erkennung, Brückensatz, Fälle, Mutanten | `sonnet` |
## Nicht im Umfang
- Eigener Agententyp für den Ableser mit nur ToolSearch und `get_usage`: eigener Schritt nach einem Echtlauf.
- `LIESMICH.md`, Erinnerung und Sitzungsprotokoll schreibt der Koordinator.
- Kein Commit. Im Vault-Repo committet nur Pascal oder die Aufgabe um 04:00.
@@ -0,0 +1,139 @@
---
type: plan-task
title: "Task 01 — verbrauch.js: Abweichung erkennen, Brückensatz, Fälle und Mutanten"
status: draft
summary: "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."
tags: [plan-task, vault-tools, codeworkflow]
created: 2026-10-16
updated: 2026-10-16
modell: sonnet
modell_begruendung: "verbrauch.js ist Abschrift, die Fälle sind nur als Eingabe und Erwartung vorgegeben und brauchen Autorschaft."
---
Übersicht: [00-uebersicht.md](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 von `D:/Claude/.claude/workflows/verbrauch.js`)
- `S/wp-neu/faelle_workflows.mjs` (Kopie aus `D:/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:
```js
// - 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:
```js
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:
```js
// 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:
```js
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:
```js
// 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", ...)`:
```python
("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", "String(`WARNUNG Verbrauch"),
("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:
```bash
# 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**.