"Each capability prepares a serializable change receipt before acting. The receipt records both the intended change and its observed outcome." — Tinker architecture
Prepare: Describe the World You Are About to Change
prepare(input) runs before anything happens and returns a list of ChangePlan values, one per thing that could change. Each plan carries a key that names the target uniquely (for an app, its bundle ID, process ID and launch time), a payload holding everything apply and undo will need, and a needsApply flag. The flag is the quiet hero of the design: a plan whose target is already in the desired state is returned with needsApply: false. It is still described — the engine needs to know it exists, as you will see with shared ownership — but it is never applied and never gets a receipt of its own. (If Tinker already holds a receipt for that same target from another preset, the new owner joins it instead — track 3.)
Prepare is also where a capability refuses. Malformed input, an empty list, a standing condition that forbids the action right now — all of these throw from prepare, and because the engine prepares every step of a preset before it touches anything, one refusal anywhere means nothing happens anywhere.
Apply: One Planned Piece at a Time
The engine then walks the plans. For each one that needs applying it first writes a prepared receipt to the journal, then calls apply(payload), then rewrites the receipt as applied. A child's apply receives a single payload, never the whole list, so it cannot quietly do more than one planned change per call. If apply throws, the engine stops the preset and restores whatever it had already confirmed for that owner.
Undo: Take Back Exactly That Change
undo(payload) receives the payload saved in the receipt — not today's version of the preset. That matters: if Dad edits the editing preset while it is active, restoring it must still undo what was actually done, not what the edited list now says. Undo returns one of two results. .restored means it reversed the change. .noLongerApplicable means there was nothing left to reverse — the app quit, or someone already showed it by hand — and that is a success, not an error: the receipt is cleared either way. Restoration walks a preset's receipts in reverse order, the way you take off layers you put on.
The Shape of the Whole
Put together, the lifecycle reads like a careful person's checklist: write down what you are going to touch; for each item, note that you are about to touch it, touch it, note that you did; to undo, read your notes, not your intentions. The next lessons show the one child that implements it and the one exception the engine carves out of it.