gitnexus 1.6.10-rc.99 → 1.6.10

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 (775) hide show
  1. package/README.md +177 -18
  2. package/dist/_shared/graph/types.d.ts +21 -2
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/index.d.ts +3 -3
  5. package/dist/_shared/index.d.ts.map +1 -1
  6. package/dist/_shared/index.js +1 -1
  7. package/dist/_shared/index.js.map +1 -1
  8. package/dist/_shared/integrations/circuit-breaker.d.ts.map +1 -1
  9. package/dist/_shared/integrations/circuit-breaker.js.map +1 -1
  10. package/dist/_shared/integrations/resilient-fetch.d.ts +16 -0
  11. package/dist/_shared/integrations/resilient-fetch.d.ts.map +1 -1
  12. package/dist/_shared/integrations/resilient-fetch.js +19 -7
  13. package/dist/_shared/integrations/resilient-fetch.js.map +1 -1
  14. package/dist/_shared/language-detection.d.ts.map +1 -1
  15. package/dist/_shared/lbug/schema-constants.d.ts +2 -2
  16. package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
  17. package/dist/_shared/lbug/schema-constants.js +3 -0
  18. package/dist/_shared/lbug/schema-constants.js.map +1 -1
  19. package/dist/_shared/scope-resolution/evidence-weights.d.ts.map +1 -1
  20. package/dist/_shared/scope-resolution/finalize-algorithm.d.ts +5 -0
  21. package/dist/_shared/scope-resolution/finalize-algorithm.d.ts.map +1 -1
  22. package/dist/_shared/scope-resolution/finalize-algorithm.js +315 -36
  23. package/dist/_shared/scope-resolution/finalize-algorithm.js.map +1 -1
  24. package/dist/_shared/scope-resolution/reference-site.d.ts +115 -0
  25. package/dist/_shared/scope-resolution/reference-site.d.ts.map +1 -1
  26. package/dist/_shared/scope-resolution/registries/field-registry.js.map +1 -1
  27. package/dist/_shared/scope-resolution/registries/lookup-core.d.ts.map +1 -1
  28. package/dist/_shared/scope-resolution/registries/lookup-core.js +58 -2
  29. package/dist/_shared/scope-resolution/registries/lookup-core.js.map +1 -1
  30. package/dist/_shared/scope-resolution/registries/method-registry.js.map +1 -1
  31. package/dist/_shared/scope-resolution/scope-tree.d.ts.map +1 -1
  32. package/dist/_shared/scope-resolution/scope-tree.js.map +1 -1
  33. package/dist/_shared/scope-resolution/symbol-definition.d.ts +47 -0
  34. package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
  35. package/dist/_shared/scope-resolution/types.d.ts +278 -3
  36. package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
  37. package/dist/cli/ai-context.d.ts +3 -2
  38. package/dist/cli/ai-context.js +71 -16
  39. package/dist/cli/analyze-config.d.ts +1 -1
  40. package/dist/cli/analyze-options.d.ts +131 -0
  41. package/dist/cli/analyze-options.js +1 -0
  42. package/dist/cli/analyze.d.ts +21 -113
  43. package/dist/cli/analyze.js +172 -29
  44. package/dist/cli/cli-message.d.ts +1 -1
  45. package/dist/cli/detect-changes-format.js +19 -2
  46. package/dist/cli/doctor.d.ts +12 -0
  47. package/dist/cli/doctor.js +32 -5
  48. package/dist/cli/editor-targets.js +6 -0
  49. package/dist/cli/eval-server.js +2 -1
  50. package/dist/cli/format-symbol.d.ts +15 -0
  51. package/dist/cli/format-symbol.js +17 -0
  52. package/dist/cli/generated-skill.d.ts +17 -0
  53. package/dist/cli/generated-skill.js +1 -0
  54. package/dist/cli/group.js +229 -21
  55. package/dist/cli/help-i18n.js +1 -2
  56. package/dist/cli/i18n/en.d.ts +11 -9
  57. package/dist/cli/i18n/en.js +13 -9
  58. package/dist/cli/i18n/resources.d.ts +15 -11
  59. package/dist/cli/i18n/zh-CN.d.ts +4 -2
  60. package/dist/cli/i18n/zh-CN.js +11 -9
  61. package/dist/cli/index.js +8 -4
  62. package/dist/cli/resolve-invocation.d.ts +7 -3
  63. package/dist/cli/resolve-invocation.js +7 -3
  64. package/dist/cli/setup.js +4 -3
  65. package/dist/cli/skill-gen.d.ts +1 -6
  66. package/dist/cli/tool.d.ts +1 -0
  67. package/dist/cli/tool.js +74 -17
  68. package/dist/cli/wiki.js +53 -10
  69. package/dist/config/ignore-service.d.ts +2 -0
  70. package/dist/config/ignore-service.js +54 -13
  71. package/dist/core/analyzer-identity.d.ts +80 -0
  72. package/dist/core/analyzer-identity.js +364 -26
  73. package/dist/core/augmentation/engine.js +86 -71
  74. package/dist/core/embedding-checkpoint.d.ts +143 -0
  75. package/dist/core/embedding-checkpoint.js +221 -0
  76. package/dist/core/embedding-count.d.ts +61 -0
  77. package/dist/core/embedding-count.js +69 -0
  78. package/dist/core/embeddings/ast-utils.js +9 -1
  79. package/dist/core/embeddings/embedding-pipeline.d.ts +8 -0
  80. package/dist/core/embeddings/embedding-pipeline.js +253 -14
  81. package/dist/core/embeddings/http-client.d.ts +5 -0
  82. package/dist/core/embeddings/http-client.js +142 -27
  83. package/dist/core/graph/graph.js +3 -0
  84. package/dist/core/graph/import-cycles.d.ts +194 -3
  85. package/dist/core/graph/import-cycles.js +522 -73
  86. package/dist/core/graph/types.d.ts +18 -0
  87. package/dist/core/group/bridge-db.d.ts +204 -1
  88. package/dist/core/group/bridge-db.js +401 -28
  89. package/dist/core/group/completeness.d.ts +130 -0
  90. package/dist/core/group/completeness.js +83 -0
  91. package/dist/core/group/config-parser.js +0 -5
  92. package/dist/core/group/cross-impact.d.ts +46 -1
  93. package/dist/core/group/cross-impact.js +220 -19
  94. package/dist/core/group/cross-trace.d.ts +32 -11
  95. package/dist/core/group/cross-trace.js +114 -20
  96. package/dist/core/group/extractors/http-patterns/java.js +278 -22
  97. package/dist/core/group/extractors/http-patterns/node.js +332 -216
  98. package/dist/core/group/extractors/http-patterns/types.d.ts +8 -0
  99. package/dist/core/group/extractors/http-route-extractor.d.ts +1 -0
  100. package/dist/core/group/extractors/http-route-extractor.js +122 -48
  101. package/dist/core/group/extractors/include-extractor.js +20 -2
  102. package/dist/core/group/extractors/manifest-extractor.d.ts +1 -1
  103. package/dist/core/group/extractors/manifest-extractor.js +7 -7
  104. package/dist/core/group/extractors/python-workspace-extractor.js +5 -2
  105. package/dist/core/group/group-lock.d.ts +31 -0
  106. package/dist/core/group/group-lock.js +166 -0
  107. package/dist/core/group/service.js +297 -16
  108. package/dist/core/group/storage.d.ts +3 -0
  109. package/dist/core/group/storage.js +7 -39
  110. package/dist/core/group/sync.d.ts +49 -3
  111. package/dist/core/group/sync.js +0 -0
  112. package/dist/core/group/types.d.ts +183 -8
  113. package/dist/core/group/types.js +28 -1
  114. package/dist/core/incremental/subgraph-extract.d.ts +9 -6
  115. package/dist/core/incremental/subgraph-extract.js +33 -10
  116. package/dist/core/index-freshness.d.ts +77 -2
  117. package/dist/core/index-freshness.js +109 -2
  118. package/dist/core/ingestion/call-processor.d.ts +13 -1
  119. package/dist/core/ingestion/call-processor.js +110 -3
  120. package/dist/core/ingestion/cfg/callee-cell-format.d.ts +42 -0
  121. package/dist/core/ingestion/cfg/callee-cell-format.js +42 -0
  122. package/dist/core/ingestion/cfg/emit.d.ts +8 -23
  123. package/dist/core/ingestion/cfg/emit.js +9 -23
  124. package/dist/core/ingestion/class-extractors/configs/go.js +10 -5
  125. package/dist/core/ingestion/cluster-enricher.js +8 -4
  126. package/dist/core/ingestion/community-processor.d.ts +21 -3
  127. package/dist/core/ingestion/community-processor.js +81 -82
  128. package/dist/core/ingestion/di-extractors/index.d.ts +9 -33
  129. package/dist/core/ingestion/di-extractors/spring.d.ts +1 -1
  130. package/dist/core/ingestion/di-extractors/spring.js +8 -1
  131. package/dist/core/ingestion/di-extractors/types.d.ts +60 -0
  132. package/dist/core/ingestion/di-extractors/types.js +15 -0
  133. package/dist/core/ingestion/filesystem-walker.js +30 -14
  134. package/dist/core/ingestion/finalize-orchestrator.js +1 -0
  135. package/dist/core/ingestion/frameworks/spring/analysis-features.d.ts +6 -0
  136. package/dist/core/ingestion/frameworks/spring/analysis-features.js +35 -1
  137. package/dist/core/ingestion/frameworks/spring/annotation-arguments.d.ts +13 -0
  138. package/dist/core/ingestion/frameworks/spring/annotation-arguments.js +227 -0
  139. package/dist/core/ingestion/frameworks/spring/aop-candidates.d.ts +15 -0
  140. package/dist/core/ingestion/frameworks/spring/aop-candidates.js +85 -0
  141. package/dist/core/ingestion/frameworks/spring/aop.d.ts +118 -0
  142. package/dist/core/ingestion/frameworks/spring/aop.js +476 -0
  143. package/dist/core/ingestion/frameworks/spring/auto-configuration.d.ts +8 -0
  144. package/dist/core/ingestion/frameworks/spring/auto-configuration.js +16 -0
  145. package/dist/core/ingestion/frameworks/spring/bean-catalog.js +1 -0
  146. package/dist/core/ingestion/frameworks/spring/bean-factories.d.ts +33 -0
  147. package/dist/core/ingestion/frameworks/spring/bean-factories.js +65 -0
  148. package/dist/core/ingestion/frameworks/spring/conditionals.d.ts +25 -0
  149. package/dist/core/ingestion/frameworks/spring/conditionals.js +319 -0
  150. package/dist/core/ingestion/frameworks/spring/di-metadata.d.ts +3 -0
  151. package/dist/core/ingestion/frameworks/spring/di-metadata.js +162 -13
  152. package/dist/core/ingestion/frameworks/spring/non-http-handlers.d.ts +28 -0
  153. package/dist/core/ingestion/frameworks/spring/non-http-handlers.js +152 -0
  154. package/dist/core/ingestion/frameworks/spring/resource-injection.d.ts +5 -0
  155. package/dist/core/ingestion/frameworks/spring/resource-injection.js +91 -0
  156. package/dist/core/ingestion/import-resolvers/configs/csharp.js +5 -1
  157. package/dist/core/ingestion/import-resolvers/configs/swift.js +13 -0
  158. package/dist/core/ingestion/import-resolvers/csharp.d.ts +9 -1
  159. package/dist/core/ingestion/import-resolvers/csharp.js +234 -27
  160. package/dist/core/ingestion/import-resolvers/go.d.ts +11 -1
  161. package/dist/core/ingestion/import-resolvers/go.js +44 -17
  162. package/dist/core/ingestion/import-resolvers/jvm.d.ts +2 -2
  163. package/dist/core/ingestion/import-resolvers/node-workspace-packages.d.ts +90 -0
  164. package/dist/core/ingestion/import-resolvers/node-workspace-packages.js +429 -0
  165. package/dist/core/ingestion/import-resolvers/package-dir-index.d.ts +124 -0
  166. package/dist/core/ingestion/import-resolvers/package-dir-index.js +223 -0
  167. package/dist/core/ingestion/import-resolvers/pass-cache.d.ts +50 -0
  168. package/dist/core/ingestion/import-resolvers/pass-cache.js +60 -0
  169. package/dist/core/ingestion/import-resolvers/per-file-set.d.ts +71 -0
  170. package/dist/core/ingestion/import-resolvers/per-file-set.js +11 -0
  171. package/dist/core/ingestion/import-resolvers/php.d.ts +1 -1
  172. package/dist/core/ingestion/import-resolvers/php.js +65 -19
  173. package/dist/core/ingestion/import-resolvers/python-file-index.d.ts +201 -0
  174. package/dist/core/ingestion/import-resolvers/python-file-index.js +302 -0
  175. package/dist/core/ingestion/import-resolvers/python.js +25 -6
  176. package/dist/core/ingestion/import-resolvers/ruby.d.ts +1 -1
  177. package/dist/core/ingestion/import-resolvers/rust.d.ts +2 -2
  178. package/dist/core/ingestion/import-resolvers/standard.d.ts +1 -1
  179. package/dist/core/ingestion/import-resolvers/types.d.ts +1 -12
  180. package/dist/core/ingestion/import-resolvers/utils.d.ts +65 -6
  181. package/dist/core/ingestion/import-resolvers/utils.js +215 -36
  182. package/dist/core/ingestion/import-resolvers/workspace-file-index.d.ts +72 -0
  183. package/dist/core/ingestion/import-resolvers/workspace-file-index.js +58 -0
  184. package/dist/core/ingestion/language-config.d.ts +29 -1
  185. package/dist/core/ingestion/language-config.js +110 -35
  186. package/dist/core/ingestion/language-provider.d.ts +209 -7
  187. package/dist/core/ingestion/language-provider.js +37 -0
  188. package/dist/core/ingestion/languages/c/captures.js +7 -0
  189. package/dist/core/ingestion/languages/c/import-target.js +12 -16
  190. package/dist/core/ingestion/languages/c/scope-resolver.js +20 -19
  191. package/dist/core/ingestion/languages/c/static-linkage.js +12 -16
  192. package/dist/core/ingestion/languages/c-cpp.js +13 -0
  193. package/dist/core/ingestion/languages/cobol/scope-resolver.js +27 -20
  194. package/dist/core/ingestion/languages/cobol.js +13 -0
  195. package/dist/core/ingestion/languages/cpp/adl.d.ts +2 -2
  196. package/dist/core/ingestion/languages/cpp/adl.js +67 -44
  197. package/dist/core/ingestion/languages/cpp/captures.js +14 -2
  198. package/dist/core/ingestion/languages/cpp/file-local-linkage.js +11 -15
  199. package/dist/core/ingestion/languages/cpp/inline-namespaces.d.ts +28 -8
  200. package/dist/core/ingestion/languages/cpp/inline-namespaces.js +242 -68
  201. package/dist/core/ingestion/languages/cpp/interpret.d.ts +2 -0
  202. package/dist/core/ingestion/languages/cpp/interpret.js +126 -6
  203. package/dist/core/ingestion/languages/cpp/query.js +106 -0
  204. package/dist/core/ingestion/languages/cpp/scope-resolver.js +48 -20
  205. package/dist/core/ingestion/languages/csharp/accessor-unwrap.d.ts +2 -15
  206. package/dist/core/ingestion/languages/csharp/accessor-unwrap.js +18 -10
  207. package/dist/core/ingestion/languages/csharp/captures.js +19 -0
  208. package/dist/core/ingestion/languages/csharp/import-target.js +46 -72
  209. package/dist/core/ingestion/languages/csharp/namespace-siblings.js +5 -1
  210. package/dist/core/ingestion/languages/csharp/query.js +25 -5
  211. package/dist/core/ingestion/languages/csharp/scope-resolver.js +75 -2
  212. package/dist/core/ingestion/languages/dart/captures.d.ts +10 -0
  213. package/dist/core/ingestion/languages/dart/captures.js +598 -16
  214. package/dist/core/ingestion/languages/dart/import-target.js +32 -9
  215. package/dist/core/ingestion/languages/dart/index.d.ts +1 -1
  216. package/dist/core/ingestion/languages/dart/index.js +1 -1
  217. package/dist/core/ingestion/languages/dart/query.js +98 -1
  218. package/dist/core/ingestion/languages/dart/scope-resolver.js +14 -3
  219. package/dist/core/ingestion/languages/dart/simple-hooks.js +9 -0
  220. package/dist/core/ingestion/languages/dart.js +6 -1
  221. package/dist/core/ingestion/languages/go/captures.js +108 -3
  222. package/dist/core/ingestion/languages/go/generic-type-parameters.d.ts +31 -0
  223. package/dist/core/ingestion/languages/go/generic-type-parameters.js +140 -0
  224. package/dist/core/ingestion/languages/go/import-target.d.ts +3 -10
  225. package/dist/core/ingestion/languages/go/import-target.js +34 -30
  226. package/dist/core/ingestion/languages/go/index.d.ts +1 -1
  227. package/dist/core/ingestion/languages/go/interface-impls.d.ts +9 -1
  228. package/dist/core/ingestion/languages/go/interface-impls.js +693 -87
  229. package/dist/core/ingestion/languages/go/interpret.d.ts +2 -0
  230. package/dist/core/ingestion/languages/go/interpret.js +22 -8
  231. package/dist/core/ingestion/languages/go/method-owners.js +31 -12
  232. package/dist/core/ingestion/languages/go/package-clause.d.ts +46 -0
  233. package/dist/core/ingestion/languages/go/package-clause.js +75 -0
  234. package/dist/core/ingestion/languages/go/package-siblings.js +7 -11
  235. package/dist/core/ingestion/languages/go/query.js +56 -3
  236. package/dist/core/ingestion/languages/go/scope-resolver.js +39 -0
  237. package/dist/core/ingestion/languages/go.js +9 -0
  238. package/dist/core/ingestion/languages/java/analysis-features.d.ts +4 -0
  239. package/dist/core/ingestion/languages/java/analysis-features.js +12 -0
  240. package/dist/core/ingestion/languages/java/capture-side-channel.d.ts +12 -0
  241. package/dist/core/ingestion/languages/java/capture-side-channel.js +48 -0
  242. package/dist/core/ingestion/languages/java/captures.js +77 -32
  243. package/dist/core/ingestion/languages/java/import-target.d.ts +49 -9
  244. package/dist/core/ingestion/languages/java/import-target.js +68 -88
  245. package/dist/core/ingestion/languages/java/interpret.js +3 -2
  246. package/dist/core/ingestion/languages/java/module-resolution.d.ts +62 -0
  247. package/dist/core/ingestion/languages/java/module-resolution.js +142 -0
  248. package/dist/core/ingestion/languages/java/query.js +15 -3
  249. package/dist/core/ingestion/languages/java/record-components.d.ts +14 -0
  250. package/dist/core/ingestion/languages/java/record-components.js +185 -0
  251. package/dist/core/ingestion/languages/java/scope-resolver.js +10 -2
  252. package/dist/core/ingestion/languages/java/spring-aop.d.ts +12 -0
  253. package/dist/core/ingestion/languages/java/spring-aop.js +49 -0
  254. package/dist/core/ingestion/languages/java/spring-conditionals.d.ts +11 -0
  255. package/dist/core/ingestion/languages/java/spring-conditionals.js +48 -0
  256. package/dist/core/ingestion/languages/java/spring-di.d.ts +4 -1
  257. package/dist/core/ingestion/languages/java/spring-di.js +41 -9
  258. package/dist/core/ingestion/languages/java/spring-non-http-handlers.d.ts +7 -0
  259. package/dist/core/ingestion/languages/java/spring-non-http-handlers.js +32 -0
  260. package/dist/core/ingestion/languages/java.js +94 -3
  261. package/dist/core/ingestion/languages/javascript/captures.d.ts +6 -1
  262. package/dist/core/ingestion/languages/javascript/captures.js +262 -4
  263. package/dist/core/ingestion/languages/javascript/import-target.d.ts +17 -21
  264. package/dist/core/ingestion/languages/javascript/import-target.js +24 -41
  265. package/dist/core/ingestion/languages/javascript/index.d.ts +54 -5
  266. package/dist/core/ingestion/languages/javascript/index.js +54 -5
  267. package/dist/core/ingestion/languages/javascript/query.d.ts +1 -0
  268. package/dist/core/ingestion/languages/javascript/query.js +211 -5
  269. package/dist/core/ingestion/languages/javascript/scope-resolver.js +12 -0
  270. package/dist/core/ingestion/languages/javascript/simple-hooks.js +2 -1
  271. package/dist/core/ingestion/languages/jvm/package-siblings.js +77 -9
  272. package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +15 -0
  273. package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +48 -0
  274. package/dist/core/ingestion/languages/kotlin/captures.js +43 -1
  275. package/dist/core/ingestion/languages/kotlin/import-target.d.ts +8 -1
  276. package/dist/core/ingestion/languages/kotlin/import-target.js +20 -123
  277. package/dist/core/ingestion/languages/kotlin/index.d.ts +1 -0
  278. package/dist/core/ingestion/languages/kotlin/index.js +1 -0
  279. package/dist/core/ingestion/languages/kotlin/module-resolution.d.ts +22 -0
  280. package/dist/core/ingestion/languages/kotlin/module-resolution.js +108 -0
  281. package/dist/core/ingestion/languages/kotlin/query.js +28 -2
  282. package/dist/core/ingestion/languages/kotlin/scope-resolver.js +23 -2
  283. package/dist/core/ingestion/languages/kotlin/spring-aop.d.ts +12 -0
  284. package/dist/core/ingestion/languages/kotlin/spring-aop.js +64 -0
  285. package/dist/core/ingestion/languages/kotlin/spring-conditionals.d.ts +12 -0
  286. package/dist/core/ingestion/languages/kotlin/spring-conditionals.js +49 -0
  287. package/dist/core/ingestion/languages/kotlin/spring-di.d.ts +2 -0
  288. package/dist/core/ingestion/languages/kotlin/spring-di.js +60 -11
  289. package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.d.ts +10 -0
  290. package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.js +41 -0
  291. package/dist/core/ingestion/languages/php/captures.d.ts +5 -0
  292. package/dist/core/ingestion/languages/php/captures.js +319 -51
  293. package/dist/core/ingestion/languages/php/import-target.d.ts +3 -4
  294. package/dist/core/ingestion/languages/php/import-target.js +192 -62
  295. package/dist/core/ingestion/languages/php/query.js +31 -0
  296. package/dist/core/ingestion/languages/python/arity-metadata.d.ts +1 -0
  297. package/dist/core/ingestion/languages/python/arity-metadata.js +1 -0
  298. package/dist/core/ingestion/languages/python/captures.js +29 -0
  299. package/dist/core/ingestion/languages/python/import-decomposer.js +22 -1
  300. package/dist/core/ingestion/languages/python/import-target.d.ts +42 -1
  301. package/dist/core/ingestion/languages/python/import-target.js +277 -91
  302. package/dist/core/ingestion/languages/python/index.d.ts +1 -1
  303. package/dist/core/ingestion/languages/python/index.js +1 -1
  304. package/dist/core/ingestion/languages/python/interpret.d.ts +52 -0
  305. package/dist/core/ingestion/languages/python/interpret.js +249 -7
  306. package/dist/core/ingestion/languages/python/query.js +9 -0
  307. package/dist/core/ingestion/languages/python/receiver-binding.d.ts +8 -6
  308. package/dist/core/ingestion/languages/python/receiver-binding.js +108 -12
  309. package/dist/core/ingestion/languages/python/scope-resolver.js +27 -4
  310. package/dist/core/ingestion/languages/python/simple-hooks.js +2 -8
  311. package/dist/core/ingestion/languages/python.js +13 -0
  312. package/dist/core/ingestion/languages/ruby/captures.js +158 -0
  313. package/dist/core/ingestion/languages/ruby/import-target.js +7 -5
  314. package/dist/core/ingestion/languages/ruby/query.js +93 -0
  315. package/dist/core/ingestion/languages/ruby/scope-resolver.js +2 -0
  316. package/dist/core/ingestion/languages/ruby/simple-hooks.d.ts +1 -1
  317. package/dist/core/ingestion/languages/ruby/simple-hooks.js +22 -1
  318. package/dist/core/ingestion/languages/rust/captures.js +39 -1
  319. package/dist/core/ingestion/languages/rust/method-owners.js +11 -1
  320. package/dist/core/ingestion/languages/rust/module-path.d.ts +126 -0
  321. package/dist/core/ingestion/languages/rust/module-path.js +214 -0
  322. package/dist/core/ingestion/languages/rust/qualified-call.d.ts +41 -0
  323. package/dist/core/ingestion/languages/rust/qualified-call.js +481 -0
  324. package/dist/core/ingestion/languages/rust/query.js +39 -6
  325. package/dist/core/ingestion/languages/rust/scope-resolver.js +21 -2
  326. package/dist/core/ingestion/languages/rust.js +17 -0
  327. package/dist/core/ingestion/languages/swift/captures.js +87 -3
  328. package/dist/core/ingestion/languages/swift/conditional-directive-preprocess.d.ts +48 -0
  329. package/dist/core/ingestion/languages/swift/conditional-directive-preprocess.js +253 -0
  330. package/dist/core/ingestion/languages/swift/import-target.js +4 -9
  331. package/dist/core/ingestion/languages/swift/query.js +17 -0
  332. package/dist/core/ingestion/languages/swift/receiver-binding.d.ts +8 -0
  333. package/dist/core/ingestion/languages/swift/receiver-binding.js +6 -2
  334. package/dist/core/ingestion/languages/swift.js +2 -0
  335. package/dist/core/ingestion/languages/typescript/captures.d.ts +90 -1
  336. package/dist/core/ingestion/languages/typescript/captures.js +267 -5
  337. package/dist/core/ingestion/languages/typescript/cjs-export-assignment.d.ts +134 -0
  338. package/dist/core/ingestion/languages/typescript/cjs-export-assignment.js +523 -0
  339. package/dist/core/ingestion/languages/typescript/cjs-module-exports.d.ts +54 -0
  340. package/dist/core/ingestion/languages/typescript/cjs-module-exports.js +191 -0
  341. package/dist/core/ingestion/languages/typescript/convex-endpoint-metadata.d.ts +7 -0
  342. package/dist/core/ingestion/languages/typescript/convex-endpoint-metadata.js +92 -0
  343. package/dist/core/ingestion/languages/typescript/file-candidates.d.ts +29 -0
  344. package/dist/core/ingestion/languages/typescript/file-candidates.js +70 -0
  345. package/dist/core/ingestion/languages/typescript/import-decomposer.d.ts +28 -1
  346. package/dist/core/ingestion/languages/typescript/import-decomposer.js +125 -10
  347. package/dist/core/ingestion/languages/typescript/import-target.d.ts +25 -37
  348. package/dist/core/ingestion/languages/typescript/import-target.js +24 -26
  349. package/dist/core/ingestion/languages/typescript/interpret.d.ts +21 -1
  350. package/dist/core/ingestion/languages/typescript/interpret.js +45 -5
  351. package/dist/core/ingestion/languages/typescript/module-resolution.d.ts +48 -0
  352. package/dist/core/ingestion/languages/typescript/module-resolution.js +171 -0
  353. package/dist/core/ingestion/languages/typescript/query.d.ts +1 -0
  354. package/dist/core/ingestion/languages/typescript/query.js +303 -14
  355. package/dist/core/ingestion/languages/typescript/receiver-binding.d.ts +17 -0
  356. package/dist/core/ingestion/languages/typescript/receiver-binding.js +27 -0
  357. package/dist/core/ingestion/languages/typescript/scope-resolver.js +27 -40
  358. package/dist/core/ingestion/languages/typescript/simple-hooks.d.ts +0 -10
  359. package/dist/core/ingestion/languages/typescript/simple-hooks.js +22 -22
  360. package/dist/core/ingestion/languages/typescript/tsconfig.d.ts +59 -0
  361. package/dist/core/ingestion/languages/typescript/tsconfig.js +292 -0
  362. package/dist/core/ingestion/languages/typescript.js +93 -2
  363. package/dist/core/ingestion/languages/vue/import-target.d.ts +6 -22
  364. package/dist/core/ingestion/languages/vue/import-target.js +11 -47
  365. package/dist/core/ingestion/languages/vue/scope-resolver.js +4 -2
  366. package/dist/core/ingestion/local-symbol-pruner.js +11 -11
  367. package/dist/core/ingestion/method-extractors/configs/csharp.js +1 -0
  368. package/dist/core/ingestion/method-extractors/generic.js +1 -0
  369. package/dist/core/ingestion/method-types.d.ts +16 -0
  370. package/dist/core/ingestion/pipeline-phases/di.d.ts +1 -1
  371. package/dist/core/ingestion/pipeline-phases/di.js +136 -21
  372. package/dist/core/ingestion/pipeline-phases/index.d.ts +2 -0
  373. package/dist/core/ingestion/pipeline-phases/index.js +2 -0
  374. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +15 -0
  375. package/dist/core/ingestion/pipeline-phases/parse-impl.js +154 -4
  376. package/dist/core/ingestion/pipeline-phases/parse.js +5 -0
  377. package/dist/core/ingestion/pipeline-phases/processes.d.ts +3 -2
  378. package/dist/core/ingestion/pipeline-phases/processes.js +91 -6
  379. package/dist/core/ingestion/pipeline-phases/routes.js +116 -25
  380. package/dist/core/ingestion/pipeline-phases/spring-aop.d.ts +34 -0
  381. package/dist/core/ingestion/pipeline-phases/spring-aop.js +439 -0
  382. package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.d.ts +34 -0
  383. package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.js +255 -0
  384. package/dist/core/ingestion/pipeline-phases/types.d.ts +7 -0
  385. package/dist/core/ingestion/pipeline.d.ts +26 -2
  386. package/dist/core/ingestion/pipeline.js +60 -11
  387. package/dist/core/ingestion/process-processor.d.ts +109 -2
  388. package/dist/core/ingestion/process-processor.js +464 -52
  389. package/dist/core/ingestion/resolve-references.d.ts +6 -1
  390. package/dist/core/ingestion/resolve-references.js +66 -6
  391. package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +8 -2
  392. package/dist/core/ingestion/route-extractors/constant-resolver.js +11 -7
  393. package/dist/core/ingestion/route-extractors/data-route-table.d.ts +40 -0
  394. package/dist/core/ingestion/route-extractors/data-route-table.js +876 -0
  395. package/dist/core/ingestion/route-extractors/dispatch-guard.d.ts +96 -0
  396. package/dist/core/ingestion/route-extractors/dispatch-guard.js +1184 -0
  397. package/dist/core/ingestion/route-extractors/java-const-resolver.d.ts +114 -0
  398. package/dist/core/ingestion/route-extractors/java-const-resolver.js +569 -0
  399. package/dist/core/ingestion/route-extractors/js-const-resolver.d.ts +192 -0
  400. package/dist/core/ingestion/route-extractors/js-const-resolver.js +1033 -0
  401. package/dist/core/ingestion/route-extractors/nest.d.ts +53 -0
  402. package/dist/core/ingestion/route-extractors/nest.js +523 -0
  403. package/dist/core/ingestion/route-extractors/spring-shared.d.ts +11 -0
  404. package/dist/core/ingestion/route-extractors/spring-shared.js +89 -0
  405. package/dist/core/ingestion/route-extractors/spring.js +214 -29
  406. package/dist/core/ingestion/scope-extractor-bridge.js +9 -1
  407. package/dist/core/ingestion/scope-extractor.d.ts +22 -7
  408. package/dist/core/ingestion/scope-extractor.js +309 -15
  409. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +311 -21
  410. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.js +16 -5
  411. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +12 -0
  412. package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +47 -0
  413. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.d.ts +20 -15
  414. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +280 -42
  415. package/dist/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.d.ts +123 -0
  416. package/dist/core/ingestion/scope-resolution/graph-bridge/imports-to-edges.js +171 -17
  417. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.d.ts +58 -1
  418. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +137 -34
  419. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +30 -1
  420. package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +39 -1
  421. package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.d.ts +18 -1
  422. package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.js +113 -18
  423. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.d.ts +107 -5
  424. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.js +590 -33
  425. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +3 -0
  426. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +101 -41
  427. package/dist/core/ingestion/scope-resolution/passes/imported-value-refs.d.ts +34 -0
  428. package/dist/core/ingestion/scope-resolution/passes/imported-value-refs.js +62 -0
  429. package/dist/core/ingestion/scope-resolution/passes/property-dispatch.d.ts +5 -1
  430. package/dist/core/ingestion/scope-resolution/passes/property-dispatch.js +8 -1
  431. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +105 -5
  432. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +931 -92
  433. package/dist/core/ingestion/scope-resolution/passes/return-shape-members.d.ts +58 -0
  434. package/dist/core/ingestion/scope-resolution/passes/return-shape-members.js +458 -0
  435. package/dist/core/ingestion/scope-resolution/passes/unique-name-properties.d.ts +180 -0
  436. package/dist/core/ingestion/scope-resolution/passes/unique-name-properties.js +418 -0
  437. package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +29 -0
  438. package/dist/core/ingestion/scope-resolution/pipeline/phase.js +57 -0
  439. package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +55 -1
  440. package/dist/core/ingestion/scope-resolution/pipeline/run.js +241 -19
  441. package/dist/core/ingestion/scope-resolution/resolution-outcome.d.ts +112 -2
  442. package/dist/core/ingestion/scope-resolution/resolution-outcome.js +38 -1
  443. package/dist/core/ingestion/scope-resolution/scope/namespace-targets.d.ts +25 -3
  444. package/dist/core/ingestion/scope-resolution/scope/namespace-targets.js +36 -16
  445. package/dist/core/ingestion/scope-resolution/scope/walkers.d.ts +210 -9
  446. package/dist/core/ingestion/scope-resolution/scope/walkers.js +905 -22
  447. package/dist/core/ingestion/scope-resolution/summary-maps.d.ts +28 -0
  448. package/dist/core/ingestion/scope-resolution/summary-maps.js +50 -0
  449. package/dist/core/ingestion/scope-resolution/undecided-satisfaction.d.ts +55 -0
  450. package/dist/core/ingestion/scope-resolution/undecided-satisfaction.js +37 -0
  451. package/dist/core/ingestion/scope-resolution/unresolved-receivers.d.ts +109 -0
  452. package/dist/core/ingestion/scope-resolution/unresolved-receivers.js +204 -0
  453. package/dist/core/ingestion/scope-resolution/utils/definition-id.d.ts +13 -0
  454. package/dist/core/ingestion/scope-resolution/utils/definition-id.js +19 -0
  455. package/dist/core/ingestion/scope-resolution/utils/generic-instantiation.d.ts +171 -0
  456. package/dist/core/ingestion/scope-resolution/utils/generic-instantiation.js +218 -0
  457. package/dist/core/ingestion/scope-resolution/workspace-index-types.d.ts +34 -0
  458. package/dist/core/ingestion/scope-resolution/workspace-index-types.js +15 -0
  459. package/dist/core/ingestion/scope-resolution/workspace-index.d.ts +7 -20
  460. package/dist/core/ingestion/tree-sitter-queries.d.ts +11 -11
  461. package/dist/core/ingestion/tree-sitter-queries.js +678 -4
  462. package/dist/core/ingestion/type-env.js +11 -7
  463. package/dist/core/ingestion/type-extractors/shared.d.ts +17 -0
  464. package/dist/core/ingestion/type-extractors/shared.js +16 -0
  465. package/dist/core/ingestion/type-extractors/types.d.ts +12 -0
  466. package/dist/core/ingestion/type-extractors/typescript.d.ts +20 -0
  467. package/dist/core/ingestion/type-extractors/typescript.js +26 -0
  468. package/dist/core/ingestion/utils/ast-helpers.d.ts +297 -15
  469. package/dist/core/ingestion/utils/ast-helpers.js +578 -46
  470. package/dist/core/ingestion/utils/call-analysis.d.ts +27 -22
  471. package/dist/core/ingestion/utils/call-analysis.js +202 -7
  472. package/dist/core/ingestion/utils/callable-flow-captures.d.ts +59 -0
  473. package/dist/core/ingestion/utils/callable-flow-captures.js +51 -1
  474. package/dist/core/ingestion/utils/callable-labels.d.ts +25 -0
  475. package/dist/core/ingestion/utils/callable-labels.js +31 -0
  476. package/dist/core/ingestion/utils/effective-ram.d.ts +40 -0
  477. package/dist/core/ingestion/utils/effective-ram.js +58 -0
  478. package/dist/core/ingestion/utils/line-base.d.ts +14 -0
  479. package/dist/core/ingestion/utils/line-base.js +14 -0
  480. package/dist/core/ingestion/utils/method-props.d.ts +27 -4
  481. package/dist/core/ingestion/utils/method-props.js +29 -4
  482. package/dist/core/ingestion/utils/receiver-chain-captures.d.ts +31 -0
  483. package/dist/core/ingestion/utils/receiver-chain-captures.js +57 -0
  484. package/dist/core/ingestion/utils/receiver-chain-codec.d.ts +89 -0
  485. package/dist/core/ingestion/utils/receiver-chain-codec.js +182 -0
  486. package/dist/core/ingestion/utils/scope-tree-walk.d.ts +22 -0
  487. package/dist/core/ingestion/utils/scope-tree-walk.js +33 -0
  488. package/dist/core/ingestion/utils/template-arguments.d.ts +96 -0
  489. package/dist/core/ingestion/utils/template-arguments.js +196 -0
  490. package/dist/core/ingestion/utils/type-parameters.d.ts +49 -0
  491. package/dist/core/ingestion/utils/type-parameters.js +206 -0
  492. package/dist/core/ingestion/workers/callable-id.d.ts +80 -0
  493. package/dist/core/ingestion/workers/callable-id.js +125 -0
  494. package/dist/core/ingestion/workers/parse-worker.d.ts +14 -1
  495. package/dist/core/ingestion/workers/parse-worker.js +493 -54
  496. package/dist/core/ingestion/workers/worker-pool.d.ts +20 -27
  497. package/dist/core/ingestion/workers/worker-pool.js +91 -3
  498. package/dist/core/lbug/csv-generator.d.ts +27 -0
  499. package/dist/core/lbug/csv-generator.js +72 -17
  500. package/dist/core/lbug/extension-load-error.js +13 -2
  501. package/dist/core/lbug/extension-loader.d.ts +29 -0
  502. package/dist/core/lbug/extension-loader.js +31 -6
  503. package/dist/core/lbug/graph-emit-sink.d.ts +264 -0
  504. package/dist/core/lbug/graph-emit-sink.js +581 -0
  505. package/dist/core/lbug/lbug-adapter.d.ts +290 -11
  506. package/dist/core/lbug/lbug-adapter.js +652 -69
  507. package/dist/core/lbug/native-check.d.ts +21 -0
  508. package/dist/core/lbug/native-check.js +248 -32
  509. package/dist/core/lbug/pdg-emit-sink.d.ts +13 -4
  510. package/dist/core/lbug/pdg-emit-sink.js +21 -111
  511. package/dist/core/lbug/pool-adapter.d.ts +9 -0
  512. package/dist/core/lbug/pool-adapter.js +164 -14
  513. package/dist/core/lbug/query-batch.d.ts +75 -0
  514. package/dist/core/lbug/query-batch.js +102 -0
  515. package/dist/core/lbug/rel-pair-routing.d.ts +160 -2
  516. package/dist/core/lbug/rel-pair-routing.js +228 -10
  517. package/dist/core/lbug/schema.d.ts +163 -4
  518. package/dist/core/lbug/schema.js +404 -159
  519. package/dist/core/lbug/sync-csv-writer.d.ts +47 -0
  520. package/dist/core/lbug/sync-csv-writer.js +108 -0
  521. package/dist/core/run-analyze.d.ts +147 -0
  522. package/dist/core/run-analyze.js +1215 -179
  523. package/dist/core/search/bm25-index.d.ts +11 -0
  524. package/dist/core/search/bm25-index.js +60 -26
  525. package/dist/core/search/fts-indexes.d.ts +150 -9
  526. package/dist/core/search/fts-indexes.js +241 -23
  527. package/dist/core/wiki/graph-queries.js +145 -112
  528. package/dist/core/wiki/llm-client.d.ts +29 -3
  529. package/dist/core/wiki/llm-client.js +47 -12
  530. package/dist/core/wiki/prompts.d.ts +19 -0
  531. package/dist/core/wiki/prompts.js +20 -1
  532. package/dist/lib/utils.d.ts +113 -0
  533. package/dist/lib/utils.js +185 -0
  534. package/dist/mcp/local/aop-metadata.d.ts +77 -0
  535. package/dist/mcp/local/aop-metadata.js +227 -0
  536. package/dist/mcp/local/bean-metadata.d.ts +2 -1
  537. package/dist/mcp/local/bean-metadata.js +22 -1
  538. package/dist/mcp/local/convex-metadata.d.ts +8 -0
  539. package/dist/mcp/local/convex-metadata.js +45 -0
  540. package/dist/mcp/local/local-backend.d.ts +174 -11
  541. package/dist/mcp/local/local-backend.js +1678 -331
  542. package/dist/mcp/local/path-predicate.d.ts +19 -0
  543. package/dist/mcp/local/path-predicate.js +21 -0
  544. package/dist/mcp/local/pdg-impact.d.ts +132 -10
  545. package/dist/mcp/local/pdg-impact.js +391 -98
  546. package/dist/mcp/repository-policy.d.ts +1 -0
  547. package/dist/mcp/repository-policy.js +5 -0
  548. package/dist/mcp/resources.js +26 -4
  549. package/dist/mcp/server.js +23 -13
  550. package/dist/mcp/tools.d.ts +8 -0
  551. package/dist/mcp/tools.js +76 -23
  552. package/dist/server/analyze-job.d.ts +37 -2
  553. package/dist/server/analyze-job.js +13 -2
  554. package/dist/server/analyze-launch.d.ts +1 -1
  555. package/dist/server/analyze-launch.js +79 -10
  556. package/dist/server/analyze-worker-core.d.ts +1 -1
  557. package/dist/server/analyze-worker-core.js +10 -1
  558. package/dist/server/analyze-worker-ipc.d.ts +1 -1
  559. package/dist/server/analyze-worker-ipc.js +4 -0
  560. package/dist/server/analyze-worker-protocol.d.ts +59 -0
  561. package/dist/server/analyze-worker-protocol.js +1 -0
  562. package/dist/server/analyze-worker.d.ts +1 -17
  563. package/dist/server/api.d.ts +2 -11
  564. package/dist/server/api.js +164 -163
  565. package/dist/server/embed-run-outcome.d.ts +89 -0
  566. package/dist/server/embed-run-outcome.js +88 -0
  567. package/dist/server/git-clone.js +6 -2
  568. package/dist/server/middleware.d.ts +116 -9
  569. package/dist/server/middleware.js +291 -22
  570. package/dist/server/sse-progress.d.ts +41 -0
  571. package/dist/server/sse-progress.js +125 -0
  572. package/dist/storage/branch-index.d.ts +11 -6
  573. package/dist/storage/branch-index.js +15 -7
  574. package/dist/storage/file-hash.js +2 -2
  575. package/dist/storage/fs-atomic.d.ts +25 -0
  576. package/dist/storage/fs-atomic.js +42 -0
  577. package/dist/storage/git.d.ts +131 -0
  578. package/dist/storage/git.js +236 -2
  579. package/dist/storage/index-lock.d.ts +102 -0
  580. package/dist/storage/index-lock.js +660 -0
  581. package/dist/storage/parse-cache.js +588 -6
  582. package/dist/storage/parsedfile-store.js +76 -6
  583. package/dist/storage/repo-manager.d.ts +54 -441
  584. package/dist/storage/repo-manager.js +312 -221
  585. package/dist/storage/repo-meta.d.ts +530 -0
  586. package/dist/storage/repo-meta.js +100 -0
  587. package/dist/types/pipeline.d.ts +37 -0
  588. package/hooks/antigravity/gitnexus-antigravity-hook.cjs +1 -1
  589. package/hooks/claude/gitnexus-hook.cjs +1 -1
  590. package/hooks/claude/resolve-analyze-cmd.cjs +80 -13
  591. package/package.json +11 -2
  592. package/scripts/cross-platform-shard.ts +153 -0
  593. package/scripts/cross-platform-tests.ts +122 -0
  594. package/scripts/run-cross-platform.ts +16 -5
  595. package/skills/gitnexus-cli.md +3 -3
  596. package/skills/gitnexus-debugging.md +37 -7
  597. package/skills/gitnexus-exploring.md +26 -4
  598. package/skills/gitnexus-impact-analysis.md +71 -10
  599. package/skills/gitnexus-plan/README.md +11 -6
  600. package/skills/gitnexus-plan/references/evidence-provenance.md +49 -12
  601. package/skills/gitnexus-plan/scripts/evidence-provenance.mjs +654 -372
  602. package/skills/gitnexus-refactoring.md +48 -5
  603. package/skills/gitnexus-review/SKILL.md +12 -6
  604. package/skills/gitnexus-review/ci-personas/ci-adversarial-lens.md +1 -1
  605. package/skills/gitnexus-review/ci-personas/ci-blast-radius-lens.md +1 -1
  606. package/skills/gitnexus-review/ci-personas/ci-correctness-lens.md +1 -1
  607. package/skills/gitnexus-review/ci-personas/ci-coverage-lens.md +1 -1
  608. package/skills/gitnexus-review/ci-personas/ci-critic-lens.md +1 -1
  609. package/skills/gitnexus-review/ci-personas/ci-security-lens.md +1 -1
  610. package/skills/gitnexus-taint-analysis.md +13 -7
  611. package/skills/gitnexus-work/SKILL.md +4 -1
  612. package/skills/gitnexus-work/references/evidence-provenance.md +49 -12
  613. package/skills/gitnexus-work/scripts/evidence-provenance.mjs +654 -372
  614. package/vendor/leiden/utils.cjs +28 -1
  615. package/web/assets/ProcessFlowModal-Badh2Pbg.js +24 -0
  616. package/web/assets/{__vite-browser-external-bMKyYQkO.js → __vite-browser-external-COxE8F0G.js} +1 -1
  617. package/web/assets/abnfDiagram-QNN2D4NM-Cq2djWWe.js +1 -0
  618. package/web/assets/agent-Dr4l5EOp.js +662 -0
  619. package/web/assets/architecture-TIHT7OUA-V6N4J3SY-fTePvLoe.js +1 -0
  620. package/web/assets/architectureDiagram-OT7VKSJ7-mKEXxkeF.js +36 -0
  621. package/web/assets/{blockDiagram-7IZFK4PR-DBefcjof.js → blockDiagram-54WLDVWM-Dg_hrRWE.js} +4 -4
  622. package/web/assets/{c4Diagram-Y2BXMSZH-EjWnjEJl.js → c4Diagram-X2LASM7V-CnhoT4aV.js} +2 -2
  623. package/web/assets/chunk-224SPVON-B8gxtXpy.js +1 -0
  624. package/web/assets/chunk-2AEHWXPW-CV4r6-1I.js +127 -0
  625. package/web/assets/chunk-2SREHG4O-Dip42xOq.js +1 -0
  626. package/web/assets/chunk-4RFN2BYJ-DHHWuC-n.js +1 -0
  627. package/web/assets/chunk-66DQ2XMT-CM0xjFAN.js +1 -0
  628. package/web/assets/chunk-6BELYETK-ChsYtfHW.js +1 -0
  629. package/web/assets/{chunk-LII3EMHJ-BL6lKJ_P.js → chunk-6L755F7B-CMhLBxi2.js} +1 -1
  630. package/web/assets/{chunk-QA3QBVWF-DVXPOIxe.js → chunk-7CWYLC5S-DRgGkkpF.js} +1 -1
  631. package/web/assets/{chunk-ZXARS5L4-C3v-4Fsw.js → chunk-A7VWPJGB-B4O3oQdQ.js} +1 -1
  632. package/web/assets/chunk-BI6VK774-D0oaWk8V.js +1 -0
  633. package/web/assets/chunk-D6VWDJW2-BxcBdZ9c.js +2 -0
  634. package/web/assets/chunk-DMV4VAQV-Bn6WXDSX.js +4 -0
  635. package/web/assets/chunk-E5QJAATJ-dh-5CtIV.js +2 -0
  636. package/web/assets/chunk-EQFTRU2I-1ix7TzW9.js +2 -0
  637. package/web/assets/chunk-FWYVLQTC-BgDItRzJ.js +1 -0
  638. package/web/assets/chunk-HNC4WDU7-DoU3KnA7.js +1 -0
  639. package/web/assets/chunk-L5GCOVLC-CE2w8Nm_.js +161 -0
  640. package/web/assets/chunk-LAHSG3N2-Bz4hcn0N.js +321 -0
  641. package/web/assets/chunk-LORZLZWG-B57uGw2N.js +88 -0
  642. package/web/assets/chunk-NLANEA3F-XpH_NPA5.js +62 -0
  643. package/web/assets/chunk-NV3KIAZN-5yvcpMiu.js +1 -0
  644. package/web/assets/chunk-OIYT25JQ-CQ6KOZGX.js +1 -0
  645. package/web/assets/chunk-PE7DX7ZZ-CCvRVj43.js +10 -0
  646. package/web/assets/chunk-Q67WD55A-BWCH2SVz.js +156 -0
  647. package/web/assets/chunk-RRFMTAIC-CMN0wcYA.js +1 -0
  648. package/web/assets/{chunk-RLI5ZMPA-CkXZ0y0U.js → chunk-SATU7PGQ-B1zhgOvc.js} +1 -1
  649. package/web/assets/chunk-STOV2HOB-GnExfzIX.js +1 -0
  650. package/web/assets/{chunk-INKRHTLW-Ckl3_KkO.js → chunk-SZD42YQK-ijyKKVr1.js} +21 -21
  651. package/web/assets/{chunk-LCXTWHL2-C162wE5z.js → chunk-TFPGFQPA-Dj6a-0pC.js} +3 -3
  652. package/web/assets/chunk-TGVD4F4B-BMc31Gj2.js +2 -0
  653. package/web/assets/chunk-TZUXEDM2-B7p9AcTw.js +1 -0
  654. package/web/assets/chunk-UAT7B5JY-DW-A_fpI.js +1 -0
  655. package/web/assets/{chunk-6764PJDD-C7xxk063.js → chunk-VE5CLXGZ-C1vB7wpY.js} +1 -1
  656. package/web/assets/{chunk-RG4AUYOV-ZNgyLFq6.js → chunk-VJFVEZTB-CX66F2ep.js} +3 -3
  657. package/web/assets/chunk-VY5UBI4V-yxPQAWxw.js +1 -0
  658. package/web/assets/chunk-WJBAP47W-BckNkuEN.js +1 -0
  659. package/web/assets/chunk-XNMVGMAZ-Cg_LnPtj.js +1 -0
  660. package/web/assets/classDiagram-VPOSVPXH-BjOiXA_C.js +1 -0
  661. package/web/assets/classDiagram-v2-5VFNUXQA-BjOiXA_C.js +1 -0
  662. package/web/assets/{cose-bilkent-UX7MHV2Q-BmnZ7Mvj.js → cose-bilkent-RZA4XIPR-BHpK4Crp.js} +1 -1
  663. package/web/assets/cynefin-VYW2F7L2-2VAHYKR6-DAsF6GZv.js +1 -0
  664. package/web/assets/cynefinDiagram-TR7LZUCG-C3Iar9lZ.js +62 -0
  665. package/web/assets/dagre-K64A6Z3X-CUwi79mA.js +4 -0
  666. package/web/assets/diagram-2TLGJV2N-C2F5Nfym.js +30 -0
  667. package/web/assets/diagram-JCD7PQ7C-DC5-9FRr.js +24 -0
  668. package/web/assets/{diagram-HNR7UZ2L-DVRltWbL.js → diagram-KFBZAVDW-Dfmf_4ti.js} +3 -3
  669. package/web/assets/diagram-L7DVE3PN-GIRyVUtt.js +41 -0
  670. package/web/assets/diagram-YP3FGXHI-CyNFYtkd.js +24 -0
  671. package/web/assets/ebnfDiagram-DRHRQJWO-D8_CI4ZF.js +1 -0
  672. package/web/assets/erDiagram-SZLJLQMB-CohQjznC.js +85 -0
  673. package/web/assets/error-D9MtuG9s.js +1 -0
  674. package/web/assets/eventmodeling-45OFAUF4-AOUJWSLX-BvTc6iQi.js +1 -0
  675. package/web/assets/flowDiagram-BWE6NHOH-B6RnEvD9.js +1 -0
  676. package/web/assets/ganttDiagram-2QTCJSNI-Cks_mEcF.js +292 -0
  677. package/web/assets/gitGraph-TEB2WS4Q-U5VWYIBC-Dy7CCSZ5.js +1 -0
  678. package/web/assets/gitGraphDiagram-VVZAVV5G-CG41cIVc.js +106 -0
  679. package/web/assets/{index-D7mTFcvQ.js → index-2zdvEdzg.js} +51 -51
  680. package/web/assets/index-CJDpyH-n.css +2 -0
  681. package/web/assets/info-DKCQHKI2-DX6KST54-BLJg1ikX.js +1 -0
  682. package/web/assets/infoDiagram-FY4PZKRE-BJ3vPVwW.js +2 -0
  683. package/web/assets/{ishikawaDiagram-BNXS4ZKH-XpjJRU9h.js → ishikawaDiagram-4JDSWWDM-DmqWtjkl.js} +2 -2
  684. package/web/assets/{journeyDiagram-M6C3CM3L-C6wjooas.js → journeyDiagram-QUS3FAKT-XAzVzrQW.js} +3 -3
  685. package/web/assets/{kanban-definition-75IXJCU3-5_UVY79g.js → kanban-definition-D4L7SQKK-YurRnmYn.js} +6 -6
  686. package/web/assets/katex-C5OPUE3Q-Bnbavtmu.js +257 -0
  687. package/web/assets/{mindmap-definition-2TDM6QVE-8xDLzk2e.js → mindmap-definition-66QP5TD6-ChrWWnil.js} +5 -5
  688. package/web/assets/node.browser-U-KyT5AW.js +1 -0
  689. package/web/assets/packet-7NZHBO7P-5WG45QPS-KUxcuvaA.js +1 -0
  690. package/web/assets/pegDiagram-YKIO5C6U-QGeQLEq2.js +1 -0
  691. package/web/assets/pie-RZYD4A2V-2OCZ2VTD-DPs08kJY.js +1 -0
  692. package/web/assets/pieDiagram-YPY3TKG5-BuT3MYzm.js +39 -0
  693. package/web/assets/{quadrantDiagram-VICAPDV7-DR54jOeR.js → quadrantDiagram-VO5QLCXA-B7098wSc.js} +3 -3
  694. package/web/assets/radar-I7S5WNFK-EPLSA35B-w5F0K3a7.js +1 -0
  695. package/web/assets/railroad-3IZDKUUU-PWFQV6Y6-Bu668yqY.js +1 -0
  696. package/web/assets/railroad-abnf-AHOZXSZD-JYYJX3BS-B6ghpETS.js +1 -0
  697. package/web/assets/railroad-ebnf-EBAXGLYW-RBZ4ONAP-D-XmHh3M.js +1 -0
  698. package/web/assets/railroad-peg-LSFZ7HO6-KHNPXGPG-mhkrhzEn.js +1 -0
  699. package/web/assets/railroadDiagram-M77LTMSB-AXu4vxk_.js +1 -0
  700. package/web/assets/{requirementDiagram-JXO7QTGE-PEkg7sKC.js → requirementDiagram-RASO5HTO-B-l8InpK.js} +4 -4
  701. package/web/assets/{sankeyDiagram-URQDO5SZ-DDWEtjcs.js → sankeyDiagram-F32LOJ6L-Kd7zjJgX.js} +3 -3
  702. package/web/assets/{sequenceDiagram-VS2MUI6T-Bv-uwANx.js → sequenceDiagram-URATNSBD-BlcdY9DS.js} +7 -7
  703. package/web/assets/sizeCapture-5GORAGP4-BEqQzsxs.js +1 -0
  704. package/web/assets/src-C5sx_gMp.js +1 -0
  705. package/web/assets/stateDiagram-DODFXNG5-DTdHc-fF.js +1 -0
  706. package/web/assets/stateDiagram-v2-JNMM5JRA-DioNLDDo.js +1 -0
  707. package/web/assets/swimlanes-OSWOYLSK-CA0ofdwY.js +2 -0
  708. package/web/assets/swimlanesDiagram-RHGX2RDE-PkwUdckC.js +8 -0
  709. package/web/assets/{timeline-definition-O6YCAMPW-Qmsuo7qS.js → timeline-definition-WJXWRH4I-DUfp1R3E.js} +3 -3
  710. package/web/assets/treeView-QDETBFTQ-EHYTSQNO-C5lpBgPm.js +1 -0
  711. package/web/assets/treemap-6X3UGDF4-CCWCF7EK-BB0ZyO-B.js +1 -0
  712. package/web/assets/vennDiagram-K3VCMQLI-Bj-FN-XS.js +34 -0
  713. package/web/assets/wardley-OPB4EBWU-6OWERDVT-CEA3Nq0j.js +1 -0
  714. package/web/assets/wardleyDiagram-XK6FUAWV-CVV0dHFr.js +78 -0
  715. package/web/assets/xychartDiagram-5VRUVLCW-CK_rbSWE.js +7 -0
  716. package/web/index.html +16 -15
  717. package/dist/core/ingestion/languages/python/index-stats.d.ts +0 -18
  718. package/dist/core/ingestion/languages/python/index-stats.js +0 -25
  719. package/web/assets/ProcessFlowModal-CwkpVkv-.js +0 -22
  720. package/web/assets/agent-Ds-lkZjX.js +0 -626
  721. package/web/assets/architecture-7EHR7CIX-6QZW5X65-BVWFvYz2.js +0 -1
  722. package/web/assets/architectureDiagram-UL44E2DR-CmG3uPWf.js +0 -36
  723. package/web/assets/chunk-2T2R6R2M-Bb6Sy3_j.js +0 -4
  724. package/web/assets/chunk-2UTLFMKG-CXlhF3Pt.js +0 -1
  725. package/web/assets/chunk-3SSMPTDK-rPsRM1x0.js +0 -321
  726. package/web/assets/chunk-4R4BOZG6-Be_F0JoX.js +0 -159
  727. package/web/assets/chunk-67TQ5CYL-CA7OhIEf.js +0 -124
  728. package/web/assets/chunk-7J6CGLKN-BlKwgXKs.js +0 -10
  729. package/web/assets/chunk-C62D2QBJ-3gdL8EKc.js +0 -1
  730. package/web/assets/chunk-CEXFNPSA-CjwtMDkc.js +0 -1
  731. package/web/assets/chunk-J5EP6P6S-L19oz55R.js +0 -1
  732. package/web/assets/chunk-KGFNY3KK-BZeP-55u.js +0 -62
  733. package/web/assets/chunk-KGYTTC2M-zm6n242I.js +0 -1
  734. package/web/assets/chunk-KNLZD3CH-BGlP6X9R.js +0 -1
  735. package/web/assets/chunk-LRIF4GLE-n59lhprL.js +0 -1
  736. package/web/assets/chunk-RERM46MO-B5dAdWpP.js +0 -1
  737. package/web/assets/chunk-RKZBBQEN-MyIQbGgD.js +0 -1
  738. package/web/assets/chunk-T2UQINTJ-BEyXhZWe.js +0 -1
  739. package/web/assets/chunk-UP6H54XL-BG-n7qDp.js +0 -1
  740. package/web/assets/chunk-UXSXWOXI-CW1_r5cS.js +0 -1
  741. package/web/assets/chunk-UY5QBCOK-ByqTVLvh.js +0 -1
  742. package/web/assets/chunk-VU6ZFW4Y-BLeasdkU.js +0 -2
  743. package/web/assets/classDiagram-KGZ6W3CR-olpO3fMe.js +0 -1
  744. package/web/assets/classDiagram-v2-72OJOZXJ-olpO3fMe.js +0 -1
  745. package/web/assets/dagre-ND4H6XIP-CY4iIF7v.js +0 -4
  746. package/web/assets/diagram-3NCE3AQN-CO6QpzEE.js +0 -43
  747. package/web/assets/diagram-GF46GFSD-B2atbzmU.js +0 -24
  748. package/web/assets/diagram-QXG6HAR7-DR6AHD2h.js +0 -24
  749. package/web/assets/diagram-WEQXMOUZ-DkpoMwTL.js +0 -10
  750. package/web/assets/erDiagram-L5TCEMPS-n8g_90bc.js +0 -85
  751. package/web/assets/eventmodeling-FCH6USID-MREXMVOE-CgFBM7e-.js +0 -1
  752. package/web/assets/flowDiagram-H6V6AXG4-SGMDiCkB.js +0 -162
  753. package/web/assets/ganttDiagram-JCBTUEKG-Cb3UBqRS.js +0 -292
  754. package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DCJv7SII.js +0 -1
  755. package/web/assets/gitGraphDiagram-S2ZK5IYY-Bs9CR7tq.js +0 -106
  756. package/web/assets/index-CX_fADmQ.css +0 -2
  757. package/web/assets/info-J43DQDTF-KCYPFFUO-BfNy-9Nd.js +0 -1
  758. package/web/assets/infoDiagram-3YFTVSEB-T368on4D.js +0 -2
  759. package/web/assets/katex-K3KEBU37-qRQBy-EZ.js +0 -261
  760. package/web/assets/node-Ct_zna8U.js +0 -8
  761. package/web/assets/packet-YPE3B663-LP52Z2RK-D4qkeG9k.js +0 -1
  762. package/web/assets/pie-LRSECV5Y-TCRJHUBD-B_yMKyQa.js +0 -1
  763. package/web/assets/pieDiagram-CU6KROY3-Bv4LpAbr.js +0 -30
  764. package/web/assets/radar-GUYGQ44K-RDLRG3WG-DeD6yN_0.js +0 -1
  765. package/web/assets/sdk-CzHHH8tD.js +0 -37
  766. package/web/assets/src-Cv1eWg0o.js +0 -1
  767. package/web/assets/stateDiagram-7D4R322I-DVNjmkEq.js +0 -1
  768. package/web/assets/stateDiagram-v2-36443NZ5-CyN4Fh7_.js +0 -1
  769. package/web/assets/treeView-BLDUP644-QA4HXRO3-CDuSYnd4.js +0 -1
  770. package/web/assets/treemap-LRROVOQU-LLAWBHMP-imazucyJ.js +0 -1
  771. package/web/assets/vennDiagram-MWXL3ELB-BD1iK1SX.js +0 -34
  772. package/web/assets/wardley-L42UT6IY-5TKZOOLJ-DqrT9tB8.js +0 -1
  773. package/web/assets/wardleyDiagram-CUQ6CDDI-D6TzLVob.js +0 -78
  774. package/web/assets/xychartDiagram-N2JHSOCM-CoZ_Tits.js +0 -7
  775. /package/web/assets/{chunk-7W6UQGC5-pyKGssV3.js → chunk-LIEV3EAG-pyKGssV3.js} +0 -0
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Detects execution flows (Processes) in the code graph by:
5
5
  * 1. Finding entry points (functions with no internal callers)
