Abgleich mit dem Vault-Stand 22761eb
11 Datei(en) geändert. Erzeugt von .vault-tools/auto-push/werkzeuge_spiegel.py.
This commit is contained in:
1 parent
9e506ff588
commit
ae3ec3ca89
11 files changed
+1520
-65
No files matched your search
@@ -26,6 +26,9 @@ export const meta = {
|
||||
// und der Woche.
|
||||
// - Rückgabe mit status fertig oder gebremst; ein gebremster Lauf wird neu gestartet, nicht
|
||||
// fortgesetzt.
|
||||
// - werkzeug_befunde (seit 2026-11-02) listet die Befundzeilen der Planwerkzeuge und die von
|
||||
// plan_materialisiere.py aus materialisieren, je mit dem Werkzeug. Die Plankritik hält dabei
|
||||
// nicht an; die Linsen laufen wie sonst.
|
||||
//
|
||||
// Rollenparameter: model wird immer gesetzt (Stamm). Der Effort der pruefer kommt aus dem
|
||||
// Frontmatter von .claude/agents/pruefer.md; args.effort überschreibt ihn nur bewusst.
|
||||
@@ -45,6 +48,36 @@ const VERBRAUCH = 'D:/Claude/.claude/workflows/verbrauch.js'
|
||||
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, "'\\''") + "'"
|
||||
// Befundzeile der Planwerkzeuge: "BEFUND <datei>:<zeile>:", bei plan_zeichen "<datei>:<zeile>:<spalte>:".
|
||||
// kopie_bauen.py schreibt "BEFUND Projekt ..." ohne Zeilennummer; die Form trennt beide.
|
||||
const BEFUNDZEILE = /^BEFUND [^\s:]+:\d+:/
|
||||
const befundZeilen = text => String(text || '').split('\n').map(z => z.replace(/\r$/, '')).filter(z => BEFUNDZEILE.test(z))
|
||||
// Ein Hilfsagent darf seine Ausgabe auf mehrere laeufe verteilen: Im Echtlauf wf_9ab7fd8e-ad1
|
||||
// (2026-11-02) gab werkzeug:planwerkzeuge je Werkzeug einen Lauf zurück, und laeufe[0] allein
|
||||
// enthielt plan_bloecke nicht. Jede Ausgabe eines Hilfsagenten wird deshalb über alle laeufe gelesen,
|
||||
// in ihrer Reihenfolge und mit Zeilenumbruch verbunden: Befund- und EXIT-Zeilen, KOPIE-Zeile und
|
||||
// angewendete Blöcke, Mutantenlauf.
|
||||
const ausgabeAller = r => (r && Array.isArray(r.laeufe) ? r.laeufe : []).map(l => String((l && l.ausgabe) || '')).join('\n')
|
||||
// Exit über alle laeufe, für die Kopie aus materialisieren: Ihr Befehl ist eine Kette mit &&, sie
|
||||
// endet nur mit 0, wenn jedes Glied mit 0 endet. Verwendbar ist die Kopie deshalb nur, wenn jeder Lauf
|
||||
// Exit 0 hat; ein Lauf ohne Exit zählt nicht als 0 und steht im Log als undefined. Planwerkzeuge und
|
||||
// Mutantenlauf lesen stattdessen die EXIT-Zeilen, die ihr Befehl selbst schreibt.
|
||||
const exitsAller = r => (r && Array.isArray(r.laeufe) ? r.laeufe : []).map(l => l && l.exit)
|
||||
const alleExitNull = r => exitsAller(r).length > 0 && exitsAller(r).every(x => x === 0)
|
||||
|
||||
// Stand eines Planwerkzeugs aus seiner EXIT-Zeile und dem Teil der Ausgabe, der zu ihm gehört.
|
||||
// Gelaufen ist es mit Exit 0, mit Exit 2 und mindestens einer Befundzeile, plan_bloecke auch mit
|
||||
// Exit 3 und "Nichts geprueft:" (kein Aus-/wird-Block). Exit 2 ohne Befundzeile ist ein
|
||||
// gescheitertes Werkzeug: python endet auch bei "can't open file" mit 2 (2026-09-24 ging so ein
|
||||
// Errno 2 als Rohausgabe an die Linse).
|
||||
function werkzeugStand(aus, name, abschnitt) {
|
||||
const m = new RegExp('EXIT ' + name + ': (\\d+)').exec(aus)
|
||||
const befunde = befundZeilen(abschnitt)
|
||||
if (!m) return { name, gelaufen: false, grund: 'ohne EXIT-Zeile', befunde }
|
||||
const exit = Number(m[1])
|
||||
const gelaufen = exit === 0 || (exit === 2 && befunde.length > 0) || (name === 'plan_bloecke' && exit === 3 && /^Nichts geprueft:/m.test(abschnitt))
|
||||
return { name, gelaufen, grund: 'Exit ' + exit + (exit === 2 && !befunde.length ? ' ohne Befundzeile' : ''), befunde }
|
||||
}
|
||||
|
||||
// Text für die Linse arithmetik, wenn der Mutantenlauf (werkzeug:mutanten) etwas geliefert hat.
|
||||
// Seit der Nachbesserung 2026-09-28 (N5, N7): modus: muster in der Rohausgabe heißt, dass kein
|
||||
@@ -231,19 +264,29 @@ 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, mutantenLauf: null, mutantenStatus: null }
|
||||
const ctx = { kopie: args.kopie || null, werkzeuge: null, temp: null, mutantenLauf: null, mutantenStatus: null, befunde: [] }
|
||||
const MUTANTEN_MODUS = args.mutanten || 'voll'
|
||||
const vorbereitung = []
|
||||
|
||||
// Eine Kopie gilt nur als verwendbar, wenn der Lauf sauber endet, den Pfad bis zum
|
||||
// Zeilenende nennt (Pfade mit Leerzeichen) und das Planwerkzeug mindestens einen Block
|
||||
// angewendet hat. Sonst rechnet Linse 1 am Text, und das steht im Log.
|
||||
// Eine Kopie gilt nur als verwendbar, wenn jeder Lauf sauber endet (alleExitNull), die Ausgabe
|
||||
// den Pfad bis zum Zeilenende nennt (Pfade mit Leerzeichen) und das Planwerkzeug mindestens einen
|
||||
// Block angewendet hat. Sonst rechnet Linse 1 am Text, und das steht im Log. Meldet
|
||||
// plan_materialisiere.py einen Befund, ist das kein gescheitertes Werkzeug: Die Zeilen gehen
|
||||
// nach werkzeug_befunde, und der Temp-Ordner wird genannt.
|
||||
function kopieAusLauf(r, wozu) {
|
||||
const lauf = r && r.laeufe && r.laeufe[0]
|
||||
if (!lauf) { log(`${wozu}: Hilfsagent ohne Ergebnis, keine Kopie`); return null }
|
||||
const m = /^KOPIE=(.+?)\s*$/m.exec(lauf.ausgabe)
|
||||
const angewendet = /'(neu|ersetzt|angehaengt)': [1-9]/.test(lauf.ausgabe)
|
||||
if (lauf.exit !== 0 || !m) { log(`${wozu}: Kopie nicht verwendbar (Exit ${lauf.exit}${m ? '' : ', kein KOPIE-Pfad'})`); return null }
|
||||
const exits = exitsAller(r)
|
||||
if (!exits.length) { log(`${wozu}: Hilfsagent ohne Ergebnis, keine Kopie`); return null }
|
||||
const aus = ausgabeAller(r)
|
||||
const m = /^KOPIE=(.+?)\s*$/m.exec(aus)
|
||||
const angewendet = /'(neu|ersetzt|angehaengt)': [1-9]/.test(aus)
|
||||
const befunde = befundZeilen(aus)
|
||||
if (befunde.length) {
|
||||
befunde.forEach(befund => ctx.befunde.push({ werkzeug: 'plan_materialisiere', befund }))
|
||||
if (m) ctx.temp = m[1].replace(/\/mat$/, '')
|
||||
log(`${wozu}: plan_materialisiere.py meldet ${befunde.length} Befund(e) (Exit ${exits.map(String).join('/')}), keine Kopie; die Zeilen stehen unter werkzeug_befunde`)
|
||||
return null
|
||||
}
|
||||
if (!alleExitNull(r) || !m) { log(`${wozu}: Kopie nicht verwendbar (Exit ${exits.map(String).join('/')}${m ? '' : ', kein KOPIE-Pfad'})`); return null }
|
||||
ctx.temp = m[1].replace(/\/mat$/, '')
|
||||
if (!angewendet) { log(`${wozu}: das Planwerkzeug hat keinen Block angewendet; die Kopie ist der unveränderte Stand und wird nicht verwendet`); return null }
|
||||
return m[1]
|
||||
@@ -268,13 +311,22 @@ if (!ctx.kopie && args.materialisieren) {
|
||||
{
|
||||
const befehl = `${PY} ${q(W + '/plan_zeichen.py')} ${q(args.planordner)}; echo "EXIT plan_zeichen: $?"; ls ${q(args.planordner)}/task-*.md >/dev/null 2>&1 && { ${PY} ${q(W + '/plan_bloecke.py')} vor ${q(args.planordner)}/task-*.md --projekt ${q(args.projekt)}; echo "EXIT plan_bloecke: $?"; } || echo "plan_bloecke: keine task-*.md im Planordner, nicht gefahren"`
|
||||
const r = await werkzeugAgent('werkzeug:planwerkzeuge', 'Vorbereitung', befehl, 'Codeblöcke auf unsichtbare Zeichen und Aus-Blöcke gegen den Baum prüfen')
|
||||
// Nur wenn beide Werkzeuge mit 0 endeten, gilt die Ausgabe als gelaufen (2026-09-24: ein Protokollsatz statt
|
||||
// Pfad in args.werkzeuge endete mit Errno 2 und ging trotzdem als Rohausgabe an die Linse). Der Exit des
|
||||
// ganzen Befehls hilft dabei nicht, er ist der des letzten echo; gelesen werden die EXIT-Zeilen.
|
||||
const aus = r && r.laeufe && r.laeufe[0] ? String(r.laeufe[0].ausgabe || '') : ''
|
||||
const gelaufen = /EXIT plan_zeichen: 0(?!\d)/.test(aus) && (/EXIT plan_bloecke: 0(?!\d)/.test(aus) || /plan_bloecke: keine task-/.test(aus))
|
||||
if (gelaufen) ctx.werkzeuge = aus
|
||||
else log('Planwerkzeuge: Hilfsagent ohne Ergebnis; Linse bezeichner fährt sie selbst')
|
||||
// Die Ausgabe geht an die Linse, wenn beide Werkzeuge gelaufen sind, auch mit Befund (werkzeugStand oben).
|
||||
// Der Exit des ganzen Befehls hilft dabei nicht, er ist der des letzten echo; gelesen werden die
|
||||
// EXIT-Zeilen. Was vor "EXIT plan_zeichen:" steht, gehört zu plan_zeichen, der Rest zu plan_bloecke.
|
||||
const lauf = r && r.laeufe && r.laeufe[0]
|
||||
if (!lauf) log('Planwerkzeuge: Hilfsagent ohne Ergebnis; Linse bezeichner fährt sie selbst')
|
||||
else {
|
||||
const aus = ausgabeAller(r)
|
||||
const grenze = aus.indexOf('EXIT plan_zeichen:')
|
||||
const zeichen = werkzeugStand(aus, 'plan_zeichen', grenze >= 0 ? aus.slice(0, grenze) : aus)
|
||||
const bloecke = /plan_bloecke: keine task-/.test(aus)
|
||||
? { name: 'plan_bloecke', gelaufen: true, befunde: [] }
|
||||
: werkzeugStand(aus, 'plan_bloecke', grenze >= 0 ? aus.slice(grenze) : '')
|
||||
for (const w of [zeichen, bloecke]) w.befunde.forEach(befund => ctx.befunde.push({ werkzeug: w.name, befund }))
|
||||
if (zeichen.gelaufen && bloecke.gelaufen) ctx.werkzeuge = aus
|
||||
else log('Planwerkzeuge: ' + [zeichen, bloecke].filter(w => !w.gelaufen).map(w => w.name + ' ' + w.grund).join(', ') + '; 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,
|
||||
@@ -298,9 +350,13 @@ else if (!ctx.kopie) ctx.mutantenStatus = 'ohne_kopie'
|
||||
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 || '') : ''
|
||||
// Alle laeufe, etwa Anfang und Ende einer gekürzten Ausgabe: Die EXIT-Zeile steht am Schluss
|
||||
// (mutanten_lauf_kopie.sh schreibt höchstens eine); bei mehreren gilt wie bisher die erste.
|
||||
// KEINE_MUTANTEN_TOML zählt nur als ganze Zeile, wie das Skript sie schreibt: Ein zusätzlicher Lauf,
|
||||
// der etwa den Skripttext zeigt, machte sonst aus einem gefahrenen Lauf keine_toml.
|
||||
const aus = ausgabeAller(r)
|
||||
const exitMatch = /EXIT mutanten_lauf: (\d+)/.exec(aus)
|
||||
if (/KEINE_MUTANTEN_TOML/.test(aus)) { ctx.mutantenLauf = { keineToml: true, rohausgabe: aus }; ctx.mutantenStatus = 'keine_toml' }
|
||||
if (/^KEINE_MUTANTEN_TOML\s*$/m.test(aus)) { ctx.mutantenLauf = { keineToml: true, rohausgabe: aus }; ctx.mutantenStatus = 'keine_toml' }
|
||||
else if (exitMatch) { ctx.mutantenLauf = { keineToml: false, rohausgabe: aus }; ctx.mutantenStatus = 'exit_' + exitMatch[1] }
|
||||
else { log('Mutantenlauf: Hilfsagent ohne verwertbares Ergebnis (kein KEINE_MUTANTEN_TOML, kein EXIT mutanten_lauf); Linsen laufen ohne Mutantenlauf weiter'); ctx.mutantenStatus = 'ohne_ergebnis' }
|
||||
vorbereitung.push(r)
|
||||
@@ -324,6 +380,7 @@ if (vorLinsen.gebremst) {
|
||||
selbst_ausgefuehrt: [],
|
||||
nicht_pruefbar: [],
|
||||
vorbereitung,
|
||||
werkzeug_befunde: ctx.befunde,
|
||||
ohne_ergebnis: gewaehlt,
|
||||
verbrauch: ablesungen,
|
||||
plaetze: { linsen: 0, widerlegung: 0 },
|
||||
@@ -388,6 +445,7 @@ return {
|
||||
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)),
|
||||
vorbereitung,
|
||||
werkzeug_befunde: ctx.befunde,
|
||||
ohne_ergebnis: ohneErgebnis,
|
||||
verbrauch: ablesungen,
|
||||
plaetze: { linsen: vorLinsen.plaetze, widerlegung: plaetzeWiderlegung },
|
||||
|
||||
Reference in new issue
Block a user