Zum Hauptinhalt springen

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).


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 Agenten-Instanz.

Konsequenzen:

  • GitHub drkv-com/medidentas ist die einzige Quelle der Wahrheit.
  • Eine neue Session startet nicht "bei null" — sie liest HANDOFF.md, docs/fachlich/Lastenheft.md und dieses Dokument und 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).

Begründung: Git-diffbar, reviewable, mergeable; Diagramme als Code (Mermaid) sind genauso versioniert wie der Prosa-Text; Coding-Agenten können .md direkt lesen, ändern und Diffs erzeugen; keine Tooling-Abhängigkeit.

Mermaid-Typen, die wir im Repo verwenden:

TypWofür
flowchartUse-Cases, Architektur, Prozess-Logik
erDiagramDatenmodell, Entitäts-Beziehungen
stateDiagram-v2Lifecycle (Mandant, Dokument, Unterschrift)
sequenceDiagramInteraktionen (NextCloud-Upload, Signatur-Webhook)
ganttzeitliche Abläufe (Wiedervorlagen, Fristen)

Anführungszeichen: immer gerade ("/'), nie typografisch. Alle .md-Dokumente nutzen ausschließlich gerade Anführungszeichen ("…", '…') — kein deutsches „…", kein «…», keine kurvigen "…"/'…'. Grund: der historische Bestand mischte „…" (öffnend typografisch, schließend gerade) mit vereinzelt korrektem „…" und löste damit wiederholt CodeRabbits Typografie-Nitpicks aus (MED-D-145) — ein einheitliches, gerades Zeichen ist eindeutig zu matchen und tool-stabil. Ausnahme: technische Platzhalter-Notation wie ‹Variable› in Dentmarking-Excel-Logik.md (Excel-Formel-Konvention, kein Zitat) bleibt unangetastet. .coderabbit.yaml weist CodeRabbit über path_instructions explizit an, gerade Anführungszeichen nicht zu bemängeln.

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äfixBedeutungQuelle
G-nGlobales PrinzipCLAUDE.md / Lastenheft §3
RxModul (R1 Mandant, R2 Onboarding, …)Lastenheft §4–5
Rx-F##Feld einer EntitätLastenheft Tabellen
A-nArchitektur-EntscheidungLastenheft §9 / docs/architektur/
S-nVereinfachungLastenheft §10
UC-xKern-Use-CaseLastenheft §2
OP-<Thema>-nOffener Punkt (z. B. OP-SIGN-1, OP-STACK-1)Lastenheft §11 / HANDOFF.md §4
FR-nFuture-Release-NoteLastenheft §12
<TOOL>-nAnforderung eines Spezial-Tools (tool-scoped, z. B. DEX-n für Dexman)docs/spezialtools/<Tool>.md
D-nChronologische Entscheidung (Audit-Trail)docs/betrieb/Decision-Log.md
RISK-nRisiko (Technik/Sicherheit/Datenschutz/Regulatorik)docs/betrieb/Risikoregister.md
KB-nKunden-Besprechungspunkt (vor dem Bau zu klären)docs/betrieb/Kunden-Besprechungspunkte.md

Projekt-Kürzel MED (verbindlich, ab MED-D-51): neu vergebene IDs sowie Chat-/Session-Namen tragen das Präfix MED- (z. B. MED-D-51, MED-OP-<Thema>-n, Session-ID MED-<Datum>-<branch-slug>). Bestehende IDs werden nicht retroaktiv umbenannt — Alt- und Neu-Bestand koexistieren bewusst; eine Alt-ID wird erst mitgezogen, wenn ihre Zeile inhaltlich angefasst wird. (Beschlossen als MED-D-51.)

Repo-übergreifende IDs (Repo-Key-Registry, MED-D-57): Für repo-übergreifende Referenzen wird eine ID mit dem Repo-Key qualifiziert (analog GitHubs owner/repo#123): taktanoTKT (TKT-OP-CI-2) · medidentasMED (MED-OP-SIGN-1) · gh-self-hosted-runners-director (gh-runner-manager) → GRM (GRM-OP-2). Der medidentas-Key MED ist zugleich das stehende Präfix neuer medidentas-IDs (MED-D-51 oben) — neue IDs sind hier ohnehin MED-…; die Registry ergänzt die Fremd-Repo-Keys TKT/GRM und hält die drei Keys projektweit konsistent. Bestehende bare Alt-IDs bleiben unverändert (keine Massen-Umbenennung); parallel verankert in taktano (docs/konventionen/IDs.md) und gh-runner-manager (docs/open-points.md).

Regel für Commits: Wenn ein Commit eine entscheidungs-relevante Änderung vornimmt, ID(s) in der Commit-Message nennen, z. B.:

Resolve OP-SIGN-1: E-Signatur-Provider = DocuSign (eIDAS-QES für Verträge)

ID-Vergabe bei parallelen Sessions (MED-D-110). Neue MED-D-n/MED-OP-…-IDs werden aus dem höchsten bereits vergebenen Stand abgeleitet — Quelle ist der jeweils aktuelle main (git fetch origin maingrep -oE 'MED-D-[0-9]+' docs/betrieb/Decision-Log.md | sort -n | tail -1), nicht der lokale Branch-Stand. Laufen mehrere Sessions parallel, kann dieselbe Nummer trotzdem doppelt gegriffen werden (am 12.07. zweimal: MED-D-93/94, MED-D-95). Konfliktregel: Wird beim main-Abgleich vor dem PR eine Kollision sichtbar (die eigene ID ist auf main bereits anderweitig belegt), weicht der noch nicht gemergte PR nach oben aus (höchste freie Nummer) und zieht die Referenzen konsistent nach — der bereits gemergte Eintrag behält seine ID (append-only, First-merge-wins). Beim ID-Ziehen daher spät festlegen (kurz vor dem PR erneut gegen main prüfen) statt früh reservieren.

4. Verbindliche Dokumente (lesen in dieser Reihenfolge)

  1. HANDOFF.mdWie ist der aktuelle Stand? Status, geparkte Fragen, nächste Schritte. Zuerst.
  2. docs/fachlich/Lastenheft.mdWas bauen wir? Vollständige fachliche Spezifikation. Master.
  3. docs/konventionen/agents.md — dieses Dokument.
  4. CLAUDE.md / README.md — gebündelte Leitplanke bzw. Setup/Orientierung.

Außerdem gepflegt: docs/betrieb/Timesheet.md — Arbeitszeit-Timesheet; am Session-Ende aktualisieren (Session-Zeile und das KW-Aggregat + Gesamtsumme — je Session mitziehen, damit die Zeit-Statistiken jederzeit stimmen, nicht erst „nach Wochenschluss"). Protokoll → §5.1 "Arbeitszeit erfassen".

5. Verhaltensregeln für Agenten

5.1 Was tun

  • IDs respektieren: Beim Verweis auf existierende Entscheidungen ID nennen.
  • Lastenheft und HANDOFF gemeinsam pflegen: Eine neue Entscheidung landet im Lastenheft (Kern-Spec) und in HANDOFF.md (kompakt für die nächste Session).
  • Markdown + Mermaid: Neue Dokumente in .md. Diagramme als Mermaid inline.
  • Single Source of Truth: Wenn ein Wert abgeleitet werden kann, wird er abgeleitet — nirgends doppelt gespeichert (z. B. "Onboarding vollständig?" aus den Pflicht-Items).
  • Standardwerkzeuge bevorzugen (G-1): Wo ein bewährtes Standard-Tool die Aufgabe löst, anbinden statt nachbauen (Dokumente → NextCloud, Unterschriften → DocuSign/PandaDoc, Kundenstamm → CRM). Eigenbau begründen (warum kein Standard).
  • Selbsterklärbarkeit (G-3): durchgängig sprechende, eindeutige Bezeichnungen (Beratungs-/ Back-office-Sprache statt technischer Labels; z. B. "Unterschrift ausstehend" statt "pending"). UI und Doku.
  • Rechtssichere, lückenlose Doku (G-4): Beratungsdoku, Unterschriften, Belege append-only + auditierbar.
  • Datenschutz by design (G-5): PII minimal, EU-/CH-Residenz, keine PII/Secrets im Klartext.
  • Jedes Feature wird dokumentiert (goldene Regel): Kein Feature ist "fertig", bevor die zuständige Produkt-/Architektur-Doku es beschreibt. HANDOFF ist das Arbeitslog, kein Ersatz für die Fach-Docs.
  • Doku-Konsistenz-Check (verbindlich, OP-DOCS-1): Die Doku muss in sich konsistent sein und (sobald Code existiert) zur Implementierung passen. Cadence: zu Session-Beginn sichten und vor jedem PR/Merge gegenprüfen. Zwei Achsen:
    • Doku↔Doku: IDs (G-/R-/A-/S-/OP-…) existieren & sind eindeutig, Glossar-Begriffe einheitlich, Modul-/Phasen-Liste und Status (✅/🟡/⛔) stimmen über HANDOFF.md · Lastenheft.md · CHANGELOG.md überein, Querverweise lösen auf, keine widersprüchlichen Aussagen.
    • Doku↔Implementierung: genannte Feldnamen/Enums/DTOs/Routen existieren im Code (und umgekehrt); beschriebene Features sind gebautund Gebautes ist beschrieben.
    • Mechanik: der maschinell prüfbare Teil läuft als bash scripts/check-doc-consistency.sh (tote Links/Bilder + Log-Hygiene) — warnt, blockt nicht. Der semantische Teil ist Agenten-Pflicht. Bei Unklarheit/Widerspruch: nachfragen (nicht raten).
  • Audit-Trail: Entscheidungen + Diskussionsergebnisse festhalten: Jede Design-/Architektur-/Prozess- Entscheidung und jedes Diskussionsergebnis (auch verworfene Optionen mit Begründung) landet in der Doku — fachlich/OP in HANDOFF.md §4 + Lastenheft, Architektur in docs/architektur/, Guiding Principles in CLAUDE.md.
  • CHANGELOG.md pflegen (je PR): ein Eintrag pro PR — Datum · PR-Nummer mit Link · kurze Beschreibung inkl. getroffener Entscheidungen, neueste zuerst.
  • Versionierung (je PR): APP_VERSION (SemVer) bewusst setzen, sobald die Single-Source-Stelle existiert (OP-STACK-1) — Build-Nummer kommt dann automatisch. Solange nur Doku: keine Versions-Datei nötig.
  • Log-Hygiene (regelmäßig): die merge=union-Logs (CHANGELOG/HANDOFF/Timesheet) zu Session-Beginn
    • nach Merges glätten (Duplikate raus, IDs eindeutig, chronologisch) — check-doc-consistency.sh flaggt Kandidaten. Detail: §6.
  • Annahmen sichtbar machen + Optionen zuerst: Berührt eine Aufgabe versteckte Annahmen oder Produkt-/ Datenmodell-Entscheidungen, nicht drauflosbauen — Annahme explizit auflisten + begründen, Optionen mit Empfehlung vorlegen, entscheiden lassen, dann bauen + Entscheidung dokumentieren.
  • Verifizieren statt behaupten: Previewbare Änderungen live verifizieren (z. B. docs-site-Build) statt den User prüfen zu lassen.
  • Arbeitszeit erfassen: docs/betrieb/Timesheet.md pflegen — Start/Stop je Session, Gap-Regel (> 1 h seit letzter Interaktion → User nach Stop fragen, neue Session). Am Session-Ende aktualisieren.
  • Proaktives Compliance-Flagging: kritische/regulatorisch relevante Themen für DE/AT/CH (DSGVO/revDSG, eIDAS/ZertES, Aufbewahrungsfristen …) aktiv flaggen + Optionen zeigen; im Risikoregister eintragen.

5.2 Was NICHT tun

  • Keine binären Dokumente als Master-Quelle.
  • Keine ungefragten Refactorings am Lastenheft oder Code. 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 (Decision-Sprawl vermeiden).
  • Kein Eigenbau, wo ein Standard-Werkzeug passt (G-1) — ohne begründete Ausnahme.
  • Keine PII / Passwörter / Secrets in Klartext committen.

5.3 Bei Unsicherheit

  • Lieber eine kurze Frage stellen als annehmen.
  • Wenn nicht entscheidbar: Punkt als OP-<Thema>-n in Lastenheft §11 und HANDOFF §4 parken und weitermachen.

5.4 Kanonische Quellen — "eine Definition, ein Ort" (MED-D-110, aus Doku-Audit B16–B18)

Jede wiederkehrende Regel hat genau eine maßgebliche Stelle (G-2, gilt auch für Meta-Doku). Andere Docs dürfen sie zusammenfassen und darauf verlinken, aber nicht divergierend neu formulieren — sonst driften sie (Beleg: G-8 fehlte nach MED-D-85 in fünf Docs). Bei Widerspruch gilt die kanonische Stelle.

RegelKanonische QuelleWer verweist
Leitprinzipien G-1…G-n (Volltext)CLAUDE.md §LeitprinzipienEntwicklungsansatz, Lastenheft §3, agents.md (nur Kurzform + Link)
Session-Start-Lesereihenfolgeagents.md §4CLAUDE.md, HANDOFF, README (Kurzform + Link)
ID-System + ID-Vergabe (parallel)agents.md §3CLAUDE.md, Entwicklungsansatz, README
Draft-PR-/Review-Workflow (MED-D-60/100)agents.md §7CLAUDE.md, Entwicklungsansatz
CI-Gate / Branch-Protection (MED-D-59/109)agents.md §6.5 + §7HANDOFF §6
Prozessphasen-/Lifecycle-Achsen + -Diagrammdocs/architektur/Prozessmodell.md §2/§3System-Charakter §1, Lastenheft §5
Pflege-Pflichtsatz je PRhier, §5.4 (Liste unten)CLAUDE.md, Entwicklungsansatz
Weltmodell / Wertobjekte (G-8)docs/architektur/Weltmodell-Data-Dictionary.mdCLAUDE.md G-8, Lastenheft

Pflege-Pflichtsatz je PR — kanonische Liste (nur die betroffenen führen, nicht mechanisch alle):

  • immer: CHANGELOG.md (ein Eintrag, mit PR-Link) · docs/betrieb/Timesheet.md (Session-Zeile) · HANDOFF.md (§2 Stand und/oder §4 OPs, soweit berührt).
  • bei Entscheidung: docs/betrieb/Decision-Log.md (MED-D-n) — und die kanonische Regel-Quelle oben.
  • bei neuem/geändertem Feature: docs/fachlich/Feature-Liste.md · docs/fachlich/Lastenheft.md.
  • bei neuen/entfernten Tests: docs/betrieb/Test-Uebersicht.md.
  • bei Kundenklärung: docs/betrieb/Kunden-Besprechungspunkte.md (MED-KB-n).
  • bei Code mit Versionssprung: server/src/version.ts (APP_VERSION).

Last-Kritik (B18). Die Liste wirkt lang, ist aber bedingt: ein reiner Fix berührt oft nur CHANGELOG + Timesheet + HANDOFF. Der merge=union-Trick (OP-PM-1) macht die append-only Logs konfliktfrei; der Aufwand liegt in den lebenden Übersichten (Feature-Liste/Test-Übersicht), die nur bei echten Feature-/Test-Änderungen anzufassen sind. Nicht jeder PR fasst "~10 Docs" an.

6. Workflow für Änderungen

6.1 Eine Entscheidung treffen

  1. ID vergeben (oder bestehende referenzieren).
  2. Lastenheft (passender Abschnitt) updaten.
  3. HANDOFF.md §3/§4 updaten (Entscheidung notieren oder offenen Punkt schließen).
  4. Commit-Message: Resolve <ID>: <kurz>.

6.2 Eine offene Frage aufnehmen

  1. Eintrag in Lastenheft §11 mit neuer ID OP-<Thema>-n.
  2. Eintrag in HANDOFF.md §4 (Kurzform).
  3. Commit-Message: Park <ID>: <kurz>.

6.3 Doku-Konsistenz prüfen (Session-Start + vor jedem PR)

  1. Session-Start: HANDOFF.mdLastenheft.mdagents.md lesen; relevante Docs sichten.
  2. Vor dem PR: beide Achsen prüfen (§5.1); bash scripts/check-doc-consistency.sh laufen lassen; docs-site baut durch.
  3. Drift gefunden? Doku (oder Code) angleichen, bei Unklarheit nachfragen; im PR/CHANGELOG vermerken.

6.4 Merge-Strategie & Log-Hygiene (OP-PM-1)

  • merge=union für CHANGELOG.md, HANDOFF.md, docs/betrieb/Timesheet.md (.gitattributes): Git konkateniert beide Seiten statt zu blocken.
  • Session-ID sprechend & branch-abgeleitetab MED-D-51 mit Projekt-Kürzel MED-<Datum>-<branch-slug> (Bestandszeilen bleiben ohne Präfix) → git-weit eindeutig; bei mehreren Sessions je Branch am selben Tag ein Zähl-Suffix -2/-3 anhängen (z. B. …-gkedy6-2), sonst kann die ID kollidieren.
  • "Update branch" lokal, nicht server-seitig: GitHubs server-seitiger Merge wendet den merge=union- Treiber NICHT an → log-berührende PRs lokal aktualisieren (git fetch origin maingit merge origin/main → push).
  • Pflicht — Logs regelmäßig glätten: zu Session-Beginn + nach Merges: exakte Duplikate entfernen, Session-/OP-/PR-Nummern eindeutig + chronologisch, keine Konflikt-Marker-Reste. bash scripts/check-doc-consistency.sh flaggt Kandidaten (warnt, blockt nicht).

6.5 Nicht-automatisierbare Checks (Agenten-Pflicht)

Einige Setup-Kontrollen lassen sich nicht per CI-Skript/MCP prüfen — dann per gh api (falls Token-Scope) oder den Nutzer fragen/hinweisen. Abweichungen melden, nie still übergehen. Setzen (die konkreten gh api-Kommandos für Merge-Regeln, Auto-Merge/Auto-Delete & Branch-Protection/Ruleset): Runbook docs/architektur/Deploy.md §7c — nur manuell/mit eigenem Admin-PAT, da der MCP-/Agenten-Token bewusst kein Administration-Recht trägt.

  1. Merge-Methoden = nur Squash aktiv. — gh api repos/<o>/<r> --jq '.allow_squash_merge,.allow_merge_commit,.allow_rebase_merge'
  2. allow_auto_merge = true (OP-PM-1). — gh api repos/<o>/<r> --jq '.allow_auto_merge'
  3. delete_branch_on_merge = true. — gh api repos/<o>/<r> --jq '.delete_branch_on_merge'
  4. Branch-Protection auf main (erforderliche Checks CI Gate und CodeRabbit, MED-D-59; "require branches up to date" bewusst AUS, MED-D-109 — sonst Rate-Limit-Treadmill bei Parallel-Merges). — prüft alle drei Invarianten (strict=false und beide Required-Contexts vorhanden): gh api repos/<o>/<r>/branches/main/protection --jq 'if .required_status_checks.strict==false and (.required_status_checks.contexts|index("CI Gate")) and (.required_status_checks.contexts|index("CodeRabbit")) then "ok" else error("branch-protection-Vertrag unvollständig") end'
  5. Semantische Doku-Konsistenz (§5.1) — ohnehin Agenten-Pflicht.

6.6 CI-Pipelines: Concurrency (überholte Läufe abbrechen)

Regel: Jede Workflow-Pipeline bekommt einen concurrency-Block, wo er Nutzen bringt — ü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 → neuer Push auf denselben PR/Branch bricht den vorherigen Lauf ab:
    concurrency:
    group: ci-${{ github.workflow }}-${{ github.ref }}
    cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
    Nicht auf main abbrechen (dort liefe sonst ein Deploy ins Leere). Umgesetzt in ci.yml.
  • Deploy-/Ressourcen-Pipelines (genau ein Ziel, z. B. der Worker) → überlappende Deploys verhindern: group: <deploy-ziel> (fixer Name), cancel-in-progress: true. Umgesetzt in app-deploy.yml.
  • Serielle Jobs, die nicht abgebrochen werden dürfen (z. B. Migrationen) → nur serialisieren, nicht canceln: cancel-in-progress: false.

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) — Concurrency und Event-Trigger greifen zusammen.

actions/setup-node-cache: npm ist konditional — nur auf GH-hosted, nicht auf self-hosted (MED-D-225). Der npm-Cache von setup-node ist für ephemere Runner gedacht: dort ist kaltes npm ci (voller Download) der Hauptkostenpunkt, den der Actions-Cache-Service abfängt. Auf dem persistenten self-hosted hot-Runner ist ~/.npm zwischen Läufen ohnehin warm; dort würde cache: npm nur ein großes Archiv (100en MB) langsam durch den Cache-Service schaufeln (Timeout-Risiko). Deshalb wird der Cache je Runner-Modus geschaltet: cache: ${{ (github.event.pull_request.head.repo.fork || vars.CI_RUNNER == 'ubuntu-latest') && 'npm' || '' }} (leerer String = kein Cache). Analog cached client-build .angular/cache per actions/cache nur auf GH-hosted (self-hosted hält ihn via clean:false). So ist jeder Modus optimal, ohne den anderen zu regressieren. Gilt in ci.yml (docs-build/server-test/client-build/sbom), app-deploy.yml, docs-deploy.yml.

Pipeline-Geschwindigkeit (weitere Hebel, in ci.yml umgesetzt):

  • Pfad-Filter (changes-Job, dorny/paths-filter): jeder schwere Job (server/client/docs) läuft nur, wenn sein Bereich geändert wurde — Doku-only-PRs überspringen Server/Client, Code-only die Doku-Site. Geteilte Dateien (ci.yml, scripts/**) triggern alle Bereiche; auf main-Push läuft immer alles voll (Deploy-Validierung). Übersprungene Jobs zählen im CI Gate als bestanden (skipped ≠ failure).
  • Schnelle Installs: npm ci --prefer-offline --no-audit --fund=false — nutzt das warme lokale ~/.npm ohne Audit-/Funding-Netz-Calls.
  • Flacher Checkout auf PRs: fetch-depth ist nur auf main-Push 0 (volle History für die Build-Nummer), auf PRs 1 (shallow) → schnellerer Checkout; die PR-Build-Nummer ist irrelevant (nicht deployt).
  • Angular-Build-Cache (beide Runner-Modi, je nach Herkunft, MED-D-225): .angular/cache beschleunigt Folge-Builds inkrementell — angular.jsoncli.cache.environment: "all" (Angular deaktiviert den Cache in CI sonst per Default). Wie er zwischen Läufen überlebt, hängt vom Runner-Modus ab: auf self-hosted hot via actions/checkout mit clean: false (der gitignorierte Cache übersteht den git clean -ffdx); auf GH-hosted (fork oder CI_RUNNER == 'ubuntu-latest') via actions/cache@v4 im client-build-Job (Key aus Client-Lockfile+sha, restore-keys-Fallback). Content-adressiert (selbst-invalidierend) → unbedenklich. Auf ephemeral self-hosted (frisch je Lauf, kein actions/cache-Guard) bleibt er wirkungslos.

Runner-Labels hot vs. ephemeral (wichtig): Die self-hosted Runner 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 obigen Cache-/Offline-Hebel nur dort greifen (auf ephemeral wäre der entfernte setup-node-npm-Cache sogar nützlich). Fork-PRs bleiben über das Gate auf ubuntu-latest; Umschalten via Repo-Variable CI_RUNNER. Kapazität: die Zahl der hot-Runner ist damit die Parallelitäts-Obergrenze — genügend hot-Runner bereitstellen (≥ breitester Job-Fächer).

Auto-Rerun bei flakigem Runner (auto-rerun.yml, D-40): Ein separater, workflow_run-getriggerter Workflow stößt bei einem fehlgeschlagenen CI-Lauf die fehlgeschlagenen Jobs genau einmal neu an (run_attempt < 2 → 1 Retry, kein Loop). Das heilt die typische self-hosted-Flakiness (github.com:443- Timeout beim Checkout/setup-node, Runner mitten im Job gestorben), ohne dass jemand manuell "Re-run failed jobs" klicken muss. Bewusst nicht neugestartet: abgebrochene Läufe (der Concurrency-Cancel liefert cancelledfailure) und Fork-PRs (head_repository ≠ repository → Sicherheits-Gate RISK-24 bleibt gewahrt). Dependency-frei via curl gegen die REST-API (rerun-failed-jobs, permissions: actions: write) — kein gh/Node-Action, also keine node20-Deprecation-Warnung. Deploys (app-deploy.yml/docs-deploy.yml) sind bewusst ausgenommen (ein halb-deployter Stand soll nicht blind wiederholt werden). Grenze: hängt der Runner permanent, hilft der Retry nicht — dann ist es kein Flake, sondern ein echter Ausfall (Runner prüfen).

6.7 Regelmäßige Meisterwerk-Audits (MED-D-97 / MED-OP-REVIEW-1) — kanonische Definition

Der Anspruch "App und Doku sind ein Meisterwerk" wird nicht nur behauptet, sondern periodisch auditiert. Zwei Quality-Audits, beide als datierte Docs in docs/betrieb/ (append-only Historie — neue Audits ergänzen, alte bleiben als Zeitzeugen liegen):

AuditFrageDatei-MusterErstausgabe
App-AuditIst die App ein Meisterwerk? (UX/Prozess, True North, G-3)UX-Prozess-Review-<JJJJ-MM>.md2026-07 (v0.62.0)
Doku-AuditIst die Doku ein Meisterwerk? (pyramidal · zielgruppen-gerecht · visuell · konsistent)Doku-Review-<JJJJ-MM>.md2026-07 (v0.65.0)

Verbindliche Regeln:

  1. Bezugspunkt-Pflicht: Jeder Audit nennt in der Titelzeile seinen Stand als (Stand vX.Y.Z, JJJJ-MM-TT) und im Kopf/Fuß den Commit-SHA — ohne klaren Bezugspunkt ist ein Audit wertlos, weil niemand weiß, worauf sich die Befunde beziehen.
  2. Kadenz: mindestens alle ~10 Minor-Versionen oder alle 3 Monate (was zuerst eintritt), zusätzlich nach jedem Meilenstein (z. B. 1.0.0) und nach Abschluss einer aus dem Audit abgeleiteten Maßnahmen-Serie (UX-Wellen / Doku-Wellen) — dann als Wirksamkeits-Kontrolle.
  3. Stale-Regel: Liegt der Bezugspunkt des jüngsten Audits ≥10 Minor-Versionen hinter APP_VERSION oder ist er >90 Tage alt, gilt der Audit als veraltet. Dann gilt: aktiv anregen, den Audit zu aktualisieren — der Agent flaggt das bei der Session-Start-Sichtung (§4) gegenüber dem Nutzer; mechanisch warnt scripts/check-doc-consistency.sh (warnt, blockt nicht).
  4. Folge-Arbeit als OPs: Audit-Befunde werden nicht im Audit "abgearbeitet", sondern als MED-OP-…-Punkte in HANDOFF.md §4 überführt (Vorbild: MED-OP-UX-1..4 aus dem App-Audit, MED-OP-DOKU-1..3 aus dem Doku-Audit) — der Audit bleibt unverändertes Zeitdokument.

7. Branch- und Push-Konventionen

  • Default-Branch: main.
  • GitHub-Operationen über die GitHub-API/MCP, nicht über lokales git/gh für Remote-Writes (verbindlich, v. a. in der Remote-/Cloud-Session): PR anlegen/mergen, Review-/Issue-Kommentare, Commits/Pushes auf Remote-Branches über die GitHub-MCP-Tools; CI-Status & Mergeability über pull_request_read prüfen, nicht erraten. Lokales git bleibt für lokale Arbeit ok (Branch, Merge/Rebase, Reads).
  • Neuer Code (KI) → immer zuerst einen neuen Branch anlegen und nur dort arbeiten. Merge nach main nur via PR (mit grüner CI). Niemals Code direkt auf main.
  • Doku-Fast-Track: Auch reine Doku-Änderungen laufen über Branch + PR (nie Direkt-Push auf main) — der Audit-/PR-Nummern-Trail bleibt lückenlos. Reine-Doku-PRs dürfen per Auto-Merge (Squash) durch. Required Checks (Branch-Protection main): CI Gate und der CodeRabbit-Commit-Status CodeRabbit (MED-D-59) — der Merge wartet auf "Review lief" (nicht "keine Findings"). "Require branches up to date" ist bewusst AUS (MED-D-109): ein einmal grüner PR mergt auch, wenn main inzwischen weitergezogen ist (behind blockt nicht) — sonst entsteht bei Parallel-Merges eine Rate-Limit-Treadmill (jedes Pflicht-Branch-Update triggert eine neue CodeRabbit-Review). Die Qualitätssicherung bleibt: CI + Review sind weiter Pflicht.
  • EIN Review je PR — Config + Draft-Workflow (verbindlich, MED-D-60 + MED-D-100): Zwei Hebel gegen Rate-Limit-Spend, die zusammenwirken:
    • Config (MED-D-100): .coderabbit.yaml auto_incremental_review: false → CodeRabbit reviewt genau einmal je PR (beim Umschalten auf "ready for review"), keine inkrementellen Re-Reviews je Folge-Push — unabhängig davon, wie oft gepusht wurde.
    • Verhalten (MED-D-60): Feature-PRs als Draft öffnen und im Draft frei bepushen (CodeRabbit reviewt Drafts nicht, drafts: false → kein Kontingent/Rauschen); erst wenn die Arbeit fertig ist auf "ready for review" schalten und Auto-Merge (Squash) scharfstellen. Preis (MED-D-100): ein Push nach dem Ready-Review bekommt keinen frischen CodeRabbit-Status → der Required-Check auf dem neuen Head bleibt offen und Auto-Merge wartet, bis manuell @coderabbitai review gepostet wird. Konsequenz: PR erst komplett (alle Commits, lokal grün) auf "ready" schalten; muss nach dem Review doch noch ein Fix gepusht werden, danach @coderabbitai review posten, damit der Check auflöst. Der Normalfall "ready → 1 Review → Merge" ohne Folge-Push löst ganz normal auf. Gilt für alle Agenten/Sessions. Bot-PRs (z. B. dependabot[bot]) werden mitreviewt (bewusst keine ignore_usernames-Ausnahme, MED-D-60): ein ausgenommener Bot-PR bekäme nie den CodeRabbit-Status und bliebe als Required Check dauerhaft am Gate hängen.
  • "go"-Gate: Commit, Push und Merge erfolgen nur auf explizites "go" des Users. Branch anlegen + Dateien im Arbeitsbaum vorbereiten ist ok; das Schreiben in die Historie / nach außen wartet auf "go". (Der Draft-PR-Workflow ändert das "go"-Gate nicht — auch das Öffnen des Draft-PR wartet auf "go".)
  • Branch laufend auf main aktuell halten: zu Beginn und in Abständen git fetch origin main → rebase/merge — zur Konflikt-/Drift-Vermeidung, nicht als Merge-Gate. Ein grüner, konfliktfreier PR darf behind mergen (MED-D-109 — "require branches up to date" ist AUS); ein Branch-Update vor dem Merge ist nur nötig, wenn main Konflikte bringt oder ein konkretes Risiko es rechtfertigt (z. B. Änderung an derselben Datei/Logik). Kein Update allein deshalb, weil der PR behind ist.
  • Branch nach Merge schließen: Sobald ein PR gemergt ist, wird der Feature-Branch gelöscht (remote + lokal); bevorzugt GitHub "Automatically delete head branches". Wirkung auf Stacking (MED-D-65): das Setting löscht nur den Head-Branch eines gemergten PRs (nicht unmerged/lokale Branches, nichts Rekursives) → stört Stacking nicht.
  • Stacked / Child-Branches bei komplexen Changes (MED-D-65): Getrennt reviewbare Teilschritte dürfen als Stack laufen (mainfeature-basisfeature-child, Child-PR-Base = feature-basis). Regeln: (a) bottom-up mergen — erst feature-basismain; GitHub retargetet offene Child-PRs dann automatisch auf main (der Child-Branch überlebt, weil er Head seines eigenen PRs ist). (b) Squash-Reibung einplanen: weil wir Squash-only mergen (OP-PM-1), ist der Squash-Commit auf main ≠ die Original-Basis- Commits im Child → nach jedem Parent-Merge das Child rebasen: git rebase --onto main <alte-basis> <child> + git push --force-with-lease. (c) Draft bis rebased: Child-PR als Draft halten (MED-D-60), bis Parent gemergt und Child rebased ist → CodeRabbit reviewt nur den finalen, korrekten Diff. Default bleibt "ein Branch, mehrere Commits, ein PR" (Squash faltet sie ohnehin) — Stacking nur, wenn die Teilschritte wirklich getrennt review-/mergebar sein müssen.
  • Doku-Pflicht je PR & Merge: Jeder PR pflegt HANDOFF.md und docs/betrieb/Timesheet.md mit (und die fachlich betroffenen Docs).
  • Push-Integrität — nie auf detached HEAD committen (verbindlich, MED-D-255). Auslöser: PR #288 mergte ein Duplikat und der eigentliche Fix erreichte nie main/Prod, weil ein Commit auf einem losgelösten (detached) HEAD entstand (git checkout origin/main zum Lesen) und git push -u origin <branch> dann die stale Branch-Referenz hochschob statt des neuen Commits. Verbindliche Disziplin:
    1. Vor jeder Änderung git checkout -B <branch> origin/main — HEAD ist dann immer ein echter Branch. Zum reinen Lesen von main nicht auschecken, sondern git show origin/main:<pfad>.
    2. Nach jedem Push verifizieren: git rev-parse HEAD == git rev-parse origin/<branch>. Weicht es ab → nicht mergen, Ursache klären.
    3. Vor dem (Auto-)Merge den PR-Diff sichten: die geänderten Dateien müssen zur Absicht passen; ein leerer oder falscher Diff (wie #288) = sofortiger Stopp.
    4. Nach dem Merge den Deploy verifizieren: Worker-modified_on muss nach der Merge-Zeit liegen (Cloudflare workers_list) bzw. der App-deploy_status den neuen Commit zeigen — fängt „gemergt, aber nicht live" ab. Guardrail (eingecheckt): .githooks/pre-push bricht einen Push aus detached HEAD (bzw. mit Spitze ≠ HEAD) ab; aktiviert via git config core.hooksPath .githooks (in scripts/session-start-hook.sh je Session automatisch gesetzt).

7a. Design-Sync aus Claude Design (MED-D-193)

Beim Übernehmen eines Designs/Design-Systems aus Claude Design (via DesignSync-MCP) gilt eine feste Regel (Nutzer-Vorgabe 2026-07-23):

  • Bei Diskrepanzen oder Konflikten mit früheren Entscheidungen (Wording, Enums, Datenmodell, IA, bereits getroffene MED-D-Entscheidungen …) wird der Konflikt dem Nutzer zur Klärung vorgelegt (AskUserQuestion oder kurze Prosa-Rückfrage) — nicht einseitig aufgelöst. Erst nach Klärung bauen.
  • Die Klärungs-Entscheidung wird als MED-D-Zeile im Decision-Log festgehalten (Everything-as-Code, G-2).
  • Reversible Defaults bevorzugen: wo eine risikoarme, umkehrbare Variante existiert (z. B. UI-Mapping statt Server-Enum-Umbau), diese als Default wählen und benennen; irreversible/breaking Änderungen (Migrationen, Enum-Renames) nie ohne ausdrückliche Zustimmung.
  • Präzedenz: die drei Weggabelungen aus MED-D-188 (Plan-first · Assistent gegen die Fakes · 1:n-Bankkonten) und die S2-Enum/Wording-Frage (MED-D-192, per UI-Mapping) wurden so entschieden.

8. Was nicht in dieses Repo gehört

  • Personendaten realer Kunden / Mitarbeiter (auch nicht in Beispielen — Beispiele sind synthetisch).
  • Secrets, API-Keys, Tokens (für CI: GitHub Encrypted Secrets nutzen).
  • Generierte Build-Artefakte (build/, .docusaurus/, node_modules/ — siehe .gitignore).
  • Binär-Exporte als "Master" (.docx, .pdf).

Letztes Update: 2026-07-23 (S2 Dokument-Zustandsmaschine MED-D-192 + Design-Sync-Konvention §7a MED-D-193; zuvor 2026-07-14 Doku-Welle 4c, MED-D-133-Folge: ID-System-Tabelle §3 um D-n/RISK-n/ KB-n ergänzt — diese Präfixe waren live im Einsatz, aber in der kanonischen Quelle nicht gelistet). Repo-Init (27.06.2026): Way-of-Working für Medidentas etabliert — übernimmt die bewährten Taktano-Konventionen [ID-System · md+mermaid · union-Merge-Logs · Branch-first · GitHub-MCP für Remote-Writes] und ergänzt G-1 Standardwerkzeuge-bevorzugen als domänenspezifisches Leitprinzip; seither laufend fortgeschrieben (u. a. §5.4 "eine Definition, ein Ort", MED-D-110).