Abgleich mit dem Vault-Stand a201514
16 Datei(en) geändert. Erzeugt von .vault-tools/auto-push/werkzeuge_spiegel.py.
This commit is contained in:
1 parent
fb8bc625e3
commit
4d90e6be60
16 files changed
+781
-36
No files matched your search
@@ -5,7 +5,7 @@ title: "Workflow-Prüfung: Attrappe, Fälle und Messreihe zum Verbrauch"
|
||||
summary: "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."
|
||||
tags: [vault-tools, codeworkflow]
|
||||
created: 2026-09-24
|
||||
updated: 2026-10-16
|
||||
updated: 2026-10-17
|
||||
---
|
||||
|
||||
# Workflow-Prüfung
|
||||
@@ -21,7 +21,7 @@ Die Regel dazu steht in [[AI/Regelwerk/codeworkflow|codeworkflow.md]], Abschnitt
|
||||
|
||||
## 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ß. 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.
|
||||
`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.
|
||||
|
||||
@@ -40,6 +40,7 @@ Stand 2026-09-24 nach Plankritik, Prüfung und Nachbesserung. Die Zahlen gelten
|
||||
- **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.
|
||||
|
||||
**Offen:** Die Trading-Sitzung hat `plankritik.js` am 2026-09-24 nach einem echten Lauf nachgebessert (Ausgabe der Planwerkzeuge nur bei `EXIT 0`). Für diese Stelle gibt es noch keinen Fall.
|
||||
|
||||
|
||||
@@ -14,16 +14,25 @@
|
||||
// - agent() mit schema braucht type object und properties, required muss in properties stehen.
|
||||
// Ein Ergebnis ohne die required-Felder wird wie ein gescheiterter Agent zu null.
|
||||
// - parallel() ist eine Barriere; ein werfender Thunk wird zu null.
|
||||
// - agent() mit einem agentType, den die Sitzung nicht kennt, wirft vor dem Start (CLI-Abbild
|
||||
// 2.1.299). Bekannt sind die Agentendateien unter .claude/agents/ des Vaults oder optionen.agenten.
|
||||
// Zusätzlich als Verstoß protokolliert (Stamm, "Agenten & Modelle"): agent() ohne model.
|
||||
// Was die Attrappe nicht nachbildet: die Obergrenze gleichzeitiger Agenten je Lauf, Budget,
|
||||
// Resume und das Verhalten echter Modelle. Sie ist ein Fangnetz für die Steuerlogik der
|
||||
// Skripte, kein Nachweis für einen echten Lauf.
|
||||
import { readFileSync, existsSync } from 'node:fs'
|
||||
import { readFileSync, existsSync, readdirSync } from 'node:fs'
|
||||
import path from 'node:path'
|
||||
|
||||
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
|
||||
// Aufrufe über den echten Pfad werden in den Ordner unter Test umgeleitet.
|
||||
const ECHTER_ORDNER = 'D:/Claude/.claude/workflows/'
|
||||
// Agententypen wie in der Sitzung: die Agentendateien des Vaults neben den Workflows. Fehlt der
|
||||
// Ordner, ist jeder agentType unbekannt und jeder Fall damit rot: ein Befund, kein Durchlass.
|
||||
const AGENTEN_ORDNER = path.join(ECHTER_ORDNER, '..', 'agents')
|
||||
function agentenDesVaults() {
|
||||
if (!existsSync(AGENTEN_ORDNER)) return []
|
||||
return readdirSync(AGENTEN_ORDNER).filter(n => n.endsWith('.md')).map(n => n.slice(0, -3))
|
||||
}
|
||||
|
||||
class DatumAttrappe extends Date {
|
||||
constructor(...a) {
|
||||
@@ -51,6 +60,7 @@ const warte = ms => new Promise(r => setTimeout(r, ms))
|
||||
// aufruf trägt label, phase, modell, effort, agentType, prompt, tiefe und schema.
|
||||
export async function fuehreAus(datei, args, antworte, optionen = {}) {
|
||||
const ordner = optionen.ordner || path.dirname(datei)
|
||||
const agenten = optionen.agenten || agentenDesVaults()
|
||||
const protokoll = { agents: [], logs: [], phasen: [], verstoesse: [], spitze: {}, spitzeJePhase: {}, workflows: [] }
|
||||
const laufend = {}
|
||||
const laufendJePhase = {}
|
||||
@@ -82,6 +92,7 @@ export async function fuehreAus(datei, args, antworte, optionen = {}) {
|
||||
if (!opts.schema || opts.schema.type !== 'object' || !opts.schema.properties) throw new Error('Schema braucht type object und properties: ' + opts.label)
|
||||
if ((opts.schema.required || []).some(k => !(k in opts.schema.properties))) throw new Error('required nicht in properties: ' + opts.label)
|
||||
}
|
||||
if (opts.agentType != null && !agenten.includes(String(opts.agentType))) throw new Error(`agent({agentType}): agent type '${opts.agentType}' not found. Available agents: ${agenten.join(', ')}`)
|
||||
const modell = opts.model || '(erbt)'
|
||||
const phase = kindPhase || opts.phase || aktuellePhase || '(ohne)'
|
||||
const eintrag = { label: opts.label || null, phase, modell, effort: opts.effort, agentType: opts.agentType, prompt, tiefe, start: ++uhr, ende: null, ergebnis: undefined }
|
||||
|
||||
+3
-2
@@ -5,7 +5,7 @@ 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
|
||||
updated: 2026-10-17
|
||||
---
|
||||
|
||||
Projekt: [LIESMICH](../../../LIESMICH.md)
|
||||
@@ -42,9 +42,10 @@ Projekt: [LIESMICH](../../../LIESMICH.md)
|
||||
| Nr. | Datei | Thema | Modell |
|
||||
|---|---|---|---|
|
||||
| 01 | [task-01-erkennung.md](task-01-erkennung.md) | Erkennung, Brückensatz, Fälle, Mutanten | `sonnet` |
|
||||
| 02 | [task-02-agententyp.md](task-02-agententyp.md) | Ableser als Agententyp `verbrauch-ableser`, Startfehler abfangen, Attrappe prüft `agentType` | `sonnet` |
|
||||
|
||||
## Nicht im Umfang
|
||||
|
||||
- Eigener Agententyp für den Ableser mit nur ToolSearch und `get_usage`: eigener Schritt nach einem Echtlauf.
|
||||
- Task 02 (Möglichkeit 5, Agententyp mit nur ToolSearch und `get_usage`) kam am 2026-10-17 auf Pascals Auftrag dazu. Die Agentendatei und die Zeile in der Rollentabelle legt der Koordinator an, und vor Task 02 läuft ein Echtlauf über das Workflow-Werkzeug.
|
||||
- `LIESMICH.md`, Erinnerung und Sitzungsprotokoll schreibt der Koordinator.
|
||||
- Kein Commit. Im Vault-Repo committet nur Pascal oder die Aufgabe um 04:00.
|
||||
+1
-1
@@ -118,7 +118,7 @@ Diese Einträge in `MUTANTEN`, direkt nach `("verbrauch", "5-Stunden-Regex unver
|
||||
("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", "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", ""),
|
||||
```
|
||||
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
---
|
||||
type: plan-task
|
||||
title: "Task 02 — verbrauch.js: Ableser als Agententyp verbrauch-ableser, Startfehler abfangen, Attrappe prüft agentType"
|
||||
status: draft
|
||||
summary: "Der Ableser läuft als agentType verbrauch-ableser mit nur ToolSearch und get_usage; ein Startfehler, etwa ein in der Sitzung noch unbekannter Typ, kommt als nicht_gelesen mit Warnzeile zurück statt als Absturz. Die Attrappe wirft wie das Ziel bei einem unbekannten agentType."
|
||||
tags: [plan-task, vault-tools, codeworkflow]
|
||||
created: 2026-10-16
|
||||
updated: 2026-10-17
|
||||
modell: sonnet
|
||||
modell_begruendung: "verbrauch.js und attrappe.mjs sind Abschrift, die Fälle brauchen Autorschaft."
|
||||
---
|
||||
|
||||
Übersicht: [00-uebersicht.md](00-uebersicht.md)
|
||||
|
||||
# Task 02 — Agententyp verbrauch-ableser
|
||||
|
||||
Pascals Auftrag vom 2026-10-17: Möglichkeit 5 umsetzen. Die Agentendatei `D:/Claude/.claude/agents/verbrauch-ableser.md` und die Zeile in der Rollentabelle des Stamms hat der Koordinator angelegt. Voraussetzung ist der Stand von `verbrauch.js` nach Task 01 (Erkennung `abgewichen`, Brückensatz, `kurz`); er ist seit dem 2026-10-17 eingespielt.
|
||||
|
||||
## Arbeitsorte
|
||||
|
||||
Wie Task 01, `S` gleich. Du schreibst **nur**:
|
||||
|
||||
- `S/wf-neu/verbrauch.js`
|
||||
- `S/wp-neu/attrappe.mjs`
|
||||
- `S/wp-neu/faelle_workflows.mjs`
|
||||
- `S/wp-neu/mutanten_workflows.py`
|
||||
|
||||
Nichts unter `D:/Claude/` anfassen. Keine Hilfsdateien. Kein Commit.
|
||||
|
||||
## Belege
|
||||
|
||||
- Ziel, CLI-Abbild 2.1.299 (gelesen, nicht gelaufen): `agent()` mit einem `agentType`, den die Sitzung nicht kennt, wirft `agent({agentType}): agent type '<typ>' not found. Available agents: ...`, bevor ein Agent startet.
|
||||
- Stamm, „Agenten & Modelle": Mit `agentType` liefert dessen Frontmatter den Effort; ein `effort`-Parameter daneben steht nur für eine bewusste Abweichung.
|
||||
- Echtlauf 2026-10-17, `wf_63cb007d-71b`: Solange die Sitzung den Typ nicht kannte, warf `agent()` genau diese Meldung, nach 145 ms und ohne Agent.
|
||||
- Echtlauf 2026-10-17, `wf_1901f51f-dd3`, drei Ablesungen mit `agentType: 'verbrauch-ableser'`: Alle drei liefen als `verbrauch-ableser` auf `claude-haiku-5-5` mit Effort `low` und riefen nur ToolSearch, `get_usage` und StructuredOutput auf. Als nachladbares Werkzeug war nur `get_usage` angeboten. Die Werte stimmten mit der eigenen Ablesung des Koordinators überein (36 % und 53 %). Der Lauf startete in einem Zug ohne Nutzernachricht, der Ableser sah also keine abweichende Nutzeranfrage.
|
||||
|
||||
## 1 verbrauch.js
|
||||
|
||||
**1a, Kopfkommentar:** Vor der Zeile `// Was das Skript nicht sieht: Agenten, die nach der Ablesung in anderen Sitzungen starten;` kommen diese Zeilen:
|
||||
|
||||
```js
|
||||
// - Wer abliest: der Agententyp verbrauch-ableser (.claude/agents/), Haiku mit effort low und
|
||||
// nur ToolSearch und get_usage, damit ein Ableser, der der Nutzeranfrage folgt, nichts anderes
|
||||
// tun kann. Kennt die Sitzung den Typ nicht, wirft agent() vor dem Start (CLI-Abbild 2.1.299);
|
||||
// das kommt als nicht_gelesen mit WARNUNG zurück, nie als Rückfall auf einen Agenten mit allen
|
||||
// Werkzeugen.
|
||||
```
|
||||
|
||||
**1b, Aufruf:** Die Zeile
|
||||
|
||||
```js
|
||||
ablesung = await agent(AUFTRAG, { label: 'verbrauch:' + args.anlass, phase: 'Verbrauch', schema: ABLESUNG, model: 'haiku' })
|
||||
```
|
||||
|
||||
wird zu
|
||||
|
||||
```js
|
||||
try {
|
||||
ablesung = await agent(AUFTRAG, { label: 'verbrauch:' + args.anlass, phase: 'Verbrauch', schema: ABLESUNG, agentType: 'verbrauch-ableser', model: 'haiku' })
|
||||
} catch (e) {
|
||||
ablesung = null
|
||||
startfehler = kurz((e && e.message) || e)
|
||||
}
|
||||
```
|
||||
|
||||
**1c, Variable:** Die Zeile `let ablesung = args.probe` wird zu zwei Zeilen:
|
||||
|
||||
```js
|
||||
let ablesung = args.probe
|
||||
let startfehler = null
|
||||
```
|
||||
|
||||
**1d, Rückgabe:** Vor der Zeile `if (!ablesung || typeof ablesung !== 'object') return ohneAblesung('nicht_gelesen', 'kein Ergebnis vom Ableseagenten')` kommt:
|
||||
|
||||
```js
|
||||
if (startfehler) {
|
||||
log(`WARNUNG Verbrauch ${args.anlass}: Ableser nicht startbar (${startfehler}); die Bremse misst nicht.`)
|
||||
return ohneAblesung('nicht_gelesen', 'Ableser nicht startbar: ' + startfehler)
|
||||
}
|
||||
```
|
||||
|
||||
`kurz` ist in Task 01 vor `pruefeArgs(args)` angelegt und damit vor dem Aufruf definiert. Sonst änderst du an `verbrauch.js` nichts.
|
||||
|
||||
## 2 attrappe.mjs
|
||||
|
||||
Die Attrappe wirft wie das Ziel bei einem unbekannten `agentType`. Bekannt sind die Namen der Dateien `*.md` in `D:/Claude/.claude/agents/`, abgeleitet aus `ECHTER_ORDNER`, oder eine Liste aus `optionen.agenten`. Nicht relativ zur Attrappe, weil sie im Prüfstand auch als Kopie im Scratchpad läuft.
|
||||
|
||||
**2a, Kopfkommentar:** Nach der Zeile `// - parallel() ist eine Barriere; ein werfender Thunk wird zu null.` kommt:
|
||||
|
||||
```js
|
||||
// - agent() mit einem agentType, den die Sitzung nicht kennt, wirft vor dem Start (CLI-Abbild
|
||||
// 2.1.299). Bekannt sind die Agentendateien unter .claude/agents/ des Vaults oder optionen.agenten.
|
||||
```
|
||||
|
||||
**2b, Import:** `import { readFileSync, existsSync } from 'node:fs'` wird zu `import { readFileSync, existsSync, readdirSync } from 'node:fs'`.
|
||||
|
||||
**2c, Liste:** Nach der Zeile `const ECHTER_ORDNER = 'D:/Claude/.claude/workflows/'` kommt:
|
||||
|
||||
```js
|
||||
// Agententypen wie in der Sitzung: die Agentendateien des Vaults neben den Workflows. Fehlt der
|
||||
// Ordner, ist jeder agentType unbekannt und jeder Fall damit rot: ein Befund, kein Durchlass.
|
||||
const AGENTEN_ORDNER = path.join(ECHTER_ORDNER, '..', 'agents')
|
||||
function agentenDesVaults() {
|
||||
if (!existsSync(AGENTEN_ORDNER)) return []
|
||||
return readdirSync(AGENTEN_ORDNER).filter(n => n.endsWith('.md')).map(n => n.slice(0, -3))
|
||||
}
|
||||
```
|
||||
|
||||
**2d, in `fuehreAus`:** Nach der Zeile `const ordner = optionen.ordner || path.dirname(datei)` kommt `const agenten = optionen.agenten || agentenDesVaults()`.
|
||||
|
||||
**2e, in `agent()`:** Nach dem Block, der das Schema prüft (er endet mit der schließenden `}` nach `throw new Error('required nicht in properties: ' + opts.label)`), kommt:
|
||||
|
||||
```js
|
||||
if (opts.agentType != null && !agenten.includes(String(opts.agentType))) throw new Error(`agent({agentType}): agent type '${opts.agentType}' not found. Available agents: ${agenten.join(', ')}`)
|
||||
```
|
||||
|
||||
## 3 faelle_workflows.mjs
|
||||
|
||||
| Abschnitt | Name | Eingabe | Erwartung |
|
||||
|---|---|---|---|
|
||||
| `attrappe` | `unbekannter agentType wirft vor dem Start` | Skript mit `agent('x', { label: 'werkzeug:planwerkzeuge', model: 'sonnet', agentType: 'gibt-es-nicht' })` | Fehler passt auf `/agent type 'gibt-es-nicht' not found/`, `p.agents.length === 0` |
|
||||
| `attrappe` | `bekannter agentType aus optionen.agenten läuft` | dasselbe mit `agentType: 'eigen'` und `fuehreAus(..., { ordner: TMP, agenten: ['eigen'] })` | kein Fehler, ein Agent mit `agentType 'eigen'` |
|
||||
| `verbrauch` | Grundlinie ergänzen | bestehender Fall `Grundlinie: Agent liest 10/10, ...` | zusätzlich `p.agents[0].agentType === 'verbrauch-ableser'` und `p.agents[0].effort === undefined` |
|
||||
| `verbrauch` | `Ableser-Typ unbekannt: nicht_gelesen mit Warnung, kein Absturz` | `fuehreAus(WF('verbrauch'), { anlass: 't', wunsch: 3 }, antworten({}), { ordner: ORDNER, agenten: ['planer'] })` | `fehler === null`, `status 'nicht_gelesen'`, `plaetze 2`, `grund` passt auf `/nicht startbar/` und auf `/not found/`, genau eine Warnzeile, kein Agent gestartet |
|
||||
| `plankritik` | `Ableser-Typ unbekannt: Linsen zu zweit, Plankritik läuft` | `PK(PK_ARGS, {}, { agenten: ['pruefer'] })` | `e.status 'fertig'`, Spitze `Plankritik`/`opus` gleich 2, `e.verbrauch.every(v => v.status === 'nicht_gelesen')`, drei Warnzeilen |
|
||||
|
||||
Für den letzten Fall nimmt `PK` die Optionen schon als drittes Argument entgegen.
|
||||
|
||||
## 4 mutanten_workflows.py
|
||||
|
||||
Nach den Einträgen aus Task 01:
|
||||
|
||||
```python
|
||||
("verbrauch", "Ableser ohne Agententyp", "agentType: 'verbrauch-ableser', ", ""),
|
||||
("verbrauch", "Startfehler nicht abgefangen", " ablesung = null\n startfehler = kurz((e && e.message) || e)\n", " throw e\n"),
|
||||
("verbrauch", "Startfehler ohne Warnzeile", "log(`WARNUNG Verbrauch ${args.anlass}: Ableser nicht startbar", "String(`WARNUNG Verbrauch ${args.anlass}: Ableser nicht startbar"),
|
||||
("verbrauch", "Ableser erbt Sitzungseffort statt Frontmatter", "agentType: 'verbrauch-ableser', model: 'haiku' }", "agentType: 'verbrauch-ableser', model: 'haiku', effort: 'max' }"),
|
||||
```
|
||||
|
||||
**Korrektur nach dem Lauf (2026-10-17):** Der Block 1d beginnt wie die Warnzeile aus Task 01, das Muster des Mutanten „Warnzeile fehlt“ kam dadurch zweimal vor (VERALTET). Es lautet jetzt ``log(`WARNUNG Verbrauch ${args.anlass}: Der Ableser``; Task 01 ist mitgezogen.
|
||||
|
||||
## Prüfen
|
||||
|
||||
```bash
|
||||
# Alle Fälle gegen den neuen Stand
|
||||
node "$S/wp-neu/faelle_workflows.mjs" "$S/wf-neu"; echo "EXIT $?"
|
||||
# Rotlauf der neuen verbrauch- und plankritik-Fälle gegen den Stand nach Task 01 ist nicht nötig; Rotlauf gegen den alten Stand
|
||||
node "$S/wp-neu/faelle_workflows.mjs" "D:/Claude/.claude/workflows" | grep -v "^OK"; echo "EXIT ${PIPESTATUS[0]}"
|
||||
# Mutanten: kein UEBERLEBT, kein VERALTET
|
||||
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**.
|
||||
|
||||
@@ -146,6 +146,22 @@ fall('attrappe', 'agent() ohne model ist ein Verstoß', async () => {
|
||||
return fehler
|
||||
})
|
||||
|
||||
fall('attrappe', 'unbekannter agentType wirft vor dem Start', async () => {
|
||||
const { fehler, soll } = pruefe()
|
||||
const { fehler: f, protokoll: p } = await A(skript('typ-unbekannt', "return await agent('x', { label: 'werkzeug:planwerkzeuge', model: 'sonnet', agentType: 'gibt-es-nicht' })"))
|
||||
soll(f && /agent type 'gibt-es-nicht' not found/.test(f), 'Fehler: ' + f)
|
||||
soll(p.agents.length === 0, 'Agent gestartet trotz unbekanntem Typ: ' + p.agents.length)
|
||||
return fehler
|
||||
})
|
||||
|
||||
fall('attrappe', 'bekannter agentType aus optionen.agenten läuft', async () => {
|
||||
const { fehler, soll } = pruefe()
|
||||
const { fehler: f, protokoll: p } = await fuehreAus(skript('typ-bekannt', "return await agent('x', { label: 'werkzeug:planwerkzeuge', model: 'sonnet', agentType: 'eigen' })"), {}, antworten({}), { ordner: TMP, agenten: ['eigen'] })
|
||||
soll(f === null, 'Fehler: ' + f)
|
||||
soll(p.agents.length === 1 && p.agents[0].agentType === 'eigen', 'Agenten: ' + JSON.stringify(p.agents.map(x => x.agentType)))
|
||||
return fehler
|
||||
})
|
||||
|
||||
fall('attrappe', 'Ergebnis ohne required-Feld wird null und ist ein Verstoß', async () => {
|
||||
const { fehler, soll } = pruefe()
|
||||
const schema = "{ type: 'object', properties: { a: { type: 'string' }, b: { type: 'string' } }, required: ['a', 'b'] }"
|
||||
@@ -171,6 +187,7 @@ fall('verbrauch', 'Grundlinie: Agent liest 10/10, wunsch 3 ergibt 3 Plätze', as
|
||||
soll(f === null, 'Fehler: ' + f)
|
||||
soll(e && e.status === 'ok' && e.plaetze === 3 && e.gebremst === false && e.quelle === 'agent', 'Ergebnis: ' + JSON.stringify(e))
|
||||
soll(p.agents.length === 1 && p.agents[0].label === 'verbrauch:test' && p.agents[0].modell === 'haiku', 'Agent: ' + JSON.stringify(p.agents.map(x => [x.label, x.modell])))
|
||||
soll(p.agents[0].agentType === 'verbrauch-ableser' && p.agents[0].effort === undefined, 'Typ/Effort: ' + JSON.stringify([p.agents[0].agentType, p.agents[0].effort]))
|
||||
ohneVerstoss(p, soll)
|
||||
return fehler
|
||||
})
|
||||
@@ -313,6 +330,16 @@ fall('verbrauch', 'Auftrag ordnet die Ablesung der Nutzeranfrage zu', async () =
|
||||
return fehler
|
||||
})
|
||||
|
||||
fall('verbrauch', 'Ableser-Typ unbekannt: nicht_gelesen mit Warnung, kein Absturz', async () => {
|
||||
const { fehler, soll } = pruefe()
|
||||
const { ergebnis: e, fehler: f, protokoll: p } = await fuehreAus(WF('verbrauch'), { anlass: 't', wunsch: 3 }, antworten({}), { ordner: ORDNER, agenten: ['planer'] })
|
||||
soll(f === null, 'Fehler: ' + f)
|
||||
soll(e && e.status === 'nicht_gelesen' && e.plaetze === 2 && /nicht startbar/.test(e.grund) && /not found/.test(e.grund), JSON.stringify(e))
|
||||
soll(warnung(p).length === 1, 'Warnzeilen: ' + JSON.stringify(warnung(p)))
|
||||
soll(p.agents.length === 0, 'Agenten gestartet: ' + p.agents.length)
|
||||
return fehler
|
||||
})
|
||||
|
||||
for (const [name, probe] of [
|
||||
['status unavailable', { verfuegbar: true, status: 'unavailable', plan: '', fenster: [], fehler: '' }],
|
||||
['verfuegbar false', { verfuegbar: false, status: 'fehler', plan: '', fenster: [], fehler: 'Werkzeug fehlt' }],
|
||||
@@ -479,6 +506,16 @@ fall('plankritik', 'Ablesung ohne Ergebnis: Linsen zu zweit (alte Obergrenze)',
|
||||
return fehler
|
||||
})
|
||||
|
||||
fall('plankritik', 'Ableser-Typ unbekannt: Linsen zu zweit, Plankritik läuft', async () => {
|
||||
const { fehler, soll } = pruefe()
|
||||
const { ergebnis: e, protokoll: p } = await PK(PK_ARGS, {}, { agenten: ['pruefer'] })
|
||||
soll(e && e.status === 'fertig', 'status ' + (e && e.status))
|
||||
soll(spitze(p, 'Plankritik', 'opus') === 2, 'Linsen gleichzeitig: ' + spitze(p, 'Plankritik', 'opus'))
|
||||
soll(e && e.verbrauch.every(v => v.status === 'nicht_gelesen'), JSON.stringify(e && e.verbrauch.map(v => v.status)))
|
||||
soll(warnung(p).length === 3, 'Warnzeilen: ' + JSON.stringify(warnung(p)))
|
||||
return fehler
|
||||
})
|
||||
|
||||
fall('plankritik', 'Abweichung bei der ersten Ablesung: Linsen zu zweit, Status abgewichen im Ergebnis', async () => {
|
||||
const { fehler, soll } = pruefe()
|
||||
const { ergebnis: e, protokoll: p } = await PK(PK_ARGS, { ablesungen: [BEANTWORTET] })
|
||||
|
||||
@@ -82,9 +82,13 @@ MUTANTEN = [
|
||||
("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", "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", ""),
|
||||
("verbrauch", "Ableser ohne Agententyp", "agentType: 'verbrauch-ableser', ", ""),
|
||||
("verbrauch", "Startfehler nicht abgefangen", " ablesung = null\n startfehler = kurz((e && e.message) || e)\n", " throw e\n"),
|
||||
("verbrauch", "Startfehler ohne Warnzeile", "log(`WARNUNG Verbrauch ${args.anlass}: Ableser nicht startbar", "String(`WARNUNG Verbrauch ${args.anlass}: Ableser nicht startbar"),
|
||||
("verbrauch", "Ableser erbt Sitzungseffort statt Frontmatter", "agentType: 'verbrauch-ableser', model: 'haiku' }", "agentType: 'verbrauch-ableser', model: 'haiku', effort: 'max' }"),
|
||||
("plankritik", "Muster-Satz fehlt (N5)", "musterModus\n ? ' Kein Mutant ist gefahren; OK heißt hier nur, dass das Muster genau einmal in der Datei steht; ob ein Test fällt, ist unbelegt.'\n : ", ""),
|
||||
("plankritik", "Exit 2 wird wie 0 behandelt (N7)", "exitCode === 2 || exitCode === 3", "false"),
|
||||
("quorum", "Mehrheit schon bei einer Stimme", "mehrheit: beteiligt.length >= 2", "mehrheit: beteiligt.length >= 1"),
|
||||
|
||||
Reference in new issue
Block a user