fix(n8n): seed reachability from independent main-subgraph heads (closes #57)#58
Open
hatyibei wants to merge 1 commit into
Open
fix(n8n): seed reachability from independent main-subgraph heads (closes #57)#58hatyibei wants to merge 1 commit into
hatyibei wants to merge 1 commit into
Conversation
n8n documents routinely bundle several independent flows in one file: a triggered main flow alongside manually-run fragments or sub-workflow bodies the author starts from an arbitrary node. Reachability was seeded only from trigger nodes, so every node of a non-triggered fragment was reported as unreachable_node — 125 of the 198 residual FPs after the earlier n8n fixes, e.g. the entire 38-node "Autonomous AI crawler" subgraph rooted at the incoming-edge-less "Set domain (URL)" (16 nodes, all FP). Fix: seed reachability from triggers PLUS the head of every independent main subgraph — a node with no incoming `main` edge but >=1 outgoing `main` edge (new entryRootIDs, replacing allTriggerNodeIDs). Fully-detached nodes (no in, no out) are NOT roots, so genuine dead nodes still surface as unreachable_node. ai_* edges are excluded: the rule already treats them as undirected, and a sub-resource (model/memory/tool) has only ai_* edges so it never becomes a spurious root. Measured on 308 real workflows (enescingoz/awesome-n8n-templates), unreachable_node: 198 -> 32 (this fix -166); across all four n8n fixes 973 -> 32 (-96.7%). Residual 32 = 6 minor FPs + 26 genuinely-detached dead nodes (true positives). "Autonomous AI crawler": 16 -> 0. Test: IndependentMainSubgraphRoot (an independent subgraph head is a virtual-root child; a fully-detached node is not). go test ./domain/rules/... ./infrastructure/parser/... green. Closes #57. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #57.
Fourth and final
unreachable_nodeFP pattern from the n8n dogfood loop: nodes on the main data-flow flagged unreachable because they head an independent subgraph the trigger can't reach.Root cause
n8n bundles several independent flows in one document — a triggered main flow alongside manually-run fragments or sub-workflow bodies the author starts from an arbitrary node. Reachability was seeded only from trigger nodes, so every node of a non-triggered fragment was reported unreachable.
Representative case —
Autonomous AI crawler.json(38 nodes, 0 disabled): the crawler subgraph is rooted atSet domain (URL)/Set domain (text), which have no incomingmainedge. From there 16 nodes (Get website,Aggregate URLs,Convert HTML to Markdown, …) cascaded to unreachable.Fix
Seed reachability from triggers PLUS the head of every independent main subgraph — a node with no incoming
mainedge but ≥1 outgoingmainedge (entryRootIDs, replacingallTriggerNodeIDs).unreachable_node. Detection power preserved.ai_*edges are excluded: the reachability rule already treats them as undirected, and a sub-resource (model/memory/tool) has onlyai_*edges, so it never becomes a spurious root.Impact (308 real workflows)
Across all four n8n fixes: 973 → 32 (−96.7%).
Autonomous AI crawler: 16 → 0.Residual 32 = 6 minor FPs (noOp/agent, separate small pattern) + 26 genuinely-detached dead nodes (true positives — nodes placed but never wired). The FP tail is essentially gone; what remains is mostly correct.
Tests
TestN8nParser_IndependentMainSubgraphRoot: an independent subgraph head is wired from the virtual root; a fully-detached node is not.go test ./domain/rules/... ./infrastructure/parser/...green.🤖 Generated with Claude Code