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
@@ -5,6 +5,7 @@ import { generateId } from '../../lib/utils.js';
5
5
  import { getLanguageFromFilename, SupportedLanguages } from '../../_shared/index.js';
6
6
  import { extractVueScript, isVueSetupTopLevel } from './vue-sfc-extractor.js';
7
7
  import { yieldToEventLoop } from './utils/event-loop.js';
8
+ import { parseSourceSafe } from '../tree-sitter/safe-parse.js';
8
9
  import { isVerboseIngestionEnabled } from './utils/verbose.js';
9
10
  import { getDefinitionNodeFromCaptures, findEnclosingClassInfo, getLabelFromCaptures, CLASS_CONTAINER_TYPES, } from './utils/ast-helpers.js';
10
11
  import { detectFrameworkFromAST } from './framework-detection.js';
@@ -15,35 +16,18 @@ import { getTreeSitterBufferSize, getTreeSitterContentByteLength, TREE_SITTER_MA
15
16
  // ============================================================================
16
17
  // Worker-based parallel parsing
17
18
  // ============================================================================
18
- const processParsingWithWorkers = async (graph, files, symbolTable, astCache, workerPool, onFileProgress) => {
19
- // Filter to parseable files only
20
- const parseableFiles = [];
21
- for (const file of files) {
22
- const lang = getLanguageFromFilename(file.path);
23
- if (lang)
24
- parseableFiles.push({ path: file.path, content: file.content });
25
- }
26
- if (parseableFiles.length === 0)
27
- return {
28
- imports: [],
29
- calls: [],
30
- assignments: [],
31
- heritage: [],
32
- routes: [],
33
- fetchCalls: [],
34
- decoratorRoutes: [],
35
- toolDefs: [],
36
- ormQueries: [],
37
- constructorBindings: [],
38
- fileScopeBindings: [],
39
- parsedFiles: [],
40
- };
41
- const total = files.length;
42
- // Dispatch to worker pool — pool handles splitting into chunks and sub-batching
43
- const chunkResults = await workerPool.dispatch(parseableFiles, (filesProcessed) => {
44
- onFileProgress?.(Math.min(filesProcessed, total), total, 'Parsing...');
45
- });
46
- // Merge results from all workers into graph and symbol table
19
+ /**
20
+ * Merge a list of `ParseWorkerResult`s into the running graph + symbol
21
+ * table state and produce the chunk-aggregated `WorkerExtractedData`.
22
+ *
23
+ * Extracted from `processParsingWithWorkers` so the same merge logic can
24
+ * be applied to both freshly-parsed worker output AND cached worker
25
+ * output replayed during incremental analyze. Idempotent on the
26
+ * accumulator fields (push-only); idempotent on graph if the caller
27
+ * starts from a clean graph (otherwise duplicate `addNode` calls are
28
+ * silently no-op'd by `KnowledgeGraph`).
29
+ */
30
+ export const mergeChunkResults = (graph, symbolTable, chunkResults) => {
47
31
  const allImports = [];
48
32
  const allCalls = [];
49
33
  const allAssignments = [];
@@ -102,14 +86,70 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
102
86
  if (result.fileScopeBindings)
103
87
  for (const item of result.fileScopeBindings)
104
88
  fileScopeBindingsByFile.push(item);
105
- // RFC #909 Ring 2: aggregate per-file scope artifacts. Tolerant of
106
- // workers that don't emit the field yet (older worker builds or
107
- // partial rollouts), since the additive contract means undefined =
108
- // "this worker produced no ParsedFiles for this chunk".
109
89
  if (result.parsedFiles)
110
90
  for (const item of result.parsedFiles)
111
91
  allParsedFiles.push(item);
112
92
  }
93
+ return {
94
+ imports: allImports,
95
+ calls: allCalls,
96
+ assignments: allAssignments,
97
+ heritage: allHeritage,
98
+ routes: allRoutes,
99
+ fetchCalls: allFetchCalls,
100
+ decoratorRoutes: allDecoratorRoutes,
101
+ toolDefs: allToolDefs,
102
+ ormQueries: allORMQueries,
103
+ constructorBindings: allConstructorBindings,
104
+ fileScopeBindings: fileScopeBindingsByFile,
105
+ parsedFiles: allParsedFiles,
106
+ };
107
+ };
108
+ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, workerPool, onFileProgress,
109
+ /**
110
+ * When provided, populated with the raw worker results before merging.
111
+ * Used by the incremental-indexing parse cache to capture the per-chunk
112
+ * worker output for caching across runs. The mutation happens in-place
113
+ * so the caller (parse-impl) can keep a reference. See
114
+ * `gitnexus/src/storage/parse-cache.ts`.
115
+ */
116
+ outRawResults) => {
117
+ // Filter to parseable files only
118
+ const parseableFiles = [];
119
+ for (const file of files) {
120
+ const lang = getLanguageFromFilename(file.path);
121
+ if (lang)
122
+ parseableFiles.push({ path: file.path, content: file.content });
123
+ }
124
+ if (parseableFiles.length === 0)
125
+ return {
126
+ imports: [],
127
+ calls: [],
128
+ assignments: [],
129
+ heritage: [],
130
+ routes: [],
131
+ fetchCalls: [],
132
+ decoratorRoutes: [],
133
+ toolDefs: [],
134
+ ormQueries: [],
135
+ constructorBindings: [],
136
+ fileScopeBindings: [],
137
+ parsedFiles: [],
138
+ };
139
+ const total = files.length;
140
+ // Dispatch to worker pool — pool handles splitting into chunks and sub-batching
141
+ const chunkResults = await workerPool.dispatch(parseableFiles, (filesProcessed) => {
142
+ onFileProgress?.(Math.min(filesProcessed, total), total, 'Parsing...');
143
+ });
144
+ // Capture the raw chunk results for the incremental parse cache before
145
+ // merging — the cache stores the unmerged worker output so a future run
146
+ // can re-merge them into a fresh graph state.
147
+ if (outRawResults) {
148
+ for (const r of chunkResults)
149
+ outRawResults.push(r);
150
+ }
151
+ // Merge results from all workers into graph and symbol table.
152
+ const merged = mergeChunkResults(graph, symbolTable, chunkResults);
113
153
  // Merge and log skipped languages from workers
114
154
  const skippedLanguages = new Map();
115
155
  for (const result of chunkResults) {
@@ -125,20 +165,7 @@ const processParsingWithWorkers = async (graph, files, symbolTable, astCache, wo
125
165
  }
126
166
  // Final progress
127
167
  onFileProgress?.(total, total, 'done');
128
- return {
129
- imports: allImports,
130
- calls: allCalls,
131
- assignments: allAssignments,
132
- heritage: allHeritage,
133
- routes: allRoutes,
134
- fetchCalls: allFetchCalls,
135
- decoratorRoutes: allDecoratorRoutes,
136
- toolDefs: allToolDefs,
137
- ormQueries: allORMQueries,
138
- constructorBindings: allConstructorBindings,
139
- fileScopeBindings: fileScopeBindingsByFile,
140
- parsedFiles: allParsedFiles,
141
- };
168
+ return merged;
142
169
  };
143
170
  // ============================================================================
144
171
  // Sequential fallback (original implementation)
@@ -274,7 +301,7 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, sco
274
301
  }