6
- * 2. Tracing forward via CALLS edges (BFS)
6
+ * 2. Tracing forward via CALLS edges (DFS)
7
7
  * 3. Grouping and deduplicating similar paths
8
8
  * 4. Labeling with heuristic names
9
9
  *
@@ -19,6 +19,16 @@ const DEFAULT_CONFIG = {
19
19
  maxProcesses: 75,
20
20
  minSteps: 3, // 3+ steps = genuine multi-hop flow (2-step is just "A calls B")
21
21
  };
22
+ /** Zeroed counters, mutated in place by the walk. */
23
+ const emptyTruncation = () => ({
24
+ truncated: false,
25
+ entryPointCandidatesDropped: 0,
26
+ entryPointsUnexplored: 0,
27
+ walksCutByBudget: 0,
28
+ tracesDepthCapped: 0,
29
+ calleesDropped: 0,
30
+ processesDropped: 0,
31
+ });
22
32
  // ============================================================================
23
33
  // MAIN PROCESSOR
24
34
  // ============================================================================
@@ -27,8 +37,16 @@ const DEFAULT_CONFIG = {
27
37
  *
28
38
  * This runs AFTER community detection, using CALLS edges to trace flows.
29
39
  */
30
- export const processProcesses = async (knowledgeGraph, memberships, onProgress, config = {}) => {
40
+ export const processProcesses = async (knowledgeGraph, memberships, onProgress, config = {},
41
+ /**
42
+ * Places the program reaches outward — fetch calls and ORM queries, each with
43
+ * a file and a line (R3-6). Attributed to their enclosing function to form the
44
+ * sink set; omitted, behaviour is exactly as before.
45
+ */
46
+ outwardActionSites = []) => {
31
47
  const cfg = { ...DEFAULT_CONFIG, ...config };
48
+ const sinkFunctions = buildSinkFunctionSet(knowledgeGraph, outwardActionSites);
49
+ const isSink = (nodeId) => sinkFunctions.has(nodeId);
32
50
  onProgress?.('Finding entry points...', 0);
33
51
  // Build lookup maps
34
52
  const membershipMap = new Map();
@@ -38,31 +56,153 @@ export const processProcesses = async (knowledgeGraph, memberships, onProgress,
38
56
  const nodeMap = new Map();
39
57
  for (const n of knowledgeGraph.iterNodes())
40
58
  nodeMap.set(n.id, n);
59
+ // Declared before Step 1 because `findEntryPoints` has a ceiling of its own
60
+ // (see `ENTRY_POINT_CANDIDATE_LIMIT`) and reports it through the same record.
61
+ const truncation = emptyTruncation();
41
62
  // Step 1: Find entry points (functions that call others but have few callers)
42
- const entryPoints = findEntryPoints(knowledgeGraph, reverseCallsEdges, callsEdges);
63
+ const entryPoints = findEntryPoints(knowledgeGraph, reverseCallsEdges, callsEdges, truncation);
43
64
  onProgress?.(`Found ${entryPoints.length} entry points, tracing flows...`, 20);
44
65
  onProgress?.(`Found ${entryPoints.length} entry points, tracing flows...`, 20);
45
66
  // Step 2: Trace processes from each entry point
46
67
  const allTraces = [];
68
+ let tracedEntryPoints = 0;
47
69
  for (let i = 0; i < entryPoints.length && allTraces.length < cfg.maxProcesses * 2; i++) {
48
70
  const entryId = entryPoints[i];
49
- const traces = traceFromEntryPoint(entryId, callsEdges, cfg);
71
+ const traces = traceFromEntryPoint(entryId, callsEdges, cfg, isSink, truncation);
72
+ tracedEntryPoints = i + 1;
50
73
  // Filter out traces that are too short
51
74
  traces.filter((t) => t.length >= cfg.minSteps).forEach((t) => allTraces.push(t));
52
75
  if (i % 10 === 0) {
53
76
  onProgress?.(`Tracing entry point ${i + 1}/${entryPoints.length}...`, 20 + (i / entryPoints.length) * 40);
54
77
  }
55
78
  }
79
+ // The loop exits on the TRACE quota, not on running out of entry points, so
80
+ // the remainder are not "no flows found" — they were never looked at.
81
+ //
82
+ // Counted over the list `findEntryPoints` RETURNS, which is already capped at
83
+ // `ENTRY_POINT_CANDIDATE_LIMIT`; candidates beyond that cap are invisible here
84
+ // by construction and are reported separately as
85
+ // `entryPointCandidatesDropped`.
86
+ truncation.entryPointsUnexplored = entryPoints.length - tracedEntryPoints;
56
87
  onProgress?.(`Found ${allTraces.length} traces, deduplicating...`, 60);
57
88
  // Step 3: Deduplicate similar traces (subset removal)
58
- const uniqueTraces = deduplicateTraces(allTraces);
89
+ const uniqueTraces = deduplicateTraces(allTraces, isSink);
59
90
  // Step 3b: Deduplicate by entry+terminal pair (keep longest path per pair)
60
91
  const endpointDeduped = deduplicateByEndpoints(uniqueTraces);
61
92
  onProgress?.(`Deduped ${uniqueTraces.length} → ${endpointDeduped.length} unique endpoint pairs`, 70);
62
- // Step 4: Limit to max processes (prioritize longer traces)
63
- const limitedTraces = endpointDeduped
64
- .sort((a, b) => b.length - a.length)
65
- .slice(0, cfg.maxProcesses);
93
+ // Step 4: Limit to max processes — deepest first, but ROUND-ROBIN across
94
+ // TERMINALS (R2-3).
95
+ //
96
+ // Ranking was `sort by length` alone, and the top of that list was one
97
+ // behaviour described many ways: measured on the reporting repo, eleven of
98
+ // the top fourteen processes were four entry points crossed with three
99
+ // terminals of the same date-window utility cluster — `Handle ->
100
+ // AlignWindowEnd`, `Main -> AlignWindowStart`, `ProcessSymbol ->
101
+ // ResolveGridIntervalMs`. Genuine call chains, but a reader learns one thing
102
+ // from fourteen entries.
103
+ //
104
+ // Keyed on the TERMINAL, not the entry point. Keying on the entry was tried
105
+ // first and made it worse — many files declare a `main`, so each was a
106
+ // distinct entry that round-robin then awarded its own slot, and
107
+ // `Main -> AlignWindowEnd` went from one row to eight. The repetition was
108
+ // never in where a flow starts; it is in where flows pile up.
109
+ //
110
+ // Depth still orders within a terminal and still leads the list, since
111
+ // insertion order here is deepest-first. What changes is that no terminal
112
+ // takes a second slot until every other has had a first. Measured: distinct
113
+ // terminals in the top 20 went 3 -> 20, and the repo's own domain flows
114
+ // (`ReconcilePositions -> ...`) moved into the top 4%.
115
+ //
116
+ // What this does NOT do, recorded so it does not read as settled: the
117
+ // reported cause — ranking rewarding fan-in, promoting chains ending in
118
+ // widely-called helpers — measured FALSE. Those terminals have one caller
119
+ // each (`alignWindowStart` 1, `validateSymbol` 1). A fan-in discount was
120
+ // implemented against that hypothesis and moved nothing.
121
+ //
122
+ // R3-6 adds one rule ahead of depth: a SINK-terminated trace outranks a
123
+ // leaf-terminated one. A flow that ends where the program does something —
124
+ // places an order, writes a row — is what a reader came for; a chain that
125
+ // ends in a date helper is where control happened to stop. Depth still orders
126
+ // within each group.
127
+ //
128
+ // This is what closed the gap that used to be described here as out of reach:
129
+ // a business flow could not be a process in its own right, because the walk
130
+ // emitted only at a leaf, at max depth, or on a cycle, so a flow whose
131
+ // meaningful endpoint calls onward survived only as whatever leaf it bottomed
132
+ // out in. Ranking could never fix it — the flow was not a candidate to rank.
133
+ // It is bounded honestly rather than fully closed: sinks are exactly where
134
+ // fetch/ORM extraction fires (see `buildSinkFunctionSet`), so a codebase whose
135
+ // outward calls are not detected as such still sees leaf-terminated traces
136
+ // only.
137
+ // DETERMINISM. The comparator below ranks by sink-ness then by depth, and for
138
+ // two flows equal on both it returned 0. `Array.prototype.sort` is stable, so
139
+ // a 0 preserves INPUT order — which traces back to `graph.iterNodes()`, i.e.
140
+ // the order files happened to be inserted. Under `maxProcesses` capping that
141
+ // decided which `Process` and `STEP_IN_PROCESS` nodes were persisted at all.
142
+ //
143
+ // Reproduced: two equal three-step flows with `maxProcesses: 1` select
144
+ // `handleAlpha`; inserting the identical nodes and CALLS edges in reverse
145
+ // select `handleBeta`. Same repository, same commit, different persisted
146
+ // graph — so an incremental run that reorders assembly, or a filesystem that
147
+ // enumerates differently, silently changes what the tool reports.
148
+ //
149
+ // The id is the tiebreak because it is the only totally-ordered, content-derived
150
+ // key available here; comparing the whole path keeps it stable when two traces
151
+ // share a terminal.
152
+ //
153
+ // MUTATION STATUS, recorded so nobody mistakes this for a verified guard:
154
+ // removing THIS tiebreak alone fails nothing, because the two dedup sorts
155
+ // below already impose a total order on the list that reaches here. The
156
+ // entry-point sort and the dedup sorts each ARE individually verified. This
157
+ // one is kept as defence in depth — it cannot misbehave (it only makes an
158
+ // already-deterministic order explicit) and it is what stops a future change
159
+ // to dedup ordering from silently re-opening the defect.
160
+ //
161
+ // Decorated once and sorted on the precomputed key rather than joining inside
162
+ // the comparator — see `traceOrderKey` for why the key exists at all and
163
+ // `sortByDepthThenPath` for why it is built exactly once per trace. The sink
164
+ // test is hoisted for the same reason: it ran twice per comparison.
165
+ const tracesByTerminal = new Map();
166
+ const rankedByInterest = (() => {
167
+ const decorated = endpointDeduped.map((trace) => ({
168
+ trace,
169
+ sink: isSink(trace[trace.length - 1] ?? '') ? 1 : 0,
170
+ key: traceOrderKey(trace),
171
+ }));
172
+ decorated.sort((a, b) => b.sink - a.sink || b.trace.length - a.trace.length || compareOrderKeys(a.key, b.key));
173
+ return decorated.map((d) => d.trace);
174
+ })();
175
+ for (const trace of rankedByInterest) {
176
+ const terminalId = trace[trace.length - 1];
177
+ if (terminalId === undefined)
178
+ continue;
179
+ const existing = tracesByTerminal.get(terminalId);
180
+ if (existing === undefined)
181
+ tracesByTerminal.set(terminalId, [trace]);
182
+ else
183
+ existing.push(trace);
184
+ }
185
+ // Insertion order is deepest-trace-first, so the round-robin visits terminals
186
+ // in that order too and depth still leads the list.
187
+ const limitedTraces = [];
188
+ for (let round = 0; limitedTraces.length < cfg.maxProcesses; round++) {
189
+ let addedAny = false;
190
+ for (const traces of tracesByTerminal.values()) {
191
+ const trace = traces[round];
192
+ if (trace === undefined)
193
+ continue;
194
+ limitedTraces.push(trace);
195
+ addedAny = true;
196
+ if (limitedTraces.length >= cfg.maxProcesses)
197
+ break;
198
+ }
199
+ if (!addedAny)
200
+ break;
201
+ }
202
+ // Counted against the DEDUPED input, not `allTraces`: the difference between
203
+ // those two is deduplication doing its job, which is not truncation.
204
+ const dedupedAvailable = [...tracesByTerminal.values()].reduce((n, t) => n + t.length, 0);
205
+ truncation.processesDropped = dedupedAvailable - limitedTraces.length;
66
206
  onProgress?.(`Creating ${limitedTraces.length} process nodes...`, 80);
67
207
  // Step 5: Create process nodes
68
208
  const processes = [];
@@ -113,6 +253,24 @@ export const processProcesses = async (knowledgeGraph, memberships, onProgress,
113
253
  const avgStepCount = processes.length > 0
114
254
  ? processes.reduce((sum, p) => sum + p.stepCount, 0) / processes.length
115
255
  : 0;
256
+ // Derived last, from the counters the walk accumulated, so a new ceiling added
257
+ // later cannot be forgotten here — it only has to increment its own counter.
258
+ //
259
+ // That claim was wrong when it was written: `findEntryPoints`' 200-candidate
260
+ // slice was an EXISTING ceiling with no counter, so it was not merely
261
+ // forgettable, it had already been forgotten. Adding a counter is only half
262
+ // the discipline; the other half is checking, when you write a line like this,
263
+ // that every cap in the file actually has one.
264
+ truncation.truncated =
265
+ truncation.entryPointCandidatesDropped > 0 ||
266
+ truncation.entryPointsUnexplored > 0 ||
267
+ truncation.walksCutByBudget > 0 ||
268
+ truncation.tracesDepthCapped > 0 ||
269
+ truncation.calleesDropped > 0 ||
270
+ truncation.processesDropped > 0;
271
+ if (truncation.truncated) {
272
+ logger.debug({ truncation }, 'process-processor: detection was truncated by one or more caps');
273
+ }
116
274
  return {
117
275
  processes,
118
276
  steps,
@@ -121,6 +279,7 @@ export const processProcesses = async (knowledgeGraph, memberships, onProgress,
121
279
  crossCommunityCount,
122
280
  avgStepCount: Math.round(avgStepCount * 10) / 10,
123
281
  entryPointsFound: entryPoints.length,
282
+ truncation,
124
283
  },
125
284
  };
126
285
  };
@@ -132,28 +291,37 @@ export const processProcesses = async (knowledgeGraph, memberships, onProgress,
132
291
  const MIN_TRACE_CONFIDENCE = 0.5;
133
292
  const buildCallsGraph = (graph) => {
134
293
  const adj = new Map();
135
- for (const rel of graph.iterRelationships()) {
136
- if (rel.type === 'CALLS' && rel.confidence >= MIN_TRACE_CONFIDENCE) {
137
- if (!adj.has(rel.sourceId)) {
138
- adj.set(rel.sourceId, []);
139
- }
140
- adj.get(rel.sourceId).push(rel.targetId);
141
- }
142
- }
294
+ // Field-wise scan (#2680) — whole-graph walk, four fields, no object needed.
295
+ graph.forEachRelationshipFields((sourceId, targetId, type, confidence) => {
296
+ if (type !== 'CALLS' || confidence < MIN_TRACE_CONFIDENCE)
297
+ return;
298
+ const existing = adj.get(sourceId);
299
+ if (existing === undefined)
300
+ adj.set(sourceId, [targetId]);
301
+ else
302
+ existing.push(targetId);
303
+ });
143
304
  return adj;
144
305
  };
145
306
  const buildReverseCallsGraph = (graph) => {
146
307
  const adj = new Map();
147
- for (const rel of graph.iterRelationships()) {
148
- if (rel.type === 'CALLS' && rel.confidence >= MIN_TRACE_CONFIDENCE) {
149
- if (!adj.has(rel.targetId)) {
150
- adj.set(rel.targetId, []);
151
- }
152
- adj.get(rel.targetId).push(rel.sourceId);
153
- }
154
- }
308
+ graph.forEachRelationshipFields((sourceId, targetId, type, confidence) => {
309
+ if (type !== 'CALLS' || confidence < MIN_TRACE_CONFIDENCE)
310
+ return;
311
+ const existing = adj.get(targetId);
312
+ if (existing === undefined)
313
+ adj.set(targetId, [sourceId]);
314
+ else
315
+ existing.push(sourceId);
316
+ });
155
317
  return adj;
156
318
  };
319
+ /**
320
+ * How many ranked candidates survive to be traced. Everything below this line
321
+ * is discarded — see `ProcessTruncationStats.entryPointCandidatesDropped`, the
322
+ * counter that exists because this cap spent a release being invisible.
323
+ */
324
+ const ENTRY_POINT_CANDIDATE_LIMIT = 200;
157
325
  /**
158
326
  * Find functions/methods that are good entry points for tracing.
159
327
  *
@@ -164,7 +332,15 @@ const buildReverseCallsGraph = (graph) => {
164
332
  *
165
333
  * Test files are excluded entirely.
166
334
  */
167
- const findEntryPoints = (graph, reverseCallsEdges, callsEdges) => {
335
+ const findEntryPoints = (graph, reverseCallsEdges, callsEdges,
336
+ /**
337
+ * Mutated in place when the candidate cap fires. Optional and reported
338
+ * through an out-parameter rather than a richer return value, matching
339
+ * `traceFromEntryPoint`: the `string[]` contract every caller already uses is
340
+ * unchanged, and a caller that does not care about completeness does not have
341
+ * to unwrap a counter to ask for entry points.
342
+ */
343
+ truncation) => {
168
344
  const symbolTypes = new Set(['Function', 'Method']);
169
345
  const entryPointCandidates = [];
170
346
  for (const node of graph.iterNodes()) {
@@ -191,8 +367,12 @@ const findEntryPoints = (graph, reverseCallsEdges, callsEdges) => {
191
367
  entryPointCandidates.push({ id: node.id, score, reasons });
192
368
  }
193
369
  }
194
- // Sort by score descending and return top candidates
195
- const sorted = entryPointCandidates.sort((a, b) => b.score - a.score);
370
+ // Sort by score descending, then by node id. Ties on score are common — most
371
+ // candidates share a heuristic bucket — and a stable sort resolves them by
372
+ // `iterNodes()` order, so which entry points survive the `slice` below became
373
+ // a function of file insertion order. See the determinism note on
374
+ // `rankedByInterest`.
375
+ const sorted = entryPointCandidates.sort((a, b) => b.score - a.score || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
196
376
  // DEBUG: Log top candidates with new scoring details
197
377
  if (sorted.length > 0 && isDev) {
198
378
  logger.info(`[Process] Top 10 entry point candidates (new scoring):`);
@@ -204,24 +384,66 @@ const findEntryPoints = (graph, reverseCallsEdges, callsEdges) => {
204
384
  logger.info(` score: ${c.score.toFixed(2)} = [${c.reasons.join(' × ')}]`);
205
385
  });
206
386
  }
207
- return sorted
208
- .slice(0, 200) // Limit to prevent explosion
209
- .map((c) => c.id);
387
+ // Limit to prevent explosion — and SAY SO. This is the ceiling that decides
388
+ // how much of a repository process detection ever looks at: on anything with
389
+ // more than 200 scoring candidates the reported flows are a sample of the
390
+ // top-ranked ones, and every downstream count (`entryPointsFound`,
391
+ // `entryPointsUnexplored`) is computed over the survivors, so none of them can
392
+ // see what was cut here.
393
+ if (truncation !== undefined && sorted.length > ENTRY_POINT_CANDIDATE_LIMIT) {
394
+ truncation.entryPointCandidatesDropped = sorted.length - ENTRY_POINT_CANDIDATE_LIMIT;
395
+ }
396
+ return sorted.slice(0, ENTRY_POINT_CANDIDATE_LIMIT).map((c) => c.id);
210
397
  };
211
398
  // ============================================================================
212
- // HELPER: Trace from entry point (BFS)
399
+ // HELPER: Trace from entry point (DFS)
213
400
  // ============================================================================
214
401
  /**
215
- * Trace forward from an entry point using BFS.
402
+ * Trace forward from an entry point using DEPTH-first search.
216
403
  * Returns all distinct paths up to maxDepth.
217
404
  */
218
- const traceFromEntryPoint = (entryId, callsEdges, config) => {
405
+ // Exported for tests ONLY: traversal order is the whole behaviour here, and it
406
+ // is unobservable through `processProcesses` because `findEntryPoints` supplies
407
+ // several starting points — a deep chain gets traced from inside it regardless
408
+ // of order, so a test at that level passes under either traversal and pins
409
+ // nothing.
410
+ export const traceFromEntryPoint = (entryId, callsEdges, config,
411
+ /**
412
+ * Functions that reach outward (R3-6). A trace also ENDS here, even though
413
+ * the walk continues past it: a flow whose meaningful endpoint calls onward
414
+ * was otherwise never a candidate, only ever surviving as whatever leaf it
415
+ * bottomed out in.
416
+ */
417
+ isSink = () => false,
418
+ /**
419
+ * Mutated in place when a ceiling fires. Optional so the many direct callers
420
+ * in tests are unchanged, and because a caller that does not care about
421
+ * completeness should not have to invent a counter to ask for a trace.
422
+ */
423
+ truncation) => {
219
424
  const traces = [];
220
- // BFS with path tracking
221
- // Each queue item: [currentNodeId, pathSoFar]
222
- const queue = [[entryId, [entryId]]];
223
- while (queue.length > 0 && traces.length < config.maxBranching * 3) {
224
- const [currentId, path] = queue.shift();
425
+ // DEPTH-first, not breadth-first. Each stack item: [currentNodeId, pathSoFar].
426
+ //
427
+ // The walk stops after a fixed NUMBER of traces, so the traversal order
428
+ // decides which traces those are. Breadth-first reaches every shallow
429
+ // terminal before any deep one, so the quota filled with the shortest paths
430
+ // in the graph and the walk stopped — `maxTraceDepth` was never approached.
431
+ // Measured on a 75k-node repo: of 300 processes, none exceeded 7 steps and
432
+ // 90% were 3-4, so a multi-hop business flow (signal → order → exit) had no
433
+ // process that could represent it, and `query` could only rank the mechanical
434
+ // pairs that did exist.
435
+ //
436
+ // Depth-first descends to a terminal first, so the same quota is spent on
437
+ // paths worth keeping. Cost is unchanged — same budget, same cycle guard,
438
+ // same `maxTraceDepth` ceiling — only the ORDER of exploration differs, and
439
+ // the caller already sorts by length and dedupes by endpoint, so it was
440
+ // always asking for the deepest traces this walk could give it.
441
+ // A LIFO stack, not a queue — the name followed the traversal when this was
442
+ // breadth-first and was left behind by the change to depth-first.
443
+ const stack = [[entryId, [entryId]]];
444
+ const traceBudget = config.maxBranching * 3;
445
+ while (stack.length > 0 && traces.length < traceBudget) {
446
+ const [currentId, path] = stack.pop();
225
447
  // Get outgoing calls
226
448
  const callees = callsEdges.get(currentId) || [];
227
449
  if (callees.length === 0) {
@@ -231,19 +453,41 @@ const traceFromEntryPoint = (entryId, callsEdges, config) => {
231
453
  }
232
454
  }
233
455
  else if (path.length >= config.maxTraceDepth) {
234
- // Max depth reached - save what we have
456
+ // Max depth reached - save what we have. The trace is kept, but it is a
457
+ // PREFIX of a longer flow rather than a flow that ended, and only this
458
+ // counter distinguishes the two downstream.
459
+ if (truncation !== undefined)
460
+ truncation.tracesDepthCapped++;
235
461
  if (path.length >= config.minSteps) {
236
462
  traces.push([...path]);
237
463
  }
238
464
  }
239
465
  else {
466
+ // A SINK ends a trace without ending the walk (R3-6). Emitting here is
467
+ // what lets `placeOrder` be an endpoint while `placeOrder -> formatDate`
468
+ // still exists as its own longer trace; the two answer different
469
+ // questions and neither should suppress the other.
470
+ if (isSink(currentId) && path.length >= config.minSteps) {
471
+ traces.push([...path]);
472
+ }
240
473
  // Continue tracing - limit branching
241
474
  const limitedCallees = callees.slice(0, config.maxBranching);
475
+ if (truncation !== undefined && callees.length > limitedCallees.length) {
476
+ truncation.calleesDropped += callees.length - limitedCallees.length;
477
+ }
242
478
  let addedBranch = false;
243
- for (const calleeId of limitedCallees) {
479
+ // PUSHED IN REVERSE so the stack POPS them in source order. `slice`
480
+ // selects the first N callees while `pop()` takes the last pushed, so
481
+ // without this the walk spends its trace budget on the LAST-declared
482
+ // branch first: for `main() { init(); loadConfig(); run(); shutdown(); }`
483
+ // it explores `shutdown` first and can exhaust the quota before reaching
484
+ // `init` — dropping the earliest steps of a flow, which is the opposite
485
+ // of what a process is meant to describe. Selecting the first N and then
486
+ // exploring them last-first was simply inconsistent.
487
+ for (const calleeId of [...limitedCallees].reverse()) {
244
488
  // Avoid cycles
245
489
  if (!path.includes(calleeId)) {
246
- queue.push([calleeId, [...path, calleeId]]);
490
+ stack.push([calleeId, [...path, calleeId]]);
247
491
  addedBranch = true;
248
492
  }
249
493
  }
@@ -253,8 +497,130 @@ const traceFromEntryPoint = (entryId, callsEdges, config) => {
253
497
  }
254
498
  }
255
499
  }
500
+ // A silently truncating cap reads as "this is everything", which is the same
501
+ // class of confident-empty answer this work is about. The repo already sets
502
+ // this precedent for `dispatchFanoutSkipped` and
503
+ // `propertyDispatch.skippedKeys`.
504
+ //
505
+ // The debug line stays for the per-entry-point detail (which entry, how many
506
+ // branches); the counter is what escapes to a CONSUMER. A log nobody has
507
+ // enabled is not a disclosure.
508
+ if (stack.length > 0) {
509
+ if (truncation !== undefined)
510
+ truncation.walksCutByBudget++;
511
+ logger.debug({ entryId, traceBudget, unexploredBranches: stack.length }, 'process-processor: trace budget exhausted; unexplored branches remain for this entry point');
512
+ }
256
513
  return traces;
257
514
  };
515
+ const CALLABLE_SINK_LABELS = new Set([
516
+ 'Function',
517
+ 'Method',
518
+ 'Constructor',
519
+ ]);
520
+ /**
521
+ * Functions that DO something outward — issue a request, run a query (R3-6).
522
+ *
523
+ * The missing layer behind "business flows are never processes". A trace is
524
+ * only emitted at a node with NO outgoing calls, so a real flow — scan, score,
525
+ * arm, place the order — is always a PREFIX of some longer chain that runs on
526
+ * into date helpers and formatters, and can never be a process in its own
527
+ * right. Ending a trace somewhere meaningful needs a notion of an endpoint that
528
+ * is not a leaf, and the walk had none.
529
+ *
530
+ * GitNexus already knew where the program reaches outward: the parse phase
531
+ * collects fetch calls and ORM queries carrying `filePath` + `lineNumber`. Those
532
+ * facts only ever produced FILE-level edges (`File -[FETCHES]-> Route`), which
533
+ * is too coarse to end a trace on — every function in a file containing one
534
+ * would qualify. Attributing each site to the function whose range CONTAINS it
535
+ * turns the same facts into the function-level signal the walk needs, with no
536
+ * new extraction, no new relation pair, and no schema change.
537
+ *
538
+ * Innermost wins: a nested closure that performs the call is the sink, not the
539
+ * outer function that merely spans it.
540
+ */
541
+ export function buildSinkFunctionSet(graph, sites) {
542
+ const sinks = new Set();
543
+ if (sites.length === 0)
544
+ return sinks;
545
+ const byFile = new Map();
546
+ for (const node of graph.iterNodes()) {
547
+ if (!CALLABLE_SINK_LABELS.has(node.label))
548
+ continue;
549
+ const props = node.properties;
550
+ if (typeof props.filePath !== 'string')
551
+ continue;
552
+ if (typeof props.startLine !== 'number' || typeof props.endLine !== 'number')
553
+ continue;
554
+ const entry = { id: node.id, start: props.startLine, end: props.endLine };
555
+ const list = byFile.get(props.filePath);
556
+ if (list === undefined)
557
+ byFile.set(props.filePath, [entry]);
558
+ else
559
+ list.push(entry);
560
+ }
561
+ for (const site of sites) {
562
+ const candidates = byFile.get(site.filePath);
563
+ if (candidates === undefined)
564
+ continue;
565
+ let best;
566
+ for (const c of candidates) {
567
+ if (site.lineNumber < c.start || site.lineNumber > c.end)
568
+ continue;
569
+ if (best === undefined || c.end - c.start < best.end - best.start)
570
+ best = c;
571
+ }
572
+ if (best !== undefined)
573
+ sinks.add(best.id);
574
+ }
575
+ return sinks;
576
+ }
577
+ // ============================================================================
578
+ // HELPER: Deterministic trace ordering
579
+ // ============================================================================
580
+ /**
581
+ * Total-order key for a trace — the TIEBREAK every trace sort in this file uses.
582
+ *
583
+ * NUL is the separator, and that is load-bearing rather than cosmetic. Node ids
584
+ * embed file paths and a path may contain a SPACE, so a space-joined key is
585
+ * ambiguous in exactly the way `traceKey`'s unpadded `->` join was (#2894):
586
+ * `['A B', 'C']` and `['A', 'B C']` both render as `A B C`, the comparator
587
+ * returns 0, and `Array.prototype.sort` — being stable — falls straight back to
588
+ * the input order the tiebreak exists to remove. Two of the three trace sorts
589
+ * here joined on a space and had that hole; all three now share this key.
590
+ *
591
+ * NUL cannot occur in a node id (not in a POSIX path, not in a source
592
+ * identifier) and sorts below every character that can, so joining on it is
593
+ * order-equivalent to comparing the two arrays element by element. That
594
+ * equivalence is what makes it a drop-in for the space-joined keys: on any
595
+ * corpus without the collision above the resulting order is IDENTICAL, which is
596
+ * asserted directly in `process-processor.test.ts`.
597
+ */
598
+ const traceOrderKey = (trace) => trace.join('\u0000');
599
+ /** Lexicographic compare of two `traceOrderKey` results. */
600
+ const compareOrderKeys = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
601
+ /**
602
+ * Sort traces deepest-first, breaking ties on the path key.
603
+ *
604
+ * A Schwartzian transform: the key is built ONCE per trace and the comparator
605
+ * only compares two strings. Written the obvious way — `a.join(sep) <
606
+ * b.join(sep)` inside the comparator — each comparison allocates up to FOUR
607
+ * joined strings, so an O(n log n) sort performs O(n log n) joins of
608
+ * O(depth x id-length) characters each.
609
+ *
610
+ * `n` is bounded here (`ENTRY_POINT_CANDIDATE_LIMIT` entry points x the
611
+ * per-entry trace budget), so the cost is small and once-per-analyze: measured
612
+ * at the ceiling, 23,851 comparisons performed 70,524 joins, and end-to-end
613
+ * `processProcesses` at 80,000 functions / 640k CALLS went 456 -> 555 ms. It is
614
+ * fixed anyway because it is the same allocation-in-the-comparator shape that
615
+ * was just removed from `deduplicateTraces` below (deep_chain 1233 -> 102 ms),
616
+ * and leaving one instance of it standing next to that comment invites the next
617
+ * one.
618
+ */
619
+ const sortByDepthThenPath = (traces) => {
620
+ const decorated = traces.map((trace) => ({ trace, key: traceOrderKey(trace) }));
621
+ decorated.sort((a, b) => b.trace.length - a.trace.length || compareOrderKeys(a.key, b.key));
622
+ return decorated.map((d) => d.trace);
623
+ };
258
624
  // ============================================================================
259
625
  // HELPER: Deduplicate traces
260
626
  // ============================================================================
@@ -262,21 +628,65 @@ const traceFromEntryPoint = (entryId, callsEdges, config) => {
262
628
  * Merge traces that are subsets of other traces.
263
629
  * Keep longer traces, remove redundant shorter ones.
264
630
  */
265
- const deduplicateTraces = (traces) => {
631
+ export const deduplicateTraces = (traces,
632
+ /** See `buildSinkFunctionSet` — a sink-terminated trace survives subsumption. */
633
+ isSink = () => false) => {
266
634
  if (traces.length === 0)
267
635
  return [];
268
- // Sort by length descending
269
- const sorted = [...traces].sort((a, b) => b.length - a.length);
636
+ // Sort by length descending, then by path, so equal-length traces have a
637
+ // total order instead of inheriting graph-traversal order (determinism note
638
+ // on `rankedByInterest`). Which of two equal traces is kept as the
639
+ // representative is otherwise decided by insertion order.
640
+ const sorted = sortByDepthThenPath(traces);
270
641
  const unique = [];
642
+ // Keys for `unique`, built ONCE per surviving trace rather than once per
643
+ // COMPARISON. The join used to sit inside the `some()` callback below, so
644
+ // every already-kept trace had its key rebuilt from scratch against every
645
+ // candidate — O(T*U) joins of O(depth * id-length) characters, and it is that
646
+ // allocation, not the substring scan, that dominates the pass.
647
+ //
648
+ // Nothing about breadth-first search made that safe; it only kept the cost
649
+ // small by keeping traces short. Measured on this repo, the walk went from an
650
+ // average of 4.3 steps to 9.4 when D1 made it depth-first, which roughly
651
+ // doubles both the number of surviving traces and the length of every key —
652
+ // so the same quadratic that was affordable under BFS is ~6x the work under
653
+ // DFS. Hoisting the join removes the multiplication entirely.
654
+ const uniqueKeys = [];
271
655
  for (const trace of sorted) {
656
+ // A SINK-TERMINATED trace is never redundant (R3-6), even though it is by
657
+ // definition a prefix of the longer chain that runs on past the sink into
658
+ // helpers. That is the whole shape of a business flow — scan, score, arm,
659
+ // PLACE THE ORDER — so subsuming it here is exactly what kept such flows
660
+ // from ever being processes. Emitting one at the walk and deleting it one
661
+ // step later would have been a no-op fix.
662
+ const terminal = trace[trace.length - 1];
663
+ // PADDED with the separator on both ends, so `includes` can only match whole
664
+ // steps (#2894). Unpadded, the test is not anchored to a step boundary and a
665
+ // match may begin in the MIDDLE of a node id:
666
+ //
667
+ // 'X->AA->B'.includes('A->B') -> true
668
+ //
669
+ // which discards `A -> B` as redundant against a chain `A` is not a step of
670
+ // at all. Measured inert on every corpus tried — the collision needs one id
671
+ // to be a strict suffix of another, which real ids
672
+ // (`Function:<path>:<name>`) do not produce — but the predicate did not mean
673
+ // what the surrounding code says it means, and this is a function whose
674
+ // entire job is deciding what to delete.
675
+ //
676
+ // Note the encoding assumes `->` never appears IN a node id. A C++
677
+ // `operator->` would defeat the join regardless of padding; out of scope
678
+ // here, but the assumption is real.
679
+ const traceKey = `->${trace.join('->')}->`;
680
+ if (terminal !== undefined && isSink(terminal)) {
681
+ unique.push(trace);
682
+ uniqueKeys.push(traceKey);
683
+ continue;
684
+ }
272
685
  // Check if this trace is a subset of any already-added trace
273
- const traceKey = trace.join('->');
274
- const isSubset = unique.some((existing) => {
275
- const existingKey = existing.join('->');
276
- return existingKey.includes(traceKey);
277
- });
686
+ const isSubset = uniqueKeys.some((existingKey) => existingKey.includes(traceKey));
278
687
  if (!isSubset) {
279
688
  unique.push(trace);
689
+ uniqueKeys.push(traceKey);
280
690
  }
281
691
  }
282
692
  return unique;
@@ -292,8 +702,10 @@ const deduplicateByEndpoints = (traces) => {
292
702
  if (traces.length === 0)
293
703
  return [];
294
704
  const byEndpoints = new Map();
295
- // Sort longest first so the first seen per key is the longest
296
- const sorted = [...traces].sort((a, b) => b.length - a.length);
705
+ // Sort longest first so the first seen per key is the longest; the path
706
+ // tiebreak makes "which of two equal-length traces represents this endpoint
707
+ // pair" independent of insertion order.
708
+ const sorted = sortByDepthThenPath(traces);
297
709
  for (const trace of sorted) {
298
710
  const key = `${trace[0]}::${trace[trace.length - 1]}`;
299
711
  if (!byEndpoints.has(key)) {