What it means
A leaf identifier is the identifier node in an expression that directly reads a value. It is the immediate property access — the first (and direct) read on whatever context it finds itself on. In a + b, both a and b are leaf identifiers: each is read directly from the model. In user.profile.name, name is the leaf identifier: it is the direct read on user.profile.
By default, rs-x watches the leaf identifier for direct value replacement. For user.profile.name, the watch is on the 'name' key of user.profile; only assigning user.profile.name = 'Bob' fires reevaluation. Changing a different property like user.profile.role does not. user.profile.name is a member expression; the segments user and user.profile are also watched for reference replacement. Replacing either re-attaches the watch, and if the resolved value of name has changed as a result, a change event is emitted.
When the identifier's value is an Array, Map, Set, or Date, rs-x automatically wraps it in a Proxy. No watch rule is needed: mutations like array.push() or map.set() fire the expression the same way a direct assignment does.
When you need to observe mutations inside the identifier's value, pass an IIndexWatchRule as the second argument: rsx('expr')(model, watchRule). The rule's test(index, target)method is called at the leaf level to decide which sub-properties of the identifier's value should be observed. Returning true for a sub-property key installs an observer for it; returning false leaves it unwatched.