Abgleich mit dem Vault-Stand 7f484f9
38 Datei(en) geändert. Erzeugt von .vault-tools/auto-push/werkzeuge_spiegel.py.
This commit is contained in:
1 parent
f5747605c7
commit
9e506ff588
38 files changed
+2325
-24
No files matched your search
@@ -16,7 +16,7 @@ Du denkst, du tippst nicht. Dein Ergebnis ist ein Plan, den ein Executer ohne R
|
||||
- **Ablageform hängt am Umfang.** Bis zwei Tasks eine Datei `docs/plans/JJJJ-MM-TT-<thema>.md`. **Ab etwa drei Tasks ein Ordner** `docs/plans/JJJJ-MM-TT-<thema>/` mit `00-uebersicht.md` (Ziel, Architektur, globale Vorgaben, Dateiübersicht, Tasktabelle, Abnahme) und je Task einer Datei `task-NN-<thema>.md`. Jede Taskdatei verweist im Kopf auf die globalen Vorgaben der Übersicht, statt sie zu wiederholen — zwei Fassungen derselben Vorgabe laufen auseinander.
|
||||
- **Jede Plandatei verlinkt ihren Hub direkt unter dem Frontmatter**, als relativen Markdown-Link, nicht nur als Pfad in Backticks. Die Übersicht und ein Einzeldatei-Plan verlinken das Projekt-README (`Projekt: [README](../../../README.md)`, die Tiefe passend zum Ort), jede andere Datei im Planordner die Übersicht (`Übersicht: [00-uebersicht.md](00-uebersicht.md)`). Leerzeichen und Umlaute im Pfad schreibst du URL-kodiert. Liegt der Plan unter `docs/` an der Vault-Wurzel, ist der Hub die `README.md` dort, und die Zeile beginnt mit `Vault:` statt `Projekt:`. Liegt er in einem Projekt im IT Workspace, etwa unter `_arbeitsstand/`, verlinkt die Übersicht stattdessen die Projektübersicht (`_MOC-*.md` im Projektordner) als Wikilink mit vollem Pfad. Die Planwerkzeuge vertragen die Zeile an dieser Stelle, weil sie nur Überschriften, Codezäune und den Abschnitt `## Zieldateien` auswerten (Befund im Plan `.vault-tools/linkcheck/docs/plans/2026-09-29-waisen/`). Regel und Begründung: `AI/Regelwerk/navigation.md`, Abschnitt „Links schreiben und Dateien verschieben“.
|
||||
- **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, auch wenn ein Codeblock typografische Zeichen wie „ “ – — … enthält (Haiku 5.5, Pascals Entscheidung vom 2026-10-09; die Ausnahme für Haiku 4.5 steht in `AI/Regelwerk/codeworkflow.md`, Schritt 3). 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.
|
||||
- **Erst lesen, dann planen.** Bestehende Struktur, Namensgebung, Testkonventionen und Abhängigkeiten des Zielprojekts lesen. Der Plan passt sich der vorhandenen Umgebung an, nicht umgekehrt. Nennt der Auftrag eine Leseliste mit Dateien und Zeilenbereichen, liest du sie zuerst. Sie ist nie abschließend: Jede Datei, deren Pfad, Bezeichner oder Inhalt du in den Plan schreibst, hast du selbst gelesen. Grund: Planer ohne eigenes Lesen schrieben Pfade aus dem Gedächtnis (Pascal, 2026-10-30).
|
||||
- **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).
|
||||
- **Rot vor der Umsetzung bei neuen Modulen** (Pascal, 2026-10-26). Testet ein Task ein Modul, eine Datei oder ein Skript, das es vor dem Task nicht gibt, darf der Test vor der Umsetzung am Import (`ModuleNotFoundError`), an der fehlenden Datei oder an einem Gerüst-Stub (`NichtBereit`) scheitern. Die erwartete Fehlerzeile nennt genau diese erste Zeile. Dass die Zusicherungen greifen, belegen dann die Mutanten: Jeder neue Verhaltenszweig, auch jeder Fehler- und Sperrzweig, bekommt einen Mutanten mit `rot_bei`. Bei einem bestehenden Modul bleibt Rot an einer Zusicherung Pflicht.
|
||||
- **Doku-Tasks verankern nie auf Plandaten** (Pascal, 2026-10-26). `Aus:`-Blöcke in `CHANGELOG.md`, `README.md`, Anleitung und Codedoku verankern an einem Titel oder einer stabilen Abschnittsüberschrift (`# Änderungen`, `## Stand`), nie an einem Versionskopf, einer `updated:`-Zeile oder Text eines anderen Pakets. Ein neuer Versionskopf trägt „Datum bei Freigabe“. Kein Planblock ändert `updated:`; das zieht der Koordinator am Umsetzungstag nach. Beleg: UI-876 und KN-883 brachen in der Nacht zum 2026-10-26 dreimal, sobald ein Vorgängerpaket korrigiert wurde.
|
||||
@@ -26,7 +26,12 @@ Du denkst, du tippst nicht. Dein Ergebnis ist ein Plan, den ein Executer ohne R
|
||||
- `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.
|
||||
- **Blöcke in der Form, die `plan_materialisiere.py` anwendet.** Die Marke steht als letzte nicht leere Zeile vor dem Zaun, ohne Formatierung: `Aus:`, `wird:`, `Die ganze Datei ist neu:` oder `Häng diesen Block ans Ende:`. Die Überschrift (`##` bis `####`) über dem Block endet mit dem Pfad der Zieldatei in Backticks; ein Pfad ohne Schrägstrich und ohne Endung `.py`, `.md`, `.toml`, `.json`, `.ts` oder `.css` steht als `./name` (etwa `./versions.env`). Eine Datei ganz ohne Endung (`host/logrotate/edge-traefik`, `Dockerfile`, `.gitignore`) erkennt das Werkzeug nur, wenn derselbe Pfad unter `## Zieldateien` steht; sonst ist ihr Block ein Befund (seit 2026-10-17). Eine Löschung steht in `## Zieldateien` als ``- `pfad` (gelöscht)``. Eine fette Marke, eine andere Formulierung („mit dem Write-Werkzeug anlegen“, „löschen“) oder eine Überschrift, deren letzter Pfad nicht das Ziel ist, übergeht das Werkzeug ohne Fehler. Am 2026-10-11 im Edge-Stack betraf das 8 von 11 Taskdateien; die Plankritik hätte ohne angewendete Kopie gearbeitet. Prüfskripte im Plan, die Marken zählen, suchen genau diese Form.
|
||||
- **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.
|
||||
- **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.
|
||||
- **Korrektur vor der ersten Ausführung als Ersetzungsliste, nicht als Neufassung** (Pascal, 2026-10-30). Das ist die Voreinstellung, auch wenn der Auftrag die Form nicht nennt; nur ein ausdrücklicher Auftrag zur Neufassung hebt sie auf. Du schreibst eine Datei `NN-ersetzungen-<anlass>.md` in den Planordner und lässt jede Taskdatei byte-gleich. Format, so wie `D:\Claude\.vault-tools\plan-kopie\ersetzungen_einsetzen.py` es einsetzt (Gebrauch: `LIESMICH.md` dort, Schritt 9):
|
||||
- je Ersetzung ein Abschnitt `## Ersetzung N — Titel`, darin `Datei:` mit dem Pfad relativ zum Planordner, dann `Alt:` und `Neu:`;
|
||||
- jeder Block steht zwischen einer Zeile `~~~~text` und einer Zeile `~~~~`;
|
||||
- jeder Alt-Text steht zum Zeitpunkt seiner Ersetzung genau einmal in seiner Datei, die Ersetzungen laufen der Reihe nach; sonst schreibt das Skript gar nichts.
|
||||
- Beleg vom 2026-10-13 (Trading Plattform, Paket FP): 129 Ersetzungen in sechs Dateien, Prüflauf ohne Befund. Beim Neuschreiben waren am 2026-09-23 10 von 17 Befunden der Nachprüfung durch das Umschreiben entstanden.
|
||||
- **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.
|
||||
|
||||
## Aufbau des Plans
|
||||
|
||||
@@ -20,6 +20,24 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python",
|
||||
"args": [
|
||||
"-I",
|
||||
"-X",
|
||||
"utf8",
|
||||
"D:/Claude/.vault-tools/shell-wache/shell_wache.py"
|
||||
],
|
||||
"timeout": 10
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Edit|Write|MultiEdit",
|
||||
|
||||
@@ -9,7 +9,8 @@ export const meta = {
|
||||
// aus dem Frontmatter von .claude/agents/executer.md (medium); ein effort im Task überschreibt
|
||||
// ihn, etwa low für Abschrift mit typografischen Zeichen. Ein Opus-Task ist die Hochstufung
|
||||
// nach zwei Fehlschlägen und läuft ohne Angabe auf high statt auf dem medium des Executers.
|
||||
// Haiku kennt keinen Effort.
|
||||
// Bei haiku verwirft effortFuer() einen Task-Effort; es gilt das medium aus dem Frontmatter,
|
||||
// das Haiku 5.5 auch erhält (AI/Regelwerk/haiku-5-5.md, A1 und A7).
|
||||
const MODELLE = ['haiku', 'sonnet', 'opus']
|
||||
const EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max']
|
||||
const OPUS_PARALLEL = 2
|
||||
@@ -72,7 +73,7 @@ ${a.zusatz ? a.zusatz + '\n' : ''}Übertrage deinen Schlussbericht in die Felder
|
||||
|
||||
function effortFuer(t) {
|
||||
if (t.modell === 'haiku') {
|
||||
if (t.effort) log(`${t.datei}: effort ${t.effort} bei haiku wirkungslos, nicht gesetzt`)
|
||||
if (t.effort) log(`${t.datei}: effort ${t.effort} bei haiku nicht gesetzt, es gilt das medium aus dem Frontmatter des executer`)
|
||||
return undefined
|
||||
}
|
||||
if (t.effort) return t.effort
|
||||
|
||||
@@ -31,6 +31,8 @@ export const meta = {
|
||||
// Frontmatter von .claude/agents/pruefer.md; args.effort überschreibt ihn nur bewusst.
|
||||
// Der Hilfsagent hat keinen agentType und bekommt deshalb seinen Effort mit (low: gemessen
|
||||
// gleich treu wie high bei mechanischer Arbeit, codeworkflow.md "Effort je Rolle").
|
||||
// Modell: werkzeug:kopie läuft auf haiku, weil nur kopieAusLauf() die Ausgabe liest. Planwerkzeuge und
|
||||
// Mutantenlauf bleiben auf sonnet: ihre Rohausgabe geht wörtlich an die Linsen.
|
||||
// Opus-Plätze: Vor den Linsen und vor der Widerlegung liest verbrauch.js den Planverbrauch ab.
|
||||
// Die Linsen laufen mit so vielen Plätzen, wie verbrauch.js erlaubt (höchstens so viele wie
|
||||
// Linsen, höchstens LINSEN_HOECHSTENS), die Widerlegung mit höchstens zwei. Gebremst heißt: Die
|
||||
@@ -164,14 +166,14 @@ async function ablesen(anlass, wunsch) {
|
||||
return r
|
||||
}
|
||||
|
||||
function werkzeugAgent(label, phase, befehl, zweck, zusatz) {
|
||||
function werkzeugAgent(label, phase, befehl, zweck, zusatz, modell = 'sonnet') {
|
||||
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' })
|
||||
{ label, phase, schema: LAUF, model: modell, effort: 'low' })
|
||||
}
|
||||
|
||||
function testort(ctx) {
|
||||
@@ -259,7 +261,7 @@ if (!ctx.kopie && args.materialisieren) {
|
||||
? `TASKS=(${liste})`
|
||||
: `shopt -s nullglob; pushd ${q(args.planordner)} >/dev/null && TASKS=(task-*.md) && popd >/dev/null; [ \${#TASKS[@]} -gt 0 ] || { echo "KEINE_TASKS: im Planordner liegt keine task-*.md; materialisieren.tasks angeben"; exit 3; }`
|
||||
const befehl = `${auswahl}; T=$(mktemp -d) && echo "KOPIE=$(cygpath -m "$T/mat")" && ${PY} ${q(W + '/kopie_bauen.py')} ${q(args.projekt)} "$T/mat" --ohne ${args.materialisieren.ohne.map(q).join(' ')} && ${PY} ${q(W + '/plan_materialisiere.py')} ${q(args.planordner)} "$T/mat" "\${TASKS[@]}"`
|
||||
const r = await werkzeugAgent('werkzeug:kopie', 'Vorbereitung', befehl, 'Kopie des Projekts bauen und den Plan darauf anwenden')
|
||||
const r = await werkzeugAgent('werkzeug:kopie', 'Vorbereitung', befehl, 'Kopie des Projekts bauen und den Plan darauf anwenden', '', 'haiku')
|
||||
ctx.kopie = kopieAusLauf(r, 'Plankritik')
|
||||
vorbereitung.push(r)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
export const meta = {
|
||||
name: 'planung',
|
||||
description: 'Erstplanung: je Task ein planer, gestartet, sobald die Taskdateien seiner Voraussetzungen geschrieben sind; Opus-Plätze nach Verbrauch, vorgegeben zwei',
|
||||
whenToUse: 'Schritt 2 der Standardschleife, wenn 00-uebersicht.md mit der Tasktabelle steht und viele Taskdateien zu schreiben sind (AI/Regelwerk/codeworkflow.md, "Verbrauch und Opus-Plätze"). Nicht für Nachbesserungen. Args: {projekt, planordner, gemeinsam, taskauftrag, tasks: [{nr, thema, datei, modell, voraussetzungen: [nr], welle?}], erledigt?: [nr], plaetze?: 1..4, nachlesen_alle?: 1..20, zusatz?}. plaetze ist der Wunsch, verbrauch.js senkt ihn; ohne plaetze gilt zwei, drei oder vier erst nach der Eichung der Stufen. taskauftrag darf {NR}, {THEMA}, {DATEI}, {MODELL}, {WELLE} und {VORAUSSETZUNGEN} enthalten. Rückgabe mit status fertig, unvollstaendig, gebremst oder abgebrochen; offene Tasks mit erledigt in einem neuen Lauf nachholen, nicht mit resumeFromRunId. Die Plankritik läuft danach als eigener Workflow.',
|
||||
whenToUse: 'Schritt 2 der Standardschleife, wenn 00-uebersicht.md mit der Tasktabelle steht und viele Taskdateien zu schreiben sind (AI/Regelwerk/codeworkflow.md, "Verbrauch und Opus-Plätze"). Nicht für Nachbesserungen. Args: {projekt, planordner, gemeinsam, taskauftrag, tasks: [{nr, thema, datei, modell, voraussetzungen: [nr], welle?}], erledigt?: [nr], plaetze?: 1..4, nachlesen_alle?: 1..20, effort?, zusatz?}. effort überschreibt den Effort aller Planer bewusst, etwa für die Messung medium gegen high; ohne effort gilt das Frontmatter von planer.md. plaetze ist der Wunsch, verbrauch.js senkt ihn; ohne plaetze gilt zwei; drei oder vier sind seit der Eichung der Stufen am 2026-10-30 frei. taskauftrag darf {NR}, {THEMA}, {DATEI}, {MODELL}, {WELLE} und {VORAUSSETZUNGEN} enthalten. Rückgabe mit status fertig, unvollstaendig, gebremst oder abgebrochen; offene Tasks mit erledigt in einem neuen Lauf nachholen, nicht mit resumeFromRunId. Die Plankritik läuft danach als eigener Workflow.',
|
||||
phases: [{ title: 'Taskdateien', detail: 'planer je Task, Start nach den Voraussetzungen, Plätze nach Verbrauch' }],
|
||||
}
|
||||
|
||||
// Rollenparameter: model wird immer gesetzt (Stamm), der Effort kommt aus dem Frontmatter von
|
||||
// .claude/agents/planer.md. Ein Task startet erst, wenn die Planer aller seiner Voraussetzungen
|
||||
// .claude/agents/planer.md; args.effort überschreibt ihn nur bewusst (Messplan A2). Ein Task startet erst, wenn die Planer aller seiner Voraussetzungen
|
||||
// ein Ergebnis geliefert haben; sonst erfindet er Namen, die ein Vorgänger anders schreibt
|
||||
// (codeworkflow.md, "Verbrauch und Opus-Plätze"). Die Zahl gleichzeitiger Planer liest
|
||||
// verbrauch.js am Anfang und nach je nachlesen_alle fertigen Planern ab. Gebremst heißt: Kein
|
||||
@@ -14,8 +14,9 @@ export const meta = {
|
||||
// ohne Ergebnis startet keiner mehr, meist ist dann das Kontingent erschöpft. Ein Ergebnis zählt
|
||||
// nur, wenn es die erwartete Taskdatei nennt; sonst gilt der Task als gescheitert.
|
||||
// VORGABE_PLAETZE ist Stufe 1 der Freigabe vom 2026-09-24 (Pool mit zwei Plätzen). Stufe 3 mit
|
||||
// drei bis vier Plätzen für die Erstplanung kommt erst nach der Eichung der Stufen in verbrauch.js.
|
||||
// drei bis vier Plätzen über plaetze hat Pascal nach der Eichung am 2026-10-30 freigegeben.
|
||||
const MODELLE = ['haiku', 'sonnet', 'opus']
|
||||
const EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max']
|
||||
const HOECHSTENS = 4
|
||||
const VORGABE_PLAETZE = 2
|
||||
const OHNE_ABLESUNG = 2
|
||||
@@ -60,6 +61,7 @@ function pruefeArgs(a) {
|
||||
}))
|
||||
if (a.erledigt !== undefined && !(Array.isArray(a.erledigt) && a.erledigt.every(n => nummern.has(n)))) throw new Error('planung: erledigt muss eine Liste bekannter Tasknummern sein')
|
||||
if (a.plaetze !== undefined && !(Number.isInteger(a.plaetze) && a.plaetze >= 1 && a.plaetze <= HOECHSTENS)) throw new Error('planung: plaetze muss eine ganze Zahl von 1 bis ' + HOECHSTENS + ' sein')
|
||||
if (a.effort !== undefined && !EFFORTS.includes(a.effort)) throw new Error('planung: effort "' + a.effort + '" ungültig')
|
||||
if (a.nachlesen_alle !== undefined && !(Number.isInteger(a.nachlesen_alle) && a.nachlesen_alle >= 1 && a.nachlesen_alle <= 20)) throw new Error('planung: nachlesen_alle muss eine ganze Zahl von 1 bis 20 sein')
|
||||
// Zyklen: Kahn-Verfahren über die Voraussetzungen; was übrig bleibt, hängt im Kreis.
|
||||
const offen = new Map(a.tasks.map(t => [t.nr, t.voraussetzungen.length]))
|
||||
@@ -134,6 +136,7 @@ const nochOffen = () => [...status.values()].some(s => s === 'offen')
|
||||
function starte(t) {
|
||||
status.set(t.nr, 'laeuft')
|
||||
const opts = { label: `planer:task-${String(t.nr).padStart(2, '0')}`, phase: 'Taskdateien', schema: TASK_SCHEMA, agentType: 'planer', model: 'opus' }
|
||||
if (args.effort) opts.effort = args.effort
|
||||
laufend.set(t.nr, agent(auftrag(args, t, jeNr), opts).then(r => ({ nr: t.nr, r }), e => ({ nr: t.nr, r: null, fehler: e && e.message })))
|
||||
}
|
||||
|
||||
@@ -199,6 +202,7 @@ const offen = liste('offen')
|
||||
const zustand = gebremst ? 'gebremst' : abgebrochen ? 'abgebrochen' : gescheitert.length || blockiert.length || offen.length ? 'unvollstaendig' : 'fertig'
|
||||
return {
|
||||
status: zustand,
|
||||
effort: args.effort || '(Frontmatter)',
|
||||
geschrieben,
|
||||
gescheitert,
|
||||
blockiert,
|
||||
|
||||
@@ -15,7 +15,7 @@ export const meta = {
|
||||
// der Ablauf gebaut ist. Plan: .vault-tools/workflow-pruefung/docs/plans/2026-09-29-quorum/.
|
||||
//
|
||||
// Paket: Ein Workflow-Skript hat weder Dateisystem noch Shell. Das Prüfpaket baut deshalb ein
|
||||
// Hilfsagent (sonnet, low), der genau einen Befehl fährt: quorum_werkzeug.py paket. Das Skript
|
||||
// Hilfsagent (haiku, low), der genau einen Befehl fährt: quorum_werkzeug.py paket. Das Skript
|
||||
// entscheidet, ob der Unterschied leer ist; der Hilfsagent überträgt nur die Ausgabe.
|
||||
// Die Zeile QUORUM_PAKET trägt nur Felder fester Größe. Dateiliste und Stand-Liste bleiben in
|
||||
// paket.json; den Stand setzt quorum_werkzeug.py ablegen beim Ablegen des Berichts aus paket.json
|
||||
@@ -32,8 +32,9 @@ export const meta = {
|
||||
// "usage limit" im Log des Jobs und zieht die Antwort heraus.
|
||||
// - Gültig ist die Codex-Stimme nur mit gelesenem Status vor dem Lauf, Job completed, gelesenem
|
||||
// Log ohne "usage limit" und einem Lesebeleg mit der Lesemarke aus paket.md. Sonst Haiku.
|
||||
// - Die Codex-Hilfsagenten laufen auf sonnet mit low: feste Befehle, Ausgaben übertragen. Haiku
|
||||
// nicht, weil Befundtexte typografische Zeichen tragen können, die Haiku still ersetzt.
|
||||
// - Die Hilfsagenten für Paket und Codex laufen auf haiku mit low: feste Befehle, das Skript liest nur
|
||||
// Marken und Felder. Haiku 4.5 ersetzte typografische Zeichen still; Haiku 5.5 hielt sie in 6 von 6
|
||||
// Läufen (AI/Regelwerk/haiku-5-5.md, A3). codex:ende überträgt Befundtexte, der Byte-Vergleich fehlt dort.
|
||||
// Zusammenführen: Ein Sonnet-Agent ohne agentType gruppiert nur belegte Befunde; das Skript teilt
|
||||
// jede Gruppe nach Datei und Zeilen in zusammenhängende Teilgruppen (Funktion teilgruppen) und
|
||||
// zählt die Stimmen. Mehrheit heißt zwei verschiedene Stimmen, die Schwere der Gruppe ist die
|
||||
@@ -161,7 +162,7 @@ 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' })
|
||||
{ label, phase, schema: LAUF, model: 'haiku', effort: 'low' })
|
||||
}
|
||||
|
||||
function ausgabe(r) {
|
||||
@@ -320,7 +321,7 @@ async function codexStimme(a, p) {
|
||||
z.grund = gescheitert ? 'Warten auf Codex gescheitert, Auftrag abgebrochen' : `nach ${runden} Warterunden nicht fertig, Auftrag abgebrochen`
|
||||
return z
|
||||
}
|
||||
const e = await agent(codexEndeAuftrag(a, p, z.job), { label: 'codex:ende', phase: 'Stimmen', schema: CODEX, model: 'sonnet', effort: 'low' })
|
||||
const e = await agent(codexEndeAuftrag(a, p, z.job), { label: 'codex:ende', phase: 'Stimmen', schema: CODEX, model: 'haiku', effort: 'low' })
|
||||
if (e && Number.isInteger(e.dauer_s)) z.dauer_s = e.dauer_s
|
||||
const ungueltig = codexUngueltig(e, p)
|
||||
if (ungueltig) {
|
||||
|
||||
@@ -13,8 +13,16 @@ export const meta = {
|
||||
// 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.
|
||||
// - Die Stufen: Projektvorgabe (Pascal, 2026-09-24), geeicht am 2026-10-30 und von Pascal
|
||||
// unverändert bestätigt. Messreihe verbrauch_reihe.py, Ablesungen nach Plan und Konto getrennt
|
||||
// (Max-Plan, zwei Konten, 406 Paare, 232 Opus-Agentenstunden): rund 9 bis 10 % des
|
||||
// 5-Stunden-Fensters und 2,5 % der Woche je Opus-Agentenstunde, andere Sitzungen eingerechnet.
|
||||
// Ein Paar aufeinanderfolgender Ablesungen, meist eine Staffel, hob das Fenster im Median um 3
|
||||
// bis 5 Punkte, im P90 um 9 bis 14, in der Spitze um 33 bis 42. Nach einer P90-Staffel bleiben
|
||||
// damit bei 4 Plätzen mindestens 36 Punkte Abstand zu 100 %, bei 2 mindestens 16, bei 1 nur
|
||||
// rund 2. Die Wochenstufen halten Reserve für den Rest der Woche, eine Staffel mit vier
|
||||
// Opus-Agenten kostet rund 5 Wochenpunkte. Für vier gleichzeitige Opus-Agenten gab es nur zwei
|
||||
// Paare. Belege: .vault-tools/workflow-pruefung/LIESMICH.md. Die Stufen stehen nur hier.
|
||||
// - Ohne lesbare Ablesung: Projektvorgabe, die bisherige Stammregel von zwei Opus-Agenten.
|
||||
// - Ob der Ableser abgelesen hat: Quelle. Der Auftrag schreibt im Fehlerfall status "fehler",
|
||||
// plan "" und fenster [] vor; get_usage kennt laut Werkzeugbeschreibung (gelesen 2026-10-16)
|
||||
|
||||
@@ -14,6 +14,8 @@ export const meta = {
|
||||
// Aufträge und Rollenparameter an genau einer Stelle stehen. Der Hilfsagent hat keinen
|
||||
// agentType und bekommt seinen Effort deshalb mit (low). Opus läuft nur in den Kindern,
|
||||
// und die laufen nacheinander; die Obergrenze von zwei hält executer-welle selbst.
|
||||
// Modell: werkzeug:kopie läuft auf haiku, weil nur das Skript die Ausgabe liest. werkzeug:vergleich
|
||||
// bleibt auf sonnet: seine Rohausgabe geht an den pruefer.
|
||||
// Verbrauch: Vor und nach der Prüfung liest dieser Workflow den Planverbrauch über verbrauch.js
|
||||
// ab (nur messen); das Kind pruefung bekommt verbrauch: false, weil ein Kind keinen weiteren
|
||||
// Workflow aufrufen kann.
|
||||
@@ -53,14 +55,14 @@ function pruefeArgs(a) {
|
||||
}
|
||||
}
|
||||
|
||||
function werkzeugAgent(label, phase, befehl, zweck) {
|
||||
function werkzeugAgent(label, phase, befehl, zweck, modell = 'sonnet') {
|
||||
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}
|
||||
|
||||
Ä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' })
|
||||
{ label, phase, schema: LAUF, model: modell, effort: 'low' })
|
||||
}
|
||||
|
||||
// Anfang und Ende behalten: Das Ergebnis der Suite steht am Schluss.
|
||||
@@ -94,7 +96,7 @@ const fehler = []
|
||||
phase('Kopie')
|
||||
if (!kopie) {
|
||||
const befehl = `T=$(mktemp -d) && echo "KOPIE=$(cygpath -m "$T/mat")" && ${PY} ${q(W + '/kopie_bauen.py')} ${q(args.projekt)} "$T/mat" --ohne ${args.ohne.map(q).join(' ')} && ${PY} ${q(W + '/plan_materialisiere.py')} ${q(args.planordner)} "$T/mat" ${taskdateien.map(q).join(' ')}`
|
||||
const r = await werkzeugAgent('werkzeug:kopie', 'Kopie', befehl, 'Stand vor der Welle kopieren und die Taskdateien der Welle darauf anwenden')
|
||||
const r = await werkzeugAgent('werkzeug:kopie', 'Kopie', befehl, 'Stand vor der Welle kopieren und die Taskdateien der Welle darauf anwenden', 'haiku')
|
||||
belege.kopie = r
|
||||
const lauf = r && r.laeufe && r.laeufe[0]
|
||||
const m = lauf && /^KOPIE=(.+?)\s*$/m.exec(lauf.ausgabe)
|
||||
|
||||
Reference in new issue
Block a user