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/git-intent-board-feedback.md
pijukka ff024def02 feat(board-agent): job-typed queue with Builder/Reviewer auto-trigger
Implements Phase 1 of docs/intent/git-intent-board-feedback.md: the
kanban board pilot (board-agent) gains a job_type field and now drives
the real Builder and Reviewer roles instead of only ever running
admin.md.

- board-agent/trigger.py: jobs carry job_type (default "builder").
- board-agent/worker.py: "builder" jobs translate and hand off into
  agent-codex's existing builder-inbox queue (sender=requested_by=
  Builder owner, so they run immediately) instead of duplicating
  builder.py's atomic-session/iteration-limit/stash-commit logic here.
  "review" jobs run `codex exec --sandbox read-only` against
  agents/reviewer.md and extract a ===REVIEW-REPORT=== marker block to
  write docs/review/<slug>.md themselves, outside Codex's sandbox --
  corrected after live-testing this environment's codex-cli build
  showed `--sandbox workspace-write --add-dir <dir>` does NOT scope
  writes to that directory as the intent document assumed (a write
  outside it still succeeded); `--sandbox read-only` is a real,
  verified restriction, so the "Codex proposes, wrapper applies" marker
  pattern (already used for builder.py's ===COMMIT-MESSAGE===) replaces
  the originally planned sandbox scoping.
- board-agent/completion_watcher.py (new): reacts to a finished
  board-triggered Builder run and auto-queues the follow-up review job,
  or just records the outcome if nothing was committed.
- agent-codex/builder.py: opt-in completion-hook (on_complete_dir) so
  board-triggered jobs can be observed asynchronously; a no-op for
  ordinary XMPP-driven jobs, which never set that field.
- Nix wiring for the new completion-watcher service/path unit and the
  cross-service ReadWritePaths it needs.

Two of the intent document's assumptions didn't hold and were changed
rather than implemented as originally specified (documented in the
intent doc's Status note and this repo's READMEs): no reusable
oauth2-proxy/Dex mechanism exists for internal routes, so auth stays
Traefik BasicAuth for this phase; and board-triggered Builder jobs reuse
the existing shared-checkout/stash execution model instead of new
isolated git worktrees.

68 agent-codex tests + 15 new board-agent tests pass; blunix toplevel
builds clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ANg2L2xUmNJ45t9mcv6HVT
2026-09-06 17:54:32 +02:00

229 lines
13 KiB
Markdown

# Intent: Git-natives Intent-Board mit Reviewer-Feedback
## Ziel
Ein Git-natives Intent-Board ersetzt Vikunja für den Lebenszyklus
`Idee/Backlog → Geplant → In Umsetzung → Review → bereit für Deployment →
Deployed` mit kontrolliertem Rückfluss `Review → Planung mit Feedback`.
Ein Web-UI auf blunix visualisiert den Zustand und löst zwei Übergänge
aktiv aus. Löst und ersetzt `docs/intent/kanban-board-admin-trigger.md`.
**Konsolidierung (2026-09-06):** dieses Dokument ist jetzt auch die
alleinige Fortsetzung von
`docs/intent/builder-pipeline-git-intent-board-feedback.md`, das
dieselbe Ausbaustufe in einer früheren, allgemeineren Fassung
beschrieben hatte, ohne sie explizit abzulösen. Beide Dokumente
entstanden im selben Planungsschritt (Commit `3909cbf`); die
Iterationslimit-Hälfte davon wurde als eigener, engerer Intent
ausgekoppelt (`docs/intent/builder-iterationslimit.md`, umgesetzt und
deployed 2026-09-06, Commit `e8983e4`) und ist damit erledigt, nicht mehr
offen. Die verbleibende Board-Hälfte lebt ab jetzt ausschließlich hier;
`builder-pipeline-git-intent-board-feedback.md` bleibt als historisches
Dokument liegen, wird aber nicht mehr separat umgesetzt (gleiches Muster
wie bei `kanban-board-admin-trigger.md` oben). Inhalte aus dem
abgelösten Dokument, die hier noch fehlten, sind unten eingearbeitet
(Modellwahl-Abschnitt, zwei zusätzliche offene Risiken).
**Status: Phase 1 umgesetzt und deployed (2026-09-06).** Kern des
Job-getypten Queue-/Watcher-Mechanismus, Builder-Wiederverwendung über
`agent-codex`s bestehende `builder-inbox/`, headless Reviewer-Runner und
automatische Phasenübergänge stehen (`hosts/blunix/localServices/agent-codex/builder.py`
Completion-Hook, `hosts/blunix/localServices/board-agent/worker.py` +
`completion_watcher.py`). Zwei Annahmen unten stimmten nicht mit der
Realität überein und wurden dabei bewusst geändert statt umgesetzt wie
ursprünglich spezifiziert:
- **Auth bleibt vorerst Traefik-BasicAuth**, nicht OIDC/Dex — es gibt im
Repo keinen wiederverwendbaren `oauth2-proxy`/Dex-Mechanismus für
interne Routen (verifiziert 06.09.2026: `oauth2-proxy` ist eine
Singleton-Instanz vor einem einzigen, aktuell deaktivierten Backend).
OIDC-Self-Check (wie Forgejo/GoToSocial/Headscale) bleibt ein
eigenständiger Folge-Intent.
- **Builder-Artefakt: bestehendes Stash-Modell wiederverwendet, keine
isolierten Worktrees.** Board-Jobs laufen über den bereits gebauten,
getesteten `agent-codex`-Builder (Lock + `git stash` im geteilten
Checkout) statt über neue Worktree-Infrastruktur — bewusste
Entscheidung, siehe "Offene Risiken" unten.
- Zusätzlicher Fund: Reviewer läuft `--sandbox read-only`, nicht
`workspace-write --add-dir docs/review` — Letzteres scoped
Schreibrechte in diesem `codex-cli`-Build nachweislich NICHT
pfadgenau (live getestet). Reviewer liefert seinen Bericht stattdessen
als `===REVIEW-REPORT===`-Marker-Block, den der Wrapper außerhalb der
Sandbox schreibt.
**Weiterhin nicht Teil dieser Phase** (unverändert offen):
`docs/board/<slug>.yaml` mit automatischen lokalen Git-Commits (Board
bleibt bei `state.json`) und die Planner-Modellwahl-Eskalation aus dem
Umfang-Abschnitt unten (kein Planner-Handoff-Mechanismus für
Board-Karten vorhanden, der strukturierte Metadaten liefern könnte).
## Umfang
- `docs/intent/<slug>.md` bleibt der fachliche Auftrag; pro Intent eine
versionierte `docs/board/<slug>.yaml` mit Phase, Job-ID, Modellprofil +
Begründung, Iterationslimit/verbrauchte Iterationen (aus
`docs/intent/builder-iterationslimit.md`), Worktree-/Branch-Referenz,
Prüf-Commit, Reviewer-Bericht(e), Review-Entscheidung, Zeitpunkte,
Fehlerstatus.
- **Modellwahl** (aus `builder-pipeline-git-intent-board-feedback.md`
übernommen, dort wie in `builder-iterationslimit.md` bereits
spezifiziert): Standard ist ein günstiges Modellprofil. Der Planner
darf pro Auftrag ein stärkeres, individuell begründetes Profil
anfordern — ausschließlich aus den bekannten, konfigurierten
Profilen, niemals aus Freitext innerhalb eines Intent- oder
Reviewer-Textes heraus. Modellprofil und Begründung werden als
strukturierte Auftragsmetadaten übergeben und landen als eigene
Felder in der Board-Metadatei (siehe oben). Das Iterationslimit gilt
unabhängig vom gewählten Modell. Der Planner darf zusätzlich ein
aufgabenspezifisches Iterationsbudget vorschlagen; die Plattform
validiert es gegen die globale Obergrenze (20, siehe
`builder-iterationslimit.md`) — der genaue Validierungsmechanismus ist
Sache der Umsetzung.
- Web-UI (Tailnet-only, ausschließlich blunix) hinter der **bestehenden**
`oauth2-proxy`/Dex-Grenze für interne Dienste — keine eigene
Auth-Implementierung. Nur du (lukas) erfüllst den geforderten
OIDC-Gruppenclaim/Identität für die auslösende Aktion.
- **Ein generischer, parametrisierter Queue-/Watcher-Mechanismus**: ein
`systemd.paths`-Unit beobachtet ein Queue-Verzeichnis, Jobs tragen ein
Feld „Job-Art" (`builder` oder `review`) und werden davon abhängig an
die passende Rolle headless übergeben. Der zugehörige Dienst verarbeitet
Jobs mit **Concurrency=1** streng seriell — dadurch strukturell keine
parallelen Schreiber auf dieselbe Board-Datei, kein separates
Git-Lock-Konzept nötig.
- Aktiv steuerbar sind genau zwei Übergänge über denselben Mechanismus:
1. **Geplant → In Umsetzung**: durch dich im Web-UI ausgelöst, legt
einen `builder`-Job in die Queue. Dieser ruft die **bestehende
Builder-Rolle** headless auf (ihr bereits vorgesehener Start
`xmpp-worker` deckt das ab) — nicht den Administrator. Das
entspricht dem bestehenden Builder-Vertrag (Schreibzugriff,
Commit/Push erlaubt, kein Deploy) und weicht nicht von der
„Orchestrator ist einzige Dialogschnittstelle"-Regel für sichtbare
Spezialisten ab, weil der Builder ohnehin schon headless/direkt
ansprechbar ist.
2. **Erfolgreicher Builder-Prüf-Commit → Review**: vollautomatisch,
legt einen `review`-Job in dieselbe Queue.
- Builder-Artefakt: isolierter lokaler Git-Worktree/Job-Branch, bei Erfolg
ein lokaler Prüf-Commit, Board referenziert Commit-Hash/Branch/
Diff-Basis; Haupt-Checkout bleibt frei von halbfertigen Änderungen; bei
Limitüberschreitung (siehe `builder-iterationslimit.md`) bleibt
Zwischenstand im Worktree, gilt nicht als fertiger Prüfstand.
- Reviewer: **keine neue Aufgabenart** — die bestehende freie Diff-Review
in `reviewer.md` bekommt einen zusätzlichen, klar markierten Absatz: bei
Auslösung durch den Board-Trigger mit festem Commit-Scope schreibt sie
zusätzlich einen Bericht nach `docs/review/<slug>.md` (Intent-Slug,
geprüfter Commit, Scope/Prüfmethoden, priorisierte Befunde,
Unsicherheiten, Entscheidung, Empfehlungen) und trifft eine der zwei
Entscheidungen unten. Dieser Lauf darf headless statt `herdr-visible`
laufen (Abweichung vom sonstigen Start-Modus der Reviewer-Rolle, nur für
diesen Trigger).
- Review-Entscheidungen: `bereit für Deployment` (Board → Wartephase,
Mensch entscheidet über Push/Merge/Deployment) oder `zurück zur
Planung` (Board → Feedback-/Planungsphase, Bericht bleibt dauerhaft,
**keine** automatische neue Planner-Session — du startest sie bewusst
mit Intent+Bericht als Kontext). Nach manuellem Deployment setzt du die
Karte selbst auf `Deployed`.
## Explizit ausgeschlossen
- Ersetzt `docs/intent/kanban-board-admin-trigger.md` und
`docs/intent/builder-pipeline-git-intent-board-feedback.md` fachlich;
beide Dateien bleiben als historische Dokumente liegen, werden aber
nicht mehr separat umgesetzt.
- Kein automatischer Git-Push, kein automatisches Merge/Deployment/
Aktivierung.
- Keine automatische Planner-Session, keine automatische
Builder-Korrektur direkt aus dem Reviewer.
- Keine Verwendung/Integration von Vikunja, keine neue externe
Datenbank/SaaS-Abhängigkeit.
- Keine Änderung an `tnix`/`pinix`, keine Änderung am bestehenden
Dashboard-Stack.
- Kein öffentlicher Zugriff auf das Web-UI, kein roher API-Key für
Agentenläufe.
- Keine eigene Identitätsprüfung außerhalb des bestehenden
Dex/oauth2-proxy-Musters.
- Kein separates Git-Level-Lock-Konzept (ersetzt durch
Concurrency-1-Queue).
- Keine neue, eigenständig dokumentierte Reviewer-Aufgabenart.
- Kein neuer Rollenkatalog-Eintrag für die reine Plattforminfrastruktur
(Web-UI-Dienst, Queue-Verzeichnis, `systemd.paths`-Watcher,
`oauth2-proxy`-Route) — analog zu `agent-codex` reine NixOS-Dienste
ohne eigenen Agent-Rolleneintrag.
## Annahmen
- Primärer Ausführungspunkt bleibt `blunix`; Git ist der dauerhafte
Audit-Trail.
- `docs/intent/builder-iterationslimit.md` ist umgesetzt und deployed
(2026-09-06, Commit `e8983e4`) — dieses Dokument definiert das Limit
nicht neu, referenziert dessen Daten (Limit 20, verbrauchte
Iterationen) nur im Board.
- Reviewer bleibt read-only gegenüber Code/Konfiguration; einzige neue
Schreibausnahme ist der Bericht unter `docs/review/`.
- „Builder" umfasst auch den Administrator bei technischen
Plattformänderungen; der `builder`-Job-Typ aus der Queue ruft aber
konkret die Builder-Rolle auf, nicht den Administrator.
- Der bestehende `oauth2-proxy`/Dex-Mechanismus lässt sich analog zu
anderen internen Diensten auf dieses Web-UI anwenden.
- Die Umsetzung ändert `agents/reviewer.md` (neuer Absatz für
board-getriggerten Review), `agents/catalog.json` und
`agents/claude-settings/reviewer.json` (Versionsbump, Klarstellung des
headless-Starts für diesen Trigger).
## Offene Risiken
- **Entschieden und umgesetzt (2026-09-06):** Board-Jobs verwenden den
bestehenden, geteilten Builder-Checkout (Lock + `git stash`,
`locked_repos()`/`stash_foreign_changes()`) statt eines isolierten
Worktrees/Job-Branches — die "Builder-Artefakt"-Formulierung oben gilt
fachlich als entsprechend abgeschwächt für diese Phase. Wiedervorlage,
falls echte Parallelität mehrerer gleichzeitiger Board-Jobs mal
gebraucht wird.
- **Neu, aus der Konsolidierung:** ein lokaler Commit ohne Push kann auf
einem anderen Checkout (z. B. dem Recovery-Checkout auf pinix)
unsichtbar bleiben. Der manuelle Veröffentlichungsweg (wer pusht wann,
von welchem Checkout aus) muss dokumentiert sein, bevor das Board
produktiv genutzt wird.
- **Bereits gelöst, nicht mehr offen:** zuverlässiges Zählen der
Codex-JSON-Ereignisse für das Iterationslimit — erledigt in
`common.run_streaming()`/`builder.py` (`item.completed`-Events, live
gegen `codex-cli` verifiziert). Ebenso bereits gelöst: der
board-getriggerte Reviewer-Absatz existiert schon in
`agents/reviewer.md` (Commit `3909cbf`), muss also bei der Umsetzung
nur noch tatsächlich aufgerufen werden, nicht neu entworfen.
- Selbst-Trigger-Vermeidung: auch mit Concurrency-1-Queue muss der
Watcher-Mechanismus so gebaut sein, dass er nicht auf eigene
Status-Update-Schreibvorgänge in der Board-Datei reagiert (Trigger
sollte an neue Job-Dateien in der Queue gebunden sein, nicht an jede
Änderung der YAML-Datei selbst) — Detailkonstruktion ist Sache der
Umsetzung.
- Abgebrochener Worktree braucht Aufräum-, Wiederaufnahme- und
Verwerfungsregeln.
- Exaktes Job-/Queue-Schema für beide Job-Arten, Fehlerbehandlung bei
abstürzendem/unterbrochenem Lauf (z. B. durch einen Deploy, der den
Worker-Dienst neu lädt).
- Automatische lokale Board-Commits brauchen eine technische
Git-Identität.
- **Vertagt (2026-09-06):** genaue OIDC-Gruppen-/Claim-Anforderung für den
Trigger-Endpunkt — Auth bleibt für diese Phase BasicAuth (siehe
Status-Notiz oben), wird also erst mit dem OIDC-Folge-Intent relevant.
## Erfolgskriterien
- Board aktualisiert Zustand ausschließlich über versionierte
Metadateien und lokale Git-Commits, kein automatischer Push/Deploy.
- Eine fertige Intent-Karte lässt sich im Web-UI nur von dir (verifiziert
über die bestehende OIDC-Grenze) von „Geplant" nach „In Umsetzung"
bewegen und löst nachweisbar einen echten headless Builder-Lauf aus.
- Jeder erfolgreiche Builder-Commit startet automatisch genau einen
Reviewer-Lauf über denselben generischen Mechanismus, der einen
Bericht unter `docs/review/` erzeugt.
- Zu keinem Zeitpunkt schreiben zwei Prozesse gleichzeitig dieselbe
Board-Datei (verifiziert durch Concurrency-1-Queue-Verhalten).
- Positiver Review → `bereit für Deployment`; negativer Review →
`zurück zur Planung` mit Bericht im Planner-Kontext verfügbar.
- Web-UI läuft ausschließlich Tailnet-erreichbar hinter bestehender
OIDC-Grenze, kein öffentlicher Zugriff, kein roher API-Key.
- Ablauf funktioniert ohne Vikunja, ohne neue externe Datenbank, ohne
Änderungen an `tnix`/`pinix`/Dashboard-Stack.
- `docs/intent/kanban-board-admin-trigger.md` und
`docs/intent/builder-pipeline-git-intent-board-feedback.md` gelten als
durch diesen Intent abgelöst.