Review follow-ups on f12ba2f9:
- An instance whose AreaId points at an area outside the supplied list was
silently dropped; it now surfaces at the root, mirroring the orphaned-area
rule, and stays filterable.
- InstanceTreeNode.Children is an IReadOnlyList over a private backing list,
composed by the builder through an internal AddChild — the record no longer
hands callers a mutable list.
- Extra tests: unknown-area instance (root + filterable), 3-level nesting,
a ParentAreaId cycle that must neither loop nor throw, and a filter that
matches instance names only (an area name match alone does not keep it).
Claude-Session: https://claude.ai/code/session_01NcMG6xXdsJbmD2wYAgkK29
Task 1 of the Instance Picker plan (docs/plans/2026-09-08-instance-picker.md).
Pure, DI-free builder that nests a site's areas by ParentAreaId and hangs each
area's instances beneath it, mirroring Topology's ordering (child areas first,
then that level's instances; OrdinalIgnoreCase sorts) with unparented instances
at the root after the root areas. Orphaned areas become roots, a case-insensitive
filter keeps matching instances plus their ancestors and drops empty branches,
and a ParentAreaId cycle can never recurse forever.
Claude-Session: https://claude.ai/code/session_01NcMG6xXdsJbmD2wYAgkK29