gitnexus 1.6.5-rc.2 → 1.6.5-rc.21

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 (288) hide show
  1. package/README.md +1 -1
  2. package/dist/_shared/scope-resolution/method-dispatch-index.d.ts +26 -0
  3. package/dist/_shared/scope-resolution/method-dispatch-index.d.ts.map +1 -1
  4. package/dist/_shared/scope-resolution/method-dispatch-index.js +22 -3
  5. package/dist/_shared/scope-resolution/method-dispatch-index.js.map +1 -1
  6. package/dist/_shared/scope-resolution/registries/lookup-core.js +18 -1
  7. package/dist/_shared/scope-resolution/registries/lookup-core.js.map +1 -1
  8. package/dist/cli/ai-context.d.ts +1 -0
  9. package/dist/cli/ai-context.js +30 -12
  10. package/dist/cli/analyze.d.ts +18 -0
  11. package/dist/cli/analyze.js +33 -4
  12. package/dist/cli/augment.d.ts +1 -1
  13. package/dist/cli/augment.js +1 -1
  14. package/dist/cli/index.js +6 -1
  15. package/dist/cli/setup.js +6 -0
  16. package/dist/core/augmentation/engine.d.ts +2 -2
  17. package/dist/core/augmentation/engine.js +26 -6
  18. package/dist/core/embeddings/ast-utils.js +2 -1
  19. package/dist/core/embeddings/http-client.js +22 -6
  20. package/dist/core/group/extractors/grpc-extractor.js +2 -1
  21. package/dist/core/group/extractors/http-patterns/python.js +175 -0
  22. package/dist/core/group/extractors/http-route-extractor.js +2 -1
  23. package/dist/core/group/extractors/include-extractor.js +2 -1
  24. package/dist/core/group/extractors/thrift-extractor.js +2 -1
  25. package/dist/core/group/extractors/tree-sitter-scanner.js +2 -1
  26. package/dist/core/incremental/shadow-candidates.d.ts +44 -0
  27. package/dist/core/incremental/shadow-candidates.js +74 -0
  28. package/dist/core/incremental/subgraph-extract.d.ts +64 -0
  29. package/dist/core/incremental/subgraph-extract.js +111 -0
  30. package/dist/core/ingestion/call-processor.js +166 -47
  31. package/dist/core/ingestion/community-processor.js +18 -0
  32. package/dist/core/ingestion/heritage-processor.js +3 -2
  33. package/dist/core/ingestion/import-processor.js +2 -1
  34. package/dist/core/ingestion/import-resolvers/standard.d.ts +5 -0
  35. package/dist/core/ingestion/import-resolvers/standard.js +27 -1
  36. package/dist/core/ingestion/import-resolvers/utils.js +4 -0
  37. package/dist/core/ingestion/languages/c/arity-metadata.d.ts +14 -0
  38. package/dist/core/ingestion/languages/c/arity-metadata.js +94 -0
  39. package/dist/core/ingestion/languages/c/arity.d.ts +6 -0
  40. package/dist/core/ingestion/languages/c/arity.js +18 -0
  41. package/dist/core/ingestion/languages/c/captures.d.ts +2 -0
  42. package/dist/core/ingestion/languages/c/captures.js +105 -0
  43. package/dist/core/ingestion/languages/c/header-scan.d.ts +7 -0
  44. package/dist/core/ingestion/languages/c/header-scan.js +55 -0
  45. package/dist/core/ingestion/languages/c/import-decomposer.d.ts +8 -0
  46. package/dist/core/ingestion/languages/c/import-decomposer.js +50 -0
  47. package/dist/core/ingestion/languages/c/import-target.d.ts +14 -0
  48. package/dist/core/ingestion/languages/c/import-target.js +57 -0
  49. package/dist/core/ingestion/languages/c/index.d.ts +11 -0
  50. package/dist/core/ingestion/languages/c/index.js +11 -0
  51. package/dist/core/ingestion/languages/c/interpret.d.ts +14 -0
  52. package/dist/core/ingestion/languages/c/interpret.js +48 -0
  53. package/dist/core/ingestion/languages/c/merge-bindings.d.ts +7 -0
  54. package/dist/core/ingestion/languages/c/merge-bindings.js +23 -0
  55. package/dist/core/ingestion/languages/c/query.d.ts +3 -0
  56. package/dist/core/ingestion/languages/c/query.js +161 -0
  57. package/dist/core/ingestion/languages/c/scope-resolver.d.ts +13 -0
  58. package/dist/core/ingestion/languages/c/scope-resolver.js +60 -0
  59. package/dist/core/ingestion/languages/c/simple-hooks.d.ts +14 -0
  60. package/dist/core/ingestion/languages/c/simple-hooks.js +19 -0
  61. package/dist/core/ingestion/languages/c/static-linkage.d.ts +13 -0
  62. package/dist/core/ingestion/languages/c/static-linkage.js +57 -0
  63. package/dist/core/ingestion/languages/c-cpp.js +10 -0
  64. package/dist/core/ingestion/languages/csharp/captures.js +2 -1
  65. package/dist/core/ingestion/languages/csharp/namespace-siblings.js +3 -2
  66. package/dist/core/ingestion/languages/go/captures.js +2 -1
  67. package/dist/core/ingestion/languages/go/range-binding.js +2 -1
  68. package/dist/core/ingestion/languages/java/arity-metadata.d.ts +18 -0
  69. package/dist/core/ingestion/languages/java/arity-metadata.js +40 -0
  70. package/dist/core/ingestion/languages/java/arity.d.ts +10 -0
  71. package/dist/core/ingestion/languages/java/arity.js +24 -0
  72. package/dist/core/ingestion/languages/java/cache-stats.d.ts +15 -0
  73. package/dist/core/ingestion/languages/java/cache-stats.js +26 -0
  74. package/dist/core/ingestion/languages/java/captures.d.ts +17 -0
  75. package/dist/core/ingestion/languages/java/captures.js +187 -0
  76. package/dist/core/ingestion/languages/java/import-decomposer.d.ts +18 -0
  77. package/dist/core/ingestion/languages/java/import-decomposer.js +85 -0
  78. package/dist/core/ingestion/languages/java/import-target.d.ts +17 -0
  79. package/dist/core/ingestion/languages/java/import-target.js +100 -0
  80. package/dist/core/ingestion/languages/java/index.d.ts +29 -0
  81. package/dist/core/ingestion/languages/java/index.js +29 -0
  82. package/dist/core/ingestion/languages/java/interpret.d.ts +13 -0
  83. package/dist/core/ingestion/languages/java/interpret.js +131 -0
  84. package/dist/core/ingestion/languages/java/merge-bindings.d.ts +12 -0
  85. package/dist/core/ingestion/languages/java/merge-bindings.js +40 -0
  86. package/dist/core/ingestion/languages/java/query.d.ts +30 -0
  87. package/dist/core/ingestion/languages/java/query.js +192 -0
  88. package/dist/core/ingestion/languages/java/receiver-binding.d.ts +11 -0
  89. package/dist/core/ingestion/languages/java/receiver-binding.js +95 -0
  90. package/dist/core/ingestion/languages/java/scope-resolver.d.ts +50 -0
  91. package/dist/core/ingestion/languages/java/scope-resolver.js +74 -0
  92. package/dist/core/ingestion/languages/java/simple-hooks.d.ts +13 -0
  93. package/dist/core/ingestion/languages/java/simple-hooks.js +34 -0
  94. package/dist/core/ingestion/languages/java.js +11 -0
  95. package/dist/core/ingestion/languages/php/arity-metadata.d.ts +28 -0
  96. package/dist/core/ingestion/languages/php/arity-metadata.js +63 -0
  97. package/dist/core/ingestion/languages/php/arity.d.ts +25 -0
  98. package/dist/core/ingestion/languages/php/arity.js +40 -0
  99. package/dist/core/ingestion/languages/php/cache-stats.d.ts +15 -0
  100. package/dist/core/ingestion/languages/php/cache-stats.js +26 -0
  101. package/dist/core/ingestion/languages/php/captures.d.ts +34 -0
  102. package/dist/core/ingestion/languages/php/captures.js +739 -0
  103. package/dist/core/ingestion/languages/php/import-decomposer.d.ts +28 -0
  104. package/dist/core/ingestion/languages/php/import-decomposer.js +265 -0
  105. package/dist/core/ingestion/languages/php/import-target.d.ts +47 -0
  106. package/dist/core/ingestion/languages/php/import-target.js +100 -0
  107. package/dist/core/ingestion/languages/php/index.d.ts +68 -0
  108. package/dist/core/ingestion/languages/php/index.js +72 -0
  109. package/dist/core/ingestion/languages/php/interpret.d.ts +36 -0
  110. package/dist/core/ingestion/languages/php/interpret.js +241 -0
  111. package/dist/core/ingestion/languages/php/merge-bindings.d.ts +19 -0
  112. package/dist/core/ingestion/languages/php/merge-bindings.js +47 -0
  113. package/dist/core/ingestion/languages/php/namespace-siblings.d.ts +51 -0
  114. package/dist/core/ingestion/languages/php/namespace-siblings.js +288 -0
  115. package/dist/core/ingestion/languages/php/query.d.ts +32 -0
  116. package/dist/core/ingestion/languages/php/query.js +326 -0
  117. package/dist/core/ingestion/languages/php/receiver-binding.d.ts +36 -0
  118. package/dist/core/ingestion/languages/php/receiver-binding.js +128 -0
  119. package/dist/core/ingestion/languages/php/scope-resolver.d.ts +23 -0
  120. package/dist/core/ingestion/languages/php/scope-resolver.js +358 -0
  121. package/dist/core/ingestion/languages/php/simple-hooks.d.ts +42 -0
  122. package/dist/core/ingestion/languages/php/simple-hooks.js +111 -0
  123. package/dist/core/ingestion/languages/php.d.ts +0 -7
  124. package/dist/core/ingestion/languages/php.js +15 -0
  125. package/dist/core/ingestion/languages/python/captures.js +2 -1
  126. package/dist/core/ingestion/languages/typescript/captures.js +2 -1
  127. package/dist/core/ingestion/parsing-processor.d.ts +22 -2
  128. package/dist/core/ingestion/parsing-processor.js +85 -50
  129. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +5 -0
  130. package/dist/core/ingestion/pipeline-phases/parse-impl.js +119 -11
  131. package/dist/core/ingestion/pipeline-phases/parse.d.ts +14 -0
  132. package/dist/core/ingestion/pipeline.d.ts +13 -0
  133. package/dist/core/ingestion/registry-primary-flag.js +2 -0
  134. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +65 -0
  135. package/dist/core/ingestion/scope-resolution/graph-bridge/method-dispatch.d.ts +1 -1
  136. package/dist/core/ingestion/scope-resolution/graph-bridge/method-dispatch.js +12 -2
  137. package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +5 -0
  138. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +25 -1
  139. package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +79 -7
  140. package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +7 -3
  141. package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +24 -4
  142. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +21 -2
  143. package/dist/core/ingestion/scope-resolution/pipeline/phase.js +13 -1
  144. package/dist/core/ingestion/scope-resolution/pipeline/registry.js +6 -0
  145. package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +17 -0
  146. package/dist/core/ingestion/scope-resolution/pipeline/run.js +31 -7
  147. package/dist/core/ingestion/tree-sitter-queries.d.ts +1 -1
  148. package/dist/core/ingestion/tree-sitter-queries.js +10 -0
  149. package/dist/core/ingestion/workers/parse-worker.js +2 -1
  150. package/dist/core/lbug/lbug-adapter.d.ts +26 -0
  151. package/dist/core/lbug/lbug-adapter.js +174 -40
  152. package/dist/core/lbug/pool-adapter.js +19 -2
  153. package/dist/core/run-analyze.d.ts +2 -0
  154. package/dist/core/run-analyze.js +323 -29
  155. package/dist/core/tree-sitter/safe-parse.d.ts +6 -0
  156. package/dist/core/tree-sitter/safe-parse.js +32 -0
  157. package/dist/server/git-clone.js +10 -13
  158. package/dist/storage/file-hash.d.ts +47 -0
  159. package/dist/storage/file-hash.js +86 -0
  160. package/dist/storage/git.d.ts +17 -6
  161. package/dist/storage/git.js +46 -12
  162. package/dist/storage/parse-cache.d.ts +67 -0
  163. package/dist/storage/parse-cache.js +182 -0
  164. package/dist/storage/repo-manager.d.ts +41 -1
  165. package/dist/storage/repo-manager.js +17 -2
  166. package/hooks/claude/gitnexus-hook.cjs +8 -1
  167. package/hooks/claude/hook-lock.cjs +119 -0
  168. package/package.json +1 -1
  169. package/web/assets/{agent-BpHQleHE.js → agent-BG6RCOzz.js} +1 -1
  170. package/web/assets/architecture-7EHR7CIX-6QZW5X65-F-tujre-.js +1 -0
  171. package/web/assets/architectureDiagram-UL44E2DR-2GL7nOvO.js +36 -0
  172. package/web/assets/blockDiagram-7IZFK4PR-5AjX0pPU.js +132 -0
  173. package/web/assets/{c4Diagram-DFAF54RM-DeJV1rCn.js → c4Diagram-Y2BXMSZH-hLOeq7xC.js} +2 -2
  174. package/web/assets/chunk-2T2R6R2M-B_pq_2nf.js +4 -0
  175. package/web/assets/chunk-2UTLFMKG-CpoohCFN.js +1 -0
  176. package/web/assets/{chunk-7RZVMHOQ-BdIU-RGO.js → chunk-3SSMPTDK-CfqpR3Nr.js} +1 -1
  177. package/web/assets/chunk-4R4BOZG6-D3gm7tYj.js +159 -0
  178. package/web/assets/chunk-6764PJDD-WcI965eO.js +1 -0
  179. package/web/assets/chunk-AQ6EADP3-BpMj3rQl.js +1 -0
  180. package/web/assets/{chunk-KSICW3F5-C2tZmXwv.js → chunk-AZZRMDJM-DSoCJlUA.js} +1 -1
  181. package/web/assets/chunk-C62D2QBJ-CvFF2PnB.js +1 -0
  182. package/web/assets/chunk-CEXFNPSA-DdNtJtrF.js +1 -0
  183. package/web/assets/chunk-J5EP6P6S-DtcVaAJI.js +1 -0
  184. package/web/assets/{chunk-AEOMTBSW-D7qjBMHW.js → chunk-JQRUD6KW-DElaNjc0.js} +1 -1
  185. package/web/assets/chunk-KGYTTC2M-D0K5or7e.js +1 -0
  186. package/web/assets/chunk-KRXBNO2N-DpR8iDt8.js +1 -0
  187. package/web/assets/chunk-LCXTWHL2-DdMObOEk.js +231 -0
  188. package/web/assets/chunk-LII3EMHJ-I78zXtzi.js +1 -0
  189. package/web/assets/chunk-RERM46MO-Betu1cSy.js +1 -0
  190. package/web/assets/chunk-RG4AUYOV-BUCJ2JP5.js +206 -0
  191. package/web/assets/chunk-RKZBBQEN-Cutpza0t.js +1 -0
  192. package/web/assets/chunk-RLI5ZMPA-BFUxCvX2.js +1 -0
  193. package/web/assets/chunk-T5OCTHI4-DKwlkuvB.js +1 -0
  194. package/web/assets/chunk-UP6H54XL-0YWa0NDg.js +1 -0
  195. package/web/assets/chunk-UXSXWOXI-CSz0OXpz.js +1 -0
  196. package/web/assets/chunk-W44A43WB-AOmgoT-X.js +1 -0
  197. package/web/assets/{chunk-RWUO3TPN-DTWzAhQ1.js → chunk-ZXARS5L4-DIzgxjMw.js} +1 -1
  198. package/web/assets/classDiagram-KGZ6W3CR-BT-rn7LF.js +1 -0
  199. package/web/assets/classDiagram-v2-72OJOZXJ-uR3nDadY.js +1 -0
  200. package/web/assets/{cose-bilkent-PNC4W37J-DdZq7Qz_.js → cose-bilkent-UX7MHV2Q-DCSCD1TK.js} +1 -1
  201. package/web/assets/dagre-ND4H6XIP-CsciHSij.js +4 -0
  202. package/web/assets/diagram-3NCE3AQN-BKUT5Rpc.js +43 -0
  203. package/web/assets/diagram-GF46GFSD-Dxb4hZSo.js +24 -0
  204. package/web/assets/diagram-HNR7UZ2L-D3qus9Cn.js +3 -0
  205. package/web/assets/diagram-QXG6HAR7-r9BMLGGP.js +24 -0
  206. package/web/assets/diagram-WEQXMOUZ-BGXqs7-m.js +10 -0
  207. package/web/assets/{erDiagram-GCSMX5X6-DfdN6iqF.js → erDiagram-L5TCEMPS-LgSWVrkZ.js} +2 -2
  208. package/web/assets/eventmodeling-FCH6USID-MREXMVOE-By7r3bla.js +1 -0
  209. package/web/assets/flowDiagram-H6V6AXG4-Bj_vV5ky.js +162 -0
  210. package/web/assets/ganttDiagram-JCBTUEKG-B1eVITSh.js +292 -0
  211. package/web/assets/gitGraph-WXDBUCRP-R675I2BI-ClEP6RdE.js +1 -0
  212. package/web/assets/gitGraphDiagram-S2ZK5IYY-BP0R-_FD.js +106 -0
  213. package/web/assets/{index-3NUCUW2s.js → index-oL-ZNYwb.js} +80 -81
  214. package/web/assets/info-J43DQDTF-KCYPFFUO-bBJRjmP5.js +1 -0
  215. package/web/assets/infoDiagram-3YFTVSEB-Dmj4OEO3.js +2 -0
  216. package/web/assets/{ishikawaDiagram-YMYX4NHK-BF8AtDaj.js → ishikawaDiagram-BNXS4ZKH-B3NgQ4lJ.js} +2 -2
  217. package/web/assets/{journeyDiagram-SO5T7YLQ-BW8oKa3N.js → journeyDiagram-M6C3CM3L-DALmL4_N.js} +3 -3
  218. package/web/assets/{kanban-definition-LJHFXRCJ-DzbOsR-2.js → kanban-definition-75IXJCU3-AvVbHpnN.js} +4 -4
  219. package/web/assets/{katex-GD7MH7QM-CJiOjBBJ.js → katex-K3KEBU37-CqF6_ZN-.js} +1 -1
  220. package/web/assets/{mindmap-definition-2EUWGEK5-BIXGQALq.js → mindmap-definition-2TDM6QVE-B5c9VOzs.js} +28 -28
  221. package/web/assets/packet-YPE3B663-LP52Z2RK-1ZCldnu3.js +1 -0
  222. package/web/assets/pie-LRSECV5Y-TCRJHUBD-EhjHC5EE.js +1 -0
  223. package/web/assets/pieDiagram-CU6KROY3-Po2HSSR4.js +30 -0
  224. package/web/assets/quadrantDiagram-VICAPDV7-C47UxSZD.js +7 -0
  225. package/web/assets/radar-GUYGQ44K-RDLRG3WG-CvXjgxlW.js +1 -0
  226. package/web/assets/{requirementDiagram-M5DCFWZL-CzUUrhQD.js → requirementDiagram-JXO7QTGE-CpECN_Hq.js} +6 -6
  227. package/web/assets/sankeyDiagram-URQDO5SZ-B3b7cLrS.js +40 -0
  228. package/web/assets/sequenceDiagram-VS2MUI6T-CRJ95oVP.js +162 -0
  229. package/web/assets/stateDiagram-7D4R322I-C7U9b3ks.js +1 -0
  230. package/web/assets/stateDiagram-v2-36443NZ5-BQajbtov.js +1 -0
  231. package/web/assets/{timeline-definition-5SPVSISX-DkMiGj4Z.js → timeline-definition-O6YCAMPW-rtbk6BBo.js} +4 -4
  232. package/web/assets/treeView-BLDUP644-QA4HXRO3-R2o5gwfP.js +1 -0
  233. package/web/assets/treemap-LRROVOQU-LLAWBHMP-Cesmac_u.js +1 -0
  234. package/web/assets/{vennDiagram-IE5QUKF5-BCxMmf9q.js → vennDiagram-MWXL3ELB-W8Yoaayh.js} +3 -3
  235. package/web/assets/wardley-L42UT6IY-5TKZOOLJ-B9HYoRgA.js +1 -0
  236. package/web/assets/wardleyDiagram-CUQ6CDDI-DIZw5Abj.js +78 -0
  237. package/web/assets/{xychartDiagram-ZHJ5623Y-DZ7fP1_3.js → xychartDiagram-N2JHSOCM-DGRtrj4P.js} +3 -3
  238. package/web/index.html +2 -2
  239. package/web/assets/architecture-YZFGNWBL-S5CXDPWN-BUzkWgDl.js +0 -1
  240. package/web/assets/architectureDiagram-EMZXCZ2Q-CXbzok1G.js +0 -36
  241. package/web/assets/blockDiagram-IGV67L2C-DA1QJ4ZB.js +0 -132
  242. package/web/assets/chunk-3GS5O3IE-B8hpnia8.js +0 -231
  243. package/web/assets/chunk-3YCYZ6SJ-B-BVu21C.js +0 -1
  244. package/web/assets/chunk-6NTNNK5N-DW-jYSDr.js +0 -1
  245. package/web/assets/chunk-A34GCYZU-BbZl-IKy.js +0 -1
  246. package/web/assets/chunk-DJ7UZH7F-B5tMfF87.js +0 -1
  247. package/web/assets/chunk-DKKBVRCY-Djm-6K_e.js +0 -4
  248. package/web/assets/chunk-DU5LTGQ6-QPoynYcp.js +0 -1
  249. package/web/assets/chunk-FXACKDTF-jieSmbe2.js +0 -159
  250. package/web/assets/chunk-H3VCZNTA-8EMHZ3SV.js +0 -1
  251. package/web/assets/chunk-HN6EAY2L-CgE_agsD.js +0 -1
  252. package/web/assets/chunk-O5ABG6QK-DEZV1O19.js +0 -1
  253. package/web/assets/chunk-PK6DOVAG-BXv0JnsJ.js +0 -206
  254. package/web/assets/chunk-RNJOYNJ4-BiBkF9dN.js +0 -1
  255. package/web/assets/chunk-TBF5ZNIQ-BSl6s9lT.js +0 -1
  256. package/web/assets/chunk-TU3PZOEN-DE5Qhc0N.js +0 -1
  257. package/web/assets/chunk-TYMNRAUI-D1NDLIMG.js +0 -1
  258. package/web/assets/chunk-VELTKBKT-C9dVN39o.js +0 -1
  259. package/web/assets/chunk-W7ZLLLMY-Bu-cdLzs.js +0 -1
  260. package/web/assets/chunk-WSB5WSVC-Dor71SOz.js +0 -1
  261. package/web/assets/chunk-XGPFEOL4-CUonLRle.js +0 -1
  262. package/web/assets/classDiagram-PPOCWD7C-Cdd6UdVv.js +0 -1
  263. package/web/assets/classDiagram-v2-23LJLIIU-DNhxY2Ib.js +0 -1
  264. package/web/assets/dagre-E77IOHMT-Cfj_6e17.js +0 -4
  265. package/web/assets/diagram-H7BISOXX-BNvpsrBv.js +0 -43
  266. package/web/assets/diagram-JC5VWROH-Cn0rtDbJ.js +0 -24
  267. package/web/assets/diagram-LXUTUG65-CHfoVKNm.js +0 -10
  268. package/web/assets/diagram-WEHSV5V5-BLxHksnu.js +0 -24
  269. package/web/assets/flowDiagram-OTCZ4VVT-aAZw4c_M.js +0 -162
  270. package/web/assets/ganttDiagram-MUNLMDZQ-BEfC_7Or.js +0 -292
  271. package/web/assets/gitGraph-7Q5UKJZL-54BCDZD5-B6ZeRLP0.js +0 -1
  272. package/web/assets/gitGraphDiagram-3HKGZ4G3-CG0kC8Q5.js +0 -106
  273. package/web/assets/info-OMHHGYJF-BF2H5H6G-BIOsZy0W.js +0 -1
  274. package/web/assets/infoDiagram-MN7RKWGX-DUoMH-pq.js +0 -2
  275. package/web/assets/packet-4T2RLAQJ-EV4IVRXR-Bs7ysNMU.js +0 -1
  276. package/web/assets/pie-ZZUOXDRM-N23DN5KN-Csi8nnbH.js +0 -1
  277. package/web/assets/pieDiagram-3IATQBI2-QY-u7P6a.js +0 -30
  278. package/web/assets/quadrantDiagram-E256RVCF-Di4aNiU8.js +0 -7
  279. package/web/assets/radar-PYXPWWZC-P6TP7ZYP-DJlyXh2-.js +0 -1
  280. package/web/assets/sankeyDiagram-L3NBLAOT-D2fbMiIU.js +0 -10
  281. package/web/assets/sequenceDiagram-ZOUHS735-BNdkqguh.js +0 -157
  282. package/web/assets/stateDiagram-MLPALWAM-51_Q2w2L.js +0 -1
  283. package/web/assets/stateDiagram-v2-B5LQ5ZB2-8nHs2aNE.js +0 -1
  284. package/web/assets/treeView-SZITEDCU-5DXDK3XO-Cy6P0_CZ.js +0 -1
  285. package/web/assets/treemap-W4RFUUIX-WYLRDWKO-C_pp1R7A.js +0 -1
  286. package/web/assets/wardley-RL74JXVD-BCRCBASE-CMStJhpn.js +0 -1
  287. package/web/assets/wardleyDiagram-XU3VSMPF-ijlLF77s.js +0 -20
  288. /package/web/assets/{context-builder-CqQNhRj1.js → context-builder-CG-ydtp4.js} +0 -0
