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/medidentasist die einzige Quelle der Wahrheit. - Eine neue Session startet nicht "bei null" — sie liest
HANDOFF.md,docs/fachlich/Lastenheft.mdund 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:
| Typ | Wofür |
|---|---|
flowchart | Use-Cases, Architektur, Prozess-Logik |
erDiagram | Datenmodell, Entitäts-Beziehungen |
stateDiagram-v2 | Lifecycle (Mandant, Dokument, Unterschrift) |
sequenceDiagram | Interaktionen (NextCloud-Upload, Signatur-Webhook) |
gantt | zeitliche 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äfix | Bedeutung | Quelle |
|---|---|---|
G-n | Globales Prinzip | CLAUDE.md / Lastenheft §3 |
Rx | Modul (R1 Mandant, R2 Onboarding, …) | Lastenheft §4–5 |
Rx-F## | Feld einer Entität | Lastenheft Tabellen |
A-n | Architektur-Entscheidung | Lastenheft §9 / docs/architektur/ |
S-n | Vereinfachung | Lastenheft §10 |
UC-x | Kern-Use-Case | Lastenheft §2 |
OP-<Thema>-n | Offener Punkt (z. B. OP-SIGN-1, OP-STACK-1) | Lastenheft §11 / HANDOFF.md §4 |
FR-n | Future-Release-Note | Lastenheft §12 |
<TOOL>-n | Anforderung eines Spezial-Tools (tool-scoped, z. B. DEX-n für Dexman) | docs/spezialtools/<Tool>.md |
D-n | Chronologische Entscheidung (Audit-Trail) | docs/betrieb/Decision-Log.md |
RISK-n | Risiko (Technik/Sicherheit/Datenschutz/Regulatorik) | docs/betrieb/Risikoregister.md |
KB-n | Kunden-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): taktano → TKT (TKT-OP-CI-2) ·
medidentas → MED (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 main → grep -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)
HANDOFF.md— Wie ist der aktuelle Stand? Status, geparkte Fragen, nächste Schritte. Zuerst.docs/fachlich/Lastenheft.md— Was bauen wir? Vollständige fachliche Spezifikation. Master.docs/konventionen/agents.md— dieses Dokument.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 überHANDOFF.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 gebaut — und 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).
- Doku↔Doku: IDs (
- 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 indocs/architektur/, Guiding Principles inCLAUDE.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.shflaggt Kandidaten. Detail: §6.
- nach Merges glätten (Duplikate raus, IDs eindeutig, chronologisch) —
- 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.mdpflegen — 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>-nin 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.
| Regel | Kanonische Quelle | Wer verweist |
|---|---|---|
| Leitprinzipien G-1…G-n (Volltext) | CLAUDE.md §Leitprinzipien | Entwicklungsansatz, Lastenheft §3, agents.md (nur Kurzform + Link) |
| Session-Start-Lesereihenfolge | agents.md §4 | CLAUDE.md, HANDOFF, README (Kurzform + Link) |
| ID-System + ID-Vergabe (parallel) | agents.md §3 | CLAUDE.md, Entwicklungsansatz, README |
| Draft-PR-/Review-Workflow (MED-D-60/100) | agents.md §7 | CLAUDE.md, Entwicklungsansatz |
| CI-Gate / Branch-Protection (MED-D-59/109) | agents.md §6.5 + §7 | HANDOFF §6 |
| Prozessphasen-/Lifecycle-Achsen + -Diagramm | docs/architektur/Prozessmodell.md §2/§3 | System-Charakter §1, Lastenheft §5 |
| Pflege-Pflichtsatz je PR | hier, §5.4 (Liste unten) | CLAUDE.md, Entwicklungsansatz |
| Weltmodell / Wertobjekte (G-8) | docs/architektur/Weltmodell-Data-Dictionary.md | CLAUDE.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
- ID vergeben (oder bestehende referenzieren).
- Lastenheft (passender Abschnitt) updaten.
- HANDOFF.md §3/§4 updaten (Entscheidung notieren oder offenen Punkt schließen).
- Commit-Message:
Resolve <ID>: <kurz>.
6.2 Eine offene Frage aufnehmen
- Eintrag in Lastenheft §11 mit neuer ID
OP-<Thema>-n. - Eintrag in HANDOFF.md §4 (Kurzform).
- Commit-Message:
Park <ID>: <kurz>.
6.3 Doku-Konsistenz prüfen (Session-Start + vor jedem PR)
- Session-Start:
HANDOFF.md→Lastenheft.md→agents.mdlesen; relevante Docs sichten. - Vor dem PR: beide Achsen prüfen (§5.1);
bash scripts/check-doc-consistency.shlaufen lassen;docs-sitebaut durch. - Drift gefunden? Doku (oder Code) angleichen, bei Unklarheit nachfragen; im PR/CHANGELOG vermerken.
6.4 Merge-Strategie & Log-Hygiene (OP-PM-1)
merge=unionfürCHANGELOG.md,HANDOFF.md,docs/betrieb/Timesheet.md(.gitattributes): Git konkateniert beide Seiten statt zu blocken.- Session-ID sprechend & branch-abgeleitet — ab 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/-3anhä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 main→git 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.shflaggt 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.
- Merge-Methoden = nur Squash aktiv. —
gh api repos/<o>/<r> --jq '.allow_squash_merge,.allow_merge_commit,.allow_rebase_merge' allow_auto_merge= true (OP-PM-1). —gh api repos/<o>/<r> --jq '.allow_auto_merge'delete_branch_on_merge= true. —gh api repos/<o>/<r> --jq '.delete_branch_on_merge'- Branch-Protection auf
main(erforderliche ChecksCI GateundCodeRabbit, 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' - 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:
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. der Worker) → überlappende Deploys
verhindern:
group: <deploy-ziel>(fixer Name),cancel-in-progress: true. Umgesetzt inapp-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; aufmain-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~/.npmohne Audit-/Funding-Netz-Calls. - Flacher Checkout auf PRs:
fetch-depthist nur aufmain-Push0(volle History für die Build-Nummer), auf PRs1(shallow) → schnellerer Checkout; die PR-Build-Nummer ist irrelevant (nicht deployt). - Angular-Build-Cache (beide Runner-Modi, je nach Herkunft, MED-D-225):
.angular/cachebeschleunigt Folge-Builds inkrementell —angular.json→cli.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-hostedhotviaactions/checkoutmitclean: false(der gitignorierte Cache übersteht dengit clean -ffdx); auf GH-hosted (fork oderCI_RUNNER == 'ubuntu-latest') viaactions/cache@v4imclient-build-Job (Key aus Client-Lockfile+sha, restore-keys-Fallback). Content-adressiert (selbst-invalidierend) → unbedenklich. Aufephemeralself-hosted (frisch je Lauf, keinactions/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
cancelled ≠ failure) 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):
| Audit | Frage | Datei-Muster | Erstausgabe |
|---|---|---|---|
| App-Audit | Ist die App ein Meisterwerk? (UX/Prozess, True North, G-3) | UX-Prozess-Review-<JJJJ-MM>.md | 2026-07 (v0.62.0) |
| Doku-Audit | Ist die Doku ein Meisterwerk? (pyramidal · zielgruppen-gerecht · visuell · konsistent) | Doku-Review-<JJJJ-MM>.md | 2026-07 (v0.65.0) |
Verbindliche Regeln:
- 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. - 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. - Stale-Regel: Liegt der Bezugspunkt des jüngsten Audits ≥10 Minor-Versionen hinter
APP_VERSIONoder 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 warntscripts/check-doc-consistency.sh(warnt, blockt nicht). - Folge-Arbeit als OPs: Audit-Befunde werden nicht im Audit "abgearbeitet", sondern als
MED-OP-…-Punkte inHANDOFF.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/ghfü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 überpull_request_readprüfen, nicht erraten. Lokalesgitbleibt für lokale Arbeit ok (Branch, Merge/Rebase, Reads). - Neuer Code (KI) → immer zuerst einen neuen Branch anlegen und nur dort arbeiten. Merge nach
mainnur via PR (mit grüner CI). Niemals Code direkt aufmain. - 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-Protectionmain):CI Gateund der CodeRabbit-Commit-StatusCodeRabbit(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, wennmaininzwischen weitergezogen ist (behindblockt 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.yamlauto_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 frischenCodeRabbit-Status → der Required-Check auf dem neuen Head bleibt offen und Auto-Merge wartet, bis manuell@coderabbitai reviewgepostet 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 reviewposten, 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 keineignore_usernames-Ausnahme, MED-D-60): ein ausgenommener Bot-PR bekäme nie denCodeRabbit-Status und bliebe als Required Check dauerhaft am Gate hängen.
- Config (MED-D-100):
- "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
mainaktuell halten: zu Beginn und in Abständengit 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, wennmainKonflikte bringt oder ein konkretes Risiko es rechtfertigt (z. B. Änderung an derselben Datei/Logik). Kein Update allein deshalb, weil der PRbehindist. - 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 (
main←feature-basis←feature-child, Child-PR-Base =feature-basis). Regeln: (a) bottom-up mergen — erstfeature-basis→main; GitHub retargetet offene Child-PRs dann automatisch aufmain(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 aufmain≠ 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.mdunddocs/betrieb/Timesheet.mdmit (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/mainzum Lesen) undgit push -u origin <branch>dann die stale Branch-Referenz hochschob statt des neuen Commits. Verbindliche Disziplin:- Vor jeder Änderung
git checkout -B <branch> origin/main— HEAD ist dann immer ein echter Branch. Zum reinen Lesen vonmainnicht auschecken, sonderngit show origin/main:<pfad>. - Nach jedem Push verifizieren:
git rev-parse HEAD==git rev-parse origin/<branch>. Weicht es ab → nicht mergen, Ursache klären. - 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.
- Nach dem Merge den Deploy verifizieren: Worker-
modified_onmuss nach der Merge-Zeit liegen (Cloudflareworkers_list) bzw. der App-deploy_statusden neuen Commit zeigen — fängt „gemergt, aber nicht live" ab. Guardrail (eingecheckt):.githooks/pre-pushbricht einen Push aus detached HEAD (bzw. mit Spitze ≠ HEAD) ab; aktiviert viagit config core.hooksPath .githooks(inscripts/session-start-hook.shje Session automatisch gesetzt).
- Vor jeder Änderung
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 (AskUserQuestionoder 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).