Brainversum · tuxametrics Graph Admin

konzept vertraulich owner: matus

Demo-Daten-Tooling bündeln — Vergleich mit eimr/evenews/evepop/DOT

Demo-Daten-Tooling bündeln — Vergleich mit eimr/evenews/evepop/DOT

Status: umgesetzt in drei Iterationen (alle 2026-08-15) · Adressat: Product Owner · Art: Iterationen 1–2 UI/Navigation; Iteration 3 zusätzlich Backend (zwei neue Demo-Bundles) — keine neue Fachzahl, keine berührte Leitplanke

Lesehinweis: Die Abschnitte bis „Warum Test-/Demo-Elemente überhaupt auf Fachseiten landeten" beschreiben die erste Iteration (Demo-Tooling raus aus den Fachseiten, rein in eine eigene Sektion). Sie ließ Laden und Löschen auf einer Seite. Der Abschnitt „Zweite Iteration" korrigiert das und enthält die tiefere, im Code nachgeprüfte Vergleichsanalyse (inklusive der präzisierten DOT-Antwort). Die „Dritte Iteration" macht aus dem einen Referenzfall drei und benennt dabei eine gefundene, bewusst nicht behobene Lücke im Auswertungslauf. Bei Widersprüchen gilt der spätere Abschnitt — insbesondere ist die in Iteration 2 begründete Wortwahl „Referenzfall laden" statt „Demo-Vorlagen" seit Iteration 3 überholt.

Anlass war eine Nutzerbeobachtung im Screenshot-Vergleich: das Demo-Daten-Tooling und der Testfallkatalog sahen in tuxametrics „nicht annähernd so gut aus" wie in den Schwesterprodukten. Auftrag war zunächst nur Analyse, dann („SETZE ES UM") die Umsetzung der Schritte 1–3 unten. Dieses Dokument hält fest, was die Schwesterprodukte tatsächlich haben, was tuxametrics vorher hatte, was übernommen wurde — und was ausdrücklich nicht.

Dieses Thema berührt keine der fünf Leitplanken aus CLAUDE.md. GM-7 ist hier irrelevant: Demodaten laden und löschen ist keine klinische Entscheidung und kein Schritt der Freigabekette. txm.demo.cleanup ist zwar NUR_MENSCHEN (tuxametrics-laborauswertung-service/src/main/java/io/dl/tuxametrics/laborauswertung/service/capability/CapabilityRegistrar.java, Z. 151–155) — aber laut eigener Begründung dort nicht aus GM-7-Gründen, sondern wegen der Tragweite eines mandantenweiten Datenverlusts.


Zwei korrigierte Prämissen

Beide Korrekturen betreffen die Ausgangsannahme, nicht die Sache. Sie stehen hier, weil sonst das falsche Repo als Vorbild herangezogen wird.

Annahme Befund
„DOT hat eine Demo-Sektion" Nein. C:\dev\dot\dot\dot-platform-ui hat kein domains/demo, keinen Sidebar-Eintrag „Demo" und keinen Testfallkatalog im Frontend. Was es gibt, ist eine Datenbereinigung unter Administration: domains/administration/sidebar.ts Z. 21 (administration/data-cleanup) und domains/administration/pages/DataCleanupPage.tsxPageHeader, Type-to-confirm, zwei capability-gegatete Aktionen. Der Rest des DOT-Demo-Tooling ist skript-/dokumentationsbasiert (DOT/DEMO_DATA.md, scripts/reset-odc-demo.mjs u. a., per node-CLI). DOT ist also kein Vorbild für Bündelung, aber ein Beleg dafür, dass eine eigene Cleanup-Seite produktübergreifend Standard ist.
„Testmanagement wie bei evepop" evepop hat die dünnste Lösung der drei. evepop-platform-ui/src/domains/testing/ enthält nur api/, hooks/, model/, index.tskeine Seiten; es wird inline als Widget in domains/process-hub/pages/ProcessDefinitionDetailPage.tsx benutzt. Der frühere Cleanup-Eintrag ist laut Kommentar in domains/administration/sidebar.ts Z. 7–9 am 2026-08-13 nach eimr-ui gewandert. evepop steht damit für die Zwirn-Testmanagement-Basis, nicht für ein Frontend-Vorbild. Das deckt sich mit der bereits im Repo stehenden Selbstkorrektur in testmanagement-integration.md („Korrektur 2026-08-14").

Das echte Vorbild ist eimr, sekundär evenews.


Was eimr und evenews tatsächlich haben

