homegraph 1.1.3 → 1.4.1

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 (412) hide show
  1. package/README.md +43 -18
  2. package/dist/arkts/ohos-api-index.d.ts +15 -0
  3. package/dist/arkts/ohos-api-index.d.ts.map +1 -0
  4. package/dist/arkts/ohos-api-index.js +190 -0
  5. package/dist/arkts/ohos-api-index.js.map +1 -0
  6. package/dist/arkts/ohos-sdk-input.d.ts +36 -0
  7. package/dist/arkts/ohos-sdk-input.d.ts.map +1 -0
  8. package/dist/arkts/ohos-sdk-input.js +214 -0
  9. package/dist/arkts/ohos-sdk-input.js.map +1 -0
  10. package/dist/bin/command-supervision.d.ts +12 -0
  11. package/dist/bin/command-supervision.d.ts.map +1 -0
  12. package/dist/bin/command-supervision.js +86 -0
  13. package/dist/bin/command-supervision.js.map +1 -0
  14. package/dist/bin/homegraph.d.ts +1 -1
  15. package/dist/bin/homegraph.js +709 -168
  16. package/dist/bin/homegraph.js.map +1 -1
  17. package/dist/context/index.d.ts.map +1 -1
  18. package/dist/context/index.js +85 -0
  19. package/dist/context/index.js.map +1 -1
  20. package/dist/db/index.d.ts +84 -5
  21. package/dist/db/index.d.ts.map +1 -1
  22. package/dist/db/index.js +217 -14
  23. package/dist/db/index.js.map +1 -1
  24. package/dist/db/migrations.d.ts +1 -1
  25. package/dist/db/migrations.d.ts.map +1 -1
  26. package/dist/db/migrations.js +58 -1
  27. package/dist/db/migrations.js.map +1 -1
  28. package/dist/db/queries.d.ts +131 -2
  29. package/dist/db/queries.d.ts.map +1 -1
  30. package/dist/db/queries.js +473 -9
  31. package/dist/db/queries.js.map +1 -1
  32. package/dist/db/schema.sql +52 -1
  33. package/dist/db/wal-valve.d.ts +106 -0
  34. package/dist/db/wal-valve.d.ts.map +1 -0
  35. package/dist/db/wal-valve.js +208 -0
  36. package/dist/db/wal-valve.js.map +1 -0
  37. package/dist/directory.d.ts +36 -0
  38. package/dist/directory.d.ts.map +1 -1
  39. package/dist/directory.js +274 -0
  40. package/dist/directory.js.map +1 -1
  41. package/dist/extraction/arkts-batch-worker.d.ts +2 -0
  42. package/dist/extraction/arkts-batch-worker.d.ts.map +1 -0
  43. package/dist/extraction/arkts-batch-worker.js +28 -0
  44. package/dist/extraction/arkts-batch-worker.js.map +1 -0
  45. package/dist/extraction/cfml-extractor.d.ts +107 -0
  46. package/dist/extraction/cfml-extractor.d.ts.map +1 -0
  47. package/dist/extraction/cfml-extractor.js +494 -0
  48. package/dist/extraction/cfml-extractor.js.map +1 -0
  49. package/dist/extraction/context.d.ts +11 -0
  50. package/dist/extraction/context.d.ts.map +1 -1
  51. package/dist/extraction/context.js +20 -0
  52. package/dist/extraction/context.js.map +1 -1
  53. package/dist/extraction/grammars.d.ts +25 -1
  54. package/dist/extraction/grammars.d.ts.map +1 -1
  55. package/dist/extraction/grammars.js +177 -24
  56. package/dist/extraction/grammars.js.map +1 -1
  57. package/dist/extraction/index.d.ts +55 -2
  58. package/dist/extraction/index.d.ts.map +1 -1
  59. package/dist/extraction/index.js +923 -381
  60. package/dist/extraction/index.js.map +1 -1
  61. package/dist/extraction/languages/arkts-state-decorators.d.ts +13 -0
  62. package/dist/extraction/languages/arkts-state-decorators.d.ts.map +1 -0
  63. package/dist/extraction/languages/arkts-state-decorators.js +26 -0
  64. package/dist/extraction/languages/arkts-state-decorators.js.map +1 -0
  65. package/dist/extraction/languages/arkts-viewtree.d.ts +4 -2
  66. package/dist/extraction/languages/arkts-viewtree.d.ts.map +1 -1
  67. package/dist/extraction/languages/arkts-viewtree.js +21 -6
  68. package/dist/extraction/languages/arkts-viewtree.js.map +1 -1
  69. package/dist/extraction/languages/arkts.d.ts +98 -2
  70. package/dist/extraction/languages/arkts.d.ts.map +1 -1
  71. package/dist/extraction/languages/arkts.js +1290 -61
  72. package/dist/extraction/languages/arkts.js.map +1 -1
  73. package/dist/extraction/languages/c-cpp.d.ts +98 -0
  74. package/dist/extraction/languages/c-cpp.d.ts.map +1 -1
  75. package/dist/extraction/languages/c-cpp.js +563 -1
  76. package/dist/extraction/languages/c-cpp.js.map +1 -1
  77. package/dist/extraction/languages/cfquery.d.ts +12 -0
  78. package/dist/extraction/languages/cfquery.d.ts.map +1 -0
  79. package/dist/extraction/languages/cfquery.js +28 -0
  80. package/dist/extraction/languages/cfquery.js.map +1 -0
  81. package/dist/extraction/languages/cfscript.d.ts +3 -0
  82. package/dist/extraction/languages/cfscript.d.ts.map +1 -0
  83. package/dist/extraction/languages/cfscript.js +73 -0
  84. package/dist/extraction/languages/cfscript.js.map +1 -0
  85. package/dist/extraction/languages/cobol.d.ts +33 -0
  86. package/dist/extraction/languages/cobol.d.ts.map +1 -0
  87. package/dist/extraction/languages/cobol.js +499 -0
  88. package/dist/extraction/languages/cobol.js.map +1 -0
  89. package/dist/extraction/languages/erlang.d.ts +3 -0
  90. package/dist/extraction/languages/erlang.d.ts.map +1 -0
  91. package/dist/extraction/languages/erlang.js +350 -0
  92. package/dist/extraction/languages/erlang.js.map +1 -0
  93. package/dist/extraction/languages/index.d.ts.map +1 -1
  94. package/dist/extraction/languages/index.js +16 -0
  95. package/dist/extraction/languages/index.js.map +1 -1
  96. package/dist/extraction/languages/nix.d.ts +3 -0
  97. package/dist/extraction/languages/nix.d.ts.map +1 -0
  98. package/dist/extraction/languages/nix.js +294 -0
  99. package/dist/extraction/languages/nix.js.map +1 -0
  100. package/dist/extraction/languages/ohos-api-consumer.d.ts +34 -0
  101. package/dist/extraction/languages/ohos-api-consumer.d.ts.map +1 -0
  102. package/dist/extraction/languages/ohos-api-consumer.js +283 -0
  103. package/dist/extraction/languages/ohos-api-consumer.js.map +1 -0
  104. package/dist/extraction/languages/solidity.d.ts +3 -0
  105. package/dist/extraction/languages/solidity.d.ts.map +1 -0
  106. package/dist/extraction/languages/solidity.js +293 -0
  107. package/dist/extraction/languages/solidity.js.map +1 -0
  108. package/dist/extraction/languages/terraform.d.ts +3 -0
  109. package/dist/extraction/languages/terraform.d.ts.map +1 -0
  110. package/dist/extraction/languages/terraform.js +641 -0
  111. package/dist/extraction/languages/terraform.js.map +1 -0
  112. package/dist/extraction/languages/vbnet.d.ts +11 -0
  113. package/dist/extraction/languages/vbnet.d.ts.map +1 -0
  114. package/dist/extraction/languages/vbnet.js +141 -0
  115. package/dist/extraction/languages/vbnet.js.map +1 -0
  116. package/dist/extraction/mybatis-extractor.d.ts +30 -10
  117. package/dist/extraction/mybatis-extractor.d.ts.map +1 -1
  118. package/dist/extraction/mybatis-extractor.js +140 -38
  119. package/dist/extraction/mybatis-extractor.js.map +1 -1
  120. package/dist/extraction/parse-pool.d.ts +152 -0
  121. package/dist/extraction/parse-pool.d.ts.map +1 -0
  122. package/dist/extraction/parse-pool.js +387 -0
  123. package/dist/extraction/parse-pool.js.map +1 -0
  124. package/dist/extraction/parse-worker.js +9 -2
  125. package/dist/extraction/parse-worker.js.map +1 -1
  126. package/dist/extraction/tree-sitter-helpers.d.ts.map +1 -1
  127. package/dist/extraction/tree-sitter-helpers.js +1 -0
  128. package/dist/extraction/tree-sitter-helpers.js.map +1 -1
  129. package/dist/extraction/tree-sitter-types.d.ts +20 -1
  130. package/dist/extraction/tree-sitter-types.d.ts.map +1 -1
  131. package/dist/extraction/tree-sitter.d.ts +59 -0
  132. package/dist/extraction/tree-sitter.d.ts.map +1 -1
  133. package/dist/extraction/tree-sitter.js +952 -37
  134. package/dist/extraction/tree-sitter.js.map +1 -1
  135. package/dist/extraction/wasm/tree-sitter-arkts.wasm +0 -0
  136. package/dist/extraction/wasm/tree-sitter-cfml.wasm +0 -0
  137. package/dist/extraction/wasm/tree-sitter-cfquery.wasm +0 -0
  138. package/dist/extraction/wasm/tree-sitter-cfscript.wasm +0 -0
  139. package/dist/extraction/wasm/tree-sitter-cobol.wasm +0 -0
  140. package/dist/extraction/wasm/tree-sitter-erlang.wasm +0 -0
  141. package/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
  142. package/dist/extraction/wasm/tree-sitter-terraform.wasm +0 -0
  143. package/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
  144. package/dist/graph/traversal.d.ts.map +1 -1
  145. package/dist/graph/traversal.js +77 -18
  146. package/dist/graph/traversal.js.map +1 -1
  147. package/dist/index.d.ts +85 -2
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +426 -9
  150. package/dist/index.js.map +1 -1
  151. package/dist/installer/index.d.ts +42 -0
  152. package/dist/installer/index.d.ts.map +1 -1
  153. package/dist/installer/index.js +97 -2
  154. package/dist/installer/index.js.map +1 -1
  155. package/dist/mcp/daemon-paths.d.ts +30 -3
  156. package/dist/mcp/daemon-paths.d.ts.map +1 -1
  157. package/dist/mcp/daemon-paths.js +50 -10
  158. package/dist/mcp/daemon-paths.js.map +1 -1
  159. package/dist/mcp/daemon-registry.d.ts.map +1 -1
  160. package/dist/mcp/daemon-registry.js +7 -3
  161. package/dist/mcp/daemon-registry.js.map +1 -1
  162. package/dist/mcp/daemon.d.ts +73 -3
  163. package/dist/mcp/daemon.d.ts.map +1 -1
  164. package/dist/mcp/daemon.js +258 -40
  165. package/dist/mcp/daemon.js.map +1 -1
  166. package/dist/mcp/dynamic-boundaries.d.ts.map +1 -1
  167. package/dist/mcp/dynamic-boundaries.js +2 -1
  168. package/dist/mcp/dynamic-boundaries.js.map +1 -1
  169. package/dist/mcp/early-ppid.d.ts +26 -0
  170. package/dist/mcp/early-ppid.d.ts.map +1 -0
  171. package/dist/mcp/early-ppid.js +29 -0
  172. package/dist/mcp/early-ppid.js.map +1 -0
  173. package/dist/mcp/engine.d.ts +16 -0
  174. package/dist/mcp/engine.d.ts.map +1 -1
  175. package/dist/mcp/engine.js +100 -2
  176. package/dist/mcp/engine.js.map +1 -1
  177. package/dist/mcp/index.d.ts.map +1 -1
  178. package/dist/mcp/index.js +66 -49
  179. package/dist/mcp/index.js.map +1 -1
  180. package/dist/mcp/liveness-watchdog.d.ts +18 -1
  181. package/dist/mcp/liveness-watchdog.d.ts.map +1 -1
  182. package/dist/mcp/liveness-watchdog.js +73 -13
  183. package/dist/mcp/liveness-watchdog.js.map +1 -1
  184. package/dist/mcp/memory-budget.d.ts +30 -0
  185. package/dist/mcp/memory-budget.d.ts.map +1 -0
  186. package/dist/mcp/memory-budget.js +123 -0
  187. package/dist/mcp/memory-budget.js.map +1 -0
  188. package/dist/mcp/ppid-watchdog.d.ts +18 -0
  189. package/dist/mcp/ppid-watchdog.d.ts.map +1 -1
  190. package/dist/mcp/ppid-watchdog.js +37 -0
  191. package/dist/mcp/ppid-watchdog.js.map +1 -1
  192. package/dist/mcp/proxy.d.ts.map +1 -1
  193. package/dist/mcp/proxy.js +88 -4
  194. package/dist/mcp/proxy.js.map +1 -1
  195. package/dist/mcp/query-cache.d.ts +56 -0
  196. package/dist/mcp/query-cache.d.ts.map +1 -0
  197. package/dist/mcp/query-cache.js +261 -0
  198. package/dist/mcp/query-cache.js.map +1 -0
  199. package/dist/mcp/query-pool.d.ts +128 -0
  200. package/dist/mcp/query-pool.d.ts.map +1 -0
  201. package/dist/mcp/query-pool.js +374 -0
  202. package/dist/mcp/query-pool.js.map +1 -0
  203. package/dist/mcp/query-worker.d.ts +24 -0
  204. package/dist/mcp/query-worker.d.ts.map +1 -0
  205. package/dist/mcp/query-worker.js +87 -0
  206. package/dist/mcp/query-worker.js.map +1 -0
  207. package/dist/mcp/server-instructions.d.ts +4 -29
  208. package/dist/mcp/server-instructions.d.ts.map +1 -1
  209. package/dist/mcp/server-instructions.js +39 -86
  210. package/dist/mcp/server-instructions.js.map +1 -1
  211. package/dist/mcp/session.d.ts +14 -0
  212. package/dist/mcp/session.d.ts.map +1 -1
  213. package/dist/mcp/session.js +28 -1
  214. package/dist/mcp/session.js.map +1 -1
  215. package/dist/mcp/startup-handshake.d.ts +44 -0
  216. package/dist/mcp/startup-handshake.d.ts.map +1 -0
  217. package/dist/mcp/startup-handshake.js +73 -0
  218. package/dist/mcp/startup-handshake.js.map +1 -0
  219. package/dist/mcp/tools.d.ts +179 -2
  220. package/dist/mcp/tools.d.ts.map +1 -1
  221. package/dist/mcp/tools.js +3027 -192
  222. package/dist/mcp/tools.js.map +1 -1
  223. package/dist/mcp/transport.d.ts.map +1 -1
  224. package/dist/mcp/transport.js +18 -0
  225. package/dist/mcp/transport.js.map +1 -1
  226. package/dist/project-config.d.ts +58 -0
  227. package/dist/project-config.d.ts.map +1 -1
  228. package/dist/project-config.js +141 -2
  229. package/dist/project-config.js.map +1 -1
  230. package/dist/reasoning/login.js +1 -1
  231. package/dist/reasoning/login.js.map +1 -1
  232. package/dist/resolution/c-fnptr-synthesizer.d.ts +2 -29
  233. package/dist/resolution/c-fnptr-synthesizer.d.ts.map +1 -1
  234. package/dist/resolution/c-fnptr-synthesizer.js +866 -148
  235. package/dist/resolution/c-fnptr-synthesizer.js.map +1 -1
  236. package/dist/resolution/callback-synthesizer.d.ts +9 -1
  237. package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
  238. package/dist/resolution/callback-synthesizer.js +1232 -183
  239. package/dist/resolution/callback-synthesizer.js.map +1 -1
  240. package/dist/resolution/cooperative-yield.d.ts +32 -0
  241. package/dist/resolution/cooperative-yield.d.ts.map +1 -0
  242. package/dist/resolution/cooperative-yield.js +42 -0
  243. package/dist/resolution/cooperative-yield.js.map +1 -0
  244. package/dist/resolution/frameworks/cics.d.ts +20 -0
  245. package/dist/resolution/frameworks/cics.d.ts.map +1 -0
  246. package/dist/resolution/frameworks/cics.js +90 -0
  247. package/dist/resolution/frameworks/cics.js.map +1 -0
  248. package/dist/resolution/frameworks/index.d.ts.map +1 -1
  249. package/dist/resolution/frameworks/index.js +3 -0
  250. package/dist/resolution/frameworks/index.js.map +1 -1
  251. package/dist/resolution/frameworks/java.d.ts.map +1 -1
  252. package/dist/resolution/frameworks/java.js +14 -6
  253. package/dist/resolution/frameworks/java.js.map +1 -1
  254. package/dist/resolution/frameworks/terraform.d.ts +38 -0
  255. package/dist/resolution/frameworks/terraform.d.ts.map +1 -0
  256. package/dist/resolution/frameworks/terraform.js +277 -0
  257. package/dist/resolution/frameworks/terraform.js.map +1 -0
  258. package/dist/resolution/goframe-synthesizer.d.ts +2 -1
  259. package/dist/resolution/goframe-synthesizer.d.ts.map +1 -1
  260. package/dist/resolution/goframe-synthesizer.js +8 -3
  261. package/dist/resolution/goframe-synthesizer.js.map +1 -1
  262. package/dist/resolution/import-resolver.d.ts +7 -0
  263. package/dist/resolution/import-resolver.d.ts.map +1 -1
  264. package/dist/resolution/import-resolver.js +129 -4
  265. package/dist/resolution/import-resolver.js.map +1 -1
  266. package/dist/resolution/index.d.ts +65 -3
  267. package/dist/resolution/index.d.ts.map +1 -1
  268. package/dist/resolution/index.js +477 -59
  269. package/dist/resolution/index.js.map +1 -1
  270. package/dist/resolution/name-matcher.d.ts +22 -3
  271. package/dist/resolution/name-matcher.d.ts.map +1 -1
  272. package/dist/resolution/name-matcher.js +657 -39
  273. package/dist/resolution/name-matcher.js.map +1 -1
  274. package/dist/resolution/strip-comments.d.ts +1 -1
  275. package/dist/resolution/strip-comments.d.ts.map +1 -1
  276. package/dist/resolution/strip-comments.js +49 -0
  277. package/dist/resolution/strip-comments.js.map +1 -1
  278. package/dist/resolution/types.d.ts +29 -0
  279. package/dist/resolution/types.d.ts.map +1 -1
  280. package/dist/resolution/workspace-packages.d.ts +10 -0
  281. package/dist/resolution/workspace-packages.d.ts.map +1 -1
  282. package/dist/resolution/workspace-packages.js +142 -4
  283. package/dist/resolution/workspace-packages.js.map +1 -1
  284. package/dist/search/identifier-segments.d.ts +60 -0
  285. package/dist/search/identifier-segments.d.ts.map +1 -0
  286. package/dist/search/identifier-segments.js +176 -0
  287. package/dist/search/identifier-segments.js.map +1 -0
  288. package/dist/search/query-utils.d.ts +201 -0
  289. package/dist/search/query-utils.d.ts.map +1 -1
  290. package/dist/search/query-utils.js +919 -2
  291. package/dist/search/query-utils.js.map +1 -1
  292. package/dist/spec/config.d.ts +7 -11
  293. package/dist/spec/config.d.ts.map +1 -1
  294. package/dist/spec/config.js +77 -48
  295. package/dist/spec/config.js.map +1 -1
  296. package/dist/spec/db/fragment-node.d.ts +1 -0
  297. package/dist/spec/db/fragment-node.d.ts.map +1 -1
  298. package/dist/spec/db/fragment-node.js +8 -0
  299. package/dist/spec/db/fragment-node.js.map +1 -1
  300. package/dist/spec/db/fts.d.ts +14 -0
  301. package/dist/spec/db/fts.d.ts.map +1 -1
  302. package/dist/spec/db/fts.js +43 -4
  303. package/dist/spec/db/fts.js.map +1 -1
  304. package/dist/spec/db/schema.d.ts +6 -3
  305. package/dist/spec/db/schema.d.ts.map +1 -1
  306. package/dist/spec/db/schema.js +36 -4
  307. package/dist/spec/db/schema.js.map +1 -1
  308. package/dist/spec/db/schema.sql +11 -1
  309. package/dist/spec/evolve/logic-checker.d.ts +2 -2
  310. package/dist/spec/evolve/logic-checker.d.ts.map +1 -1
  311. package/dist/spec/evolve/logic-checker.js +3 -27
  312. package/dist/spec/evolve/logic-checker.js.map +1 -1
  313. package/dist/spec/evolve/pipeline.d.ts +21 -19
  314. package/dist/spec/evolve/pipeline.d.ts.map +1 -1
  315. package/dist/spec/evolve/pipeline.js +284 -31
  316. package/dist/spec/evolve/pipeline.js.map +1 -1
  317. package/dist/spec/evolve/spec-rewriter.d.ts +2 -2
  318. package/dist/spec/evolve/spec-rewriter.d.ts.map +1 -1
  319. package/dist/spec/evolve/spec-rewriter.js +7 -31
  320. package/dist/spec/evolve/spec-rewriter.js.map +1 -1
  321. package/dist/spec/graph/queries.d.ts +97 -0
  322. package/dist/spec/graph/queries.d.ts.map +1 -1
  323. package/dist/spec/graph/queries.js +225 -0
  324. package/dist/spec/graph/queries.js.map +1 -1
  325. package/dist/spec/llm/client.d.ts +29 -0
  326. package/dist/spec/llm/client.d.ts.map +1 -0
  327. package/dist/spec/llm/client.js +123 -0
  328. package/dist/spec/llm/client.js.map +1 -0
  329. package/dist/spec/llm/index.d.ts +3 -0
  330. package/dist/spec/llm/index.d.ts.map +1 -0
  331. package/dist/spec/llm/index.js +11 -0
  332. package/dist/spec/llm/index.js.map +1 -0
  333. package/dist/spec/llm/prompts.d.ts +13 -0
  334. package/dist/spec/llm/prompts.d.ts.map +1 -0
  335. package/dist/spec/llm/prompts.js +75 -0
  336. package/dist/spec/llm/prompts.js.map +1 -0
  337. package/dist/spec/mining/git-scanner.d.ts +12 -0
  338. package/dist/spec/mining/git-scanner.d.ts.map +1 -1
  339. package/dist/spec/mining/git-scanner.js +41 -0
  340. package/dist/spec/mining/git-scanner.js.map +1 -1
  341. package/dist/spec/mining/pipeline.d.ts.map +1 -1
  342. package/dist/spec/mining/pipeline.js +14 -1
  343. package/dist/spec/mining/pipeline.js.map +1 -1
  344. package/dist/spec/utils.d.ts +2 -1
  345. package/dist/spec/utils.d.ts.map +1 -1
  346. package/dist/spec/utils.js +3 -1
  347. package/dist/spec/utils.js.map +1 -1
  348. package/dist/sync/git-hooks.d.ts.map +1 -1
  349. package/dist/sync/git-hooks.js +2 -0
  350. package/dist/sync/git-hooks.js.map +1 -1
  351. package/dist/sync/watcher.d.ts +10 -5
  352. package/dist/sync/watcher.d.ts.map +1 -1
  353. package/dist/sync/watcher.js +51 -14
  354. package/dist/sync/watcher.js.map +1 -1
  355. package/dist/sync/worktree.d.ts +9 -0
  356. package/dist/sync/worktree.d.ts.map +1 -1
  357. package/dist/sync/worktree.js +45 -0
  358. package/dist/sync/worktree.js.map +1 -1
  359. package/dist/types.d.ts +25 -2
  360. package/dist/types.d.ts.map +1 -1
  361. package/dist/types.js +10 -0
  362. package/dist/types.js.map +1 -1
  363. package/dist/ui/shimmer-progress.d.ts +2 -0
  364. package/dist/ui/shimmer-progress.d.ts.map +1 -1
  365. package/dist/ui/shimmer-progress.js +19 -2
  366. package/dist/ui/shimmer-progress.js.map +1 -1
  367. package/dist/upgrade/index.d.ts +32 -0
  368. package/dist/upgrade/index.d.ts.map +1 -1
  369. package/dist/upgrade/index.js +163 -15
  370. package/dist/upgrade/index.js.map +1 -1
  371. package/dist/upgrade/remove-binary.d.ts +87 -0
  372. package/dist/upgrade/remove-binary.d.ts.map +1 -0
  373. package/dist/upgrade/remove-binary.js +289 -0
  374. package/dist/upgrade/remove-binary.js.map +1 -0
  375. package/dist/upgrade/update-check.d.ts +92 -0
  376. package/dist/upgrade/update-check.d.ts.map +1 -0
  377. package/dist/upgrade/update-check.js +258 -0
  378. package/dist/upgrade/update-check.js.map +1 -0
  379. package/package.json +4 -4
  380. package/scripts/agent-eval/repro-concurrent-explore.mjs +119 -0
  381. package/scripts/agent-eval/repro-daemon-clients.mjs +125 -0
  382. package/scripts/agent-eval/run-all.sh +6 -0
  383. package/scripts/build-bundle.sh +5 -0
  384. package/scripts/exp_boundary_eval/README.md +247 -0
  385. package/scripts/exp_boundary_eval/_test_mcp_chain.py +78 -0
  386. package/scripts/exp_boundary_eval/_test_stdin.py +8 -0
  387. package/scripts/exp_boundary_eval/_utils.py +1116 -0
  388. package/scripts/exp_boundary_eval/analyze.py +1313 -0
  389. package/scripts/exp_boundary_eval/deveco_arm.py +519 -0
  390. package/scripts/exp_boundary_eval/run_all.py +378 -0
  391. package/scripts/exp_boundary_eval/run_one.py +165 -0
  392. package/scripts/exp_boundary_eval/run_session.py +158 -0
  393. package/scripts/exp_boundary_eval/setup.py +120 -0
  394. package/scripts/exp_boundary_eval/win_mcp_launcher.py +73 -0
  395. package/scripts/exp_boundary_eval/win_mcp_stdio_wrap.js +36 -0
  396. package/scripts/exp_boundary_eval/win_node_launcher.py +24 -0
  397. package/scripts/npm-shim.js +32 -3
  398. package/scripts/ohos-sdk-publish.mjs +133 -0
  399. package/scripts/qa_eval/README.md +0 -407
  400. package/scripts/qa_eval/_test_deveco_probe.py +0 -41
  401. package/scripts/qa_eval/agent_runner.py +0 -526
  402. package/scripts/qa_eval/data/.gitignore +0 -4
  403. package/scripts/qa_eval/data/test-set.jsonl +0 -2
  404. package/scripts/qa_eval/eval_metrics.py +0 -274
  405. package/scripts/qa_eval/external_agent.py +0 -976
  406. package/scripts/qa_eval/llm_config.py +0 -92
  407. package/scripts/qa_eval/memory_monitor.py +0 -132
  408. package/scripts/qa_eval/my_answer_accuracy.py +0 -187
  409. package/scripts/qa_eval/requirements.txt +0 -2
  410. package/scripts/qa_eval/run_pipeline.py +0 -804
  411. package/scripts/qa_eval/stats_efficiency.py +0 -279
  412. package/scripts/qa_eval/stats_scores.py +0 -207