@@ -29,7 +29,8 @@ import { getLanguageFromFilename, SupportedLanguages } from '../../_shared/index
29
29
  import { isRegistryPrimary } from './registry-primary-flag.js';
30
30
  import { isVerboseIngestionEnabled } from './utils/verbose.js';
31
31
  import { yieldToEventLoop } from './utils/event-loop.js';
32
- import { FUNCTION_NODE_TYPES, findEnclosingClassId, findEnclosingClassInfo, genericFuncName, inferFunctionLabel, } from './utils/ast-helpers.js';
32
+ import { parseSourceSafe } from '../tree-sitter/safe-parse.js';
33
+ import { CLASS_CONTAINER_TYPES, FUNCTION_NODE_TYPES, findEnclosingClassInfo, genericFuncName, inferFunctionLabel, } from './utils/ast-helpers.js';
33
34
  import { typeTagForId, constTagForId, buildCollisionGroups } from './utils/method-props.js';
34
35
  import { countCallArguments, inferCallForm, extractReceiverName, extractReceiverNode, extractMixedChain, extractCallArgTypes, } from './utils/call-analysis.js';
35
36
  import { buildTypeEnv, isSubclassOf } from './type-env.js';
@@ -38,6 +39,57 @@ import { normalizeFetchURL, routeMatches } from './route-extractors/nextjs.js';
38
39
  import { extractTemplateComponents } from './vue-sfc-extractor.js';
