CycleDetector
Detects guaranteed-infinite mapping cycles at compile time.
An edge is only included in cycle detection when it traverses a field that is:
non-nullable (so the value MUST exist — nullable is always break-able at runtime)
not a collection (a collection can be empty, so recursion terminates)
Examples:
A -> B -> Athrough non-null fields → ERROR (cycle)Cat(parent: Cat?)→ OK (nullable breaks the cycle)Node(children: List<Node>)→ OK (collection breaks the cycle)