The three classes
Everything is keyed on
id, which is your localId namespaced with your adapter id. Nothing
is matched by position, model, label or proximity.
What is compared
exactly
A
type that changed for the same id reads as a replacement, and a restore refuses it
rather than attempting one.within 0.01 source units
within 0.01 degrees, wrapped
Angles are compared as a wrapped delta, so 359.999 and 0.001 are the same angle rather than
a full rotation apart.
per key
Strings and booleans compare exactly. Numbers compare within the same small epsilon, so
a float that lost precision through JSON is not reported as a change for ever after. A
change of Lua type is a change.
not compared
bounds is spatial metadata used for placement. label is for humans. Neither is diffed
for classification, so renaming a label does not create a change row.Why determinism matters more than it sounds
Two consecutive captures of an unchanged world must produce identical records. If they do not, every diff reports every object as changed, for ever. The consequences compound:- the history stops being readable, because every entry is noise;
- a restore plan against your domain becomes enormous, because every object needs an operation;
- deployment reports permanent production drift, and asks for an acknowledgement every single run.
Things that break determinism
Iteration order
If yourlocalId comes from a durable key, iteration order does not matter: the diff is keyed
on id, not on array position.
If your ids depend on iteration order at all, they are not identities. Fix that first.
Refusing rather than guessing
Where identity cannot be established, Blueprints does not fall back on a heuristic. It reports one of a closed set of reasons, and the set is closed precisely so it cannot grow a “probably the same object” entry:
Your part in that is honest scope declaration. An adapter that declares
persistent when it
means session converts an honest “we cannot match these” into a silent wrong match.