39
40
  import { extractReturnTypeName, stripNullable } from './type-extractors/shared.js';
40
41
  import { logger } from '../logger.js';
42
+ // ── Property-prepass helpers (parity with parse-worker.ts) ──
43
+ // These mirror the sequential-path equivalents in parse-worker.ts so the main-
44
+ // thread `processCalls` pre-pass produces byte-identical Property nodes/symbols
45
+ // to the worker pool. Drift between the two paths breaks the
46
+ // `incremental ≡ --force` invariant the moment a repo crosses the worker
47
+ // threshold between runs.
48
+ /** Walk up to the nearest enclosing class/struct/interface AST node. */
49
+ const findEnclosingClassNode = (node) => {
50
+ let current = node.parent;
51
+ while (current) {
52
+ if (CLASS_CONTAINER_TYPES.has(current.type))
53
+ return current;
54
+ current = current.parent;
55
+ }
56
+ return null;
57
+ };
58
+ /** No-op SymbolTable stub for FieldExtractorContext — matches parse-worker. */
59
+ const NOOP_SYMBOL_TABLE = {
60
+ lookupExact: () => undefined,
61
+ lookupExactFull: () => undefined,
62
+ lookupExactAll: () => [],
63
+ lookupCallableByName: () => [],
64
+ getFiles: () => [][Symbol.iterator](),
65
+ getStats: () => ({ fileCount: 0 }),
66
+ };
67
+ /**
68
+ * Extract (and cache) field info for a class node. Cache is passed in so it
69
+ * stays scoped to a single `processCalls` invocation rather than leaking
70
+ * across analyze runs (worker uses module-level caching because each worker
71
+ * process is short-lived; the main thread is not).
72
+ *
73
+ * Cache key is `${filePath}:${classNode.startIndex}` — startIndex alone is a
74
+ * per-file byte offset, so almost every Ruby/Python file's leading class lands
75
+ * at byte 0 and would collide across files in the shared map.
76
+ */
77
+ const getFieldInfo = (classNode, provider, context, cache) => {
78
+ if (!provider.fieldExtractor)
79
+ return undefined;
80
+ const cacheKey = `${context.filePath}:${classNode.startIndex}`;
81
+ const cached = cache.get(cacheKey);
82
+ if (cached)
83
+ return cached;
84
+ const result = provider.fieldExtractor.extract(classNode, context);
85
+ if (!result?.fields?.length)
86
+ return undefined;
87
+ const map = new Map();
88
+ for (const field of result.fields)
89
+ map.set(field.name, field);
90
+ cache.set(cacheKey, map);
91
+ return map;
92
+ };
41
93
  /**
42
94
  * Type labels treated as class-like **method-dispatch receivers** by the call
43
95
  * resolver — the set walked by the MRO / heritage path for member and static
@@ -614,7 +666,7 @@ importedRawReturnTypesMap, heritageMap, bindingAccumulator) => {
614
666
  if (!tree) {
615
667
  const parseContent = provider.preprocessSource?.(file.content, file.path) ?? file.content;
616
668
  try {
617
- tree = parser.parse(parseContent, undefined, {
669
+ tree = parseSourceSafe(parser, parseContent, undefined, {
618
670
  bufferSize: getTreeSitterBufferSize(parseContent),
619
671
  });
620
672
  }
@@ -701,6 +753,111 @@ importedRawReturnTypesMap, heritageMap, bindingAccumulator) => {
701
753
  }
702
754
  prepared.push({ file, language, provider, tree, matches, parentMap, typeEnv });
703
755
  }
756
+ // ── Property-registration pre-pass ──
757
+ // Register all routed properties (e.g. Ruby attr_accessor) BEFORE the
758
+ // resolution loop so cross-file field-type lookups (e.g.
759
+ // `user.address.save → Address#save`) succeed regardless of file
760
+ // processing order. This MUST stay in lockstep with the equivalent
761
+ // worker-path block in parse-worker.ts (kind === 'properties') — any
762
+ // divergence between the two paths breaks the `incremental ≡ --force`
763
+ // invariant once a repo crosses the worker threshold between runs.
764
+ const fieldInfoCache = new Map();
765
+ for (const { file, language, provider, matches, typeEnv } of prepared) {
766
+ const callRouter = provider.callRouter;
767
+ if (!callRouter)
768
+ continue;
769
+ matches.forEach((match) => {
770
+ const captureMap = {};
771
+ match.captures.forEach((c) => (captureMap[c.name] = c.node));
772
+ if (!captureMap['call'])
773
+ return;
774
+ const callNameNode = captureMap['call.name'];
775
+ if (!callNameNode)
776
+ return;
777
+ const routed = callRouter(callNameNode.text, captureMap['call']);
778
+ if (!routed || routed.kind !== 'properties')
779
+ return;
780
+ const propEnclosingInfo = findEnclosingClassInfo(captureMap['call'], file.path, provider.resolveEnclosingOwner);
781
+ const propEnclosingClassId = propEnclosingInfo?.classId ?? null;
782
+ // Enrich routed properties with FieldExtractor metadata so types
783
+ // discovered from constructor assignments (e.g. `@address = Address.new`)
784
+ // are propagated even when the routing payload itself lacks declaredType.
785
+ let routedFieldMap;
786
+ if (provider.fieldExtractor && typeEnv) {
787
+ const classNode = findEnclosingClassNode(captureMap['call']);
788
+ if (classNode) {
789
+ routedFieldMap = getFieldInfo(classNode, provider, {
790
+ typeEnv,
791
+ symbolTable: NOOP_SYMBOL_TABLE,
792
+ filePath: file.path,
793
+ language,
794
+ }, fieldInfoCache);
795
+ }
796
+ }
797
+ const fileId = generateId('File', file.path);
798
+ for (const item of routed.items) {
799
+ const routedFieldInfo = routedFieldMap?.get(item.propName);
800
+ const propQualifiedName = propEnclosingInfo
801
+ ? `${propEnclosingInfo.className}.${item.propName}`
802
+ : item.propName;
803
+ const nodeId = generateId('Property', `${file.path}:${propQualifiedName}`);
804
+ graph.addNode({
805
+ id: nodeId,
806
+ label: 'Property',
807
+ properties: {
808
+ name: item.propName,
809
+ filePath: file.path,
810
+ startLine: item.startLine,
811
+ endLine: item.endLine,
812
+ language,
813
+ isExported: true,
814
+ description: item.accessorType,
815
+ ...(item.declaredType
816
+ ? { declaredType: item.declaredType }
817
+ : routedFieldInfo?.type
818
+ ? { declaredType: routedFieldInfo.type }
819
+ : {}),
820
+ ...(routedFieldInfo?.visibility !== undefined
821
+ ? { visibility: routedFieldInfo.visibility }
822
+ : {}),
823
+ ...(routedFieldInfo?.isStatic !== undefined
824
+ ? { isStatic: routedFieldInfo.isStatic }
825
+ : {}),
826
+ ...(routedFieldInfo?.isReadonly !== undefined
827
+ ? { isReadonly: routedFieldInfo.isReadonly }
828
+ : {}),
829
+ },
830
+ });
831
+ ctx.model.symbols.add(file.path, item.propName, nodeId, 'Property', {
832
+ ...(propEnclosingClassId ? { ownerId: propEnclosingClassId } : {}),
833
+ ...(item.declaredType
834
+ ? { declaredType: item.declaredType }
835
+ : routedFieldInfo?.type
836
+ ? { declaredType: routedFieldInfo.type }
837
+ : {}),
838
+ });
839
+ const relId = generateId('DEFINES', `${fileId}->${nodeId}`);
840
+ graph.addRelationship({
841
+ id: relId,
842
+ sourceId: fileId,
843
+ targetId: nodeId,
844
+ type: 'DEFINES',
845
+ confidence: 1.0,
846
+ reason: '',
847
+ });
848
+ if (propEnclosingClassId) {
849
+ graph.addRelationship({
850
+ id: generateId('HAS_PROPERTY', `${propEnclosingClassId}->${nodeId}`),
851
+ sourceId: propEnclosingClassId,
852
+ targetId: nodeId,
853
+ type: 'HAS_PROPERTY',
854
+ confidence: 1.0,
855
+ reason: '',
856
+ });
857
+ }
858
+ }
859
+ });
860
+ }
704
861
  // ── Resolution loop: verify constructor bindings and resolve calls ──
705
862
  // The accumulator (if present) is now fully populated from the preparation
706
863
  // loop above, so verifyConstructorBindings sees all provider bindings
@@ -749,9 +906,10 @@ importedRawReturnTypesMap, heritageMap, bindingAccumulator) => {
749
906
  if (receiverTypeName) {
750
907
  const enclosing = findEnclosingFunction(captureMap['assignment'], file.path, ctx, provider);
751
908
  const srcId = enclosing || generateId('File', file.path);
752
- // Defer resolution: Ruby attr_accessor properties are registered during
753
- // this same loop, so cross-file lookups fail if the declaring file hasn't
754
- // been processed yet. Collect now, resolve after all files are done.
909
+ // Defer resolution so write-access tracking sees the FINAL graph
910
+ // state — properties from the pre-pass are present, but receiver-type
911
+ // resolution can still depend on inference that completes during the
912
+ // main loop. Resolve after all files have been processed.
755
913
  pendingWrites.push({ receiverTypeName, propertyName, filePath: file.path, srcId });
756
914
  }
757
915
  // Assignment-only capture (no @call sibling): skip the rest of this
@@ -841,47 +999,8 @@ importedRawReturnTypesMap, heritageMap, bindingAccumulator) => {
841
999
  case 'import':
842
1000
  return;
843
1001
  case 'properties': {
844
- const fileId = generateId('File', file.path);
845
- const propEnclosingClassId = findEnclosingClassId(captureMap['call'], file.path);
846
- for (const item of routed.items) {
847
- const nodeId = generateId('Property', `${file.path}:${item.propName}`);
848
- graph.addNode({
849
- id: nodeId,
850
- label: 'Property',
851
- properties: {
852
- name: item.propName,
853
- filePath: file.path,
854
- startLine: item.startLine,
855
- endLine: item.endLine,
856
- language,
857
- isExported: true,
858
- description: item.accessorType,
859
- },
860
- });
861
- ctx.model.symbols.add(file.path, item.propName, nodeId, 'Property', {
862
- ...(propEnclosingClassId ? { ownerId: propEnclosingClassId } : {}),
863
- ...(item.declaredType ? { declaredType: item.declaredType } : {}),
864
- });
865
- const relId = generateId('DEFINES', `${fileId}->${nodeId}`);
866
- graph.addRelationship({
867
- id: relId,
868
- sourceId: fileId,
869
- targetId: nodeId,
870
- type: 'DEFINES',
871
- confidence: 1.0,
872
- reason: '',
873
- });
874
- if (propEnclosingClassId) {
875
- graph.addRelationship({
876
- id: generateId('HAS_PROPERTY', `${propEnclosingClassId}->${nodeId}`),
877
- sourceId: propEnclosingClassId,
878
- targetId: nodeId,
879
- type: 'HAS_PROPERTY',
880
- confidence: 1.0,
881
- reason: '',
882
- });
883
- }
884
- }
1002
+ // Properties already registered in the pre-pass above.
1003
+ // Skip to avoid duplicate nodes/edges.
885
1004
  return;
886
1005
  }
887
1006
  case 'call':
@@ -2586,7 +2705,7 @@ export const extractFetchCallsFromFiles = async (files, astCache) => {
2586
2705
  if (!tree) {
2587
2706
  const parseContent = provider.preprocessSource?.(file.content, file.path) ?? file.content;
2588
2707
  try {
2589
- tree = parser.parse(parseContent, undefined, {
2708
+ tree = parseSourceSafe(parser, parseContent, undefined, {
2590
2709
  bufferSize: getTreeSitterBufferSize(parseContent),
2591
2710
  });
2592
2711
  }
@@ -20,6 +20,23 @@ const __dirname = dirname(__filename);
20
20
  const leidenPath = resolve(__dirname, '..', '..', '..', 'vendor', 'leiden', 'index.cjs');
21
21
  const _require = createRequire(import.meta.url);
22
22
  const leiden = _require(leidenPath);
23
+ /**
24
+ * Deterministic PRNG (mulberry32) seed for the vendored Leiden algorithm.
25
+ * Vendored Leiden defaults `rng: Math.random`, which makes community
26
+ * assignment non-deterministic across runs. Passing a seeded RNG gives us
27
+ * reproducible community/modularity output, which is required for the
28
+ * incremental-indexing equivalence test (incremental ≡ full rebuild).
29
+ */
30
+ const LEIDEN_SEED = 0xc0de;
31
+ function createSeededRng(seed) {
32
+ let s = seed >>> 0;
33
+ return () => {
34
+ s = (s + 0x6d2b79f5) >>> 0;
35
+ let t = Math.imul(s ^ (s >>> 15), 1 | s);
36
+ t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
37
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
38
+ };
39
+ }
23
40
  // ============================================================================