package/dist/index.js CHANGED
@@ -49,6 +49,7 @@ const queries_1 = require("./db/queries");
49
49
  const directory_1 = require("./directory");
50
50
  const extraction_1 = require("./extraction");
51
51
  const context_1 = require("./extraction/context");
52
+ const arkts_1 = require("./extraction/languages/arkts");
52
53
  const resolution_1 = require("./resolution");
53
54
  const graph_1 = require("./graph");
54
55
  const context_2 = require("./context");
@@ -57,6 +58,8 @@ const sync_1 = require("./sync");
57
58
  const extraction_version_1 = require("./extraction/extraction-version");
58
59
  const directory_2 = require("./directory");
59
60
  const query_utils_1 = require("./search/query-utils");
61
+ const identifier_segments_1 = require("./search/identifier-segments");
62
+ const cooperative_yield_1 = require("./resolution/cooperative-yield");
60
63
  const version_1 = require("./mcp/version");
61
64
  // Re-export types for consumers
62
65
  __exportStar(require("./types"), exports);
@@ -157,6 +160,10 @@ class HomeGraph {
157
160
  this.graphManager = new graph_1.GraphQueryManager(this.queries);
158
161
  this.traverser = new graph_1.GraphTraverser(this.queries);
159
162
  this.contextBuilder = (0, context_2.createContextBuilder)(this.projectRoot, this.queries, this.traverser);
163
+ (0, arkts_1.restoreOhosApiDbAttach)(this.queries);
164
+ if (!this.queries.getOhosApiDbPath()) {
165
+ (0, arkts_1.bindOhosApiDbForProject)(this.projectRoot, this.queries);
166
+ }
160
167
  }
