Files
claude-werkzeuge/.vault-tools/workflow-pruefung/docs/plans/2026-09-24-parallelitaet/task-09-nachbesserung-pruefung.md
T
Pascal MichelandClaude Opus 5.5 fa1c26b407 Erste Fassung: Claude-Werkzeuge aus dem Vault
.vault-tools (ohne trading-plattform-pruefung und watermarks-remover),
.claude/agents, .claude/skills, .claude/workflows, .claude/settings.json.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 11:27:59 +02:00

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.
plan-task
vault-tools
codeworkflow
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.js weist doppelte Linsen ab. welle-mit-pruefung.js meldet status: ohne_pruefung, wenn die Prüfung übersprungen wurde oder scheiterte. planung.js vergleicht 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.js in welle-mit-pruefung und 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.