275
302
  let tree;
276
303
  try {
277
- tree = parser.parse(parseContent, undefined, {
304
+ tree = parseSourceSafe(parser, parseContent, undefined, {
278
305
  bufferSize: getTreeSitterBufferSize(parseContent),
279
306
  });
280
307
  }
@@ -561,7 +588,15 @@ export const processParsing = async (graph, files, symbolTable, astCache,
561
588
  * Worker-mode parses skip — Trees can't cross MessageChannels.
562
589
  * Pass `undefined` if no consumer needs cross-phase access.
563
590
  */
564
- scopeTreeCache, onFileProgress, workerPool) => {
591
+ scopeTreeCache, onFileProgress, workerPool,
592
+ /**
593
+ * Optional out-parameter for the incremental parse cache. When
594
+ * provided AND the worker-pool path runs successfully, populated
595
+ * with the raw `ParseWorkerResult[]` from the workers (pre-merge).
596
+ * Stays empty for the sequential fallback path (no per-chunk
597
+ * artifact to cache there). See `gitnexus/src/storage/parse-cache.ts`.
598
+ */
599
+ outRawResults) => {
565
600
  let lastProgress = 0;
566
601
  const reportProgress = onFileProgress
567
602
  ? (current, total, detail) => {
@@ -578,7 +613,7 @@ scopeTreeCache, onFileProgress, workerPool) => {
578
613
  logger.warn(`[scope-resolution prof] worker pool engaged for ${files.length} files — cross-phase tree cache will be empty; scope-resolution re-parses.`);
579
614
  }
580
615
  try {
581
- return await processParsingWithWorkers(graph, files, symbolTable, astCache, workerPool, reportProgress);
616
+ return await processParsingWithWorkers(graph, files, symbolTable, astCache, workerPool, reportProgress, outRawResults);
582
617
  }
583
618
  catch (err) {
584
619
  const message = err instanceof Error ? err.message : String(err);
@@ -54,5 +54,10 @@ export declare function runChunkedParseAndResolve(graph: KnowledgeGraph, scanned
54
54
  * source. See plan
55
55
  * docs/plans/2026-04-20-002-perf-parse-heritage-mro-plan.md (Unit 4). */
56
56
  scopeTreeCache: ASTCache;
57
+ /** Worker-produced ParsedFile artifacts aggregated across chunks.
58
+ * Threaded into scope-resolution as a re-extract cache so the warm-
59
+ * cache analyze run can skip the dominant `extractParsedFile` cost
60
+ * (otherwise ~58s on a 1000-file repo). */
61
+ parsedFiles: import('../../../_shared/index.js').ParsedFile[];
57
62
  }>;
58
63
  export {};
@@ -12,7 +12,8 @@
12
12
  * @module
13
13
  */
14
14
  import { BindingAccumulator, enrichExportedTypeMap, } from '../binding-accumulator.js';
15
- import { processParsing } from '../parsing-processor.js';
15
+ import { processParsing, mergeChunkResults } from '../parsing-processor.js';
16
+ import { fileContentHash, computeChunkHash } from '../../../storage/parse-cache.js';
16
17
  import { processImports, processImportsFromExtracted, buildImportResolutionContext, } from '../import-processor.js';
17
18
  import { EMPTY_INDEX } from '../import-resolvers/utils.js';
18
19
  import { processCalls, processCallsFromExtracted, processAssignmentsFromExtracted, processRoutesFromExtracted, seedCrossFileReceiverTypes, buildExportedTypeMapFromGraph, } from '../call-processor.js';
@@ -33,8 +34,22 @@ import { synthesizeWildcardImportBindings, needsSynthesis } from './wildcard-syn
33
34
  import { extractORMQueriesInline } from './orm-extraction.js';
34
35
  import { logger } from '../../logger.js';
35
36
  // ── Constants ──────────────────────────────────────────────────────────────
36
- /** Max bytes of source content to load per parse chunk. */
37
- const CHUNK_BYTE_BUDGET = 20 * 1024 * 1024; // 20MB
37
+ /** Max bytes of source content to load per parse chunk.
38
+ *
39
+ * Memory bound for the worker pool dispatch + a granularity knob for
40
+ * the parse cache. A single file change invalidates only its enclosing
41
+ * chunk, so smaller budgets → finer-grained invalidation.
42
+ *
43
+ * Override via GITNEXUS_CHUNK_BYTE_BUDGET (bytes) — the default of 2MB
44
+ * gives a useful invalidation floor (~1/N chunks on a multi-MB repo)
45
+ * while keeping worker dispatch overhead under 5% on cold runs.
46
+ */
47
+ const CHUNK_BYTE_BUDGET = (() => {
48
+ const env = Number(process.env.GITNEXUS_CHUNK_BYTE_BUDGET);
49
+ if (Number.isFinite(env) && env > 0)
50
+ return env;
51
+ return 2 * 1024 * 1024;
52
+ })();
38
53
  /**
39
54
  * Chunked parse + resolve loop.
40
55
  *
@@ -64,6 +79,14 @@ export async function runChunkedParseAndResolve(graph, scannedFiles, allPaths, t
64
79
  for (const [lang, count] of skippedByLang) {
65
80
  logger.warn(`Skipping ${count} ${lang} file(s) — ${lang} parser not available (native binding may not have built). Try: npm rebuild tree-sitter-${lang}`);
66
81
  }
82
+ // Sort parseableScanned alphabetically for stable chunk membership
83
+ // across runs (Finding 4). Without this, filesystem-scan order can
84
+ // shift between runs (notably on macOS APFS where directory entry
85
+ // order can change after modifications) — different files in the
86
+ // same chunk → different chunk hash → cache miss even when no file
87
+ // content changed. The cache also becomes platform-specific: a
88
+ // Linux-built cache misses on macOS for the same repo.
89
+ parseableScanned.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
67
90
  const totalParseable = parseableScanned.length;
68
91
  if (totalParseable === 0) {
69
92
  onProgress({
@@ -164,6 +187,19 @@ export async function runChunkedParseAndResolve(graph, scannedFiles, allPaths, t
164
187
  const deferredWorkerHeritage = [];
165
188
  const deferredConstructorBindings = [];
166
189
  const deferredAssignments = [];
190
+ // Aggregated per-file ParsedFile artifacts produced by workers' calls
191
+ // to `extractParsedFile`. Threaded through to the scope-resolution
192
+ // phase so it can SKIP its own re-extraction on cache hits — this is
193
+ // the second-half of the parse-cache speedup since scope-resolution's
194
+ // re-parse otherwise dominates the warm-cache wall-clock time.
195
+ const allParsedFiles = [];
196
+ // Incremental parse cache (Option B): chunk-level content-addressed.
197
+ // When the chunk's (filePath, content-hash) signature matches a prior
198
+ // run's, replay the cached ParseWorkerResult[] instead of dispatching
199
+ // to workers. See gitnexus/src/storage/parse-cache.ts.
200
+ const parseCache = options?.parseCache;
201
+ let chunkCacheHits = 0;
202
+ let chunkCacheMisses = 0;
167
203
  try {
168
204
  for (let chunkIdx = 0; chunkIdx < numChunks; chunkIdx++) {
169
205
  const chunkPaths = chunks[chunkIdx];
@@ -171,21 +207,76 @@ export async function runChunkedParseAndResolve(graph, scannedFiles, allPaths, t
171
207
  const chunkFiles = chunkPaths
172
208
  .filter((p) => chunkContents.has(p))
173
209
  .map((p) => ({ path: p, content: chunkContents.get(p) }));
174
- const chunkWorkerData = await processParsing(graph, chunkFiles, symbolTable, astCache, scopeTreeCache, (current, _total, filePath) => {
175
- const globalCurrent = filesParsedSoFar + current;
176
- const parsingProgress = 20 + (globalCurrent / totalParseable) * 62;
210
+ // Compute the chunk's content-hash signature (if cache available).
211
+ let chunkHash = null;
212
+ if (parseCache) {
213
+ const entries = chunkFiles.map((f) => ({
214
+ filePath: f.path,
215
+ contentHash: fileContentHash(f.content),
216
+ }));
217
+ chunkHash = computeChunkHash(entries);
218
+ }
219
+ let chunkWorkerData;
220
+ const cachedRaw = chunkHash ? parseCache.entries.get(chunkHash) : undefined;
221
+ // Track every chunk hash we touched so the orchestrator can
222
+ // prune stale entries (chunks whose composition no longer
223
+ // corresponds to a live chunk in the current scan) before saving.
224
+ if (parseCache && chunkHash)
225
+ parseCache.usedKeys.add(chunkHash);
226
+ if (cachedRaw && cachedRaw.length > 0) {
227
+ // Cache hit: replay the cached worker output through the same
228
+ // merge logic the live worker path uses.
229
+ chunkCacheHits++;
230
+ chunkWorkerData = mergeChunkResults(graph, symbolTable, cachedRaw);
231
+ if (isDev) {
232
+ logger.info(`📦 parse-cache HIT: chunk ${chunkIdx + 1}/${numChunks} (${chunkFiles.length} files, ${chunkHash.slice(0, 8)})`);
233
+ }
234
+ // Progress update so UI advances even on a cache hit.
235
+ const cachedFiles = chunkFiles.length;
177
236
  onProgress({
178
237
  phase: 'parsing',
179
- percent: Math.round(parsingProgress),
180
- message: `Parsing chunk ${chunkIdx + 1}/${numChunks}...`,
181
- detail: filePath,
238
+ percent: Math.round(20 + ((filesParsedSoFar + cachedFiles) / totalParseable) * 62),
239
+ message: `Parsing chunk ${chunkIdx + 1}/${numChunks} (cache)...`,
182
240
  stats: {
183
- filesProcessed: globalCurrent,
241
+ filesProcessed: filesParsedSoFar + cachedFiles,
184
242
  totalFiles: totalParseable,
185
243
  nodesCreated: graph.nodeCount,
186
244
  },
187
245
  });
188
- }, workerPool);
246
+ }
247
+ else {
248
+ // Cache miss: dispatch to workers, capture the raw results, store
249
+ // them under the chunk hash for the next run.
250
+ chunkCacheMisses++;
251
+ const rawResults = [];
252
+ chunkWorkerData = await processParsing(graph, chunkFiles, symbolTable, astCache, scopeTreeCache, (current, _total, filePath) => {
253
+ const globalCurrent = filesParsedSoFar + current;
254
+ const parsingProgress = 20 + (globalCurrent / totalParseable) * 62;
255
+ onProgress({
256
+ phase: 'parsing',
257
+ percent: Math.round(parsingProgress),
258
+ message: `Parsing chunk ${chunkIdx + 1}/${numChunks}...`,
259
+ detail: filePath,
260
+ stats: {
261
+ filesProcessed: globalCurrent,
262
+ totalFiles: totalParseable,
263
+ nodesCreated: graph.nodeCount,
264
+ },
265
+ });
266
+ }, workerPool,
267
+ // Capture raw results only when we have a cache to write to —
268
+ // otherwise we'd retain extra arrays for nothing.
269
+ parseCache && chunkHash ? rawResults : undefined);
270
+ // Persist the raw results for this chunk hash. Sequential path
271
+ // doesn't populate rawResults (it writes directly to graph), so
272
+ // small repos without worker pool simply don't cache. That's fine.
273
+ if (parseCache && chunkHash && rawResults.length > 0) {
274
+ parseCache.entries.set(chunkHash, rawResults);
275
+ if (isDev) {
276
+ logger.info(`📦 parse-cache MISS+store: chunk ${chunkIdx + 1}/${numChunks} (${chunkFiles.length} files, ${chunkHash.slice(0, 8)})`);
277
+ }
278
+ }
279
+ }
189
280
  const chunkBasePercent = 20 + (filesParsedSoFar / totalParseable) * 62;
190
281
  if (chunkWorkerData) {
191
282
  await processImportsFromExtracted(graph, allPathObjects, chunkWorkerData.imports, ctx, (current, total) => {
@@ -217,6 +308,13 @@ export async function runChunkedParseAndResolve(graph, scannedFiles, allPaths, t
217
308
  deferredWorkerHeritage.push(item);
218
309
  for (const item of chunkWorkerData.constructorBindings)
219
310
  deferredConstructorBindings.push(item);
311
+ // Aggregate worker-produced ParsedFile artifacts so scope-
312
+ // resolution can use them as a re-extraction cache (skips its
313
+ // own tree-sitter re-parse on warm runs).
314
+ if (chunkWorkerData.parsedFiles?.length) {
315
+ for (const item of chunkWorkerData.parsedFiles)
316
+ allParsedFiles.push(item);
317
+ }
220
318
  if (chunkWorkerData.assignments?.length) {
221
319
  for (const item of chunkWorkerData.assignments)
222
320
  deferredAssignments.push(item);
@@ -297,6 +395,9 @@ export async function runChunkedParseAndResolve(graph, scannedFiles, allPaths, t
297
395
  filesParsedSoFar += chunkFiles.length;
298
396
  astCache.clear();
299
397
  }
398
+ if (isDev && parseCache && (chunkCacheHits > 0 || chunkCacheMisses > 0)) {
399
+ logger.info(`📦 parse-cache summary: ${chunkCacheHits} chunk hit(s), ${chunkCacheMisses} miss(es) across ${numChunks} chunk(s)`);
400
+ }
300
401
  const fullWorkerHeritageMap = deferredWorkerHeritage.length > 0
301
402
  ? buildHeritageMap(deferredWorkerHeritage, ctx, getHeritageStrategyForLanguage)
302
403
  : undefined;
@@ -455,5 +556,12 @@ export async function runChunkedParseAndResolve(graph, scannedFiles, allPaths, t
455
556
  // chunk-local `astCache` above is intentionally NOT exposed
456
557
  // because parse-impl clears it between chunks.
457
558
  scopeTreeCache,
559
+ // Per-file ParsedFile artifacts produced by workers' calls to
560
+ // `extractParsedFile`. Empty when only the sequential path ran
561
+ // (sequential doesn't go through the worker, and extracts ParsedFile
562
+ // inline rather than emitting it). Consumed by scope-resolution as
563
+ // a re-extraction cache: when the file's ParsedFile is here,
564
+ // scope-resolution skips its own `extractParsedFile` call.
565
+ parsedFiles: allParsedFiles,
458
566
  };
459
567
  }
@@ -17,6 +17,7 @@
17
17
  */
18
18
  import type { PipelinePhase } from './types.js';
19
19
  import type { BindingAccumulator } from '../binding-accumulator.js';
20
+ import type { ParsedFile } from '../../../_shared/index.js';
20
21
  import type { ExtractedFetchCall, ExtractedRoute, ExtractedDecoratorRoute, ExtractedToolDef, ExtractedORMQuery } from '../workers/parse-worker.js';
21
22
  import type { createResolutionContext } from '../model/resolution-context.js';
22
23
  import type { ASTCache } from '../ast-cache.js';
@@ -70,5 +71,18 @@ export interface ParseOutput {
70
71
  * `scopeTreeCache.clear()` after its extract loop finishes.
71
72
  */
72
73
  readonly scopeTreeCache: ASTCache;
74
+ /**
75
+ * Per-file `ParsedFile` artifacts produced by workers' calls to
76
+ * `extractParsedFile`. Threaded through to `scopeResolutionPhase`
77
+ * as a re-extraction cache: when a file's ParsedFile is present here,
78
+ * scope-resolution can skip its own `extractParsedFile` (which would
79
+ * otherwise re-parse the file with tree-sitter on the main thread,
80
+ * costing ~58s on a 1000-file repo).
81
+ *
82
+ * Empty for files that went through the sequential parse fallback —
83
+ * sequential doesn't emit ParsedFile artifacts; scope-resolution
84
+ * falls back to a fresh extract for those.
85
+ */
86
+ readonly parsedFiles: readonly ParsedFile[];
73
87
  }
74
88
  export declare const parsePhase: PipelinePhase<ParseOutput>;
@@ -32,5 +32,18 @@ export interface PipelineOptions {
32
32
  minFiles?: number;
33
33
  minBytes?: number;
34
34
  };
35
+ /**
36
+ * Incremental-indexing parse cache. When provided:
37
+ * - The parse phase looks up each chunk's content hash in
38
+ * `parseCache.entries`. On hit, it replays the cached
39
+ * `ParseWorkerResult[]` instead of dispatching to workers.
40
+ * - On miss, it runs the workers as today and stores the new
41
+ * results in `parseCache.entries` keyed by chunk hash.
42
+ * The caller (`run-analyze.ts`) is responsible for loading the cache
43
+ * before the pipeline runs and persisting it after. Cache survives
44
+ * `--force` because keys are content-addressed.
45
+ * See `gitnexus/src/storage/parse-cache.ts`.
46
+ */
47
+ parseCache?: import('../../storage/parse-cache.js').ParseCache;
35
48
  }
36
49
  export declare const runPipelineFromRepo: (repoPath: string, onProgress: (progress: PipelineProgress) => void, options?: PipelineOptions) => Promise<PipelineResult>;
@@ -69,6 +69,8 @@ export const MIGRATED_LANGUAGES = new Set([
69
69
  SupportedLanguages.CSharp,
70
70
  SupportedLanguages.TypeScript,
71
71
  SupportedLanguages.Go,
72
+ SupportedLanguages.C,
73
+ SupportedLanguages.PHP,
72
74
  ]);
73
75
  /**
74
76
  * Return the env-var name that controls a given language's registry-
@@ -342,6 +342,21 @@ export interface ScopeResolver {
342
342
  * inheritance).
343
343
  */
344
344
  buildMro(graph: KnowledgeGraph, parsedFiles: readonly ParsedFile[], nodeLookup: GraphNodeLookup): Map<string, string[]>;
345
+ /**
346
+ * Optional parallel MRO that EXCLUDES mixin-like augmentation (e.g., PHP
347
+ * traits). Returns the inheritance-only ancestor chain — the same kind
348
+ * of map as `buildMro` but built only from inheritance edges (EXTENDS).
349
+ *
350
+ * Used by the shared super-branch dispatch in `receiver-bound-calls`
351
+ * so that `parent::method()` walks the inheritance chain only, not the
352
+ * trait-augmented one. PHP semantics: `parent::` explicitly bypasses
353
+ * traits, even when a composed trait shadows a same-named parent method.
354
+ *
355
+ * Languages without mixin-like semantics leave this undefined — callers
356
+ * fall back to `buildMro`/`mroFor`, which for those languages is already
357
+ * the inheritance chain.
358
+ */
359
+ readonly buildExtendsOnlyMro?: (graph: KnowledgeGraph, parsedFiles: readonly ParsedFile[], nodeLookup: GraphNodeLookup) => Map<string, string[]>;
345
360
  /**
346
361
  * Mutate `parsed.localDefs[i].ownerId` to point at the structural
347
362
  * owner. Python's rule: methods (Function defs whose parent scope
@@ -414,6 +429,36 @@ export interface ScopeResolver {
414
429
  * but is too loose as a default for strict module systems.
415
430
  */
416
431
  readonly allowGlobalFreeCallFallback?: boolean;
432
+ /**
433
+ * Optional predicate to identify definitions with file-local linkage
434
+ * (e.g. C `static` functions). When provided, `pickUniqueGlobalCallable`
435
+ * excludes defs where `isFileLocalDef(def) === true` and the def lives
436
+ * in a different file from the caller. This prevents the global free-call
437
+ * fallback from creating CALLS edges to file-local symbols that are
438
+ * logically invisible from the caller's translation unit.
439
+ *
440
+ * Languages without file-local linkage semantics leave this undefined.
441
+ */
442
+ readonly isFileLocalDef?: (def: SymbolDefinition) => boolean;
443
+ /**
444
+ * Optional predicate to gate free-call fallback emission by caller-side
445
+ * visibility. When provided, `pickUniqueGlobalCallable` rejects candidates
446
+ * the caller cannot legally reach — e.g., a PHP function in a different
447
+ * namespace with no `use function` import, which PHP runtime would treat
448
+ * as `Call to undefined function`. Returning `false` blocks the candidate;
449
+ * returning `true` allows it; undefined-default keeps current behavior
450
+ * (no visibility filtering, equivalent to "all candidates visible").
451
+ *
452
+ * The hook receives the caller's `ParsedFile` (so it can consult
453
+ * `parsedImports`, `moduleScope`, etc.) and the candidate `SymbolDefinition`.
454
+ * The predicate must be pure: same inputs → same answer.
455
+ *
456
+ * Languages without namespace-scoped function resolution leave this undefined.
457
+ */
458
+ readonly isCallableVisibleFromCaller?: (ctx: {
459
+ readonly callerParsed: ParsedFile;
460
+ readonly candidate: SymbolDefinition;
461
+ }) => boolean;
417
462
  /**
418
463
  * Optional post-finalize hook to inject cross-file bindings that
419
464
  * aren't modeled via explicit imports. Runs after
@@ -490,4 +535,24 @@ export interface ScopeResolver {
490
535
  get(filePath: string): unknown;
491
536
  };
492
537
  }) => void;
538
+ /**
539
+ * Optional post-resolution pass: emit CALLS edges for member-call sites
540
+ * whose receiver cannot be typed by the scope chain (no `TypeRef`).
541
+ * Dynamically-typed languages with untyped/`mixed`/`Any` parameters use
542
+ * this hook to recover the call edge via workspace-wide method-name
543
+ * lookup, mirroring what their legacy resolvers did.
544
+ *
545
+ * Runs AFTER `emitReceiverBoundCalls` and BEFORE `emitFreeCallFallback`.
546
+ * Implementations MUST:
547
+ * - Skip sites already in `handledSites` (Invariant I2).
548
+ * - Add resolved site keys to `handledSites` before returning.
549
+ * - Stay narrow: a unique workspace-wide match is the safe baseline.
550
+ * Multi-candidate fallbacks should narrow by arity / argument types
551
+ * before emitting to keep false-positive rate bounded.
552
+ *
553
+ * Returns the number of edges emitted (for telemetry).
554
+ *
555
+ * Default: undefined (no unresolved-receiver fallback).
556
+ */
557
+ readonly emitUnresolvedReceiverEdges?: (graph: KnowledgeGraph, scopes: ScopeResolutionIndexes, parsedFiles: readonly ParsedFile[], nodeLookup: GraphNodeLookup, handledSites: Set<string>, model: SemanticModel) => number;
493
558
  }
@@ -16,4 +16,4 @@
16
16
  * can extend the return shape without breaking existing consumers.
17
17
  */
18
18
  import type { MethodDispatchIndex } from '../../../../_shared/index.js';
19
- export declare function buildPopulatedMethodDispatch(mroByDefId: ReadonlyMap<string, readonly string[]>): MethodDispatchIndex;
19
+ export declare function buildPopulatedMethodDispatch(mroByDefId: ReadonlyMap<string, readonly string[]>, extendsOnlyMroByDefId?: ReadonlyMap<string, readonly string[]>): MethodDispatchIndex;
@@ -16,8 +16,8 @@
16
16
  * can extend the return shape without breaking existing consumers.
17
17
  */
18
18
  const EMPTY_DEFS = Object.freeze([]);
19
- export function buildPopulatedMethodDispatch(mroByDefId) {
20
- return {
19
+ export function buildPopulatedMethodDispatch(mroByDefId, extendsOnlyMroByDefId) {
20
+ const base = {
21
21
  mroByOwnerDefId: mroByDefId,
22
22
  implsByInterfaceDefId: new Map(),
23
23
  mroFor(ownerDefId) {
@@ -27,4 +27,14 @@ export function buildPopulatedMethodDispatch(mroByDefId) {
27
27
  return EMPTY_DEFS;
28
28
  },
29
29
  };
30
+ if (extendsOnlyMroByDefId !== undefined) {
31
+ return {
32
+ ...base,
33
+ extendsOnlyMroByOwnerDefId: extendsOnlyMroByDefId,
34
+ extendsOnlyMroFor(ownerDefId) {
35
+ return extendsOnlyMroByDefId.get(ownerDefId) ?? EMPTY_DEFS;
36
+ },
37
+ };
38
+ }
39
+ return base;
30
40
  }
@@ -105,6 +105,11 @@ export function isLinkableLabel(label) {
105
105
  label === 'Interface' ||
106
106
  label === 'Struct' ||
107
107
  label === 'Enum' ||
108
+ // Trait nodes are linkable so MRO builders can bridge PHP/Rust trait
109
+ // defs between scope-resolution DefIds and the graph's node ids.
110
+ // IMPLEMENTS edges from classes to traits are otherwise invisible to
111
+ // the scope-resolution MRO pass.
112
+ label === 'Trait' ||
108
113
  // Variable / Property are linkable too — receiver-bound write/read
109
114
  // ACCESSES edges target field nodes (e.g. `user.name = "x"` →
110
115
  // ACCESSES edge to User's `name` Variable/Property node).
@@ -16,7 +16,7 @@
16
16
  * Generic; promoted from `languages/python/scope-resolver.ts` per the scope-resolution
17
17
  * generalization plan.
18
18
  */
19
- import type { ParsedFile, Reference, ScopeId } from '../../../../_shared/index.js';
19
+ import type { ParsedFile, Reference, ScopeId, SymbolDefinition } from '../../../../_shared/index.js';
20
20
  import type { KnowledgeGraph } from '../../../graph/types.js';
21
21
  import type { ScopeResolutionIndexes } from '../../model/scope-resolution-indexes.js';
22
22
  import type { SemanticModel } from '../../model/semantic-model.js';
@@ -26,4 +26,28 @@ export declare function emitFreeCallFallback(graph: KnowledgeGraph, scopes: Scop
26
26
  readonly bySourceScope: ReadonlyMap<ScopeId, readonly Reference[]>;
27
27
  }, handledSites: Set<string>, model: SemanticModel, workspaceIndex: WorkspaceResolutionIndex, options?: {
28
28
  readonly allowGlobalFallback?: boolean;
29
+ readonly isFileLocalDef?: (def: SymbolDefinition) => boolean;
30
+ readonly isCallableVisibleFromCaller?: (ctx: {
31
+ readonly callerParsed: ParsedFile;
32
+ readonly candidate: SymbolDefinition;
33
+ }) => boolean;
29
34
  }): number;
35
+ /** Walk up from the call-site scope to the enclosing class scope,
36
+ * pick a method member by name with overload narrowing on arity +
37
+ * argument types. Returns undefined if there's no enclosing class,
38
+ * no matching method, OR narrowing leaves multiple compatible
39
+ * candidates — in the multi-candidate case, picking
40
+ * `candidates[0]` would emit a high-confidence CALLS edge whose
41
+ * target depends on registration order rather than a defensible
42
+ * resolution. Mirrors `pickUniqueGlobalCallable`'s uniqueness check
43
+ * in the same file (Codex PR #1497 review, finding 2).
44
+ *
45
+ * Exported for unit testing — language-agnostic logic, exercised
46
+ * via synthetic stubs in `pick-implicit-this-overload.test.ts`. The
47
+ * production call site is `applyFreeCallFallback` immediately above. */
48
+ export declare function pickImplicitThisOverload(site: {
49
+ readonly inScope: ScopeId;
50
+ readonly name: string;
51
+ readonly arity?: number;
52
+ readonly argumentTypes?: readonly string[];
53
+ }, scopes: ScopeResolutionIndexes, workspaceIndex: WorkspaceResolutionIndex, model: SemanticModel): SymbolDefinition | undefined;