@path58/n8n-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/AGENT_INSTALL.md +223 -0
  2. package/CHANGELOG.md +38 -0
  3. package/LICENSE +21 -0
  4. package/README.md +187 -0
  5. package/dist/autofix/suggestion-fixers/deprecated-node-fixer.js +465 -0
  6. package/dist/autofix/suggestion-fixers/deprecated-node-fixer.js.map +1 -0
  7. package/dist/autofix/suggestion-fixers/fixer-registry.js +495 -0
  8. package/dist/autofix/suggestion-fixers/fixer-registry.js.map +1 -0
  9. package/dist/autofix/suggestion-fixers/l1-structure-fixer.js +639 -0
  10. package/dist/autofix/suggestion-fixers/l1-structure-fixer.js.map +1 -0
  11. package/dist/autofix/suggestion-fixers/l4-connection-fixer.js +449 -0
  12. package/dist/autofix/suggestion-fixers/l4-connection-fixer.js.map +1 -0
  13. package/dist/autofix/suggestion-fixers/l5-parameter-fixer.js +575 -0
  14. package/dist/autofix/suggestion-fixers/l5-parameter-fixer.js.map +1 -0
  15. package/dist/autofix/suggestion-fixers/l5-typeversion-fixer.js +431 -0
  16. package/dist/autofix/suggestion-fixers/l5-typeversion-fixer.js.map +1 -0
  17. package/dist/autofix/suggestion-fixers/l5-webhook-path-fixer.js +356 -0
  18. package/dist/autofix/suggestion-fixers/l5-webhook-path-fixer.js.map +1 -0
  19. package/dist/autofix/suggestion-fixers/l6-ai-tool-variant-fixer.js +618 -0
  20. package/dist/autofix/suggestion-fixers/l6-ai-tool-variant-fixer.js.map +1 -0
  21. package/dist/autofix/suggestion-fixers/l6-pattern-fixer.js +1475 -0
  22. package/dist/autofix/suggestion-fixers/l6-pattern-fixer.js.map +1 -0
  23. package/dist/autofix/suggestion-fixers/llm-fixer.js +716 -0
  24. package/dist/autofix/suggestion-fixers/llm-fixer.js.map +1 -0
  25. package/dist/autofix/suggestion-fixers/missing-credential-fixer.js +336 -0
  26. package/dist/autofix/suggestion-fixers/missing-credential-fixer.js.map +1 -0
  27. package/dist/autofix/suggestion-fixers/types.js +29 -0
  28. package/dist/autofix/suggestion-fixers/types.js.map +1 -0
  29. package/dist/autofix/suggestion-fixers/typo-fixer.js +197 -0
  30. package/dist/autofix/suggestion-fixers/typo-fixer.js.map +1 -0
  31. package/dist/classification/certification-engine.js +208 -0
  32. package/dist/classification/certification-engine.js.map +1 -0
  33. package/dist/classification/feedback-collector.js +516 -0
  34. package/dist/classification/feedback-collector.js.map +1 -0
  35. package/dist/classification/l5-parameter-analyzer.js +670 -0
  36. package/dist/classification/l5-parameter-analyzer.js.map +1 -0
  37. package/dist/classification/l6-graph-analyzer.js +613 -0
  38. package/dist/classification/l6-graph-analyzer.js.map +1 -0
  39. package/dist/classification/severity-classifier.js +237 -0
  40. package/dist/classification/severity-classifier.js.map +1 -0
  41. package/dist/config/env.js +280 -0
  42. package/dist/config/env.js.map +1 -0
  43. package/dist/config/env.schema.js +234 -0
  44. package/dist/config/env.schema.js.map +1 -0
  45. package/dist/config/scraperEnv.js +55 -0
  46. package/dist/config/scraperEnv.js.map +1 -0
  47. package/dist/db/postgresClient.js +38 -0
  48. package/dist/db/postgresClient.js.map +1 -0
  49. package/dist/db/scraperDb.js +6 -0
  50. package/dist/db/scraperDb.js.map +1 -0
  51. package/dist/db/scraperPostgresClient.js +118 -0
  52. package/dist/db/scraperPostgresClient.js.map +1 -0
  53. package/dist/db/validationRepository.js +55 -0
  54. package/dist/db/validationRepository.js.map +1 -0
  55. package/dist/db/validatorPostgresClient.js +248 -0
  56. package/dist/db/validatorPostgresClient.js.map +1 -0
  57. package/dist/db/workflowInstanceMappingRepository.js +128 -0
  58. package/dist/db/workflowInstanceMappingRepository.js.map +1 -0
  59. package/dist/errors/AppError.js +156 -0
  60. package/dist/errors/AppError.js.map +1 -0
  61. package/dist/errors/index.js +7 -0
  62. package/dist/errors/index.js.map +1 -0
  63. package/dist/factory/error-to-problem-mappers.js +385 -0
  64. package/dist/factory/error-to-problem-mappers.js.map +1 -0
  65. package/dist/factory/gap-recorder.js +260 -0
  66. package/dist/factory/gap-recorder.js.map +1 -0
  67. package/dist/factory/problem-recorder.js +94 -0
  68. package/dist/factory/problem-recorder.js.map +1 -0
  69. package/dist/factory/warning-to-gap-mappers.js +493 -0
  70. package/dist/factory/warning-to-gap-mappers.js.map +1 -0
  71. package/dist/factory/workflow-normalizer.js +247 -0
  72. package/dist/factory/workflow-normalizer.js.map +1 -0
  73. package/dist/mcp/adapters/catalog.js +13 -0
  74. package/dist/mcp/adapters/catalog.js.map +1 -0
  75. package/dist/mcp/adapters/index.js +36 -0
  76. package/dist/mcp/adapters/index.js.map +1 -0
  77. package/dist/mcp/adapters/supabase-catalog.js +467 -0
  78. package/dist/mcp/adapters/supabase-catalog.js.map +1 -0
  79. package/dist/mcp/adapters/test-catalog-adapter.js +100 -0
  80. package/dist/mcp/adapters/test-catalog-adapter.js.map +1 -0
  81. package/dist/mcp/adapters/validation.js +258 -0
  82. package/dist/mcp/adapters/validation.js.map +1 -0
  83. package/dist/mcp/build-email-workflow.js +113 -0
  84. package/dist/mcp/build-email-workflow.js.map +1 -0
  85. package/dist/mcp/config.js +22 -0
  86. package/dist/mcp/config.js.map +1 -0
  87. package/dist/mcp/formatters/errors.js +217 -0
  88. package/dist/mcp/formatters/errors.js.map +1 -0
  89. package/dist/mcp/formatters/index.js +12 -0
  90. package/dist/mcp/formatters/index.js.map +1 -0
  91. package/dist/mcp/formatters/response.js +141 -0
  92. package/dist/mcp/formatters/response.js.map +1 -0
  93. package/dist/mcp/quick-test.js +33 -0
  94. package/dist/mcp/quick-test.js.map +1 -0
  95. package/dist/mcp/server.js +70 -0
  96. package/dist/mcp/server.js.map +1 -0
  97. package/dist/mcp/test-mcp-error.js +81 -0
  98. package/dist/mcp/test-mcp-error.js.map +1 -0
  99. package/dist/mcp/test-mcp.js +80 -0
  100. package/dist/mcp/test-mcp.js.map +1 -0
  101. package/dist/mcp/tools/fixes/expression-fixes.js +166 -0
  102. package/dist/mcp/tools/fixes/expression-fixes.js.map +1 -0
  103. package/dist/mcp/tools/fixes/flow-fixes.js +155 -0
  104. package/dist/mcp/tools/fixes/flow-fixes.js.map +1 -0
  105. package/dist/mcp/tools/fixes/index.js +91 -0
  106. package/dist/mcp/tools/fixes/index.js.map +1 -0
  107. package/dist/mcp/tools/fixes/node-fixes.js +233 -0
  108. package/dist/mcp/tools/fixes/node-fixes.js.map +1 -0
  109. package/dist/mcp/tools/fixes/parameter-fixes.js +277 -0
  110. package/dist/mcp/tools/fixes/parameter-fixes.js.map +1 -0
  111. package/dist/mcp/tools/fixes/types.js +10 -0
  112. package/dist/mcp/tools/fixes/types.js.map +1 -0
  113. package/dist/mcp/tools/handlers/check-parameter.js +300 -0
  114. package/dist/mcp/tools/handlers/check-parameter.js.map +1 -0
  115. package/dist/mcp/tools/handlers/find-similar-pattern.js +121 -0
  116. package/dist/mcp/tools/handlers/find-similar-pattern.js.map +1 -0
  117. package/dist/mcp/tools/handlers/get-node-info.js +131 -0
  118. package/dist/mcp/tools/handlers/get-node-info.js.map +1 -0
  119. package/dist/mcp/tools/handlers/get-operation-schema.js +141 -0
  120. package/dist/mcp/tools/handlers/get-operation-schema.js.map +1 -0
  121. package/dist/mcp/tools/handlers/list-nodes.js +126 -0
  122. package/dist/mcp/tools/handlers/list-nodes.js.map +1 -0
  123. package/dist/mcp/tools/handlers/list-operations.js +138 -0
  124. package/dist/mcp/tools/handlers/list-operations.js.map +1 -0
  125. package/dist/mcp/tools/handlers/suggest-fix.js +120 -0
  126. package/dist/mcp/tools/handlers/suggest-fix.js.map +1 -0
  127. package/dist/mcp/tools/handlers/validate-workflow.js +92 -0
  128. package/dist/mcp/tools/handlers/validate-workflow.js.map +1 -0
  129. package/dist/mcp/tools/index.js +190 -0
  130. package/dist/mcp/tools/index.js.map +1 -0
  131. package/dist/mcp/tools/schemas.js +195 -0
  132. package/dist/mcp/tools/schemas.js.map +1 -0
  133. package/dist/mcp/tools/validate.js +95 -0
  134. package/dist/mcp/tools/validate.js.map +1 -0
  135. package/dist/mcp/types/mcp.js +7 -0
  136. package/dist/mcp/types/mcp.js.map +1 -0
  137. package/dist/mcp/utils/timeout.js +78 -0
  138. package/dist/mcp/utils/timeout.js.map +1 -0
  139. package/dist/services/BatchProcessor.js +433 -0
  140. package/dist/services/BatchProcessor.js.map +1 -0
  141. package/dist/services/CheckpointManager.js +281 -0
  142. package/dist/services/CheckpointManager.js.map +1 -0
  143. package/dist/services/CostCalculator.js +211 -0
  144. package/dist/services/CostCalculator.js.map +1 -0
  145. package/dist/services/EmbeddingCache.js +68 -0
  146. package/dist/services/EmbeddingCache.js.map +1 -0
  147. package/dist/services/EmbeddingService.js +143 -0
  148. package/dist/services/EmbeddingService.js.map +1 -0
  149. package/dist/services/RankingService.js +81 -0
  150. package/dist/services/RankingService.js.map +1 -0
  151. package/dist/services/RedisCache.js +376 -0
  152. package/dist/services/RedisCache.js.map +1 -0
  153. package/dist/services/RedisCatalogCache.js +680 -0
  154. package/dist/services/RedisCatalogCache.js.map +1 -0
  155. package/dist/services/ResumeManager.js +252 -0
  156. package/dist/services/ResumeManager.js.map +1 -0
  157. package/dist/services/SearchService.js +282 -0
  158. package/dist/services/SearchService.js.map +1 -0
  159. package/dist/services/SemanticCatalogSearch.js +405 -0
  160. package/dist/services/SemanticCatalogSearch.js.map +1 -0
  161. package/dist/services/ValidationCache.js +157 -0
  162. package/dist/services/ValidationCache.js.map +1 -0
  163. package/dist/services/WorkflowPipelineService.js +1997 -0
  164. package/dist/services/WorkflowPipelineService.js.map +1 -0
  165. package/dist/services/catalog/index.js +34 -0
  166. package/dist/services/catalog/index.js.map +1 -0
  167. package/dist/services/catalog/interfaces.js +17 -0
  168. package/dist/services/catalog/interfaces.js.map +1 -0
  169. package/dist/services/catalog/loaders.js +169 -0
  170. package/dist/services/catalog/loaders.js.map +1 -0
  171. package/dist/services/catalog/types.js +138 -0
  172. package/dist/services/catalog/types.js.map +1 -0
  173. package/dist/services/documentation-normalization/docUrlUtils.js +88 -0
  174. package/dist/services/documentation-normalization/docUrlUtils.js.map +1 -0
  175. package/dist/services/error-quality/ErrorQualityService.js +262 -0
  176. package/dist/services/error-quality/ErrorQualityService.js.map +1 -0
  177. package/dist/services/error-quality/analyzers/CredentialAnalyzer.js +260 -0
  178. package/dist/services/error-quality/analyzers/CredentialAnalyzer.js.map +1 -0
  179. package/dist/services/error-quality/analyzers/IssuePredictor.js +380 -0
  180. package/dist/services/error-quality/analyzers/IssuePredictor.js.map +1 -0
  181. package/dist/services/error-quality/analyzers/MockCoverageAnalyzer.js +267 -0
  182. package/dist/services/error-quality/analyzers/MockCoverageAnalyzer.js.map +1 -0
  183. package/dist/services/error-quality/data/ErrorPatternSeeder.js +963 -0
  184. package/dist/services/error-quality/data/ErrorPatternSeeder.js.map +1 -0
  185. package/dist/services/error-quality/index.js +25 -0
  186. package/dist/services/error-quality/index.js.map +1 -0
  187. package/dist/services/error-quality/reports/ReportGenerator.js +343 -0
  188. package/dist/services/error-quality/reports/ReportGenerator.js.map +1 -0
  189. package/dist/services/error-quality/taxonomy/ErrorTaxonomy.js +698 -0
  190. package/dist/services/error-quality/taxonomy/ErrorTaxonomy.js.map +1 -0
  191. package/dist/services/error-quality/types.js +11 -0
  192. package/dist/services/error-quality/types.js.map +1 -0
  193. package/dist/services/progress/ProgressTracker.js +288 -0
  194. package/dist/services/progress/ProgressTracker.js.map +1 -0
  195. package/dist/services/progress/formatters.js +122 -0
  196. package/dist/services/progress/formatters.js.map +1 -0
  197. package/dist/services/progress/index.js +36 -0
  198. package/dist/services/progress/index.js.map +1 -0
  199. package/dist/services/progress/types.js +7 -0
  200. package/dist/services/progress/types.js.map +1 -0
  201. package/dist/services/search/embeddingGenerator.js +112 -0
  202. package/dist/services/search/embeddingGenerator.js.map +1 -0
  203. package/dist/types/aiCapabilities.js +7 -0
  204. package/dist/types/aiCapabilities.js.map +1 -0
  205. package/dist/types/aiConfigSchema.js +7 -0
  206. package/dist/types/aiConfigSchema.js.map +1 -0
  207. package/dist/utils/bannerLogger.js +186 -0
  208. package/dist/utils/bannerLogger.js.map +1 -0
  209. package/dist/utils/bannerService.js +23 -0
  210. package/dist/utils/bannerService.js.map +1 -0
  211. package/dist/utils/bannerServiceAdapter.js +54 -0
  212. package/dist/utils/bannerServiceAdapter.js.map +1 -0
  213. package/dist/utils/batchLogger.js +171 -0
  214. package/dist/utils/batchLogger.js.map +1 -0
  215. package/dist/utils/bottomStickyBanner.js +239 -0
  216. package/dist/utils/bottomStickyBanner.js.map +1 -0
  217. package/dist/utils/credentialMatcher.js +206 -0
  218. package/dist/utils/credentialMatcher.js.map +1 -0
  219. package/dist/utils/credentialNormalizer.js +442 -0
  220. package/dist/utils/credentialNormalizer.js.map +1 -0
  221. package/dist/utils/integratedBannerLogger.js +59 -0
  222. package/dist/utils/integratedBannerLogger.js.map +1 -0
  223. package/dist/utils/n8nSourceGit.js +195 -0
  224. package/dist/utils/n8nSourceGit.js.map +1 -0
  225. package/dist/utils/nodeTypeNormalizer.js +131 -0
  226. package/dist/utils/nodeTypeNormalizer.js.map +1 -0
  227. package/dist/utils/openaiClient.js +397 -0
  228. package/dist/utils/openaiClient.js.map +1 -0
  229. package/dist/utils/productionLogger.js +16 -0
  230. package/dist/utils/productionLogger.js.map +1 -0
  231. package/dist/utils/progressBarBanner.js +132 -0
  232. package/dist/utils/progressBarBanner.js.map +1 -0
  233. package/dist/utils/scriptHeartbeat.js +117 -0
  234. package/dist/utils/scriptHeartbeat.js.map +1 -0
  235. package/dist/utils/scriptLogger.js +125 -0
  236. package/dist/utils/scriptLogger.js.map +1 -0
  237. package/dist/utils/scriptRunner.js +95 -0
  238. package/dist/utils/scriptRunner.js.map +1 -0
  239. package/dist/utils/scriptTimeout.js +128 -0
  240. package/dist/utils/scriptTimeout.js.map +1 -0
  241. package/dist/utils/scriptWrapper.js +219 -0
  242. package/dist/utils/scriptWrapper.js.map +1 -0
  243. package/dist/utils/stickyBanner.js +226 -0
  244. package/dist/utils/stickyBanner.js.map +1 -0
  245. package/dist/utils/terminalSpinner.js +97 -0
  246. package/dist/utils/terminalSpinner.js.map +1 -0
  247. package/dist/utils/threeLineBanner.js +427 -0
  248. package/dist/utils/threeLineBanner.js.map +1 -0
  249. package/dist/utils/validatorCheckpointManager.js +170 -0
  250. package/dist/utils/validatorCheckpointManager.js.map +1 -0
  251. package/dist/utils/validatorConnectionManager.js +124 -0
  252. package/dist/utils/validatorConnectionManager.js.map +1 -0
  253. package/dist/validation/catalog.js +56 -0
  254. package/dist/validation/catalog.js.map +1 -0
  255. package/dist/validation/config/deprecated-nodes.js +234 -0
  256. package/dist/validation/config/deprecated-nodes.js.map +1 -0
  257. package/dist/validation/config/l6-severity.js +227 -0
  258. package/dist/validation/config/l6-severity.js.map +1 -0
  259. package/dist/validation/config/terminal-nodes.js +132 -0
  260. package/dist/validation/config/terminal-nodes.js.map +1 -0
  261. package/dist/validation/config/unreachable-nodes.js +67 -0
  262. package/dist/validation/config/unreachable-nodes.js.map +1 -0
  263. package/dist/validation/core.js +47 -0
  264. package/dist/validation/core.js.map +1 -0
  265. package/dist/validation/docExtraction.js +12 -0
  266. package/dist/validation/docExtraction.js.map +1 -0
  267. package/dist/validation/dryRunMockRunner.js +128 -0
  268. package/dist/validation/dryRunMockRunner.js.map +1 -0
  269. package/dist/validation/fixtureEngine.js +61 -0
  270. package/dist/validation/fixtureEngine.js.map +1 -0
  271. package/dist/validation/index.js +15 -0
  272. package/dist/validation/index.js.map +1 -0
  273. package/dist/validation/k-levels/k2-blockers.js +222 -0
  274. package/dist/validation/k-levels/k2-blockers.js.map +1 -0
  275. package/dist/validation/l1-structure.js +296 -0
  276. package/dist/validation/l1-structure.js.map +1 -0
  277. package/dist/validation/l2-nodes.js +282 -0
  278. package/dist/validation/l2-nodes.js.map +1 -0
  279. package/dist/validation/l3-credentials.js +322 -0
  280. package/dist/validation/l3-credentials.js.map +1 -0
  281. package/dist/validation/l4-connections.js +698 -0
  282. package/dist/validation/l4-connections.js.map +1 -0
  283. package/dist/validation/l5-parameters.js +803 -0
  284. package/dist/validation/l5-parameters.js.map +1 -0
  285. package/dist/validation/l6-checks/ai-tool-variants.js +407 -0
  286. package/dist/validation/l6-checks/ai-tool-variants.js.map +1 -0
  287. package/dist/validation/l6-checks/catalog-checks.js +260 -0
  288. package/dist/validation/l6-checks/catalog-checks.js.map +1 -0
  289. package/dist/validation/l6-checks/data-contracts.js +197 -0
  290. package/dist/validation/l6-checks/data-contracts.js.map +1 -0
  291. package/dist/validation/l6-checks/deprecation.js +133 -0
  292. package/dist/validation/l6-checks/deprecation.js.map +1 -0
  293. package/dist/validation/l6-checks/error-handling.js +193 -0
  294. package/dist/validation/l6-checks/error-handling.js.map +1 -0
  295. package/dist/validation/l6-checks/expression-syntax.js +387 -0
  296. package/dist/validation/l6-checks/expression-syntax.js.map +1 -0
  297. package/dist/validation/l6-checks/flow-integrity.js +504 -0
  298. package/dist/validation/l6-checks/flow-integrity.js.map +1 -0
  299. package/dist/validation/l6-checks/index.js +106 -0
  300. package/dist/validation/l6-checks/index.js.map +1 -0
  301. package/dist/validation/l6-checks/loops.js +370 -0
  302. package/dist/validation/l6-checks/loops.js.map +1 -0
  303. package/dist/validation/l6-checks/performance.js +182 -0
  304. package/dist/validation/l6-checks/performance.js.map +1 -0
  305. package/dist/validation/l6-checks/security.js +273 -0
  306. package/dist/validation/l6-checks/security.js.map +1 -0
  307. package/dist/validation/l6-patterns.js +472 -0
  308. package/dist/validation/l6-patterns.js.map +1 -0
  309. package/dist/validation/mockLevelResolver.js +95 -0
  310. package/dist/validation/mockLevelResolver.js.map +1 -0
  311. package/dist/validation/n8nApiClient.js +21 -0
  312. package/dist/validation/n8nApiClient.js.map +1 -0
  313. package/dist/validation/n8nCli.js +87 -0
  314. package/dist/validation/n8nCli.js.map +1 -0
  315. package/dist/validation/types.js +8 -0
  316. package/dist/validation/types.js.map +1 -0
  317. package/dist/validation/usageStats.js +82 -0
  318. package/dist/validation/usageStats.js.map +1 -0
  319. package/package.json +274 -0
