@startuml title A/B trial boot and recovery skinparam shadowing false skinparam monochrome true state "A confirmed" as A state "Prepare B\nA remains the normal boot choice" as Preparing state "B prepared and verified" as Prepared state "B trial pending\nSaved target and attempt limit" as Pending state "B trial running\nUnconfirmed" as Trial state "B confirmed" as Confirmed state "Recovery to A pending" as Recovering state "A recovery running" as Recovery state "A recovery checked" as Recovered state "Separate recovery required" as Failed [*] --> A A --> Preparing : begin installation Preparing --> Preparing : reset during preparation; boot A\nB is not eligible for trial Preparing --> A : abandon incomplete or failed preparation Preparing --> Prepared : installation and verification complete Prepared --> Pending : save trial request through boot control Pending --> Trial : reset [attempts left > 0]; save attempts left - 1\nbefore handing control to B Trial --> Confirmed : local checks pass within time limit;\nsave confirmation Trial --> Recovering : local checks fail; save recovery request Trial --> Pending : reset before confirmation\n(power loss or covered watchdog) Pending --> Recovering : reset; no attempts left Recovering --> Recovery : boot control selects A on reset Recovery --> Recovered : local recovery checks pass;\nsave outcome Recovery --> Failed : recovery checks fail or startup fails\n(platform recovery policy) Confirmed --> [*] Recovered --> [*] Failed --> [*] note right of Pending Boot state is outside A and B. Attempts are consumed before starting B. Invalid records require a platform-defined recovery path, never implicit confirmation. end note note right of Recovery A must still be compatible with shared data. Do not endlessly alternate failed systems. end note legend bottom Preparation interruption assumes the installer preserves A and boot state. State transitions assume valid durable records; torn writes need platform testing. Checks and recovery are local; reports wait for connectivity. endlegend @enduml