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]>
This commit is contained in:
Pascal MichelandClaude Opus 5.5 committed 2026-10-14 11:27:59 +02:00
commit fa1c26b407
137 files changed
+43926

No files matched your search

@@ -0,0 +1,170 @@
---
type: plan-task
title: "Task 01 — verbrauch.js: Planverbrauch lesen und Opus-Plätze rechnen"
status: draft
summary: "Neuer gespeicherter Workflow, der über get_usage das 5-Stunden-Fenster und die Woche abliest und daraus die erlaubten Opus-Plätze rechnet; die Stufen stehen nur hier."
tags: [plan-task, vault-tools, codeworkflow]
created: 2026-09-24
updated: 2026-09-24
modell: sonnet
effort: low
modell_begruendung: "Abschrift: jede Zeile steht wörtlich im Plan, Zieldateien und Verbote sind genannt. Sonnet low statt Haiku, weil der Code das Zeichen · (U+00B7) trägt und Haiku in der Messung vom 2026-09-23 typografische Zeichen still ersetzt hat."
---
# Task 01 — verbrauch.js: Planverbrauch lesen und Opus-Plätze rechnen
Die globalen Vorgaben stehen in `00-uebersicht.md` (Abschnitt „Globale Vorgaben“). Arbeitsverzeichnis ist der Vault-Wurzelordner `D:/Claude`; alle Pfade gelten von dort.
Was danach anders ist:
- **Es gibt `verbrauch.js`.** Ein Haiku-Agent lädt `mcp__ccd_session_mgmt__get_usage` und überträgt die Fenster; das Skript ordnet sie ein (`5-hour ...`, `Weekly ... all models`, falls vorhanden `Weekly ... Opus`) und rechnet `plaetze = min(wunsch, Stufe 5 Stunden, Stufe Woche, 4)`.
- **Ohne lesbare Ablesung gilt zwei**, wie bisher im Stamm. `nicht_gelesen` und `unbekannte_fenster` sind eigene Stati, nie ein stilles Grün.
- **`wunsch: 0` misst nur** und bremst nie; `probe` ersetzt den Agenten für den Regressionslauf im echten Laufzeitsystem.
## Zieldateien
- `.claude/workflows/verbrauch.js` (neu)
## Verbote
- Keine andere Datei, auch nicht die übrigen Workflows unter `.claude/workflows/` und nichts unter `AI/Regelwerk/`, `.claude/agents/` oder `CLAUDE.md`.
- Kein Commit, kein Push, kein Lauf eines echten Workflows.
- Kein Umformulieren, auch nicht von Kommentaren oder Sonderzeichen; ein Widerspruch zwischen Plan und Baum wird gemeldet.
## Umsetzung
### `.claude/workflows/verbrauch.js`
Die ganze Datei ist neu:
```javascript
export const meta = {
name: 'verbrauch',
description: 'Liest den Planverbrauch (5-Stunden-Fenster, Woche) über get_usage und rechnet daraus, wie viele Opus-Agenten gleichzeitig laufen dürfen',
whenToUse: 'Vor jeder Opus-Staffel eines Workflows, als Kind aufgerufen: workflow({ scriptPath: "D:/Claude/.claude/workflows/verbrauch.js" }, { anlass, wunsch }). Args: {anlass, wunsch: ganze Zahl ab 0, probe?}. wunsch 0 heißt nur messen. Rückgabe {status: ok|nicht_gelesen|unbekannte_fenster, quelle, fuenf_stunden, woche, woche_opus, plaetze, gebremst, grund, fenster}. Ohne lesbare Ablesung gilt die alte Obergrenze zwei. Regel: AI/Regelwerk/codeworkflow.md, "Verbrauch und Opus-Plätze".',
phases: [{ title: 'Verbrauch', detail: 'ein Haiku-Agent liest get_usage ab, das Skript entscheidet' }],
}
// Geltungsbereich (AI/Regelwerk/pruefwerkzeuge.md): Das Skript liest den Planverbrauch und
// rechnet daraus, wie viele Opus-Agenten gleichzeitig laufen dürfen. Es ist eine Bremse, kein
// Nachweis. Woher die Antworten kommen:
// - Welche Fenster zählen und wie sie heißen: Quelle. get_usage in der Desktop-App lieferte am
// 2026-09-24 "5-hour limit", "Weekly · all models" und "Weekly · Fable", je mit percentUsed
// und resetsAt. Von 19 typisierten Limit-Abbrüchen im Session-Speicher (22.08. bis 20.09.)
// waren 16 five_hour und 3 seven_day, keiner seven_day_opus. Ein Fenster "Weekly · Opus" zählt
// trotzdem wie die Woche, falls es auftaucht, weil die Agenten, um die es geht, auf Opus laufen.
// - Die Stufen: Projektvorgabe, vorläufig (Pascal, 2026-09-24). Sie stehen nur hier und werden
// nach der Messreihe mit .vault-tools/workflow-pruefung/verbrauch_reihe.py nachgestellt.
// - Ohne lesbare Ablesung: Projektvorgabe, die bisherige Stammregel von zwei Opus-Agenten.
// Was das Skript nicht sieht: Agenten, die nach der Ablesung in anderen Sitzungen starten;
// laufende Agenten, die nach der Ablesung weiter verbrauchen; Sitzungen ohne get_usage
// (außerhalb der Desktop-App). Das Urteil rechnet das Skript, der Haiku-Agent liest nur ab.
const HARTE_OBERGRENZE = 4
const OHNE_ABLESUNG = 2
// Je Stufe [Schwelle in Prozent, Plätze unterhalb der Schwelle]; ab der letzten Schwelle 0.
const STUFEN_FUENF_STUNDEN = [[50, 4], [70, 2], [85, 1]]
const STUFEN_WOCHE = [[70, 4], [85, 2], [95, 1]]
const FUENF_STUNDEN = /^\s*5[- ]?hour/i
const WOCHE_ALLE = /^\s*weekly\b.*\ball models\b/i
const WOCHE_OPUS = /^\s*weekly\b.*\bopus\b/i
const ABLESUNG = {
type: 'object',
properties: {
verfuegbar: { type: 'boolean' },
status: { type: 'string' },
plan: { type: 'string' },
fenster: {
type: 'array',
items: {
type: 'object',
properties: { label: { type: 'string' }, percentUsed: { type: 'number' }, resetsAt: { type: 'string' } },
required: ['label', 'percentUsed', 'resetsAt'],
},
},
fehler: { type: 'string' },
},
required: ['verfuegbar', 'status', 'plan', 'fenster', 'fehler'],
}
const AUFTRAG = `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.
Übertrage aus dem Ergebnis plan.status nach status und plan.plan nach plan. Übertrage jeden Eintrag aus plan.windows mit label, percentUsed und resetsAt unverändert nach fenster, auch Einträge, die dir unwichtig erscheinen. Setze verfuegbar auf true und fehler auf "".
Ist das Werkzeug nicht verfügbar oder scheitert der Aufruf, setze verfuegbar auf false, status auf "fehler", plan auf "", fenster auf [] und schreibe die Fehlermeldung wörtlich nach fehler.
Tu sonst nichts. Übertrage das Ergebnis in die Felder des StructuredOutput-Werkzeugs.`
function pruefeArgs(a) {
if (!a || typeof a !== 'object') throw new Error('verbrauch: args fehlen')
if (typeof a.anlass !== 'string' || !a.anlass.trim()) throw new Error('verbrauch: anlass fehlt')
if (!Number.isInteger(a.wunsch) || a.wunsch < 0) throw new Error('verbrauch: wunsch muss eine ganze Zahl ab 0 sein, ist ' + JSON.stringify(a.wunsch))
if (a.probe !== undefined && (a.probe === null || typeof a.probe !== 'object' || Array.isArray(a.probe))) throw new Error('verbrauch: probe muss ein Objekt sein')
}
function stufe(prozent, stufen) {
for (const [schwelle, plaetze] of stufen) if (prozent < schwelle) return plaetze
return 0
}
// Ordnet die Fenster ein. Ein Fenster, das als 5 Stunden oder Woche erkannt wird, aber keine
// Prozentzahl von 0 bis 100 trägt, ist ein Befund und wird nicht still übergangen.
function einordnen(fenster) {
if (!Array.isArray(fenster)) return { fehler: 'fenster ist keine Liste' }
const e = { fuenf: null, woche: null, opus: null, andere: [] }
for (const f of fenster) {
if (!f || typeof f !== 'object' || typeof f.label !== 'string') return { fehler: 'Fenster ohne label: ' + JSON.stringify(f) }
const art = FUENF_STUNDEN.test(f.label) ? 'fuenf' : WOCHE_ALLE.test(f.label) ? 'woche' : WOCHE_OPUS.test(f.label) ? 'opus' : null
if (!art) { e.andere.push(f.label); continue }
const p = f.percentUsed
if (typeof p !== 'number' || !Number.isFinite(p) || p < 0 || p > 100) return { fehler: `${f.label}: percentUsed ${JSON.stringify(p)} ist keine Zahl von 0 bis 100` }
const neu = { prozent: p, zuruecksetzung: typeof f.resetsAt === 'string' ? f.resetsAt : null }
if (!e[art] || e[art].prozent < p) e[art] = neu
}
const fehlt = [!e.fuenf && '5-hour limit', !e.woche && 'Weekly all models'].filter(Boolean)
if (fehlt.length) return { fehler: 'Fenster fehlt: ' + fehlt.join(', ') + (e.andere.length ? '; gelesen: ' + e.andere.join(', ') : '') }
return e
}
pruefeArgs(args)
phase('Verbrauch')
const wunsch = args.wunsch
const deckel = wunsch > HARTE_OBERGRENZE ? `; wunsch ${wunsch} auf die harte Obergrenze ${HARTE_OBERGRENZE} gesenkt` : ''
let quelle = 'probe'
let ablesung = args.probe
if (ablesung === undefined) {
quelle = 'agent'
ablesung = await agent(AUFTRAG, { label: 'verbrauch:' + args.anlass, phase: 'Verbrauch', schema: ABLESUNG, model: 'haiku' })
}
function ohneAblesung(status, grund) {
const plaetze = Math.min(wunsch, OHNE_ABLESUNG)
log(`Verbrauch ${args.anlass}: ${status} (${grund}); ${plaetze} Plätze nach der alten Obergrenze`)
return { status, quelle, fuenf_stunden: null, woche: null, woche_opus: null, plaetze, gebremst: false, grund: grund + deckel, fenster: ablesung && Array.isArray(ablesung.fenster) ? ablesung.fenster : null }
}
if (!ablesung || typeof ablesung !== 'object') return ohneAblesung('nicht_gelesen', 'kein Ergebnis vom Ableseagenten')
if (ablesung.verfuegbar !== true || ablesung.status !== 'ok') return ohneAblesung('nicht_gelesen', `get_usage: verfuegbar ${ablesung.verfuegbar}, status ${ablesung.status}${ablesung.fehler ? ', ' + ablesung.fehler : ''}`)
const e = einordnen(ablesung.fenster)
if (e.fehler) return ohneAblesung('unbekannte_fenster', e.fehler)
const wocheProzent = Math.max(e.woche.prozent, e.opus ? e.opus.prozent : 0)
const grenzeFuenf = stufe(e.fuenf.prozent, STUFEN_FUENF_STUNDEN)
const grenzeWoche = stufe(wocheProzent, STUFEN_WOCHE)
const plaetze = Math.min(wunsch, grenzeFuenf, grenzeWoche, HARTE_OBERGRENZE)
const gebremst = wunsch > 0 && plaetze === 0
const grund = `5 Stunden ${e.fuenf.prozent} % (bis ${grenzeFuenf} Plätze), Woche ${wocheProzent} % (bis ${grenzeWoche} Plätze)${e.opus ? ', Opus-Woche ' + e.opus.prozent + ' %' : ''}${deckel}`
log(`Verbrauch ${args.anlass}: ${grund}; ${plaetze} von ${wunsch} Plätzen${gebremst ? ', gebremst' : ''}`)
return { status: 'ok', quelle, fuenf_stunden: e.fuenf, woche: e.woche, woche_opus: e.opus, plaetze, gebremst, grund, fenster: ablesung.fenster }
```
## Verifikation
Im Vault-Wurzelordner:
```bash
node -e "const t=require('fs').readFileSync(process.argv[1],'utf8').replace(/^export const meta = /m,'const meta = ');new (Object.getPrototypeOf(async function(){}).constructor)('agent','parallel','pipeline','phase','log','workflow','args','budget',t);console.log('PARSE OK')" .claude/workflows/verbrauch.js
```
Erwartet: `PARSE OK`, Exit 0.
Danach `git status --porcelain -- .claude/workflows/verbrauch.js` zeigen.