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-interactive-planner-intake.md
pijukka 7c8c8c8f77 board: pin Agents column, fix smoke-test cleanup sandbox, add interactive Planner intake
- board.html: replace the collapsible "Agent profiles" <details> panel
  (which re-collapsed on every 5s refresh) with a fixed, always-visible
  Agents column on the left, plus a bulk "apply to all" runtime dropdown
  and per-phase links to view each role's agents/*.md prompt in the
  existing Intent-dialog mechanism.
- board-agent.nix/trigger.py: fix the "Smoke-Tests entfernen" 502 --
  board-agent-trigger's sandbox only had docs/intent writable, not
  docs/review/research(-intent); widened ReadWritePaths and made the
  delete loop tolerate a per-file OSError instead of dying mid-request.
- board.html: pause the periodic 5s render() while any board input/
  select/textarea has focus, instead of unconditionally rebuilding the
  DOM and stealing keystrokes out of whatever the operator was typing.
- New job_type="draft" (worker.py/trigger.py): an interactive,
  multi-turn Planner intake dialogue ("+ Karte (interaktiv)") that
  starts a card from a topic instead of a hand-written intent document.
  Each turn resends the conversation so far to a read-only, repo-less
  Planner call and gets back either a follow-up question (with
  quick-reply options) or a finished intent, which the wrapper -- never
  the model -- writes to docs/intent/<slug>.md before replacing the
  draft card with a normal "geplant" one. See
  docs/intent/board-interactive-planner-intake.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016w25covboHfcYuLXBAvX3g
2026-09-10 18:00:40 +02:00

6.6 KiB
Raw Permalink Blame History

Intent: Interaktive Intent-Erstellung über eine Planner-Konversation im Board

Ziel

Eine dritte Art, eine Karte auf dem Intent-Board anzulegen, neben dem manuellen Schreiben eines docs/intent/<slug>.md-Dokuments von Hand und dem einfachen "+ Karte"-Backlog-Eintrag: ein Button auf dem Backlog ("+ Karte (interaktiv)"), der ein Thema entgegennimmt und daraus eine mehrrundige Rückfrage-Konversation mit der Planner-Rolle startet, bis genug Kontext für einen vollständigen, eigenständigen Intent vorliegt. Motivation aus einer Live-Diskussion auf dem Board selbst (10.09.2026): die Operator-typische Vorarbeit ("mit einem Planner reden, bis der Auftrag klar ist") sollte auch ohne separate Chat-Session möglich sein, direkt im Board, mit Buttons statt Freitext wo sinnvoll.

Umfang

  • Neue Karten-Quelle "draft" (parallel zu "idea"): lebt ausschließlich in state.json, keine Backing-Datei, bis die Konversation abgeschlossen ist. create_draft(topic) legt sie an (draft-<uuid>) und queued sofort die erste Planner-Runde mit dem Thema als einziger Nachricht.
  • Neuer job_type="draft" in worker.py: run_draft() ruft die Planner-Rolle ohne jeden Repo-Zugriff auf (kein -C in den Checkout, kein --add-dir) — ein Entwurf hat noch keine existierenden Dateien zu lesen, und Lesezugriff auf einen noch unfertigen, ungescopten Intent hätte hier keinen Nutzen. Jede Runde bekommt die vollständige bisherige Konversation als Text mitgegeben; es gibt keine persistente Modell-Session, Kontinuität lebt ausschließlich in state.jsons draft_conversation.
  • Antwortformat: pro Runde genau ein Marker-Block, nie beide, nie keiner:
    • ===DRAFT-QUESTION=== / ===END-DRAFT-QUESTION===: eine konkrete Rückfrage plus optional bis zu vier kurze Antwortvorschläge (optionen: a | b | c | d oder optionen: keine) — das Frontend rendert sie als Buttons, zusätzlich zu einem freien Textfeld.
    • ===DRAFT-INTENT=== / ===END-DRAFT-INTENT===: slug:-Kopfzeile plus vollständiger Intent-Dokumentinhalt, exakt das slug: ... / --- / Inhalt-Format, das run_split() für seine ===CHILD===-Unterblöcke bereits verwendet.
  • Eine Rückfrage aktualisiert nur draft_conversation und setzt die Karte auf entwurf_frage — kein Repo-Zugriff, kein Lock, läuft neben Builder/Review/Research/Split her.
  • Ein fertiger Intent wird vom Wrapper, nie vom Modell, als docs/intent/<slug>.md geschrieben — derselbe "Rolle schlägt vor, Wrapper wendet an"-Grundsatz wie bei Review/Research/Split. Dieser eine Schreibmoment läuft unter demselben acquire_repo_lock() wie run_split(), nicht die ganze Konversation. Ein Slug-Kollision (Zieldatei existiert schon) verwirft den Vorschlag vollständig, die Karte bleibt in entwurf_fehlgeschlagen für einen manuellen erneuten Versuch.
  • Nach erfolgreichem Schreiben ersetzt record_draft_intent() den draft-<uuid>-State-Eintrag durch eine normale Karte unter dem neuen Slug, Phase "Geplant" — kein Auto-Trigger, derselbe manuelle "Geplant → In Umsetzung"-Weg wie jede andere Karte. draft_origin verlinkt zurück auf die ursprüngliche Dialog-ID, draft_conversation bleibt als Audit-Trail erhalten.
  • Antworten/erneute Versuche: answer_draft(card_id, answer) (nur bei Phase entwurf_frage, max. 4000 Zeichen, max. 40 Konversationsrunden) und retry_draft(card_id) (nur bei Phase entwurf_fehlgeschlagen, sendet die letzte Runde unverändert erneut). Beide über eigene POST /api/board/cards/<id>/draft-answer bzw. .../draft-retry.
  • delete_manual_card() (vormals delete_idea()) akzeptiert jetzt "idea" und "draft" als löschbare Quellen — ein abgebrochener Entwurf verschwindet über denselben "×"-Button wie eine Idee-Karte.
  • Frontend: eigene Spalten-Zuordnung (entwurf_laeuft → "Running", entwurf_frage/entwurf_fehlgeschlagen → "Needs attention"), eigenes Transkript-Rendering (appendDraftDialogue()), Options-Buttons plus Freitextfeld für eine offene Rückfrage, "Erneut versuchen" bei einem Fehlschlag.
  • Nebenbefund aus derselben Diskussion, unabhängig vom Rest dieses Intents: der periodische 5-Sekunden-Refresh (setInterval(render, ...)) pausiert jetzt, solange ein Formularelement innerhalb des Boards fokussiert ist (boardEditInProgress()), statt bei jedem Tick bedingungslos die gesamte DOM neu aufzubauen und damit Fokus/Eingabe zu zerstören — betrifft auch dieses Feature direkt (ein offenes Antwortfeld im laufenden Dialog).

