The Pass-2 topological level assignment in cmdPhasePlanIndex dequeued its Kahn's-algorithm queue with Array.shift(), which is O(n) per call in V8, so the BFS was O(V^2) and slowed superlinearly on deep queues (wide fan-in plan graphs). Extract the traversal into a pure, exported computeDependencyLevels (rawPlans, planMap, canonicalToId) and dequeue via a head index (queue[head++]) -> O(V+E). Behavior is identical: same FIFO order, same longest-path levels, same visited-count cycle detection. A complexity-contract comment above the loop documents why shift() must not be reintroduced. Adds tests/phase-dependency-levels.test.cjs with deterministic behavior and edge-case coverage (linear chain, diamond longest-path, independent set, cycle, canonical-prefix resolution, empty, self-loop, duplicate edge, external dep). A timing-based complexity guard was intentionally omitted: the O(V+E) Map-build constant dilutes the O(V^2) signal until impractical N (~1e6), so an empirical guard is inherently flaky on contended CI — the contract is enforced by the inline comment and correctness tests instead. Fixes #307 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7.6 KiB
7.6 KiB