This repository has been archived on 2026-09-17. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
nixos-config/docs/intent/board-builder-limit-reached-auto-split.md
pijukka a7f3532d49 board-agent: manual split escalation for cards stuck at the Builder iteration limit
Implements docs/intent/board-builder-limit-reached-auto-split.md. A card
that hits limit_reached twice (manual trigger + its one automatic retry)
can now be dragged into a new "Aufteilen angefordert" column, which runs
the Planner role read-only against the original intent plus the stored
builder_report and splits it into up to 10 independent child intents
(===SPLIT-REPORT===/===CHILD=== marker blocks, wrapper writes every
docs/intent/<child-slug>.md itself, all-or-nothing on any malformed or
oversized proposal). Children land in "Geplant" with parent_id set, no
auto-trigger; the parent moves to the new terminal phase "Aufgeteilt" with
child_slugs recorded.

Implemented directly in this session rather than via the board's own
Builder pipeline: the automated Builder run for this exact intent hit its
own 20-iteration limit twice, which is the failure mode this feature exists
to handle.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F51W1LEGuSvNroZNj7vXqC
2026-09-08 16:33:08 +02:00

135 lines
7.5 KiB
Markdown

# Intent: Automatisches Zerlegen einer zu großen Karte über eine Board-Spalte
## Ziel
Für eine Builder-Karte, die auch nach dem automatischen Einzelversuch aus
`docs/intent/board-builder-limit-reached-fallback.md` erneut am
Iterationslimit hängen bleibt, eine bewusste, manuell ausgelöste
Eskalationsstufe anbieten: eine eigene Board-Spalte, in die man die Karte
zieht, löst einen automatischen Zerlege-Lauf aus, der den zu großen
Intent in mehrere kleinere, unabhängige Kind-Intents aufteilt. Das
Zusammenführen der Ergebnisse am Ende ist **kein neuer Mechanismus** —
dafür wird der bereits entworfene, aber noch nicht gebaute
Synthese-Schritt aus `docs/intent/board-subintent-fanout-synthesis.md`
wiederverwendet, indem das Zerlegen genau dessen Datenmodell
(`parent_id`, Kind-Endzustände) von Anfang an befüllt.
## Umfang
- Neue Phase `aufteilen_angefordert` in `trigger.py`s `PHASES`, erreichbar
nur per manuellem Drag einer Karte, deren `last_run_status ==
"limit_reached"` **und** deren `auto_retry_attempts >= 1` ist (der
automatische Einzelversuch aus dem Fallback-Intent muss bereits
verbraucht sein) — verhindert, dass diese teurere Eskalationsstufe vor
der billigeren automatischen Wiederholung gezogen wird.
- Der Move queued einen neuen `job_type="split"`-Job in `board-agent`s
eigener Inbox (analog zu `"review"`/`"research"`).
- `worker.py` bekommt `run_split()`: ruft die Planner-Rolle read-only auf
(gleiches Sandbox-Muster wie `run_review()` — keine Schreibrechte),
Kontext ist der vollständige, unveränderte Original-Intent **plus** der
gespeicherte `builder_report`-Text aus dem/den gescheiterten
Builder-Versuch(en) (bereits auf der Karte vorhanden, kein Zugriff auf
Git-Stashes/Diffs nötig), Auftrag: den Intent in N unabhängige,
eigenständig umsetzbare Kind-Intents zerlegen.
- Antwortformat: ein Marker-Block (`===SPLIT-REPORT===` /
`===END-SPLIT-REPORT===`), der pro Kind einen eigenen Unterblock mit
Slug und vollständigem Intent-Dokumentinhalt liefert — der Wrapper
parst das und schreibt jede `docs/intent/<kind-slug>.md`-Datei selbst,
außerhalb des Modellprozesses (dasselbe „Rolle schlägt vor, Wrapper
wendet an"-Muster wie bei Review-/Research-/Commit-Marker).
- Für jedes neu geschriebene Kind: initialer State-Eintrag mit
`parent_id = <Slug der Elternkarte>`, Phase **„Geplant"** — kein
automatischer Trigger, jedes Kind durchläuft den normalen manuellen
„Geplant → In Umsetzung"-Weg, exakt wie in
`board-subintent-fanout-synthesis.md` für den Synthese-Intent gefordert.
- **Obergrenze: maximal 10 Kinder pro Zerlege-Vorschlag.** Enthält der
Marker-Block mehr als 10 Unterblöcke, wird der gesamte Vorschlag
verworfen (keine einzige Kind-Datei geschrieben) und der Job endet wie
ein fehlgeschlagener Split — dieselbe Alles-oder-nichts-Validierung,
die `run_review()` heute schon für die Entscheidungszeile durchsetzt,
keine partielle Anwendung.
- Die Elternkarte wechselt nach erfolgreichem Split in eine neue
Endphase `aufgeteilt` (analog zu `archiviert` behandelt: kein Vorwärts-
Move erlaubt außer der ohnehin immer erlaubten Rückwärtsbewegung),
bekommt `child_slugs` (Liste) zur Anzeige gesetzt.
- Farbliche/visuelle Gruppierung von Eltern-/Kindkarten im Frontend ist
**nicht Teil dieses Intents**, sondern die bereits in
`board-subintent-fanout-synthesis.md` als Folgeintent ausgeklammerte
„Board-UI-Änderung (Parent-/Child-Anzeige, Baumdarstellung)".
## Explizit ausgeschlossen
- Keine Änderung an der automatischen Einzel-Retry-Logik aus
`board-builder-limit-reached-fallback.md` — diese Eskalationsstufe
setzt exakt dort auf, wo jene endet.
- Keine automatische Weiterverkettung über die Kind-Erzeugung hinaus —
kein Kind wird automatisch auf „In Umsetzung" gesetzt, kein
Synthese-Intent wird von diesem Intent selbst erzeugt (das bleibt
vollständig Aufgabe von `board-subintent-fanout-synthesis.md`, sobald
dieses umgesetzt ist).
- Keine Board-UI-Arbeit (Farbgruppierung, Baumdarstellung) — separater,
bereits ausgeklammerter Folgeintent.
- Kein Zugriff des Zerlege-Laufs auf Git-Stashes/rohe Diffs vorheriger
Builder-Versuche — nur der bereits gespeicherte `builder_report`-Text.
- Keine Bearbeitung/Freigabe des Zerlege-Vorschlags **vor** dem Schreiben
der Kind-Dateien — die Prüfung findet stattdessen implizit dadurch
statt, dass jedes Kind zunächst in „Geplant" landet und einen normalen
manuellen Trigger braucht, nicht durch einen zusätzlichen
Freigabeschritt direkt nach dem Split.
- Setzt `board-subintent-fanout-synthesis.md` **nicht** als
Voraussetzung für die Umsetzung dieses Intents selbst voraus (das
Schreiben der Kind-Dateien mit `parent_id` funktioniert unabhängig
davon) — wohl aber für den späteren automatischen Synthese-Schritt, der
ohne jenes Intent schlicht noch nicht existiert und die Kinder dann
wie jede andere fertige Karte manuell zusammengeführt werden müssten.
## Annahmen
- Die Planner-Rolle kann read-only aufgerufen werden, ähnlich der
Reviewer-Rolle heute (`--sandbox read-only` bzw. deaktivierte
Schreibwerkzeuge je Runtime).
- Ein automatisch vorgeschlagener Zerlege-Plan ist grundsätzlich weniger
durchdacht als ein von Hand erarbeiteter — dieselbe Einschränkung, die
`board-subintent-fanout-synthesis.md` schon für automatisch erzeugte
Synthese-Intents benennt. Das Landen in „Geplant" statt eines
automatischen Triggers ist die bewusste Absicherung dagegen, keine
zusätzliche Qualitätsprüfung.
- `docs/intent/<slug>.md` bleibt die einzige Quelle der Wahrheit für den
Intent-Inhalt; `parent_id`/`child_slugs` leben ausschließlich im
Runtime-Overlay (`state.json`), nicht im Intent-Dokument selbst.
## Offene Risiken
- Die Unabhängigkeit der vorgeschlagenen Kind-Intents ist nicht
automatisch geprüft (gleiche Grundannahme wie bei
`board-builder-worktree-parallelism.md`: Unabhängigkeit ist
Planungs-, nicht Werkzeugaufgabe) — ein schlechter Zerlege-Vorschlag
mit überlappenden Zielen fällt erst beim manuellen Review jedes Kindes
auf, nicht vorher.
- Der Zerlege-Lauf selbst könnte bei einem besonders unübersichtlichen
Original-Intent an sein eigenes Iterationslimit stoßen; da das
Auslösen ein einzelner, manueller Schritt ist (kein automatischer
Retry für den Split-Job selbst vorgesehen), bleibt die Karte in diesem
Fall einfach wie zuvor stehen — kein Rekursionsrisiko.
- Falls `board-subintent-fanout-synthesis.md` nie umgesetzt wird, bleiben
automatisch erzeugte Kinder ohne automatischen Synthese-Schritt am
Ende — funktional weiterhin nutzbar (jedes Kind ist eine normale
Karte), nur ohne die automatische Zusammenführung.
## Erfolgskriterien
- Eine Karte mit `last_run_status == "limit_reached"` und bereits
verbrauchtem automatischem Retry lässt sich in die neue Spalte ziehen
und löst genau einen Zerlege-Lauf aus.
- Der Zerlege-Lauf schreibt N (maximal 10) neue `docs/intent/<slug>.md`-
Dateien mit vollständigem, eigenständigem Intent-Inhalt, jede mit
`parent_id` auf die Elternkarte in `state.json` verknüpft, Phase
„Geplant". Bei mehr als 10 vorgeschlagenen Kindern wird keine einzige
Datei geschrieben, der Split-Job gilt als fehlgeschlagen.
- Die Elternkarte wechselt nach „aufgeteilt" und referenziert ihre
Kinder; kein Kind wird automatisch angestoßen.
- Kinder verhalten sich ansonsten wie jede normale Intent-Karte
(manueller „Geplant → In Umsetzung"-Trigger, eigener Builder-/Review-
Durchlauf).
- Bestehende Tests (`test_board_agent.py`) bleiben grün oder werden
entsprechend angepasst.