Explizit ausgeschlossen

  • Datei-Anhänge (Bild, Audio) an einen Entwurf — keiner der Runtimes bekommt über diesen CLI-Wrapper-Pfad heute nicht-textuelle Eingaben; Audio bräuchte zusätzlich einen eigenen Transkriptionsschritt. Separater Folgeintent, falls gewünscht.
  • Eine strukturierte Formular-Alternative (feste Felder statt freier Konversation) — als schnellerer, modellfreier Weg diskutiert, aber bewusst nicht Teil dieses Intents.
  • Eine "Telefonat"-artige Sprachschnittstelle — als Fernziel genannt, explizit als zu früh eingestuft.
  • Column-Config-UI (Runtime/Modell-Dropdown) für die Draft-Spalte — nutzt wie run_split() feste BOARD_PLANNER_*-Defaults ohne eigenes UI-Override.
  • Automatische Qualitätsprüfung des fertigen Intent-Vorschlags — wie überall sonst in diesem Repo liest ein Mensch das Ergebnis, bevor es über "Geplant → In Umsetzung" weiterläuft.
  • known_card_ids()/Fan-out-Verlinkung für Entwürfe — ein Entwurf ist erst nach Fertigstellung eine "echte" Karte.

Annahmen

  • Die Planner-Rolle liefert ohne Repo-Kontext trotzdem sinnvolle Rückfragen, solange die Konversation selbst genug Substanz enthält — ungetestete Annahme, zu beobachten im echten Einsatz.
  • Ein Operator bricht eine ausufernde Konversation eher selbst ab (Löschen, neu beginnen) als bis zum harten 40-Runden-Limit zu gehen; das Limit ist eine Notbremse, kein erwarteter Normalfall.

Offene Risiken

  • Kein Locking zwischen answer_draft()/retry_draft() und einem bereits laufenden draft-Job für dieselbe Karte — zwei schnell aufeinanderfolgende Klicks könnten zwei Runden gleichzeitig queuen. Geringes Risiko bei einem einzelnen Operator, nicht ausgeschlossen bei mehreren gleichzeitigen Nutzern.
  • Ein Slug-Kollision bei der Finalisierung lässt den Entwurf in entwurf_fehlgeschlagen liegen; ein bloßer "Erneut versuchen" sendet dieselbe Konversation erneut und bekommt mit realistischer Wahrscheinlichkeit wieder denselben Slug vorgeschlagen. Für den ersten Wurf akzeptiert; falls das in der Praxis stört, bräuchte es eine eigene "anderen Slug vorschlagen"-Rückmeldung an den Planner.