Detects a dependency cycle using an iterative depth-first search.
Iterative rather than recursive on purpose: a deep or adversarial graph would blow the call stack,
and this runs on submitted (potentially LLM-authored) input.
Nodes referenced only by edges are still traversed, so a cycle among unknown ids is still caught —
validation of unresolvable references is a separate concern (see FindUnknownDependencyRefs).
Detects a dependency cycle using an iterative depth-first search.
Iterative rather than recursive on purpose: a deep or adversarial graph would blow the call stack, and this runs on submitted (potentially LLM-authored) input.
Nodes referenced only by edges are still traversed, so a cycle among unknown ids is still caught — validation of unresolvable references is a separate concern (see FindUnknownDependencyRefs).