Files
everythingbutwork/_bmad-output/planning-artifacts/epics.md
T
dejanandClaude Opus 4.7 4f33509a0f
ci / quality (push) Has been cancelled
ci / build (push) Has been cancelled
Initial commit: everythingbutwork MVP
Internes Project-Management-Tool für ToolCTRL — ergänzend zu Plane (Tickets)
und Outline (Doku). Umfasst Puls-Übersicht, Tagesrhythmus (Lock-in + Reflexion),
Bereichs-Detail-Views (Entwicklung/Vertrieb/Marketing), Pflicht-Minimum-Check
und Blocker-Lifecycle gemäß Projektmanagement-Leitfaden v3.0.

Stack: pnpm-Monorepo · Vite + React 18 + Tailwind · Fastify + tRPC v11 +
Drizzle ORM · Postgres 16 · Authentik OIDC (Phase 2, Dev-Auto-Login aktiv).

Planungs-Artefakte unter _bmad-output/planning-artifacts/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 22:47:26 +02:00

56 KiB
Raw Blame History

stepsCompleted, status, completedAt, inputDocuments, workflowType, project_name, user_name, date
stepsCompleted status completedAt inputDocuments workflowType project_name user_name date
1
2
3
4
complete 2026-05-25
prds/prd-projectmanagement-2026-05-25/prd.md
prds/prd-projectmanagement-2026-05-25/addendum.md
architecture.md
ux-design-specification.md
prds/prd-projectmanagement-2026-05-25/.decision-log.md
epics-and-stories ToolCTRL Unternehmens-Cockpit Dejancosic 2026-05-25

ToolCTRL Unternehmens-Cockpit - Epic Breakdown

Overview

Dieses Dokument zerlegt das PRD (49 FRs, 16 NFRs), die Architektur (komplett, Vite + React + Fastify + tRPC + Drizzle + Postgres + Authentik) und die UX-Spec (15 Custom-Components, Brand-Tokens, 5 User Journeys) in implementierbare Epics und Stories.

Requirements Inventory

Functional Requirements

49 FRs aus PRD §6, organisiert in 10 Feature-Gruppen (A–J).

A: Unternehmens-Puls (Startseite)

  • FR-1 Übersichtsleiste aller Areas (Entwicklung, Vertrieb, Marketing) inkl. aggregiertem Ampelstatus und Anzahl heute-fehlender Updates pro Area.
  • FR-1a Ampel-Aggregation Algorithmus pro Area: Rot wenn ≥ 1 Projekt rot; Gelb wenn ≥ 1 Projekt gelb und kein rotes; Grün wenn alle grün; Grau wenn keine aktiven Projekte. Pflicht-Minimum-Verstöße heben Ampel mindestens auf Gelb.
  • FR-2 Bereichsübergreifende Liste aller offenen Blocker, sortiert nach Alter.
  • FR-3 Heute-Quote „X von Y Mitarbeitern haben heute gepingt" mit Klick auf Liste der fehlenden Personen.
  • FR-4 Anzeige des nächsten Jourfixe-Termins (statisch konfigurierbar, Default Di 11:00).
  • FR-5 Pro Bereich definierter Key-Metrics-Katalog:
    • Entwicklung: # Projekte gesamt / im Plan / gefährdet / blockiert / # überzogene Meilensteine.
    • Vertrieb: gewichteter Pipeline-Wert (Σ value × probability) / # offene Deals / gewonnene Deals (Quartal, # + EUR) / # offene GTM-Schritte.
    • Marketing: Reichweite (Periode) / # aktive Kampagnen / Leads / MQLs / Übergaben an Vertrieb.
  • FR-6 Klick auf Bereich-Kachel öffnet Bereichs-Detail-View.
  • FR-7 Pflicht-Minimum-Übersicht im Puls: Liste aller aktiven Projekte mit roten/gelben Pflicht-Minimum-Punkten.

B: Bereichs-Detail Entwicklung

  • FR-8 Liste aller aktiven Projekte, gruppiert nach Projektart (Kundenprojekt / Internes Projekt — Leitfaden §1).
  • FR-9 Pro Projekt-Kachel: Name, Verantwortliche/r (P1), Ampelstatus + Trend (↗︎/→/↘︎), Deadline-Progress-Bar, # offene Meilensteine, Pflicht-Minimum-Score (z. B. „5/6").
  • FR-10 Projekt-Detail mit Kopfzeile (Name, P1, Projektart, Arbeitsmodus, Ampel + Trend), Pflicht-Minimum-Anzeige, Verlinkungen (Outline-Steckbrief, Plane-Board, Risikoliste), optional DoD-Text, Meilenstein-Checkliste, Update-Feed.
  • FR-11 Meilensteine als grobe Cockpit-Sicht (Titel, Fälligkeit, Status: offen/erledigt/überzogen). Wahrheit bleibt im Outline-Steckbrief.

