"Persist a prepared receipt before each change. Mark applied only after the OS reports hidden." — Tinker architecture, hide invariant 3
The Order That Makes Crashes Honest
There are only two possible orders for "change the screen" and "write it down". Effect first, then write: if Tinker dies between them, an app is hidden and the disk has no record of it — after relaunch nobody owns it and nothing will ever restore it. Write first, then effect: if Tinker dies between them, the disk says "about to hide Eagle" and Eagle may or may not be hidden. The second failure is recoverable — there is a record, and it is honest about what it does not know. The first is not. So Tinker always writes first. Databases call the same idea write-ahead logging; Tinker's version is small enough to read in one sitting.
What the Journal Holds
The journal is one JSON document, journal.json, in Tinker's own data directory outside the source checkout. It has a schema version, an active set naming every owner that is currently applied (such as preset/edit), and a list of ChangeReceipts. Each receipt records its key, the capability that made it, the payload undo will need, its set of owners, its phase, and an optional error message. Nothing else — no timestamps of Watchfire readings, no UI state. A journal that only describes ownership is a journal that can be checked for consistency on every load.
Every Mutation Is a Whole-Document Write
The engine never edits the journal in place. It copies the current journal, changes the copy, and hands the whole copy to persist, which writes it through CwkKit's LocalDocumentStore. That store writes atomically — a temporary file renamed over the old one — so a crash mid-write leaves either the old document or the new one, never half of each. Only after the write succeeds does the engine adopt the copy as its in-memory journal. Memory never runs ahead of disk.
A Failed Write Disables the Engine
If a write fails — a full disk, a permissions change — persist records the failure as the engine's fault and rethrows. From then on every apply is refused with that fault as the reason. An actuator that cannot record what it is about to do must not do it. Tinker's tests include a persistence-failure case that checks exactly this: the effect never happens when the receipt could not be saved.