161
168
  /**
162
169
  * Heal a stale database handle in place. If `.homegraph/` was removed and
@@ -271,6 +278,48 @@ class HomeGraph {
271
278
  }
272
279
  return instance;
273
280
  }
281
+ /**
282
+ * Rebuild the project's database from scratch and return a fresh, empty
283
+ * instance — the "same result as a fresh init" semantics that `codegraph
284
+ * index` documents.
285
+ *
286
+ * Unlike `open()` followed by `clear()`, this DISCARDS the existing
287
+ * `.codegraph/codegraph.db` (and its `-wal`/`-shm` sidecars) before
288
+ * re-initializing, instead of opening the old database and DELETE-ing every
289
+ * row. On a large or pre-fix poisoned index — e.g. an old graph that scanned
290
+ * an ignored gitlink corpus (#1065) into ~1.6M nodes with a multi-GB WAL —
291
+ * the per-row `nodes_fts` delete-trigger churn blocks the main thread long
292
+ * enough to trip the #850 liveness watchdog before indexing even starts, so a
293
+ * full re-index could never recover the bad state (#1067). Discarding the
294
+ * files is O(1) regardless of size, reclaims the disk, and sidesteps opening
295
+ * (and running migrations against) the poisoned database entirely.
296
+ */
297
+ static async recreate(projectRoot) {
298
+ await (0, extraction_1.initGrammars)();
299
+ const resolvedRoot = path.resolve(projectRoot);
300
+ // Check if initialized — recreate REBUILDS an existing project; it is not a
301
+ // first-time `init`.
302
+ if (!(0, directory_1.isInitialized)(resolvedRoot)) {
303
+ throw new Error(`HomeGraph not initialized in ${resolvedRoot}. Run init() first.`);
304
+ }
305
+ const dbPath = (0, db_1.getDatabasePath)(resolvedRoot);
306
+ try {
307
+ (0, db_1.removeDatabaseFiles)(dbPath);
308
+ }
309
+ catch (err) {
310
+ // POSIX unlinks an open file fine; this fires mainly on Windows when a
311
+ // live daemon/MCP server still holds the database. Turn the raw EBUSY into
312
+ // an actionable instruction instead of a generic failure.
313
+ const reason = err instanceof Error ? err.message : String(err);
314
+ throw new Error(`Could not rebuild the index — the database file is in use (${reason}). ` +
315
+ `Stop any running HomeGraph MCP server/daemon for this project and retry, ` +
316
+ `or remove the ${(0, directory_2.getHomeGraphDir)(resolvedRoot)} directory and run "homegraph init".`);
317
+ }
318
+ // Re-create an empty, freshly-schema'd database at the same path.
319
+ const db = db_1.DatabaseConnection.initialize(dbPath);
320
+ const queries = new queries_1.QueryBuilder(db.getDb());
321
+ return new HomeGraph(db, queries, resolvedRoot);
322
+ }
274
323
  /**
275
324
  * Open synchronously (without sync)
276
325
  */
