Expand description
Cycle-safe canonical-parent resolution, split out of spatial.rs (same
reason spatial_elevation.rs, spatial_invariant.rs and spatial_tree.rs
already are: stay under the module-size ratchet). Mirrors
packages/parser/src/spatial-hierarchy-canonical-parent.ts, which split
the same concern out of spatial-hierarchy-builder.ts for the same
reason.
Constants§
- CYCLE_
CHECK_ 🔒VISIT_ BUDGET - Upper bound on aggregate-graph node visits spent on back-edge cycle checks
for one upload. The check only runs for children named by MORE THAN ONE
IFCRELAGGREGATES(already malformed) and costs one descendant walk per such child - O(V+E) each - so a crafted upload with thousands of contested children could otherwise hold a blocking worker for O(C·(V+E)). Past the budget the resolver falls back to plain first-declared-wins and logs once. MirrorsCYCLE_CHECK_VISIT_BUDGETinpackages/parser/src/spatial-hierarchy-canonical-parent.ts.
Functions§
- aggregated_
descendants 🔒 - Aggregated descendants of
child_id(transitive, forwardIFCRELAGGREGATES), charged againstbudget.Nonewhen the budget ran out mid-walk: a partial set must not be used, since a missing descendant reads as “no cycle” - the wrong side to err on. Used only to disqualify a tied candidate parent that would close a cycle back through the child itself (#4246: the STEP-authoring-tool mistake of declaring an aggregation pair in both directions, or an indirect A -> B -> C -> A chain) - the common case (one candidate) never calls this. Mirrorspackages/parser/src/spatial-hierarchy-canonical-parent.ts’saggregatedDescendants. - resolve_
aggregate_ 🔒canonical_ parents - Resolve each spatial child’s ONE canonical
IFCRELAGGREGATESparent, globally, from the raw relationship list. Plain first-declared-wins, EXCEPT that a candidate closing a cycle back through the child is skipped first (#4246) - a mutual or longer aggregation back-edge (a STEP-authoring-tool mistake: a parent/child pair declared in both directions) cannot win a tie against a candidate that doesn’t orphan the child’s own subtree from itself. Falls through to plain first-declared if every candidate closes a cycle, so a child is never left without a parent. Mirrorspackages/parser/src/spatial-hierarchy-canonical-parent.ts’scomputeCanonicalParent. - resolve_
aggregate_ 🔒canonical_ parents_ with_ budget