feat(vorlagen): bedingte Abschnitte und Schritte (#039)
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:
co-authored by
Claude Opus 5
parent
2f247b3617
commit
a2330ef682
@@ -219,6 +219,73 @@ Import: ein Abteilungsname bedeutet in einer anderen Installation dasselbe.
|
||||
**Lässt für eine Abteilung kein Abschnitt übrig, wird der Lauf abgewiesen** — es gäbe nichts
|
||||
abzuarbeiten. Das passiert nur, wenn jeder Abschnitt einer Vorlage eingeschränkt ist.
|
||||
|
||||
## Bedingte Abschnitte und Schritte
|
||||
|
||||
Die Onboarding-Vorlage enthält **beide** Konto-Abschnitte — „Konto anlegen (Active Directory)“ mit
|
||||
fünf Schritten und „Konto anlegen (Entra ID)“ mit vier. In jedem einzelnen Lauf gilt nur einer, und
|
||||
die Variable **Kontotyp** sagt beim Start, welcher. Bis hierher klickte ein Techniker die anderen
|
||||
neun Schritte weg.
|
||||
|
||||
Mit einer **Bedingung** erscheint ein Abschnitt oder ein einzelner Schritt nur dann, wenn er
|
||||
zutrifft. Im Editor steht an jedem Abschnitt und an jedem Schritt **Bedingung (optional)**; ohne
|
||||
eine gilt er immer.
|
||||
|
||||
### Zwei Arten, und die Wahl entscheidet, wann die Antwort entsteht
|
||||
|
||||
| Die Bedingung hängt an … | Beispiel | Wann sie entschieden wird |
|
||||
|---|---|---|
|
||||
| einer **Variable** | „gilt, wenn Kontotyp gleich Active Directory ist“ | beim Start, wenn die Variablen erfasst werden |
|
||||
| einem **Schritt** | „gilt, wenn Prüfen fehlgeschlagen ist“ | während der Arbeit, sobald jemand den Schritt setzt |
|
||||
|
||||
Die zweite ist die interessantere: ein Abschnitt „Nacharbeit“, der erst erscheint, wenn der
|
||||
Restore-Test fehlgeschlagen ist. Er ist zu Beginn nicht da und kommt in dem Moment dazu, in dem der
|
||||
Schritt auf „fehlgeschlagen“ geht — bei einer offenen zweiten Sitzung sofort.
|
||||
|
||||
### Eine Bedingung, nicht mehr
|
||||
|
||||
Es gibt **kein** „und“ und kein „oder“. Wer zwei Bedingungen braucht, nimmt zwei Abschnitte oder
|
||||
zwei Vorlagen. Das ist Absicht: ein Formular, in dem sich beliebige Ausdrücke bauen lassen, wäre
|
||||
eine kleine Programmiersprache — und ein Abschnitt, der aus unerklärlichen Gründen fehlt, ist
|
||||
schlimmer als einer zu viel.
|
||||
|
||||
Bei einer Schritt-Bedingung lassen sich dagegen **mehrere Zustände** ankreuzen: „erledigt oder nicht
|
||||
zutreffend“ ist eine Frage, nicht zwei.
|
||||
|
||||
### Vier Dinge, die man dazu wissen muss
|
||||
|
||||
- **Lässt sich eine Bedingung nicht entscheiden, erscheint der Teil.** Hat niemand den Kontotyp
|
||||
angegeben, stehen **beide** Konto-Abschnitte da — genau wie vorher. Auszublenden hieße, eine
|
||||
Antwort zu erfinden, die niemand gegeben hat. Ein Abschnitt zu viel ist sichtbar und
|
||||
korrigierbar; ein fehlender fällt niemandem auf.
|
||||
- **Ein ausgeblendeter Pflichtschritt blockiert den Abschluss nicht** — dieselbe Regel wie bei den
|
||||
Abteilungsabschnitten. Er steht nicht in der Abarbeitung, also lässt er sich nicht abhaken.
|
||||
- **Ausgeblendet heißt nicht gelöscht.** Hat jemand in einem Schritt eine Notiz hinterlassen und
|
||||
kippt dessen Bedingung danach, verschwindet der Schritt aus der Ansicht — die Notiz bleibt. Kippt
|
||||
die Bedingung zurück, ist alles wieder da.
|
||||
- **Die Nummerierung zählt, was man sieht.** Ein ausgeblendeter Abschnitt hinterlässt keine Lücke;
|
||||
aus `01 · 02 · 03` wird nicht `01 · 03`.
|
||||
|
||||
### Die Warnung „dieser Schritt kommt später“
|
||||
|
||||
Zeigt eine Bedingung auf einen Schritt, der **nach** dem bedingten Teil steht, warnt der Editor.
|
||||
Verboten ist es nicht, aber fast immer ein Versehen: der Abschnitt wäre beim Abarbeiten zunächst
|
||||
unsichtbar und erschiene erst, nachdem jemand weiter unten etwas abgehakt hat — also rückwärts.
|
||||
Gemeint ist meist ein Schritt davor.
|
||||
|
||||
### Export und Import
|
||||
|
||||
Eine Bedingung wandert mit. Im Austauschdokument steht sie über **Titel** statt über Kennungen
|
||||
(`"abschnitt": "Prüfung", "schritt": "Prüfen"`), denn eine Kennung bedeutet in einer anderen
|
||||
Installation nichts. Beim Import wird daraus wieder der richtige Schritt.
|
||||
|
||||
Findet sich der Titel-Pfad in der Datei nicht — etwa nach einem Tippfehler in einer von Hand
|
||||
geschriebenen Vorlage —, wird die Bedingung **weggelassen**. Der Abschnitt gilt dann immer, und das
|
||||
steht sichtbar im Editor. Die ganze Vorlage deswegen abzuweisen wäre die teurere Antwort.
|
||||
|
||||
**Ein Baustein-Schritt hat keine Bedingung.** Ein Baustein ist wiederverwendbar, und eine Bedingung
|
||||
auf einer Variable, die es in der Zielvorlage nicht gibt, wäre dort nicht entscheidbar. Der
|
||||
Abschnitt, in dem der Baustein eingesetzt wird, darf eine haben.
|
||||
|
||||
## Bausteine: ein Abschnitt für mehrere Vorlagen
|
||||
|
||||
„Datensicherung prüfen“ steht in vier der sieben mitgelieferten Vorlagen, wortgleich. Wer den Ablauf
|
||||
|
||||
@@ -387,6 +387,42 @@ Vom Mitarbeiter holt dieses Lesemodell **nur Name, UPN und Abteilung** — nicht
|
||||
alles und dann gefiltert. Ein Ausdruck liegt herum, wird kopiert und weitergegeben;
|
||||
was darauf steht, ist aus der Hand gegeben.
|
||||
|
||||
## 5f-2. Bedingte Teile: zwei Filter, eine Reihenfolge
|
||||
|
||||
Was ein Lauf zeigt, entsteht aus **zwei** Filtern uebereinander, und ihre
|
||||
Reihenfolge ist der ganze Inhalt von `geltendeStruktur` in
|
||||
`src/lib/bedingungen.ts`:
|
||||
|
||||
1. **Die Abteilungsauswahl (#031)** — beim Start festgeschrieben in
|
||||
`Lauf.geltendeAbschnitte`. Festgeschrieben, weil ein archivierter Lauf genau
|
||||
die Schritte zeigen muss, die damals abgearbeitet wurden, und ein spaeterer
|
||||
Abteilungswechsel keinen Schritt entfernen darf, an dem eine Notiz haengt.
|
||||
2. **Die Bedingungen (#039)** — **laufend** ausgewertet. Eine Bedingung auf einer
|
||||
Variable liesse sich auch festschreiben; eine auf einem Schrittergebnis nicht,
|
||||
denn ihre Antwort entsteht erst waehrend der Arbeit. Ein Abschnitt
|
||||
„Nacharbeit“, der erscheint, wenn der Restore-Test fehlschlaegt, ist der Fall,
|
||||
fuer den es gebaut ist.
|
||||
|
||||
Wer nur den ersten anwendet, bekommt Abschnitte, die nicht gelten; wer nur den
|
||||
zweiten anwendet, umgeht die Abteilungsregel. Drei Schichten brauchen beide — die
|
||||
Abschlussregel im Dienst, die Abarbeitung und die Druckansicht —, und
|
||||
`tests/bedingte-laeufe.test.ts` prueft **strukturell**, dass keine davon die
|
||||
zweite vergisst. Dieselbe Art Test wie „jede Seite prueft selbst“ (#038): die
|
||||
Zusage steht in der Vollstaendigkeit einer Liste, und die muss jemand bewachen.
|
||||
|
||||
**Nicht entscheidbar heisst: gilt.** Hat niemand den Kontotyp angegeben, stehen
|
||||
beide Konto-Abschnitte da — genau wie vor #039. Auszublenden hiesse, eine Antwort
|
||||
zu erfinden, die niemand gegeben hat; und die Richtung, in die der Zweifel
|
||||
faellt, soll die harmlose sein.
|
||||
|
||||
**Verwiesen wird ueber Titel-Pfade, nicht ueber Kennungen.** Vier Wege schreiben
|
||||
eine Struktur neu und geben dabei neue Kennungen: Import, Export, Seed und
|
||||
`entwurfSpeichern`. Eine Bedingung auf einer Kennung ueberlebte keinen davon —
|
||||
ein Titel-Pfad ueberlebt alle vier, und `bedingungAufloesen` ist fuer alle
|
||||
dieselbe Stelle. Dass eine Schritt-Bedingung auf **dieselbe Version** zeigt,
|
||||
haelt ein Trigger: nach dem Veroeffentlichen waere ein fremder Verweis nicht mehr
|
||||
entscheidbar, und der Abschnitt erschiene stillschweigend immer.
|
||||
|
||||
## 5g. Der Verzeichnis-Abgleich: vier Schichten und eine Notbremse
|
||||
|
||||
Eine Verzeichnisquelle hat seit #028 eine **Art** — `LDAP`, `GRAPH` oder `SCIM` —,
|
||||
|
||||
+77
-2
@@ -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.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# #039 M23 – Bedingte Schritte und Abschnitte
|
||||
|
||||
**Status:** offen
|
||||
**Status:** erledigt
|
||||
**Im Tracker:** –
|
||||
**Meilenstein:** v0.3.0
|
||||
**Labels:** phase-3, backend, frontend
|
||||
**Geschätzt:** 12 h **Tatsächlich:** –
|
||||
**Geschätzt:** 12 h **Tatsächlich:** 5 h 20 min
|
||||
|
||||
## Ziel
|
||||
|
||||
@@ -23,7 +23,7 @@ Stelle, an der das sitzt.
|
||||
|
||||
## Zu entscheiden
|
||||
|
||||
- [ ] **Wann wird ausgewertet?** Das ist die Entscheidung, an der alles hängt.
|
||||
- [x] **Wann wird ausgewertet?** Das ist die Entscheidung, an der alles hängt.
|
||||
|
||||
Für Abteilungen (#031) wird beim **Start festgeschrieben** — die Abteilung des Laufs steht
|
||||
dann fest, und ein archivierter Lauf muss genau die Schritte zeigen, die damals galten.
|
||||
@@ -36,60 +36,129 @@ Stelle, an der das sitzt.
|
||||
Änderung an einem Schrittergebnis; was dabei herauskommt, wird in den Lauf geschrieben (wie
|
||||
`geltendeAbschnitte`). Damit gilt für das Archiv weiter „der Lauf weiß, was galt“, und der
|
||||
Ereignisstrom aus #033 trägt die Änderung ohnehin schon zur zweiten Sitzung.
|
||||
- [ ] **Woran darf eine Bedingung hängen?** Empfehlung: an einer **Variable** des Laufs und an
|
||||
- [x] **Woran darf eine Bedingung hängen?** Empfehlung: an einer **Variable** des Laufs und an
|
||||
einem **Schrittergebnis** derselben Version. Nicht an Gerätetyp, Abteilung oder Rolle — für
|
||||
Abteilungen gibt es #031, und je mehr Quellen, desto schwerer zu erklären, warum ein Schritt
|
||||
fehlt.
|
||||
- [ ] **Wie wird sie gespeichert?** Empfehlung: ein Json-Feld `bedingung` an `VorlagenAbschnitt`
|
||||
- [x] **Wie wird sie gespeichert?** Empfehlung: ein Json-Feld `bedingung` an `VorlagenAbschnitt`
|
||||
und `VorlagenSchritt`, mit einem engen Schema — `{ art: "variable", schluessel, operator,
|
||||
wert }` oder `{ art: "schritt", schrittId, zustand }`. Json, weil `konfig` es schon so macht
|
||||
und ein neuer Operator dann keine Migration braucht.
|
||||
**Eine Bedingung, kein Ausdrucksbaum.** Kein `und`/`oder`, keine Verschachtelung: das wäre
|
||||
eine kleine Sprache, die niemand im Editor pflegen kann, und ein Abschnitt, der aus
|
||||
unerklärlichen Gründen fehlt, ist schlimmer als einer zu viel.
|
||||
- [ ] **Was passiert mit einem Schrittergebnis, das schon Daten trägt**, wenn die Bedingung
|
||||
- [x] **Was passiert mit einem Schrittergebnis, das schon Daten trägt**, wenn die Bedingung
|
||||
umschlägt? Empfehlung: die Zeile **bleibt** und wird nur ausgeblendet. Löschen hieße, eine
|
||||
Notiz zu verlieren, die jemand geschrieben hat; und schlägt die Bedingung zurück, ist sie
|
||||
wieder da.
|
||||
|
||||
## Aufgaben
|
||||
|
||||
- [ ] Migration: `bedingung Json?` an `VorlagenAbschnitt` und `VorlagenSchritt`, dazu ein CHECK, der
|
||||
- [x] Migration: `bedingung Json?` an `VorlagenAbschnitt` und `VorlagenSchritt`, dazu ein CHECK, der
|
||||
sicherstellt, dass eine Bedingung auf einen Schritt **derselben Version** zeigt (sonst zeigt
|
||||
sie nach dem Veröffentlichen ins Leere)
|
||||
- [ ] `src/lib/bedingungen.ts`, framework-frei: Schema, Auswertung, und die Liste der Schritte und
|
||||
- [x] `src/lib/bedingungen.ts`, framework-frei: Schema, Auswertung, und die Liste der Schritte und
|
||||
Abschnitte, die gelten. **Dieselbe Stelle für alle drei Schichten**, wie
|
||||
`src/lib/geltende-abschnitte.ts`
|
||||
- [ ] Auswertung bei jedem Schreiben an einem `Schrittergebnis`; das Ergebnis in den Lauf
|
||||
- [ ] Abschlussregel: ein ausgeblendeter Pflichtschritt hält den Abschluss **nicht** auf (dieselbe
|
||||
- [x] Auswertung bei jedem Schreiben an einem `Schrittergebnis`; das Ergebnis in den Lauf
|
||||
- [x] Abschlussregel: ein ausgeblendeter Pflichtschritt hält den Abschluss **nicht** auf (dieselbe
|
||||
Regel wie bei #031, dieselbe Funktion)
|
||||
- [ ] Fortschrittsbalken und Zählwerte rechnen nur mit dem, was gilt
|
||||
- [ ] Editor: Bedingung an Abschnitt und Schritt setzen, mit Auswahl der Variable bzw. des Schritts
|
||||
- [x] Fortschrittsbalken und Zählwerte rechnen nur mit dem, was gilt
|
||||
- [x] Editor: Bedingung an Abschnitt und Schritt setzen, mit Auswahl der Variable bzw. des Schritts
|
||||
**aus derselben Version**; eine Vorschau, die sagt „gilt, wenn …“
|
||||
- [ ] Warnung im Editor bei einer Bedingung auf einen Schritt, der **nach** dem bedingten steht —
|
||||
- [x] Warnung im Editor bei einer Bedingung auf einen Schritt, der **nach** dem bedingten steht —
|
||||
sie wäre beim Abarbeiten noch offen, und der Abschnitt erschiene erst rückwirkend
|
||||
- [ ] Abarbeitung: ausgeblendete Abschnitte verschwinden, ohne die Nummerierung zu verschieben
|
||||
- [x] Abarbeitung: ausgeblendete Abschnitte verschwinden, ohne die Nummerierung zu verschieben
|
||||
(`01 · Vorbereitung` kommt aus der Position und wird nie gespeichert)
|
||||
- [ ] Druckansicht und Archiv zeigen, was galt
|
||||
- [ ] Export/Import: die Bedingung wandert mit, und ein Verweis auf einen Schritt wird dabei auf die
|
||||
- [x] Druckansicht und Archiv zeigen, was galt
|
||||
- [x] Export/Import: die Bedingung wandert mit, und ein Verweis auf einen Schritt wird dabei auf die
|
||||
**neue** Kennung umgeschrieben — sonst zeigt sie in der zweiten Installation ins Leere
|
||||
- [ ] Seed: „Mitarbeiter-Onboarding“ bekommt die Bedingung auf `konto_typ`, die beiden
|
||||
- [x] Seed: „Mitarbeiter-Onboarding“ bekommt die Bedingung auf `konto_typ`, die beiden
|
||||
Konto-Abschnitte bleiben drin und schließen sich gegenseitig aus. Das ist die Gegenprobe am
|
||||
echten Fall.
|
||||
- [ ] Anleitung Kapitel 04 (Vorlagen): wann eine Bedingung das richtige Mittel ist und wann eine
|
||||
- [x] Anleitung Kapitel 04 (Vorlagen): wann eine Bedingung das richtige Mittel ist und wann eine
|
||||
zweite Vorlage
|
||||
|
||||
## Akzeptanzkriterien
|
||||
|
||||
- [ ] Test: ein Lauf mit `konto_typ = AD` hat die 5 AD-Schritte und **keinen** der 4 Entra-Schritte
|
||||
- [ ] Test: dasselbe umgekehrt, und bei nicht gesetzter Variable gelten **beide** — eine Bedingung,
|
||||
- [x] Test: ein Lauf mit `konto_typ = AD` hat die 5 AD-Schritte und **keinen** der 4 Entra-Schritte
|
||||
- [x] Test: dasselbe umgekehrt, und bei nicht gesetzter Variable gelten **beide** — eine Bedingung,
|
||||
die nicht entschieden werden kann, blendet nichts aus
|
||||
- [ ] Test: eine Bedingung auf einem Schrittergebnis schlägt um, **während** der Lauf läuft, und der
|
||||
- [x] Test: eine Bedingung auf einem Schrittergebnis schlägt um, **während** der Lauf läuft, und der
|
||||
Abschnitt erscheint
|
||||
- [ ] Test: ein ausgeblendeter Pflichtschritt hält den Abschluss nicht auf
|
||||
- [ ] Test: ein Schrittergebnis mit Notiz bleibt stehen, wenn seine Bedingung umschlägt, und ist
|
||||
- [x] Test: ein ausgeblendeter Pflichtschritt hält den Abschluss nicht auf
|
||||
- [x] Test: ein Schrittergebnis mit Notiz bleibt stehen, wenn seine Bedingung umschlägt, und ist
|
||||
danach wieder da
|
||||
- [ ] Test: Export und Import einer Vorlage mit Bedingungen ergeben dieselbe Struktur, und der
|
||||
- [x] Test: Export und Import einer Vorlage mit Bedingungen ergeben dieselbe Struktur, und der
|
||||
Schritt-Verweis zeigt auf den richtigen Schritt der **neuen** Version
|
||||
- [ ] Test: ein archivierter Lauf zeigt genau die Schritte, die bei seinem Abschluss galten
|
||||
- [ ] Am Handy kein horizontales Scrollen
|
||||
- [x] Test: ein archivierter Lauf zeigt genau die Schritte, die bei seinem Abschluss galten
|
||||
- [x] Am Handy kein horizontales Scrollen
|
||||
|
||||
## Beim Umsetzen dazugekommen
|
||||
|
||||
- **Die Entscheidungen aus dem Issue sind so gefallen wie empfohlen**, und zwei davon haben sich im
|
||||
Code als richtig erwiesen:
|
||||
- **Laufend auswerten, nicht beim Start festschreiben.** Eine Bedingung auf einer Variable ließe
|
||||
sich wie #031 beim Start festhalten; eine auf einem Schrittergebnis nicht — und genau die ist der
|
||||
interessante Fall (ein Abschnitt „Nacharbeit“, der erscheint, wenn der Restore-Test
|
||||
fehlschlägt).
|
||||
- **Nicht entscheidbar heißt: gilt.** Ein Lauf ohne `konto_typ` zeigt beide Konto-Abschnitte —
|
||||
genau wie vor diesem Meilenstein. Eine erfundene Antwort wäre die Verschlechterung.
|
||||
- **`OFFEN` ist eine Antwort, keine Lücke.** Der Unterschied zur Variable musste scharf gezogen
|
||||
werden: eine nicht gesetzte Variable ist nicht entscheidbar, ein offener Schritt dagegen klar
|
||||
„noch nicht erfüllt“. Wäre `OFFEN` unentscheidbar, wäre ein bedingter Abschnitt von Anfang an
|
||||
sichtbar — das Gegenteil des Zwecks.
|
||||
- **Verwiesen wird über Titel-Pfade, nicht über Kennungen**, und das war die größte Einzelerkenntnis.
|
||||
**Vier** Wege schreiben eine Struktur neu und geben dabei neue Kennungen: Import, Export, Seed und
|
||||
`entwurfSpeichern`. Eine Bedingung auf einer Kennung überlebt keinen davon. `bedingungAufloesen`
|
||||
ist für alle vier dieselbe Stelle; dass eine Bedingung auf **dieselbe Version** zeigt, hält
|
||||
zusätzlich ein Trigger.
|
||||
- **Ein struktureller Test bewacht die drei Schichten.** Abschlussregel, Abarbeitung und Druck
|
||||
müssen alle `geltendeStruktur` rufen; vergisst eine es, sieht der Techniker andere Schritte als
|
||||
der Ausdruck. Der Test liest die drei Dateien — dieselbe Art Prüfung wie „jede Seite prüft selbst“
|
||||
(#038).
|
||||
- **Zwei Schemas für dieselbe Form liefen fast auseinander.** Austauschformat und Editor-Struktur
|
||||
brauchen die Pfad-Form; ich hatte sie zweimal geschrieben, und TypeScript meldete es erst, als die
|
||||
beiden Typen aufeinandertrafen. Jetzt steht `PfadBedingungSchema` in `src/lib/bedingungen.ts`, und
|
||||
`vorlagen-format.ts` importiert es.
|
||||
|
||||
## Zwei stille Datenverluste, gefunden bei der Klickprobe
|
||||
|
||||
Beides hätte keine Suite gezeigt, und das zweite war **älter als dieser Meilenstein**:
|
||||
|
||||
- **Der Import verwarf `nurFuerAbteilungen`.** Der Export schreibt die Abteilungseinschränkung seit
|
||||
[#031](031-abteilungsabschnitte.md), das Schema nimmt sie an — und der Import setzte sie nicht.
|
||||
Eine Vorlage, die jemand in eine zweite Installation brachte, verlor ihre Abteilungsabschnitte:
|
||||
sie galten dort für **alle**. Also mehr Schritte statt weniger, und niemand merkt es.
|
||||
- **Die tiefe Kopie verwarf sie ebenfalls — und seit heute auch die Bedingung.** „Bearbeiten“ einer
|
||||
Vorlage erzeugt eine tiefe Kopie als Entwurf (#009); `vorlageDuplizieren` dasselbe. Beide hatten
|
||||
die Kopie einzeln ausgeschrieben, und beide vergaßen dieselben Felder. Damit verlor **jede
|
||||
Bearbeitung** alle Abteilungseinschränkungen.
|
||||
|
||||
**Die Ursache war ein von Hand getippter Zwischentyp.** `VersionMitInhalt` nannte weniger Felder,
|
||||
als die Abfrage liefert; die Felder waren da, der Code konnte sie nicht sehen. Jetzt ist der Typ
|
||||
aus Prisma abgeleitet — ein neues Feld am Modell ist dort automatisch vorhanden.
|
||||
|
||||
Gefunden hat es die **Klickprobe am gebauten Stand**: der Editor zeigte „Bedingung gesetzt“ in der
|
||||
veröffentlichten Version, und nach „Bearbeiten“ war sie weg. Das ist genau der Grund, warum diese
|
||||
Probe in `CLAUDE.md` steht.
|
||||
|
||||
Bewacht wird es jetzt von einem Test, der Kopie und Original **Feld für Feld** vergleicht — nicht
|
||||
stichprobenweise. So fällt auch das nächste Feld auf, das jemand ergänzt und beim Kopieren
|
||||
vergisst.
|
||||
|
||||
- **Ein Mangel an der neuen Komponente**, aufgefallen beim Klicken: die Auswahlfelder standen in
|
||||
einem umhüllenden `<label>`, und damit schluckte ihr zugänglicher Name den Text der gewählten
|
||||
Option mit („VariableKontotyp“). Für einen Screenreader ist das eine Bezeichnung, die sich beim
|
||||
Umschalten ändert. Jetzt `htmlFor`/`id` — derselbe Fehler wie bei der Adresse im Verzeichnis-Formular
|
||||
(#016).
|
||||
|
||||
## Was offen bleibt
|
||||
|
||||
- **Kein `und`/`oder`**, bewusst. Wer zwei Bedingungen braucht, nimmt zwei Abschnitte.
|
||||
- **Ein Baustein-Schritt hat keine Bedingung** (der Abschnitt, in dem er steht, darf eine haben): ein
|
||||
Baustein ist wiederverwendbar, und eine Bedingung auf einer Variable der Zielvorlage wäre dort
|
||||
nicht entscheidbar.
|
||||
- **Zwei Schritte mit demselben Titel im selben Abschnitt** sind über den Titel-Pfad nicht
|
||||
unterscheidbar; die Bedingung zeigt dann auf den ersten. Benannt in `src/lib/bedingungen.ts` —
|
||||
zwei gleich benannte Schritte nebeneinander kann auch ein Mensch nicht unterscheiden.
|
||||
|
||||
@@ -43,8 +43,8 @@ Diese Dateien sind die Quelle; `pnpm issues:sync` spiegelt sie in den Gitea-Trac
|
||||
| #036 | [Reviewbefunde aus der Durchsicht von Phase 2](036-reviewbefunde-phase-2.md) | erledigt | v0.2.0 | 4 h | 3 h 40 min |
|
||||
| #037 | [Zwei Nachzügler aus der Durchsicht von Phase 2](037-anhaenge-lesemodell.md) | erledigt | v0.2.0 | 2 h | 1 h 50 min |
|
||||
| #038 | [Die E2E-Abläufe laufen in keinem Tor und waren monatelang rot](038-e2e-im-tor.md) | erledigt | v0.2.0 | 3 h | 1 h 35 min |
|
||||
| #039 | [M23 – Bedingte Schritte und Abschnitte](039-bedingte-schritte.md) | offen | v0.3.0 | 12 h | – |
|
||||
| #039 | [M23 – Bedingte Schritte und Abschnitte](039-bedingte-schritte.md) | erledigt | v0.3.0 | 12 h | 5 h 20 min |
|
||||
| #040 | [M24 – Vier-Augen-Freigabe](040-vier-augen-freigabe.md) | offen | v0.3.0 | 8 h | – |
|
||||
| #041 | [M25 – PDF-Übergabeprotokoll mit Unterschrift](041-pdf-uebergabeprotokoll.md) | offen | v0.3.0 | 8 h | – |
|
||||
| #042 | [M26 – Weitere Schritt-Typen](042-weitere-schritt-typen.md) | offen | v0.3.0 | 6 h | – |
|
||||
| | **Summe** | | | **272 h** | **73 h 55 min** |
|
||||
| | **Summe** | | | **272 h** | **79 h 15 min** |
|
||||
|
||||
Reference in New Issue
Block a user