You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
extractKeyMap (src/engine.ts) builds the pattern→key map by walking the schema's literal properties and items only. It does not resolve $ref or follow recursive schema definitions. So for a recursively-shaped tree — a node whose children array has the same keyed shape as the node — keying is only registered as deep as the schema is written out literally. Past that depth, arrays fall back to index-zip diffing and items()/diff() lose identity addressing silently (no error, just a wrong/cascading diff).
Example
A natural way to express an arbitrary-depth tree is a $ref:
extractKeyMap registers nothing for children (it never enters the $ref), so editing a grandchild produces an index-zip cascade instead of one identity-attributed op.
Today you must either:
write x-key literally as deep as you ever nest ($['nodes'][*]['children'][*]['children'][*]…), which is impossible for unbounded depth; or
pass { key } inline on each items() / diff() call at the level you're reading (this works, because inline key resolves against the concrete path at call time).
Possible directions
Resolve $ref against $defs/# when walking the schema (handle self-reference without infinite recursion — detect cycles and register the key pattern as repeating).
Or: support a recursive/wildcard pattern entry in the keyMap (e.g. a pattern that matches children at any depth) so a self-referential shape needs one registration.
At minimum: document the limitation and the inline-key workaround in docs/engine.md.
Origin: surfaced while building a recursive tree editor on items() (branch claude/practical-shannon-jr19ie). Deliberately not addressed there — items()/diff() work fine with inline { key } per call.
Activity