@@ -330,6 +379,17 @@ class HomeGraph {
330
379
  }
331
380
  try {
332
381
  const before = this.queries.getNodeAndEdgeCount();
382
+ // Mark the index as in-flight BEFORE any writes: a run killed mid-index
383
+ // leaves this marker behind so `homegraph status` can tell a truncated
384
+ // index from a completed one.
385
+ try {
386
+ this.queries.setMetadata('index_state', 'indexing');
387
+ }
388
+ catch { /* metadata is advisory */ }
389
+ try {
390
+ this.queries.clearNameSegmentVocab();
391
+ }
392
+ catch { /* vocab is advisory — never fail an index over it */ }
333
393
  const result = await this.orchestrator.indexAll(options.onProgress, options.signal, options.verbose);
334
394
  // Re-detect frameworks now that the index is populated. The resolver
335
395
  // is constructed with createResolver() before any files exist, so
@@ -364,10 +424,10 @@ class HomeGraph {
364
424
  // receiver conforms to (protocol-extension / inherited / default-
365
425
  // interface). Needs the implements/extends edges the main pass just
366
426
  // built, so it runs after resolution (#750).
367
- this.resolver.resolveChainedCallsViaConformance();
427
+ await this.resolver.resolveChainedCallsViaConformance();
368
428
  // Same lifecycle for `this.<member>` callback registrations whose
369
429
  // member is inherited from a supertype (#808).
370
- this.resolver.resolveDeferredThisMemberRefs();
430
+ await this.resolver.resolveDeferredThisMemberRefs();
371
431
  }
372
432
  // Refresh planner stats + checkpoint the WAL after bulk writes.
373
433
  // Cheap and non-blocking; never load-bearing for correctness.
@@ -393,7 +453,43 @@ class HomeGraph {
393
453
  this.queries.setMetadata('indexed_with_extraction_version', String(extraction_version_1.EXTRACTION_VERSION));
394
454
  }
395
455
  catch { /* metadata is advisory — never fail an index over it */ }
456
+ const languages = Object.entries(this.getStats().filesByLanguage)
457
+ .filter(([, count]) => count > 0)
458
+ .map(([lang]) => lang);
459
+ const ohosBinding = (0, arkts_1.bindOhosApiDbForProject)(this.projectRoot, this.queries, languages);
460
+ if (ohosBinding && 'code' in ohosBinding) {
461
+ result.errors.push({ message: ohosBinding.message, severity: 'warning', code: ohosBinding.code });
462
+ }
396
463
  }