C: Bereichs-Detail Vertrieb

  • FR-12 5-Spalten Kanban: Lead → Erstgespräch → Demo → Angebot → Abschluss, mit Drag-and-Drop.
  • FR-13 Deal-Karten: Name, Verantwortlicher, Wert (€), Stage-Wahrscheinlichkeit (0-100 %), Tage in aktueller Stage.
  • FR-14 Vertriebs-Header-KPIs: gewichteter Pipeline-Wert, gewonnene Deals (# + EUR, laufendes Quartal), aktiver Deal-Count, ⌀ Stage-Verweildauer.
  • FR-15 Pro Produkt eine sortierbare GTM-Schritt-Liste (Schritt, Verantwortlicher, Status).
  • FR-16 Vertrieb-Update-Feed (Filter Bezug = Deal oder Vertrieb-allgemein).

D: Bereichs-Detail Marketing

  • FR-17 Horizontaler Lead-Funnel mit 5 Stufen (Reichweite → Website → Leads → MQL → Übergabe) + Conversion-%.
  • FR-18 Liste aktiver Kampagnen mit Status (Aktiv / Pausiert / Beendet), Reichweite, Verantwortlicher.
  • FR-19 Crosslink-Banner Marketing↔Vertrieb: „Marketing hat X Leads übergeben in [Zeitraum], Vertrieb hat daraus Y Deals erzeugt (Z €)".
  • FR-20 Marketing-Update-Feed (Filter Bezug = Kampagne oder Marketing-allgemein).

E: Tagesrhythmus

  • FR-21 „Einstempeln"-Aktion auf Puls (großer CTA), öffnet ToDo-Eingabe für heute.
  • FR-22 ToDo-Liste: 1-N Items, pro Item Titel (max. 200 Z) + optionaler Bezug.
  • FR-23 Eingestempelt = Tag „begonnen", Person verschwindet aus „heute fehlt"-Liste.
  • FR-24 Sichtbarkeit innerhalb des Tages: nur binäre Anwesenheit für Kollegen, ToDo-Inhalte privat. P1 sieht ToDos seiner Projekte.
  • FR-25 ToDos editierbar bis zur Reflexion.
  • FR-26 Reflexions-Formular: ToDos abhaken/verwerfen (mit Grund), Freitext (max. 1000 Z), Ampel (Grün/Gelb/Rot mit Leitfaden-Semantik), Trend (Pflicht bei Bezug=Projekt), optional Blocker, optional URL.
  • FR-27 Reflexion → Tag „voll abgeschlossen", Streak +1.
  • FR-28 Reflexion 30 min editierbar; Reflexions-Erinnerung ab konfigurierbarer Zeit (Default 17:00).
  • FR-29 Konsolidierter Vortags-Eintrag wird am nächsten Werktag morgen publiziert (sichtbar für Kollegen).
  • FR-30 Feed-Sortierung: neueste oben. Pagination 50/Seite.
  • FR-31 Reflexion setzt automatisch Ampel + Trend des verlinkten Projekts/Deals/Kampagne.
  • FR-32 Rückwirkende Erfassung max. 1 Werktag zurück.
  • FR-33 Tages-Status pro Person: 🟢 voll / 🟡 halb / ⚪ nicht angefangen / 🟣 abwesend.

F: Streak / Anwesenheit / Disziplin

  • FR-34 Pro Person aktuelle Streak (aufeinanderfolgende „volle" Werktage).
  • FR-35 „Heute fehlt"-Liste auf Puls — nach 11:00 für nicht-eingestempelte, nach 17:00 für „halb"-Status.
  • FR-36 Werktage = Mo-Fr (Feiertage Phase 2).
  • FR-37 Person markiert sich für Tag/Zeitraum als „Abwesend" (Urlaub/Krankheit), zählt nicht gegen Streak.

G: Pflicht-Minimum-Check (Leitfaden §9)

  • FR-38 Pro aktivem Projekt 6-Punkte-Checkliste sichtbar:
    1. Projektsteckbrief in Outline freigegeben → erfüllt wenn outline_steckbrief_url gepflegt UND als „freigegeben" markiert.
    2. P1 gesetzt.
    3. Plane-Board mit zerlegter Arbeit → erfüllt wenn plane_project_url gepflegt.
    4. Meilensteine mit groben Terminen → erfüllt wenn ≥ 1 Meilenstein.
    5. Status-Ampel aktuell → erfüllt wenn letzte Reflexion mit Projektbezug ≤ 7 Werktage alt.
    6. Abschluss-Retrospektive (nur bei beendeten Projekten).
  • FR-39 MVP: Punkte 1, 2, 3, 4 manuell als Cockpit-Checkbox; Punkt 5 automatisch aus Reflexions-Zeitstempel; Punkt 6 im Abschluss-Workflow.
  • FR-40 Projekte mit unerfülltem Pflicht-Punkt prominent auf Puls.

H: Blocker

  • FR-41 Blocker entsteht inline in Reflexion oder via „Neuer Blocker"-Button.
  • FR-42 Blocker-Felder: Titel, Beschreibung, Verantwortlicher, Ersteller, Bereich(e), Datum offen, Status.
  • FR-43 Blocker erscheint auf Puls, in betroffenen Bereichs-Detail-Views und in Projekt-Detail.
  • FR-44 Auflösung mit Auflöser, Datum, Kommentar. Nur P1 des bezogenen Projekts darf auflösen; bei projektlosen Blockern auch Ersteller/Verantwortlicher.

I: Projekt-Abschluss

  • FR-45 P1 setzt Projekt auf „abgeschlossen".
  • FR-46 Beim Abschluss fordert Cockpit Lessons-Learned-URL an.
  • FR-47 Abgeschlossene Projekte verschwinden aus Puls, bleiben in Archiv-Sicht pro Bereich.

J: Navigation, Suche & Filter

  • FR-48 Globale TopNav: Puls / Entwicklung / Vertrieb / Marketing / Mein heute / Eigenes Profil / Archiv.
  • FR-49 Volltextsuche → Phase 2; MVP: Filter im Feed nach Bereich/Bezug.

NonFunctional Requirements

16 NFRs aus PRD §7.

Performance

  • NFR-1 Puls-Seite < 1,5 s bei 6-15 Nutzern und 90 Tagen Historie.
  • NFR-2 Tagesupdate-Speichern < 500 ms.

Verfügbarkeit

  • NFR-3 Mo-Fr 8-19: 99 %.
  • NFR-4 Wartungsfenster außerhalb Kernzeit kommunizierbar.

Security & Privacy

  • NFR-5 Alle Routen hinter Authentik-OIDC.
  • NFR-6 Keine externe PII in Deal-Karten.
  • NFR-7 Audit-Trail für jede mutierende Operation (actor / timestamp / payload).

Bedienbarkeit & Visual

  • NFR-8 Brand-konform: weiß primär, schwarz sekundär, ToolCTRL Brand Identity.
  • NFR-9 Tagesupdate-Schreib-Workflow ≤ 3 Klicks ab Puls.
  • NFR-10 Desktop-first, mobil-lesbar (nicht mobil-schreibbar).
  • NFR-11 Deutsch durchgängig, keine i18n.

Voice & Tone

  • NFR-12 Tonalität locker/direkt/deutsch, kurze Imperative ("Stark.", "Wie läuft es?", "Du hast heute noch nicht gepingt.").
  • NFR-13 Keine Corporate-Sprech, keine englischen Floskeln (Fachbegriffe aus Leitfaden ausgenommen).

Datenhaltung & Erweiterbarkeit

  • NFR-14 Postgres als Persistenz.
  • NFR-15 Tägliches Backup.
  • NFR-16 Datenmodell erweiterbar ohne Migrationen > 2 h.

Additional Requirements

Aus Architektur-Spec abgeleitete technische Anforderungen.

  • AR-1 Starter / Bootstrap: Custom Monorepo (pnpm-Workspaces) mit apps/web (Vite + React + TS + Tailwind), apps/api (Fastify + tRPC + Drizzle), packages/db (Drizzle-Schema), packages/shared (Zod + Types). Erste Story nutzt die in der Architektur §"Initialization Commands" beschriebenen Setup-Befehle.
  • AR-2 Datenmodell in packages/db/schema.ts mit allen 14 Entitäten (User, Area, Project, Milestone, Deal, GtmStep, Campaign, LeadHandover, DayEntry, Todo, Blocker, AbsenceDay, AuditEvent, Session) gemäß Addendum §1.2 und Architektur §Project Structure. UUID v7 als ID-Primary.
  • AR-3 Auth-Flow: openid-client v6+ direkt im Fastify, Authorization Code + PKCE gegen Authentik. Server-Side-Session in Postgres, HttpOnly + SameSite=Lax + Secure Cookie. Default-Bereich aus Authentik-Group-Claim.
  • AR-4 tRPC Procedure-Typen: publicProcedure, protectedProcedure, dayEntryVisibleProcedure (Sichtbarkeitsfilter pre/post published_at), projectOwnerProcedure (P1-Check).
  • AR-5 Audit-Middleware (withAudit) um jede schreibende tRPC-Mutation, schreibt parallel in audit_event.
  • AR-6 Background-Jobs via System-Cron → authentifizierter Fastify-Endpoint (POST /internal/cron/* mit Bearer-Token):
    • publish-day-entries (tägl. 00:05 Europe/Berlin)
    • recompute-pflicht-minimum-5 (stündlich)
    • recompute-streaks (tägl. 00:10)
    • pg-dump-backup (tägl. 02:00)
  • AR-7 Werktag-Logik zentral in apps/api/src/lib/werktag.ts (Mo-Fr Europe/Berlin). Frontend bekommt vorberechnete Werte, niemals eigene Datumsmagie.
  • AR-8 Ampel-Aggregation in apps/api/src/lib/ampel.ts (FR-1a-Algorithmus).
  • AR-9 Pflicht-Minimum-Berechnung in apps/api/src/lib/pflicht-minimum.ts, lazy beim Read.
  • AR-10 Hosting: Docker-Compose mit web-Container (Caddy-served apps/web/dist), api-Container (Node 22+), postgres:16-Container, caddy-Container als Reverse-Proxy auf cockpit.tool-ctrl.de.
  • AR-11 CI/CD: Gitea Actions Pipeline (Typecheck, Lint, Vitest, Build, Docker-Image-Push, Deploy-Trigger).
  • AR-12 Tests: Vitest (Unit + tRPC-Procedures), Playwright (E2E auf UJ-1, UJ-2, UJ-5). Lighthouse-A11y-Score ≥ 95.
  • AR-13 Logging: strukturierte JSON-Logs via pino → stdout.
  • AR-14 Healthcheck: GET /api/health (Postgres-Ping + Authentik-Reachability) für Docker-Healthcheck.
  • AR-15 Konventionen-Datei CONVENTIONS.md im Repo-Root (spiegelt Architektur §Implementation Patterns), Pflicht-Lesen vor Story-Bearbeitung.
  • AR-16 Backup-Strategie: pg_dump täglich auf separates Volume, Retention 14 Tage. Restore-Drill quartalsweise dokumentiert in docs/operations.md.

UX Design Requirements

Aus UX-Spec abgeleitete UI/Visual/A11y-Anforderungen.

Brand-Tokens & Visual Foundation

  • UX-DR1 Brand-Tokens als CSS-Variablen in apps/web/src/styles/globals.css definieren und in tailwind.config.ts als Theme spiegeln. Werte gemäß UX-Spec §Visual Design Foundation:
    • --color-bg: #ffffff, --color-surface: #fafafa, --color-surface-elevated: #ffffff
    • --color-border: #e5e5e5, --color-border-strong: #d4d4d4
    • --color-ink: #0a0a0a, --color-ink-muted: #525252, --color-ink-faint: #a3a3a3
    • --color-brand: #0a0a0a, --color-brand-fg: #ffffff
    • Ampel: green #15803d/#dcfce7, amber #a16207/#fef3c7, red #b91c1c/#fee2e2
    • Trend: up #15803d, flat #525252, down #b91c1c
  • UX-DR2 Typografie: Inter (UI, variable) + JetBrains Mono (Werte) selbst-gehostet via @fontsource/inter und @fontsource/jetbrains-mono. 7-Stufen-Type-Scale aus UX-Spec §Typography.
  • UX-DR3 Spacing-Skala, Radii und Schatten gemäß UX-Spec §Spacing & Layout — als Tailwind-Theme-Erweiterung.
  • UX-DR4 Container-Max-Width 1.280 px, 12-Spalten-Grid mit 24 px Gap; Puls auf Desktop 3-Spalten.

Custom-Component-Library (apps/web/src/components/ui/)

  • UX-DR5 Button mit 3 Varianten (primary/secondary/ghost) + Destructive + Icon-Only, 3 Größen (sm/md/lg).
  • UX-DR6 Card mit Compound-API (Card.Root, Card.Header, Card.Body, Card.Footer).
  • UX-DR7 Input, Textarea (mit Zeichen-Counter), Select (via Radix), Checkbox (via Radix mit animiertem Häkchen).
  • UX-DR8 AmpelButton (3-Wege-Toggle Grün/Gelb/Rot, große Klick-Targets), TrendButton (3-Wege ↗︎/→/↘︎).
  • UX-DR9 Dialog (via Radix mit Brand-Header und radius-xl), Tooltip (via Radix, schwarzer Bubble), Toast (via Sonner, Bottom-Right, schwarzer Pill).
  • UX-DR10 SkeletonCard — graue Card-Skelette identischer Geometrie wie echte Cards.
  • UX-DR11 AmpelBadge — Status-Pill mit Farbpunkt + Label + optionalem Trend-Pfeil.
  • UX-DR12 PflichtMinimumIndicator — sechs kleine Quadrate horizontal, gefüllt/leer.
  • UX-DR13 KeyCaret — SVG-Komponente für das Brand-^-Element, einbindbar in Header/Logo/Toast.

Layout & Navigation

  • UX-DR14 TopNav fest mit cockpit ^ Logo links, Tabs (Puls / Entwicklung / Vertrieb / Marketing / Mein heute / Archiv), rechts Streak-Badge + Avatar. Aktiver Tab mit 2 px schwarzem Underline.
  • UX-DR15 Breadcrumbs in Detail-Views (Puls › Entwicklung › Projekt X), klickbar pro Segment.
  • UX-DR16 Tastatur-Shortcuts: g p, g h, g e, g v, g m, g a, n (Neuer Blocker), ? (Cheatsheet), Esc (Modal schließen).

Voice & Tone (Mikrocopy)

  • UX-DR17 Zentrale Mikrocopy-Datei apps/web/src/lib/voice.ts mit allen UI-Strings. Beispiele: „Stark.", „Wie läuft es?", „Du hast heute noch nicht gepingt.", „Reflektiert.", „Blocker offen.". Pflicht-Anwendung in allen Komponenten.

User-Journey-Flows

  • UX-DR18 UJ-1 Tagesrhythmus: /mein-heute (Morgen-Einstempeln + ToDo-Editor) und /reflexion (Abend-Reflexion mit Tagesplan-Echo).
  • UX-DR19 UJ-2 Jourfixe: Puls-Layout muss alle 3 Bereiche in einem Scroll abdeckbar machen.
  • UX-DR20 UJ-5 Projekt anlegen: Modal mit Pflicht-Feldern (Name, P1, Projektart, Arbeitsmodus, Steckbrief-URL, Plane-URL).

Responsive & Accessibility

  • UX-DR21 Drei Sicht-Ebenen: Desktop (≥ 1280 px, 3-Spalten Puls), Tablet (≥ 768 px, 2-Spalten), Mobile (< 768 px, Single-Column + Bottom-Tab-Bar, lesbar).
  • UX-DR22 WCAG 2.1 AA durchgängig. Keyboard-First (Tab, Enter, Space, Esc). Sichtbarer Fokus-Ring (outline: 2px solid var(--color-ink), 2 px Offset).
  • UX-DR23 Skip-Link „Zum Hauptinhalt springen" oben. Saubere Heading-Hierarchie. Live-Regionen für Toasts.
  • UX-DR24 prefers-reduced-motion → Fade-Animationen auf 0 ms.
  • UX-DR25 axe-core in Vitest pro Komponente; @axe-core/playwright für E2E. ESlint-jsx-a11y mit recommended aktiviert.

Interaktions-Patterns

  • UX-DR26 Optimistic Updates bei Checkbox-Abhaken und Ampel-Setzen (Rollback bei API-Fehler).
  • UX-DR27 Skeleton-Cards beim Initial-Load — nie leerer Bildschirm, nie Spinner alleine.
  • UX-DR28 Empty-States als Voice-konforme Tropfen-Information (z. B. „Hier erscheinen die Updates des Tages, sobald jemand reflektiert hat.").
  • UX-DR29 Reflexions-Erinnerung im Header ab 17:00 (dezenter Pill, klickbar).
  • UX-DR30 Vortrags-Reveal: Fade-In ≤ 200 ms beim ersten Laden am Werktag X+1.

FR Coverage Map

FR Epic Kurztitel
FR-1, FR-1a, FR-2, FR-3, FR-4, FR-5, FR-6, FR-7 Epic 3 Puls & Übersicht
FR-8, FR-9, FR-10, FR-11 Epic 4 Bereich Entwicklung
FR-12, FR-13, FR-14, FR-15, FR-16 Epic 4 Bereich Vertrieb
FR-17, FR-18, FR-19, FR-20 Epic 4 Bereich Marketing
FR-21 – FR-33 Epic 2 Tagesrhythmus
FR-34, FR-35, FR-36, FR-37 Epic 2 + Epic 3 Streak + Anwesenheit
FR-38, FR-39, FR-40 Epic 5 Pflicht-Minimum
FR-41, FR-42, FR-43, FR-44 Epic 5 Blocker
FR-45, FR-46, FR-47 Epic 6 Projekt-Abschluss
FR-48 Epic 1 Navigation (Top-Nav)
FR-49 Phase 2 Volltextsuche

NFR-Abdeckung: NFR-5/7/8/9 ⇒ Epic 1 · NFR-1/2 ⇒ über alle Epics validiert · NFR-3/4/14/15/16 ⇒ Epic 6 · NFR-10/11/12/13 ⇒ Epic 1 + Epic 2 (Voice-Anker etabliert)

Epic List

6 Epics, jedes liefert ein eigenständig nutzbares Stück. Reihenfolge folgt der in architecture.md § "Decision Impact Analysis → Implementation Sequence" festgelegten Story-Sequenz.

Epic 1: Fundament — Login, Shell, Brand

Ziel: Eine Person kann sich via Authentik einloggen und landet in einer leeren, brand-konformen Cockpit-Shell mit funktionierender Navigation. Es passiert noch nichts Fachliches — aber das Fundament steht.

Was nach Epic 1 nutzbar ist:

  • Login/Logout funktioniert
  • TopNav steht (Puls-Tab, Profil, Streak-Badge-Slot leer)
  • Brand-Theme aktiv (Farben, Typografie, KeyCaret-Logo)
  • Healthcheck + Docker-Compose laufen lokal

FRs: FR-48 NFRs: NFR-5, NFR-7, NFR-8, NFR-9 (vorbereitet), NFR-11, NFR-12, NFR-13, NFR-14 AR: AR-1, AR-2 (Schema-Skeleton User+Session+AuditEvent), AR-3, AR-4 (Procedure-Typen-Skeleton), AR-5 (Audit-Wrapper), AR-10, AR-15, AR-13 (pino), AR-14 (Healthcheck) UX-DR: UX-DR1, UX-DR2, UX-DR3, UX-DR4, UX-DR5, UX-DR6, UX-DR7, UX-DR13, UX-DR14, UX-DR15, UX-DR16, UX-DR17, UX-DR22, UX-DR23, UX-DR24, UX-DR25

Epic 2: Tagesrhythmus — Einstempeln, ToDos, Reflexion

Ziel: Eine Person kann morgens einstempeln + ToDos schreiben, abends reflektieren mit Ampel/Trend, und am nächsten Werktag wird der konsolidierte Eintrag für Kollegen sichtbar. Das Herz des Cockpits.

Was nach Epic 2 nutzbar ist:

  • Person kann den vollen Tagesrhythmus durchlaufen (UJ-1)
  • Streak und Tages-Status erscheinen im Profil und in der „Heute fehlt"-Liste (basal — volle Puls-Visualisierung kommt in Epic 3)
  • Cron-Job publiziert Vortags-Einträge

FRs: FR-21 – FR-33, FR-34, FR-36, FR-37 AR: AR-2 (Schema DayEntry, Todo, AbsenceDay), AR-4 (dayEntryVisibleProcedure), AR-5, AR-6 (publish-day-entries cron + recompute-streaks cron), AR-7 UX-DR: UX-DR8 (AmpelButton, TrendButton), UX-DR9 (Dialog für AbwesendDialog), UX-DR10 (SkeletonCard), UX-DR18 (/mein-heute + /reflexion), UX-DR26 (optimistic), UX-DR27 (Skeleton), UX-DR28 (Empty-State), UX-DR29 (17:00-Hinweis), UX-DR30 (Vortrags-Reveal Fade-In)

Epic 3: Puls & Bereichs-Übersicht

Ziel: Eine Person öffnet das Cockpit und sieht in unter 60 Sekunden den Unternehmens-Puls: alle drei Bereiche mit aggregiertem Ampelstatus, Heute-Quote, bereichsübergreifende Blocker, Jourfixe-Hinweis. Vortrags-Einträge im Feed.

Was nach Epic 3 nutzbar ist:

  • Puls-Seite ist die Heimat (UJ-2, UJ-3)
  • „Heute fehlt"-Liste klickbar mit Personen
  • Bereichs-Strip mit Ampel-Aggregation
  • Feed konsolidierter Vortrags-Einträge

FRs: FR-1, FR-1a, FR-2, FR-3, FR-4, FR-5 (Schema-Layout, KPIs werden mit Echtdaten in Epic 4 gefüllt), FR-6, FR-7 (Pflicht-Minimum-Slot, gefüllt in Epic 5), FR-35 AR: AR-8 (Ampel-Aggregation), AR-7 (Werktage) UX-DR: UX-DR11 (AmpelBadge), UX-DR19 (Puls-Layout 3-Spalten)

Epic 4: Projekte, Deals, Kampagnen — Bereichs-Details

Ziel: Eine Person kann Projekte (Entwicklung), Deals (Vertrieb) und Kampagnen (Marketing) anlegen und pflegen. Bereichs-Detail-Views zeigen Listen, Kanban, Lead-Funnel, Crosslinks. Reflexionen (aus Epic 2) setzen Projekt-Ampeln korrekt.

Was nach Epic 4 nutzbar ist:

  • Projekte/Deals/Kampagnen können angelegt, geändert und gelistet werden (UJ-5)
  • Sales-Kanban funktioniert (Drag-and-Drop, Stage-Wechsel)
  • Lead-Funnel + Crosslink-Banner zeigen Aggregate
  • KPIs im Puls-Bereichs-Strip (FR-5) zeigen Echtdaten

FRs: FR-8, FR-9, FR-10, FR-11, FR-12, FR-13, FR-14, FR-15, FR-16, FR-17, FR-18, FR-19, FR-20, FR-31 AR: AR-2 (Schema Project, Milestone, Deal, GtmStep, Campaign, LeadHandover) UX-DR: UX-DR9 (Dialog für Projekt-Anlegen), UX-DR20 (Projekt-Anlege-Modal)

Epic 5: Pflicht-Minimum & Blocker

Ziel: Die 6 Leitfaden-Pflicht-Punkte pro Projekt werden sichtbar gemacht. Blocker können erfasst, gelistet und (nur durch P1) aufgelöst werden.

Was nach Epic 5 nutzbar ist:

  • Pflicht-Minimum-Indikator in Projekt-Card und -Detail (FR-7 wird voll funktional auf dem Puls)
  • Blocker-Lebenszyklus komplett (Erfassen via Reflexion-Inline oder „+ Neuer Blocker"-Button, Anzeige im Puls/Bereich/Projekt, Auflösung)
  • Frühwarn-Mechanik aktiv

FRs: FR-38, FR-39, FR-40, FR-41, FR-42, FR-43, FR-44 AR: AR-4 (projectOwnerProcedure), AR-6 (recompute-pflicht-minimum-5 cron), AR-9 UX-DR: UX-DR12 (PflichtMinimumIndicator)

Epic 6: Projekt-Abschluss, Archiv & Production

Ziel: Projekte können abgeschlossen werden (mit Lessons-Learned-Link), Archiv-Sicht existiert. Production-Pipeline ist scharf: CI/CD, tägliches Backup, Healthcheck-Monitoring, A11y-Tests im CI.

Was nach Epic 6 nutzbar ist:

  • Volle Projekt-Lebensspanne von Anlage bis Lessons-Learned
  • Cockpit ist deploybar und beobachtbar
  • Backup + Restore-Drill dokumentiert
  • A11y-Score ≥ 95 im CI gemessen

FRs: FR-45, FR-46, FR-47 NFRs: NFR-1, NFR-2, NFR-3, NFR-4, NFR-10 (Responsive-Validierung), NFR-15, NFR-16 AR: AR-6 (pg-dump-backup), AR-11 (Gitea Actions), AR-12 (Tests, Playwright), AR-14 (Healthcheck-Erweiterung), AR-16 (Backup + Restore-Drill) UX-DR: UX-DR21 (Responsive-Sichtbarkeitsprüfung), UX-DR25 (axe-core + jsx-a11y in CI)


Phase-2-Backlog (nicht im MVP, nicht in Epics):

  • FR-49 Volltextsuche
  • Plane-/Outline-API-Sync
  • Mobile schreibbar
  • Reaktionen / Kommentare auf Updates
  • Element/Matrix/Mail-Reminders
  • Loki/Grafana, Sentry, Feiertags-Kalender, Dark Mode

Epic 1: Fundament — Login, Shell, Brand

Eine Person kann sich via Authentik einloggen und landet in einer leeren, brand-konformen Cockpit-Shell mit funktionierender Navigation. Es passiert noch nichts Fachliches — aber das Fundament steht und alle weiteren Epics können darauf aufsetzen.

Story 1.1: Repo-Bootstrap und Tooling

Als Entwickler, ich möchte ein lauffähiges Monorepo mit Vite-Frontend, Fastify-Backend, Drizzle-DB-Package und Shared-Package, sodass alle Folge-Stories auf einem konsistenten Setup aufsetzen können.

Acceptance Criteria:

Given ein leeres cockpit/-Repo, When pnpm install und pnpm typecheck ausgeführt werden, Then alle 4 Workspaces (apps/web, apps/api, packages/db, packages/shared) sind installiert und typecheckbar And pnpm --filter web dev startet Vite auf Port 5173 And pnpm --filter api dev startet Fastify auf Port 3000 And CONVENTIONS.md ist im Repo-Root vorhanden und spiegelt die Patterns aus architecture.md § Implementation Patterns And ESLint und Prettier sind konfiguriert und liefern keinen Fehler beim Start.

Story 1.2: Postgres + Drizzle-Schema-Skeleton mit User, Session, AuditEvent

Als Entwickler, ich möchte eine laufende Postgres-Instanz und das Drizzle-Schema für die drei Fundament-Entitäten, sodass Auth und Audit auf einer realen DB-Schicht funktionieren können.

Acceptance Criteria:

Given Docker auf dem Dev-Host, When docker compose -f docker-compose.dev.yml up postgres läuft, Then Postgres 16 ist auf Port 5432 erreichbar And packages/db/schema.ts definiert die Tabellen user, session, audit_event mit UUID-v7-IDs, snake_case-Spalten und timestamptz-Zeitstempeln And pnpm --filter db migrate:generate erzeugt eine Migration 0000_init.sql And pnpm --filter db migrate führt sie aus und die drei Tabellen existieren in der DB.

Story 1.3: Authentik-OIDC-Login-Flow

Als Mitarbeiter, ich möchte mich via Authentik (SSO) einloggen und nach dem Login automatisch auf der Cockpit-Heimseite landen, sodass ich ohne separate Account-Anlage Zugang zum Cockpit bekomme.

Acceptance Criteria:

Given ich öffne cockpit.tool-ctrl.de ohne Session, When das Backend mich an auth.tool-ctrl.de weiterleitet und ich mich dort erfolgreich einlogge, Then werde ich auf /puls zurückgeleitet And ein HttpOnly + SameSite=Lax + Secure Cookie session_id ist gesetzt And in der DB existiert eine session-Zeile mit expires_at 24 h in der Zukunft And in der DB existiert eine user-Zeile mit authentik_sub, name, email und (sofern Group-Claim vorhanden) default_area_id And ein erneutes Aufrufen jeder geschützten Route innerhalb der Session-Gültigkeit funktioniert ohne erneuten Login And POST /api/auth/logout invalidiert die Session in der DB und löscht das Cookie.

Story 1.4: tRPC-Bootstrap mit protectedProcedure und Audit-Wrapper

Als Entwickler, ich möchte die tRPC-v11-Infrastruktur mit Context, protectedProcedure und withAudit-Wrapper laufen haben, sodass alle fachlichen Stories direkt typsicher Procedures bauen können.

Acceptance Criteria:

Given Story 1.3 ist gemerged, When ein Client trpc.user.me ohne Session aufruft, Then liefert das Backend TRPCError(UNAUTHORIZED) mit deutscher Message And mit gültiger Session liefert es das User-Objekt aus der DB And withAudit wrapt jede Mutation und schreibt parallel in audit_event in derselben Transaktion (verifiziert via Test) And der Frontend-tRPC-Client in apps/web/src/lib/trpc.ts ist konfiguriert mit zentralem onError-Toast und nutzt die AppRouter-Typdefinition aus packages/shared.

Story 1.5: Brand-Tokens, Tailwind-Theme und Voice-Datei

Als UI-Entwickler, ich möchte die ToolCTRL-Brand-Tokens als CSS-Variablen und Tailwind-Theme-Erweiterung aktiv haben, sodass alle weiteren UI-Komponenten brand-konform stylebar sind.

Acceptance Criteria:

Given Story 1.1 ist mergeable, When ich apps/web/src/styles/globals.css lade, Then sind alle Farb-Tokens, Spacing-, Radii- und Schatten-Variablen aus der UX-Spec definiert And tailwind.config.ts spiegelt diese Tokens als Theme-Erweiterung And @fontsource/inter und @fontsource/jetbrains-mono sind installiert und geladen And apps/web/src/lib/voice.ts existiert mit allen Mikrocopy-Strings aus UX-Spec § Voice & Tone als exportierte Konstanten And eine Test-Route /dev/tokens (nur in import.meta.env.DEV) zeigt eine Palette aller Tokens als visuelle Referenz.

Story 1.6: TopNav-Shell mit Logo, Tabs, Profil-Slot und Keyboard-Shortcuts

Als Mitarbeiter, ich möchte eine sichtbare, navigierbare Cockpit-Shell mit Brand-Logo, Hauptnavigation und Profil-Bereich, sodass ich die App-Struktur sofort verstehe.

Acceptance Criteria:

Given ich bin eingeloggt, When ich cockpit.tool-ctrl.de öffne, Then sehe ich oben links cockpit ^ (KeyCaret-SVG + Lockup) und in der Mitte die TopNav-Tabs Puls, Entwicklung, Vertrieb, Marketing, Mein heute, Archiv And rechts erscheint mein Avatar (Initialen) und ein Streak-Badge-Platzhalter And der aktive Tab zeigt einen 2 px dicken schwarzen Underline And Tastatur-Shortcuts g p, g h, g e, g v, g m, g a springen auf die jeweilige Route And ? öffnet einen Cheatsheet-Dialog (alle Shortcuts gelistet) And WCAG 2.1 AA wird erfüllt (axe-core-Test grün), Fokus-Ring sichtbar auf jedem Tab.

Story 1.7: Healthcheck, Docker-Compose und CI-Skeleton

Als DevOps, ich möchte docker compose up startet Web + API + Postgres + Caddy lokal und der Healthcheck antwortet, sodass Deployments und CI auf einer reproduzierbaren Basis aufsetzen können.

Acceptance Criteria:

Given docker-compose.yml und Caddyfile existieren, When docker compose up -d --build läuft, Then sind alle vier Container web, api, postgres, caddy healthy And GET /api/health liefert 200 OK mit JSON { "status": "ok", "db": "ok", "authentik": "ok" } And GET / liefert die SPA-Index (statisch via Caddy) And ein minimales Gitea-Actions-Workflow ci.yml läuft Typecheck, Lint und Vitest auf jedem Push.


Epic 2: Tagesrhythmus — Einstempeln, ToDos, Reflexion

Eine Person kann den vollen Tagesrhythmus durchlaufen: morgens einstempeln + ToDos schreiben, abends reflektieren, am nächsten Werktag wird der Eintrag konsolidiert. Das ist die Kern-Erfahrung des Cockpits.

Story 2.1: DayEntry- und Todo-Schema, AbsenceDay, Werktag-Helper

Als Entwickler, ich möchte die DB-Tabellen für Tageseinträge, ToDos und Abwesenheiten plus die Werktag-Logik im Backend, sodass die Tagesrhythmus-Procedures auf einer korrekten Datenbasis arbeiten.

Acceptance Criteria:

Given Epic 1 ist abgeschlossen, When die Migration 0001_day_rhythm.sql läuft, Then existieren in der DB die Tabellen day_entry, todo, absence_day, blocker gemäß Addendum § 1.2 And apps/api/src/lib/werktag.ts bietet isWerktag(date), nextWerktag(date), werktagsDistance(a, b) mit Mo-Fr-Logik in Europe/Berlin And Vitest-Tests decken Grenzfälle ab (Wochenende, Tageswechsel um Mitternacht).

Story 2.2: Einstempeln + ToDo-Eingabe auf „Mein heute"

Als Mitarbeiter, ich möchte mich morgens einstempeln und meine ToDos für heute eintippen, sodass mein Tag begonnen ist und ich für Kollegen als „eingestempelt" sichtbar bin.

Acceptance Criteria:

Given ich öffne /mein-heute als noch nicht eingestempelte Person, When ich auf „Einstempeln" klicke und 3 ToDos eintippe (Enter erzeugt neue Zeile, optionaler Bezug per Inline-Select), Then wird beim Klick auf „Eingestempelt" ein day_entry mit status='begun' und checked_in_at angelegt sowie 3 todo-Zeilen And ich werde auf /puls weitergeleitet And im „Heute fehlt"-Modul auf dem Puls erscheine ich nicht mehr (Kollegen sehen nur binäre Anwesenheit, nicht die ToDo-Inhalte — vgl. FR-24) And ein „Eingestempelt."-Toast erscheint 2 s in Bottom-Right And der Median-Speed-Test (manuelle Stoppuhr) zeigt ≤ 60 s für 3 ToDos (CM1a).

Story 2.3: Tagsüber ToDos editieren, „Mein heute" als private Sicht

Als Mitarbeiter, ich möchte meine ToDos im Verlauf des Tages ergänzen oder ändern können, sodass mein Tagesplan realitätsnah bleibt — und kein Kollege das mitliest, bevor ich reflektiert habe.

Acceptance Criteria:

Given ich bin eingestempelt mit 3 ToDos, When ich /mein-heute erneut öffne, Then sehe ich meine ToDos editierbar (hinzufügen, ändern, löschen) bis zur Reflexion And Edits werden gespeichert via tRPC-Mutation todo.update/todo.create/todo.delete And ein anderer User, der dieselbe Person als „eingestempelt" sieht, kann keine ToDo-Inhalte abrufen (tRPC dayEntry.todosForUser liefert für andere User vor published_at nur count) And die Projekt-P1 darf die ToDos sehen, sofern ein ToDo Bezug auf ihr/sein Projekt hat — verifiziert durch tRPC-Test mit zwei verschiedenen User-Sessions.

Story 2.4: Abend-Reflexion mit Tagesplan-Echo, Ampel + Trend

Als Mitarbeiter, ich möchte abends meine ToDos durchgehen, abhaken oder verwerfen, einen Freitext schreiben und Ampel/Trend setzen, sodass mein Tag offiziell als „voll" abgeschlossen gilt und der Status meines Projekts aktuell ist.

Acceptance Criteria:

Given ich bin eingestempelt und öffne /reflexion, When ich meine ToDos sehe (Tagesplan-Echo mit 200 ms Fade-In) und einige abhake, einige verwerfe (Inline-Grund-Feld) und einen Freitext mit ≤ 1000 Zeichen schreibe, Then kann ich Ampel (🟢/🟡/🔴 als drei große Buttons) und Trend (↗︎/→/↘︎) setzen And Trend ist Pflichtfeld, sofern mindestens ein ToDo Bezug=Projekt hat — Submit ohne Trend zeigt deutsche Inline-Fehlermeldung And Submit setzt day_entry.status='full', reflected_at, schreibt reflection_text, ampel, trend And die Ampel + der Trend des verlinkten Projekts werden in derselben DB-Transaktion aktualisiert (status_cache, trend_cache) And ein „Reflektiert."-Toast erscheint, ich werde auf /puls redirected And Reflexion ist 30 min lang editierbar — danach erscheint sie unverändert.

Story 2.5: Blocker inline in der Reflexion erfassen

Als Mitarbeiter, ich möchte bei der Reflexion einen Blocker mit einem Toggle eintragen, sodass das Team meine Hindernisse am nächsten Werktagsmorgen sieht.

Acceptance Criteria:

Given ich bin in der Reflexion, When ich den „Blocker?"-Toggle aktiviere und Titel + Beschreibung eintippe, Then wird beim Submit zusätzlich ein blocker-Datensatz erzeugt And der Blocker ist mit opened_by = mein User und (sofern ToDo-Bezug=Projekt) project_id verknüpft And der day_entry.blocker_id zeigt auf den neuen Blocker And der Blocker erscheint erst nach Publikation am nächsten Werktag im bereichsübergreifenden Blocker-Modul des Puls (Verifizierung mit zweiter Session).

Story 2.6: Cron „publish-day-entries" + Streak-Berechnung

Als System, möchte ich nachts um 00:05 Europe/Berlin die DayEntries des Vortags publizieren und Streaks neu berechnen, sodass am Morgen X+1 die konsolidierten Vortrags-Einträge sichtbar werden und Streaks korrekt sind.

Acceptance Criteria:

Given mehrere User haben am Vortag eingestempelt + reflektiert, When der System-Cron POST /internal/cron/publish-day-entries mit Bearer-Token aufruft, Then werden alle day_entry-Zeilen des Vortags mit published_at = heute 00:00 versehen And die nachfolgende tRPC-Procedure dayEntry.feedForArea liefert diese Einträge inklusive ToDos + Reflexion für alle Kollegen And ein zweiter Cron-Aufruf recompute-streaks setzt user.current_streak korrekt (vollständige + halbe + abwesende Tage gemäß FR-33/34) And Cron-Aufrufe ohne korrekten Bearer-Token liefern 401.

Story 2.7: Streak-Badge, Abwesenheit, „Halb"-Status

Als Mitarbeiter, ich möchte meine aktuelle Streak in der TopNav sehen und mich für Tage als abwesend markieren können, sodass Urlaubstage nicht meine Streak brechen.

Acceptance Criteria:

Given ich bin eingeloggt, When ich die TopNav betrachte, Then sehe ich rechts neben meinem Avatar einen Pill „N ^" (N = aktuelle Streak, KeyCaret als Suffix) And ich kann via Profil-Modal einen Zeitraum als „abwesend" (Urlaub/Krank/Sonstiges) markieren And Abwesenheits-Tage werden als absence_day gespeichert und im Streak-Cron als „nicht gegen die Serie zählend" behandelt And wenn ich morgens nur einstempele aber nicht reflektiere, zeigt dayEntry.todayStatus für mich status='begun' und mein Tages-Status-Indikator wird gelb („halb") And der nächste Streak-Cron würde diesen Tag nicht für die Serie zählen (verifiziert via Unit-Test in werktag.ts).


Epic 3: Puls & Bereichs-Übersicht

Eine Person öffnet das Cockpit und sieht in unter 60 Sekunden alles Wesentliche: drei Bereiche mit Ampel-Aggregat, Heute-Quote, Blocker, Jourfixe-Hinweis, Vortrags-Feed.

Story 3.1: Area-Schema, Aggregations-Algorithmus, Puls-Procedure

Als Entwickler, ich möchte die area-Tabelle und die apps/api/src/lib/ampel.ts-Aggregations-Logik plus eine tRPC-Procedure puls.overview, sodass die Puls-Frontend-Seite alle Aggregat-Daten in einem Roundtrip bekommt.

Acceptance Criteria:

Given die DB enthält drei area-Zeilen (dev, sales, marketing) und (zunächst leere) Projekt-Tabelle, When trpc.puls.overview ohne Filter aufgerufen wird, Then liefert es ein Objekt mit areas: [{ id, name, ampel, ampel_count, missing_today_count }], blockers: [...], heuteQuote: { gepingt, gesamt, fehlende: [...] }, jourfixe: { nextDate, label } And die Ampel-Aggregation pro Bereich folgt FR-1a-Algorithmus (verifiziert via Vitest-Test mit Fixtures aus mehreren Status-Kombinationen) And die Procedure liefert in < 200 ms bei 6-15 Usern und 90 Tagen Historie (Performance-Test mit vitest --bench).

Story 3.2: Puls-Seite Layout mit Bereichs-Strip und Heute-Quote

Als Mitarbeiter, ich möchte auf /puls in einem Blick die drei Bereiche mit Ampelstatus und die Heute-Quote sehen, sodass ich morgens innerhalb 60 s einen Überblick habe.

Acceptance Criteria:

Given ich öffne /puls, When die Seite geladen hat, Then sehe ich oben einen Hero mit „Stand: Di, 25. Mai 2026" And unter dem Hero ein 3-Spalten-Grid mit den drei Bereichen, jeweils mit AmpelBadge, Bereichsname, Anzahl fehlender Updates heute, und einer Klick-Aktion zur Bereichs-Detail-View And rechts (oder darunter auf Tablet) ein „Heute fehlt"-Modul mit X/Y eingestempelt-Stat und Klick auf Detail-Liste der fehlenden Personen (mit Avatar + Name) And wenn ich noch nicht eingestempelt bin, erscheint prominent oberhalb des Folds der CTA „Du hast heute noch nicht gepingt." mit „Einstempeln"-Primary-Button → führt zu /mein-heute And Skeleton-Cards beim Initial-Load, Fade-In ≤ 200 ms beim Datenanstieg.

Story 3.3: Blocker-Modul, Jourfixe-Hinweis, KPI-Slots

Als Mitarbeiter, ich möchte auf /puls die offenen Blocker, den nächsten Jourfixe und KPI-Slots pro Bereich sehen, sodass ich den ganzen Unternehmens-Puls auf einer Seite verstehe.

Acceptance Criteria:

Given ich öffne /puls, When die Seite vollständig geladen ist, Then sehe ich unter dem Bereichs-Strip ein Modul „Bereichsübergreifend offen" mit allen offenen Blockern sortiert nach Alter And ein Modul „Jourfixe" zeigt den nächsten Termin (Default „Di, 11:00") And pro Bereich erscheint eine KPI-Kachel mit Slots aus FR-5 (Anzahl Projekte, Status-Verteilung etc.) — Werte sind in Epic 3 ggf. noch 0 (echte Daten kommen in Epic 4) And das Modul „Pflicht-Minimum" ist als Slot vorhanden, zeigt aber bis Epic 5 nur „Keine Projekte mit unerfülltem Pflicht-Minimum" als Empty-State.

Story 3.4: Vortrags-Feed im Puls + „Heute fehlt"-Detail

Als Mitarbeiter, ich möchte am Morgen X+1 die konsolidierten Vortrags-Einträge meiner Kollegen im Feed sehen, sodass ich weiß, was gestern lief.

Acceptance Criteria:

Given am Tag X haben N Personen reflektiert und der Publikations-Cron lief um 00:05, When ich am Tag X+1 morgens /puls öffne, Then sehe ich unten einen „Gestern im Team"-Feed mit konsolidierten DayEntries (Avatar + Name + Bereich + Ampel + Trend + Reflexionstext + abgehakte/verworfene ToDos) And der Feed sortiert neueste oben, paginiert 50/Seite mit „Mehr laden" And Klick auf einen Eintrag öffnet die Detail-Sicht (read-only) And das „Heute fehlt"-Modul klickt jetzt auf eine vollständige Liste der heute noch nicht eingestempelten Personen And Performance-Budget < 1,5 s gesamtladezeit auf /puls mit 90 Tagen Historie (Lighthouse-Test).


Epic 4: Projekte, Deals, Kampagnen — Bereichs-Details

Eine Person kann Projekte, Deals und Kampagnen anlegen und in den jeweiligen Bereichs-Detail-Views arbeiten. Die KPI-Slots im Puls werden mit Echtdaten gefüllt.

Story 4.1: Project-, Milestone- und Verlinkungs-Schema, Anlage-Modal

Als Projektverantwortliche/r (P1), ich möchte ein Projekt im Cockpit anlegen können mit allen Cockpit-Sicht-Feldern und Pflicht-Verlinkungen, sodass das Projekt im Puls und in der Bereichs-Detail-View erscheint.

Acceptance Criteria:

Given ich bin eingeloggt und in der Bereichs-Detail-View Entwicklung, When ich auf „+ Neues Projekt" klicke, Then öffnet sich ein Dialog mit den Pflichtfeldern Name, Verantwortliche/r (P1, User-Auswahl), Projektart (Kundenprojekt/Internes Projekt), Arbeitsmodus (Cycle/Kanban), Outline-Steckbrief-URL, Plane-Board-URL And optional DoD-Text, Risikoliste-URL, Start, Deadline und 0..N grobe Meilensteine inline And beim Submit werden project- und milestone-Zeilen geschrieben (Migration 0002_projects.sql), audit-getracked And das neue Projekt erscheint sofort im Bereich Entwicklung (FR-8/9) und im Puls-KPI-Slot.

Story 4.2: Bereichs-Detail Entwicklung mit Projekt-Karten und Detail-View

Als Mitarbeiter, ich möchte die Liste aller Entwicklungs-Projekte in zwei Gruppen (Kundenprojekt/Internes Projekt) sehen und in die Detail-Sicht klicken, sodass ich Status, Meilensteine und letzte Updates pro Projekt erfasse.

Acceptance Criteria:

Given mindestens 2 Projekte (eines Kundenprojekt, eines internes) existieren, When ich /bereich/entwicklung öffne, Then sehe ich zwei Sektionen „Kundenprojekte" und „Interne Projekte" mit Projekt-Cards (Name, P1-Avatar, AmpelBadge + Trend, Deadline-Progress-Bar, # offene Meilensteine, Pflicht-Minimum-Score Slot) And Klick auf Projekt-Card öffnet /projekt/:id mit der Detail-Sicht: Kopfzeile (Name, P1, Projektart, Arbeitsmodus, Ampel + Trend), Verlinkungen (Outline-Steckbrief, Plane-Board, optional Risikoliste), optional DoD-Text, Meilenstein-Checkliste, Update-Feed dieses Projekts And Meilensteine sind inline editierbar (Status: offen/erledigt/überzogen, Fälligkeit ändern) und werden in der Cockpit-DB persistiert.

Story 4.3: Deal-Schema, Sales-Kanban und Pipeline-KPIs

Als Vertrieb, ich möchte meine Deals als Kanban in 5 Stages sehen und per Drag-and-Drop verschieben, sodass die Pipeline immer aktuell ist.

Acceptance Criteria:

Given Migration 0003_sales.sql ist gelaufen und mind. 3 Deals existieren, When ich /bereich/vertrieb öffne, Then sehe ich oben das KPI-Header-Modul mit gewichtetem Pipeline-Wert (Σ value × probability), aktiven Deals-Count, gewonnenen Deals des laufenden Quartals (# + EUR formatiert als 12.500,00 €), ⌀ Stage-Verweildauer And darunter ein 5-Spalten-Kanban (Lead → Erstgespräch → Demo → Angebot → Abschluss) mit Deal-Karten And Drag-and-Drop einer Karte auf eine andere Spalte ändert deal.stage und setzt entered_stage_at = now() (optimistic UI + Rollback bei Fehler) And unten ein gefilterter Vertrieb-Update-Feed (Bezug=Deal oder Vertrieb-allgemein).

Story 4.4: GTM-Schritte und Vertrieb-Feed

Als Vertrieb, ich möchte pro Produkt eine sortierbare GTM-Schritt-Liste pflegen, sodass die Markteinführung jedes Produkts strukturiert ist.

Acceptance Criteria:

Given im Vertriebs-Detail existiert ein Bereich „GTM-Schritte pro Produkt", When ich ein neues Produkt-Tab hinzufüge und Schritte (Titel + Verantwortlicher + Status) einpflege, Then wird gtm_step in der DB persistiert mit order-Feld für die Reihenfolge And Schritte sind per Drag-and-Drop oder Up/Down-Tastatur-Buttons umsortierbar (order wird neu vergeben in einer Transaktion) And der Status (offen/in Arbeit/erledigt) ist inline änderbar.

Story 4.5: Campaign-Schema, Lead-Funnel und Crosslink-Banner

Als Marketing, ich möchte den Lead-Funnel mit Conversion-Prozenten und die Kampagnen-Liste sehen, plus einen Crosslink-Banner zur Vertriebs-Übergabe, sodass ich verstehe, wie viele Leads in echte Deals umgewandelt werden.

Acceptance Criteria:

Given Migration 0004_marketing.sql ist gelaufen und lead_handover enthält Daten, When ich /bereich/marketing öffne, Then sehe ich oben einen horizontalen 5-Stufen-Lead-Funnel (Reichweite → Website → Leads → MQL → Übergabe) mit Conversion-% zwischen den Stufen And darunter eine Liste aktiver Kampagnen (Aktiv/Pausiert/Beendet, Reichweite, Verantwortlicher) And ein Crosslink-Banner zeigt „Marketing hat X Leads übergeben in [letzten 30 Tagen], Vertrieb hat daraus Y Deals erzeugt (Z € im Quartal)" And derselbe Banner spiegelt sich umgekehrt im Vertrieb-Detail (FR-19) And unten ein gefilterter Marketing-Update-Feed.


Epic 5: Pflicht-Minimum & Blocker

Die 6 Leitfaden-Pflicht-Punkte pro Projekt werden sichtbar gemacht. Blocker-Lebenszyklus ist komplett — inkl. der Regel „nur P1 darf auflösen".

Story 5.1: Pflicht-Minimum-State, Lazy-Berechnung und Cron-Punkt-5

Als Entwickler, ich möchte die Pflicht-Minimum-Logik im Backend mit der korrekten Punkt-5-Aktualisierung, sodass der Status pro Projekt stets korrekt aus den Daten abgeleitet wird.

Acceptance Criteria:

Given Migration 0005_pflicht_minimum.sql ergänzt project.pflicht_minimum_state (JSONB) und project.steckbrief_freigegeben (bool), When apps/api/src/lib/pflicht-minimum.ts computePflichtMinimum(projectId) aufgerufen wird, Then liefert es ein Objekt mit 6 Booleans gemäß FR-38 Definition (Punkte 1-4 manuell aus DB-Feldern, Punkt 5 berechnet aus letztem Reflexions-Zeitstempel) And der Cron-Endpoint POST /internal/cron/recompute-pflicht-minimum-5 setzt Punkt 5 auf false für alle Projekte mit letzter Reflexion > 7 Werktage zurück And der Aggregations-Algorithmus aus FR-1a wird ergänzt: Pflicht-Minimum-Verstöße heben Ampel mindestens auf Gelb (Vitest-Test mit Fixtures).

Story 5.2: Pflicht-Minimum-Indikator und -Panel in der UI

Als P1 / P4, ich möchte pro Projekt-Card und Projekt-Detail die 6 Pflicht-Punkte als visuelle Indikatoren sehen, sodass ich sofort sehe, was bei diesem Projekt fehlt.

Acceptance Criteria:

Given Stories 5.1 ist abgeschlossen und ein Projekt hat 4/6 Punkte erfüllt, When ich /bereich/entwicklung öffne, Then zeigt jede Projekt-Card unten rechts den PflichtMinimumIndicator mit 6 horizontalen Quadraten (gefüllt/leer) und Score „4/6" And auf /projekt/:id erscheint das PflichtMinimumPanel mit allen 6 Punkten als Checkliste, jeweils mit Status, kurzer Beschreibung und (für Punkte 1-4) Quick-Action-Button („Steckbrief verlinken", „P1 setzen", „Plane-Board verlinken", „Meilenstein anlegen") And Punkte 5 und 6 sind read-only mit Erklärungs-Tooltip And Projekte mit ≥ 1 unerfülltem Punkt erscheinen auf /puls im Modul „Pflicht-Minimum" (vorher leerer Slot wird gefüllt).

Story 5.3: Blocker-Lebenszyklus — Erfassen, Anzeige, P1-Auflösung

Als Mitarbeiter, ich möchte Blocker außerhalb der Reflexion erfassen können und P1 kann sie auflösen, sodass das Team auf bereichsübergreifende Hindernisse reagieren kann.

Acceptance Criteria:

Given der „+ Neuer Blocker"-Button in der TopNav (Shortcut n), When ich auf ihn klicke und Titel + Beschreibung + Verantwortlichen + Bereich(e) + optionale Projekt-Verknüpfung eintrage, Then wird blocker in der DB persistiert mit opened_by = ich And der Blocker erscheint auf /puls im bereichsübergreifenden Modul, im jeweiligen Bereichs-Detail und (sofern projektgebunden) im Projekt-Detail And auf der Blocker-Card erscheint ein „Auflösen"-Button nur sichtbar, wenn ich P1 des bezogenen Projekts bin (oder bei projektlosen Blockern Ersteller oder Verantwortlicher) And ein nicht-P1-User, der versucht via direktem tRPC-Call aufzulösen, bekommt TRPCError(FORBIDDEN) mit deutscher Message And beim Auflösen werden resolved_by, resolved_at und resolution_text persistiert; Blocker verschwindet aus den offenen Listen.

Story 5.4: Blocker im Projekt-Detail und Audit der Auflösung

Als P1 / P4, ich möchte die Blocker-Historie pro Projekt einsehen können, sodass ich nachvollziehe, was und wann gelöst wurde.

Acceptance Criteria:

Given ein Projekt hat mehrere Blocker (einige offen, einige gelöst), When ich /projekt/:id öffne, Then sehe ich einen Tab oder Bereich „Blocker" mit zwei Listen: offene Blocker oben (mit „Auflösen"-Button für P1), gelöste Blocker darunter (mit Auflöser-Name + Datum + Kommentar) And jede Blocker-Mutation (erstellen, lösen) hat einen entsprechenden audit_event-Eintrag (verifiziert per DB-Query in Test).


Epic 6: Projekt-Abschluss, Archiv & Production

Projekte können abgeschlossen werden inkl. Lessons-Learned-Pflicht. Archiv-Sicht existiert. Production-Pipeline ist scharf: CI/CD, Backup, A11y-Tests.

Story 6.1: Projekt-Abschluss-Workflow und Lessons-Learned-Pflicht

Als P1, ich möchte ein Projekt auf „abgeschlossen" setzen können — aber nur, wenn ich die Lessons-Learned-URL angegeben habe, sodass die Leitfaden-Pflicht-Minimum-Position 6 garantiert erfüllt wird.

Acceptance Criteria:

Given ich bin P1 eines aktiven Projekts und öffne den Projekt-Header, When ich auf „Projekt abschließen" klicke, Then öffnet sich ein Dialog, der die Lessons-Learned-URL als Pflichtfeld einfordert (URL-Format-Validierung via Zod) And beim Submit wird project.archiviert=true, archiviert_am=now(), lessons_learned_url gesetzt und pflicht_minimum_state.6=true neu berechnet And das Projekt verschwindet sofort aus /bereich/entwicklung und /puls And Try-To-Submit ohne URL zeigt deutsche Inline-Fehlermeldung And ein nicht-P1-User sieht den „Abschließen"-Button nicht (UI + tRPC-Guard).

Story 6.2: Archiv-Sicht pro Bereich

Als Mitarbeiter, ich möchte abgeschlossene Projekte in einer Archiv-Sicht einsehen, sodass vergangene Erkenntnisse auffindbar bleiben.

Acceptance Criteria:

Given mindestens 2 Projekte sind abgeschlossen, When ich /archiv öffne (oder via TopNav-Tab), Then sehe ich pro Bereich (Tabs Entwicklung/Vertrieb/Marketing) eine Liste abgeschlossener Items sortiert nach archiviert_am (neueste oben) And Klick auf ein Item öffnet die read-only Detail-Sicht mit allen Daten + Lessons-Learned-Link And die Archiv-Sicht hat denselben Sub-Header wie die Bereichs-Detail-Views (Sticky), aber mit zusätzlichem „Archiv"-Marker.

Story 6.3: Backup-Cron, Restore-Drill-Dokumentation

Als DevOps, ich möchte ein tägliches pg_dump-Backup mit 14-Tage-Retention und dokumentiertem Restore-Pfad, sodass Datenverlust auch nach einem schweren Vorfall begrenzt bleibt.

Acceptance Criteria:

Given der Cron-Endpoint POST /internal/cron/pg-dump-backup ist implementiert, When die System-Cron-Definition den Endpoint täglich 02:00 aufruft, Then wird ein gz-komprimiertes Dump-File auf einem separaten Docker-Volume backups geschrieben And Dumps älter als 14 Tage werden automatisch gelöscht And docs/operations.md enthält eine Restore-Anleitung in 5 Schritten (Stop API, Restore Dump, Migrate, Smoke-Test, Start API) And ein quartalsweiser Restore-Drill ist als Issue im Plane geöffnet (Story-Akzeptanz prüft, dass die Aufgabe dokumentiert ist, nicht den Drill selbst).

Story 6.4: CI-Pipeline mit Vitest, Playwright und Lighthouse-A11y

Als Entwickler, ich möchte eine CI-Pipeline, die Typecheck, Lint, Vitest, Playwright und Lighthouse-A11y-Test bei jedem PR ausführt, sodass Qualität und Barrierefreiheit nicht erodieren.

Acceptance Criteria:

Given .gitea/workflows/ci.yml erweitert die Pipeline, When ein PR geöffnet wird, Then läuft die Pipeline pnpm install → pnpm typecheck → pnpm lint → pnpm test (Vitest mit axe-core auf Komponenten-Snapshots) → pnpm build → Playwright-E2E auf den drei UJs (UJ-1, UJ-2, UJ-5) gegen eine ephemere Docker-Compose-Umgebung → Lighthouse-CI auf /puls, /mein-heute, /projekt/:id And Lighthouse-A11y-Score < 95 lässt die Pipeline fehlschlagen And jeder PR-Check zeigt einen Statusbericht mit den erfüllten/gefehlten Punkten.

Story 6.5: Responsive-Audit und Mobile-Lesbarkeit

Als Mitarbeiter, ich möchte das Cockpit auch unterwegs am Handy lesen können (nicht schreiben — das bleibt Desktop), sodass ich beim Pendeln zumindest sehe, wie es um die Projekte steht.

Acceptance Criteria:

Given ich öffne /puls und /projekt/:id auf einem mobilen Browser (Viewport 375×667), When die Seiten geladen sind, Then sind alle Karten und Listen leserlich gestapelt (Single-Column), keine horizontalen Scrolls And die TopNav wird zu einer Bottom-Tab-Bar mit 4 Items (Puls, Mein heute, Bereiche-Dropdown, Profil) And der Einstempel-CTA auf /mein-heute zeigt einen sichtbaren Hinweis „Tagesupdate auf Desktop empfohlen" (Voice-konform) And Playwright-Mobile-Viewport-Tests laufen für /puls und /projekt/:id und prüfen Layout-Integrität.


Validation Summary

FR Coverage Check

FR Story Status
FR-1, 1a, 2-7 3.1-3.4 ✅
FR-8-11 4.1, 4.2 ✅
FR-12-16 4.3, 4.4 ✅
FR-17-20 4.5 ✅
FR-21-25 2.2, 2.3 ✅
FR-26-28, 31 2.4 ✅
FR-29, 30 2.6, 3.4 ✅
FR-32, 33 2.2, 2.4, 2.7 ✅
FR-34-37 2.7 ✅
FR-38-40 5.1, 5.2 ✅
FR-41-44 2.5, 5.3, 5.4 ✅
FR-45-47 6.1, 6.2 ✅
FR-48 1.6 ✅
FR-49 — ⏭ Phase 2 (explizit)

Coverage: 48 von 49 FRs durch Stories abgedeckt; FR-49 (Volltextsuche) bewusst Phase 2 gemäß PRD § 8.

NFR Coverage Check

  • Performance (NFR-1, 2): 3.1 (Procedure-Budget), 3.4 (Lighthouse), 6.4 (CI-Performance-Gate)
  • Verfügbarkeit (NFR-3, 4): 6.3 (Backup + Restore-Drill), 1.7 (Healthcheck)
  • Security (NFR-5, 6, 7): 1.3 (Authentik), 1.4 (Audit-Wrapper)
  • Bedienbarkeit (NFR-8-10): 1.5 (Brand-Tokens), 6.5 (Mobile-Audit)
  • Voice & Tone (NFR-11, 12, 13): 1.5 (voice.ts) — alle UI-Stories nutzen die zentrale Datei
  • Daten (NFR-14, 15, 16): 1.2 (Postgres+Drizzle), 6.3 (Backup), 1.1 (Drizzle-Migrationen)

Story-Quality-Validation

  • ✅ Sized for single dev agent: keine Story > 1 Arbeitstag in der KI-gestützten Entwicklung.
  • ✅ Given/When/Then-Format auf jeder AK.
  • ✅ Keine Vorwärts-Abhängigkeiten — jede Story baut auf vorherigen Stories (gleicher Epic) oder bereits abgeschlossenen Epics auf.
  • ✅ Inkrementelles Schema: DB-Migrationen entstehen je Story-Bedarf, nicht upfront. (0000_init, 0001_day_rhythm inkl. blocker, 0002_projects, 0003_sales, 0004_marketing, 0005_pflicht_minimum.)
  • ✅ Custom-Starter ist Story 1.1 (Repo-Bootstrap), entspricht Architektur § Initialization Commands.

Epic-Independence-Check

Epic Depends on Liefert
1 — Login + Shell + Brand
2 1 Tagesrhythmus inkl. Cron + Streak
3 1, 2 Puls-Übersicht mit Vortrags-Feed
4 1 (unabhängig von 2/3 möglich) Projekt-/Deal-/Kampagnen-Domain
5 4 (Projekte) + 2 (Blocker-Inline) Pflicht-Minimum + Blocker-Lifecycle
6 4 (Archiv), 2 (Cron-Pattern) Abschluss + Production-Pipeline

✅ Jedes Epic liefert eigenständig nutzbaren Wert.

File-Churn-Check

  • Epic 2 und Epic 5 berühren beide blocker-Schema und -Komponente — bewusst getrennt: Epic 2 etabliert nur Inline-Erfassung in der Reflexion, Epic 5 fügt vollständigen Lifecycle (Standalone-Button + P1-Auflösung + Audit-Tab) hinzu. Aufteilung mitigiert Risiko, dass das volle Blocker-System verzögert wird, bevor der Tagesrhythmus läuft.
  • Epic 3 und Epic 4 berühren beide apps/api/src/routers/puls.ts und KPI-Slots im Frontend — getrennt, weil Epic 3 die Aggregation für leere Bereiche etabliert (skelettiert) und Epic 4 die Domain-Daten dahinter liefert. Konsolidierung hätte ein zu großes Epic ohne Zwischen-Release-Wert ergeben.

UX-DR-Coverage-Spot-Check

  • UX-DR1-4 (Brand-Tokens, Typo, Spacing, Container) → Story 1.5
  • UX-DR5-7 (Button, Card, Input, Textarea, Select, Checkbox) → Story 1.5 + 1.6 (verteilt, je nach Bedarf in Folge-Stories)
  • UX-DR8 (AmpelButton, TrendButton) → Story 2.4
  • UX-DR9 (Dialog, Tooltip) → Story 4.1 + 6.1
  • UX-DR10 (SkeletonCard) → Story 3.2
  • UX-DR11 (AmpelBadge) → Story 3.2 / 4.2
  • UX-DR12 (PflichtMinimumIndicator) → Story 5.2
  • UX-DR13 (KeyCaret) → Story 1.6 + 2.7
  • UX-DR14-16 (Navigation, Breadcrumbs, Shortcuts) → Story 1.6
  • UX-DR17 (voice.ts) → Story 1.5
  • UX-DR18-20 (User Journeys) → Stories 2.2/2.4, 3.2, 4.1
  • UX-DR21-25 (Responsive + A11y) → Story 6.4 + 6.5
  • UX-DR26-30 (Interaktions-Patterns) → verteilt über alle UI-Stories

✅ Alle 30 UX-DRs sind in Stories adressiert.

Validation Verdict

🟢 READY FOR DEVELOPMENT

  • 49 FRs · 16 NFRs · 16 AR-Items · 30 UX-DRs → durch 6 Epics und 32 Stories abgedeckt
  • Keine Vorwärts-Abhängigkeiten, keine Upfront-Big-Bang-Migrationen
  • Epic-Reihenfolge entspricht der Architektur-Implementation-Sequence
  • Bauen kann mit Story 1.1 (Repo-Bootstrap) sofort starten.