Automatischer Push: 11 Datei(en) geändert
- .claude/agents/planer.md - .claude/workflows/plankritik.js - .vault-tools/plan-kopie/LIESMICH.md - .vault-tools/plan-kopie/mutanten_lauf.py - .vault-tools/plan-kopie/mutanten_lauf_ENTWURF.md - .vault-tools/plan-kopie/mutanten_lauf_kopie.sh - .vault-tools/plan-kopie/mutanten_lauf_treiber.py - .vault-tools/workflow-pruefung/faelle_workflows.mjs - .vault-tools/workflow-pruefung/mutanten_workflows.py - AI/Regelwerk/codeworkflow.md - CLAUDE.md Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
1 parent
e50c8296d7
commit
bc9b4f4497
11 files changed
+2214
-10
No files matched your search
@@ -17,6 +17,10 @@ Du denkst, du tippst nicht. Dein Ergebnis ist ein Plan, den ein Executer ohne R
|
||||
- **Jede Taskdatei trägt im Frontmatter `modell:` und `modell_begruendung:`.** `title`, `summary` und `modell_begruendung` stehen in Anführungszeichen — ein `: ` im Text macht den Block sonst zu ungültigem YAML (Blöcke und Regel: `AI/Regelwerk/frontmatter.md`). Das Kriterium ist eine einzige Frage: Braucht der Executer für diesen Task Ermessen, oder steht alles wörtlich im Plan? Steht der Code wörtlich da, sind die Zieldateien namentlich genannt und die Verbote ausdrücklich, dann ist die Rolle Abschrift und `haiku` genügt — außer ein Codeblock des Tasks enthält Anführungszeichen wie „ “ ” ‚ ‘ ’ « », Gedanken- oder Streckenstriche – — oder Auslassungspunkte …: Dann `modell: sonnet` und zusätzlich `effort: low` im Frontmatter, weil Haiku solche Zeichen still ersetzt (Messung 2026-09-23). Bleibt Ermessen offen, ist es Fehlersuche, oder muss Fließtext formuliert statt abgeschrieben werden, dann `sonnet`.
|
||||
- **Erst lesen, dann planen.** Bestehende Struktur, Namensgebung, Testkonventionen und Abhängigkeiten des Zielprojekts lesen. Der Plan passt sich der vorhandenen Umgebung an, nicht umgekehrt.
|
||||
- **Erwartete pytest-Fehlerzeilen nur mit breiter Ausgabe.** Ohne Terminal kürzt pytest (gemessen an 9.1.1) jede `FAILED`-Zeile der Kurzzusammenfassung auf 80 Zeichen, die Fehlerart ist dann abgeschnitten („Failed: D..."). Nennt der Plan eine erwartete Fehlerzeile wörtlich, steht im Befehl `COLUMNS=300` davor (Git-Bash) bzw. `$env:COLUMNS=300;` (PowerShell).
|
||||
- **Mutanten stehen in einer Datei, nicht als Prosa.** Verlangt der Auftrag Mutanten, schreibst du sie als `mutanten.toml` in den Planordner, Format 1 nach `D:\Claude\.vault-tools\plan-kopie\mutanten_lauf_ENTWURF.md`, Abschnitt 2; lies den Abschnitt, bevor du die Datei schreibst. Die Plankritik fährt die Datei mit `mutanten_lauf.py` auf ihrer Kopie. In „Fertig heißt“ steht danach nur der Aufruf mit der Erwartung „Exit 0, jeder Mutant `OK`“, keine Zählung. Drei Fallen, alle belegt:
|
||||
- `aus` sind eine oder mehrere ganze Zeilen samt Einrückung und stehen genau einmal in der Datei.
|
||||
- `rot_bei` nennt parametrisierte Tests mit voller Kennung, und zwar nur die Fälle, die der Mutant umkippt. Bei B1 (2026-09-27) wären unter `return False` drei von fünf Fällen grün geblieben.
|
||||
- `aus` und `wird` stehen in `'''…'''`, damit Backslashes wörtlich bleiben.
|
||||
- **Keine Platzhalter.** Kein „analog zu Task 2", kein „hier noch ergänzen", kein Pseudocode. Was im Plan steht, ist tippfertig.
|
||||
- **Nachbesserung nach einer ausgeführten Welle schreibst du als neue Taskdateien, nicht als Neufassung.** Du hast kein Edit-Werkzeug und schreibst jede überarbeitete Datei komplett neu; am 2026-09-23 im Nexhorizons Hub waren dabei 10 von 17 Befunden der Nachprüfung durch das Umschreiben selbst entstanden. Deshalb: neue `task-NN-nachbesserung-<thema>.md` mit `Aus:`/`wird:`-Blöcken gegen den Baum, bestehende Taskdateien bleiben byte-gleich. Was ältere Tasks an den neuen Stand anpassen muss, schreibst du als Folgenliste `nachbesserung-<welle>-folgen.md` im selben `Aus:`/`wird:`-Format; eingesetzt wird sie vom Koordinator oder einem Executer. Für Korrekturen vor der ersten Ausführung gilt das nicht, außer der Auftrag verlangt es.
|
||||
- **Offene Entscheidungen benennen, nicht überspielen.** Wo der Auftrag mehrdeutig ist: Annahme treffen, im Abschnitt „Getroffene Annahmen" explizit nennen. Nur abbrechen, wenn jede Annahme den Plan unbrauchbar machen würde.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const meta = {
|
||||
name: 'plankritik',
|
||||
description: 'Plankritik: pruefer-Linsen nach Verbrauch, doppelte Befunde zusammengefasst, wichtige und blockierende von einem zweiten pruefer widerlegt',
|
||||
whenToUse: 'Schritt 2 der Standardschleife vor dem ersten Executer, Pflicht ab etwa drei Tasks (AI/Regelwerk/codeworkflow.md). Args: {projekt, planordner, spec?, kopie?, materialisieren?: {ohne: [relpfade], tasks?: [taskdateien]}, suite?, linsen?, plaetze?: 1..4, verifizieren?: true, verifizieren_ab?: "wichtig"|"blockierend", effort?, werkzeuge?: Ordner der Planwerkzeuge, zusatz?}. Einzelheiten im Kommentar unter meta.',
|
||||
whenToUse: 'Schritt 2 der Standardschleife vor dem ersten Executer, Pflicht ab etwa drei Tasks (AI/Regelwerk/codeworkflow.md). Args: {projekt, planordner, spec?, kopie?, materialisieren?: {ohne: [relpfade], tasks?: [taskdateien]}, suite?, linsen?, mutanten?: "voll"|"muster"|"aus" (Vorgabe voll), plaetze?: 1..4, verifizieren?: true, verifizieren_ab?: "wichtig"|"blockierend", effort?, werkzeuge?: Ordner der Planwerkzeuge, zusatz?}. Einzelheiten im Kommentar unter meta.',
|
||||
phases: [
|
||||
{ title: 'Vorbereitung', detail: 'Hilfsagent: Kopie bauen, Plan anwenden, Planwerkzeuge fahren' },
|
||||
{ title: 'Plankritik', detail: 'je Linse ein pruefer, gleichzeitig nach Verbrauch' },
|
||||
@@ -17,6 +17,8 @@ export const meta = {
|
||||
// - werkzeuge ist ein Pfad, keine Ausgabe; Vorgabe D:/Claude/.vault-tools/plan-kopie.
|
||||
// - Ohne kopie baut materialisieren sie selbst (kopie_bauen.py plus plan_materialisiere.py);
|
||||
// ohne() muss Geheimnisdateien und große Datenordner nennen.
|
||||
// - mutanten: "voll" (Vorgabe), "muster" oder "aus". Nur wirksam mit gesetztem kopie; steuert den
|
||||
// Hilfsagenten werkzeug:mutanten, der mutanten_lauf_kopie.sh fährt (siehe Kommentar dort unten).
|
||||
// - plaetze begrenzt die gleichzeitigen Linsen; verbrauch.js senkt sie nach dem 5-Stunden-Fenster
|
||||
// und der Woche.
|
||||
// - Rückgabe mit status fertig oder gebremst; ein gebremster Lauf wird neu gestartet, nicht
|
||||
@@ -39,8 +41,18 @@ const RANG = { blockierend: 0, wichtig: 1, klein: 2 }
|
||||
// Einfache Anführungszeichen: In Bash bleiben darin $, Backtick und Backslash wörtlich.
|
||||
const q = s => "'" + String(s).replace(/'/g, "'\\''") + "'"
|
||||
|
||||
// Text für die Linse arithmetik, wenn der Mutantenlauf (werkzeug:mutanten) etwas geliefert hat.
|
||||
function mutantenText(m) {
|
||||
if (!m) return ''
|
||||
if (m.keineToml) return ' Der Plan hat keine mutanten.toml. Das ist ein Befund der Schwere wichtig, sobald der Plan Mutanten in "Fertig heißt" nennt.'
|
||||
const zeilen = m.rohausgabe.split('\n')
|
||||
const letzte = zeilen.slice(-200).join('\n')
|
||||
const grenze = /ZEITGRENZE/.test(m.rohausgabe) ? ' Der Lauf hat seine Zeitgrenze erreicht: Mutanten ohne eigene Zeile sind nicht gefahren; setze für sie selbst höchstens die aus, die dir am riskantesten erscheinen, in einer eigenen Kopie.' : ''
|
||||
return `${grenze} Bewerte jeden Mutanten mit LUECKE, UNKLAR, ZEIT oder MUSTER als Befund und prüfe bei OK an der Fehlermeldung, ob der Test an der gemeinten Stelle fällt; setze Mutanten nicht erneut von Hand.\n<mutantenlauf>\n${letzte}\n</mutantenlauf>`
|
||||
}
|
||||
|
||||
const LINSEN = {
|
||||
arithmetik: (a, ctx) => `Linse: Fixture-Arithmetik und Rot-Nachweise. Rechne jede Mindestzahl, jede Grenze und jeden Schwellenwert im Produktivcode des Plans gegen jede Fixture der Tests nach. Prüfe jede im Plan erwartete Fehlermeldung und jede vorhergesagte Testausgabe wörtlich: Würde der Test vor der Umsetzung genau so rot, und danach grün? pytest kürzt FAILED-Zeilen ohne Terminal auf 80 Zeichen; vergleiche Fehlerzeilen deshalb mit COLUMNS=300 vor dem Befehl.${ctx.kopie ? ` Der Plan ist auf die Kopie ${ctx.kopie} angewendet. Fahre dort die Suite (${a.suite || 'Testbefehl aus dem Plan'}) und vergleiche jede Vorhersage des Plans mit der echten Ausgabe. In der Kopie änderst du nichts außer dem, was die Testläufe selbst anlegen.` : ' Eine Kopie mit angewendetem Plan gibt es nicht; du rechnest am Text.'}`,
|
||||
arithmetik: (a, ctx) => `Linse: Fixture-Arithmetik und Rot-Nachweise. Rechne jede Mindestzahl, jede Grenze und jeden Schwellenwert im Produktivcode des Plans gegen jede Fixture der Tests nach. Prüfe jede im Plan erwartete Fehlermeldung und jede vorhergesagte Testausgabe wörtlich: Würde der Test vor der Umsetzung genau so rot, und danach grün? pytest kürzt FAILED-Zeilen ohne Terminal auf 80 Zeichen; vergleiche Fehlerzeilen deshalb mit COLUMNS=300 vor dem Befehl.${ctx.kopie ? ` Der Plan ist auf die Kopie ${ctx.kopie} angewendet. Fahre dort die Suite (${a.suite || 'Testbefehl aus dem Plan'}) und vergleiche jede Vorhersage des Plans mit der echten Ausgabe. In der Kopie änderst du nichts außer dem, was die Testläufe selbst anlegen.` : ' Eine Kopie mit angewendetem Plan gibt es nicht; du rechnest am Text.'}${mutantenText(ctx.mutantenLauf)}`,
|
||||
bezeichner: (a, ctx) => `Linse: Bezeichner, Signaturen und Byte-Treue. Prüfe jeden Namen, jede Signatur und jeden Import über Taskgrenzen hinweg. Jeder Aus-Block muss genau einmal im echten Baum stehen, jeder Codeblock muss sich parsen lassen, und Codeblöcke dürfen keine Zeilen- und Absatztrenner, Format- oder Steuerzeichen enthalten. Prüfbefehle im Plan dürfen nur Code treffen, nie ein Wort, das auch in einem Kommentar steht.${ctx.werkzeuge ? `\n\nDie Planwerkzeuge sind schon gelaufen, hier ihre Rohausgabe. Bewerte sie, statt sie erneut zu fahren; nur bei Zweifeln selbst nachfahren.\n<werkzeugausgabe>\n${ctx.werkzeuge}\n</werkzeugausgabe>` : ` Fahre dazu plan_bloecke.py vor und plan_zeichen.py aus ${a.werkzeuge || 'D:/Claude/.vault-tools/plan-kopie'}.`}`,
|
||||
abdeckung: (a) => `Linse: Spec-Abdeckung in beide Richtungen. Jede Anforderung${a.spec ? ` aus ${a.spec}` : ' der Übersicht'} braucht einen Task und einen Test, und jeder Task braucht eine Anforderung. Die "Fertig heißt"-Liste der Übersicht muss je Check einen Beleg außerhalb der eigenen Meinung haben. Das Frontmatter jeder Taskdatei braucht modell und modell_begruendung; Abschrift-Tasks mit Anführungszeichen, Gedanken- und Streckenstrichen oder Auslassungspunkten im Code tragen modell sonnet und effort low statt haiku.`,
|
||||
}
|
||||
@@ -101,6 +113,7 @@ function pruefeArgs(a) {
|
||||
if (a.verifizieren_ab !== undefined && !['wichtig', 'blockierend'].includes(a.verifizieren_ab)) throw new Error('plankritik: verifizieren_ab muss wichtig oder blockierend sein')
|
||||
if (a.plaetze !== undefined && !(Number.isInteger(a.plaetze) && a.plaetze >= 1 && a.plaetze <= LINSEN_HOECHSTENS)) throw new Error('plankritik: plaetze muss eine ganze Zahl von 1 bis ' + LINSEN_HOECHSTENS + ' sein')
|
||||
if (a.materialisieren && !(Array.isArray(a.materialisieren.ohne) && a.materialisieren.ohne.length > 0 && a.materialisieren.ohne.every(x => typeof x === 'string' && x))) throw new Error('plankritik: materialisieren.ohne muss eine nicht leere Liste sein, Ausschlüsse als Pfade vom Projektwurzelordner, mindestens .git (falls vorhanden) und Geheimnisdateien')
|
||||
if (a.mutanten !== undefined && !['voll', 'muster', 'aus'].includes(a.mutanten)) throw new Error('plankritik: mutanten muss voll, muster oder aus sein')
|
||||
}
|
||||
|
||||
// Höchstens n Aufgaben gleichzeitig, ohne Leerlauf zwischen Paaren.
|
||||
@@ -137,12 +150,12 @@ async function ablesen(anlass, wunsch) {
|
||||
return r
|
||||
}
|
||||
|
||||
function werkzeugAgent(label, phase, befehl, zweck) {
|
||||
function werkzeugAgent(label, phase, befehl, zweck, zusatz) {
|
||||
return agent(`Du führst einen Werkzeugbefehl aus und gibst seine Ausgabe roh zurück. Zweck: ${zweck}
|
||||
|
||||
Führe genau diesen Befehl einmal im Bash-Werkzeug (Git-Bash) aus, unverändert:
|
||||
${befehl}
|
||||
|
||||
${zusatz ? '\n' + zusatz + '\n' : ''}
|
||||
Ändere keine Datei außer denen, die der Befehl selbst anlegt. Deute nichts und fasse nichts zusammen. Gib Befehl, Exit-Code und die vollständige Ausgabe zurück; bei mehr als 200 Zeilen die ersten 60 und die letzten 120, mit einer Zeile "[... N Zeilen gekürzt ...]" dazwischen.`,
|
||||
{ label, phase, schema: LAUF, model: 'sonnet', effort: 'low' })
|
||||
}
|
||||
@@ -202,7 +215,8 @@ Gilt der Befund nur unter einer Bedingung, nenn sie. Gib deine eigene Einschätz
|
||||
pruefeArgs(args)
|
||||
const W = args.werkzeuge || 'D:/Claude/.vault-tools/plan-kopie'
|
||||
const PY = 'PYTHONIOENCODING=utf-8 python -X utf8'
|
||||
const ctx = { kopie: args.kopie || null, werkzeuge: null, temp: null }
|
||||
const ctx = { kopie: args.kopie || null, werkzeuge: null, temp: null, mutantenLauf: null }
|
||||
const MUTANTEN_MODUS = args.mutanten || 'voll'
|
||||
const vorbereitung = []
|
||||
|
||||
// Eine Kopie gilt nur als verwendbar, wenn der Lauf sauber endet, den Pfad bis zum
|
||||
@@ -247,6 +261,26 @@ if (!ctx.kopie && args.materialisieren) {
|
||||
else log('Planwerkzeuge: Hilfsagent ohne Ergebnis; Linse bezeichner fährt sie selbst')
|
||||
vorbereitung.push(r)
|
||||
}
|
||||
// Mutantenlauf (seit 2026-09-27). mutanten_lauf.py ändert Dateien in der Wurzel, die es bekommt,
|
||||
// und setzt sie nach jedem Mutanten zurück. Die Linsen fahren gleichzeitig Tests in ctx.kopie;
|
||||
// deshalb arbeitet mutanten_lauf_kopie.sh auf einer Kopie der Kopie unter /tmp in WSL.
|
||||
// MSYS_NO_PATHCONV=1 ist Pflicht: Ohne sie übersetzt die Git-Bash /mnt/d/... in einen
|
||||
// Windows-Pfad (Erinnerung git-bash-uebersetzt-pfade-fuer-wsl-exe). cygpath -l ist Pflicht, weil
|
||||
// die Kopie oft unter dem Kurznamen PASCAL~1 liegt. cygpath -m statt -w: wsl -d Debian -- ...
|
||||
// reicht die Befehlszeile an die Linux-Shell weiter, und die verschluckt jeden Backslash
|
||||
// ("D:\Claude\foo" kam als "D:Claudefoo" an, gemessen 2026-09-27); Vorwärtsschrägstriche
|
||||
// übersteht der Pfad, und wslpath -u im Skript wandelt ihn um. Das Bash-Werkzeug des Hilfsagenten
|
||||
// endet nach höchstens zehn Minuten; das Skript begrenzt den Lauf deshalb selbst auf 540 s und
|
||||
// meldet eine überschrittene Grenze mit ZEITGRENZE.
|
||||
if (ctx.kopie && MUTANTEN_MODUS !== 'aus') {
|
||||
const befehl = `MSYS_NO_PATHCONV=1 wsl -d Debian -- bash /mnt/d/Claude/.vault-tools/plan-kopie/mutanten_lauf_kopie.sh "$(cygpath -m -l ${q(ctx.kopie)})" "$(cygpath -m -l ${q(args.planordner)})" ${MUTANTEN_MODUS === 'muster' ? 'muster' : 'voll'}`
|
||||
const r = await werkzeugAgent('werkzeug:mutanten', 'Vorbereitung', befehl, 'Mutanten aus mutanten.toml auf einer Kopie der Kopie fahren', 'Setze im Bash-Werkzeug den Parameter timeout auf 600000; der Befehl darf bis zu zehn Minuten laufen.')
|
||||
const aus = r && r.laeufe && r.laeufe[0] ? String(r.laeufe[0].ausgabe || '') : ''
|
||||
if (/KEINE_MUTANTEN_TOML/.test(aus)) ctx.mutantenLauf = { keineToml: true, rohausgabe: aus }
|
||||
else if (/EXIT mutanten_lauf: \d+/.test(aus)) ctx.mutantenLauf = { keineToml: false, rohausgabe: aus }
|
||||
else log('Mutantenlauf: Hilfsagent ohne verwertbares Ergebnis (kein KEINE_MUTANTEN_TOML, kein EXIT mutanten_lauf); Linsen laufen ohne Mutantenlauf weiter')
|
||||
vorbereitung.push(r)
|
||||
}
|
||||
|
||||
phase('Plankritik')
|
||||
const gewaehlt = args.linsen && args.linsen.length ? args.linsen : Object.keys(LINSEN)
|
||||
@@ -320,6 +354,7 @@ return {
|
||||
zaehlung,
|
||||
kopie: ctx.kopie,
|
||||
temp_ordner: tempText(),
|
||||
mutanten_lauf: ctx.mutantenLauf ? ctx.mutantenLauf.rohausgabe : null,
|
||||
befunde,
|
||||
selbst_ausgefuehrt: ergebnisse.map(e => ({ linse: e.linse, befehle: e.ergebnis.selbst_ausgefuehrt })),
|
||||
nicht_pruefbar: ergebnisse.flatMap(e => e.ergebnis.nicht_pruefbar.map(x => e.linse + ': ' + x)),
|
||||
|
||||
Reference in new issue
Block a user