464
+ // Reconcile the scan's ground truth against what the pipeline accounted for.
465
+ try {
466
+ if (!result.success) {
467
+ this.queries.setMetadata('index_state', 'failed');
468
+ }
469
+ else {
470
+ const accounted = result.filesIndexed + result.filesSkipped + result.filesErrored;
471
+ const discovered = result.filesDiscovered;
472
+ const shortfall = discovered !== undefined ? discovered - accounted : 0;
473
+ if (discovered !== undefined && shortfall > 0) {
474
+ this.queries.setMetadata('index_state', 'partial');
475
+ this.queries.setMetadata('index_files_discovered', String(discovered));
476
+ this.queries.setMetadata('index_files_accounted', String(accounted));
477
+ result.errors.push({
478
+ message: `Index is missing ${shortfall} of ${discovered} discovered files (indexed ${result.filesIndexed}, skipped ${result.filesSkipped}, errored ${result.filesErrored}). The index is PARTIAL — re-run \`homegraph index\`.`,
479
+ severity: 'warning',
480
+ code: 'index_partial',
481
+ });
482
+ }
483
+ else {
484
+ this.queries.setMetadata('index_state', 'complete');
485
+ if (discovered !== undefined) {
486
+ this.queries.setMetadata('index_files_discovered', String(discovered));
487
+ this.queries.setMetadata('index_files_accounted', String(accounted));
488
+ }
489
+ }
490
+ }
491
+ }
492
+ catch { /* metadata is advisory — never fail an index over it */ }
397
493
  return result;