@@ -0,0 +1,370 @@
1
+ /**
2
+ * L6 Loop Detection Checks
3
+ *
4
+ * RAG-2.2.77: L6 New Pattern Checks
5
+ * Created: 2026-01-17
6
+ * Updated: 2026-01-22 (RAG-2.2.92.10: Add pattern detection for intentional loops)
7
+ *
8
+ * Validates workflow graph for circular references (infinite loops):
9
+ * - CIRCULAR_REFERENCE: Cycle detected in workflow graph
10
+ *
11
+ * Uses depth-first search (DFS) with recursion stack tracking
12
+ * to detect cycles in the directed graph of workflow connections.
13
+ *
14
+ * RAG-2.2.92.10: Now applies the same pattern detection logic as L4 to filter out
15
+ * intentional iteration patterns (879 L6_CIRCULAR_REFERENCE warnings were false positives).
16
+ */
17
+ import { getL6Severity, blocksCertification } from '../config/l6-severity.js';
18
+ /** Intentional loop node types that create valid cycles */
19
+ const INTENTIONAL_LOOP_TYPES = new Set([
20
+ 'n8n-nodes-base.splitInBatches',
21
+ 'n8n-nodes-base.loop',
22
+ ]);
23
+ /** Node types that indicate valid polling/retry patterns */
24
+ const POLLING_RETRY_NODE_TYPES = new Set([
25
+ 'n8n-nodes-base.wait',
26
+ 'n8n-nodes-base.if',
27
+ 'n8n-nodes-base.switch',
28
+ ]);
29
+ /** Node types that indicate valid conversational/iterative patterns */
30
+ const CONVERSATIONAL_NODE_TYPES = new Set([
31
+ '@n8n/n8n-nodes-langchain.agent',
32
+ 'n8n-nodes-base.formTrigger',
33
+ 'n8n-nodes-base.webhook',
34
+ ]);
35
+ /** Node types used for code-based iteration control */
36
+ const CODE_ITERATION_NODE_TYPES = new Set([
37
+ 'n8n-nodes-base.code',
38
+ 'n8n-nodes-base.set',
39
+ ]);
40
+ /**
41
+ * Keywords indicating intentional iteration patterns
42
+ * (from L4_ITERATIVE_LOOP_PATTERNS.md)
43
+ */
44
+ const ITERATION_KEYWORDS = [
45
+ // Loop control keywords
46
+ 'loop', 'vars', 'iteration', 'step', 'next', 'retry', 'cycle',
47
+ // Validation keywords
48
+ 'check', 'validate', 'verify', 'status', 'poll',
49
+ // Content generation keywords
50
+ 'generate', 'create', 'planner',
51
+ // Human-in-the-loop keywords
52
+ 'approval', 'review', 'feedback', 'revision', 'human',
53
+ // Router/command keywords
54
+ 'router', 'responder', 'command',
55
+ // Data processing keywords (common in ETL/sync workflows)
56
+ 'refresh', 'token', 'download', 'upload', 'load', 'merge', 'extract',
57
+ // Conditional loop keywords
58
+ 'exists', 'invalid', 'complete', 'loaded', 'open', 'all', 'finished',
59
+ // Pagination/cursor keywords
60
+ 'page', 'cursor', 'increment', 'more', 'list', 'get',
61
+ // Sync/update keywords
62
+ 'sync', 'update', 'clear', 'duplicate', 'rename', 'set',
63
+ // Automation/deployment keywords
64
+ 'docker', 'compose', 'pull', 'image', 'deploy', 'approve', 'notif',
65
+ // Audio/voice processing keywords
66
+ 'voice', 'audio', 'fetch', 'text', 'speech', 'tts',
67
+ ];
68
+ /**
69
+ * Build a map of node names to their types
70
+ */
71
+ function buildNodeTypeMap(workflow) {
72
+ const map = new Map();
73
+ if (workflow.nodes && Array.isArray(workflow.nodes)) {
74
+ for (const node of workflow.nodes) {
75
+ map.set(node.name, node.type);
76
+ }
77
+ }
78
+ return map;
79
+ }
80
+ /**
81
+ * Check if cycle contains a Wait/delay node
82
+ */
83
+ function hasWaitNode(cycleNodeTypes) {
84
+ return cycleNodeTypes.includes('n8n-nodes-base.wait');
85
+ }
86
+ /**
87
+ * Check if cycle contains If/Switch conditional nodes
88
+ */
89
+ function hasConditionalNode(cycleNodeTypes) {
90
+ return cycleNodeTypes.some((type) => type === 'n8n-nodes-base.if' || type === 'n8n-nodes-base.switch');
91
+ }
92
+ /**
93
+ * Check if cycle represents a status polling pattern
94
+ */
95
+ function isStatusPollingPattern(cycleLower, hasWait) {
96
+ if (!hasWait)
97
+ return false;
98
+ const statusKeywords = ['status', 'check', 'verify', 'complete', 'ready', 'progress'];
99
+ return statusKeywords.some((kw) => cycleLower.includes(kw));
100
+ }
101
+ /**
102
+ * Check if cycle represents a result polling pattern
103
+ */
104
+ function isResultPollingPattern(cycleLower, hasWait) {
105
+ if (!hasWait)
106
+ return false;
107
+ return cycleLower.includes('get results') ||
108
+ cycleLower.includes('get result') ||
109
+ cycleLower.includes('get status');
110
+ }
111
+ /**
112
+ * Check if cycle represents an AI agent conversational loop
113
+ */
114
+ function isAgentLoopPattern(cycleNodeTypes, cycleLower, cycleLength) {
115
+ if (cycleLength < 3)
116
+ return false;
117
+ return cycleNodeTypes.some((type) => type === '@n8n/n8n-nodes-langchain.agent' || type?.includes('agent')) || cycleLower.includes('agent');
118
+ }
119
+ /**
120
+ * Check if cycle represents a form validation retry pattern
121
+ */
122
+ function isFormRetryPattern(cycleNodeTypes, cycleLower) {
123
+ const hasFormNode = cycleNodeTypes.some((type) => type === 'n8n-nodes-base.formTrigger' || type === 'n8n-nodes-base.webhook');
124
+ if (!hasFormNode)
125
+ return false;
126
+ const formKeywords = ['form', 'validation', 'retry', 'reenter', 'correct'];
127
+ return formKeywords.some((kw) => cycleLower.includes(kw));
128
+ }
129
+ /**
130
+ * Check if cycle represents a code-based iteration pattern
131
+ *
132
+ * These are intentional loops that use IF/Switch + Code/Set nodes instead of
133
+ * explicit loop nodes. Common in n8n.io published workflows.
134
+ *
135
+ * See: docs/validation/levels/l4/L4_ITERATIVE_LOOP_PATTERNS.md
136
+ */
137
+ function isCodeBasedIterationPattern(cycle, nodeTypeMap) {
138
+ const cycleNodeTypes = cycle.map((name) => nodeTypeMap.get(name)).filter(Boolean);
139
+ const cycleLower = cycle.join(' → ').toLowerCase();
140
+ // Pattern 1: Has IF/Switch node + iteration keywords
141
+ const hasIfNode = cycleNodeTypes.some((t) => t === 'n8n-nodes-base.if' || t === 'n8n-nodes-base.switch');
142
+ const hasIterationKeyword = ITERATION_KEYWORDS.some((kw) => cycleLower.includes(kw));
143
+ if (hasIfNode && hasIterationKeyword) {
144
+ return true;
145
+ }
146
+ // Pattern 2: Has Code/Set nodes for loop control (vars pattern)
147
+ const hasCodeIteration = cycleNodeTypes.some((t) => CODE_ITERATION_NODE_TYPES.has(t));
148
+ const hasVarsPattern = cycleLower.includes('vars') || cycleLower.includes('parameters');
149
+ if (hasCodeIteration && hasVarsPattern) {
150
+ return true;
151
+ }
152
+ // Pattern 3: Status polling pattern (Get + Check/Status + IF)
153
+ const hasGetAndCheck = cycleLower.includes('get') &&
154
+ (cycleLower.includes('status') || cycleLower.includes('check'));
155
+ if (hasGetAndCheck && hasIfNode) {
156
+ return true;
157
+ }
158
+ // Pattern 4: Self-loop (same node name repeated) - often Airtable/table patterns
159
+ // Example: "Table: Tools → Table: Tools"
160
+ if (cycle.length === 2 && cycle[0] === cycle[cycle.length - 1]) {
161
+ return true;
162
+ }
163
+ // Pattern 5: AI/LLM chain patterns
164
+ const hasAiChain = cycleLower.includes('chain') ||
165
+ cycleLower.includes('summariz') ||
166
+ cycleLower.includes('ai ') ||
167
+ cycleLower.includes('llm') ||
168
+ cycleLower.includes('gpt');
169
+ if (hasAiChain) {
170
+ return true;
171
+ }
172
+ // Pattern 6: Any cycle with IF node (conservative fallback for published n8n.io workflows)
173
+ // These are almost always intentional - IF nodes control loop termination
174
+ if (hasIfNode) {
175
+ return true;
176
+ }
177
+ return false;
178
+ }
179
+ /**
180
+ * Check if a cycle is a valid polling/retry pattern
181
+ */
182
+ function isPollingOrRetryPattern(cycle, nodeTypeMap) {
183
+ const cycleLower = cycle.join(' → ').toLowerCase();
184
+ const cycleNodeTypes = cycle.map((name) => nodeTypeMap.get(name)).filter(Boolean);
185
+ const hasWait = hasWaitNode(cycleNodeTypes);
186
+ return (isStatusPollingPattern(cycleLower, hasWait) ||
187
+ (hasConditionalNode(cycleNodeTypes) && hasWait) ||
188
+ isResultPollingPattern(cycleLower, hasWait) ||
189
+ hasWait ||
190
+ isAgentLoopPattern(cycleNodeTypes, cycleLower, cycle.length) ||
191
+ isFormRetryPattern(cycleNodeTypes, cycleLower) ||
192
+ isCodeBasedIterationPattern(cycle, nodeTypeMap));
193
+ }
194
+ /**
195
+ * Check if a cycle is an intentional loop pattern
196
+ *
197
+ * RAG-2.2.92.10: Apply same logic as L4 to filter out intentional loops.
198
+ * Returns true if the cycle should be SKIPPED (not reported as an error).
199
+ */
200
+ function isIntentionalLoopPattern(cycle, nodeTypeMap) {
201
+ // Check for explicit loop nodes first
202
+ for (const nodeName of cycle) {
203
+ const nodeType = nodeTypeMap.get(nodeName);
204
+ if (nodeType && INTENTIONAL_LOOP_TYPES.has(nodeType)) {
205
+ return true;
206
+ }
207
+ }
208
+ // Check for polling/retry/conversational patterns
209
+ for (const nodeName of cycle) {
210
+ const nodeType = nodeTypeMap.get(nodeName);
211
+ if (nodeType && (POLLING_RETRY_NODE_TYPES.has(nodeType) || CONVERSATIONAL_NODE_TYPES.has(nodeType))) {
212
+ return true;
213
+ }
214
+ }
215
+ // Check for code-based iteration patterns
216
+ if (isPollingOrRetryPattern(cycle, nodeTypeMap)) {
217
+ return true;
218
+ }
219
+ return false;
220
+ }
221
+ /**
222
+ * Get outgoing connection target node names from a source node
223
+ * @param nodeName - Source node name
224
+ * @param workflow - Workflow to analyze
225
+ * @returns Array of target node names
226
+ */
227
+ function getOutgoingConnections(nodeName, workflow) {
228
+ const targets = [];
229
+ const outgoing = workflow.connections?.[nodeName];
230
+ if (!outgoing) {
231
+ return targets;
232
+ }
233
+ for (const outputType of Object.keys(outgoing)) {
234
+ const connections = outgoing[outputType];
235
+ if (!connections || !Array.isArray(connections)) {
236
+ continue;
237
+ }
238
+ for (const connectionGroup of connections) {
239
+ if (Array.isArray(connectionGroup)) {
240
+ for (const connection of connectionGroup) {
241
+ if (connection && typeof connection === 'object' && connection.node) {
242
+ targets.push(connection.node);
243
+ }
244
+ }
245
+ }
246
+ else if (connectionGroup && typeof connectionGroup === 'object' && 'node' in connectionGroup) {
247
+ const conn = connectionGroup;
248
+ if (typeof conn.node === 'string') {
249
+ targets.push(conn.node);
250
+ }
251
+ }
252
+ }
253
+ }
254
+ return targets;
255
+ }
256
+ /**
257
+ * Check for circular references (infinite loops) in workflow graph
258
+ *
259
+ * Uses DFS with recursion stack tracking to detect cycles.
260
+ * Reports all nodes involved in cycles.
261
+ *
262
+ * RAG-2.2.92.10: Now filters out intentional loop patterns using the same
263
+ * detection logic as L4. Intentional patterns include:
264
+ * - Explicit loop nodes (SplitInBatches, Loop)
265
+ * - Polling/retry patterns (Wait + If/Switch)
266
+ * - AI agent conversational loops
267
+ * - Code-based iteration patterns (IF + iteration keywords)
268
+ *
269
+ * @param context - L6 validation context
270
+ * @returns Array of L6Error for each cycle detected (excluding intentional patterns)
271
+ */
272
+ export function checkCircularReferences(context) {
273
+ const { workflow } = context;
274
+ const errors = [];
275
+ // Guard: Ensure workflow.nodes exists
276
+ if (!workflow.nodes || !Array.isArray(workflow.nodes)) {
277
+ return errors;
278
+ }
279
+ // RAG-2.2.92.10: Build node type map for pattern detection
280
+ const nodeTypeMap = buildNodeTypeMap(workflow);
281
+ const visited = new Set();
282
+ const recursionStack = new Set();
283
+ const reportedCycles = new Set(); // Avoid duplicate cycle reports
284
+ /**
285
+ * Depth-first search to detect cycles
286
+ * @param nodeName - Current node being visited
287
+ * @param path - Path of nodes visited to reach current node
288
+ */
289
+ function dfs(nodeName, path) {
290
+ // If node is in recursion stack, we found a cycle
291
+ if (recursionStack.has(nodeName)) {
292
+ const cycleStart = path.indexOf(nodeName);
293
+ const cycle = path.slice(cycleStart);
294
+ // Create unique key for this cycle to avoid duplicates
295
+ const cycleKey = [...cycle].sort().join('->');
296
+ if (reportedCycles.has(cycleKey)) {
297
+ return;
298
+ }
299
+ reportedCycles.add(cycleKey);
300
+ // RAG-2.2.92.10: Skip intentional loop patterns
301
+ if (isIntentionalLoopPattern(cycle, nodeTypeMap)) {
302
+ return;
303
+ }
304
+ const code = 'CIRCULAR_REFERENCE';
305
+ errors.push({
306
+ code: 'CIRCULAR_REFERENCE',
307
+ message: `Circular reference detected: ${cycle.join(' → ')} → ${nodeName}`,
308
+ path: `workflow.connections`,
309
+ node_name: nodeName,
310
+ severity: getL6Severity(code),
311
+ blocks_certification: blocksCertification(code),
312
+ details: {
313
+ cycle_nodes: cycle,
314
+ cycle_length: cycle.length,
315
+ },
316
+ suggested_fix: {
317
+ id: `fix-circular-${nodeName}-${Date.now()}`,
318
+ fix_type: 'remove_connection',
319
+ confidence: 0.7,
320
+ auto_applicable: false,
321
+ description: `Remove one connection to break the cycle: ${cycle.join(' → ')}`,
322
+ target_node: nodeName,
323
+ patch: {},
324
+ context: {
325
+ cycle_nodes: cycle,
326
+ suggested_break_point: cycle[cycle.length - 1], // Last node before cycle repeats
327
+ },
328
+ },
329
+ });
330
+ return;
331
+ }
332
+ // If already fully visited, skip
333
+ if (visited.has(nodeName)) {
334
+ return;
335
+ }
336
+ // Mark as visiting (in recursion stack)
337
+ visited.add(nodeName);
338
+ recursionStack.add(nodeName);
339
+ // Visit all connected nodes
340
+ const connections = getOutgoingConnections(nodeName, workflow);
341
+ for (const targetNode of connections) {
342
+ dfs(targetNode, [...path, nodeName]);
343
+ }
344
+ // Remove from recursion stack when done
345
+ recursionStack.delete(nodeName);
346
+ }
347
+ // Start DFS from all nodes to handle disconnected subgraphs
348
+ for (const node of workflow.nodes) {
349
+ if (!visited.has(node.name)) {
350
+ dfs(node.name, []);
351
+ }
352
+ }
353
+ return errors;
354
+ }
355
+ /**
356
+ * Run all loop detection checks
357
+ *
358
+ * @param context - L6 validation context
359
+ * @returns Object containing errors and warnings
360
+ */
361
+ export async function checkLoops(context) {
362
+ const startTime = performance.now();
363
+ const circularErrors = checkCircularReferences(context);
364
+ const duration = performance.now() - startTime;
365
+ return {
366
+ errors: circularErrors,
367
+ warnings: [], // No loop-related warnings currently
368
+ };
369
+ }
370
+ //# sourceMappingURL=loops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loops.js","sourceRoot":"","sources":["../../../src/validation/l6-checks/loops.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,182 @@
1
+ /**
2
+ * L6 Performance Checks
3
+ *
4
+ * RAG-2.2.77: L6 New Pattern Checks
5
+ * Created: 2026-01-17
6
+ *
7
+ * Validates workflow performance characteristics:
8
+ * - OVERSIZED_WORKFLOW: Workflow has excessive number of nodes (50+)
9
+ * - EXCESSIVE_RETRY: Node has excessive retry configuration (>10)
10
+ *
11
+ * These are warnings that don't block certification but flag
12
+ * potential performance and maintainability issues.
13
+ */
14
+ import { getL6Severity, blocksCertification } from '../config/l6-severity.js';
15
+ /**
16
+ * Workflow size thresholds
17
+ */
18
+ const SIZE_THRESHOLDS = {
19
+ /** Warning threshold - workflow is getting large */
20
+ warning: 50,
21
+ /** Critical threshold - workflow is too large, suggest splitting */
22
+ critical: 100,
23
+ };
24
+ /**
25
+ * Maximum reasonable retry count
26
+ */
27
+ const MAX_REASONABLE_RETRIES = 10;
28
+ /**
29
+ * Check for oversized workflows (50+ nodes)
30
+ *
31
+ * Large workflows can impact:
32
+ * - Performance during execution
33
+ * - Maintainability and debugging
34
+ * - n8n editor responsiveness
35
+ *
36
+ * @param context - L6 validation context
37
+ * @returns Array of L6Warning for oversized workflows
38
+ */
39
+ export function checkWorkflowSize(context) {
40
+ const { workflow } = context;
41
+ const warnings = [];
42
+ // Guard: Ensure workflow.nodes exists
43
+ if (!workflow.nodes || !Array.isArray(workflow.nodes)) {
44
+ return warnings;
45
+ }
46
+ const nodeCount = workflow.nodes.length;
47
+ // Only report if above critical threshold (100+)
48
+ // Per assignment: trigger at SIZE_THRESHOLDS.critical
49
+ if (nodeCount >= SIZE_THRESHOLDS.critical) {
50
+ const code = 'OVERSIZED_WORKFLOW';
51
+ warnings.push({
52
+ code: 'OVERSIZED_WORKFLOW',
53
+ message: `Workflow has ${nodeCount} nodes (>${SIZE_THRESHOLDS.critical}). Consider splitting into sub-workflows for better maintainability.`,
54
+ node_name: '__workflow__',
55
+ severity: getL6Severity(code),
56
+ blocks_certification: blocksCertification(code),
57
+ details: {
58
+ node_count: nodeCount,
59
+ threshold: SIZE_THRESHOLDS.critical,
60
+ warning_threshold: SIZE_THRESHOLDS.warning,
61
+ },
62
+ suggested_fix: {
63
+ id: `fix-oversized-workflow-${Date.now()}`,
64
+ fix_type: 'split_workflow',
65
+ confidence: 0.5,
66
+ auto_applicable: false,
67
+ description: 'Split workflow into smaller sub-workflows using Execute Workflow node',
68
+ target_node: '__workflow__',
69
+ patch: {},
70
+ context: {
71
+ current_node_count: nodeCount,
72
+ recommendation: 'Consider grouping related nodes into sub-workflows',
73
+ },
74
+ },
75
+ });
76
+ }
77
+ else if (nodeCount >= SIZE_THRESHOLDS.warning) {
78
+ // Warn at 50+ nodes but less critical
79
+ const code = 'OVERSIZED_WORKFLOW';
80
+ warnings.push({
81
+ code: 'OVERSIZED_WORKFLOW',
82
+ message: `Workflow has ${nodeCount} nodes (>${SIZE_THRESHOLDS.warning}). May impact performance.`,
83
+ node_name: '__workflow__',
84
+ severity: getL6Severity(code),
85
+ blocks_certification: blocksCertification(code),
86
+ details: {
87
+ node_count: nodeCount,
88
+ threshold: SIZE_THRESHOLDS.warning,
89
+ },
90
+ });
91
+ }
92
+ return warnings;
93
+ }
94
+ /**
95
+ * Check for excessive retry configurations (>10 retries)
96
+ *
97
+ * Nodes with too many retries can cause:
98
+ * - Long delays during failure scenarios
99
+ * - Resource exhaustion
100
+ * - Poor user experience
101
+ *
102
+ * @param context - L6 validation context
103
+ * @returns Array of L6Warning for nodes with excessive retries
104
+ */
105
+ export function checkExcessiveRetries(context) {
106
+ const { workflow } = context;
107
+ const warnings = [];
108
+ // Guard: Ensure workflow.nodes exists
109
+ if (!workflow.nodes || !Array.isArray(workflow.nodes)) {
110
+ return warnings;
111
+ }
112
+ for (const node of workflow.nodes) {
113
+ // Check if node has retry configured
114
+ // n8n uses retryOnFail boolean and maxTries number
115
+ const retryOnFail = node.retryOnFail;
116
+ const maxTries = node.maxTries || 3;
117
+ const waitBetweenTries = node.waitBetweenTries || 1000;
118
+ // Only check if retry is actually enabled
119
+ if (!retryOnFail) {
120
+ continue;
121
+ }
122
+ if (maxTries > MAX_REASONABLE_RETRIES) {
123
+ const maxWaitSeconds = (maxTries * waitBetweenTries) / 1000;
124
+ const code = 'EXCESSIVE_RETRY';
125
+ warnings.push({
126
+ code: 'EXCESSIVE_RETRY',
127
+ message: `Node "${node.name}" has ${maxTries} retries (>${MAX_REASONABLE_RETRIES}). Maximum wait time: ${maxWaitSeconds}s.`,
128
+ node_name: node.name,
129
+ node_type: node.type,
130
+ severity: getL6Severity(code),
131
+ blocks_certification: blocksCertification(code),
132
+ details: {
133
+ max_tries: maxTries,
134
+ threshold: MAX_REASONABLE_RETRIES,
135
+ wait_between_tries_ms: waitBetweenTries,
136
+ max_wait_seconds: maxWaitSeconds,
137
+ },
138
+ suggested_fix: {
139
+ id: `fix-excessive-retry-${node.name}-${Date.now()}`,
140
+ fix_type: 'reduce_retries',
141
+ confidence: 0.8,
142
+ auto_applicable: true,
143
+ description: `Reduce maxTries from ${maxTries} to ${MAX_REASONABLE_RETRIES} or less`,
144
+ target_node: node.name,
145
+ patch: {
146
+ node_settings: {
147
+ maxTries: MAX_REASONABLE_RETRIES,
148
+ },
149
+ },
150
+ context: {
151
+ current_max_tries: maxTries,
152
+ recommended_max_tries: MAX_REASONABLE_RETRIES,
153
+ },
154
+ },
155
+ });
156
+ }
157
+ }
158
+ return warnings;
159
+ }
160
+ /**
161
+ * Run all performance checks
162
+ *
163
+ * @param context - L6 validation context
164
+ * @returns Object containing errors and warnings
165
+ */
166
+ export async function checkPerformance(context) {
167
+ const startTime = performance.now();
168
+ // Run checks in parallel
169
+ const [oversizedWarnings, excessiveRetryWarnings,] = await Promise.all([
170
+ Promise.resolve(checkWorkflowSize(context)),
171
+ Promise.resolve(checkExcessiveRetries(context)),
172
+ ]);
173
+ const duration = performance.now() - startTime;
174
+ return {
175
+ errors: [], // Performance checks are warnings only
176
+ warnings: [
177
+ ...oversizedWarnings,
178
+ ...excessiveRetryWarnings,
179
+ ],
180
+ };
181
+ }
182
+ //# sourceMappingURL=performance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance.js","sourceRoot":"","sources":["../../../src/validation/l6-checks/performance.ts"],"names":[],"mappings":"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"}