--- type: Reference status: ACTIVE owner: Lead Architect date: 2026-04-21 --- # Wizard‑DSL & Orchestrator – Referenz ## Ziel Deklarative Beschreibung von Wizard‑Flows als Graph (Steps, Guards, Transitions) mit klaren Side‑Effects und Offline‑Draft‑Unterstützung. ## Kern‑Interfaces (Skizze) ```kotlin interface StepId data class WizardContext( val origin: AppScreen, val role: String?, val isOnline: Boolean, val stats: MasterdataStats? ) data class WizardState( val current: S, val history: List = emptyList(), val acc: A, val errors: List = emptyList() ) typealias Guard = (WizardContext, A) -> Boolean data class Transition(val target: S, val guard: Guard? = null, val id: String) interface StepEffects { suspend fun onEnter(ctx: WizardContext, state: WizardState) {} suspend fun onLeave(ctx: WizardContext, state: WizardState) {} suspend fun onComplete(ctx: WizardContext, state: WizardState) {} } ``` ## DSL (Skizze) ```kotlin class FlowBuilder { fun step(id: S, block: StepBuilder.() -> Unit) { /* … */ } } class StepBuilder { fun onEnter(block: suspend (WizardContext, WizardState) -> Unit) { /* … */ } fun whenGuard(id: String, g: Guard, go: S) { /* … */ } fun otherwise(go: S) { /* … */ } } fun flow(start: S, build: FlowBuilder.() -> Unit): WizardRuntime { /* … */ } ``` ## Beispiel – Event‑Flow (Auszug) ```kotlin sealed interface EventStep: StepId { data object ZnsCheck: EventStep data object VeranstalterSelection: EventStep data object AnsprechpersonMapping: EventStep data object MetaData: EventStep data object TurnierAnlage: EventStep data object Summary: EventStep } data class EventAcc( val veranstalterId: Uuid? = null, val veranstalterNr: String = "", val veranstalterName: String = "", val ansprechpersonSatznr: String = "", val name: String = "", val ort: String = "", val start: LocalDate? = null, val end: LocalDate? = null, val turniere: List = emptyList() ) object EventGuards { val hasZns: Guard = { ctx, _ -> (ctx.stats?.vereinCount ?: 0) > 0 } val needsContactPerson: Guard = { _, acc -> acc.veranstalterId == null || acc.veranstalterNr.startsWith("ORG-") } } val EventFlow = flow(start = EventStep.ZnsCheck) { step(EventStep.ZnsCheck) { onEnter { ctx, _ -> /* prefetch stats */ } whenGuard("hasZns", EventGuards.hasZns, go = EventStep.VeranstalterSelection) otherwise(go = EventStep.VeranstalterSelection) } step(EventStep.VeranstalterSelection) { whenGuard("needsContact", EventGuards.needsContactPerson, go = EventStep.AnsprechpersonMapping) otherwise(go = EventStep.MetaData) } } ``` ## DevTools - Strukturierte Logs je Transition (from, to, guard-id, result, duration). - Graph‑Export (DOT/PlantUML) aus der DSL für Doku & Reviews. ## Tests (Empfehlungen) - Unit: Guards (100% Branch‑Abdeckung), Runtime‑History. - Property: Resume‑Determinismus (Draft → korrekter Step). - Snapshot: Compose‑Panels mit Beispielkontexten. ## Verweise - ADR‑0025 Orchestrator · ADR‑0026 Validation‑Policy · ADR‑0027 Draft‑Domain & Delta‑Sync - Roadmap: `docs/01_Architecture/MASTER_ROADMAP.md#3-initiative-wizard-orchestrator--offline-drafts-q2q3-2026`