398
494
  }
399
495
  finally {
@@ -436,6 +532,18 @@ class HomeGraph {
436
532
  return { filesChecked: 0, filesAdded: 0, filesModified: 0, filesRemoved: 0, nodesUpdated: 0, durationMs: 0 };
437
533
  }
438
534
  try {
535
+ // Captured BEFORE the sync runs: the sync's own incremental writes
536
+ // populate vocab rows for the files it touches, so an end-of-sync
537
+ // emptiness check would see "non-empty" and skip the backfill forever,
538
+ // leaving every unchanged file's names unsegmented.
539
+ const vocabWasEmpty = (() => {
540
+ try {
541
+ return this.queries.isNameSegmentVocabEmpty();
542
+ }
543
+ catch {
544
+ return false;
545
+ }
546
+ })();
439
547
  const result = await this.orchestrator.sync(options.onProgress);
440
548
  // Cross-file finalization (e.g. NestJS RouterModule prefixes). Run on
441
549
  // every sync that touched files so edits to `app.module.ts` propagate
@@ -444,11 +552,25 @@ class HomeGraph {
444
552
  if (result.filesAdded > 0 || result.filesModified > 0) {
445
553
  this.resolver.runPostExtract();
446
554
  }
555
+ else if (result.filesRemoved > 0) {
556
+ // A pure-removal sync still resolves refs below — the deletion path
557
+ // resurrects the removed file's incoming edges as pending refs
558
+ // (#1240 removal case) and the orphan sweep consumes them. In a
559
+ // long-lived process (daemon) the resolver's name caches were
560
+ // warmed against the pre-removal graph; drop them so resolution
561
+ // sees the post-removal state. (runPostExtract above clears caches
562
+ // itself, so the changed-files branch is already covered.)
563
+ this.resolver.clearCaches();
564
+ }
447
565
  // Resolve references if files were updated
448
- if (result.filesAdded > 0 || result.filesModified > 0) {
566
+ const filesChanged = result.filesAdded > 0 || result.filesModified > 0;
567
+ if (filesChanged) {
449
568
  if (result.changedFilePaths) {
450
569
  // Scope resolution to changed files (git fast path — bounded set)
570
+ const tRefLoad = Date.now();
451
571
  const unresolvedRefs = this.queries.getUnresolvedReferencesByFiles(result.changedFilePaths);
572
+ if (process.env.HOMEGRAPH_SYNTH_TIMINGS)
573
+ console.error(`[phase-timing] sync-ref-load: ${Date.now() - tRefLoad}ms (${unresolvedRefs.length} refs)`);
452
574
  options.onProgress?.({
453
575
  phase: 'resolving',
454
576
  current: 0,
@@ -461,6 +583,32 @@ class HomeGraph {
461
583
  total,
462
584
  });
463
585
  });
586
+ // Retry previously-failed refs the changed files may now satisfy
587
+ // (#1240). Scoped resolution above only re-resolves refs FROM the
588
+ // changed files — but when a changed file gains an export/symbol,
589
+ // refs in UNCHANGED files that failed against the old graph can
590
+ // now resolve, and nothing else ever revisits them (their rows
591
+ // were parked as status='failed' by an earlier completed pass).
592
+ // Look them up by the symbol names the changed files now carry
593
+ // and re-resolve just that set. On a sync where no failed ref
594
+ // matches, this is one indexed lookup.
595
+ const tRetry = Date.now();
596
+ const retryable = this.queries.getRetryableFailedReferences(this.queries.getNodeNamesByFiles(result.changedFilePaths));
597
+ if (retryable.length > 0) {
598
+ options.onProgress?.({
599
+ phase: 'resolving',
600
+ current: 0,
601
+ total: retryable.length,
602
+ });
603
+ await this.resolver.resolveAndPersistListYielding(retryable);
604
+ options.onProgress?.({
605
+ phase: 'resolving',
606
+ current: retryable.length,
607
+ total: retryable.length,
608
+ });
609
+ }
610
+ if (process.env.HOMEGRAPH_SYNTH_TIMINGS)
611
+ console.error(`[phase-timing] sync-failed-ref-retry: ${Date.now() - tRetry}ms (${retryable.length} refs)`);
464
612
  }
465
613
  else {
466
614
  // No git info — use batched resolution to avoid OOM
@@ -476,20 +624,75 @@ class HomeGraph {
476
624
  current,
477
625
  total,
478
626
  });
627
+ }, (done, totalPasses) => {
628
+ options.onProgress?.({
629
+ phase: 'linking',
630
+ current: done,
631
+ total: totalPasses,
632
+ });
479
633
  });
480
634
  }
635
+ }
636
+ // Orphan sweep (#1187). A resolution pass that dies mid-run — the #850
637
+ // daemon liveness watchdog's SIGKILL (#1122), Ctrl-C, a crash — leaves
638
+ // the refs it never reached in unresolved_refs, and the git-scoped fast
639
+ // path above never revisits them (it reads only the changed files'
640
+ // rows). Those files' call edges were then missing PERMANENTLY, with
641
+ // nothing to see except a too-small blast radius, until a full
642
+ // re-index. A completed pass takes every row it processed out of the
643
+ // PENDING set (resolved rows are deleted, unresolvable ones parked as
644
+ // status='failed' for the #1240 retry above), so any pending row now
645
+ // is such an orphan — or a row from an older engine's scoped pass.
646
+ // Grind them down with the batched resolver; this also makes a bare
647
+ // `homegraph sync` the recovery command for a wedged index. On a
648
+ // healthy index this is one COUNT query.
649
+ const orphanCount = this.queries.getUnresolvedReferencesCount();
650
+ if (orphanCount > 0) {
651
+ options.onProgress?.({
652
+ phase: 'resolving',
653
+ current: 0,
654
+ total: orphanCount,
655
+ });
656
+ await this.resolveReferencesBatched((current, total) => {
657
+ options.onProgress?.({
658
+ phase: 'resolving',
659
+ current,
660
+ total,
661
+ });
662
+ }, (done, totalPasses) => {
663
+ options.onProgress?.({
664
+ phase: 'linking',
665
+ current: done,
666
+ total: totalPasses,
667
+ });
668
+ });
669
+ }
670
+ if (filesChanged || orphanCount > 0) {
481
671
  // Second pass: chained calls whose method lives on a supertype the
482
672
  // receiver conforms to (protocol-extension / inherited). Needs the
483
673
  // implements/extends edges built above (#750).
484
- this.resolver.resolveChainedCallsViaConformance();
674
+ await this.resolver.resolveChainedCallsViaConformance();
485
675
  // Same lifecycle for `this.<member>` callback registrations whose
486
676
  // member is inherited from a supertype (#808).
487
- this.resolver.resolveDeferredThisMemberRefs();
677
+ await this.resolver.resolveDeferredThisMemberRefs();
488
678
  }
