agents.md — Konventionen für KI-Agenten und Coding-Agenten
Dieses Dokument beschreibt, wie ein KI-Agent (Claude, Codex, Cursor, Continue, etc.) in diesem Repo arbeitet. Es ist verbindlich für jede Session und sollte beim Start jeder neuen Konversation mitgelesen werden — typischerweise zusammen mit HANDOFF.md. Es ist unsere „Way of Working" und wird laufend aktuell gehalten: ändert sich, wie wir zusammenarbeiten, landet es hier (kein paralleles Prozess-Doc — Decision-Sprawl vermeiden, §5.2).
1. Repo-Philosophie: „Everything as Code"
Alle Artefakte des Projekts leben im Repo: Spezifikation, Entscheidungen, Architektur, Code, Diagramme, Konventionen. Nichts Überlebenswertes verbleibt im flüchtigen Konversations-Verlauf oder im Session-Memory einer einzelnen Cowork/Claude-Instanz.
Konsequenzen:
- GitHub
drkv-com/taktanoist die einzige Quelle der Wahrheit. - Eine neue Session startet nicht „bei null" — sie liest
HANDOFF.mdunddocs/fachlich/Lastenheft.mdund ist sofort im Kontext. - Wenn etwas entschieden wird, landet es als Commit im Repo, bevor die Konversation endet.
2. Doku-Format: Markdown + Mermaid (kein .docx, kein .pdf)
Regel: Alle versionierten Dokumente sind .md mit Inline-Mermaid für Diagramme. Keine binären Formate (.docx, .pdf, .pptx, .xlsx) als Master-Quelle. Falls ein externer Stakeholder PDF/Word braucht, kann es bei Bedarf aus dem .md exportiert werden (pandoc, Mermaid-CLI für SVG-Diagramme, etc.).
Begründung:
- Git-diffbar, reviewable, mergeable.
- Diagramme als Code (Mermaid) sind genauso versioniert wie der Prosa-Text.
- Coding-Agenten können
.mddirekt lesen, ändern und Diffs erzeugen. - Keine Tooling-Abhängigkeit (Word, LibreOffice, Adobe).
Mermaid-Typen, die wir im Repo verwenden:
| Typ | Wofür |
|---|---|
flowchart | Use-Cases, Architektur, Ampel-Logik |
erDiagram | Datenmodell, Entitäts-Beziehungen |
stateDiagram-v2 | Lifecycle (Auftrag, Teilschritt) |
sequenceDiagram | Interaktionen (Protokoll-Submit, Scheduler-Calls) |
gantt | Zeitliche Abläufe (Teilschritt + Cool-down im Bay) |
pie | nur falls aussagekräftig — selten sinnvoll |
2.1 Doku-Navigation: Frontmatter, Kopf-Block, Landkarte
Damit die Doku navigierbar bleibt (nicht nur ist), gelten für jede Datei unter docs/:
-
YAML-Frontmatter ganz oben (Maschinen-/Sidebar-Belange, minimal halten):
---sidebar_position: 20 # 10er-Schritte = Lesereihenfolge (nicht alphabetisch)sidebar_label: Kurz-Label # nur falls die H1 für die Sidebar zu lang ist---Kein
title:im Frontmatter — der Titel wird aus der ersten H1 abgeleitet (Single Source).sidebar_positionin 10er-Schritten, damit neue Docs ohne Umnummerieren einsortieren. -
Sichtbarer Kopf-Block in
docs/architektur/*.mddirekt nach der H1 (rendert auch auf GitHub, Selbsterklärbarkeit) — kanonischer Standard (seit 07-12, Doku-Review E6; per Warn-Gate incheck-doc-consistency.sherzwungen; für andere schweredocs/-Dokumente empfohlen, dort ohne Gate-Pflicht):> **Status:** <ehrlich: Design (kein Code) / in Umsetzung, Slice X ✅ / gebaut (vX) / lebend> ·> **Bezug:** <Owning-OP + wichtigste IDs> · **Zielgruppe:** <Rolle(n) der sieben Leserkreise> ·> **True North:** <ehrlicher Halbsatz — welche Leitfrage, direkt/indirekt; „nur indirekt" ist ok>> **Kernaussage.** <2–5 Sätze, Antwort/Entscheidung zuerst (Minto)>Genau eine Kernaussage je Doc, exakt im Format
> **Kernaussage.**(keine Varianten wie## Kernaussage-Headings oder> **Zweck.**). Bewusst zwei getrennte Blockquotes (Metadaten-Box + Kernaussage-Box, VorbildDoku-UX-Konzept.md) — der markdownlint-Hinweis MD028 („blank line in blockquote") ist hier kein Fehler, sondern Design. Status/Stand ändern sich oft → bewusst sichtbar (Diff = Audit); Gebaut vs. Geplant nie vermischen (Status-Ehrlichkeit). -
Landkarte & Sidebar pflegen: neues Doc in den passenden Unterordner legen, in
docs/README.mdeintragen, und (neuer Ordner) ein_category_.jsonmitlabel/position/link: generated-indexanlegen. -
Begriffe & IDs: neuen Fachbegriff in
docs-site/src/glossar/glossar.mjsergänzen (Single Source → generiertesglossar/Glossar.md+ Begriffs-Sprechblasen,npm run glossar); bekommt ein OP ein eigenes Dokument, die Zeile inIDs.md(OP → Owning-Doc) ergänzen. -
OP-Listen tragen klickbare OP-ID-Sprünge (verbindlich). In jeder OP-Liste in der Doku ist die OP-ID selbst ein Hyperlink zum direkten Sprung an ihr Zuhause — konkret:
- Navigations-Indizes
Register.md§1 +IDs.md-Reverse-Lookup: OP-ID → Owning-Doc, sonstops/<ID>.mdbzw. per-OP-Anker in Lastenheft §11 (#op-<id>, fachliches Detail); Familien-/Sammelzeilen (OP-R*-*) → passender §11-Sektions-Anker (#11-1-auftraege…#11-10-tests-qs). - Volle OP-Liste
Offene-Punkte.md(generiert ausops/*.md): jede OP-ID verlinkt ihreops/-Datei; derendetail:zeigt aufs Owning-Doc bzw. Lastenheft-§11-#op-<id>. (Das frühere HANDOFF-§4-Archiv ist seit 07-12 vollständig migriert.) - Fachliche Master-Liste Lastenheft §11: jede führende OP-ID trägt einen expliziten
<a id="op-<id>">-Anker (präzises Sprungziel; Sektions-Anker{#11-x-…}zusätzlich).
Neue/umziehende OPs immer so verlinken + verankern (kein blanker
`OP-…`-Code ohne Link/Anker). Anker sind explizite{#…}-Heading-Anker bzw. inline<a id>(stabil, Docusaurus). - Navigations-Indizes
Der mechanische Teil (Landkarte-Vollständigkeit, Frontmatter-Präsenz, _category_.json)
wird von scripts/check-doc-consistency.sh geprüft (harte Teilmenge blockt in CI, Rest warnt — OP-DOCS-9/-14, §5.1).
3. Identifikator-System
Jede Entscheidung, jedes Feld, jede Empfehlung, jeder offene Punkt hat eine kurze stabile ID. Diese IDs sind über das gesamte Repo durchsuchbar und werden in Commits, PRs, Issues, Chats referenziert.
| Präfix | Bedeutung | Quelle |
|---|---|---|
G-n | Globales Prinzip | Lastenheft §3 |
Rx | Modul (R1 Mitarbeiter, R2 Arbeitsplätze, …) | Lastenheft §4–5 |
Rx-F## | Feld einer Entität | Lastenheft Tabellen |
Rx-S## | Sub-Entität / Tab | Lastenheft |
A-n | Architektur-Empfehlung | Lastenheft §9 |
S-n | Vereinfachung gegenüber Altsystem | Lastenheft §10 |
UC-x | Kern-Use-Case | Lastenheft §2 |
OP-Rx-n | Offener Punkt | ops/<ID>.md (fachliches Detail oft Lastenheft §11) |
FR-n | Future-Release-Note | Lastenheft §12 |
FM-n | Future-Module-Note | Lastenheft §12 |
Regel für Commits: Wenn ein Commit eine entscheidung-relevante Änderung vornimmt, ID(s) in der Commit-Message nennen, z. B.:
Resolve OP-R7-8: Termin-Ampel Schwellen (4h grün, 0h orange)
4. Verbindliche Dokumente (lesen in dieser Reihenfolge)
HANDOFF.md— Wie ist der aktuelle Stand? Status, geparkte Fragen, nächste Schritte. Bei jeder neuen Session zuerst.docs/fachlich/Lastenheft.md— Was bauen wir? Vollständige fachliche Spezifikation mit Diagrammen. Master.docs/konventionen/agents.md— dieses Dokument.README.md— Wie starte ich es? Orientierung, Setup, Deploy.
Außerdem gepflegt (nicht zwingend zuerst zu lesen): docs/betrieb/Timesheet.md — Arbeitszeit-Timesheet (Start/Stop je Session · Gap-Regel · Methodik); am Session-Ende aktualisieren. Protokoll → §5.1 „Arbeitszeit erfassen".
5. Verhaltensregeln für Agenten
5.1 Was tun
- IDs respektieren: Beim Verweis auf existierende Entscheidungen ID nennen (z. B. „gemäß R3a-F04 ist Standzeit in Stunden").
- Lastenheft und HANDOFF gemeinsam pflegen: Eine neue Entscheidung landet als Update im Lastenheft (Kern-Spec) und in HANDOFF.md (kompakt für die nächste Session).
- Markdown + Mermaid: Neue Dokumente in
.mdanlegen. Diagramme als Mermaid inline. - Single Source of Truth: Wenn ein Wert (z. B. Status) abgeleitet werden kann, wird er abgeleitet — nirgends doppelt gespeichert. Siehe G-2 / S-2.
- Selbsterklärbarkeit: Taktano soll ohne Schulung verständlich sein — durchgängig sprechende, eindeutige Bezeichnungen für Status, Aktionen, Felder und Räume (Werkstatt-Sprache statt technischer/abstrakter Labels; z. B. „Fahrzeug angeliefert" statt „Reserviert"). Gilt für UI und Doku. Bei neuen Labels diesen Maßstab anlegen. (Lastenheft §1.2 Leitprinzip.)
- Anführungszeichen: gerade ASCII-Zeichen (
"und') sind der Standard — in Code, Doku und UI-Strings (PO-Entscheid 07-18). Keine typografischen/geschwungenen Anführungszeichen in neuem Text; Bestehendes bleibt (kein retroaktiver Umbau, keine ungefragten Sweeps). CodeRabbit ist entsprechend konfiguriert (.coderabbit.yaml→tone_instructions), den Anführungszeichen-Stil nicht mehr zu beanstanden. - Tests on-demand + CI: Alle automatischen Tests müssen lokal on demand ausführbar sein (Anleitung in
README.md) und in der CI/CD-Pipeline laufen. Neue Tests immer beiden Wegen hinzufügen (Lastenheft §11.10; OP-TEST-1/2/3). - Versioniertes Datenmodell + automatische Migration: Jede Datenmodell-Änderung ist versioniert (z. B.
schemaVersion). Für jede neue Version gibt es eine automatische Migration. Jede Instanz wird beim Laden auf die Version geprüft und ggf. automatisch migriert (idempotent, jede Versionsstufe genau einmal). Beispiel im Code:SCHEMA_VERSION+ versionierte Remaps inserver/party/leitstand.ts(onStart). Persistierte Daten nie ohne Migration „brechen". - Logging via OpenTelemetry: Anwendungs-Logs (und Traces/Metrics) über das OTel-SDK je Laufzeit (Worker/DO · Angular-Client · Python-Solver) emittieren — nicht roh
console.log/printim Laufzeit-/Produktivpfad (CLI-Demos & Self-Tests dürfenconsole/print). Strukturiert über einen Logger-Wrapper,trace_id-korreliert. Verdrahtung + Collector/Backend: OP-OBS-1 (heute noch console-basiert). Siehe Root-CLAUDE.md→ Observability / Logging. - Tasks tracken: Multi-Step-Arbeit über das Task-System der Coding-Umgebung (Cowork TaskCreate/TaskUpdate, Claude Code TODO-System, etc.) sichtbar machen.
- Bei jeder größeren Aktion: offene Punkte im Auge behalten (
ops/*.md→Offene-Punkte.md). - Jedes Feature wird dokumentiert (goldene Regel): Kein Feature ist „fertig", bevor die zuständige Produkt-/Design-Doku es beschreibt (
WORKSPACES.md,OPTIMIERER_TERMINKLASSEN.md,COMPONENTS.md,DESIGN_TOKENS.md, Lastenheft). HANDOFF ist das Arbeitslog, kein Ersatz für die Produkt-Docs. - Doku-Konsistenz-Check (verbindlich, OP-DOCS-9): Die Doku muss in sich konsistent sein und zur Implementierung passen. Cadence: zu Session-Beginn die relevanten Docs sichten und vor jedem PR/Merge gegenprüfen (zusätzlich zu den Test-Gates). Zwei Achsen:
- Doku↔Doku (in sich): IDs (
G-/R-/A-/S-/OP-…) existieren & sind eindeutig, Glossar-Begriffe einheitlich verwendet (z. B. Crystal-Bar), Workspace-/Phasen-Liste und Status (✅/🟡/⛔) stimmen überHANDOFF.md·docs/fachlich/Lastenheft.md·CHANGELOG.md·design/überein, Version/Build überall =server/src/version.ts, Querverweise (§-Verweise, Datei-/Bildlinks) lösen auf, keine widersprüchlichen Aussagen. - Doku↔Implementierung: in der Doku genannte Feldnamen/Enums/DTOs/Routen/Token existieren im Code (und umgekehrt) und tragen dieselbe Bedeutung; beschriebene Features sind gebaut — und Gebautes ist beschrieben (goldene Regel). Bei Abweichung: entweder Code oder Doku angleichen (begründet entscheiden), nie still auseinanderlaufen lassen.
- Mechanik: der maschinell prüfbare Teil läuft als
bash scripts/check-doc-consistency.sh. Seit OP-DOCS-14 Teil 3 zweistufig: die harte Teilmenge (tote Links/Bilder · Version/Build-Single-Source · veraltete generierteOffene-Punkte.md) blockt den Merge (CI-Jobdoc-consistencyläuft mit--strictund hängt amci-gate); alle übrigen Checks (Landkarte/Frontmatter/Sidebar · Log-Hygiene · Zeilenlängen · Footer-Staleness · Landkarte-Rücklink, Generatorscripts/gen-doc-footer.mjs) warnen weiter (::warning::). Der semantische Teil (IDs/Glossar/Workspace-Liste · Doku↔Code) ist Agenten-Pflicht und nicht voll automatisierbar — das Skript ersetzt ihn nicht. Bei Unklarheit/Widerspruch: nachfragen (nicht raten).
- Doku↔Doku (in sich): IDs (
- Audit-Trail: Entscheidungen + Diskussionsergebnisse festhalten: Jede Design-/Architektur-/Prozess-Entscheidung und jedes Diskussionsergebnis (auch UX-Richtungen, verworfene Optionen mit Begründung) landet in der Doku — fachlich im Lastenheft, OPs als
ops/<ID>.md, Design indesign/, Guiding Principles im Root-CLAUDE.md. Ziel: lückenloser, nachvollziehbarer Audit-Trail. - CHANGELOG.md pflegen (je PR):
CHANGELOG.md(Repo-Root) immer aktuell halten — ein Eintrag pro PR: Datum · PR-Nummer mit Link · kurze Beschreibung inkl. getroffener Entscheidungen, neueste zuerst. Der Changelog ist der schnelle chronologische Audit-Trail; die Tiefe steht in HANDOFF/Lastenheft. - Versionierung (je PR): nur
APP_VERSION(SemVer) inserver/src/version.tsbewusst setzen — die Build-Nummer kommt automatisch (Git-Commit-Count beim Deploy,build-number.ts/stamp-build.mjs, nicht von Hand). Details: Root-CLAUDE.md§Versionierung, OP-PM-2. - Test-Übersicht mitführen (je PR): Wer eine automatische Prüfung hinzufügt/entfernt (
test:*-Script, Smoke, Gate, CI-Job), ziehtdocs/betrieb/Tests.mdnach (Befehl · Prüfgegenstand · OP-Bezug · CI-Job) — die lebende, vollständige Liste aller automatischen Tests. Mechanischer Rückhalt:scripts/check-doc-consistency.shwarnt, wenn eintest:*-Script (server/ + client/) dort fehlt; der semantische Teil bleibt Pflicht (§5.1/OP-DOCS-9). Root-CLAUDE.md§Tests & CI. - Log-Hygiene (regelmäßig): die
merge=union-Logs (CHANGELOG/HANDOFF/Timesheet) zu Session-Beginn + nach Merges glätten (Duplikate raus, Nummern eindeutig, chronologisch) —scripts/check-doc-consistency.shflaggt Kandidaten,npm run smooth-logsentfernt sichere Duplikate automatisch. Detail: §6.6. - Annahmen sichtbar machen + Optionen zuerst: Berührt eine Aufgabe versteckte Annahmen oder Produkt-/Datenmodell-Entscheidungen, nicht drauflosbauen — Annahme explizit auflisten + begründen (gegen das Datenmodell prüfen), Optionen mit Empfehlung vorlegen, entscheiden lassen, dann bauen + Entscheidung dokumentieren.
- Verifizieren statt behaupten: Previewbare Änderungen live verifizieren (Preview-Tools, echte Daten) statt den User prüfen zu lassen; reine Logik als self-asserting Demo (in CI, z. B.
test:*); bei Client↔Server-Protokollen Symmetrie prüfen (jeder Client-Sender hat einen Server-Handler). - Arbeitszeit erfassen:
docs/betrieb/Timesheet.mdpflegen — Start/Stop je Session, Gap-Regel (> 1 h seit letzter Interaktion → User nach Stop fragen, neue Session). Am Session-Ende aktualisieren.
5.2 Was NICHT tun
- ❌ Keine binären Dokumente als Master-Quelle. Kein
.docx, kein.pdfals Spezifikations-Quelle. Wenn vorhanden, sind diese reine Exporte aus dem.md. - ❌ Keine ungefragten Refactorings am Lastenheft oder Prototyp. Erst klären, dann tun.
- ❌ Kein Pushen ohne Confirm in
main, wenn der Wert der Änderung unklar ist. Lieber Branch + PR. - ❌ Keine duplizierten Decision-Docs außerhalb von Lastenheft + HANDOFF. Wir vermeiden „Decision-Sprawl".
- ❌ Keine Read-Only-Analyse von Drittsystemen ohne expliziten User-Auftrag. Wenn nötig: User loggt selbst ein, Agent navigiert per Browser-Extension.
- ❌ Keine PII / Passwörter in Klartext committen.
5.3 Bei Unsicherheit
- Lieber eine kurze Frage stellen als annehmen.
- Wenn die Antwort nicht entscheidbar ist: Punkt als
ops/OP-Rx-n.mdparken (§6.2) und weitermachen.
6. Workflow für Änderungen
6.1 Eine Entscheidung treffen
- ID vergeben (oder bestehende referenzieren).
- Lastenheft §X (passender Abschnitt) updaten.
- HANDOFF.md §3 bzw. betroffene
ops/<ID>.mdupdaten (Entscheidung kompakt notieren oder OP schließen +gen-ops). - Commit-Message:
Resolve <ID>: <kurz>.
6.2 Eine offene Frage aufnehmen (ops/-first — verbindlich seit 07-12, OP-DOCS-11)
ops/<OP-ID>.mdanlegen (Vorlageops/_Vorlage.md; Frontmatter-Pflichtid/title/status/audience—gen-ops.mjsvalidiert hart). Diese Datei ist die einzige Quelle für Lebenszyklus/Status/Priorität des OP; die Beschreibung bleibt prägnant (wird als GitHub-Issue gespiegelt), Tiefe gehört insdetail-Ziel (Owning-Doc).node scripts/gen-ops.mjs(bzw.npm run gen-opsinserver/) → regeneriertdocs/betrieb/Offene-Punkte.md(Staleness blockt in CI, §5.1); der GitHub-Issues-Spiegel läuft automatisch bei Push (sync-ops.yml).- Fachlicher Kontext (falls vorhanden): im Owning-Doc bzw. passenden Lastenheft-Abschnitt kurz
verlinken (
ops/<ID>.mdals Status-Quelle nennen); bekommt der OP ein eigenes Dokument → Zeile inIDs.mdergänzen (§2.1). - Commit-Message:
Park <ID>: <kurz>.
Nicht mehr: OP-Einträge in HANDOFF.md §4 oder als Lastenheft-§11-Vollbeschreibung anlegen/pflegen —
der komplette Alt-Bestand wurde am 12.07.2026 hierher migriert (Big-Bang auf PO-Auftrag; §4 ist nur
noch ein Pointer, Lastenheft §11 bleibt fachliche Detailbeschreibung als detail:-Ziel, Status dort
nicht mehr pflegen). Die frühere Dreifach-Buchführung war Doku-Review-Befund D4.
Sichten & Steuern (OP-ORG-1, PO-Vorgabe 07-12): Die generierte 📊-Statistik + Grafik in
Offene-Punkte.md (OPs · Alt-Archiv · Entscheidungen · Risiken, offen vs. abgeschlossen) ist der
Standard-Blick — zu Session-Beginn kurz sichten (zusammen mit dem Risikoregister-Check, §5).
Fürs Stakeholder-Steuern dient das GitHub-Projects-Board über die op-sync-Issues (seit 07-12 live;
Auto-Add-Filter is:issue label:op-sync; die Spiegel-Labels status:*/prio:*/bereich:*/audience:*
dienen als Filter/Slice — Board-Spalten sind das Projects-eigene Status-Feld, „Item closed → Done"
läuft automatisch). Kadenz (PO-Entscheid 07-12): wöchentlicher PO-Blick aufs Board. Das Board ist
reiner Konsument — Statusänderungen laufen ausschließlich über ops/<ID>.md im Repo.
6.2a OP-Grooming & Diskussion (agentgetrieben, on-demand — PO-Entscheid 07-12)
Bewusst keine Pipeline/Automatik, sondern stehende Tasks, die ein Agent (Claude Code / Codex) auf Zuruf ausführt; das Repo bleibt alleinige Quelle (das Board ist reiner Spiegel).
- Priorität/Reihenfolge = im Repo entscheiden.
prio:(jetzt|next|spaeter) undstatus:werden direkt inops/<ID>.mdgesetzt — nicht auf dem Board. Dersync-ops-Spiegel trägt sie alsprio:*/status:*-Label ins Issue, das Board filtert danach. Es gibt keinen Board→Repo- Backflow (PO-Entscheid: Everything-as-Code, eine Quelle). - OP-Diskussion zusammenfassen (Task, auf Zuruf — „fasse die Diskussion zu OP-X zusammen"): Der
Agent liest die Kommentare des zugehörigen
op-sync-Issues (GitHub-MCP), verdichtet sie zu einem Block## Diskussion (Stand JJJJ-MM-TT)in derops/<ID>.mdund legt einen PR an. Weil der Datei-Body 1:1 ins Issue gespiegelt wird, ist die Zusammenfassung danach auch auf dem Board sichtbar. So kommt die Stakeholder-Diskussion (die sonst nur auf GitHub lebt) zurück in die Quelle der Wahrheit. - OP anreichern / grooming (Task, auf Zuruf — „groome OP-X"): Der Agent ergänzt je genanntem OP
einen Block
## Grooming (Stand JJJJ-MM-TT)mit Akzeptanzkriterien · Aufwand (grob) · Abhängigkeiten (OP-/RISK-IDs) · offene Compliance-/DSGVO-Fragen (DE/AT/CH) ·prio-Vorschlag und legt einen PR an — du entscheidest je OP. Genau hier werden die von Reviews angemahnten Klärpunkte bewusst abgearbeitet (statt sie in die Migration zu zwängen). Kein Massen-Lauf.
6.3 Eine neue Architektur-/Vereinfachungs-Idee
- Eintrag in Lastenheft §9 (
A-) oder §10 (S-). - Begründung mit ggf. Mermaid-Diagramm.
- Commit-Message:
Propose <ID>: <kurz>.
6.4 Codeänderungen am Prototyp
- TypeScript-Server:
cd server && npm run typecheckmuss passen. - Angular-Client:
cd client && npx ng build --configuration productionmuss passen (CI-Hook geplant, siehe HANDOFF §7). - Commit-Message-Konvention frei, aber mit relevanter Lastenheft-ID, wenn die Änderung eine Anforderung implementiert.
6.5 Doku-Konsistenz prüfen (Session-Start + vor jedem PR)
- Session-Start:
HANDOFF.md→docs/fachlich/Lastenheft.md→docs/konventionen/agents.mdlesen; relevante Docs zum Vorhaben sichten (der SessionStart-Hookscripts/session-start-hook.shblendet diese Erinnerung ein). - Vor dem PR: beide Achsen prüfen (Doku↔Doku und Doku↔Implementierung, s. §5.1 „Doku-Konsistenz-Check");
bash scripts/check-doc-consistency.shfür die mechanische Teilmenge laufen lassen. - Drift gefunden? Code oder Doku angleichen (begründet) — bei Unklarheit nachfragen. Ergebnis im PR/CHANGELOG vermerken.
- Commit-Message bei reiner Angleichung:
Sync docs <Bereich>: <kurz>.
6.6 Merge-Strategie & Log-Hygiene (OP-PM-2)
Problem: Praktisch jeder PR ergänzt die append-only Logs (CHANGELOG.md, HANDOFF.md, docs/betrieb/Timesheet.md) und früher auch die Build-Nummer in version.ts → bei parallelen Merges Dauer-Konflikte + Build-/Session-Nummern-Kollisionen.
Maßnahmen (umgesetzt):
merge=unionfür die drei Log-Dateien (.gitattributes): Git konkateniert beide Seiten statt zu blocken — kein Stop-the-line mehr.- Build-Nummer automatisch aus dem Git-Commit-Count (kein Hand-
+1mehr) → keine Build-Kollision (siehe Root-CLAUDE.md§Versionierung;scripts/stamp-build.mjs). - Session-ID sprechend, repo- & branch-abgeleitet (
<repo>-<Datum>-<branch-slug>, z. B.taktano-2026-06-28-comments-image-support-caix8o) statt fortlaufender Zahl (OP-PM-3): Der Repository-Name als Präfix macht die ID repo-übergreifend eindeutig und auf einen Blick zuordenbar; Branch-Name + Datum sind git-weit eindeutig → die Timesheet-Session-ID kann nicht kollidieren, der union-Merge konkateniert nur (kein Umnummerieren mehr). Sprechend (Repo=wo, Datum=wann, Slug=was) + chronologisch sortierbar. Alt-Sessions (Zahl 0…52 bzw. frühere<Datum>-<branch-slug>ohne Repo-Präfix) bleiben unverändert (nicht rückwirkend umgeschrieben). Detail:docs/betrieb/Timesheet.md§Protokoll. - Empfohlen (Repo-Setting): GitHub Merge Queue bzw. „Allow auto-merge" (Settings → General → Pull Requests) → serialisiert Merges, beendet das Wettrennen. Kann nicht per Repo-Datei gesetzt werden.
- „Update branch" lokal, nicht server-seitig (wichtige Einschränkung, 06-27 verifiziert): GitHubs server-seitiger Merge — der „Update branch"-Button, die
update-branch-API und die Mergeability-Berechnung — wendet den.gitattributes-merge=union-Treiber NICHT an. Ein PR, der die Logs berührt, zeigt nach einem main-Vorlauf darum trotzdemdirty/Konflikt, und „Update branch" scheitert mit422 merge conflict, obwohl derselbe Merge lokal (mit union) sauber durchläuft. Konsequenz: einen log-berührenden PR lokal aktualisieren —git fetch origin main→git merge origin/main(union greift) → vom Repo-Rootnode scripts/smooth-logs.mjs→ push —, nicht den GitHub-Button. Automatisiert: der Workflow.github/workflows/sync-pr-logs.ymlmacht genau das per Knopfdruck — Auslöser/sync-logs-Kommentar am PR oder manuellerworkflow_dispatch(PR-Nummer); bei echten Konflikten (jenseits der union-Logs) bricht er ab und kommentiert. (Hinweis: ein Push mit dem Default-GITHUB_TOKENtriggert keine neue PR-CI — optionales SecretSYNC_BOT_TOKEN[PAT,contents:write] setzen, dann läuft die CI nach dem Sync neu.) Der squash-Merge selbst ist von der Einschränkung unberührt, sobald der Branch main enthält (deshalb zuerst lokal syncen, dann squash-mergen).
Setup SYNC_BOT_TOKEN (optional, für den sync-pr-logs-Workflow): Damit der Push des Workflows die PR-CI neu auslöst, ein Repo-Secret SYNC_BOT_TOKEN hinterlegen — GitHub unterdrückt CI-Trigger für Pushes mit dem Default-GITHUB_TOKEN (Loop-Schutz), d. h. ohne das Secret wird der Branch zwar aktualisiert, die CI muss aber einmal manuell angestoßen werden (Checks-Tab → Re-run, oder leerer Commit). Least-privilege empfohlen: fine-grained PAT, nur auf drkv-com/taktano begrenzt, Permissions Contents: R/W (+ Pull requests: R/W für den Sync-Kommentar); alternativ ein GitHub-App-Installations-Token (sauberste Variante, nicht an ein Personenkonto gebunden). Ein klassischer PAT braucht zusätzlich den workflow-Scope, falls ein gesyncter Branch .github/workflows/** ändert. Anlegen: Settings → Secrets and variables → Actions → New repository secret SYNC_BOT_TOKEN, oder gh secret set SYNC_BOT_TOKEN. Compliance (OP-SEC-1/Risikoregister): langlebige Credentials — Ablauf setzen + rotieren, breite klassische PATs meiden. Der Workflow liest das Secret bereits (token: ${{ secrets.SYNC_BOT_TOKEN || github.token }}).
Pflicht — Logs regelmäßig glätten (union-Merge kann Duplikate/Reihenfolge-Unschärfe erzeugen):
- Wann: zu Session-Beginn und nach jedem Merge von
main. - Was: exakte Duplikate entfernen; Session-IDs (Timesheet — neu branch-abgeleitet/kollisionsfrei) und OP-/PR-Nummern eindeutig + chronologisch; Summen/KW-Aggregate im Timesheet stimmig; keine Konflikt-Marker-Reste.
- Hilfe (flaggt):
bash scripts/check-doc-consistency.shflaggt Kandidaten (Marker-Reste · doppelte Timesheet-Session-IDs · doppelte CHANGELOG-PR-Zeilen · Mega-Zeilen > 2000 Zeichen) — diese Log-Hygiene-Checks warnen, blocken nicht (die harte Teilmenge des Skripts blockt separat, §5.1). - Hilfe (fixt):
npm run smooth-logs(inserver/; odernode scripts/smooth-logs.mjs) entfernt byte-identische Duplikate automatisch (CHANGELOG-Einträge · Timesheet-Session-Zeilen) und meldet alles, was menschliches Urteil braucht (Konflikt-Marker-Reste · gleiche Session-ID mit abweichendem Inhalt) — es fasst Zweifelhaftes nie an und sortiert nicht um. Vorschau ohne Schreiben:npm run smooth-logs:check(Exit 1 bei Glätt-Bedarf). Das Urteils-Glätten (Reihenfolge/Chronologie, abweichende Inhalte zusammenführen) bleibt Agenten-Aufgabe.
6.7 Nicht-automatisierbare Checks (Agenten-Pflicht — „nicht per MCP/Skript prüfbar")
Problem: Einige Sicherheits-/Setup-Kontrollen lassen sich nicht per CI-Skript und nicht über die
GitHub-MCP zuverlässig prüfen — entweder fehlt ein MCP-Tool (Repo-Settings/Code-Scanning-Modus) oder
der CI-GITHUB_TOKEN hat keinen Admin-Scope. scripts/check-security-setup.sh (im wöchentlichen
weekly-audit.yml) prüft die mechanische Teilmenge und meldet diese Punkte best-effort als
ℹ️/⚠️ „nicht abfragbar" — die eigentliche Verifikation ist dann Agenten-Pflicht.
Wann: zu Session-Beginn, vor jedem PR und nach jeder Repo-Setting-Änderung.
Wie: wenn ein gh/Token mit ausreichendem Scope vorhanden ist, per gh api prüfen; sonst den
Nutzer fragen bzw. aktiv darauf hinweisen (Optionen zeigen, §5.3) und Abweichungen melden — nie still
übergehen.
Checkliste (nicht-mechanisch):
- Merge-Methoden = nur Squash aktiv (Merge-Commits + Rebase aus). —
gh api repos/<o>/<r> --jq '.allow_squash_merge,.allow_merge_commit,.allow_rebase_merge' allow_auto_merge= true (OP-PM-2). —gh api repos/<o>/<r> --jq '.allow_auto_merge'delete_branch_on_merge= true (Branch-Cleanup). —gh api repos/<o>/<r> --jq '.delete_branch_on_merge'- Code scanning läuft (Entscheidung 06-27: GitHub Default Setup, deckt TS+Python automatisch; kein eigener
codeql.yml— advanced + default schließen sich aus). —gh api repos/<o>/<r>/code-scanning/default-setup --jq '.state'(erwartetconfigured); ergänzend Security-Tab/Alerts sichten. - Branch-Protection auf
main(erforderliche Checks gesetzt). —gh api repos/<o>/<r>/branches/main/protection(Admin-Scope nötig). - Semantische Doku-Konsistenz (§5.1/§6.5) — ohnehin Agenten-Pflicht (kein Skript ersetzt sie).
Soll-Zustand (Stand 06-27): 1–4 ✅ gesetzt; verwaiste Alt-Branches (vor Auto-Delete gemergt) sind manuell aufzuräumen. Abweichungen vom Soll → im PR/HANDOFF vermerken und dem Nutzer melden.
6.8 CI-Pipelines: Concurrency (überholte Läufe abbrechen)
Regel: Jede Workflow-Pipeline bekommt einen concurrency-Block, wo er Nutzen bringt — d. h.
überall, wo mehrere Läufe desselben Kontexts (PR/Branch, Deploy-Ziel) überlappen können und der ältere
Lauf durch den neueren überflüssig wird. Das spart Runner-Minuten und liefert schneller ein aktuelles
Ergebnis. Gemeint ist das GitHub-Actions-Schlüsselwort concurrency: (Läufe gruppieren/canceln) —
nicht die Job-Parallelität (die regelt der Job-Graph über needs).
Muster (je Pipeline-Typ):
- CI / PR-Pipelines → nächsten Push auf denselben PR/Branch den vorherigen Lauf abbrechen lassen:
Nicht aufconcurrency:group: ci-${{ github.workflow }}-${{ github.ref }}cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
mainabbrechen — dort liefe sonst ein Deploy ins Leere. Umgesetzt inci.yml. - Deploy-/Ressourcen-Pipelines (genau ein Ziel, z. B. ein Worker) → überlappende Deploys
verhindern:
group: <deploy-ziel>(fixer Name),cancel-in-progress: true. - Serielle Jobs, die nicht abgebrochen werden dürfen (z. B. Log-Sync, Migrationen) →
nur serialisieren, nicht canceln:
cancel-in-progress: false. Umgesetzt insync-pr-logs.yml.
Faustregel cancel-in-progress: true für idempotente/überholbare Läufe (PR-CI, Deploy);
false, wenn jeder Lauf zu Ende laufen muss. Ergänzend wirkt die Trigger-Hygiene gegen
Doppelläufe (push nur auf main + pull_request statt push auf allen Branches, OP-CI-1) —
Concurrency und Event-Trigger greifen zusammen: der eine cancelt überholte Läufe desselben Events, der
andere verhindert den doppelten push+pull_request-Lauf desselben Commits.
Kein actions/setup-node-cache: npm auf dem persistenten self-hosted Runner. Der npm-Cache von
setup-node ist für ephemere GitHub-Runner gedacht (die nach jedem Lauf verschwinden). Unser Org-Runner
ist persistent → ~/.npm ist zwischen Läufen ohnehin warm; cache: npm würde nur ein großes Archiv
langsam durch den Actions-Cache-Service tarren/laden (auf flakiger Runner-Anbindung ein Timeout-Risiko).
Daher in ci.yml entfernt; npm ci/npm install nutzen das lokale ~/.npm. Auf Fork-PRs
(ubuntu-latest, ephemer) lädt npm dann frisch aus der Registry — selten und akzeptabel.
Schnelle Installs: die npm ci-Aufrufe in ci.yml laufen mit --prefer-offline --no-audit --fund=false
— nutzt das warme lokale ~/.npm ohne Audit-/Funding-Netz-Calls (spart Zeit, robuster bei flakiger
Anbindung). Der Pfad-Filter (changes-Job) hält bereichsfremde/docs-only-PRs schlank (schwere Jobs
skippen; „CI Gate" bleibt grün, skipped ≠ failure).
Runner-Labels hot vs. ephemeral (wichtig): Die self-hosted Runner der Org tragen ein Label —
hot = persistent (Arbeitsordner + ~/.npm + Build-Caches überleben zwischen Läufen), ephemeral
= frisch je Lauf. CI pinnt auf hot (runs-on: … || 'hot'), weil alle Cache-/Offline-Hebel nur dort
greifen: warmes ~/.npm (Offline-Installs), fehlender setup-node-npm-Cache (auf ephemeral wäre er sogar
nützlich), und der persistente Build-Cache (unten). Fork-PRs bleiben über das Gate auf ubuntu-latest;
Umschalten via Repo-Variable CI_RUNNER. Kapazität beachten: Pinnt CI auf hot, ist die Zahl der
hot-Runner die Parallelitäts-Obergrenze — genügend hot-Runner bereitstellen (≥ breitester Job-Fächer).
Persistenter Build-Cache (nur hot): Der Angular-Disk-Cache (.angular/cache) beschleunigt Folge-Builds
inkrementell. Zwei Voraussetzungen, beide gesetzt: (1) angular.json → cli.cache.environment: "all"
(Angular deaktiviert den Cache in CI sonst per Default), (2) actions/checkout mit clean: false im
Client-Job, damit der (gitignorierte) Cache den git clean -ffdx überlebt. Der Cache ist content-adressiert
(selbst-invalidierend) → unbedenklich; auf ephemeral/Fork-Runnern ist er wirkungslos (kein Zustand), aber
nie schädlich.
Auto-Rerun bei flakigem Runner (auto-rerun.yml): Schlägt ein CI-Lauf fehl, stößt ein
workflow_run-getriggerter Job die fehlgeschlagenen Jobs einmalig neu an (run_attempt < 2 deckelt auf
genau 1 Retry → kein Loop). Heilt die typische self-hosted-Flakiness (github.com:443-Timeout, Runner
mitten im Job gestorben, Laptop zu). Nicht neugestartet: abgebrochene Läufe (Concurrency-Cancel =
cancelled ≠ failure) und Fork-PRs. Ein echter Test-Fail läuft im Retry erneut rot (Preis: ein
Extra-Lauf je Fehlschlag; auf self-hosted ohne Minuten-Kosten vertretbar). Deploys sind bewusst
ausgenommen (bei Bedarf manuell re-runnen).
6.9 Kanonische PR-Checkliste (OP-DOCS-15)
Die vollständige Liste aller Je-PR-Pflichten steht an genau einem Ort:
.github/PULL_REQUEST_TEMPLATE.md
— GitHub legt sie jedem neuen PR automatisch in den Body (Checkboxen). Hintergrund: das Doku-Review
2026-07 (Befund D5) belegte ~20 Pflichten verstreut über ≥5 Orte, einige nur als Tabellenzelle
(z. B. Funktionsumfang-Pflicht) — Rezept für selektive Compliance.
Rollenverteilung (kein neuer Regel-Owner!): Die Checkliste ist eine Sicht; jede Pflicht
zitiert ihre Owner-Regel (CLAUDE.md bzw. dieses Dokument). Pflege-Regel: Wer eine Je-PR-Pflicht
einführt, ändert oder streicht, zieht das Template im selben PR nach — eine Pflicht, die dort
fehlt, existiert praktisch nicht. Agenten, die PRs per API erstellen (eigener Body statt Template),
arbeiten die Checkliste inhaltlich ab und spiegeln die Struktur im PR-Body.
7. Branch- und Push-Konventionen
- Default-Branch:
main. - GitHub-Operationen über die GitHub-API/MCP, nicht über lokales
git/gh(verbindlich, v. a. in der Remote-/Cloud-Session): Remote-Schreibvorgänge — PR anlegen/mergen, Review-/Issue-Kommentare, Commits/Pushes auf Remote-Branches — laufen über die GitHub-MCP-Tools (create_pull_request,merge_pull_request,create_or_update_file/push_files,add_issue_comment, …); CI-Status & Mergeability überpull_request_read(get_status/get_check_runs) prüfen, nicht erraten. Grund: in der Remote-Ausführungs-Umgebung sind lokalegit-Schreibbefehle (push/commit) unzuverlässig (der Permission-Stream bricht intermittierend ab); die API ist robust, atomar und permissions-arm. Lokalesgitbleibt für lokale Arbeit ok (Branch anlegen, Merge/Rebase + Konflikt-Auflösung im Arbeitsbaum, Reads wiestatus/diff/log). Der „go"-Gate (unten) gilt unverändert — nur der Transport-Weg ist die API. - Neuer Code (KI) → immer zuerst einen neuen Branch anlegen und nur dort arbeiten. Verbindlich: Erzeugt/ändert ein KI-Agent Code, legt er vor der ersten Änderung einen Feature-Branch an (
git checkout -b …) und committet/pusht ausschließlich dort; Merge nachmainnur via PR (mit grüner CI). Niemals Code direkt aufmain. - Doku-Fast-Track statt Direkt-Push: Auch reine Doku-Änderungen laufen über Branch + PR (nie Direkt-Push auf
main) — der Audit-/PR-Nummern-Trail bleibt lückenlos (§5.1, CHANGELOG „je PR ein Eintrag"). Damit das friktionsfrei bleibt, gilt für PRs, deren Diff ausschließlich Doku berührt (alle geänderten Dateien liegen unterdocs/oder sind*.md): (1) die schweren CI-Jobs (Server/Client/Solver/Design/SBOM) werden übersprungen — derchanges-Job inci.ymlerkennt „docs-only" und der aggregierteCI Gate(einziger Required-Check) wird trotzdem grün; (2) Auto-Merge darf aktiviert werden (GitHub „Auto-merge", Squash). So ist ein Doku-PR praktisch Ein-Klick, ohne die App-CI zu binden. Sobald eine Nicht-Doku-Datei im Diff ist, läuft die volle CI (Fast-Track entfällt automatisch). Repo-Voraussetzung: Branch-Protection vonmainverlangt nur den CheckCI Gate(nicht die Einzel-Jobs), und „Allow auto-merge" ist aktiv. - Force-Pushes nur lokal, niemals auf shared Branches.
- „go"-Gate: Commit, Push und Merge erfolgen nur auf explizites „go" des Users. Einen Branch anlegen + Dateien im Arbeitsbaum vorbereiten ist ok; das Schreiben in die Historie / nach außen (Push, PR, Merge) wartet auf „go".
- pr-weise: offene PRs einzeln mergen (einer nach dem anderen), jeweils mit grüner CI — kein Sammel-Merge.
- Branch laufend auf
mainaktuell halten: Den Feature-Branch nicht nur am Ende, sondern durchgängig auf den aktuellenmainbringen — (1) zu Beginn, bevor inhaltliche Änderungen starten (frisch vonmainabzweigen bzw. direkt aktualisieren); (2) in vernünftigen Abständen während längerer Arbeit; (3) vor dem Erstellen des PR; (4) vor dem Merge. Mechanik:git fetch origin main→git rebase origin/main(bei bereits geteiltem/gestapeltem Branch:git merge origin/main). Grund:mainbewegt sich durch parallele Merges; frühes + regelmäßiges Aktualisieren hält die Divergenz klein — etwaige Konflikte entstehen lokal beim Autor (nicht erst beim Merge als „base branch was modified") und bleiben winzig. - Branch nach Merge schließen: Sobald ein PR gemergt ist, wird der zugehörige Feature-Branch gelöscht (remote und lokal) — kein Sammeln verwaister Branches. Empfohlen ist die GitHub-Repo-Einstellung „Automatically delete head branches" (löscht den Head-Branch automatisch beim Merge); ist sie nicht aktiv, löscht der Agent den Branch unmittelbar nach dem Merge selbst (
git push origin --delete <branch>+git branch -d <branch>). Ausnahme nur für Branches, die noch von anderen offenen PRs als Basis dienen. - Feature-Branches aktuell halten: Laufende Feature-Branches werden regelmäßig gegen
mainaktualisiert, damit zwischenzeitlich gemergte PRs einfließen und Konflikte klein bleiben. Konkret: zu Session-Beginn und vor PR-Erstellunggit fetch origin mainundmainin den Branch mergen bzw. den Branch darauf rebasen; bei langen Sessions auch zwischendurch, sobald relevante PRs aufmainlanden. - Doku-Pflicht je PR & Merge: Jeder PR pflegt
HANDOFF.mdunddocs/betrieb/Timesheet.mdmit (und die fachlich betroffenen Docs — Lastenheft, Design-Docs, Sanity-Checkliste; goldene Doku-Regel §5.1). Konkret: (a) vor dem Erstellen eines PR ist HANDOFF (§2 Stand) + betroffeneops/-Dateien auf den Stand des Branches gebracht und der Timesheet-Eintrag der Session aktualisiert; (b) beim Merge wird, falls sich seit PR-Erstellung etwas geändert hat, HANDOFF nachgezogen. Ein PR ohne HANDOFF-/Timesheet-Pflege gilt als unvollständig.
8. Cowork-Setup-Snippet (für eine neue Session)
Was der User in der ersten Nachricht typischerweise sagt:
Lies
HANDOFF.mdunddocs/konventionen/agents.md. Dann arbeiten wir an: <Aufgabe>.
Damit hat der Agent (a) den aktuellen Stand, (b) die Konventionen, (c) den Auftrag — und kann sofort liefern.
9. Was nicht in dieses Repo gehört
- Personendaten realer Kunden / Mitarbeiter (auch nicht in Beispielen — die im Lastenheft sind synthetisch).
- Secrets, API-Keys, Tokens (für CI: GitHub Encrypted Secrets nutzen).
- Generierte Build-Artefakte (
dist/,.angular/,.wrangler/— siehe.gitignore). - Binär-Exporte als „Master" (
.docx,.pdf). Falls jemand temporär einen Export braucht, kann er ihn lokal ausLastenheft.mdgenerieren, sollte ihn aber nicht committen.
Letztes Update: 27.06.2026 (Way-of-Working: Doku-Fast-Track — reine Doku-PRs überspringen die schwere CI [changes-Job + aggregierter CI Gate als einziger Required-Check] und dürfen per Auto-Merge durch; §7 — baut auf OP-PM-2 [union-Merge-Logs + Auto-Build-Nummer, §6.6] auf). Frühere: 26.06.: GitHub-Operationen über die GitHub-API/MCP statt lokales git/gh für Remote-Writes (§7; lokales git push/commit ist in der Remote-Session unzuverlässig). 23.06.: Branch laufend auf main aktuell halten — zu Beginn, in Abständen, vor PR & vor Merge [fetch+rebase/merge origin/main]. 22.06.: goldene Doku-Regel · Annahmen-sichtbar/Optionen-zuerst · Verifizieren statt behaupten · Timesheet-Pflicht · „go"-Gate · pr-weise · Branch nach Merge schließen · Doku-Pflicht je PR & Merge: HANDOFF + Timesheet.