24
41
  // COMMUNITY COLORS (for visualization)
25
42
  // ============================================================================
@@ -83,6 +100,7 @@ export const processCommunities = async (knowledgeGraph, onProgress) => {
83
100
  Promise.resolve(leiden.detailed(graph, {
84
101
  resolution: isLarge ? 2.0 : 1.0,
85
102
  maxIterations: isLarge ? 3 : 0,
103
+ rng: createSeededRng(LEIDEN_SEED),
86
104
  })),
87
105
  new Promise((_, reject) => setTimeout(() => reject(new Error('Leiden timeout')), LEIDEN_TIMEOUT_MS)),
88
106
  ]);
@@ -19,6 +19,7 @@ import { generateId } from '../../lib/utils.js';
19
19
  import { getLanguageFromFilename } from '../../_shared/index.js';
20
20
  import { isVerboseIngestionEnabled } from './utils/verbose.js';
21
21
  import { yieldToEventLoop } from './utils/event-loop.js';
22
+ import { parseSourceSafe } from '../tree-sitter/safe-parse.js';
22
23
  import { getProvider } from './languages/index.js';
23
24
  import { getTreeSitterBufferSize } from './constants.js';
24
25
  import { resolveExtendsType } from './model/heritage-map.js';
@@ -152,7 +153,7 @@ export const processHeritage = async (graph, files, astCache, ctx, onProgress) =
152
153
  // re-parses see the same input as the cached AST.
