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

7.5 KiB

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.pys 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-agents 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.