feat(vorlagen): bedingte Abschnitte und Schritte (#039)
Prüfung / pruefung (push) Waiting to run
Prüfung / e2e (push) Blocked by required conditions

Ein Abschnitt oder ein einzelner Schritt erscheint nur, wenn seine Bedingung
zutrifft — abhaengig von einer Variable des Laufs oder vom Zustand eines
anderen Schritts. Der echte Fall steht im Seed: "Mitarbeiter-Onboarding" traegt
beide Konto-Abschnitte, fuenf AD-Schritte und vier fuer Entra ID, und
`konto_typ` sagt beim Start, welcher gilt. Bisher klickte ein Techniker die
anderen neun bei jedem Onboarding weg.

Entscheidungen, alle im Issue begruendet:

- Laufend ausgewertet, nicht beim Start festgeschrieben. Fuer die
  Abteilungsabschnitte (#031) ist Festschreiben richtig; fuer Bedingungen nicht
  — die Antwort auf "ist Pruefen fehlgeschlagen?" entsteht erst waehrend der
  Arbeit. Ein struktureller Test prueft, dass alle drei Schichten
  (Abschlussregel, Abarbeitung, Druck) die Auswertung rufen.
- Nicht entscheidbar heisst: gilt. Ein Lauf ohne konto_typ zeigt beide
  Abschnitte — genau wie vorher. Ein Abschnitt zu viel ist sichtbar und
  korrigierbar, ein fehlender faellt niemandem auf.
- OFFEN ist eine Antwort, keine Luecke: waere es unentscheidbar, waere ein
  bedingter Abschnitt von Anfang an sichtbar.
- Eine Bedingung, kein Ausdrucksbaum. Kein und, kein oder.
- Verwiesen wird ueber Titel-Pfade, nicht ueber Kennungen: vier Wege schreiben
  eine Struktur neu und geben neue Kennungen.

Zwei stille Datenverluste gefunden, der zweite aelter als dieser Meilenstein:

- Der Import verwarf `nurFuerAbteilungen`. Der Export schreibt es seit #031, das
  Schema nimmt es an, der Import setzte es nicht — eine exportierte Vorlage
  verlor ihre Abteilungsabschnitte und galt dort fuer alle.
- Die tiefe Kopie verwarf es ebenfalls, womit jedes "Bearbeiten" einer Vorlage
  alle Einschraenkungen verlor. Ursache war ein von Hand getippter Zwischentyp,
  der weniger Felder nannte als die Abfrage liefert; jetzt aus Prisma
  abgeleitet, beide Kopierwege teilen eine Stelle, und ein Test vergleicht Kopie
  und Original Feld fuer Feld.

Gefunden hat beides die Klickprobe am gebauten Stand, nicht die Suite: im Editor
stand "Bedingung gesetzt", nach "Bearbeiten" war sie weg. Dreizehn Gegenproben
liefen, alle wurden rot — und der teuerste Befund lag ausserhalb von allen.

1499 Vitest-Tests (vorher 1457), 115 E2E-Ablaeufe gruen.

Closes #39

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-10-23 14:54:10 +02:00
co-authored by Claude Opus 5
parent 2f247b3617
commit a2330ef682
29 changed files with 3051 additions and 146 deletions
+77 -2
View File
@@ -40,12 +40,14 @@ als Unterpunkte mit Aufgabe und Dauer.
| #027 | Die Editor-Abläufe lassen ihre Vorlagen stehen | 2 h 10 min |
| #038 | Die E2E-Abläufe laufen in keinem Tor | 1 h 35 min |
| #037 | Zwei Nachzügler aus der Durchsicht von Phase 2 | 1 h 50 min |
| | **Summe** | **73 h 55 min** |
| #039 | M23 – Bedingte Schritte und Abschnitte | 5 h 20 min |
| | **Summe** | **79 h 15 min** |
| Meilenstein | Tatsächlich | Status |
|---|---|---|
| v0.1.0 | 35 h 20 min | veröffentlicht |
| v0.2.0 | 38 h 35 min | in Arbeit |
| v0.2.0 | 38 h 35 min | veröffentlicht |
| v0.3.0 | 5 h 20 min | in Arbeit |
---
@@ -1764,3 +1766,76 @@ Entra-Mandanten** und **gegen echte SCIM-Anbieter** ist nichts gelaufen. Die For
stammen aus der Dokumentation, nicht aus Mitschnitten. Stimmt eine Form nicht, stimmen Test und
Wirklichkeit nicht — die Prüflisten stehen in `docs/betrieb/entra-id.md` und
`docs/betrieb/scim.md`.
---
## 2026-10-23 · Sitzung 25 · 11:00–15:10
**Issue:** #039 (M23)
**Version:** 0.3.0 (unveröffentlicht)
### Erledigt
- **Bedingte Abschnitte und Schritte**, der erste Meilenstein von Phase 3. Eine Bedingung hängt an
einer Variable des Laufs oder am Zustand eines anderen Schritts; die Auswertung läuft bei jedem
Lesen und sitzt in `src/lib/bedingungen.ts`.
- **Der Seed nutzt es am echten Fall**: „Mitarbeiter-Onboarding“ hat die Bedingung auf `konto_typ`,
beide Konto-Abschnitte bleiben drin und schließen sich aus. Neun Schritte, die niemand mehr
wegklickt.
- Editor, Abarbeitung, Druck, Export, Import, Entwurf und Seed — sieben Wege, alle mit Tests.
- 1496 Vitest-Tests (vorher 1457), davon 29 neue. Klickprobe am gebauten Stand: Bildschirm, Druck
und 390 px zeigen dasselbe.
### Entscheidungen
- **Laufend auswerten, nicht beim Start festschreiben.** Für die Abteilungsabschnitte (#031) ist
Festschreiben richtig: die Abteilung steht beim Start fest. Für Bedingungen nicht — die Antwort auf
„ist Prüfen fehlgeschlagen?“ entsteht erst während der Arbeit. `geltendeStruktur` legt die
Reihenfolge der zwei Filter fest, und ein struktureller Test prüft, dass alle drei Schichten sie
rufen.
- **Nicht entscheidbar heißt: gilt.** Ein Lauf ohne `konto_typ` zeigt beide Konto-Abschnitte. Das ist
genau das Verhalten von vorher; eine erfundene Antwort wäre die Verschlechterung. Ein Abschnitt zu
viel ist sichtbar und korrigierbar, ein fehlender fällt niemandem auf.
- **`OFFEN` ist eine Antwort, keine Lücke** — der scharfe Gegensatz zur nicht gesetzten Variable.
Wäre `OFFEN` unentscheidbar, wäre ein bedingter Abschnitt von Anfang an sichtbar, also das
Gegenteil des Zwecks.
- **Eine Bedingung, kein Ausdrucksbaum.** Kein `und`, kein `oder`, keine Verschachtelung. Wer zwei
braucht, nimmt zwei Abschnitte. Ein Formular für beliebige Ausdrücke wäre eine kleine
Abfragesprache, und ein Abschnitt, der aus unerklärlichen Gründen fehlt, ist schlimmer als einer zu
viel.
- **Verwiesen wird über Titel-Pfade, nicht über Kennungen.** Vier Wege schreiben eine Struktur neu
und geben neue Kennungen: Import, Export, Seed, `entwurfSpeichern`. Eine Kennung überlebt keinen
davon.
### Probleme
- **Zwei stille Datenverluste, und der zweite war älter als dieser Meilenstein.**
- Der **Import** verwarf `nurFuerAbteilungen`: der Export schreibt es seit #031, das Schema nimmt
es an, der Import setzte es nicht. Eine exportierte Vorlage verlor ihre Abteilungsabschnitte.
- Die **tiefe Kopie** verwarf es ebenfalls — damit verlor **jedes „Bearbeiten“** einer Vorlage alle
Abteilungseinschränkungen. Beide Kopierstellen hatten den Code einzeln ausgeschrieben und
vergaßen dieselben Felder.
**Die Ursache war ein von Hand getippter Zwischentyp.** `VersionMitInhalt` nannte weniger Felder,
als die Abfrage liefert; die Daten waren da, der Code konnte sie nicht sehen. Jetzt aus Prisma
abgeleitet — ein neues Feld ist dort automatisch vorhanden. Und bewacht von einem Test, der Kopie
und Original **Feld für Feld** vergleicht, nicht stichprobenweise.
- **Gefunden hat beides die Klickprobe am gebauten Stand**, nicht die Suite: im Editor stand
„Bedingung gesetzt“, und nach „Bearbeiten“ war sie weg. Genau dafür steht diese Probe in
`CLAUDE.md`. Dreizehn Gegenproben liefen in dieser Sitzung, alle wurden rot — und trotzdem lag der
teuerste Befund außerhalb von allen.
- **Zwei Schemas für dieselbe Form** liefen fast auseinander: Austauschformat und Editor-Struktur
brauchen die Pfad-Form, und TypeScript meldete die Abweichung erst, als die Typen aufeinandertrafen.
Jetzt eine Stelle.
- **Ein Mangel an der neuen Komponente**, beim Klicken aufgefallen: die Auswahlfelder standen in
einem umhüllenden `label`, und ihr zugänglicher Name schluckte den Text der gewählten Option mit.
Derselbe Fehler wie bei der Adresse im Verzeichnis-Formular (#016) — dort war es ein Reviewbefund.
- **Zwei eigene Testfehler**: dreimal versucht, eine Bedingung an einer **veröffentlichten** Version
zu setzen (die ist unveränderlich, dafür sorgen Trigger), und `vorlageBearbeiten` mit
`entwurfHolenOderErzeugen` verwechselt. Beide Male hat die Datenbank es gesagt.
### Nächster Schritt
- **M24 (#040)** Vier-Augen-Freigabe. Der Abschluss wird dort ohnehin angefasst, und M25 braucht den
Freigeber für das Blatt.