You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(cycles): classify cycles whose only closing edges are speculative
Cycle detection (codegraph cycles / check --cycles / manifesto noCycles)
previously treated every call edge identically, so a cycle held together
only by a low-confidence dynamic-dispatch guess (dynamic = 1 AND
confidence < 1) was reported the same as one backed entirely by confirmed
static edges. A single fabricated resolver edge could therefore surface
as a "confirmed" architectural cycle and fail CI.
findCycles() now runs Tarjan a second time on the edge set with
speculative edges removed and diffs the two SCC decompositions — any
cycle that only exists in the full run is marked `speculative: true`
instead of `confirmed`. Threads `dynamic` through getCallEdges (both the
SQLite and native/rusqlite paths) so the classifier has the metadata it
needs; the SCC primitive itself (JS and native) is unchanged and reused
for both passes, so no engine can diverge on the classification.
`codegraph cycles` gains `--exclude-speculative` and annotates
speculative cycles in table/JSON output. `check --cycles` and the
manifesto `noCycles` rule ignore speculative-only cycles by default via
the new `check.excludeSpeculativeCycles` config default.
Copy file name to clipboardExpand all lines: docs/guides/configuration.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -315,6 +315,7 @@ Toggles for the lightweight `codegraph check` command (separate from manifesto).
315
315
| Key | Type | Default | Purpose |
316
316
|-----|------|---------|---------|
317
317
|`cycles`|`boolean`|`true`| Fail if cycles exist. |
318
+
|`excludeSpeculativeCycles`|`boolean`|`true`| Don't fail on cycles whose only closing edges are low-confidence dynamic calls (`dynamic = 1 AND confidence < 1`) — resolver guesses rather than confirmed structural dependencies. Also honored by the manifesto `noCycles` rule. |
318
319
|`blastRadius`|`number \| null`|`null`| Fail if any function's caller count exceeds this. |
319
320
|`signatures`|`boolean`|`true`| Warn on signature changes in the diff. |
320
321
|`boundaries`|`boolean`|`true`| Honor the `manifesto.boundaries` rules. |
0 commit comments