153
154
  const parseContent = provider.preprocessSource?.(file.content, file.path) ?? file.content;
154
155
  try {
155
- tree = parser.parse(parseContent, undefined, {
156
+ tree = parseSourceSafe(parser, parseContent, undefined, {
156
157
  bufferSize: getTreeSitterBufferSize(parseContent),
157
158
  });
158
159
  }
@@ -300,7 +301,7 @@ export async function extractExtractedHeritageFromFiles(files, astCache) {
300
301
  if (!tree) {
301
302
  const parseContent = provider.preprocessSource?.(file.content, file.path) ?? file.content;
302
303
  try {
303
- tree = parser.parse(parseContent, undefined, {
304
+ tree = parseSourceSafe(parser, parseContent, undefined, {
304
305
  bufferSize: getTreeSitterBufferSize(parseContent),
305
306
  });
306
307
  }
@@ -5,6 +5,7 @@ import { generateId } from '../../lib/utils.js';
5
5
  import { getLanguageFromFilename } from '../../_shared/index.js';
6
6
  import { isVerboseIngestionEnabled } from './utils/verbose.js';
7
7
  import { yieldToEventLoop } from './utils/event-loop.js';
8
+ import { parseSourceSafe } from '../tree-sitter/safe-parse.js';
8
9
  import { getTreeSitterBufferSize } from './constants.js';
9
10
  import { loadImportConfigs } from './language-config.js';
10
11
  import { buildSuffixIndex } from './import-resolvers/utils.js';
@@ -243,7 +244,7 @@ export const processImports = async (graph, files, astCache, ctx, onProgress, re
243
244
  if (!tree) {
244
245
  const parseContent = provider.preprocessSource?.(file.content, file.path) ?? file.content;
245
246
  try {
246
- tree = parser.parse(parseContent, undefined, {
247
+ tree = parseSourceSafe(parser, parseContent, undefined, {
247
248
  bufferSize: getTreeSitterBufferSize(parseContent),
248
249
  });
249
250
  }
@@ -28,3 +28,8 @@ export declare const resolveImportPath: (currentFile: string, importPath: string
28
28
  export declare function resolveStandard(rawImportPath: string, filePath: string, ctx: ResolveCtx, language: SupportedLanguages): ImportResult;
29
29
  /** Create a reusable standard-resolution strategy for a given language. */
30
30
  export declare function createStandardStrategy(language: SupportedLanguages): ImportResolverStrategy;
31
+ /**
32
+ * Strip a JS-family extension from a path, returning the stem.
33
+ * Returns `null` if the path does not end with a JS-family extension.
34
+ */
35
+ export declare function stripJsExtension(path: string): string | null;
@@ -108,7 +108,20 @@ export const resolveImportPath = (currentFile, importPath, allFiles, allFileList
108
108
  const basePath = currentDir.join('/');
109
109
  if (importPath.startsWith('.')) {
110
110
  const resolved = tryResolveWithExtensions(basePath, allFiles);
111
- return cache(resolved);
111
+ if (resolved)
112
+ return cache(resolved);
113
+ // TypeScript ESM: imports use .js/.jsx/.mjs/.cjs but source files are
114
+ // .ts/.tsx/.mts/.cts. Strip the JS-family extension and re-resolve.
115
+ // NOTE: This fallback only applies to relative imports. Path alias imports
116
+ // (e.g. @/utils.js via tsconfig paths) do not yet strip .js extensions —
117
+ // that is a known limitation tracked for follow-up.
118
+ if (language === SupportedLanguages.TypeScript || language === SupportedLanguages.JavaScript) {
119
+ const stripped = stripJsExtension(basePath);
120
+ if (stripped !== null) {
121
+ return cache(tryResolveWithExtensions(stripped, allFiles));
122
+ }
123
+ }
124
+ return cache(null);
112
125
  }
113
126
  // ---- Generic package/absolute import resolution (suffix matching) ----
114
127
  // Java wildcards are handled in processImports, not here
@@ -140,3 +153,16 @@ export function resolveStandard(rawImportPath, filePath, ctx, language) {
140
153
  export function createStandardStrategy(language) {
141
154
  return (raw, fp, ctx) => resolveStandard(raw, fp, ctx, language);
142
155
  }
156
+ // ============================================================================
157
+ // ESM extension helpers
158
+ // ============================================================================
159
+ /** JS-family extensions that TypeScript ESM maps to TS equivalents. */
160
+ const JS_EXTENSION_PATTERN = /\.(js|jsx|mjs|cjs)$/;
161
+ /**
162
+ * Strip a JS-family extension from a path, returning the stem.
163
+ * Returns `null` if the path does not end with a JS-family extension.
164
+ */
165
+ export function stripJsExtension(path) {
166
+ const match = JS_EXTENSION_PATTERN.exec(path);
167
+ return match ? path.slice(0, -match[0].length) : null;
168
+ }
@@ -8,8 +8,12 @@ export const EXTENSIONS = [
8
8
  // TypeScript/JavaScript
9
9
  '.tsx',
10
10
  '.ts',
11
+ '.mts',
12
+ '.cts',
11
13
  '.jsx',
12
14
  '.js',
15
+ '.mjs',
16
+ '.cjs',
13
17
  '.vue',
14
18
  '/index.tsx',
15
19
  '/index.ts',
@@ -0,0 +1,14 @@
1
+ import type { SyntaxNode } from '../../utils/ast-helpers.js';
2
+ export interface CArityInfo {
3
+ parameterCount?: number;
4
+ requiredParameterCount?: number;
5
+ parameterTypes?: string[];
6
+ }
7
+ /**
8
+ * Compute declaration arity from a C function definition or declaration node.
9
+ */
10
+ export declare function computeCDeclarationArity(node: SyntaxNode): CArityInfo;
11
+ /**
12
+ * Compute call-site arity from a call_expression node.
13
+ */
14
+ export declare function computeCCallArity(node: SyntaxNode): number;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Compute declaration arity from a C function definition or declaration node.
3
+ */
4
+ export function computeCDeclarationArity(node) {
5
+ // Find the function_declarator child (may be wrapped in pointer_declarator)
6
+ const funcDecl = findFuncDeclarator(node);
7
+ if (funcDecl === null)
8
+ return {};
9
+ const paramList = funcDecl.childForFieldName('parameters');
10
+ if (paramList === null)
11
+ return {};
12
+ const params = [];
13
+ for (let i = 0; i < paramList.childCount; i++) {
14
+ const child = paramList.child(i);
15
+ if (child === null)
16
+ continue;
17
+ if (child.type === 'parameter_declaration' || child.type === 'variadic_parameter') {
18
+ params.push(child);
19
+ }
20
+ }
21
+ // K&R old-style declaration: `int foo()` has an empty parameter_list with
22
+ // no parameter_declaration or variadic_parameter children. Per C89/C99,
23
+ // this means the function accepts an unspecified number/types of arguments —
24
+ // NOT zero arguments. Return unknown arity to avoid false 'incompatible'.
25
+ // `int foo(void)` is the explicit zero-parameter form and is handled below.
26
+ if (params.length === 0)
27
+ return {};
28
+ // (void) means zero parameters
29
+ if (params.length === 1 && params[0].type === 'parameter_declaration') {
30
+ const typeNode = params[0].childForFieldName('type');
31
+ const hasDeclarator = params[0].childForFieldName('declarator') !== null;
32
+ if (typeNode !== null && typeNode.text === 'void' && !hasDeclarator) {
33
+ return { parameterCount: 0, requiredParameterCount: 0, parameterTypes: [] };
34
+ }
35
+ }
36
+ const isVariadic = params.some((p) => p.type === 'variadic_parameter');
37
+ const nonVariadicCount = params.filter((p) => p.type !== 'variadic_parameter').length;
38
+ const types = [];
39
+ for (const p of params) {
40
+ if (p.type === 'variadic_parameter') {
41
+ types.push('...');
42
+ }
43
+ else {
44
+ const typeNode = p.childForFieldName('type');
45
+ types.push(typeNode?.text ?? 'unknown');
46
+ }
47
+ }
48
+ return {
49
+ parameterCount: isVariadic ? undefined : nonVariadicCount,
50
+ requiredParameterCount: nonVariadicCount,
51
+ parameterTypes: types,
52
+ };
53
+ }
54
+ /**
55
+ * Compute call-site arity from a call_expression node.
56
+ */
57
+ export function computeCCallArity(node) {
58
+ const argList = node.childForFieldName('arguments');
59
+ if (argList === null)
60
+ return 0;
61
+ let count = 0;
62
+ for (let i = 0; i < argList.childCount; i++) {
63
+ const child = argList.child(i);
64
+ if (child === null)
65
+ continue;
66
+ // Skip punctuation (commas, parens)
67
+ if (child.type !== ',' && child.type !== '(' && child.type !== ')') {
68
+ count++;
69
+ }
70
+ }
71
+ return count;
72
+ }
73
+ function findFuncDeclarator(node) {
74
+ // Direct child
75
+ let decl = node.childForFieldName('declarator');
76
+ if (decl === null) {
77
+ for (let i = 0; i < node.childCount; i++) {
78
+ const c = node.child(i);
79
+ if (c?.type === 'function_declarator')
80
+ return c;
81
+ }
82
+ return null;
83
+ }
84
+ // Unwrap pointer_declarator
85
+ while (decl.type === 'pointer_declarator') {
86
+ const next = decl.childForFieldName('declarator');
87
+ if (next === null)
88
+ break;
89
+ decl = next;
90
+ }
91
+ if (decl.type === 'function_declarator')
92
+ return decl;
93
+ return null;
94
+ }
@@ -0,0 +1,6 @@
1
+ import type { Callsite, SymbolDefinition } from '../../../../_shared/index.js';
2
+ /**
3
+ * C arity compatibility: no overloading. Variadic functions detected
4
+ * via '...' in parameterTypes. Otherwise exact match or unknown.
5
+ */
6
+ export declare function cArityCompatibility(def: SymbolDefinition, callsite: Callsite): 'compatible' | 'unknown' | 'incompatible';
@@ -0,0 +1,18 @@
1
+ /**
2
+ * C arity compatibility: no overloading. Variadic functions detected
3
+ * via '...' in parameterTypes. Otherwise exact match or unknown.
4
+ */
5
+ export function cArityCompatibility(def, callsite) {
6
+ const max = def.parameterCount;
7
+ const min = def.requiredParameterCount;
8
+ if (max === undefined && min === undefined)
9
+ return 'unknown';
10
+ if (!Number.isFinite(callsite.arity) || callsite.arity < 0)
11
+ return 'unknown';
12
+ const variadic = def.parameterTypes?.some((t) => t === '...') ?? false;
13
+ if (min !== undefined && callsite.arity < min)
14
+ return 'incompatible';
15
+ if (max !== undefined && callsite.arity > max && !variadic)
16
+ return 'incompatible';
17
+ return 'compatible';
18
+ }
@@ -0,0 +1,2 @@
1
+ import type { CaptureMatch } from '../../../../_shared/index.js';
2
+ export declare function emitCScopeCaptures(sourceText: string, filePath: string, cachedTree?: unknown): readonly CaptureMatch[];
@@ -0,0 +1,105 @@
1
+ import { findNodeAtRange, nodeToCapture, syntheticCapture, } from '../../utils/ast-helpers.js';
2
+ import { getCParser, getCScopeQuery } from './query.js';
3
+ import { getTreeSitterBufferSize } from '../../constants.js';
4
+ import { parseSourceSafe } from '../../../tree-sitter/safe-parse.js';
5
+ import { splitCInclude } from './import-decomposer.js';
6
+ import { computeCDeclarationArity, computeCCallArity } from './arity-metadata.js';
7
+ import { markStaticName } from './static-linkage.js';
8
+ export function emitCScopeCaptures(sourceText, filePath, cachedTree) {
9
+ let tree = cachedTree;
10
+ if (tree === undefined) {
11
+ tree = parseSourceSafe(getCParser(), sourceText, undefined, {
12
+ bufferSize: getTreeSitterBufferSize(sourceText),
13
+ });
14
+ }
15
+ const rawMatches = getCScopeQuery().matches(tree.rootNode);
16
+ const out = [];
17
+ // Track ranges where typedef-struct/union was captured as @declaration.struct/union
18
+ // so we can suppress the duplicate @declaration.typedef match at the same range.
19
+ const structTypedefRanges = new Set();
20
+ for (const m of rawMatches) {
21
+ const grouped = {};
22
+ for (const c of m.captures) {
23
+ const tag = '@' + c.name;
24
+ if (tag.startsWith('@_'))
25
+ continue;
26
+ grouped[tag] = nodeToCapture(tag, c.node);
27
+ }
28
+ if (Object.keys(grouped).length === 0)
29
+ continue;
30
+ // Handle #include statements
31
+ if (grouped['@import.statement'] !== undefined) {
32
+ const anchor = grouped['@import.statement'];
33
+ const includeNode = findNodeAtRange(tree.rootNode, anchor.range, 'preproc_include');
34
+ if (includeNode !== null) {
35
+ const split = splitCInclude(includeNode);
36
+ if (split !== null) {
37
+ out.push(split);
38
+ continue;
39
+ }
40
+ }
41
+ }
42
+ // Track typedef-struct ranges to suppress duplicate typedef declarations
43
+ const structAnchor = grouped['@declaration.struct'] ?? grouped['@declaration.union'];
44
+ if (structAnchor !== undefined) {
45
+ const r = structAnchor.range;
46
+ structTypedefRanges.add(`${r.startLine}:${r.startCol}:${r.endLine}:${r.endCol}`);
47
+ }
48
+ // Suppress @declaration.typedef if the same range was already captured as struct/union
49
+ const typedefAnchor = grouped['@declaration.typedef'];
50
+ if (typedefAnchor !== undefined) {
51
+ const r = typedefAnchor.range;
52
+ const key = `${r.startLine}:${r.startCol}:${r.endLine}:${r.endCol}`;
53
+ if (structTypedefRanges.has(key))
54
+ continue;
55
+ }
56
+ // Enrich function declarations with arity metadata and detect static linkage
57
+ const declAnchor = grouped['@declaration.function'];
58
+ if (declAnchor !== undefined) {
59
+ const fnNode = findNodeAtRange(tree.rootNode, declAnchor.range, 'function_definition') ??
60
+ findNodeAtRange(tree.rootNode, declAnchor.range, 'declaration');
61
+ if (fnNode !== null) {
62
+ const arity = computeCDeclarationArity(fnNode);
63
+ if (arity.parameterCount !== undefined) {
64
+ grouped['@declaration.parameter-count'] = syntheticCapture('@declaration.parameter-count', fnNode, String(arity.parameterCount));
65
+ }
66
+ if (arity.requiredParameterCount !== undefined) {
67
+ grouped['@declaration.required-parameter-count'] = syntheticCapture('@declaration.required-parameter-count', fnNode, String(arity.requiredParameterCount));
68
+ }
69
+ if (arity.parameterTypes !== undefined) {
70
+ grouped['@declaration.parameter-types'] = syntheticCapture('@declaration.parameter-types', fnNode, JSON.stringify(arity.parameterTypes));
71
+ }
72
+ // Detect static storage class (file-local linkage)
73
+ if (hasStaticStorageClass(fnNode)) {
74
+ const nameText = grouped['@declaration.name']?.text;
75
+ if (nameText !== undefined) {
76
+ markStaticName(filePath, nameText);
77
+ }
78
+ }
79
+ }
80
+ }
81
+ // Enrich call references with arity
82
+ const callAnchor = grouped['@reference.call.free'] ?? grouped['@reference.call.member'];
83
+ if (callAnchor !== undefined && grouped['@reference.arity'] === undefined) {
84
+ const callNode = findNodeAtRange(tree.rootNode, callAnchor.range, 'call_expression');
85
+ if (callNode !== null) {
86
+ grouped['@reference.arity'] = syntheticCapture('@reference.arity', callNode, String(computeCCallArity(callNode)));
87
+ }
88
+ }
89
+ out.push(grouped);
90
+ }
91
+ return out;
92
+ }
93
+ /**
94
+ * Check if a C function_definition or declaration has `static` storage class.
95
+ * Walks direct children for a `storage_class_specifier` node with text `static`.
96
+ */
97
+ function hasStaticStorageClass(node) {
98
+ for (let i = 0; i < node.childCount; i++) {
99
+ const child = node.child(i);
100
+ if (child !== null && child.type === 'storage_class_specifier' && child.text === 'static') {
101
+ return true;
102
+ }
103
+ }
104
+ return false;
105
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Walk `repoPath` recursively and return relative paths of all `.h` files.
3
+ * Used by `loadResolutionConfig` so the C resolver can resolve `#include`
4
+ * targets that live in `.h` files (classified as C++ by language detection
5
+ * but importable from `.c` files).
6
+ */
7
+ export declare function scanHeaderFiles(repoPath: string): ReadonlySet<string>;