eimr (eimr-ui/src/domains/demo) evenews (evenews-ui/src/domains/demo)
Sidebar-Sektion „Demo", Icon FlaskConical, basePath: demo-tools (sidebar.ts) „Demo", Icon Wand2, basePath: blueprints (sidebar.ts)
Section-weites Capability-Gate nein — je Item eines nein — je Item eines
Items Testgruppen · Demo-Vorlagen (Mocks) · Testdaten zurücksetzen Demo-Vorlagen (Blueprints) · Mocked Services · Cleanup
URL-Präfix demo-tools/ (nicht demo/ — Test-Tenant heißt „demo", ADR-0053) keins — Items liegen direkt auf Tenant-Ebene (ADR-0055, routes.tsx Kopfkommentar). Die Sektion ist ein reines UI-Gruppierungskonzept.
Testkatalog-Tiefe 6 Routen, fünfstufig bis …/test-cases/:key/processes (routes.tsx) keiner
Cleanup CleanupPage.tsx: drei Services sequentiell, Schrittliste mit pending/running/done/error, Type-to-confirm auf Tenant-Key CleanupPage.tsx: ein Service, deshalb ausdrücklich keine Schrittliste (Kopfkommentar Z. 12–15), sonst identischer Aufbau
Mocks Tabelle + „Alle Mocks starten" (Bulk-Run mit Polling, MocksListPage.tsx) nach Typ gruppiertes Grid, Einzel-/Gruppen-/Alle-Trigger, sechs Typen über eine parametrisierte Seite (BlueprintTypeListPage.tsx, ADR-0054)
i18n src/i18n/locales/demo/{de,en}.json, 29 Zeilen (nur Cleanup — der Rest ist hartcodiertes Deutsch) dieselben Dateien, 166 Zeilen (Cleanup + Blueprints vollständig)
Kein-Zugriff-Verhalten TestGroupsPage.tsx/CleanupPage.tsx rendern statt der Seite einen „Keine Berechtigung"-Block dito

Gemeinsamer Nenner beider, und das ist der eigentliche Kern der Nutzerbeobachtung:

  1. eine Sidebar-Sektion, die Testkatalog + Demo-Vorlagen + Cleanup bündelt,
  2. Cleanup als eigene Seite mit eigener Route, nicht als Beiwerk einer Fachseite,
  3. jede Seite mit PageHeader (Breadcrumbs, Icon, Titel, Untertitel, Aktionsleiste rechts).

Ist-Zustand tuxametrics

Punkt Fundstelle Bewertung
Keine „Demo"-Sektion tuxametrics-ui/src/nav/navConfig.ts „Testfälle" ist eine eigene Sektion mit einem Item („Übersicht", Z. 100–104) in der unteren Gruppe „Technische Daten". Eine Sektion mit einem Kind ist die teuerste Form, einen einzelnen Link zu zeigen.
Kein requiredCapability in der Nav navConfig.ts Z. 24–29 Bewusste Produktentscheidung, ausformuliert im Datei-Javadoc: eine Sidebar, die Punkte je nach Rechten verschwinden lässt, verbirgt, dass es den Bereich gibt. Seit ADR-0007 existiert /me/capabilities — die Auslassung ist seitdem Entscheidung, nicht Lücke. Jede Empfehlung hier respektiert das.
Demodaten als Inline-Panel src/shell/DemoDatenPanel.tsx, eingebunden in routes/PatientUebersichtRoute.tsx und routes/AuswertungUebersichtRoute.tsx Keine eigene Route, keine Breadcrumbs, keine adressierbare Seite. Die unwiderrufliche Löschaktion sitzt damit auf zwei fachlichen Alltagsseiten.
Cleanup-Dialog src/shell/DemoDatenLoeschenDialog.tsx Type-to-confirm ist vorhanden und gut. Ein einziger Backend-Call (auswertungApi.loescheDemoDatenDemoCleanupResource). Das Ergebnis trägt zehn Zähler (DemoCleanupErgebnis), angezeigt werden zwei (Patienten, Auswertungen, Z. 106–107).
Nur ein Fachservice betroffen DemoCleanupResource Anders als eimrs drei Services (Finance/Process/TestRuns) — architektonisch bedingt, kein Rückstand. evenews steht vor genau derselben Lage und hat daraus dieselbe Konsequenz gezogen.
Genau 1 von 63 Mock-Szenarien src/shell/TestfallAusfuehren.tsx Z. 9–19 (MOCK_SZENARIEN) Dokumentiert und gewollt in testmanagement-integration.md („Was danach noch offen ist"). Prinzip im Javadoc: keine erfundene Vollständigkeit.
Testfälle-Slice src/domains/testfaelle/pages/{TestGruppenUebersichtPage,TestGruppeDetailPage,TestfallDetailPage}.tsx, components/{GoldPathDiagramm,TestCaseTable,TestfallStatusBadge}.tsx Card-Grid + Zähler + GoldPathDiagramm sind seit Commit 07bbc25 da („nach eimr-Vorbild"). Der Katalogteil ist nicht weit zurück; was fehlt, ist die Bündelung und die Seitenchrome.
Kein PageHeader Grep in tuxametrics-ui/src: 0 Treffer Siehe nächster Abschnitt — das ist kein fehlender Baustein.
useCapabilities src/domains/autoimprove/features/report/components/AutoImproveReportModal.tsx Z. 6, aus @zwirn/web Bereits einmal im Produkt in Gebrauch. Der Hook ist also weder neu noch ungetestet.

PageHeader und useCapabilities sind keine neue Abhängigkeit

Beide liegen in @zwirn/web, das dieses Produkt bereits als file:-Dependency zieht: tuxametrics-ui/node_modules/@zwirn/web/src/index.ts Z. 10 (useCapabilities), Z. 51–52 (PageHeader, Crumb). eimrs src/components/layout/PageHeader.tsx ist ein zweizeiliger Re-Export desselben Pakets, keine Eigenentwicklung. Für tuxametrics wäre es ein Import, kein Nachbau.

Zwei Dinge sind dabei sauber auseinanderzuhalten:

Konkrete Falle bei PageHeader: die Komponente bringt eigenes px-6 pt-5 mit und setzt voraus, dass sie oberstes Element in einem ungepolsterten main ist. shell/AppLayout.tsx erfüllt das (<main className="flex-1 min-w-0 overflow-auto">), aber jede heutige Seite bringt ihr eigenes p-4 mit (z. B. TestGruppenUebersichtPage.tsx Z. 65). Wer PageHeader einsetzt, muss das äußere Padding der Seite entfernen, sonst entsteht doppelter Rand.


Empfehlung: was übernehmen, was nicht

Übernehmen

Vorschlag Begründung
Eine Sidebar-Sektion „Demo", die „Demodaten" und „Testfälle" bündelt; die Einzel-Sektion „Testfälle" entfällt Genau der Kern der Nutzerbeobachtung. Beseitigt zugleich die Ein-Kind-Sektion. Bleibt in der Gruppe „Technische Daten" — Demo-Tooling ist kein Gold-Path-Schritt.
Cleanup + Referenzfall-Laden als eigene Route/Seite Der Punkt, an dem eimr/evenews/DOT alle drei übereinstimmen. Eine unwiderrufliche mandantenweite Löschung gehört nicht auf die Patientenliste.
Alle zehn Zähler im Löschergebnis zeigen DemoCleanupErgebnis liefert sie bereits; heute werden zwei angezeigt. Auf einer eigenen Seite ist Platz für eine kleine Ergebnistabelle. Kein Backend-Eingriff. Damit ist die Ergebnisdarstellung sogar detaillierter als eimrs.
PageHeader auf den Seiten der neuen Sektion (Demodaten + die drei Testfälle-Seiten) Der sichtbarste Teil des optischen Abstands. Import statt Nachbau.
Kein URL-Präfix demo/ — die Sektion bleibt reines UI-Gruppierungskonzept Genau evenews' Schluss (ADR-0055). Für tuxametrics kommt ein zweiter Grund dazu: testfaelle liegt bereits unter :tenantKey/testfaelle, und die Route umzuhängen bräche bestehende Links ohne Gegenwert.

Nicht übernehmen

Vorschlag Warum nicht
Mocks-/Blueprint-Übersicht als Grid Es gibt ein ausgearbeitetes Szenario (MOCK_SZENARIEN, TC-AUS-013). Ein Grid oder eine Vorlagen-Liste über einen Eintrag suggeriert eine Verwaltungsfläche, die nichts zu verwalten hat — genau die „erfundene Vollständigkeit", die TestfallAusfuehren.tsx Z. 13–14 ausdrücklich ablehnt. Auch eine editierbare Mock-Verwaltung wie evenews scheidet aus: dahinter steht dort ein Service mit CRUD; tuxametrics hat POST /demo/referenzfall, sonst nichts.
Mehrstufige Cleanup-Schrittliste (eimr) Ein Backend-Call. Eine Fortschrittsliste mit einem Schritt ist Theater. evenews hat für dieselbe Lage dieselbe Entscheidung getroffen und sie im Kopfkommentar seiner CleanupPage.tsx begründet — inklusive des Rückwegs, falls ein zweiter Service dazukommt.
Section-weites requiredCapability Widerspricht navConfig.ts Z. 24–29 frontal.
„Keine Berechtigung"-Seite statt Inhalt Dito — Verstecken statt Erklären.
i18n-Namespace demo/{de,en}.json tuxametrics ist einsprachig Deutsch, NavItem hat kein labelKey (navConfig.ts Z. 23). Ein Namespace für eine Sprache wäre Aufwand ohne Nutzen.
Katalog-Admin-UI (Gruppen/Fälle anlegen, status pflegen) Steht bereits als offener Punkt in testmanagement-integration.md und ist ein eigenes Thema, nicht Teil dieser Bündelung.
Neue Capabilities Keine nötig. txm.demo.load und txm.demo.cleanup existieren, sind im Katalog registriert (laborauswertung-service/.../capability/CapabilityRegistrar.java Z. 148–155) und im Demo-Grantsatz enthalten (tuxametrics-platform-service/.../boot/CapabilityRegistrar.java Z. 77–78, Schalter TXM_DEMO_GRANTS). Die Katalog-Lese-Rechte des Testmanagement-Service ebenso.

Umsetzungsschritte

Sequenziert, jeder Schritt für sich lauffähig und einzeln abbrechbar. Nach jedem Schritt: cd tuxametrics-ui && npm run typecheck. Kein Backend-Eingriff in keinem Schritt.

Schritt 1 — Nav bündeln (kleinster sichtbarer Gewinn, keine neue Route)

Schritt 2 — Demodaten-Seite

Schritt 3 — Fachseiten entlasten

Schritt 4 — PageHeader auf den vier Seiten der Sektion

Schritt 5 — optional: Löschaktion capability-bewusst

Schritt 6 — Dokumentation


Braucht das ein ADR?

Vorschlag: nein. eimr und evenews haben für dasselbe Thema drei ADRs geschrieben (0053/0054/0055), aber deren Inhalt war überwiegend das Auflösen einer URL-Namenskollision mit ihrem Test-Tenant „demo" — ein Problem, das tuxametrics nicht hat (Mandanten heißen praxis01/praxis02, navConfig.ts Z. 148–151) und das die Empfehlung oben ohnehin umgeht, indem sie keine Routen umhängt. Keine der fünf Leitplanken ist berührt, kein Enum, kein Datenmodell, keine Fachzahl. Dieses Backlog-Dokument ist der Nachweis. Ausnahme: sollte Schritt 5 zu einem produktweiten Capability-Gating ausgebaut werden, wäre das eine Revision der Entscheidung in navConfig.ts und bräuchte dann ein ADR.


Umgesetzt am 2026-08-15

Schritte 1–3 aus dem Plan oben, in einem Zug statt einzeln geprüft (Nutzerauftrag „SETZE ES UM"):

Warum Test-/Demo-Elemente ueberhaupt auf Fachseiten landeten — und warum das falsch ist

Nutzerauftrag: eine Begründung, warum es so weit kam, nicht nur die Korrektur selbst.

Wie es entstand — vier Ursachen, keine davon böswillig:

  1. Reihenfolge des Bootstrappings. ReferenzfallLadenButton (und später der Lösch-Dialog) lösten ein akutes lokales Problem: eine leere Datenbank auf genau der Seite, die das am sichtbarsten zeigte (Patienten-/Auswertungsliste). Der Knopf landete dort, wo der Schmerzpunkt war — nicht dort, wo er strukturell hingehört.
  2. Es gab noch keine passende Nav-Heimat. Bis 2026-08-13 hatte tuxametrics-ui IconRail + Untermenü, keine feste „Werkzeug"-Sektion. Als die einheitliche Sidebar kam (Muster aus eimr/evenews, navConfig.ts Kommentar), zog nur der Testfallkatalog in einen eigenen Menüpunkt um — das Lösch-/Lade-Paar blieb aus Trägheit, wo es immer war.
  3. Die Paarungs-Begründung verdeckte die Platzierungsfrage. Das alte DemoDatenPanel.tsx hatte ein berechtigtes Argument: Laden und Löschen gehören zusammen. Das ist wahr — beantwortet aber nicht, ob die Seite, auf der beide zusammen saßen, die richtige war. Die Paarung wurde lokal gelöst (eine Komponente für beide Aktionen), ohne die Platzierung separat zu prüfen.
  4. Zwei Knöpfe fühlten sich zu klein für eine eigene Seite an. Dieses Repo vermeidet erfundene Struktur (CLAUDE.md-Grundhaltung überall). Eine eigene Route für „zwei Buttons" wirkt wie Überbau — bis eine zweite Größe ins Spiel kommt: der Vergleich mit Produkten, die dasselbe Problem bei größerem Funktionsumfang (drei Services, sechs Mock-Typen bei eimr/evenews) schon gelöst haben. Der Rückstand wurde erst beim Nebeneinanderstellen sichtbar, nicht durch eigenes Wachstum.

Warum es mehr als unordentlich ist — die eigentliche Analyse:

Zweite Iteration (2026-08-15, später am Tag): die Bündelung eine Ebene tiefer auflösen

Der erste Wurf hat das Demo-Tooling aus den Fachseiten geholt und in eine Sektion „Demo" gelegt — aber innerhalb dieser Sektion blieb genau die Bündelung stehen, die weiter oben als Problem benannt ist: eine Seite (routes/DemodatenRoute.tsx), auf der Laden und Löschen zusammensitzen. Der Nutzer hat das beanstandet und eine zweite, tiefere Vergleichsrunde verlangt. Ergebnis unten; die Umsetzung ist Teil derselben Sitzung.

Was die Nachprüfung im Code ergeben hat

Alle drei Repos wurden dieses Mal Datei für Datei gelesen, nicht aus der Zusammenfassung oben übernommen.

Die zentrale Behauptung ist bestätigt. In eimr und evenews sind „Vorlagen laden/triggern" und „Testdaten löschen" getrennte Sidebar-Items, getrennte Routen, getrennte Page-Komponenten. Geteilt wird ausschließlich die Sidebar-Sektion — ein reines UI-Gruppierungskonzept.

eimr (eimr-ui/src/domains/demo) evenews (evenews-ui/src/domains/demo)
Items (Reihenfolge!) Testgruppen · Demo-Vorlagen · Testdaten zurücksetzen (sidebar.ts Z. 15–17) Demo-Vorlagen · Mocked Services · Demodaten zurücksetzen (sidebar.ts Z. 33–37)
Routen demo-tools/mocks (Z. 20) und demo-tools/cleanup (Z. 22) — zwei Einträge, zwei Elemente :tenantKey/blueprints (Z. 17) und :tenantKey/cleanup (Z. 16) — beide top-level, kein Präfix
Vorlagen-Seite MocksListPage.tsx, 179 Z.: Tabelle, „Alle Mocks starten" (Bulk mit Polling), „Neuer Mock" BlueprintsOverviewPage.tsx, 323 Z.: nach Typ gruppierte Tabellen, Einzel-/Gruppen-/Auswahl-/Alle-Trigger, CRUD
Cleanup-Seite CleanupPage.tsx, 187 Z.: drei Services als Schrittliste, Type-to-confirm CleanupPage.tsx, 138 Z.: ein Service, Zähler statt Schrittliste, Type-to-confirm
Berührung der beiden keine — CleanupPage.tsx Z. 29 nennt die Mock-Vorlagen ausdrücklich als das, was nicht angefasst wird keine — die Blueprints-Seite verweist textlich auf „Demodaten zurücksetzen" als anderen Ort

Zwei Ordnungs-Invarianten, die beide teilen und die dieses Repo übernimmt:

  1. Die unwiderrufliche Aktion steht am Ende der Sektion, nicht zwischen den harmlosen.
  2. Der Katalog zum Nachlesen steht vor den Aktionen (eimr: Testgruppen zuerst).

Terminologie, wörtlich (aus i18n/locales/common/de.json, eimr Z. 52–57 / evenews Z. 41–46): sichtbares Label für die Vorlagen ist in beiden „Demo-Vorlagen"; für das Löschen sagt eimr „Testdaten zurücksetzen", evenews „Demodaten zurücksetzen". Das Wort Cleanup erscheint in keinem der beiden als UI-Text — nur in Code-Bezeichnern, Capability-Schlüsseln, i18n-Keys und im URL-Segment.

DOT — die präzisierte Antwort

Die Frage war ausdrücklich, ob DOT „inzwischen doch" eine Demo-Vorlagen-UI hat, und zwar auch außerhalb von dot-platform-ui. Nachgeprüft wurde das ganze Repo, nicht nur dieses Modul.

Die Antwort auf die Nutzerfrage, so genau wie sie geht: DOT hat das Demo-Tools-Muster nur zur Hälfte — die Lösch-Hälfte, und die nicht unter „Demo", sondern unter „Administration". Eine Demo-Vorlagen-UI hat DOT nicht und hatte sie nie; sein Lade-Werkzeug ist ein Node-Skript. „Sowohl DOT als auch evenews haben das Muster" trifft also für evenews (und eimr) vollständig zu, für DOT nur im Cleanup-Teil. Das ändert an der Schlussfolgerung nichts, sondern verstärkt sie: alle drei Produkte geben dem Löschen eine eigene Seite, und keines der drei setzt Löschen und Laden auf dieselbe Seite — DOT schon deshalb nicht, weil es die Lade-Seite gar nicht gibt.

Was daraus umgesetzt wurde

Zwei bewusste Abweichungen von der Vorlage

Vorlage Hier Warum
Label „Demo-Vorlagen" „Referenzfall laden" Der Plural ist dort gedeckt: eimr hat eine Tabelle mit „Neuer Mock", evenews sechs Blueprint-Typen mit CRUD. tuxametrics hat ein Szenario hinter einem POST /demo/referenzfall. Ein Menüpunkt „Demo-Vorlagen" verspräche eine Verwaltungsfläche, die es nicht gibt — dieselbe erfundene Vollständigkeit, die der Abschnitt „Nicht übernehmen" für das Grid schon ablehnt, nur im Menütext statt im Layout. „Referenzfall" ist zudem das Wort, das dieses Produkt ohnehin führt: ReferenzfallResource, init-bundle, und der Knopf selbst heißt seit jeher „Synthetischen Referenzfall laden".
Label „… zurücksetzen" „Demodaten löschen" Es wird nichts auf einen Ausgangsstand gesetzt, es wird der Fachdatenbestand geleert — ohne Sicherung, ohne Wiederherstellung. „Zurücksetzen" wäre die harmlosere Vokabel für die härtere Tat. Der Panel-Text sagt schon heute „Endgültig löschen"; das Menü sagt jetzt dasselbe.

Unverändert übernommen bleibt dagegen kein URL-Präfix demo/ (evenews-ADR-0055) — die Sektion ist auch hier ein reines UI-Gruppierungskonzept, und testfaelle liegt ohnehin schon flach auf Tenant-Ebene.

Warum die erste Runde diesen Punkt verfehlt hat

Der Vergleich oben hat die Schwesterprodukte richtig beschrieben — die Zeile „Items" in der Tabelle nennt die drei getrennten Punkte beider Produkte korrekt. Übersetzt wurde daraus aber nur die Sektion, nicht die Auftrennung darin: der Umsetzungsplan (Schritt 2) schrieb „Demodaten-Seite" im Singular und niemand hat die Zeile gegen die eigene Belegtabelle gehalten. Ursache ist dieselbe wie Punkt 4 in „Warum Test-/Demo-Elemente überhaupt auf Fachseiten landeten": zwei Knöpfe fühlen sich zu klein für zwei Seiten an. Das Argument ist auch hier falsch, und zwar aus demselben Grund — die Seitenzahl bemisst sich nicht am Platzbedarf, sondern daran, ob zwei Handlungen dieselbe Absicht haben. „Vorführdaten anlegen" und „Mandant unwiderruflich leerräumen" haben das nicht.

Dritte Iteration (2026-08-15, abends): aus „Referenzfall laden" werden „Demo-Vorlagen" — mit echten Vorlagen

Die zweite Iteration hat die Sektion richtig aufgeteilt, aber am Vorlagen-Punkt eine Abweichung festgehalten und ausführlich begründet: Label „Referenzfall laden" statt eimrs/evenews' „Demo-Vorlagen", weil tuxametrics „genau ein Szenario hinter genau einem POST /demo/referenzfall" habe und ein Plural-Menüpunkt eine Verwaltungsfläche verspräche, die es nicht gibt. Diese Begründung war richtig und ist jetzt gegenstandslos — nicht weil sie umgangen wurde, sondern weil die Voraussetzung entfallen ist: es gibt seit dieser Iteration drei ausgearbeitete Szenarien.

Nutzerauftrag war ausdrücklich beides: (a) wirklich mehr ladbare Szenarien, nicht nur strukturelle Vorbereitung, und (b) eine Seite, die auf mehrere ausgelegt ist. Ausdrücklich nicht gewählt wurde eine reine „was liegt an Demodaten herum"-Ansicht.

Der heikle Teil: welche Konstellationen — und warum nicht einfach zwei weitere

Das ist die Stelle, an der dieses Thema die Kernregel des Repos berührt (CLAUDE.md: „Wo das Material keine Zahl hat, hat der Code auch keine"). FACH-109 benennt 13 Konstellationen, von denen bis heute eine ausgearbeitet war; die übrigen zwölf sind „benannt, aber nicht ausgearbeitet — keine Eingangswerte, keine erwarteten und keine ausdrücklich nicht erwarteten Ergebnisse" (OF-41 / E-18, blockierend, in v1.2 unverändert offen).

Recherchebefund, der die Auswahl entschieden hat: Die Annahme „zu den anderen zwölf gibt es gar nichts" stimmt so nicht. tuxamed Bearbeitet/testfaelle/ überführt alle 13 Konstellationen in benannte Testfälle (00-uebersicht.md Z. 76–89), und für zwei davon steht dort eine ausgearbeitete Positiv- und eine ausdrückliche Negativerwartung: TC-AUS-008 und TC-AUS-009 in 04-fachliche-auswertung.md tragen je ein pruefung- und ein darfNichtEntstehen-Feld. Genau das ist das Akzeptanzkriterium aus FACH-109 („Ein Referenzfall ohne Negativerwartung prüft nur die Funktion, nicht die Sicherheit"). Was dort weiterhin fehlt, sind Zahlen — und die müssen auch nicht von dort kommen (siehe unten).

Gewählt wurden deshalb Konstellation 4 und 5: derselbe kritische Kaliumwert, einmal mit und einmal ohne Hämolysehinweis.

Kriterium Warum 4 und 5
Am wenigsten erfunden Die einzigen zwei der verbleibenden zwölf mit ausformulierter Negativerwartung im Material.
Anderes strukturelles Verhalten als Konstellation 2 Konstellation 4 erzeugt ein Finding ohne Ebene (PLAUSIBILITAETS_ODER_PRAEANALYTIKHINWEIS, ebene() == null, FACH-046 Z. 1085) — den einzigen solchen Zustand im Produkt. Konstellation 5 erzeugt R3 + sicherheitsstatus: kritischer-befund-offen. Konstellation 2 erreicht keinen von beiden.
Sie sind ein Paar Die beiden Bundles unterscheiden sich in einem Feld: praeanalytik.haemolysehinweis. Einzeln geladen zeigt keiner von beiden die Regel; erst der Vergleich zeigt, was FACH-045 Z. 1057 meint („der kritische Wert wird vor Auslösung des Hinweises gegen Präanalytik geprüft"). Das ist der Grund, warum das Kontingent „maximal zwei" hier auf ein Thema statt auf zwei ging.
Bisher totes Codestück Der Zweig kaliumHochUndHaemolytisch in AuswertungslaufService war von keinem Demodatensatz je erreichbar.

Keine neue Fachzahl — die Bauregel im Klartext:

Herkunft
Patient, Messwert (6,4 mmol/l), Referenzbereich ([3,5; 5,1]), Kreatinin erfunden, wie in Konstellation 2 (OF-45: es gibt kein Echtmaterial)
Die Schwelle, gegen die sie laufen (Kalium kritisch > 6,0 mmol/l) belegt: Regelkatalog.KRITISCHE_SCHWELLEN, FACH-045 Z. 1140, entschieden in v1.2 (E-8)

Die Platzhalterzahlen sind zusätzlich wörtlich aus dem bestehenden Test SicherheitUndScopeGateTest#kaliumMitHaemolyse_erzeugtProbenhinweis übernommen statt neu erfunden — dieselbe Konstellation hat im Repo damit genau eine Zahlenfassung.

Was ausdrücklich nicht gebaut wurde und nie gebaut wird: Konstellation 12 („Auffälliges Verhältnismuster ohne Einzelwertauffälligkeit") ist laut FACH-109 eine E2-Konstellation. Sie zu bauen hieße, Leitplanke 3 zu brechen. Sie ist damit die einzige der 13, die dieses Repo dauerhaft nicht abdecken kann — das steht jetzt im Javadoc von ReferenzfallService, in init-bundle/README.md und auf der Seite selbst, damit „3 von 13" nicht als bloßer Rückstand gelesen wird.

Ein Befund, der nebenbei entstand — und bewusst NICHT gefixt wurde

TC-AUS-008 verlangt neben „kein Eskalationshinweis" auch „keine Kaliumaussage". Der Auswertungslauf erzeugt bei Hämolyse zwar korrekt den Probenhinweis statt des kritischen Befunds, legt für Kalium aber trotzdem ein E3-Finding einzelwertauffaelligkeit an — erzeugeE3Findings() kennt den Präanalytikhinweis nicht. Das Javadoc von Praeanalytik.java behauptet im selben Repo bereits das Gegenteil („Interpretation und jede Kaliumaussage werden zurückgehalten").

Das ist eine bestehende Lücke des Auswertungslaufs, keine Eigenschaft der neuen Bundles — sie war nur nie sichtbar, weil kein Demodatensatz diesen Pfad je erreichte; auch der vorhandene Test prüft ausschließlich die E1-Seite. Sie zu schließen wäre eine Änderung am fachlichen Verhalten und braucht eine eigene Entscheidung, keinen Commit nebenbei. Bis dahin steht sie als erwartung.abweichung in praxis01-referenzfall-04.json. Der Referenzfall macht die Lücke sichtbar — das ist mehr wert als ein Bundle, das sie umgeht.

Was umgesetzt wurde

Backend (tuxametrics-laborauswertung-service) — erstmals in dieser Themenreihe ein Backend-Eingriff; die ersten beiden Iterationen kamen ohne aus:

Frontend (tuxametrics-ui):

Was an der Haltung dieses Dokuments unverändert gilt

Was offen bleibt

Punkt Warum
62 60 von 63 Testfällen ohne Mock-Szenario Geändert in der dritten Iteration: TC-AUS-008 und TC-AUS-009 haben seit 2026-08-15 eigene Szenarien. Die verbleibenden 60 sind unverändert fachlicher Ausarbeitungsaufwand (init-bundle-Datensätze je Fall), kein Verdrahtungsproblem — siehe testmanagement-integration.md.
10 von 13 Referenzfall-Konstellationen ohne Bundle Neu benannt in der dritten Iteration. Neun davon sind baubar und warten nur auf Arbeit; die zehnte (Konstellation 12, auffälliges Verhältnismuster) ist eine E2-Konstellation und wird in diesem Repo nie entstehen (Leitplanke 3, OF-01/E-7). Wer die Zahl „3 von 13" als reinen Rückstand liest, liest sie falsch.
erzeugeE3Findings() kennt den Präanalytikhinweis nicht Neu gefunden in der dritten Iteration und bewusst nicht behoben: Änderung am fachlichen Verhalten, braucht eine eigene Entscheidung. Ausführlich oben unter „Ein Befund, der nebenbei entstand".
Katalog seit v1.1, nicht auf v1.2 nachgezogen Unverändert, siehe testabdeckung-gold-path.md.
PageHeader nur auf vier Seiten Bewusst begrenzt, siehe Schritt 4. Produktweiter Rollout = eigenes Thema.
Nicht verifiziert Der visuelle Endzustand. Diese Analyse ist ausschließlich Code-Lektüre — es wurde nichts gestartet und nichts verglichen als laufende Oberfläche. Ob die Bündelung im Betrieb tatsächlich besser wirkt, zeigt erst ein Deploy.

Unangetastet: TUXAMETRICS_REGULATORIK_EINSTUFUNG und TUXAMETRICS_PILOT_BETRIEBSMODUS bleiben UNGEKLAERT, RegulatorikGuard ist nicht berührt. Kein neuer Capability-Schlüssel, keine neue Fachzahl, kein neuer Enum-Wert, kein Backend-Eingriff in irgendeinem der sechs Schritte.

Präzisierung nach der dritten Iteration (2026-08-15): Der letzte Halbsatz gilt nur noch für die Iterationen 1 und 2. Die dritte hat sehr wohl ins Backend eingegriffen (zwei Bundles, Szenario-Enum, zwei Endpunkte). Alles andere bleibt wörtlich richtig, und das ist hier der Punkt: kein neuer Capability-Schlüssel (CapabilityRegistrar ist im Diff nicht enthalten — Nebenbefund: er meldet inzwischen 19 statt der in CLAUDE.md genannten 18, eine Abweichung aus dem Process-Hub-Wiederanschluss desselben Tages, nicht aus dieser Session), keine neue Fachzahl (die einzige beteiligte Schwelle stand schon im Regelkatalog), kein neuer Enum-Wert im Domänenmodell, keine E2, kein RegulatorikGuard. Der einzige neue Enum ist ReferenzfallService.Szenario — eine Liste von drei Dateipfaden, kein fachliches Konzept.


Vierte Iteration (2026-08-16): aus dem Karten-Grid wird eine Tabelle mit Detailseite

Dieser Abschnitt steht bewusst nach „Was offen bleibt" und ist der jüngste — es gilt weiterhin der Lesehinweis am Dateikopf: bei Widersprüchen gilt der spätere Abschnitt.

Nutzervorgabe, sinngemäß: in eimr wie in DOT sind das normale Tabellen mit Detailseite; baue es hier auch so — was, wenn morgen zwanzig weitere Samples dazukommen? Das Argument entscheidet die Sache, und zwar unabhängig davon, wie die drei heutigen Karten aussehen: ein Grid trägt drei Einträge gut und zwanzig gar nicht. Jede Karte wiederholt dieselben vier Beschriftungen („Konstellation:", „Testfall:", „Starten"), und zwei Fälle lassen sich nur vergleichen, wenn ihre Konstellation untereinander in einer Spalte steht — was bei den Konstellationen 4 und 5 genau der Zweck ist.

Was die Nachprüfung in eimr und DOT ergeben hat

eimr DOT
Fundstelle eimr-ui/src/domains/demo/pages/MocksListPage.tsxMockDetailPage.tsx u. a. dot-platform-ui/src/domains/finance/pages/CustomersPage.tsxCustomerDetailPage.tsx, domains/xrm/.../OrganizationTable.tsx, domains/project-economy/.../ProjectTable.tsx
Struktur div.rounded-xl border overflow-hiddentable.w-full text-smthead.bg-muted/30 border-btr mit onClick={() => navigate(...)} + cursor-pointer hover:bg-accent/20ChevronRight-Spalte div.border rounded-lg overflow-hiddentable.w-full text-smtr.border-b bg-muted/50tbody.divide-y divide-bordertr mit onClick/cursor-pointer hover:bg-muted/30
Sortierung keine ja, lokale SortHeader-Komponente — pro Seite dupliziert, sortiert nur die geladene Seite
Gemeinsames Table-Component nein neinshared-kernel/ui hat Tag, Pill, ListToolbar, Pagination, aber kein Table/DataTable. Jede Domain baut ihre <table> selbst (ADR-0003 dort: {Entity}Badge/Row/Table/Detail pro Domain)
Nested-Klick-Schutz ja ja — onClick={e => e.stopPropagation()} auf Links/Buttons in Zellen

Korrektur einer Annahme aus der Auftragsstellung: DataCleanupPage.tsx ist in DOT kein Tabellen-Muster, sondern eine Formular-/Aktionsseite mit zwei Danger-Cards und Type-to-confirm — das deckt sich mit dem Befund der zweiten Iteration oben. Das DOT-Tabellenmuster steht in Finance/XRM/ Project-Economy, nicht in Administration.

Übernommen wurde die Form, nicht das Markup. Beide Vorbilder stimmen in Struktur und Verhalten überein (Wrapper mit overflow-hiddentable.w-full text-sm › klickbare Zeile › stopPropagation innen), unterscheiden sich aber in den Tailwind-Tokens. Die hiesige Tabelle folgt deshalb domains/testfaelle/components/TestCaseTable.tsx — dieselbe Form, aber mit den Tokens, die dieses Produkt bereits verwendet (bg-accent/40, border-border, hover:bg-accent/30). Ein zweites Tabellen-Aussehen im selben Repo wäre der teurere Weg zur selben Sache.

Was umgesetzt wurde — Frontend only, kein Backend-Eingriff

Kein neuer Endpunkt, keine neue Property. Die Detailseite liest denselben Szenarienkatalog wie die Liste (GET .../demo/referenzfall, gleicher Query-Key → Cache-Treffer statt zweitem Netzaufruf) und sucht den Schlüssel darin. Ein GET .../demo/referenzfall/{key} wäre derselbe Inhalt ein zweites Mal. Angezeigt werden genau die sieben Felder von ReferenzfallSzenario — auch synthetisch (immer true, OF-45) und standard, beide im Klartext statt als Häkchen. Nutzervorgabe war ausdrücklich, die Seite lieber dünn zu lassen als das Backend für optische Substanz zu erweitern; das ist auch die ehrlichere Variante.

Drei bewusste Auslassungen

Nicht gebaut Warum
Sortierbare Spalten (DOT hat sie, eimr nicht) Drei Zeilen. Eine Sortierfunktion über drei Zeilen ist dieselbe Sorte Theater wie die abgelehnte Fortschrittsliste mit einem Schritt. Rückweg, falls die Liste zweistellig wird: DOTs SortHeader ist ~15 Zeilen und dort ohnehin pro Seite kopiert.
Suche / ListToolbar / Pagination Dito — der Katalog ist eine Liste mitgelieferter Dateien, kein Datenbestand, und das Backend paginiert ihn nicht.
Ein „Starten"-Knopf pro Zeile Der Grund für den Knopf auf der Karte war, dass das Ergebnis dort stehen bleiben musste, wo geklickt wurde. Auf einer Detailseite ist diese Zuordnung trivial gegeben. Bei zwanzig Zeilen wären es zwanzig Aufforderungen, den Mandanten vollzuschreiben.

Tastaturzugänglichkeit ist der eine Punkt, an dem hier über die Vorlage hinausgegangen wurde: eimr und DOT machen die Zeile ausschließlich per onClick klickbar, damit ist die Detailseite ohne Maus unerreichbar. Hier ist der Titel zusätzlich ein echter <Link> (mit stopPropagation, sonst navigierten Link und Zeilen-Handler zweimal).

Status

npm run typecheck grün. Deployt auf die Alcatraz-VM (192.168.8.113) als einziger neu gestarteter Container (docker compose up -d --no-deps tuxametrics-ui) — tuxametrics-ui läuft, nginx-Log ohne Fehler, HTTPS antwortet mit 200, alle Nachbar-Container unberührt (Uptimes unverändert). Nicht verifiziert bleibt — wie in allen vorigen Iterationen — der visuelle Endzustand im Browser; geprüft wurde, dass die Seite ausgeliefert wird, nicht wie sie aussieht.


Fünfte Iteration (2026-08-16, später): die Detailseite zeigt die Werte

Jüngster Abschnitt. Er widerruft eine Entscheidung, die vier Absätze weiter oben noch als „die ehrlichere Variante" steht — das ist der Grund, warum er ausführlich begründet ist und nicht bloß den alten Text überschreibt.

Nutzerbefund, wörtlich: „na ja ich möchte ja die werte sehen". Die vierte Iteration hatte die Detailseite bewusst auf die sieben Katalogfelder beschränkt, mit zwei Argumenten: das Backend nicht für optische Substanz erweitern, und keine zweite fachliche Wahrheit neben dem Regelwerk erzeugen.

Das erste Argument war falsch angewandt. Die Werte einer Demo-Vorlage sind keine Optik — sie sind das, was die Vorlage ist. Wer eine Laborbefund-Vorlage auswählt, wählt einen Laborbefund; Titel und Kurzbeschreibung sind sein Etikett, nicht sein Inhalt. Bis heute war der Inhalt nur sichtbar, indem man den Fall anlegte — also durch genau den Schritt, für den man sich vorher entscheiden wollte. Das ist keine dünn gehaltene Seite, das ist eine Seite ohne ihren Gegenstand.

Das zweite Argument gilt weiter und ist die Grenze der Änderung. Gezeigt werden die Eingangswerte des Bundles. Nicht gezeigt wird, was daraus entsteht — kein Finding, keine Empfehlung, kein Sperrgrund, keine Risikoklasse. Das sagt der Auswertungslauf und steht im verlinkten Testfall. Eine Vorschau, die Ergebnisse vorwegnimmt, wäre die zweite fachliche Wahrheit, gegen die die vierte Iteration richtigerweise argumentiert hat.

Warum das eine echte Backend-Änderung sein musste

Die Werte lagen serverseitig längst in init-bundle/praxis01-referenzfall-{02,04,05}.json, waren aber über keinen Endpunkt lesbar: ReferenzfallService las die Bundles nur im Schreibpfad (lade()) und verwandelte sie dort sofort in Entitäten. Ein reiner Vorschau-Read existierte nicht. Anders als in den Iterationen 1, 2 und 4 war das hier also nicht vermeidbar — Frontend-only hätte bedeutet, die Werte im Frontend zu wiederholen, und damit hätte dasselbe Szenario zwei Quellen. Genau das verhindert ReferenzfallSzenario seit der dritten Iteration ausdrücklich.

Entscheidungen

Frage Entscheidung Verworfene Alternative
Eigener Detail-Endpunkt GET .../demo/referenzfall/{key}? Nein — die Werte hängen am bestehenden Katalog. Drei Dateien, zusammen zwölf Messwerte; der Sprung Liste → Detail bleibt ein Cache-Treffer auf ['demo','szenarien',tenantKey]. Ein zweiter Endpunkt hätte einen zweiten Query-Key, einen zweiten Ladezustand und einen zweiten Netzaufruf für dieselben wenigen Kilobyte gekostet. Bei zwanzig Bundles wäre die Abwägung neu zu treffen — dann trägt die Liste zwanzig Befunde.
Die *Create-Records direkt ausliefern? Nein, eigene Vorschau*-Records in ReferenzfallSzenario. MesswertCreate trägt Felder, die beschreiben, wie ein Wert ins System kam (normalisierterWert, angewandterFaktor, erkennungsunsicherheit, erfassungsart, bestimmungsgrenze), nicht welchen Wert der Fall setzt. Welche Felder die Vorschau zeigt, soll eine Entscheidung sein und keine Nebenwirkung eines Eingabeformats.
Nur Messwerte, wie im Auftrag als Minimum genannt? Nein — zusätzlich Patient, Befundkopf/Präanalytik, Sicherheitsmerkmale, Supplemente, Medikation. Mit nur Messwerten wären die Vorschauen der Konstellationen 4 und 5 zeichengleich: derselbe Kaliumwert 6,4 mmol/l, derselbe Referenzbereich. Ihr einziger Unterschied ist praeanalytik.haemolysehinweis — das Feld, das zwischen Probenhinweis und Notfallhinweis entscheidet (FACH-045 Z. 1057). Eine Vorschau ohne diesen Block hätte zwei identische Fälle gezeigt und die Aussage des Paars zerstört.
Leere Kategorien ausblenden? Nein, sie stehen mit Zähler (0) und einem Satz da. Dass Konstellation 4 keine Medikation und keine Supplemente trägt, ist eine Aussage über den Fall — er isoliert eine einzige Regel — und keine fehlende Angabe, die man verbergen sollte.

Zwei Stellen, an denen die Vorschau bewusst unbequem ist

Was umgesetzt wurde

Was hier nicht passiert ist

Kein neuer Capability-Schlüssel (die Vorschau hängt an txm.demo.load — wer den Fall nicht anlegen darf, sieht auch nicht, was er anlegen würde), keine neue Fachzahl (jede angezeigte Zahl stand schon vorher in ihrer Bundle-Datei), kein neuer Enum-Wert, keine E2, RegulatorikGuard unberührt. GM-7 ist wie in allen Iterationen dieses Themas nicht betroffen: eine Demo-Vorlage anzusehen ist keine klinische Entscheidung.

Status

mvn -f tuxametrics-laborauswertung-service/pom.xml test grün (67 Tests), npm run typecheck grün. Nativer Bau des Laborauswertung-Service (4 m 52 s, native-image-xmx=6g unverändert, kein Exit 137) plus Frontend-Bau, beide auf die Alcatraz-VM deployt (docker compose -f docker-compose.yml -f docker-compose.native.yml up -d --no-deps tuxametrics-laborauswertung-service tuxametrics-ui). Container healthy bzw. nginx sauber, native Startzeit 0,088 s, 19 txm.*-Capabilities registriert, kein Reflection-/Serialisierungsfehler beim Start.

Zwei Dinge sind nicht verifiziert, und das eine ist neu: