The edit log
The edit log is the only state of an editing session. It is a JSON document: the source descriptor, the plugin versions that wrote it, optional assets, and an append-only list of operations.
json
{
"version": 1,
"source": { "id": "IMG_0042", "width": 6000, "height": 4000, "hash": "9f3e…" },
"plugins": { "crop": 1, "finetune": 1, "filter": 1 },
"ops": [
{ "type": "finetune.set", "id": "01J…", "params": { "brightness": 0.1 } },
{ "type": "crop.set", "id": "01K…", "rotation": 0.0872, "rect": { "x": 0.1, "y": 0.1, "width": 0.8, "height": 0.8 } }
]
}A pure reducer folds ops[0..index) into a document (what the UI binds to) and a render plan (what the core executes). Undo, redo and time travel are prefix slices; nothing is ever re-encoded.
Every op is validated at runtime with the plugin's schema. Unknown plugins are rejected. Old logs migrate through migrate(fromVersion, op).
Ops carry an id and an optional at. Neither affects pixels: they are ignored by the renderer and by the server's job key, so retries with new ids still hit the cache.