- .claude/agents/planer.md - .claude/skills/plan-executer-pruefung/SKILL.md - .claude/workflows/plankritik.js - .claude/workflows/planung.js - .claude/workflows/pruefung.js - .claude/workflows/verbrauch.js - .claude/workflows/welle-mit-pruefung.js - .vault-tools/plan-kopie/LIESMICH.md - .vault-tools/plan-kopie/plan_zeichen.py - .vault-tools/plan-kopie/rot_nachweis.py - .vault-tools/trading-plattform-pruefung/LIESMICH.md - .vault-tools/trading-plattform-pruefung/abendkontrolle.py - … und 34 weitere Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py. Co-Authored-By: Claude Opus 5 <[email protected]>
17 KiB
type, title, status, summary, tags, created, updated, modell, effort, modell_begruendung
| type | title | status | summary | tags | created | updated | modell | effort | modell_begruendung | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| plan-task | Task 09 — Nachbesserung nach der Prüfung: Fälle für die Reset-Toleranz und kleine Lücken | draft | Delta nach Welle 1 und 2 aus der Prüfung wf_e0294c82-76c: Regressionsfälle und Mutanten für die Reset-Toleranz, doppelte Linsen abweisen, Status ohne_pruefung, Dateiname mit Pfadgrenze, Kindphase mit Nummer, Fälle für den Nachlesetakt, den Lesehinweis, fehlendes verbrauch.js und das verankerte 5-Stunden-Label. |
|
2026-09-24 | 2026-09-24 | sonnet | low | Abschrift: alle Aus-wird-Blöcke stehen wörtlich im Plan, Zieldateien und Verbote sind genannt. Sonnet low statt Haiku, weil Blöcke die Zeichen · und ▸ tragen und Haiku in der Messung vom 2026-09-23 typografische Zeichen still ersetzt hat. |
Task 09 — Nachbesserung nach der Prüfung
Die globalen Vorgaben stehen in 00-uebersicht.md (Abschnitt „Globale Vorgaben“). Arbeitsverzeichnis ist der Vault-Wurzelordner D:/Claude; alle Pfade gelten von dort. Die Tasks 02 bis 07 sind ausgeführt und bleiben byte-gleich; diese Nachbesserung ändert die Dateien nur an den Stellen unten. Jeder Aus-Block steht genau einmal in seiner Datei.
Was danach anders ist:
- Die Reset-Toleranz hat Fälle für ihren Wert: Verschiebung um 4:59 (dasselbe Fenster), um 5:01 nach vorn und nach hinten (Reset), um fünf Stunden bei steigendem Wert (Reset). Die Mutanten 6 Stunden, 1 Sekunde und „nur nach vorn“ werden gefangen.
plankritik.jsweist doppelte Linsen ab.welle-mit-pruefung.jsmeldetstatus: ohne_pruefung, wenn die Prüfung übersprungen wurde oder scheiterte.planung.jsvergleicht den Dateinamen des Planer-Ergebnisses mit Pfadgrenze.- Die Attrappe nummeriert wiederholte Kinder wie das Ziel (
▸ name #2). - Neue Fälle für den Nachlesetakt, den Lesehinweis im Planerauftrag, ein fehlendes
verbrauch.jsinwelle-mit-pruefungund das verankerte 5-Stunden-Label, dazu die Mutanten dafür.
Zieldateien
.claude/workflows/plankritik.js(geändert).claude/workflows/planung.js(geändert).claude/workflows/welle-mit-pruefung.js(geändert).vault-tools/workflow-pruefung/attrappe.mjs(geändert).vault-tools/workflow-pruefung/faelle_workflows.mjs(geändert).vault-tools/workflow-pruefung/mutanten_workflows.py(geändert).vault-tools/workflow-pruefung/faelle_verbrauch_reihe.py(geändert).vault-tools/workflow-pruefung/mutanten_reihe.py(geändert)
Verbote
- Keine andere Datei.
- Kein Commit, kein Push, kein Lauf eines echten Workflows.
- Kein Umformulieren; ein Widerspruch zwischen Plan und Baum wird gemeldet.
Umsetzung
.claude/workflows/plankritik.js, Stelle 1
Aus:
if (unbekannt.length) throw new Error('plankritik: unbekannte Linse: ' + unbekannt.join(', ') + '; bekannt: ' + Object.keys(LINSEN).join(', '))
if (a.effort !== undefined && !EFFORTS.includes(a.effort)) throw new Error('plankritik: effort "' + a.effort + '" ungültig')
wird:
if (unbekannt.length) throw new Error('plankritik: unbekannte Linse: ' + unbekannt.join(', ') + '; bekannt: ' + Object.keys(LINSEN).join(', '))
if (a.linsen && new Set(a.linsen).size !== a.linsen.length) throw new Error('plankritik: eine Linse steht doppelt in linsen: ' + a.linsen.join(', '))
if (a.effort !== undefined && !EFFORTS.includes(a.effort)) throw new Error('plankritik: effort "' + a.effort + '" ungültig')
.claude/workflows/planung.js, Stelle 1
Aus:
laufend.delete(nr)
const passt = roh && typeof roh.datei === 'string' && roh.datei.replace(/\\/g, '/').endsWith(jeNr.get(nr).datei)
const r = passt ? roh : null
wird:
laufend.delete(nr)
const passt = roh && typeof roh.datei === 'string' && ('/' + roh.datei.replace(/\\/g, '/')).endsWith('/' + jeNr.get(nr).datei)
const r = passt ? roh : null
.claude/workflows/welle-mit-pruefung.js, Stelle 1
Aus:
return {
status: 'fertig',
kopie,
wird:
return {
status: pruefung ? 'fertig' : 'ohne_pruefung',
kopie,
.vault-tools/workflow-pruefung/attrappe.mjs, Stelle 1
Aus:
// "nesting is limited to one level"; die Attrappe setzt einen Doppelpunkt statt des Strichs.
// - Im Kind ist phase() wirkungslos, und jeder agent() bekommt die Phase "▸ <meta.name>".
// - workflow() mit unbekanntem Namen oder unlesbarem scriptPath wirft.
wird:
// "nesting is limited to one level"; die Attrappe setzt einen Doppelpunkt statt des Strichs.
// - Im Kind ist phase() wirkungslos, und jeder agent() bekommt die Phase "▸ <meta.name>", ab dem
// zweiten Aufruf desselben Kindes "▸ <meta.name> #<n>" (Bundle 2.1.280 und meta.json eines
// echten Laufs mit drei Ablesungen: "▸ verbrauch", "▸ verbrauch #2", "▸ verbrauch #3").
// - workflow() mit unbekanntem Namen oder unlesbarem scriptPath wirft.
.vault-tools/workflow-pruefung/attrappe.mjs, Stelle 2
Aus:
const laufendJePhase = {}
let uhr = 0
wird:
const laufendJePhase = {}
const kindAufrufe = {}
let uhr = 0
.vault-tools/workflow-pruefung/attrappe.mjs, Stelle 3
Aus:
const { name, fn } = lade(datei)
const kindPhase = tiefe >= 1 ? '▸ ' + name : null
let aktuellePhase = null
wird:
const { name, fn } = lade(datei)
let kindPhase = null
if (tiefe >= 1) {
kindAufrufe[name] = (kindAufrufe[name] || 0) + 1
kindPhase = '▸ ' + name + (kindAufrufe[name] > 1 ? ' #' + kindAufrufe[name] : '')
}
let aktuellePhase = null
.vault-tools/workflow-pruefung/faelle_workflows.mjs, Stelle 1
Aus:
// Exit 0, wenn alle Fälle bestehen, sonst 1.
import { mkdtempSync, writeFileSync, rmSync } from 'node:fs'
import os from 'node:os'
wird:
// Exit 0, wenn alle Fälle bestehen, sonst 1.
import { mkdtempSync, writeFileSync, rmSync, cpSync } from 'node:fs'
import os from 'node:os'
.vault-tools/workflow-pruefung/faelle_workflows.mjs, Stelle 2
Aus:
soll(JSON.stringify(p.phasen) === '["Oben"]', 'phase() im Kind hat gewirkt: ' + JSON.stringify(p.phasen))
return fehler
wird:
soll(JSON.stringify(p.phasen) === '["Oben"]', 'phase() im Kind hat gewirkt: ' + JSON.stringify(p.phasen))
return fehler
})
fall('attrappe', 'dasselbe Kind zweimal: ▸ name und ▸ name #2', async () => {
const { fehler, soll } = pruefe()
const kind = skript('kindzwei', "return await agent('x', { label: 'werkzeug:planwerkzeuge', model: 'sonnet' })")
const { protokoll: p } = await A(skript('elternzwei', `await workflow({ scriptPath: ${JSON.stringify(kind)} }, {}); return await workflow({ scriptPath: ${JSON.stringify(kind)} }, {})`))
soll(JSON.stringify(p.agents.map(a => a.phase)) === '["▸ kindzwei","▸ kindzwei #2"]', 'Phasen: ' + JSON.stringify(p.agents.map(a => a.phase)))
return fehler
.vault-tools/workflow-pruefung/faelle_workflows.mjs, Stelle 3
Aus:
fall('verbrauch', 'Woche aller Modelle 90 % zählt auch neben einer niedrigen Opus-Woche', async () => {
wird:
fall('verbrauch', 'ein Label mit "hour" in der Mitte ist kein 5-Stunden-Fenster', async () => {
const { fehler, soll } = pruefe()
const { ergebnis: e } = await V({ anlass: 't', wunsch: 4, probe: ablesung(10, 10, [{ label: 'Weekly · Opus hours', percentUsed: 90, resetsAt: 'z' }]) })
soll(e && e.plaetze === 1 && e.fuenf_stunden.prozent === 10, JSON.stringify(e))
return fehler
})
fall('verbrauch', 'Woche aller Modelle 90 % zählt auch neben einer niedrigen Opus-Woche', async () => {
.vault-tools/workflow-pruefung/faelle_workflows.mjs, Stelle 4
Aus:
fall('plankritik', 'Linse ohne Ergebnis steht in ohne_ergebnis', async () => {
wird:
fall('plankritik', 'doppelte Linse wirft vor dem ersten Agenten', async () => {
const { fehler, soll } = pruefe()
const { fehler: f, protokoll: p } = await PK({ ...PK_ARGS, linsen: ['arithmetik', 'bezeichner', 'arithmetik'] }, {})
soll(f && /doppelt in linsen/.test(f), 'Fehler: ' + f)
soll(p.agents.length === 0, 'Agent gestartet')
return fehler
})
fall('plankritik', 'Linse ohne Ergebnis steht in ohne_ergebnis', async () => {
.vault-tools/workflow-pruefung/faelle_workflows.mjs, Stelle 5
Aus:
const { ergebnis: e, protokoll: p } = await WM(WM_ARGS, { executer: OHNE })
soll(e.status === 'fertig' && /unvollständig/.test(e.pruefung.uebersprungen), JSON.stringify(e.pruefung))
soll(mitLabel(p, 'verbrauch:').length === 0 && mitLabel(p, 'pruefung').length === 0, 'Ablesung oder Prüfung trotz Lücke')
return fehler
wird:
const { ergebnis: e, protokoll: p } = await WM(WM_ARGS, { executer: OHNE })
soll(e.status === 'ohne_pruefung' && /unvollständig/.test(e.pruefung.uebersprungen), JSON.stringify([e.status, e.pruefung]))
soll(mitLabel(p, 'verbrauch:').length === 0 && mitLabel(p, 'pruefung').length === 0, 'Ablesung oder Prüfung trotz Lücke')
return fehler
})
fall('welle-mit-pruefung', 'verbrauch.js fehlt: Ablesungen nicht_gelesen, Welle und Prüfung bleiben', async () => {
const { fehler, soll } = pruefe()
const ohneVerbrauch = mkdtempSync(path.join(os.tmpdir(), 'ohne-verbrauch-'))
cpSync(ORDNER, ohneVerbrauch, { recursive: true })
rmSync(path.join(ohneVerbrauch, 'verbrauch.js'))
const { ergebnis: e, fehler: f } = await fuehreAus(path.join(ohneVerbrauch, 'welle-mit-pruefung.js'), WM_ARGS, antworten({}), { ordner: ohneVerbrauch })
rmSync(ohneVerbrauch, { recursive: true, force: true })
soll(f === null && e.status === 'fertig' && e.welle && e.pruefung.zaehlung, 'Fehler/Ergebnis: ' + f + ' ' + JSON.stringify(e && e.status))
soll(e && e.verbrauch.length === 2 && e.verbrauch.every(v => v.status === 'nicht_gelesen'), JSON.stringify(e && e.verbrauch))
return fehler
.vault-tools/workflow-pruefung/faelle_workflows.mjs, Stelle 6
Aus:
fall('planung', '5 Stunden bei 60 %: höchstens zwei gleichzeitig', async () => {
wird:
fall('planung', 'Ergebnis mit ähnlichem Dateinamen gilt als gescheitert', async () => {
const { fehler, soll } = pruefe()
const { ergebnis: e } = await PL(PL_ARGS, { planerDatei: (nr, richtig) => (nr === 7 ? 'D:/x/plan/xtask-07-t.md' : richtig) })
soll(JSON.stringify(e.gescheitert) === '[7]', JSON.stringify(e.gescheitert))
return fehler
})
fall('planung', 'Nachlesen im Takt von nachlesen_alle, solange Tasks offen sind', async () => {
const { fehler, soll } = pruefe()
const { protokoll: p } = await PL({ ...PL_ARGS, tasks: FREI, plaetze: 2, nachlesen_alle: 2 }, { planerDauer: () => 100 })
const ab = mitLabel(p, 'verbrauch:').map(x => x.label.slice('verbrauch:planung:'.length))
soll(JSON.stringify(ab) === '["Anfang","nach 2 Tasks","nach 4 Tasks","nach 6 Tasks","Ende"]', 'Ablesungen: ' + JSON.stringify(ab))
return fehler
})
fall('planung', '5 Stunden bei 60 %: höchstens zwei gleichzeitig', async () => {
.vault-tools/workflow-pruefung/faelle_workflows.mjs, Stelle 7
Aus:
soll(!/\{(NR|THEMA|DATEI|MODELL|WELLE|VORAUSSETZUNGEN)\}/.test(t5), 'Platzhalter übrig')
soll(/vor: \(keine\)/.test(planerVon(p, 1).prompt), 'Task 1 ohne "(keine)"')
wird:
soll(!/\{(NR|THEMA|DATEI|MODELL|WELLE|VORAUSSETZUNGEN)\}/.test(t5), 'Platzhalter übrig')
soll(/Lies sie, bevor du einen Namen, eine Signatur oder einen Import daraus übernimmst/.test(t5), 'Lesehinweis fehlt')
soll(!/Lies sie/.test(planerVon(p, 1).prompt), 'Lesehinweis ohne Voraussetzungen')
soll(/vor: \(keine\)/.test(planerVon(p, 1).prompt), 'Task 1 ohne "(keine)"')
.vault-tools/workflow-pruefung/mutanten_workflows.py, Stelle 1
Aus:
("planung", "Rueckfall ohne Ablesung 3", "const OHNE_ABLESUNG = 2", "const OHNE_ABLESUNG = 3"),
]
wird:
("planung", "Rueckfall ohne Ablesung 3", "const OHNE_ABLESUNG = 2", "const OHNE_ABLESUNG = 3"),
("planung", "Datei ohne Pfadgrenze", "('/' + roh.datei.replace(/\\\\/g, '/')).endsWith('/' + jeNr.get(nr).datei)", "roh.datei.replace(/\\\\/g, '/').endsWith(jeNr.get(nr).datei)"),
("planung", "Nachlesezaehler nicht zurueckgesetzt", " fertigSeitAblesung = 0\n const v = await ablesen(", " const v = await ablesen("),
("planung", "nachlesen_alle ignoriert", "const nachlesenAlle = args.nachlesen_alle || NACHLESEN_ALLE", "const nachlesenAlle = NACHLESEN_ALLE"),
("planung", "Lesehinweis fehlt", " Lies sie, bevor du einen Namen, eine Signatur oder einen Import daraus übernimmst.", ""),
("plankritik", "doppelte Linse erlaubt", " if (a.linsen && new Set(a.linsen).size !== a.linsen.length) throw", " if (false) throw"),
("welle-mit-pruefung", "status fertig ohne Pruefung", "status: pruefung ? 'fertig' : 'ohne_pruefung',", "status: 'fertig',"),
("welle-mit-pruefung", "Ablesung ohne try", " try {\n r = await workflow({ scriptPath: VERBRAUCH }, { anlass: 'welle-mit-pruefung:' + anlass, wunsch: 0 })\n } catch (e) {\n r = { status: 'nicht_gelesen', grund: 'verbrauch.js nicht ausführbar: ' + (e && e.message) }\n }", " r = await workflow({ scriptPath: VERBRAUCH }, { anlass: 'welle-mit-pruefung:' + anlass, wunsch: 0 })"),
("verbrauch", "5-Stunden-Regex unverankert", "const FUENF_STUNDEN = /^\\s*5[- ]?hour/i", "const FUENF_STUNDEN = /hour/i"),
]
.vault-tools/workflow-pruefung/faelle_verbrauch_reihe.py, Stelle 1
Aus:
def f_fallender_wert(tmp):
wird:
def f_verschiebung(tmp, reset5, erwartet):
# Nur resetsAt verschiebt sich, der Wert steigt; entscheidend ist allein die Toleranz.
baue(tmp, {"wf_v": [ablesung(1, "a", "2026-09-24T10:00:00Z", 10, 5), ablesung(2, "b", "2026-09-24T10:20:00Z", 12, 5, reset5=reset5)]})
code, aus, _ = fahre(tmp)
return [] if code == 0 and erwartet in aus else [f"Exit {code}, Ausgabe {aus[-300:]!r}"]
def f_fallender_wert(tmp):
.vault-tools/workflow-pruefung/faelle_verbrauch_reihe.py, Stelle 2
Aus:
("Absturz in einem Lauf ist ein Hinweis", f_absturz_ist_befund),
("fallender Wert im selben Fenster ist ein Reset", f_fallender_wert),
wird:
("Absturz in einem Lauf ist ein Hinweis", f_absturz_ist_befund),
("resetsAt 5 Stunden weiter, Wert steigt: Reset", lambda t: f_verschiebung(t, "2026-09-24T23:30:00Z", "| Reset | 0.0 |")),
("resetsAt 4:59 verschoben: dasselbe Fenster", lambda t: f_verschiebung(t, "2026-09-24T18:34:59Z", "| 2.0 | 0.0 |")),
("resetsAt 5:01 verschoben: Reset", lambda t: f_verschiebung(t, "2026-09-24T18:35:01Z", "| Reset | 0.0 |")),
("resetsAt 5:01 frueher: Reset", lambda t: f_verschiebung(t, "2026-09-24T18:24:59Z", "| Reset | 0.0 |")),
("fallender Wert im selben Fenster ist ein Reset", f_fallender_wert),
.vault-tools/workflow-pruefung/mutanten_reihe.py, Stelle 1
Aus:
("Reset nur bei gleichem Text", "if abs(rb - ra) > RESET_TOLERANZ or b[0] < a[0]:", "if a[1] != b[1] or b[0] < a[0]:"),
("fallender Wert kein Reset", "if abs(rb - ra) > RESET_TOLERANZ or b[0] < a[0]:", "if abs(rb - ra) > RESET_TOLERANZ:"),
wird:
("Reset nur bei gleichem Text", "if abs(rb - ra) > RESET_TOLERANZ or b[0] < a[0]:", "if a[1] != b[1] or b[0] < a[0]:"),
("Toleranz 6 Stunden", "RESET_TOLERANZ = timedelta(minutes=5)", "RESET_TOLERANZ = timedelta(hours=6)"),
("Toleranz 1 Sekunde", "RESET_TOLERANZ = timedelta(minutes=5)", "RESET_TOLERANZ = timedelta(seconds=1)"),
("Toleranz nur nach vorn", "if abs(rb - ra) > RESET_TOLERANZ or b[0] < a[0]:", "if rb - ra > RESET_TOLERANZ or b[0] < a[0]:"),
("fallender Wert kein Reset", "if abs(rb - ra) > RESET_TOLERANZ or b[0] < a[0]:", "if abs(rb - ra) > RESET_TOLERANZ:"),
Verifikation
Im Vault-Wurzelordner:
node .vault-tools/workflow-pruefung/faelle_workflows.mjs
Erwartet: Alle übrigen Zeilen beginnen mit OK, die letzte enthält 0 gescheitert, Exit 0.
python .vault-tools/workflow-pruefung/faelle_verbrauch_reihe.py
Erwartet: Die letzte Zeile enthält 0 gescheitert, Exit 0.
python .vault-tools/workflow-pruefung/mutanten_reihe.py
Erwartet: Die letzte Zeile enthält 0 ueberlebt, 0 veraltet, Exit 0.
python .vault-tools/workflow-pruefung/mutanten_workflows.py
Erwartet: Die letzte Zeile enthält 0 ueberlebt, 0 veraltet, Exit 0. Der Lauf dauert einige Minuten.
Danach git status --porcelain -- .claude/workflows/plankritik.js .claude/workflows/planung.js .claude/workflows/welle-mit-pruefung.js .vault-tools/workflow-pruefung/attrappe.mjs .vault-tools/workflow-pruefung/faelle_workflows.mjs .vault-tools/workflow-pruefung/mutanten_workflows.py .vault-tools/workflow-pruefung/faelle_verbrauch_reihe.py .vault-tools/workflow-pruefung/mutanten_reihe.py zeigen.