@opensip-cli/graph 0.1.11 → 0.1.13

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 (236) hide show
  1. package/README.md +3 -3
  2. package/dist/__tests__/baseline-plane.test.js +8 -3
  3. package/dist/__tests__/baseline-plane.test.js.map +1 -1
  4. package/dist/__tests__/cache/engine-version.test.js +4 -4
  5. package/dist/__tests__/cache/engine-version.test.js.map +1 -1
  6. package/dist/__tests__/cli/graph-execute.test.js +25 -12
  7. package/dist/__tests__/cli/graph-execute.test.js.map +1 -1
  8. package/dist/__tests__/cli/graph.test.js +36 -21
  9. package/dist/__tests__/cli/graph.test.js.map +1 -1
  10. package/dist/__tests__/cli/language-mismatch.test.js +7 -2
  11. package/dist/__tests__/cli/language-mismatch.test.js.map +1 -1
  12. package/dist/__tests__/cli/lookup.test.js +32 -29
  13. package/dist/__tests__/cli/lookup.test.js.map +1 -1
  14. package/dist/__tests__/cli/session-contract.test.js +5 -1
  15. package/dist/__tests__/cli/session-contract.test.js.map +1 -1
  16. package/dist/__tests__/cli/symbol-index.test.js +9 -2
  17. package/dist/__tests__/cli/symbol-index.test.js.map +1 -1
  18. package/dist/__tests__/cli/tool-show-mode.test.js +7 -1
  19. package/dist/__tests__/cli/tool-show-mode.test.js.map +1 -1
  20. package/dist/__tests__/public-api.test.js +10 -0
  21. package/dist/__tests__/public-api.test.js.map +1 -1
  22. package/dist/__tests__/report-failure-mock.d.ts +8 -0
  23. package/dist/__tests__/report-failure-mock.d.ts.map +1 -0
  24. package/dist/__tests__/report-failure-mock.js +19 -0
  25. package/dist/__tests__/report-failure-mock.js.map +1 -0
  26. package/dist/__tests__/rules/registry.test.js +1 -0
  27. package/dist/__tests__/rules/registry.test.js.map +1 -1
  28. package/dist/__tests__/tool-branches.test.js +9 -2
  29. package/dist/__tests__/tool-branches.test.js.map +1 -1
  30. package/dist/__tests__/tool-register.test.js +26 -15
  31. package/dist/__tests__/tool-register.test.js.map +1 -1
  32. package/dist/baseline-strategy.d.ts +1 -2
  33. package/dist/baseline-strategy.d.ts.map +1 -1
  34. package/dist/baseline-strategy.js +6 -1
  35. package/dist/baseline-strategy.js.map +1 -1
  36. package/dist/cache/engine-version.d.ts.map +1 -1
  37. package/dist/cache/engine-version.js +5 -1
  38. package/dist/cache/engine-version.js.map +1 -1
  39. package/dist/cli/__tests__/dispatch-envelope.test.js +5 -1
  40. package/dist/cli/__tests__/dispatch-envelope.test.js.map +1 -1
  41. package/dist/cli/__tests__/dispatch-suppression-root.test.js +1 -0
  42. package/dist/cli/__tests__/dispatch-suppression-root.test.js.map +1 -1
  43. package/dist/cli/__tests__/equivalence-diagnostic.test.d.ts +7 -0
  44. package/dist/cli/__tests__/equivalence-diagnostic.test.d.ts.map +1 -0
  45. package/dist/cli/__tests__/equivalence-diagnostic.test.js +136 -0
  46. package/dist/cli/__tests__/equivalence-diagnostic.test.js.map +1 -0
  47. package/dist/cli/__tests__/graph-gate-mode.test.js +6 -0
  48. package/dist/cli/__tests__/graph-gate-mode.test.js.map +1 -1
  49. package/dist/cli/__tests__/graph-recipes.test.js +2 -2
  50. package/dist/cli/__tests__/graph-recipes.test.js.map +1 -1
  51. package/dist/cli/__tests__/list-files.test.js +45 -12
  52. package/dist/cli/__tests__/list-files.test.js.map +1 -1
  53. package/dist/cli/__tests__/live-suppression-parity.test.js +5 -1
  54. package/dist/cli/__tests__/live-suppression-parity.test.js.map +1 -1
  55. package/dist/cli/__tests__/lookup-result.test.d.ts +2 -0
  56. package/dist/cli/__tests__/lookup-result.test.d.ts.map +1 -0
  57. package/dist/cli/__tests__/lookup-result.test.js +119 -0
  58. package/dist/cli/__tests__/lookup-result.test.js.map +1 -0
  59. package/dist/cli/__tests__/shard-worker.test.js +2 -0
  60. package/dist/cli/__tests__/shard-worker.test.js.map +1 -1
  61. package/dist/cli/detect.d.ts.map +1 -1
  62. package/dist/cli/detect.js +4 -3
  63. package/dist/cli/detect.js.map +1 -1
  64. package/dist/cli/equivalence-check-command.d.ts.map +1 -1
  65. package/dist/cli/equivalence-check-command.js +64 -9
  66. package/dist/cli/equivalence-check-command.js.map +1 -1
  67. package/dist/cli/equivalence-diagnostic.d.ts +100 -0
  68. package/dist/cli/equivalence-diagnostic.d.ts.map +1 -0
  69. package/dist/cli/equivalence-diagnostic.js +138 -0
  70. package/dist/cli/equivalence-diagnostic.js.map +1 -0
  71. package/dist/cli/graph/graph-aux-command-specs.d.ts +2 -2
  72. package/dist/cli/graph/graph-aux-command-specs.d.ts.map +1 -1
  73. package/dist/cli/graph/graph-aux-command-specs.js +85 -51
  74. package/dist/cli/graph/graph-aux-command-specs.js.map +1 -1
  75. package/dist/cli/graph/graph-command-spec.d.ts.map +1 -1
  76. package/dist/cli/graph/graph-command-spec.js +3 -0
  77. package/dist/cli/graph/graph-command-spec.js.map +1 -1
  78. package/dist/cli/graph-config-schema.d.ts +3 -0
  79. package/dist/cli/graph-config-schema.d.ts.map +1 -1
  80. package/dist/cli/graph-config-schema.js +11 -0
  81. package/dist/cli/graph-config-schema.js.map +1 -1
  82. package/dist/cli/graph-config.d.ts.map +1 -1
  83. package/dist/cli/graph-config.js +9 -12
  84. package/dist/cli/graph-config.js.map +1 -1
  85. package/dist/cli/graph-envelope-view.d.ts.map +1 -1
  86. package/dist/cli/graph-envelope-view.js +1 -0
  87. package/dist/cli/graph-envelope-view.js.map +1 -1
  88. package/dist/cli/graph-modes.d.ts +5 -4
  89. package/dist/cli/graph-modes.d.ts.map +1 -1
  90. package/dist/cli/graph-modes.js +15 -18
  91. package/dist/cli/graph-modes.js.map +1 -1
  92. package/dist/cli/graph-recipes.d.ts.map +1 -1
  93. package/dist/cli/graph-recipes.js +12 -5
  94. package/dist/cli/graph-recipes.js.map +1 -1
  95. package/dist/cli/graph-result-delivery.d.ts.map +1 -1
  96. package/dist/cli/graph-result-delivery.js +11 -10
  97. package/dist/cli/graph-result-delivery.js.map +1 -1
  98. package/dist/cli/graph-single-run-mode.d.ts.map +1 -1
  99. package/dist/cli/graph-single-run-mode.js +3 -2
  100. package/dist/cli/graph-single-run-mode.js.map +1 -1
  101. package/dist/cli/graph-worker.d.ts.map +1 -1
  102. package/dist/cli/graph-worker.js +9 -2
  103. package/dist/cli/graph-worker.js.map +1 -1
  104. package/dist/cli/graph-workspace-mode.d.ts.map +1 -1
  105. package/dist/cli/graph-workspace-mode.js +3 -2
  106. package/dist/cli/graph-workspace-mode.js.map +1 -1
  107. package/dist/cli/graph.d.ts +2 -2
  108. package/dist/cli/graph.d.ts.map +1 -1
  109. package/dist/cli/graph.js +26 -28
  110. package/dist/cli/graph.js.map +1 -1
  111. package/dist/cli/heap-preflight.d.ts.map +1 -1
  112. package/dist/cli/heap-preflight.js +6 -5
  113. package/dist/cli/heap-preflight.js.map +1 -1
  114. package/dist/cli/list-files.d.ts.map +1 -1
  115. package/dist/cli/list-files.js +9 -4
  116. package/dist/cli/list-files.js.map +1 -1
  117. package/dist/cli/lookup-result.d.ts +4 -0
  118. package/dist/cli/lookup-result.d.ts.map +1 -0
  119. package/dist/cli/lookup-result.js +44 -0
  120. package/dist/cli/lookup-result.js.map +1 -0
  121. package/dist/cli/lookup.d.ts +12 -1
  122. package/dist/cli/lookup.d.ts.map +1 -1
  123. package/dist/cli/lookup.js +31 -30
  124. package/dist/cli/lookup.js.map +1 -1
  125. package/dist/cli/orchestrate/__tests__/cross-shard-resolve.test.js +76 -0
  126. package/dist/cli/orchestrate/__tests__/cross-shard-resolve.test.js.map +1 -1
  127. package/dist/cli/orchestrate/catalog-stats.d.ts.map +1 -1
  128. package/dist/cli/orchestrate/catalog-stats.js +0 -1
  129. package/dist/cli/orchestrate/catalog-stats.js.map +1 -1
  130. package/dist/cli/orchestrate/cross-shard-resolve.d.ts.map +1 -1
  131. package/dist/cli/orchestrate/cross-shard-resolve.js +77 -2
  132. package/dist/cli/orchestrate/cross-shard-resolve.js.map +1 -1
  133. package/dist/cli/orchestrate/flat-monorepo-strategy.d.ts.map +1 -1
  134. package/dist/cli/orchestrate/flat-monorepo-strategy.js +0 -1
  135. package/dist/cli/orchestrate/flat-monorepo-strategy.js.map +1 -1
  136. package/dist/cli/orchestrate/incremental-merge.d.ts.map +1 -1
  137. package/dist/cli/orchestrate/incremental-merge.js +3 -2
  138. package/dist/cli/orchestrate/incremental-merge.js.map +1 -1
  139. package/dist/cli/positional-paths.d.ts.map +1 -1
  140. package/dist/cli/positional-paths.js +3 -2
  141. package/dist/cli/positional-paths.js.map +1 -1
  142. package/dist/cli/pressure-monitor.d.ts +2 -0
  143. package/dist/cli/pressure-monitor.d.ts.map +1 -1
  144. package/dist/cli/pressure-monitor.js +15 -0
  145. package/dist/cli/pressure-monitor.js.map +1 -1
  146. package/dist/cli/report-data.d.ts.map +1 -1
  147. package/dist/cli/report-data.js +0 -1
  148. package/dist/cli/report-data.js.map +1 -1
  149. package/dist/cli/sarif-export.d.ts.map +1 -1
  150. package/dist/cli/sarif-export.js +4 -3
  151. package/dist/cli/sarif-export.js.map +1 -1
  152. package/dist/cli/symbol-index.d.ts.map +1 -1
  153. package/dist/cli/symbol-index.js +15 -14
  154. package/dist/cli/symbol-index.js.map +1 -1
  155. package/dist/cli/workspace-runner.d.ts.map +1 -1
  156. package/dist/cli/workspace-runner.js +5 -4
  157. package/dist/cli/workspace-runner.js.map +1 -1
  158. package/dist/index.d.ts +4 -0
  159. package/dist/index.d.ts.map +1 -1
  160. package/dist/index.js +5 -0
  161. package/dist/index.js.map +1 -1
  162. package/dist/lang-adapter/__tests__/language-of-file.test.d.ts +2 -0
  163. package/dist/lang-adapter/__tests__/language-of-file.test.d.ts.map +1 -0
  164. package/dist/lang-adapter/__tests__/language-of-file.test.js +36 -0
  165. package/dist/lang-adapter/__tests__/language-of-file.test.js.map +1 -0
  166. package/dist/lang-adapter/__tests__/near-duplicate-signature.test.d.ts +2 -0
  167. package/dist/lang-adapter/__tests__/near-duplicate-signature.test.d.ts.map +1 -0
  168. package/dist/lang-adapter/__tests__/near-duplicate-signature.test.js +78 -0
  169. package/dist/lang-adapter/__tests__/near-duplicate-signature.test.js.map +1 -0
  170. package/dist/lang-adapter/body-digest.d.ts +9 -41
  171. package/dist/lang-adapter/body-digest.d.ts.map +1 -1
  172. package/dist/lang-adapter/body-digest.js +9 -44
  173. package/dist/lang-adapter/body-digest.js.map +1 -1
  174. package/dist/lang-adapter/language-of-file.d.ts +15 -0
  175. package/dist/lang-adapter/language-of-file.d.ts.map +1 -0
  176. package/dist/lang-adapter/language-of-file.js +43 -0
  177. package/dist/lang-adapter/language-of-file.js.map +1 -0
  178. package/dist/lang-adapter/near-duplicate-signature.d.ts +12 -0
  179. package/dist/lang-adapter/near-duplicate-signature.d.ts.map +1 -0
  180. package/dist/lang-adapter/near-duplicate-signature.js +12 -0
  181. package/dist/lang-adapter/near-duplicate-signature.js.map +1 -0
  182. package/dist/lang-adapter/read-source.d.ts.map +1 -1
  183. package/dist/lang-adapter/read-source.js +0 -1
  184. package/dist/lang-adapter/read-source.js.map +1 -1
  185. package/dist/lang-adapter/registry.d.ts.map +1 -1
  186. package/dist/lang-adapter/registry.js +0 -1
  187. package/dist/lang-adapter/registry.js.map +1 -1
  188. package/dist/persistence/catalog-repo.d.ts.map +1 -1
  189. package/dist/persistence/catalog-repo.js +88 -81
  190. package/dist/persistence/catalog-repo.js.map +1 -1
  191. package/dist/persistence/session-payload.d.ts.map +1 -1
  192. package/dist/persistence/session-payload.js +0 -1
  193. package/dist/persistence/session-payload.js.map +1 -1
  194. package/dist/persistence/session-replay.d.ts.map +1 -1
  195. package/dist/persistence/session-replay.js +15 -25
  196. package/dist/persistence/session-replay.js.map +1 -1
  197. package/dist/pipeline/feature-deps.d.ts.map +1 -1
  198. package/dist/pipeline/feature-deps.js +0 -1
  199. package/dist/pipeline/feature-deps.js.map +1 -1
  200. package/dist/pipeline/features.d.ts.map +1 -1
  201. package/dist/pipeline/features.js +0 -1
  202. package/dist/pipeline/features.js.map +1 -1
  203. package/dist/pipeline/indexes.d.ts.map +1 -1
  204. package/dist/pipeline/indexes.js +0 -1
  205. package/dist/pipeline/indexes.js.map +1 -1
  206. package/dist/recipes/__tests__/resolve.test.js +7 -0
  207. package/dist/recipes/__tests__/resolve.test.js.map +1 -1
  208. package/dist/render/rule-id-mapping.d.ts.map +1 -1
  209. package/dist/render/rule-id-mapping.js +1 -0
  210. package/dist/render/rule-id-mapping.js.map +1 -1
  211. package/dist/rules/__tests__/fingerprint-golden.test.js +1 -1
  212. package/dist/rules/__tests__/fingerprint-golden.test.js.map +1 -1
  213. package/dist/rules/__tests__/near-duplicate-function-body.test.d.ts +2 -0
  214. package/dist/rules/__tests__/near-duplicate-function-body.test.d.ts.map +1 -0
  215. package/dist/rules/__tests__/near-duplicate-function-body.test.js +142 -0
  216. package/dist/rules/__tests__/near-duplicate-function-body.test.js.map +1 -0
  217. package/dist/rules/_entry-points.d.ts.map +1 -1
  218. package/dist/rules/_entry-points.js +0 -1
  219. package/dist/rules/_entry-points.js.map +1 -1
  220. package/dist/rules/duplicated-function-body.d.ts +12 -34
  221. package/dist/rules/duplicated-function-body.d.ts.map +1 -1
  222. package/dist/rules/duplicated-function-body.js +83 -233
  223. package/dist/rules/duplicated-function-body.js.map +1 -1
  224. package/dist/rules/near-duplicate-function-body.d.ts +11 -0
  225. package/dist/rules/near-duplicate-function-body.d.ts.map +1 -0
  226. package/dist/rules/near-duplicate-function-body.js +74 -0
  227. package/dist/rules/near-duplicate-function-body.js.map +1 -0
  228. package/dist/rules/registry.d.ts.map +1 -1
  229. package/dist/rules/registry.js +2 -1
  230. package/dist/rules/registry.js.map +1 -1
  231. package/dist/tool.d.ts.map +1 -1
  232. package/dist/tool.js +3 -1
  233. package/dist/tool.js.map +1 -1
  234. package/dist/types.d.ts +20 -0
  235. package/dist/types.d.ts.map +1 -1
  236. package/package.json +15 -13
