"A crash or failed post-write cannot prove who changed the OS state. Preserve the prepared entry rather than unhide somebody else's app." — a comment in Tinker's engine
No Half-Applied Presets
A preset is a single request from Dad's point of view: "editing mode". If the third of four apps refuses to hide, leaving the first two hidden would be a state nobody asked for — half of an editing mode nobody asked for. So the engine wraps the whole apply loop in a do/catch. Whatever goes wrong inside — a thrown refusal, an unconfirmed hide, a persistence failure — the catch calls the same restore routine that a normal "Editing done" would, for the same owner, and then rethrows the original error so the command still reports why it failed.
Rollback Uses the Ordinary Restore
There is no special rollback code path. The catch calls restoreImpl(id:), which walks this owner's receipts newest first: shared receipts lose this owner, applied receipts are undone and removed, and prepared receipts — including the one that just failed, if it is uncertain — are left in place and reported. Reusing the restore path means rollback has exactly the same guarantees as a normal finish, and is tested by the same cases. If the failing step proved it never reached the OS, its receipt was already dropped and the rollback leaves the journal clean; if not, the owner stays active because the uncertain record still names it.
Errors Are Collected, Not Short-Circuited
Restore does not stop at the first problem. If one app's unhide fails, the next receipt is still attempted; each error message is appended to a list, and only at the end is a single error thrown carrying all of them. A restore that gave up at the first failure would strand every change after it — the opposite of what a restore is for.
Emergency Release Interrupts From Outside
There is a second way an apply loop ends early: Dad chooses Stop and restore everything while it is running. releaseAll() sets stopped first, then waits for the running action to finish. The apply loop checks stopped before each change and throws "Emergency release requested." when it sees it, which sends it into its own rollback. Then release-all walks every remaining active owner and restores it. Tinker's tests freeze a hide mid-flight, request release, and check that the second app was never hidden and the first was restored — with the order of OS calls asserted, not merely the end state.