489
679
  // Refresh planner stats + checkpoint the WAL after bulk writes.
490
- if (result.filesAdded > 0 || result.filesModified > 0 || result.filesRemoved > 0) {
491
- this.db.runMaintenance();
680
+ // Off-thread — see indexAll's call site.
681
+ if (filesChanged || result.filesRemoved > 0 || orphanCount > 0) {
682
+ await this.db.runMaintenance();
683
+ }
684
+ // Heal the segment vocabulary on indexes built before the table
685
+ // existed (upgrade path): incremental writes above only cover changed
686
+ // files, so a vocab that was empty when this sync STARTED means the
687
+ // bulk was never segmented — backfill it (INSERT OR IGNORE, so the
688
+ // rows the sync just wrote are fine). Batched + yielding — sync can
689
+ // run on the daemon's liveness-watchdog thread (#850/#1091).
690
+ try {
691
+ if (vocabWasEmpty && this.queries.getNodeAndEdgeCount().nodes > 0) {
692
+ await this.rebuildNameSegmentVocab();
693
+ }
492
694
  }
695
+ catch { /* vocab is advisory — never fail a sync over it */ }
493
696
  return result;
494
697
  }
495
698
  finally {
@@ -600,6 +803,24 @@ class HomeGraph {
600
803
  getLastIndexedAt() {
601
804
  return this.queries.getLastIndexedAt();
602
805
  }
806
+ /**
807
+ * Access the underlying query layer. Used by the MCP query-cache layer.
808
+ */
809
+ getQueryBuilder() {
810
+ return this.queries;
811
+ }
812
+ /**
813
+ * Completeness of the last full index run. `'complete'` is the only good
814
+ * state. `'indexing'` after the fact means a run was killed mid-index;
815
+ * `'partial'` means the run finished but silently dropped files;
816
+ * `'failed'` means it reported failure. `null` = index predates this marker.
817
+ */
818
+ getIndexState() {
819
+ const raw = this.queries.getMetadata('index_state');
820
+ return raw === 'indexing' || raw === 'complete' || raw === 'partial' || raw === 'failed'
821
+ ? raw
822
+ : null;
823
+ }
603
824
  /**
604
825
  * Which engine built the current index: the package version + extraction
605
826
  * version stamped at the last full `indexAll`. Either field is null for an
@@ -612,6 +833,19 @@ class HomeGraph {
612
833
  const parsed = ev != null ? parseInt(ev, 10) : NaN;
613
834
  return { version, extractionVersion: Number.isFinite(parsed) ? parsed : null };
614
835
  }
836
+ /** Bound OHOS API db for this project, if any. */
837
+ getOhosApiBinding() {
838
+ const version = this.queries.getMetadata(arkts_1.OHOS_API_VERSION_META);
839
+ const dbPath = this.queries.getMetadata(arkts_1.OHOS_API_DB_PATH_META);
840
+ if (!version || !dbPath)
841
+ return null;
842
+ return {
843
+ version,
844
+ dbPath,
845
+ packageName: (0, arkts_1.ohosApiDbPackageName)(version),
846
+ installed: false,
847
+ };
848
+ }
615
849
  /**
616
850
  * True when the on-disk index was built by an engine whose extraction is
617
851
  * older than the one now running — i.e. a re-index would add data a migration
@@ -652,12 +886,22 @@ class HomeGraph {
652
886
  * Resolve references in batches to keep memory bounded on large codebases.
653
887
  * Processes chunks of unresolved refs, persisting results after each batch.
654
888
  */
655
- async resolveReferencesBatched(onProgress) {
656
- return this.resolver.resolveAndPersistBatched(onProgress);
889
+ async resolveReferencesBatched(onProgress, onSynthesisProgress) {
890
+ return this.resolver.resolveAndPersistBatched(onProgress, undefined, onSynthesisProgress);
657
891
  }
658
892
  /**
659
893
  * Get detected frameworks in the project
660
894
  */
895
+ /**
896
+ * References extracted but never attempted by a resolution pass. Zero on a
897
+ * healthy index — a completed pass consumes every pending row (resolving it
898
+ * or parking it as failed, #1240). Non-zero at rest means a pass was
899
+ * interrupted mid-run (#1187), so some files' call edges are missing; the
900
+ * next `sync` sweeps them.
901
+ */
902
+ getPendingReferenceCount() {
903
+ return this.queries.getUnresolvedReferencesCount();
904
+ }
661
905
  getDetectedFrameworks() {
662
906
  return this.resolver.getDetectedFrameworks();
663
907
  }
@@ -737,6 +981,178 @@ class HomeGraph {
737
981
  * bias, which would otherwise pull overloaded tokens toward whichever stack
738
982
  * embeds the project name.
739
983
  */
984
+ /**
985
+ * Graph-derived prompt matching for the front-load hook's MEDIUM tier:
986
+ * which indexed symbols do these prose words name? "state machine des
987
+ * commandes" → `OrderStateMachine`, in any human language whose technical
988
+ * nouns are Latin script — no keyword list involved.
989
+ *
990
+ * Precision comes from the repo's own naming statistics, not vocabulary:
991
+ * - CO-OCCURRENCE: ≥2 words that are segments of the SAME name ("state" +
992
+ * "machine" → OrderStateMachine) is strong evidence and always qualifies.
993
+ * - RARITY: a single matched word qualifies only when its segment is
994
+ * discriminative here (≤ {@link SEGMENT_RARITY_CEILING} distinct names) —
995
+ * "checkout" in a shop backend yes, "state" in a react app no.
996
+ * Every candidate is re-verified against `nodes` before being returned
997
+ * (vocab rows are proposals; deletions leave orphans by design), so a
998
+ * returned symbol is guaranteed to exist right now.
999
+ */
1000
+ getSegmentMatches(words, limit = 6) {
1001
+ if (words.length === 0)
1002
+ return [];
1003
+ // Variant → original word (plural folding), for coverage accounting.
1004
+ const variantToWord = new Map();
1005
+ for (const word of words) {
1006
+ for (const variant of (0, identifier_segments_1.segmentLookupVariants)(word)) {
1007
+ if (!variantToWord.has(variant))
1008
+ variantToWord.set(variant, word);
1009
+ }
1010
+ }
1011
+ const variants = [...variantToWord.keys()];
1012
+ // Tier A: co-occurrence. The SQL folds variants back to their original
1013
+ // word (#1146), so minWords=2 means two distinct PROMPT WORDS — a name
1014
+ // matching both `service` and `services` can't tie with (or crowd past
1015
+ // the LIMIT) a genuine two-word match. The JS re-check below recomputes
1016
+ // the fold from live segments as the honesty layer.
1017
+ const variantPairs = [...variantToWord.entries()].map(([segment, word]) => ({ segment, word }));
1018
+ const candidates = [];
1019
+ for (const hit of this.queries.getSegmentCoOccurrence(variantPairs, 2, 24)) {
1020
+ const matched = this.wordsMatchingName(hit.name, variantToWord);
1021
+ if (matched.size >= 2)
1022
+ candidates.push({ name: hit.name, matchedWords: matched });
1023
+ }
1024
+ // Tier B: single rare word. Only when co-occurrence found nothing — a
1025
+ // co-occurring name is categorically stronger evidence — and under
1026
+ // stricter rules, because one word is thin: the word must be ≥5 chars
1027
+ // (measured FPs: "this", "typo"); the segment must appear in AT LEAST TWO
1028
+ // names (a concept the codebase is about clusters across names —
1029
+ // CheckoutService/CheckoutController — while a prose coincidence is a
1030
+ // singleton: measured FP "deploy to PRODUCTION" → the one name
1031
+ // matchesNonProductionDir); and the candidate name must have ≥2 segments
1032
+ // (a bare common verb matching a bare function name — "write" → `write` —
1033
+ // is prose coincidence, not the user naming a symbol).
1034
+ if (candidates.length === 0) {
1035
+ const singleWordVariants = variants.filter((v) => variantToWord.get(v).length >= 5);
1036
+ const counts = this.queries.getSegmentNameCounts(singleWordVariants);
1037
+ const rare = [...counts.entries()]
1038
+ .filter(([, n]) => n >= 2 && n <= HomeGraph.SEGMENT_RARITY_CEILING)
1039
+ .sort((a, b) => a[1] - b[1])
1040
+ .slice(0, 2);
1041
+ for (const [variant] of rare) {
1042
+ const word = variantToWord.get(variant);
1043
+ for (const name of this.queries.getNamesForSegment(variant, 12)) {
1044
+ if ((0, identifier_segments_1.splitIdentifierSegments)(name).length < 2)
1045
+ continue;
1046
+ candidates.push({ name, matchedWords: new Set([word]) });
1047
+ }
1048
+ }
1049
+ }
1050
+ // Verify against nodes (the honesty gate) and pick a representative
1051
+ // definition per name. A name whose only nodes are file/import kind has
1052
+ // no real definition to point at — surfacing the import statement instead
1053
+ // reads as a matched symbol but isn't one (#1144) — so it's skipped, the
1054
+ // same way an orphaned vocab row is. (Import names no longer enter the
1055
+ // vocab at write time, but rows written before that exclusion persist
1056
+ // until the next full index.)
1057
+ const out = [];
1058
+ const seen = new Set();
1059
+ candidates.sort((a, b) => b.matchedWords.size - a.matchedWords.size || a.name.length - b.name.length);
1060
+ for (const candidate of candidates) {
1061
+ if (out.length >= limit)
1062
+ break;
1063
+ if (seen.has(candidate.name))
1064
+ continue;
1065
+ seen.add(candidate.name);
1066
+ const nodes = this.queries.getNodesByName(candidate.name);
1067
+ if (nodes.length === 0)
1068
+ continue; // orphaned vocab row — name no longer exists
1069
+ const rep = nodes.find((n) => n.kind !== 'file' && n.kind !== 'import');
1070
+ if (!rep)
1071
+ continue; // no real definition — don't surface an import/file as one
1072
+ out.push({
1073
+ name: candidate.name,
1074
+ kind: rep.kind,
1075
+ filePath: rep.filePath,
1076
+ startLine: rep.startLine ?? 0,
1077
+ matchedWords: [...candidate.matchedWords].sort(),
1078
+ });
1079
+ }
1080
+ return out;
1081
+ }
1082
+ /** A single word ("state") can match hundreds of names in a big repo — that
1083
+ * is noise, not signal. Ceiling for the single-word tier; co-occurrence is
1084
+ * exempt because two words on one name is already discriminative. */
1085
+ static SEGMENT_RARITY_CEILING = 25;
1086
+ /** Which of the prompt's original words match `name`'s segments (via
1087
+ * variants). Segments are recomputed in JS — a name-keyed vocab lookup
1088
+ * would scan the (segment, name) primary key. */
1089
+ wordsMatchingName(name, variantToWord) {
1090
+ const segments = new Set((0, identifier_segments_1.splitIdentifierSegments)(name));
1091
+ const matched = new Set();
1092
+ for (const [variant, word] of variantToWord) {
1093
+ if (segments.has(variant))
1094
+ matched.add(word);
1095
+ }
1096
+ return matched;
1097
+ }
1098
+ /**
1099
+ * One-shot upgrade heal for callers that open the graph WITHOUT syncing —
1100
+ * concretely the prompt hook, whose MEDIUM tier reads the segment
1101
+ * vocabulary: a database migrated from before the vocab table existed
1102
+ * starts with it empty, and the only other backfill lives inside `sync()`,
1103
+ * which such callers never run (#1142). Returns true when the vocab is
1104
+ * usable (already populated — the overwhelmingly common one-SELECT case —
1105
+ * or healed here); false when it isn't (empty graph, or another process
1106
+ * holds the index lock — that process's own sync heals it).
1107
+ */
1108
+ async healSegmentVocabIfEmpty() {
1109
+ const empty = (() => {
1110
+ try {
1111
+ return this.queries.isNameSegmentVocabEmpty();
1112
+ }
1113
+ catch {
1114
+ return false;
1115
+ }
1116
+ })();
1117
+ if (!empty)
1118
+ return true;
1119
+ if (this.queries.getNodeAndEdgeCount().nodes === 0)
1120
+ return false;
1121
+ return this.indexMutex.withLock(async () => {
1122
+ try {
1123
+ this.fileLock.acquire();
1124
+ }
1125
+ catch {
1126
+ return false; // an index/sync is running — it backfills the vocab itself
1127
+ }
1128
+ try {
1129
+ if (!this.queries.isNameSegmentVocabEmpty())
1130
+ return true; // raced: healed meanwhile
1131
+ await this.rebuildNameSegmentVocab();
1132
+ return true;
1133
+ }
1134
+ finally {
1135
+ this.fileLock.release();
1136
+ }
1137
+ });
1138
+ }
1139
+ /**
1140
+ * Rebuild the segment vocabulary from the current graph, batched and
1141
+ * yielding — the upgrade-heal path for indexes built before the vocab table
1142
+ * existed. Runs inside the index mutex/lock (sync and
1143
+ * healSegmentVocabIfEmpty hold them).
1144
+ */
1145
+ async rebuildNameSegmentVocab() {
1146
+ const maybeYield = (0, cooperative_yield_1.createYielder)();
1147
+ const BATCH = 2000;
1148
+ for (let offset = 0;; offset += BATCH) {
1149
+ const names = this.queries.getDistinctNodeNames(BATCH, offset);
1150
+ if (names.length === 0)
1151
+ break;
1152
+ this.queries.insertNameSegmentsBatch(names);
1153
+ await maybeYield();
1154
+ }
1155
+ }
740
1156
  getProjectNameTokens() {
741
1157
  return this.queries.getProjectNameTokens();
742
1158
  }
@@ -1018,6 +1434,7 @@ class HomeGraph {
1018
1434
  */
1019
1435
  clear() {
1020
1436
  this.queries.clear();
1437
+ (0, arkts_1.resetArkTSBatch)();
1021
1438
  }
1022
1439
  /**
1023
1440
  * Alias for close() for backwards compatibility.