@@ -1 +1 @@
1
- {"version":3,"file":"fingerprint-golden.test.js","sourceRoot":"","sources":["../../../src/rules/__tests__/fingerprint-golden.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAIzE,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,2BAA2B,CAAC,CAAC;AAE9E,MAAM,YAAY,GAAgB,EAAE,CAAC;AAErC,uEAAuE;AACvE,MAAM,KAAK,GAAoB;IAC7B,iBAAiB;IACjB,0BAA0B;IAC1B,oBAAoB;IACpB,qBAAqB;IACrB,sBAAsB;CACvB,CAAC;AAEF,SAAS,eAAe;IACtB,MAAM,OAAO,GAAG,oBAAoB,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC;YAC9E,YAAY,CAAC,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAC,IAAI,EAAE,CAAC;AAC7B,CAAC;AAED,QAAQ,CAAC,sDAAsD,EAAE,GAAG,EAAE;IACpE,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAa,CAAC;QAC7E,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,uEAAuE;QACvE,wEAAwE;QACxE,yEAAyE;QACzE,oDAAoD;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAa,CAAC;QAC3E,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,sBAAsB,EAAE,sBAAsB,CAAC,CAAC,CAAC;QAChG,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"fingerprint-golden.test.js","sourceRoot":"","sources":["../../../src/rules/__tests__/fingerprint-golden.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAIzE,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,2BAA2B,CAAC,CAAC;AAE9E,MAAM,YAAY,GAAgB,EAAE,CAAC;AAErC,uEAAuE;AACvE,MAAM,KAAK,GAAoB;IAC7B,iBAAiB;IACjB,0BAA0B;IAC1B,oBAAoB;IACpB,qBAAqB;IACrB,sBAAsB;CACvB,CAAC;AAEF,SAAS,eAAe;IACtB,MAAM,OAAO,GAAG,oBAAoB,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC;YAC9E,YAAY,CAAC,IAAI,CAAC,wBAAwB,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAC,IAAI,EAAE,CAAC;AAC7B,CAAC;AAED,QAAQ,CAAC,sDAAsD,EAAE,GAAG,EAAE;IACpE,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAa,CAAC;QAC7E,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,uEAAuE;QACvE,wEAAwE;QACxE,yEAAyE;QACzE,oDAAoD;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAa,CAAC;QAC3E,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,sBAAsB,EAAE,sBAAsB,CAAC,CAAC,CAAC;QAChG,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=near-duplicate-function-body.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"near-duplicate-function-body.test.d.ts","sourceRoot":"","sources":["../../../src/rules/__tests__/near-duplicate-function-body.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,142 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { makeCatalog, occ } from '../../__tests__/rules/_helpers.js';
3
+ import { NEAR_DUP_SIGNATURE_K, bodySignature, estimateJaccard, } from '../../lang-adapter/near-duplicate-signature.js';
4
+ import { buildIndexes } from '../../pipeline/indexes.js';
5
+ import { nearDuplicateFunctionBodyRule } from '../near-duplicate-function-body.js';
6
+ const PAYLOAD = 'abcdefghijklmnopqrstuvwxyz0123456789'.repeat(12);
7
+ const BASE_BODY = `function work(items) { const payload = "${PAYLOAD}"; let total = 0; for (const item of items) { total += item.length + payload.length; } return total; }`;
8
+ const NEAR_BODY = `function work(items) { const payload = "${PAYLOAD}"; let total = 0; for (const item of items) { total += item.length + payload.length + 1; } return total; }`;
9
+ const UNRELATED = 'export function validateConfig(cfg) { if (!cfg.apiKey) throw new Error("missing"); return cfg; }';
10
+ function withSignature(over, canonical) {
11
+ const signature = [...bodySignature(canonical)];
12
+ return occ({ ...over, bodySignature: signature, bodySize: canonical.length });
13
+ }
14
+ function evaluateNear(catalog, config = {}) {
15
+ return nearDuplicateFunctionBodyRule.evaluate(catalog, buildIndexes(catalog), config);
16
+ }
17
+ describe('near-duplicate-function-body', () => {
18
+ it('flags near-clone pairs above the similarity threshold', () => {
19
+ const sigA = bodySignature(BASE_BODY);
20
+ const sigB = bodySignature(NEAR_BODY);
21
+ expect(estimateJaccard(sigA, sigB)).toBeGreaterThanOrEqual(0.85);
22
+ const a = withSignature({
23
+ bodyHash: 'hash-a',
24
+ simpleName: 'processA',
25
+ filePath: 'src/a.ts',
26
+ line: 10,
27
+ }, BASE_BODY);
28
+ const b = withSignature({
29
+ bodyHash: 'hash-b',
30
+ simpleName: 'processB',
31
+ filePath: 'src/b.ts',
32
+ line: 20,
33
+ qualifiedName: 'src/b.processB',
34
+ }, NEAR_BODY);
35
+ const signals = evaluateNear(makeCatalog([a, b]));
36
+ expect(signals.length).toBe(1);
37
+ expect(signals[0]?.ruleId).toBe('graph:near-duplicate-function-body');
38
+ expect(signals[0]?.metadata?.nearMembers).toEqual(expect.arrayContaining(['src/a.processA', 'src/b.processB']));
39
+ });
40
+ it('does not flag exact-duplicate pairs (duplicated-function-body owns those)', () => {
41
+ const a = withSignature({ bodyHash: 'same', simpleName: 'dupA' }, BASE_BODY);
42
+ const b = withSignature({
43
+ bodyHash: 'same',
44
+ simpleName: 'dupB',
45
+ filePath: 'src/b.ts',
46
+ qualifiedName: 'src/b.dupB',
47
+ }, BASE_BODY);
48
+ const signals = evaluateNear(makeCatalog([a, b]));
49
+ expect(signals).toHaveLength(0);
50
+ });
51
+ it('skips test-file occurrences', () => {
52
+ const a = withSignature({ bodyHash: 'a', simpleName: 'a', inTestFile: true }, BASE_BODY);
53
+ const b = withSignature({
54
+ bodyHash: 'b',
55
+ simpleName: 'b',
56
+ filePath: 'src/b.ts',
57
+ qualifiedName: 'src/b.b',
58
+ }, NEAR_BODY);
59
+ const signals = evaluateNear(makeCatalog([a, b]));
60
+ expect(signals).toHaveLength(0);
61
+ });
62
+ it('is graceful when bodySignature is absent', () => {
63
+ const a = occ({ bodyHash: 'a', simpleName: 'a' });
64
+ const b = occ({ bodyHash: 'b', simpleName: 'b', filePath: 'src/b.ts' });
65
+ const signals = evaluateNear(makeCatalog([a, b]));
66
+ expect(signals).toHaveLength(0);
67
+ });
68
+ it('does not flag cross-language pairs (same-language gate)', () => {
69
+ const a = withSignature({ bodyHash: 'go-hash', simpleName: 'work', filePath: 'main.go', line: 1 }, BASE_BODY);
70
+ const b = withSignature({
71
+ bodyHash: 'ts-hash',
72
+ simpleName: 'work',
73
+ filePath: 'src/work.ts',
74
+ line: 1,
75
+ qualifiedName: 'src/work.work',
76
+ }, BASE_BODY);
77
+ const signals = evaluateNear(makeCatalog([a, b]));
78
+ expect(signals).toHaveLength(0);
79
+ });
80
+ it('merges transitive near pairs via union-find', () => {
81
+ const body1 = BASE_BODY;
82
+ const body2 = NEAR_BODY;
83
+ const body3 = body2.replace('+ 1', '+ 2');
84
+ const a = withSignature({ bodyHash: 'h1', simpleName: 'a', line: 1 }, body1);
85
+ const b = withSignature({
86
+ bodyHash: 'h2',
87
+ simpleName: 'b',
88
+ filePath: 'src/b.ts',
89
+ line: 2,
90
+ qualifiedName: 'src/b.b',
91
+ }, body2);
92
+ const c = withSignature({
93
+ bodyHash: 'h3',
94
+ simpleName: 'c',
95
+ filePath: 'src/c.ts',
96
+ line: 3,
97
+ qualifiedName: 'src/c.c',
98
+ }, body3);
99
+ expect(estimateJaccard(bodySignature(body1), bodySignature(body2))).toBeGreaterThanOrEqual(0.85);
100
+ expect(estimateJaccard(bodySignature(body2), bodySignature(body3))).toBeGreaterThanOrEqual(0.85);
101
+ const signals = evaluateNear(makeCatalog([a, b, c]), {
102
+ minNearDuplicateSimilarity: 0.85,
103
+ });
104
+ expect(signals.length).toBe(1);
105
+ expect((signals[0]?.metadata?.nearMembers).length).toBeGreaterThanOrEqual(2);
106
+ });
107
+ it('skips sub-threshold pairs', () => {
108
+ const a = withSignature({ bodyHash: 'a', simpleName: 'a' }, BASE_BODY);
109
+ const b = withSignature({
110
+ bodyHash: 'b',
111
+ simpleName: 'b',
112
+ filePath: 'src/b.ts',
113
+ qualifiedName: 'src/b.b',
114
+ }, UNRELATED);
115
+ const signals = evaluateNear(makeCatalog([a, b]), {
116
+ minNearDuplicateSimilarity: 0.85,
117
+ });
118
+ expect(signals).toHaveLength(0);
119
+ });
120
+ it('requires signature length === NEAR_DUP_SIGNATURE_K', () => {
121
+ const a = occ({ bodyHash: 'a', simpleName: 'a', bodySignature: [1, 2, 3] });
122
+ const b = occ({
123
+ bodyHash: 'b',
124
+ simpleName: 'b',
125
+ filePath: 'src/b.ts',
126
+ bodySignature: [1, 2, 3],
127
+ });
128
+ const signals = evaluateNear(makeCatalog([a, b]));
129
+ expect(signals).toHaveLength(0);
130
+ expect(NEAR_DUP_SIGNATURE_K).toBe(128);
131
+ });
132
+ it('emits nothing when nearDuplicateLshBands does not divide k (fractional rows)', () => {
133
+ // 128 / 7 is fractional → band slicing would be misaligned. The integer guard
134
+ // must reject it (the schema also refuses this value at config load).
135
+ const a = withSignature({ bodyHash: 'hash-a', simpleName: 'pA', filePath: 'src/a.ts' }, BASE_BODY);
136
+ const b = withSignature({ bodyHash: 'hash-b', simpleName: 'pB', filePath: 'src/b.ts', qualifiedName: 'src/b.pB' }, NEAR_BODY);
137
+ expect(evaluateNear(makeCatalog([a, b]), { nearDuplicateLshBands: 7 })).toHaveLength(0);
138
+ // ...but the same pair IS flagged with a valid divisor.
139
+ expect(evaluateNear(makeCatalog([a, b]), { nearDuplicateLshBands: 16 })).toHaveLength(1);
140
+ });
141
+ });
142
+ //# sourceMappingURL=near-duplicate-function-body.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"near-duplicate-function-body.test.js","sourceRoot":"","sources":["../../../src/rules/__tests__/near-duplicate-function-body.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"_entry-points.d.ts","sourceRoot":"","sources":["../../src/rules/_entry-points.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAsB,OAAO,EAAE,MAAM,aAAa,CAAC;AAYxE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,YAAY,GAAG,qBAAqB,GAAG,gBAAgB,CAAC;CAC1F;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,UAAU,EAAE,CAyB1F"}
1
+ {"version":3,"file":"_entry-points.d.ts","sourceRoot":"","sources":["../../src/rules/_entry-points.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAsB,OAAO,EAAE,MAAM,aAAa,CAAC;AAYxE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,YAAY,GAAG,qBAAqB,GAAG,gBAAgB,CAAC;CAC1F;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,UAAU,EAAE,CAyB1F"}
@@ -1,4 +1,3 @@
1
- // @fitness-ignore-file batch-operation-limits -- iterates bounded collection (catalog entries within a single graph build)
2
1
  /**
3
2
  * Entry-point inference (shared by orphan-subtree, test-only-reachable).
4
3
  *
@@ -1 +1 @@
1
- {"version":3,"file":"_entry-points.js","sourceRoot":"","sources":["../../src/rules/_entry-points.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"_entry-points.js","sourceRoot":"","sources":["../../src/rules/_entry-points.ts"],"names":[],"mappings":"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"}
@@ -1,40 +1,18 @@
1
1
  /**
2
- * graph:duplicated-function-body — group catalog entries whose body
3
- * normalizes to the same hash and report duplicate bodies. The rule has
4
- * two complementary code paths under one slug:
2
+ * graph:duplicated-function-body — group catalog entries whose body normalizes to the
3
+ * same hash and report duplicate bodies. Two complementary paths under one slug:
5
4
  *
6
- * 1. **Per-instance (size-gated).** A "duplicate" is two or more
7
- * functions whose normalized body is byte-identical
8
- * (whitespace/comment normalization handled by hashFunctionBody).
9
- * Two thresholds filter out non-actionable hits:
5
+ * 1. Per-instance (size-gated): N-1 signals per group of ≥2 byte-identical normalized
6
+ * bodies passing a line floor (default 5) AND a normalized-char floor (default 200,
7
+ * which drops thin `defineCheck`/pass-through wrappers).
8
+ * 2. Aggregate (cross-package): one signal per body hash in ≥ 3 distinct packages,
9
+ * suppressing that hash's per-instance signals (lighter body-size-only floor, 80).
10
10
  *
11
- * - minDuplicateBodyLines (default 5): the source span must be at
12
- * least this many lines.
13
- * - minDuplicateBodySize (default 200): the *normalized* body
14
- * (post comment-strip + whitespace-collapse) must be at least
15
- * this many characters. This catches the common case of a
16
- * `defineCheck({ ... analyze(content) { return analyzeFile(...) } })`
17
- * wrapper where the source spans 8+ lines but the executable
18
- * body is only ~80 characters once normalized — structurally
19
- * identical to every other thin wrapper, but never an actionable
20
- * refactor target.
21
- *
22
- * Emits N-1 signals per group (one per non-primary occurrence).
23
- *
24
- * 2. **Aggregate (cross-package).** For each body hash present in
25
- * ≥ minCrossPackageDuplicatePackages (default 3) DISTINCT packages
26
- * (via `pkgOf`), the rule emits ONE aggregate signal naming the
27
- * packages and SUPPRESSES the per-instance signals for that same hash
28
- * (no double-reporting). Bodies that don't reach N packages flow
29
- * through path (1) unchanged.
30
- *
31
- * This path applies a LIGHTER, body-size-only floor
32
- * (`minCrossPackageDuplicateBodySize`, default 80 chars — no line floor)
33
- * rather than the per-instance floor: a *small* body copied across
34
- * packages is exactly what this path exists to catch, so the floor is
35
- * tuned only to drop TRIVIAL bodies (empty DI-constructor shims,
36
- * one-line getters, thin delegators) that are never consolidation
37
- * targets, while keeping genuinely-small shared utilities visible.
11
+ * The detection algorithm + curation policy now live in `@opensip-cli/clone-detection`
12
+ * (ADR-0064) so graph and yagni single-source them. This rule is a thin adapter: it maps
13
+ * the catalog to `CloneCandidate[]` (pre-resolving `bodyLines` from the feature table and
14
+ * `package` from `pkgOf`), calls `findDuplicateBodies`, and wraps each finding into a
15
+ * graph `Signal` with the unchanged message/severity/metadata so output is byte-stable.
38
16
  */
39
17
  export declare const duplicatedFunctionBodyRule: import("../types.js").Rule;
40
18
  //# sourceMappingURL=duplicated-function-body.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"duplicated-function-body.d.ts","sourceRoot":"","sources":["../../src/rules/duplicated-function-body.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAoBH,eAAO,MAAM,0BAA0B,4BA0DrC,CAAC"}
1
+ {"version":3,"file":"duplicated-function-body.d.ts","sourceRoot":"","sources":["../../src/rules/duplicated-function-body.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAeH,eAAO,MAAM,0BAA0B,4BAoBrC,CAAC"}
@@ -1,262 +1,112 @@
1
1
  /**
2
- * graph:duplicated-function-body — group catalog entries whose body
3
- * normalizes to the same hash and report duplicate bodies. The rule has
4
- * two complementary code paths under one slug:
2
+ * graph:duplicated-function-body — group catalog entries whose body normalizes to the
3
+ * same hash and report duplicate bodies. Two complementary paths under one slug:
5
4
  *
6
- * 1. **Per-instance (size-gated).** A "duplicate" is two or more
7
- * functions whose normalized body is byte-identical
8
- * (whitespace/comment normalization handled by hashFunctionBody).
9
- * Two thresholds filter out non-actionable hits:
5
+ * 1. Per-instance (size-gated): N-1 signals per group of ≥2 byte-identical normalized
6
+ * bodies passing a line floor (default 5) AND a normalized-char floor (default 200,
7
+ * which drops thin `defineCheck`/pass-through wrappers).
8
+ * 2. Aggregate (cross-package): one signal per body hash in ≥ 3 distinct packages,
9
+ * suppressing that hash's per-instance signals (lighter body-size-only floor, 80).
10
10
  *
11
- * - minDuplicateBodyLines (default 5): the source span must be at
12
- * least this many lines.
13
- * - minDuplicateBodySize (default 200): the *normalized* body
14
- * (post comment-strip + whitespace-collapse) must be at least
15
- * this many characters. This catches the common case of a
16
- * `defineCheck({ ... analyze(content) { return analyzeFile(...) } })`
17
- * wrapper where the source spans 8+ lines but the executable
18
- * body is only ~80 characters once normalized — structurally
19
- * identical to every other thin wrapper, but never an actionable
20
- * refactor target.
21
- *
22
- * Emits N-1 signals per group (one per non-primary occurrence).
23
- *
24
- * 2. **Aggregate (cross-package).** For each body hash present in
25
- * ≥ minCrossPackageDuplicatePackages (default 3) DISTINCT packages
26
- * (via `pkgOf`), the rule emits ONE aggregate signal naming the
27
- * packages and SUPPRESSES the per-instance signals for that same hash
28
- * (no double-reporting). Bodies that don't reach N packages flow
29
- * through path (1) unchanged.
30
- *
31
- * This path applies a LIGHTER, body-size-only floor
32
- * (`minCrossPackageDuplicateBodySize`, default 80 chars — no line floor)
33
- * rather than the per-instance floor: a *small* body copied across
34
- * packages is exactly what this path exists to catch, so the floor is
35
- * tuned only to drop TRIVIAL bodies (empty DI-constructor shims,
36
- * one-line getters, thin delegators) that are never consolidation
37
- * targets, while keeping genuinely-small shared utilities visible.
11
+ * The detection algorithm + curation policy now live in `@opensip-cli/clone-detection`
12
+ * (ADR-0064) so graph and yagni single-source them. This rule is a thin adapter: it maps
13
+ * the catalog to `CloneCandidate[]` (pre-resolving `bodyLines` from the feature table and
14
+ * `package` from `pkgOf`), calls `findDuplicateBodies`, and wraps each finding into a
15
+ * graph `Signal` with the unchanged message/severity/metadata so output is byte-stable.
38
16
  */
17
+ import { findDuplicateBodies } from '@opensip-cli/clone-detection';
39
18
  import { pkgOf } from '../resolve-callee.js';
40
19
  import { createGraphSignal } from './create-graph-signal.js';
41
20
  import { defineRule } from './define-rule.js';
42
- const DEFAULT_MIN_LINES = 5;
43
- const DEFAULT_MIN_BODY_SIZE = 200;
44
- const DEFAULT_MIN_CROSS_PACKAGE_PACKAGES = 3;
45
- // Lighter than DEFAULT_MIN_BODY_SIZE (the per-instance floor) and applied with
46
- // NO line floor: the aggregate path is meant to catch genuinely-small shared
47
- // utilities copied across packages, so its floor only drops trivial bodies
48
- // (empty DI shims, one-line getters/delegators).
49
- const DEFAULT_MIN_CROSS_PACKAGE_BODY_SIZE = 80;
50
21
  const SLUG = 'graph:duplicated-function-body';
51
22
  export const duplicatedFunctionBodyRule = defineRule({
52
23
  slug: SLUG,
53
24
  defaultSeverity: 'warning',
54
25
  featureDeps: ['bodyLines'],
55
26
  evaluate({ catalog, config, features }) {
56
- const minLines = config.minDuplicateBodyLines ?? DEFAULT_MIN_LINES;
57
- const minBodySize = config.minDuplicateBodySize ?? DEFAULT_MIN_BODY_SIZE;
58
- const minPackages = config.minCrossPackageDuplicatePackages ?? DEFAULT_MIN_CROSS_PACKAGE_PACKAGES;
59
- const minCrossPackageBodySize = config.minCrossPackageDuplicateBodySize ?? DEFAULT_MIN_CROSS_PACKAGE_BODY_SIZE;
60
- const signals = [];
61
- // Aggregate path first: group every kind/test-eligible occurrence by
62
- // body hash (no line floor) so we can detect cross-package spread and
63
- // decide which hashes to suppress on the per-instance path below.
64
- const aggregateBuckets = groupByHashUnfloored(catalog);
65
- const suppressedHashes = new Set();
66
- for (const [bodyHash, occs] of aggregateBuckets) {
67
- const packages = [...new Set(occs.map((o) => pkgOf(o)))].sort();
68
- if (packages.length < minPackages)
69
- continue;
70
- const anchor = lowestByQualifiedName(occs);
71
- // Lighter, body-size-only floor (NO line floor): keeps the aggregate
72
- // path catching genuinely-small shared utilities copied across packages,
73
- // while dropping trivial bodies — empty DI-constructor shims, one-line
74
- // getters, thin delegators — that are not consolidation targets. A body
75
- // that fails this won't surface on the per-instance path either (its
76
- // 200-char floor is stricter), so there is nothing to suppress.
77
- if (anchor.bodySize !== undefined && anchor.bodySize < minCrossPackageBodySize)
78
- continue;
79
- // This hash is owned by the aggregate path; suppress its per-instance
80
- // signals so a single duplicate group never double-reports.
81
- suppressedHashes.add(bodyHash);
82
- signals.push(createGraphSignal(SLUG, config, {
83
- severity: 'low',
84
- category: 'quality',
85
- message: `This body is duplicated across ${String(packages.length)} packages (${packages.join(', ')}) in ${String(occs.length)} occurrences — hoist it into a shared package.`,
86
- code: { file: anchor.filePath, line: anchor.line, column: anchor.column },
87
- suggestion: 'Hoist the shared body into a single shared package and have every copy import it.',
88
- metadata: {
89
- packages,
90
- packageCount: packages.length,
91
- occurrenceCount: occs.length,
92
- bodyHash,
93
- },
94
- }));
95
- }
96
- // Per-instance path: size-gated groups, skipping any hash already
97
- // claimed by an aggregate signal so a group never double-reports.
98
- const groups = groupByHash(catalog, minLines, minBodySize, features);
99
- signals.push(...emitPerInstanceSignals(groups, suppressedHashes, config));
100
- return signals;
27
+ const candidates = toCandidates(catalog, features);
28
+ const { aggregates, groups } = findDuplicateBodies(candidates, {
29
+ minLines: config.minDuplicateBodyLines,
30
+ minBodySize: config.minDuplicateBodySize,
31
+ minCrossPackagePackages: config.minCrossPackageDuplicatePackages,
32
+ minCrossPackageBodySize: config.minCrossPackageDuplicateBodySize,
33
+ });
34
+ // Aggregate (cross-package) signals first, then per-instance signals — same order
35
+ // as the prior loops, but built as bounded in-memory projections over rule findings.
36
+ return [
37
+ ...aggregates.map((agg) => aggregateSignal(agg, config)),
38
+ ...groups.flatMap((group) => groupSignals(group, config)),
39
+ ];
101
40
  },
102
41
  });
103
- /**
104
- * Per-instance duplicate signals: N-1 per size-gated group, skipping any hash
105
- * already claimed by an aggregate signal (no double-reporting). Extracted from
106
- * evaluate() to keep its cognitive complexity within budget.
107
- */
108
- function emitPerInstanceSignals(groups, suppressedHashes, config) {
109
- const signals = [];
110
- for (const group of groups) {
111
- if (group.length < 2)
112
- continue;
113
- const primary = group[0];
114
- /* v8 ignore next */
115
- if (!primary)
116
- continue;
117
- if (suppressedHashes.has(primary.bodyHash))
118
- continue;
119
- for (let i = 1; i < group.length; i++) {
120
- const occ = group[i];
121
- /* v8 ignore next */
122
- if (!occ)
123
- continue;
124
- signals.push(createGraphSignal(SLUG, config, {
125
- severity: 'low',
126
- category: 'quality',
127
- message: `${occ.simpleName} has the same body as ${primary.qualifiedName} (${primary.filePath}:${String(primary.line)}).`,
128
- code: { file: occ.filePath, line: occ.line, column: occ.column },
129
- suggestion: 'Extract the shared body to a single function and have both call sites import it.',
130
- metadata: {
131
- primary: primary.qualifiedName,
132
- duplicate: occ.qualifiedName,
133
- groupSize: group.length,
134
- },
135
- }));
136
- }
137
- }
138
- return signals;
139
- }
140
- /**
141
- * A function's stable physical identity: where it is declared. The catalog's
142
- * `functions` record is keyed by simple name, and the same physical function
143
- * can surface more than once across that index (e.g. indexed under both its
144
- * simple and qualified name, or a recursive function whose self-reference is
145
- * walked as an extra occurrence). Two entries that share this identity are the
146
- * SAME function — they must never count as a duplicate of each other. Keying on
147
- * file + declaration position + simple name keeps genuinely-distinct functions
148
- * (same body, different file/line) in separate identities while collapsing
149
- * self-matches.
150
- */
151
- function identityOf(occ) {
152
- return `${occ.filePath}:${String(occ.line)}:${String(occ.column)}:${occ.simpleName}`;
42
+ function aggregateSignal(agg, config) {
43
+ return createGraphSignal(SLUG, config, {
44
+ severity: 'low',
45
+ category: 'quality',
46
+ message: `This body is duplicated across ${String(agg.packages.length)} packages (${agg.packages.join(', ')}) in ${String(agg.occurrenceCount)} occurrences — hoist it into a shared package.`,
47
+ code: { file: agg.anchor.filePath, line: agg.anchor.line, column: agg.anchor.column },
48
+ suggestion: 'Hoist the shared body into a single shared package and have every copy import it.',
49
+ metadata: {
50
+ packages: agg.packages,
51
+ packageCount: agg.packages.length,
52
+ occurrenceCount: agg.occurrenceCount,
53
+ bodyHash: agg.bodyHash,
54
+ },
55
+ });
153
56
  }
154
- /**
155
- * Add an occurrence to its body-hash bucket, deduping by physical identity so a
156
- * function never appears twice in its own bucket. Without this, a function that
157
- * surfaces more than once in the catalog index (self-reference, dual name
158
- * indexing) would form a phantom 2-member group and self-report as a duplicate.
159
- */
160
- function pushDeduped(buckets, seenByHash, occ) {
161
- let bucket = buckets.get(occ.bodyHash);
162
- let seen = seenByHash.get(occ.bodyHash);
163
- if (!bucket) {
164
- bucket = [];
165
- buckets.set(occ.bodyHash, bucket);
166
- seen = new Set();
167
- seenByHash.set(occ.bodyHash, seen);
168
- }
57
+ function groupSignals(group, config) {
58
+ const primary = group.members[0];
169
59
  /* v8 ignore next */
170
- if (!seen)
171
- return;
172
- const id = identityOf(occ);
173
- if (seen.has(id))
174
- return;
175
- seen.add(id);
176
- bucket.push(occ);
177
- }
178
- function groupByHash(catalog, minLines, minBodySize, features) {
179
- // Walk the catalog directly; the byBodyHash index dedupes by hash,
180
- // which is exactly what we need to NOT do here.
181
- const buckets = new Map();
182
- const seenByHash = new Map();
183
- for (const name of Object.keys(catalog.functions)) {
184
- const occs = catalog.functions[name];
185
- /* v8 ignore next */
186
- if (!occs)
187
- continue;
188
- for (const occ of occs) {
189
- if (!isInterestingForDup(occ, minLines, minBodySize, features))
190
- continue;
191
- pushDeduped(buckets, seenByHash, occ);
192
- }
193
- }
194
- return [...buckets.values()];
60
+ if (!primary)
61
+ return [];
62
+ return group.members.slice(1).map((occ) => createGraphSignal(SLUG, config, {
63
+ severity: 'low',
64
+ category: 'quality',
65
+ message: `${occ.simpleName} has the same body as ${primary.qualifiedName} (${primary.filePath}:${String(primary.line)}).`,
66
+ code: { file: occ.filePath, line: occ.line, column: occ.column },
67
+ suggestion: 'Extract the shared body to a single function and have both call sites import it.',
68
+ metadata: {
69
+ primary: primary.qualifiedName,
70
+ duplicate: occ.qualifiedName,
71
+ groupSize: group.members.length,
72
+ },
73
+ }));
195
74
  }
196
75
  /**
197
- * Group occurrences by body hash applying ONLY the kind/test-file
198
- * exclusions (no size/line floor) the grouping the aggregate
199
- * cross-package path consumes. Returns a Map so callers keep the body
200
- * hash key for suppression bookkeeping.
76
+ * Map the catalog to `CloneCandidate[]` in the SAME iteration order the prior in-rule
77
+ * grouping used (`Object.keys(catalog.functions)` each name's occurrences), so the
78
+ * substrate's bucket/primary selection and emission order are byte-identical.
79
+ * `bodyLines` is pre-resolved from the feature table (canonical span) with the inline
80
+ * `endLine − line + 1` fallback handled by the substrate; `package` is `pkgOf` (the
81
+ * nearest-package.json resolution the aggregate path keys on).
201
82
  */
202
- function groupByHashUnfloored(catalog) {
203
- const buckets = new Map();
204
- const seenByHash = new Map();
83
+ function toCandidates(catalog, features) {
84
+ const candidates = [];
205
85
  for (const name of Object.keys(catalog.functions)) {
206
86
  const occs = catalog.functions[name];
207
87
  /* v8 ignore next */
208
88
  if (!occs)
209
89
  continue;
210
- for (const occ of occs) {
211
- if (!isEligibleKind(occ))
212
- continue;
213
- pushDeduped(buckets, seenByHash, occ);
214
- }
90
+ for (const occ of occs)
91
+ candidates.push(toCandidate(occ, features));
215
92
  }
216
- return buckets;
217
- }
218
- function lowestByQualifiedName(occs) {
219
- return occs.reduce((lo, c) => (c.qualifiedName < lo.qualifiedName ? c : lo));
93
+ return candidates;
220
94
  }
221
- /**
222
- * The kind/test-file exclusions shared by both code paths. Inline arrows
223
- * / function expressions / module-init occurrences are never an
224
- * extract/hoist target:
225
- * - test-suite arrows with identical 5-line bodies are common boilerplate
226
- * - module-inits hash whatever is at top level; identical hashes mean
227
- * twin files, not a dup-extraction opportunity
228
- * - constructor/getter/setter/method dups are interesting; keep those
229
- *
230
- * Test-file occurrences are excluded on both paths.
231
- */
232
- function isEligibleKind(occ) {
233
- if (occ.kind === 'arrow' || occ.kind === 'function-expression' || occ.kind === 'module-init') {
234
- return false;
235
- }
236
- if (occ.inTestFile)
237
- return false;
238
- return true;
239
- }
240
- /**
241
- * The per-instance dup-body filter: the shared kind/test exclusions plus
242
- * the size/line floor. The bodySize threshold drops trivial wrappers — a
243
- * `defineCheck` or pass-through analyze that contains an `if`-guard plus a
244
- * delegating call. These have identical normalized bodies across many
245
- * files but are never the right refactor target. Catalogs from older runs
246
- * that lack `bodySize` skip the size check (treated as "passes").
247
- */
248
- function isInterestingForDup(occ, minLines, minBodySize, features) {
249
- if (!isEligibleKind(occ))
250
- return false;
251
- // The bodyLines feature column is the canonical span (computed once in
252
- // pipeline/features.ts). The inline `endLine − line + 1` here is the single
253
- // sanctioned graceful-degrade fallback for features-absent calls (3/4-arg
254
- // test evaluate), not a duplicate of the engine derivation.
255
- const span = features?.function.get(occ.bodyHash)?.bodyLines ?? occ.endLine - occ.line + 1;
256
- if (span < minLines)
257
- return false;
258
- if (occ.bodySize !== undefined && occ.bodySize < minBodySize)
259
- return false;
260
- return true;
95
+ function toCandidate(occ, features) {
96
+ const bodyLines = features?.function.get(occ.bodyHash)?.bodyLines;
97
+ return {
98
+ bodyHash: occ.bodyHash,
99
+ kind: occ.kind,
100
+ inTestFile: occ.inTestFile,
101
+ filePath: occ.filePath,
102
+ line: occ.line,
103
+ column: occ.column,
104
+ endLine: occ.endLine,
105
+ simpleName: occ.simpleName,
106
+ qualifiedName: occ.qualifiedName,
107
+ package: pkgOf(occ),
108
+ ...(occ.bodySize === undefined ? {} : { bodySize: occ.bodySize }),
109
+ ...(bodyLines === undefined ? {} : { bodyLines }),
110
+ };
261
111
  }
262
112
  //# sourceMappingURL=duplicated-function-body.js.map