Agent-Cockpit — Implementations-Plan
Overview
Marvin springt parallel zwischen 5-6 Coding-Chats und verliert beim Switch den Kontext. Aktuelle Antworten sind zu lang, zu tech-zentriert. Lösung: pro aktivem Projekt eine state.md die der Agent nach jeder Phase pflegt. Das bestehende projekt-dashboard (Next.js 16, av-cockpit-Repo) rendert sie als Cockpit-Karte auf /projekte/[slug] plus /cockpit-Übersichtsseite mit allen aktiven Projekten gleichzeitig. CLAUDE.md-Rules zwingen Antworten auf 3 Zeilen + Link und Agent in Tech-Lead-Persona. Live-Sync via S3-JSON-Push + SWR-Polling (Sub-10s-Frische, quasi-Kostenfrei auf bestehender Infra). Optional: project-diagram Skill als Schwester von SKILL für visuelle Architektur-Snapshots.
Pivot-These: Chat-Output ist flüchtig. Source of Truth lebt im Vault, sichtbar via Dashboard. Der Chat wird zur Steuer-Schicht, nicht zum Status-Speicher.
Live-These: state.md im Vault bleibt Source of Truth. Push-Script spiegelt sie als JSON nach S3 (bestehender av-dashboard-data-Bucket). Frontend pollt mit SWR. Keine neue Infra, keine WebSockets, keine SSR-Umstellung.
Problem Frame
Heute: Ziel:
┌─────────────┐ ┌─────────────────────────┐
│ Chat 1 ████ │ ← scrollen │ Cockpit (Dashboard) │
│ Chat 2 ████ │ ← scrollen │ ┌───────────────────┐ │
│ Chat 3 ████ │ ← scrollen │ │ Phase ●→●→○→○→○ │ │
│ Chat 4 ████ │ ← scrollen │ │ Letzte: ... │ │
│ Chat 5 ████ │ ← suchen │ │ Nächste: ... │ │
└─────────────┘ │ └───────────────────┘ │
└─────────────────────────┘
Status = im Chat verstreut Status = ein Ort, immer aktuell
Antwort lang + tech-tief Antwort 3 Zeilen + Link
Requirements Trace
- R1 Pro aktivem Projekt eine
state.mdmit Phasenpfeil, letzter Entscheidung, nächster Frage, Decisions-Log - R2 Agent updated
state.mdnach jeder Coding-Pipeline-Phase (Rule 21 erweitert) - R3 Bestehendes Dashboard rendert
state.mdals Cockpit-Karte auf/projekte/[slug] - R4 Chat-Antworten in Coding-Sessions standardmäßig auf 3 Zeilen + Link begrenzt
- R5 Persona-Switch: Agent reportet als Tech-Lead an Marvin (Direktor), nicht Pair-Programmer
- R6 Modi-Override: „geh tief” deaktiviert die Kürze für nächste Antwort
- R7
state.mdist human-readable Markdown — Marvin liest sie direkt auch ohne Dashboard - R8 Architektur-Snapshot pro Projekt visuell verfügbar (Schwester-Skill
project-diagram) - R9
/cockpit-Übersichtsseite zeigt alle aktiven Projekte mit Cockpit-Karten gleichzeitig, sortiert nachupdated_atDESC - R10 Live-Sicht: state.md-Änderung erscheint im Dashboard innerhalb ≤10s (Polling-Intervall) ohne Marvin-Aktion
- R11 Live-Push läuft auf bestehender Infra ohne neue AWS-Ressource zu provisionieren — Ziel-Kosten <$1/Monat zusätzlich
Scope Boundaries
Im Scope:
- Schema-Definition
state.md+ Pilot in 2 aktiven Projekten - Dashboard-Detail-Route
/projekte/[slug]mit Cockpit-Karte (war eh schon offen, siehe _index Offene Baustelle #2) /cockpit-Übersichtsseite mit allen aktiven Projekten gleichzeitig- CLAUDE.md Rule 23 + 24 + neuer
wissen/prozesse/chat-output-disziplin.md - Push-Script
push-state.mjs(lokal, AWS SDK) → S3-JSON-Sync <LiveCockpit />Client-Component mit SWR-Polling + Page-Visibility + ETag-Conditional-Requests- CloudFront-Cache-Config für
/api/states/*Pfad - Schwester-Skill
project-diagramvon SKILL abgeleitet
Out of Scope:
- Echte Sub-Sekunde-Live-Updates via SSE/WebSocket (SWR mit 5s Polling reicht)
- Automatische
state.md-Generierung aus Git-History (manuell vom Agent gepflegt, nicht via Cron) - Replacement von bestehenden
phase-N.md-Files (z.B. bedrock-cost-optimize) —state.mdist Aggregator, nicht Ersatz, verlinkt auf Detail-Files - Drag-and-Drop für Cockpit-Karten
- Dedizierter
dashboard-mcpServer (Script reicht; MCP wenn Pattern reift, Welle 2) - File-Watcher Daemon — Behavior-Rule 23 + Script-Aufruf nach jedem state.md-Write reicht
Phasen-Overview
flowchart LR P1[P1<br/>Schema +<br/>2 Piloten] --> P2[P2<br/>CLAUDE.md<br/>Rules 23+24] P2 --> P3[P3<br/>vault.ts<br/>erweitern] P3 --> P4[P4<br/>Detail-Route<br/>+ Cockpit-Karte] P4 --> P6[P6<br/>/cockpit<br/>Übersicht] P6 --> P7[P7<br/>push-state.mjs<br/>+ Rule-Update] P7 --> P8[P8<br/>LiveCockpit<br/>SWR Client] P8 --> P9[P9<br/>CloudFront<br/>Cache-Config] P9 --> P5[P5<br/>project-diagram<br/>optional]
Reihenfolge-Begründung:
- P1-P2: Schema + Rules zuerst — damit erste
state.md-Files entstehen - P3-P4: Reader + Detail-Karte — statisches Rendering läuft, validiert Schema
- P6: Übersichtsseite — alle Karten gestapelt, immer noch statisch (Build-Time)
- P7-P9: Live-Schicht obendrauf — Push-Script, Client-Polling, Cache-Config. Genau am Ende, wie Marvin gesagt hat: „step by step und dann ganz am Ende das API Root”.
- P5: project-diagram Bonus, parallel oder später
Zeit grob:
- P1+P2 = ~1.5h (Schema + Rules)
- P3+P4 = ~3-4h (Code in av-cockpit, Detail-Route)
- P6 = ~2h (Übersichtsseite)
- P7 = ~1h (Push-Script + AWS SDK)
- P8 = ~2h (SWR Client mit Page-Visibility + ETag)
- P9 = ~30min (CloudFront-Behavior + Cache-Headers)
- P5 = ~1-2h (Skill-Fork, optional)
Total ~10-13h (ohne P5 ~9-11h).
Context & Research
Relevant Code
- vault.ts — Vault-Bridge im av-cockpit Repo.
loadProjects()liestintern/projekte/*/_index.mdvia gray-matter. Erweitern umloadProjectState(slug). - page.tsx — Kanban-Übersicht mit
PipelineCard. Karten verlinken auf/projekte/[slug](neu). - schemas.md §5.5 — bestehendes Project-Schema. Ergänzen um Abschnitt 5.X State.
- SKILL.md — Blaupause für
project-diagram. 4 feste Sektionen, Excalidraw + SVG + HTML, inkrementelles Update bei Re-Run. - render.mjs — Render-Pipeline wiederverwendbar.
- CLAUDE.md Rule 9 + 15 + 21 — Bestehende Format-/Phasen-Rules. Neue Rules ordnen sich daneben ein.
Existing State-Pattern (heute)
bas-twin/_index.mdFrontmatter:phase: sprint-1,kanban_phase: vertrag,ball_bei: kunde,next_step: "..."— gut für Übersichts-Liste, zu flach für Cockpit-Tiefe.bedrock-cost-optimize/hat 6phase-N-*.md-Files plusplan.md— zu granular für Schnellblick, kein einheitlicher Status-Anker.openwebui-vf/hat 20+ Files (Sprint-Spec, Session-Prompts, Welle-1-4-Docs) — schwer zu navigieren ohne Cockpit.
Lücke: Es gibt keinen einheitlichen „wo stehen wir gerade”-File. state.md schließt sie.
Institutional Learnings
- ADHS-Pattern (siehe marvin-profile): visueller Typ, lange Listen erzeugen Paralysis. Cockpit zeigt nur 5 Felder, nicht 20.
- Rule 9 (Ein-Schritt-Prinzip): „nächste Frage” auf der Karte ist genau dieser eine Schritt.
- Rule 21 (phasenbewusst): jede Coding-Phase bekommt ein Update.
- Reference, don’t duplicate (Rule 3):
state.mdverlinkt aufplan.mdundphase-N.md, repliziert nicht.
Key Technical Decisions
| Entscheidung | Begründung |
|---|---|
state.md separates File, nicht im _index.md | _index.md-Frontmatter ist stabil (Schema 5.5, dashboard-managed Felder). State ist flüchtig und dürftig zu mergen. Trennung verhindert Frontmatter-Bloat. |
Markdown-Body mit ## Sektionen, nicht reines YAML | Marvin liest direkt ohne Dashboard. Sektion-Splitter im Parser ist trivial. |
| Phasenpfeil als Frontmatter-Liste + Marker-Mapping | YAML-Array phases: [{name, status}] ist trivial zu rendern. Markdown-Body kann Phasen-Detail haben. |
loadProjectState(slug) erweitert vault.ts, kein neues Package | Bestehender Pattern, kein neuer Loader-Layer. |
| Behavior-Rule 23+24 statt 1 große Rule | Pflege (23) und Output-Format (24) sind orthogonal. Override-Switch klarer pro Rule. |
project-diagram als eigener Skill, nicht customer-diagram-Erweiterung | Andere 4 Sektionen, andere Trigger-Phrasen. Cleaner als Mode-Parameter. |
| Detail-Route nutzt bestehende av-cockpit-Komponenten + Recharts | Kein neues UI-Framework. Phasenpfeil = horizontaler SVG-Component (~30 Zeilen). |
High-Level Technical Design
Directional guidance, nicht Implementation-Spec.
state.md Struktur (Vorschlag)
---
id: state-<projekt-slug>
type: project_state
project: "[[_index]]"
updated_at: 2026-05-21T16:30:00+02:00
mode: coding-pipeline # coding-pipeline | research | sales | maintenance
phases:
- { name: "Schema + Piloten", status: done }
- { name: "CLAUDE.md Rules", status: active }
- { name: "vault.ts", status: todo }
- { name: "Detail-Route", status: todo }
- { name: "project-diagram", status: todo }
---
## Letzte Entscheidung
state.md wird als separates File geführt, nicht in _index.md gemerged. (2026-05-21)
## Nächste Frage
Brauchen wir Modi-Switch ("geh tief") als CLAUDE.md-Anweisung oder als
explizites Marvin-Wort?
## Decisions-Log
- 2026-05-21 — Markdown-Body statt reines YAML (human-readable)
- 2026-05-21 — Eigener Skill project-diagram statt customer-diagram-Mode
## Offene Baustellen
- [[plan-agent-cockpit#open-questions|Open Questions]]Phasenpfeil-Rendering (Dashboard)
Phase ●━━━●━━━●━━━○━━━○
Schema Rules Reader Karte Diagramm
done active todo todo todo
Marker-Mapping: done=● active=◐ todo=○. Verbindungen=━ für abgeschlossene Übergänge, ┄ für offene. Horizontal SVG, scrollbar bei >7 Phasen.
Cockpit-Karten-Layout
┌──────────────────────────────────────────────────┐
│ <projekt-name> updated 2h │
│ ●━━━●━━━◐━━━○━━━○ │
├──────────────────────────────────────────────────┤
│ Letzte Entscheidung: │
│ state.md separat, nicht gemerged │
├──────────────────────────────────────────────────┤
│ Nächste Frage: │
│ Modi-Switch via CLAUDE.md oder Marvin-Wort? │
├──────────────────────────────────────────────────┤
│ [ Decisions ▾ ] [ Open Items ▾ ] │
└──────────────────────────────────────────────────┘
Implementation Units
Unit 1: state.md Schema definieren + 2 Piloten
- Goal: Stabiles Schema in
_meta/schemas.md+ 2 reale state.md-Files als Lebendprobe.
Requirements: R1, R7
Files:
- Modify:
_meta/schemas.md(neuer Abschnitt 5.13 oder hinter 5.5) - Create:
intern/projekte/projekt-dashboard/state.md(Pilot 1, dieses Projekt) - Create:
intern/projekte/bas-twin/state.md(Pilot 2, aktivstes Kunden-Projekt)
Approach:
- Schema-Felder:
id,type: project_state,project(Wikilink auf_index),updated_at(ISO-8601),mode(enum),phases(Array {name, status}) - Status-Enum:
done | active | todo | blocked - Body-Sektionen Pflicht:
## Letzte Entscheidung,## Nächste Frage,## Decisions-Log,## Offene Baustellen - Pflege-Regel:
updated_atMUSS bei jeder Änderung neu gesetzt werden (von Agent automatisch, von Mensch optional)
Patterns to follow: schemas.md §5.5 Project Frontmatter-Stil.
Verification: gray-matter parsed beide Pilot-Files ohne Fehler. Schema-Dokumentation hat Beispiel.
Unit 2: CLAUDE.md Rules 23+24 + wissen-Eintrag
- Goal: Pflege-Pflicht + Chat-Format formal verankern.
Requirements: R2, R4, R5, R6
Files:
- Modify:
CLAUDE.md(neue Rules 23 + 24, eingefügt nach Rule 22) - Create:
intern/wissen/prozesse/chat-output-disziplin.md
Approach:
Rule 23 — state.md pflegen. Bei jeder Coding-Pipeline-Phase (Rule 21) am Ende der Phase die zugehörige intern/projekte/<slug>/state.md aktualisieren: updated_at, betroffene Phase auf nächsten Status, neue Entscheidung in Letzte Entscheidung (alte wandert in Decisions-Log), neue offene Frage in Nächste Frage. Wenn keine state.md existiert und das Projekt aktiv ist: anlegen.
Rule 24 — Chat-Output-Disziplin. Default-Antwort in Coding-Sessions: max 3 Zeilen Text + Link auf state.md oder Cockpit-URL. Persona: Tech-Lead reportet an Direktor (Marvin), nicht Pair-Programmer. Verboten: Pre-Tool-Narration („jetzt mache ich X”), Tool-Output-Echo („gelesen eine Datei”), Code-Snippets ohne Anforderung. Erlaubt: Resultat + Entscheidungsfrage. Override: Wenn Marvin „geh tief”, „erklär”, „zeig Details” sagt → nächste Antwort darf lang + technisch sein, danach zurück auf Default.
chat-output-disziplin.md ergänzt mit:
- Konkrete Anti-Patterns (Beispiele aus aktuellem Chat-Stil)
- Beispiel-Antworten: gutes Format vs schlechtes Format side-by-side
- Wann Rule 24 NICHT gilt (Debug-Session, Brainstorm, Explain-Anfrage)
Verification: Marvin liest die neuen Rules und kann sich darin erkennen. Ein Test-Coding-Chat zeigt deutlich kürzere Antworten.
Unit 3: vault.ts erweitern um loadProjectState
- Goal: av-cockpit kann
state.mdlesen.
Requirements: R3
Dependencies: Unit 1 (Schema muss stehen)
Files:
- Modify:
~/source/av-cockpit/src/lib/vault.ts
Approach:
- Neue Types:
ProjectState,Phase,PhaseStatus - Neue Funktion
loadProjectState(slug: string): ProjectState | null- Liest
<VAULT_ROOT>/intern/projekte/<slug>/state.md gray-matterfür Frontmatter (phases,updated_at,mode)- Body-Parser splittet auf
##-Headings: Letzte Entscheidung, Nächste Frage, Decisions-Log (Liste), Offene Baustellen (Liste)
- Liest
loadProjects()UNVERÄNDERT lassen —state.mdist separat geladen, nicht gemerged- Fehlerfall: File existiert nicht →
nullzurück, kein Throw
Patterns to follow:
loadProjects()undloadCustomers()in derselben Datei — selber Style (gray-matter, fs.readFileSync, defensive parsing)toDate,toStringOrUndefinedHelpers wiederverwenden
Test scenarios:
- Happy path:
loadProjectState("projekt-dashboard")gibtProjectStatemit 5 Phasen, korrektemupdated_at, gefüllten Body-Sektionen - Edge case: File existiert nicht →
null - Edge case: Frontmatter ohne
phases→ leeres Array, kein Crash - Edge case: Body ohne erwartete
##-Headings → leere Strings/Arrays in den Feldern
Verification: Manueller Aufruf im Node-REPL via tsx gibt erwartete Shape für beide Piloten zurück.
Unit 4: /projekte/[slug] Detail-Route + Cockpit-Karte
- Goal: Dashboard rendert state.md visuell.
Requirements: R3
Dependencies: Unit 3 (vault.ts), Unit 1 (Piloten)
Files:
- Create:
~/source/av-cockpit/src/app/projekte/[slug]/page.tsx - Create:
~/source/av-cockpit/src/components/cockpit-card.tsx - Create:
~/source/av-cockpit/src/components/phase-arrow.tsx
Approach:
- Server Component
page.tsxlädt Projekt-Card (über bestehendesloadProjects()+slug-Filter) plusloadProjectState(slug) - Layout: Header (Projekt-Name + Frontmatter-Quickdata) →
<CockpitCard state={state} />→ Tasks-Liste (aus_index.md) → Decisions-Log einklappbar → Footer mit Links zu plan.md, runbook.md <PhaseArrow phases={state.phases} />— eigene SVG-Komponente, ~50 Zeilen, kein Recharts (overkill)- Markup-Style: konsistent zu bestehender
PipelineCardinprojekte/page.tsx - Wenn
state.mdfehlt: Empty-State-Karte „Noch kein Cockpit. Anlegen via Agent in der nächsten Coding-Session.”
Patterns to follow:
src/app/cloud/page.tsxfür Server-Component + Daten-Loading-Patternsrc/app/projekte/page.tsxfür Card-Styling- Vorhandener Prototyp bas-twin-overview.html als visuelles Vorbild
Test scenarios:
- Happy path:
/projekte/projekt-dashboardrendert Cockpit-Karte mit Phasenpfeil, Letzter Entscheidung, Nächster Frage, Decisions-Liste - Edge case:
/projekte/<slug-ohne-state>zeigt Empty-State, kein Crash - Edge case: state.md mit nur 2 Phasen → Pfeil rendert korrekt schmal
- Edge case: state.md mit 12 Phasen → Pfeil scrolled horizontal, bricht nicht das Layout
- Mobile: 375px-Viewport zeigt Karte stacked, Pfeil scrolled
Verification: Beide Pilot-Projekte unter localhost:3000/projekte/<slug> zeigen vollständige Cockpit-Karte. Build (next build) wirft keinen Fehler.
Unit 6: /cockpit Übersichtsseite
- Goal: Eine Seite die alle aktiven Projekte mit Cockpit-Karten gleichzeitig zeigt.
Requirements: R9
Dependencies: Unit 3 (vault.ts mit loadProjectState), Unit 4 (Cockpit-Karte-Komponente existiert)
Files:
- Create:
~/source/av-cockpit/src/app/cockpit/page.tsx - Modify:
~/source/av-cockpit/src/components/sidebar.tsx(Eintrag „Cockpit” oben)
Approach:
- Server Component lädt alle
state.md-Files via neue HelperloadAllProjectStates()invault.ts - Filtert auf Projekte wo
_index.mdFrontmatterstatus: active - Sortiert nach
state.updated_atDESC - Rendert vertikal gestapelt
<CockpitCard />Komponenten (Unit 4) - Filter-Bar oben: nach
mode(coding-pipeline | research | sales | maintenance) - Stale-Indikator: wenn
updated_at > 7 Tage→ grauer Rahmen + Hinweis „letzter Update vor X Tagen” - Empty-State: wenn kein Projekt aktiv → „Noch keine aktiven Projekte mit Cockpit”
Patterns to follow:
src/app/projekte/page.tsx— Kanban-Layout-Pattern, kann man fast 1:1 adaptieren auf vertikales Stapeln- Sidebar-Pattern in
src/components/sidebar.tsx
Test scenarios:
- Happy path: Beide Pilot-Projekte erscheinen auf
/cockpit, projekt-dashboard oben (neuester Update) - Edge case: Projekt mit
status: pausedtaucht NICHT auf - Edge case: Projekt ohne state.md taucht NICHT auf (auch wenn aktiv)
- Edge case: Alle Projekte stale → Liste zeigt, aber alle mit grauem Rahmen
- Mobile: Karten stacken sauber auf 375px
Verification: /cockpit lädt unter 1s, zeigt alle Pilot-Karten korrekt sortiert.
Unit 7: push-state.mjs Script + Behavior-Rule-Update
- Goal: Agent kann state.md-Änderungen 1-Click nach S3 synchronisieren.
Requirements: R10, R11
Dependencies: Unit 1 (Schema), Unit 3 (Parser-Logik kann wiederverwendet werden)
Files:
- Create:
~/source/av-cockpit/scripts/push-state.mjs - Modify:
~/source/av-cockpit/package.json(npm-Skriptpush-state) - Modify:
CLAUDE.md(Rule 23 ergänzen um Push-Schritt) - Modify:
intern/wissen/prozesse/chat-output-disziplin.md(Push-Workflow dokumentieren)
Approach:
- Script-Signatur:
node scripts/push-state.mjs <slug>odernpm run push-state -- <slug> - Liest
<VAULT_ROOT>/intern/projekte/<slug>/state.mdmit gray-matter - Parsed Body-Sektionen (gleicher Parser-Code wie in Unit 3, geteilt via
src/lib/state-parser.ts) - Serialisiert zu JSON-Shape (passt zu
<LiveCockpit />Erwartungen) - Diff-Check: lade aktuelle S3-Version (falls existiert), vergleiche Content-Hash → skip wenn identisch
- AWS SDK v3 (
@aws-sdk/client-s3ist in av-cockpit Repo vermutlich schon drin, sonst install) - Auth: AWS-Profile
av-productionüber SSO (Marvin ist sowieso eingeloggt) - Target:
s3://av-dashboard-data-425924867359/api/states/<slug>.json - Content-Type:
application/json - Cache-Control-Header:
public, max-age=10, s-maxage=10(CloudFront cached 10s) - Log: schreibt 1 Zeile in stdout („pushed states/
.json (1.2KB)” oder „no change, skipped”)
Behavior-Rule 23 Ergänzung: nach state.md-Write IMMER npm run push-state -- <slug> ausführen. Wenn Push fehlschlägt: Marvin in 1 Zeile informieren, state.md ist trotzdem gespeichert (Vault bleibt SoT).
Patterns to follow:
- AWS SDK v3 Style in
~/source/agents-platform/lambdas/dashboard-refresh/(Python, aber gleicher S3-Bucket-Pattern) - gray-matter + fs Style in
vault.ts
Test scenarios:
- Happy path: Script läuft mit
projekt-dashboard-Slug, pusht JSON nach S3,aws s3 lszeigt File - Happy path: Zweiter Lauf ohne Änderung skipped korrekt
- Edge case: state.md fehlt → klare Fehlermeldung, Exit 1
- Edge case: AWS-Profile nicht eingeloggt → klare Fehlermeldung mit Hinweis
aws sso login --profile av-production - Edge case: Slug existiert nicht in
intern/projekte/→ Fehler mit verfügbaren Slugs - Edge case: state.md mit Schema-Fehler (z.B. ungültige Phase) → Validierungs-Fehler vor Push
Verification: aws s3 cp s3://av-dashboard-data-425924867359/api/states/projekt-dashboard.json - zeigt valide JSON-Struktur. CloudFront-URL https://dashboard.agenticventures.de/api/states/projekt-dashboard.json antwortet 200 mit korrekten Cache-Headers.
Unit 8: <LiveCockpit /> Client-Component mit SWR
- Goal: Dashboard zeigt state-Änderungen ohne Page-Reload.
Requirements: R10
Dependencies: Unit 4 (<CockpitCard /> existiert), Unit 7 (S3-JSON-Endpoints existieren)
Files:
- Create:
~/source/av-cockpit/src/components/live-cockpit.tsx("use client") - Modify:
~/source/av-cockpit/src/app/projekte/[slug]/page.tsx(Server Component lädt initialen state, übergibt an<LiveCockpit initial={...} />) - Modify:
~/source/av-cockpit/src/app/cockpit/page.tsx(gleiche Hydration für Übersichtsseite)
Approach:
- Server Component lädt state aus Vault (Build-Time, statisch)
- Übergibt als
initial-Prop an<LiveCockpit slug={slug} initial={state} /> - Client Component mit SWR:
useSWR(`/api/states/${slug}.json`, fetcher, { refreshInterval: 5000, revalidateOnFocus: true, fallbackData: initial, }) - Fetcher mit ETag-Conditional: sendet
If-None-Matchmit letztem ETag, behandelt 304 als „kein Update” - Page-Visibility-API:
document.hidden→ SWRrefreshIntervalauf0(pausieren), bei Visibility-Change zurück auf 5000 - Visual Indicator: kleiner grüner Pulse-Dot wenn frisch (<10s), grauer Dot wenn stale (>5min)
- Fallback wenn fetch fehlschlägt: zeigt
initial-Daten + Hinweis „letzter Sync:”
Patterns to follow:
- SWR-Setup wie in
~/source/av-cockpit/src/app/cloud/page.tsx(existing SWR-Usage) - Page-Visibility-Pattern:
useEffectmitvisibilitychange-Listener
Test scenarios:
- Happy path: state.md auf Maschine ändern + push-state.mjs laufen → Dashboard updated innerhalb 10s ohne Page-Reload
- Edge case: Browser-Tab nicht sichtbar → keine Network-Requests (Page-Visibility)
- Edge case: S3 offline / 503 → Dashboard zeigt letzten Stand + „Sync-Fehler”
- Edge case: ETag-304 → SWR behandelt als „kein Update”, kein Re-Render
- Edge case: Initial-State leer (
null) → Empty-State angezeigt, kein Crash
Verification: Marvin ändert eine state.md in Coding-Session, push-state.mjs läuft, Dashboard zeigt innerhalb 10s den neuen Stand ohne F5.
Unit 9: CloudFront-Cache-Config + S3-CORS
- Goal: Live-Endpoints sind günstig + responsive cached.
Requirements: R11
Dependencies: Unit 7 (Endpoints existieren), Unit 8 (Frontend will sie lesen)
Files:
- Modify: CloudFront-Distribution
E3KFMPWSKO68UU(via AWS Console oderaws cloudfront update-distribution) - Modify: S3-Bucket-Policy
av-dashboard-data-425924867359(CORS-Config falls nicht schon korrekt) - Document:
intern/projekte/projekt-dashboard/runbook.md(neuer Abschnitt „Live-State CloudFront-Behavior”)
Approach:
- Neue CloudFront-Behavior für Path-Pattern
/api/states/*:- Origin: S3-Bucket
av-dashboard-data-425924867359 - Allowed Methods:
GET, HEAD, OPTIONS - Cached Methods:
GET, HEAD - Cache Policy: Custom „LiveState” mit
Min TTL: 0,Default TTL: 10,Max TTL: 30 - Compress:
Yes(gzip JSON) - Forward Headers:
Origin,Access-Control-Request-Method
- Origin: S3-Bucket
- S3-CORS-Rule auf Bucket (falls noch nicht für
/api/data/*gesetzt — vermutlich schon vorhanden):{ "AllowedOrigins": ["https://dashboard.agenticventures.de"], "AllowedMethods": ["GET", "HEAD"], "AllowedHeaders": ["If-None-Match"], "ExposeHeaders": ["ETag"] } - Smoke-Test:
curl -I https://dashboard.agenticventures.de/api/states/projekt-dashboard.jsonzeigtcache-control: public, max-age=10+ ETag
Patterns to follow:
- Bestehende CloudFront-Behavior für
/api/data/*(füraws-costs.jsonetc.) — neue Behavior wird nach Vorbild dieser angelegt - Runbook-Style in
~/source/av-cockpit/RUNBOOK.md(falls existiert) oderintern/projekte/projekt-dashboard/runbook.md
Test scenarios:
- Happy path: 5x in Folge GET, alle nach erstem aus CloudFront-Cache (Header
x-cache: Hit from cloudfront) - Happy path: nach 11s GET → CloudFront refetches von S3 (
x-cache: Miss from cloudfront) - Edge case: CORS-Preflight von
dashboard.agenticventures.de→ 200,access-control-allow-originkorrekt - Edge case: GET von fremder Origin → kein CORS-Header (oder explicit denied)
Verification: Manuelle curl-Tests bestätigen Headers. AWS Cost-Explorer zeigt nach 1 Woche < $0.50 Mehrkosten für den State-Path.
Unit 5: project-diagram Skill (optional, Bonus)
- Goal: Visueller Architektur-Snapshot pro Projekt, wiederverwendet customer-diagram-Pattern.
Requirements: R8
Dependencies: Keine harten (kann separat von Unit 1-4 laufen)
Files:
- Create:
intern/capabilities/skills/project-diagram/SKILL.md - Create:
intern/capabilities/skills/project-diagram/render.mjs(oder Symlink/Reuse von customer-diagram) - Create:
assets/firma/project-diagrams/_schema/sections.json(4 Sektionen) - Create:
assets/firma/project-diagrams/_schema/components.json(Projekt-Komponenten) - Create:
assets/firma/project-diagrams/_template/project.html - Modify:
intern/capabilities/skills/_index.md(Eintrag)
Approach:
- 4 Sektionen (statt customer-diagram-4): Phasen (Phasenpfeil als Excalidraw) / Architektur (Komponenten + Pfeile) / Decisions (Text-Liste, 3 wichtigste) / Risks (Text-Liste)
- Quelle:
intern/projekte/<slug>/state.md+_index.md+ ggf.plan.md - Output analog customer-diagram:
assets/firma/project-diagrams/<slug>.excalidraw+.svg+.html - Re-Run-Verhalten: inkrementell wie customer-diagram
Patterns to follow: SKILL.md eins-zu-eins als Schablone.
Verification: project-diagram projekt-dashboard erzeugt 3 Files. HTML öffnet sauber im Browser.
System-Wide Impact
- CLAUDE.md: zwei neue Rules ändern Default-Verhalten in allen Coding-Sessions. Nicht-Coding-Sessions (Email, Termine, Wiki-Maintenance) bleiben unverändert
- Vault-Schema: neuer
type: project_stateergänzt das Inventar in_meta/schemas.md. Bestehende Project-Files bleiben unverändert - av-cockpit Repo: vault.ts wird erweitert, kein bestehendes Verhalten gebrochen. Neue Routen
/projekte/[slug]und/cockpitsind additiv. Neuerscripts/push-state.mjsergänzt bestehende Scripts (build-finanzen.ts,deploy.sh) - AWS-Stack: ZERO neue Ressourcen. Wir nutzen bestehenden
av-dashboard-data-425924867359Bucket + bestehende CloudFront-DistributionE3KFMPWSKO68UU(Marvins Accountav-production) - CloudFront: eine neue Behavior für
/api/states/*neben der bestehenden für/api/data/*. Keine Distribution-Neuanlage - Skill-Inventar: ein neuer Skill, klar abgegrenzt von customer-diagram
- Auth: Cloudflare Access für
dashboard.agenticventures.deschützt automatisch auch/api/states/*-Pfad — nur Marvin sieht die States - Drift-Risiko: state.md-Files werden stale wenn Pflege nicht passiert. Mitigation in Risiken-Tabelle unten
Open Questions
Resolved during planning
- Wo lebt state.md? →
intern/projekte/<slug>/state.md(analog_index.md, gleiche Ebene) - Mensch- oder Maschinen-Format? → Markdown-Body + YAML-Frontmatter Mix. Marvin liest direkt, Agent parsed.
- Wer pflegt state.md? → Agent automatisch nach jeder Coding-Pipeline-Phase. Marvin manuell wenn er will.
- Override für lange Antworten? → Marvin-Wörter „geh tief”, „erklär”, „zeig Details” deaktivieren Rule 24 für nächste Antwort.
- Schwester-Skill oder customer-diagram-Erweiterung? → Schwester-Skill. Andere Sektionen, andere Trigger.
Deferred to implementation
- Recharts oder eigener SVG für Phasenpfeil? Entscheide bei Unit 4 — Vermutung: eigener SVG ist leichter (kein Recharts-Overkill für simple Horizontal-Stepper)
mode-Enum-Werte (coding-pipeline | research | sales | maintenance) — kann sich beim Pilot-Anlegen noch ändern- Wie genau formuliert man Rule 24 ohne Persona-Overkill? → Iterieren beim Schreiben in Unit 2
- Stale-Detection im Dashboard: ab wann ist state.md veraltet? 7 Tage? 14 Tage? Visualisierung wie? → Entscheide bei Unit 4
- Kollision mit phase-N.md (z.B. bedrock-cost-optimize): state.md verlinkt auf Detail-Files, ersetzt sie nicht. Konkrete Verlinkung beim Pilot-Anlegen klären.
- SWR-Polling-Intervall 5s vs 10s: start bei 5s, falls Kosten überraschend hoch oder Browser-Performance leidet → 10s. Entscheide bei Unit 8.
- Push-Script: AWS-SDK v3 vs
aws s3 cpshell-call? SDK v3 ist sauberer (Error-Handling, ETag-Diff) — Entscheide bei Unit 7, default SDK. - CloudFront-Cache-Invalidation bei jedem Push? Standardfall: nein (Cache-TTL 10s reicht). Bei kritischen Updates ggf. manuell. Entscheide bei Unit 9.
- MCP-Wrapper als Welle 2? Bewertung 3 Monate nach Go-Live: macht der Agent mehr mit dem Dashboard als nur push (query, mark-done, list-stale)? Wenn ja → mcp-eigenbau für
dashboard-mcp. Wenn nein → Script reicht.
Risks & Dependencies
| Risiko | Mitigation |
|---|---|
| state.md wird nicht gepflegt — Files veralten | Behavior-Rule 23 macht es Pflicht. Dashboard zeigt „stale” wenn updated_at > 7 Tage. Bei Wiki-Maintenance-Run prüfen. |
| Rule 24 zu rigid — Marvin kann nicht mehr deep-diven | Modi-Switch („geh tief”) explizit in Rule. Plus Trigger wie Brainstorm/Reproduce-Bug deaktivieren Default. |
| Detail-Route ist viel Frontend-Arbeit | Bestehendes Card-System wiederverwendet. Phasenpfeil als 50-Zeilen-SVG, kein neues Lib. |
| Markdown-Parser bricht bei abweichenden state.md-Files | Schema-Validierung beim Pilot-Anlegen. Defensive Parsing in vault.ts (null statt Crash). |
| project-diagram ist Scope-Creep | Als Phase 5 / optional markiert. Ohne Phase 5 funktioniert das Cockpit voll. |
| state.md dupliziert plan.md / phase-N.md | state.md ist Aggregator (5 Felder). Detail-Files bleiben Source-of-Truth, state.md verlinkt. |
Agent vergisst push-state.mjs aufzurufen → Dashboard wird stale | Rule 23 Pflicht. Script in einem Aufruf mit state.md-Edit kombinieren („nach jedem write: push”). Stale-Indikator im Frontend macht das Problem sichtbar. |
| Kosten-Surprise durch SWR-Polling | Page-Visibility-API + ETag-304-Pattern + CloudFront-Cache (10s TTL) drücken Real-Cost auf <$1/Monat. Monitoring via Cost-Explorer pro Bucket. Bei Drift → Polling-Intervall auf 10s erhöhen. |
| AWS-SSO-Token abgelaufen → Push-Fail | Push-Script gibt klaren Hinweis (aws sso login --profile av-production). Vault-File bleibt geschrieben, nur Sync schlägt fehl. Recoverable. |
| CloudFront-Cache zeigt veraltete Daten | TTL 10s ist Maximum-Drift. Bei kritischen Updates: manuell invalidieren (aws cloudfront create-invalidation). Kostet $0.005 pro Invalidation, in Praxis nie nötig. |
/api/states/* ohne Auth zugänglich | Cloudflare Access vor dashboard.agenticventures.de schützt automatisch. Direct-S3-URL bleibt private (Bucket-Policy). Verify in Smoke-Test. |
Kosten
Strategie: Komplett auf bestehendem projekt-dashboard-Stack reiten. Keine neue AWS-Ressource, keine neue Domain, kein neuer Auth-Layer.
Bestehende Infra (zahlst du eh, kein Cockpit-Anteil)
| Ressource | Status |
|---|---|
S3 av-dashboard-data-425924867359 | existiert (LiveRefreshStack nutzt ihn schon für routines-status.json etc.) |
S3 av-dashboard-frontend-425924867359 | existiert (Static Export) |
CloudFront E3KFMPWSKO68UU | existiert (Distribution für dashboard.agenticventures.de) |
| Cloudflare Access (Auth) | existiert (hello@-only, One-time PIN) |
Domain dashboard.agenticventures.de | existiert |
Cockpit-spezifische Mehrkosten (pro Monat, in EU)
| Posten | Berechnung | Kosten |
|---|---|---|
S3 Storage api/states/* | 30 Projekte × 20KB = 600KB | ~$0.00 |
| S3 PUT (Pushes) | ~10 Phasen-Updates/Tag × 30 = 300 PUTs/Monat × $0.005/1000 | ~$0.00 |
| S3 GET (Origin-Fetches durch CF-Misses) | bei 10s-Cache ~10% Miss-Rate × ~7000 Polls/Tag × 30 | ~$0.01 |
| CloudFront Requests | ~7000 GET/Tag × 30 = 210k/Monat (Free Tier deckt 10M ab) | $0.00 |
| CloudFront Egress | 5KB × 210k = 1.05GB × $0.085/GB (EU) | ~$0.09 |
| Lambda | nicht nötig | $0.00 |
| Total | ~$0.10/Monat |
Annahmen:
- Marvin nutzt Dashboard ~2h/Tag (geöffneter Tab)
- Page-Visibility pausiert Polling wenn Tab nicht aktiv → ~80% Request-Reduktion
- 5 aktive Projekte parallel auf
/cockpitÜbersicht - ETag-304-Responses reduzieren Egress um ~70% (nur Header, kein Body)
Worst-Case-Szenario
Dashboard 24/7 offen, alle 30 Projekte aktiv, kein Page-Visibility-Pause, 5s-Polling konstant:
- ~520k Requests/Monat × 3.90/Monat
- Egress ~2GB × 0.17/Monat
- Worst-Case ~$4/Monat
Das ist die Obergrenze. Realistisch landen wir bei <$1/Monat.
Kostenoptimierungen die im Plan eingebaut sind
- Page-Visibility-API (Unit 8) — Polling pausiert wenn Tab inaktiv
- ETag-Conditional-Requests (Unit 8) — 304-Responses sparen Egress
- CloudFront-Cache 10s TTL (Unit 9) — verteilt Last vom S3-Origin auf Edge
- Diff-Detection im Push (Unit 7) — keine PUTs bei unverändertem Content
- Aggressives Compression (Unit 9) — gzip auf JSON spart ~70% Egress
Was wir bewusst NICHT bauen (zu teuer ohne Mehrwert)
- AWS API Gateway WebSocket ($1/M Messages + Connection-Minutes)
- DynamoDB State-Store (redundant zu Vault als SoT)
- Eigenes Lambda für Push (Cold-Start + Invocation-Kosten ohne Nutzen)
- Cloudflare R2 + Workers KV (anderer Stack, bricht Auth/CDN-Setup)
- SSE via Next.js Server (bricht Static Export, müsste SSR oder Edge-Function werden)
Monitoring
- AWS Cost Explorer Tag-Filter:
Bucket=av-dashboard-datamit Pfad-Filterapi/states/ - Bei Drift > $2/Monat: Alert via existierendem av-cockpit
/cloud-Dashboard - Reality-Check nach 30 Tagen Go-Live, dann nach 90 Tagen
Documentation Plan
_meta/schemas.md§5.13 — Schema-Dokuintern/wissen/prozesse/chat-output-disziplin.md— Rule-24-Hintergrund + Beispieleintern/wissen/prozesse/state-md-pflege.md— Workflow „nach jeder Phase: state.md + push-state.mjs”intern/capabilities/skills/_index.md— project-diagram-Eintragintern/projekte/projekt-dashboard/_index.md— Offene Baustelle #2 (Detail-Route) als „erledigt” markieren wenn Unit 4 durchintern/projekte/projekt-dashboard/runbook.md— Live-State CloudFront-Behavior + Troubleshooting (Push-Failure, Stale-State, Cache-Invalidation)
Sources & References
- Origin: Brainstorm-Chat 2026-05-21 (Marvin + Agent), kein separates Requirements-Doc
- Bestehender Plan: plan.md (Dashboard v3) — dieser Plan ergänzt, ersetzt nicht
- Customer-Diagram-Skill als Blaupause: SKILL.md
- Vault-Bridge im av-cockpit: vault.ts
- Schema-Source-of-Truth: schemas.md
- CLAUDE.md: Behavior Rules
- ADHS-Pattern + Marvin-Profil: marvin-profile.md