homegraph 1.5.1 → 1.5.2

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 (258) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +305 -305
  3. package/dist/bin/homegraph.js +9 -9
  4. package/dist/db/index.js +36 -36
  5. package/dist/db/migrations.js +37 -37
  6. package/dist/db/queries.js +156 -156
  7. package/dist/db/schema.sql +203 -203
  8. package/dist/directory.js +5 -5
  9. package/dist/extraction/index.d.ts +1 -1
  10. package/dist/extraction/index.d.ts.map +1 -1
  11. package/dist/extraction/index.js +54 -43
  12. package/dist/extraction/index.js.map +1 -1
  13. package/dist/extraction/languages/arkts.d.ts +53 -6
  14. package/dist/extraction/languages/arkts.d.ts.map +1 -1
  15. package/dist/extraction/languages/arkts.js +565 -65
  16. package/dist/extraction/languages/arkts.js.map +1 -1
  17. package/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
  18. package/dist/extraction/wasm/tree-sitter-cfml.wasm +0 -0
  19. package/dist/extraction/wasm/tree-sitter-cfquery.wasm +0 -0
  20. package/dist/extraction/wasm/tree-sitter-cfscript.wasm +0 -0
  21. package/dist/extraction/wasm/tree-sitter-cobol.wasm +0 -0
  22. package/dist/extraction/wasm/tree-sitter-erlang.wasm +0 -0
  23. package/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
  24. package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  25. package/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +3 -2
  28. package/dist/index.js.map +1 -1
  29. package/dist/installer/instructions-template.js +9 -9
  30. package/dist/mcp/diff-impact.d.ts +131 -0
  31. package/dist/mcp/diff-impact.d.ts.map +1 -0
  32. package/dist/mcp/diff-impact.js +385 -0
  33. package/dist/mcp/diff-impact.js.map +1 -0
  34. package/dist/mcp/liveness-watchdog.js +51 -51
  35. package/dist/mcp/server-instructions.d.ts +1 -1
  36. package/dist/mcp/server-instructions.d.ts.map +1 -1
  37. package/dist/mcp/server-instructions.js +49 -47
  38. package/dist/mcp/server-instructions.js.map +1 -1
  39. package/dist/mcp/tools.d.ts +21 -5
  40. package/dist/mcp/tools.d.ts.map +1 -1
  41. package/dist/mcp/tools.js +305 -55
  42. package/dist/mcp/tools.js.map +1 -1
  43. package/dist/resolution/callback-synthesizer.d.ts +2 -1
  44. package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
  45. package/dist/resolution/callback-synthesizer.js +153 -53
  46. package/dist/resolution/callback-synthesizer.js.map +1 -1
  47. package/dist/resolution/frameworks/arkts-entry.d.ts.map +1 -1
  48. package/dist/resolution/frameworks/arkts-entry.js +20 -9
  49. package/dist/resolution/frameworks/arkts-entry.js.map +1 -1
  50. package/dist/resolution/index.d.ts.map +1 -1
  51. package/dist/resolution/index.js +1 -1
  52. package/dist/resolution/index.js.map +1 -1
  53. package/dist/resolution/memory-budget.d.ts +33 -0
  54. package/dist/resolution/memory-budget.d.ts.map +1 -1
  55. package/dist/resolution/memory-budget.js +58 -0
  56. package/dist/resolution/memory-budget.js.map +1 -1
  57. package/dist/resolution/resolver-pool.d.ts +2 -0
  58. package/dist/resolution/resolver-pool.d.ts.map +1 -1
  59. package/dist/resolution/resolver-pool.js +4 -0
  60. package/dist/resolution/resolver-pool.js.map +1 -1
  61. package/dist/spec/db/commit-node.js +4 -4
  62. package/dist/spec/db/fragment-node.js +10 -10
  63. package/dist/spec/db/fts.js +8 -8
  64. package/dist/spec/db/relations.js +88 -88
  65. package/dist/spec/db/schema.js +6 -6
  66. package/dist/spec/db/schema.sql +121 -121
  67. package/dist/spec/db/spec-node.js +4 -4
  68. package/dist/spec/llm/prompts.js +53 -53
  69. package/dist/ui/shimmer-progress.d.ts.map +1 -1
  70. package/dist/ui/shimmer-progress.js +4 -1
  71. package/dist/ui/shimmer-progress.js.map +1 -1
  72. package/package.json +61 -62
  73. package/dist/extraction/languages/arkts-viewtree.d.ts +0 -22
  74. package/dist/extraction/languages/arkts-viewtree.d.ts.map +0 -1
  75. package/dist/extraction/languages/arkts-viewtree.js +0 -133
  76. package/dist/extraction/languages/arkts-viewtree.js.map +0 -1
  77. package/dist/reasoning/config.d.ts +0 -45
  78. package/dist/reasoning/config.d.ts.map +0 -1
  79. package/dist/reasoning/config.js +0 -171
  80. package/dist/reasoning/config.js.map +0 -1
  81. package/dist/reasoning/credentials.d.ts +0 -5
  82. package/dist/reasoning/credentials.d.ts.map +0 -1
  83. package/dist/reasoning/credentials.js +0 -83
  84. package/dist/reasoning/credentials.js.map +0 -1
  85. package/dist/reasoning/login.d.ts +0 -21
  86. package/dist/reasoning/login.d.ts.map +0 -1
  87. package/dist/reasoning/login.js +0 -85
  88. package/dist/reasoning/login.js.map +0 -1
  89. package/dist/reasoning/reasoner.d.ts +0 -43
  90. package/dist/reasoning/reasoner.d.ts.map +0 -1
  91. package/dist/reasoning/reasoner.js +0 -308
  92. package/dist/reasoning/reasoner.js.map +0 -1
  93. package/dist/spec/evolve/llm-client.d.ts +0 -50
  94. package/dist/spec/evolve/llm-client.d.ts.map +0 -1
  95. package/dist/spec/evolve/llm-client.js +0 -176
  96. package/dist/spec/evolve/llm-client.js.map +0 -1
  97. package/dist/spec/evolve/logic-checker.d.ts +0 -12
  98. package/dist/spec/evolve/logic-checker.d.ts.map +0 -1
  99. package/dist/spec/evolve/logic-checker.js +0 -24
  100. package/dist/spec/evolve/logic-checker.js.map +0 -1
  101. package/dist/spec/llm/index.d.ts +0 -3
  102. package/dist/spec/llm/index.d.ts.map +0 -1
  103. package/dist/spec/llm/index.js +0 -11
  104. package/dist/spec/llm/index.js.map +0 -1
  105. package/dist/spec/mining/diff-parser.d.ts +0 -33
  106. package/dist/spec/mining/diff-parser.d.ts.map +0 -1
  107. package/dist/spec/mining/diff-parser.js +0 -166
  108. package/dist/spec/mining/diff-parser.js.map +0 -1
  109. package/dist/spec/mining/git-scanner.d.ts +0 -103
  110. package/dist/spec/mining/git-scanner.d.ts.map +0 -1
  111. package/dist/spec/mining/git-scanner.js +0 -307
  112. package/dist/spec/mining/git-scanner.js.map +0 -1
  113. package/dist/spec/mining/pipeline.d.ts +0 -53
  114. package/dist/spec/mining/pipeline.d.ts.map +0 -1
  115. package/dist/spec/mining/pipeline.js +0 -178
  116. package/dist/spec/mining/pipeline.js.map +0 -1
  117. package/dist/spec/mining/scope-resolver.d.ts +0 -45
  118. package/dist/spec/mining/scope-resolver.d.ts.map +0 -1
  119. package/dist/spec/mining/scope-resolver.js +0 -103
  120. package/dist/spec/mining/scope-resolver.js.map +0 -1
  121. package/dist/spec/mining/spec-extractor.d.ts +0 -69
  122. package/dist/spec/mining/spec-extractor.d.ts.map +0 -1
  123. package/dist/spec/mining/spec-extractor.js +0 -369
  124. package/dist/spec/mining/spec-extractor.js.map +0 -1
  125. package/dist/spec/utils.d.ts +0 -167
  126. package/dist/spec/utils.d.ts.map +0 -1
  127. package/dist/spec/utils.js +0 -463
  128. package/dist/spec/utils.js.map +0 -1
  129. package/scripts/_tmp-cfwk-resolve.log +0 -0
  130. package/scripts/_tmp-cfwk-sig.log +0 -0
  131. package/scripts/_tmp-cfwk-vt.log +0 -0
  132. package/scripts/add-lang/bench.sh +0 -60
  133. package/scripts/add-lang/check-grammar.mjs +0 -75
  134. package/scripts/add-lang/dump-ast.mjs +0 -103
  135. package/scripts/add-lang/verify-extraction.mjs +0 -70
  136. package/scripts/agent-eval/ab-adoption.sh +0 -91
  137. package/scripts/agent-eval/ab-hook.sh +0 -86
  138. package/scripts/agent-eval/ab-impl.sh +0 -78
  139. package/scripts/agent-eval/ab-new-vs-baseline.sh +0 -102
  140. package/scripts/agent-eval/ab-sufficiency.sh +0 -78
  141. package/scripts/agent-eval/arms-F.sh +0 -21
  142. package/scripts/agent-eval/arms-matrix.sh +0 -37
  143. package/scripts/agent-eval/audit.sh +0 -68
  144. package/scripts/agent-eval/bench-readme.sh +0 -28
  145. package/scripts/agent-eval/bench-why-repo.sh +0 -22
  146. package/scripts/agent-eval/block-read-hook.sh +0 -19
  147. package/scripts/agent-eval/hook-settings.json +0 -15
  148. package/scripts/agent-eval/itrun.sh +0 -120
  149. package/scripts/agent-eval/offload-eval-3arm.sh +0 -72
  150. package/scripts/agent-eval/offload-eval-cost.mjs +0 -133
  151. package/scripts/agent-eval/offload-eval-effort.mjs +0 -108
  152. package/scripts/agent-eval/offload-eval-frontload-matrix.sh +0 -25
  153. package/scripts/agent-eval/offload-eval-frontload.sh +0 -47
  154. package/scripts/agent-eval/offload-eval-ground-truth.json +0 -18
  155. package/scripts/agent-eval/offload-eval-hook.mjs +0 -84
  156. package/scripts/agent-eval/offload-eval-judge.mjs +0 -103
  157. package/scripts/agent-eval/offload-eval-matrix.sh +0 -20
  158. package/scripts/agent-eval/offload-eval-metrics.mjs +0 -94
  159. package/scripts/agent-eval/offload-eval-refs1.sh +0 -50
  160. package/scripts/agent-eval/offload-eval-setup.sh +0 -24
  161. package/scripts/agent-eval/offload-eval-styles.sh +0 -72
  162. package/scripts/agent-eval/offload-eval-summarize.mjs +0 -68
  163. package/scripts/agent-eval/offload-eval.md +0 -76
  164. package/scripts/agent-eval/parse-arms.mjs +0 -116
  165. package/scripts/agent-eval/parse-bench-readme.mjs +0 -84
  166. package/scripts/agent-eval/parse-run.mjs +0 -45
  167. package/scripts/agent-eval/parse-session.mjs +0 -93
  168. package/scripts/agent-eval/probe-context.mjs +0 -21
  169. package/scripts/agent-eval/probe-explore.mjs +0 -40
  170. package/scripts/agent-eval/probe-node.mjs +0 -20
  171. package/scripts/agent-eval/probe-sweep.mjs +0 -119
  172. package/scripts/agent-eval/probe-trace.mjs +0 -20
  173. package/scripts/agent-eval/redirect-read-hook.sh +0 -38
  174. package/scripts/agent-eval/repro-concurrent-explore.mjs +0 -119
  175. package/scripts/agent-eval/repro-daemon-clients.mjs +0 -125
  176. package/scripts/agent-eval/run-agent.sh +0 -34
  177. package/scripts/agent-eval/run-all.sh +0 -75
  178. package/scripts/agent-eval/run-arms.sh +0 -56
  179. package/scripts/agent-eval/seq-matrix.mjs +0 -137
  180. package/scripts/bench-arkts-init-rss.log +0 -0
  181. package/scripts/build-bundle.sh +0 -123
  182. package/scripts/exp_boundary_eval/README.md +0 -247
  183. package/scripts/exp_boundary_eval/__pycache__/_utils.cpython-310.pyc +0 -0
  184. package/scripts/exp_boundary_eval/__pycache__/_utils.cpython-38.pyc +0 -0
  185. package/scripts/exp_boundary_eval/__pycache__/analyze.cpython-310.pyc +0 -0
  186. package/scripts/exp_boundary_eval/__pycache__/analyze.cpython-38.pyc +0 -0
  187. package/scripts/exp_boundary_eval/__pycache__/deveco_arm.cpython-38.pyc +0 -0
  188. package/scripts/exp_boundary_eval/__pycache__/run_all.cpython-310.pyc +0 -0
  189. package/scripts/exp_boundary_eval/__pycache__/run_all.cpython-38.pyc +0 -0
  190. package/scripts/exp_boundary_eval/__pycache__/run_one.cpython-310.pyc +0 -0
  191. package/scripts/exp_boundary_eval/__pycache__/run_one.cpython-38.pyc +0 -0
  192. package/scripts/exp_boundary_eval/__pycache__/run_session.cpython-310.pyc +0 -0
  193. package/scripts/exp_boundary_eval/__pycache__/run_session.cpython-38.pyc +0 -0
  194. package/scripts/exp_boundary_eval/__pycache__/setup.cpython-310.pyc +0 -0
  195. package/scripts/exp_boundary_eval/__pycache__/setup.cpython-38.pyc +0 -0
  196. package/scripts/exp_boundary_eval/__pycache__/win_mcp_launcher.cpython-38.pyc +0 -0
  197. package/scripts/exp_boundary_eval/_test_mcp_chain.py +0 -78
  198. package/scripts/exp_boundary_eval/_test_stdin.py +0 -8
  199. package/scripts/exp_boundary_eval/_utils.py +0 -1116
  200. package/scripts/exp_boundary_eval/analyze.py +0 -1313
  201. package/scripts/exp_boundary_eval/deveco_arm.py +0 -519
  202. package/scripts/exp_boundary_eval/run_all.py +0 -378
  203. package/scripts/exp_boundary_eval/run_one.py +0 -165
  204. package/scripts/exp_boundary_eval/run_session.py +0 -158
  205. package/scripts/exp_boundary_eval/setup.py +0 -120
  206. package/scripts/exp_boundary_eval/win_mcp_launcher.py +0 -73
  207. package/scripts/exp_boundary_eval/win_mcp_stdio_wrap.js +0 -36
  208. package/scripts/exp_boundary_eval/win_node_launcher.py +0 -24
  209. package/scripts/extract-release-notes.mjs +0 -130
  210. package/scripts/local-install.sh +0 -41
  211. package/scripts/npm-sdk.js +0 -75
  212. package/scripts/npm-shim.js +0 -275
  213. package/scripts/ohos-sdk-publish.mjs +0 -133
  214. package/scripts/pack-npm.sh +0 -119
  215. package/scripts/prepare-release.mjs +0 -270
  216. package/scripts/probe-arkts-mem-why-run.log +0 -0
  217. package/scripts/probe-banner-livecard-ir.log +0 -0
  218. package/scripts/probe-cfwk-ast.stderr.log +0 -0
  219. package/scripts/probe-cfwk-ast.stdout.log +0 -0
  220. package/scripts/probe-cfwk-attr-shape.log +0 -0
  221. package/scripts/probe-cfwk-cfgdump.stderr.log +0 -0
  222. package/scripts/probe-cfwk-cfgdump.stdout.log +0 -0
  223. package/scripts/probe-cfwk-cvc.stderr.log +0 -0
  224. package/scripts/probe-cfwk-cvc.stdout.log +0 -0
  225. package/scripts/probe-cfwk-diag2.log +0 -0
  226. package/scripts/probe-cfwk-diag3.log +0 -0
  227. package/scripts/probe-cfwk-fedbg.stderr.log +0 -0
  228. package/scripts/probe-cfwk-fedbg.stdout.log +0 -0
  229. package/scripts/probe-cfwk-fileresult.log +0 -0
  230. package/scripts/probe-cfwk-fix.stderr.log +0 -0
  231. package/scripts/probe-cfwk-fix.stdout.log +0 -0
  232. package/scripts/probe-cfwk-fix2.stderr.log +0 -0
  233. package/scripts/probe-cfwk-fix2.stdout.log +0 -0
  234. package/scripts/probe-cfwk-fix3.stderr.log +0 -0
  235. package/scripts/probe-cfwk-fix3.stdout.log +0 -0
  236. package/scripts/probe-cfwk-foreach.log +0 -0
  237. package/scripts/probe-cfwk-getmethod-throw.log +0 -0
  238. package/scripts/probe-cfwk-hg-extract.log +0 -0
  239. package/scripts/probe-cfwk-pr1003-noprior.stderr.log +0 -0
  240. package/scripts/probe-cfwk-pr1003-noprior.stdout.log +0 -0
  241. package/scripts/probe-cfwk-pr1003.stderr.log +0 -0
  242. package/scripts/probe-cfwk-pr1003.stdout.log +0 -0
  243. package/scripts/probe-cfwk-preroot-noprior.stderr.log +0 -0
  244. package/scripts/probe-cfwk-preroot-noprior.stdout.log +0 -0
  245. package/scripts/probe-cfwk-preroot-prior.stderr.log +0 -0
  246. package/scripts/probe-cfwk-preroot-prior.stdout.log +0 -0
  247. package/scripts/probe-cfwk-preroot-skipstate.stderr.log +0 -0
  248. package/scripts/probe-cfwk-preroot-skipstate.stdout.log +0 -0
  249. package/scripts/probe-cfwk-resolve-sim.log +0 -0
  250. package/scripts/probe-cfwk-tree-shape.log +0 -0
  251. package/scripts/probe-cfwk-walk-abort.log +0 -0
  252. package/scripts/probe-cfwk.log +0 -0
  253. package/scripts/probe-force-index.log +0 -0
  254. package/scripts/probe-no-force-index.log +0 -0
  255. package/scripts/probe-samefile-ir.stderr.log +0 -0
  256. package/scripts/probe-samefile-ir.stdout.log +0 -224
  257. package/scripts/probe-sdk-vs-project.log +0 -0
  258. package/scripts/probe-viewtree-downgrade.log +0 -0
@@ -255,20 +255,20 @@ class QueryBuilder {
255
255
  */
256
256
  insertNode(node) {
257
257
  if (!this.stmts.insertNode) {
258
- this.stmts.insertNode = this.db.prepare(`
259
- INSERT OR REPLACE INTO nodes (
260
- id, kind, name, qualified_name, file_path, language,
261
- start_line, end_line, start_column, end_column,
262
- docstring, signature, visibility,
263
- is_exported, is_async, is_static, is_abstract,
264
- decorators, type_parameters, return_type, updated_at
265
- ) VALUES (
266
- @id, @kind, @name, @qualifiedName, @filePath, @language,
267
- @startLine, @endLine, @startColumn, @endColumn,
268
- @docstring, @signature, @visibility,
269
- @isExported, @isAsync, @isStatic, @isAbstract,
270
- @decorators, @typeParameters, @returnType, @updatedAt
271
- )
258
+ this.stmts.insertNode = this.db.prepare(`
259
+ INSERT OR REPLACE INTO nodes (
260
+ id, kind, name, qualified_name, file_path, language,
261
+ start_line, end_line, start_column, end_column,
262
+ docstring, signature, visibility,
263
+ is_exported, is_async, is_static, is_abstract,
264
+ decorators, type_parameters, return_type, updated_at
265
+ ) VALUES (
266
+ @id, @kind, @name, @qualifiedName, @filePath, @language,
267
+ @startLine, @endLine, @startColumn, @endColumn,
268
+ @docstring, @signature, @visibility,
269
+ @isExported, @isAsync, @isStatic, @isAbstract,
270
+ @decorators, @typeParameters, @returnType, @updatedAt
271
+ )
272
272
  `);
273
273
  }
274
274
  // Validate required fields to prevent SQLite bind errors
@@ -364,29 +364,29 @@ class QueryBuilder {
364
364
  */
365
365
  updateNode(node) {
366
366
  if (!this.stmts.updateNode) {
367
- this.stmts.updateNode = this.db.prepare(`
368
- UPDATE nodes SET
369
- kind = @kind,
370
- name = @name,
371
- qualified_name = @qualifiedName,
372
- file_path = @filePath,
373
- language = @language,
374
- start_line = @startLine,
375
- end_line = @endLine,
376
- start_column = @startColumn,
377
- end_column = @endColumn,
378
- docstring = @docstring,
379
- signature = @signature,
380
- visibility = @visibility,
381
- is_exported = @isExported,
382
- is_async = @isAsync,
383
- is_static = @isStatic,
384
- is_abstract = @isAbstract,
385
- decorators = @decorators,
386
- type_parameters = @typeParameters,
387
- return_type = @returnType,
388
- updated_at = @updatedAt
389
- WHERE id = @id
367
+ this.stmts.updateNode = this.db.prepare(`
368
+ UPDATE nodes SET
369
+ kind = @kind,
370
+ name = @name,
371
+ qualified_name = @qualifiedName,
372
+ file_path = @filePath,
373
+ language = @language,
374
+ start_line = @startLine,
375
+ end_line = @endLine,
376
+ start_column = @startColumn,
377
+ end_column = @endColumn,
378
+ docstring = @docstring,
379
+ signature = @signature,
380
+ visibility = @visibility,
381
+ is_exported = @isExported,
382
+ is_async = @isAsync,
383
+ is_static = @isStatic,
384
+ is_abstract = @isAbstract,
385
+ decorators = @decorators,
386
+ type_parameters = @typeParameters,
387
+ return_type = @returnType,
388
+ updated_at = @updatedAt
389
+ WHERE id = @id
390
390
  `);
391
391
  }
392
392
  // Invalidate cache before update
@@ -518,12 +518,12 @@ class QueryBuilder {
518
518
  const placeholders = variants.map(() => '?').join(', ');
519
519
  const whens = variants.map(() => 'WHEN ? THEN ?').join(' ');
520
520
  const rows = this.db
521
- .prepare(`SELECT name, COUNT(DISTINCT CASE segment ${whens} END) AS matches
522
- FROM name_segment_vocab
523
- WHERE segment IN (${placeholders})
524
- GROUP BY name
525
- HAVING matches >= ?
526
- ORDER BY matches DESC, length(name) ASC
521
+ .prepare(`SELECT name, COUNT(DISTINCT CASE segment ${whens} END) AS matches
522
+ FROM name_segment_vocab
523
+ WHERE segment IN (${placeholders})
524
+ GROUP BY name
525
+ HAVING matches >= ?
526
+ ORDER BY matches DESC, length(name) ASC
527
527
  LIMIT ?`)
528
528
  .all(...variants.flatMap((v) => [v.segment, v.word]), ...variants.map((v) => v.segment), minWords, limit);
529
529
  return rows;
@@ -535,7 +535,7 @@ class QueryBuilder {
535
535
  return new Map();
536
536
  const placeholders = segments.map(() => '?').join(', ');
537
537
  const rows = this.db
538
- .prepare(`SELECT segment, COUNT(*) AS n FROM name_segment_vocab
538
+ .prepare(`SELECT segment, COUNT(*) AS n FROM name_segment_vocab
539
539
  WHERE segment IN (${placeholders}) GROUP BY segment`)
540
540
  .all(...segments);
541
541
  return new Map(rows.map((r) => [r.segment, r.n]));
@@ -695,15 +695,15 @@ class QueryBuilder {
695
695
  // protobuf stub) outranks the real `server/etcdserver/server.go`
696
696
  // (470 edges) by 4×, and the boost would push the agent toward
697
697
  // generated code.
698
- this.stmts.getDominantFile = this.db.prepare(`
699
- SELECT n.file_path AS file_path, COUNT(*) AS edge_count
700
- FROM edges e
701
- JOIN nodes n ON e.source = n.id
702
- JOIN nodes m ON e.target = m.id
703
- WHERE n.file_path = m.file_path
704
- GROUP BY n.file_path
705
- ORDER BY edge_count DESC
706
- LIMIT 20
698
+ this.stmts.getDominantFile = this.db.prepare(`
699
+ SELECT n.file_path AS file_path, COUNT(*) AS edge_count
700
+ FROM edges e
701
+ JOIN nodes n ON e.source = n.id
702
+ JOIN nodes m ON e.target = m.id
703
+ WHERE n.file_path = m.file_path
704
+ GROUP BY n.file_path
705
+ ORDER BY edge_count DESC
706
+ LIMIT 20
707
707
  `);
708
708
  }
709
709
  const rows = this.stmts.getDominantFile.all();
@@ -730,13 +730,13 @@ class QueryBuilder {
730
730
  */
731
731
  getTopRouteFile() {
732
732
  if (!this.stmts.getTopRouteFile) {
733
- this.stmts.getTopRouteFile = this.db.prepare(`
734
- SELECT file_path, COUNT(*) AS cnt
735
- FROM nodes
736
- WHERE kind = 'route'
737
- GROUP BY file_path
738
- ORDER BY cnt DESC
739
- LIMIT 20
733
+ this.stmts.getTopRouteFile = this.db.prepare(`
734
+ SELECT file_path, COUNT(*) AS cnt
735
+ FROM nodes
736
+ WHERE kind = 'route'
737
+ GROUP BY file_path
738
+ ORDER BY cnt DESC
739
+ LIMIT 20
740
740
  `);
741
741
  }
742
742
  const rows = this.stmts.getTopRouteFile.all();
@@ -767,21 +767,21 @@ class QueryBuilder {
767
767
  // Edge kind varies across framework resolvers: Spring/Rails/
768
768
  // Laravel/Drupal emit `references`, Express emits `calls`. Accept
769
769
  // both — the semantic is the same (route → its handler).
770
- this.stmts.getRoutingManifest = this.db.prepare(`
771
- SELECT
772
- r.name AS url,
773
- h.name AS handler,
774
- h.file_path AS handler_file,
775
- h.start_line AS handler_line,
776
- h.kind AS handler_kind
777
- FROM nodes r
778
- JOIN edges e ON e.source = r.id
779
- JOIN nodes h ON e.target = h.id
780
- WHERE r.kind = 'route'
781
- AND e.kind IN ('references', 'calls')
782
- AND h.kind IN ('function', 'method', 'class')
783
- ORDER BY r.file_path, r.start_line
784
- LIMIT ?
770
+ this.stmts.getRoutingManifest = this.db.prepare(`
771
+ SELECT
772
+ r.name AS url,
773
+ h.name AS handler,
774
+ h.file_path AS handler_file,
775
+ h.start_line AS handler_line,
776
+ h.kind AS handler_kind
777
+ FROM nodes r
778
+ JOIN edges e ON e.source = r.id
779
+ JOIN nodes h ON e.target = h.id
780
+ WHERE r.kind = 'route'
781
+ AND e.kind IN ('references', 'calls')
782
+ AND h.kind IN ('function', 'method', 'class')
783
+ ORDER BY r.file_path, r.start_line
784
+ LIMIT ?
785
785
  `);
786
786
  }
787
787
  const rows = this.stmts.getRoutingManifest.all(limit);
@@ -1036,10 +1036,10 @@ class QueryBuilder {
1036
1036
  const seen = new Set(existing.map((r) => r.node.id));
1037
1037
  const merged = [...existing];
1038
1038
  const apiLimit = Math.min(20, Math.max(5, Math.floor(limit / 4)));
1039
- let sql = `
1040
- SELECT nodes.*, 0.9 as score
1041
- FROM ohos_api.nodes
1042
- WHERE (name LIKE ? OR qualified_name LIKE ?)
1039
+ let sql = `
1040
+ SELECT nodes.*, 0.9 as score
1041
+ FROM ohos_api.nodes
1042
+ WHERE (name LIKE ? OR qualified_name LIKE ?)
1043
1043
  `;
1044
1044
  const pattern = `%${text}%`;
1045
1045
  const params = [pattern, pattern];
@@ -1178,11 +1178,11 @@ class QueryBuilder {
1178
1178
  // Fetch 5x requested limit so post-hoc rescoring (kindBonus, pathRelevance,
1179
1179
  // nameMatchBonus) can promote results that BM25 alone undervalues.
1180
1180
  const ftsLimit = Math.max(limit * 5, 100);
1181
- let sql = `
1182
- SELECT nodes.*, bm25(nodes_fts, 0, 20, 5, 1, 2) as score
1183
- FROM nodes_fts
1184
- JOIN nodes ON nodes_fts.id = nodes.id
1185
- WHERE nodes_fts MATCH ?
1181
+ let sql = `
1182
+ SELECT nodes.*, bm25(nodes_fts, 0, 20, 5, 1, 2) as score
1183
+ FROM nodes_fts
1184
+ JOIN nodes ON nodes_fts.id = nodes.id
1185
+ WHERE nodes_fts MATCH ?
1186
1186
  `;
1187
1187
  const params = [ftsQuery];
1188
1188
  if (kinds && kinds.length > 0) {
@@ -1213,21 +1213,21 @@ class QueryBuilder {
1213
1213
  */
1214
1214
  searchNodesLike(query, options) {
1215
1215
  const { kinds, languages, limit = 100, offset = 0 } = options;
1216
- let sql = `
1217
- SELECT nodes.*,
1218
- CASE
1219
- WHEN name = ? THEN 1.0
1220
- WHEN name LIKE ? THEN 0.9
1221
- WHEN name LIKE ? THEN 0.8
1222
- WHEN qualified_name LIKE ? THEN 0.7
1223
- ELSE 0.5
1224
- END as score
1225
- FROM nodes
1226
- WHERE (
1227
- name LIKE ? OR
1228
- qualified_name LIKE ? OR
1229
- name LIKE ?
1230
- )
1216
+ let sql = `
1217
+ SELECT nodes.*,
1218
+ CASE
1219
+ WHEN name = ? THEN 1.0
1220
+ WHEN name LIKE ? THEN 0.9
1221
+ WHEN name LIKE ? THEN 0.8
1222
+ WHEN qualified_name LIKE ? THEN 0.7
1223
+ ELSE 0.5
1224
+ END as score
1225
+ FROM nodes
1226
+ WHERE (
1227
+ name LIKE ? OR
1228
+ qualified_name LIKE ? OR
1229
+ name LIKE ?
1230
+ )
1231
1231
  `;
1232
1232
  // Pattern variants for better matching
1233
1233
  const exactMatch = query;
@@ -1301,10 +1301,10 @@ class QueryBuilder {
1301
1301
  const allResults = [];
1302
1302
  const seenIds = new Set();
1303
1303
  for (const name of names) {
1304
- let sql = `
1305
- SELECT nodes.*, 1.0 as score
1306
- FROM nodes
1307
- WHERE name COLLATE NOCASE = ?
1304
+ let sql = `
1305
+ SELECT nodes.*, 1.0 as score
1306
+ FROM nodes
1307
+ WHERE name COLLATE NOCASE = ?
1308
1308
  `;
1309
1309
  const params = [name];
1310
1310
  if (kinds && kinds.length > 0) {
@@ -1335,10 +1335,10 @@ class QueryBuilder {
1335
1335
  allResults.push(r);
1336
1336
  }
1337
1337
  if (this.hasOhosApiAttached()) {
1338
- let apiSql = `
1339
- SELECT nodes.*, 0.95 as score
1340
- FROM ohos_api.nodes
1341
- WHERE name COLLATE NOCASE = ?
1338
+ let apiSql = `
1339
+ SELECT nodes.*, 0.95 as score
1340
+ FROM ohos_api.nodes
1341
+ WHERE name COLLATE NOCASE = ?
1342
1342
  `;
1343
1343
  const apiParams = [name];
1344
1344
  if (kinds && kinds.length > 0) {
@@ -1374,10 +1374,10 @@ class QueryBuilder {
1374
1374
  */
1375
1375
  findNodesByNameSubstring(substring, options = {}) {
1376
1376
  const { kinds, languages, limit = 30, excludePrefix } = options;
1377
- let sql = `
1378
- SELECT nodes.*, 1.0 as score
1379
- FROM nodes
1380
- WHERE name LIKE ?
1377
+ let sql = `
1378
+ SELECT nodes.*, 1.0 as score
1379
+ FROM nodes
1380
+ WHERE name LIKE ?
1381
1381
  `;
1382
1382
  const params = [`%${substring}%`];
1383
1383
  // Exclude prefix matches (handled by FTS-based prefix search in Step 2b)
@@ -1409,9 +1409,9 @@ class QueryBuilder {
1409
1409
  */
1410
1410
  insertEdge(edge) {
1411
1411
  if (!this.stmts.insertEdge) {
1412
- this.stmts.insertEdge = this.db.prepare(`
1413
- INSERT OR IGNORE INTO edges (source, target, kind, metadata, line, col, provenance)
1414
- VALUES (@source, @target, @kind, @metadata, @line, @col, @provenance)
1412
+ this.stmts.insertEdge = this.db.prepare(`
1413
+ INSERT OR IGNORE INTO edges (source, target, kind, metadata, line, col, provenance)
1414
+ VALUES (@source, @target, @kind, @metadata, @line, @col, @provenance)
1415
1415
  `);
1416
1416
  }
1417
1417
  this.stmts.insertEdge.run({
@@ -1538,12 +1538,12 @@ class QueryBuilder {
1538
1538
  * it. One indexed query (idx_nodes_file_path + idx_edges_target_kind).
1539
1539
  */
1540
1540
  getDependentFilePaths(filePath) {
1541
- const sql = `SELECT DISTINCT src.file_path AS fp
1542
- FROM edges e
1543
- JOIN nodes tgt ON tgt.id = e.target
1544
- JOIN nodes src ON src.id = e.source
1545
- WHERE tgt.file_path = ?
1546
- AND e.kind != 'contains'
1541
+ const sql = `SELECT DISTINCT src.file_path AS fp
1542
+ FROM edges e
1543
+ JOIN nodes tgt ON tgt.id = e.target
1544
+ JOIN nodes src ON src.id = e.source
1545
+ WHERE tgt.file_path = ?
1546
+ AND e.kind != 'contains'
1547
1547
  AND src.file_path != ?`;
1548
1548
  const rows = this.db.prepare(sql).all(filePath, filePath);
1549
1549
  return rows.map((r) => r.fp);
@@ -1555,12 +1555,12 @@ class QueryBuilder {
1555
1555
  * (all kinds except `contains`); same reason imports-only is insufficient.
1556
1556
  */
1557
1557
  getDependencyFilePaths(filePath) {
1558
- const sql = `SELECT DISTINCT tgt.file_path AS fp
1559
- FROM edges e
1560
- JOIN nodes src ON src.id = e.source
1561
- JOIN nodes tgt ON tgt.id = e.target
1562
- WHERE src.file_path = ?
1563
- AND e.kind != 'contains'
1558
+ const sql = `SELECT DISTINCT tgt.file_path AS fp
1559
+ FROM edges e
1560
+ JOIN nodes src ON src.id = e.source
1561
+ JOIN nodes tgt ON tgt.id = e.target
1562
+ WHERE src.file_path = ?
1563
+ AND e.kind != 'contains'
1564
1564
  AND tgt.file_path != ?`;
1565
1565
  const rows = this.db.prepare(sql).all(filePath, filePath);
1566
1566
  return rows.map((r) => r.fp);
@@ -1576,13 +1576,13 @@ class QueryBuilder {
1576
1576
  * {@link getDependentFilePaths}: all kinds except `contains`.
1577
1577
  */
1578
1578
  getCrossFileIncomingEdgesWithTarget(filePath) {
1579
- const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind,
1580
- src.file_path AS source_file_path, src.language AS source_language
1581
- FROM edges e
1582
- JOIN nodes tgt ON tgt.id = e.target
1583
- JOIN nodes src ON src.id = e.source
1584
- WHERE tgt.file_path = ?
1585
- AND e.kind != 'contains'
1579
+ const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind,
1580
+ src.file_path AS source_file_path, src.language AS source_language
1581
+ FROM edges e
1582
+ JOIN nodes tgt ON tgt.id = e.target
1583
+ JOIN nodes src ON src.id = e.source
1584
+ WHERE tgt.file_path = ?
1585
+ AND e.kind != 'contains'
1586
1586
  AND src.file_path != ?`;
1587
1587
  const rows = this.db.prepare(sql).all(filePath, filePath);
1588
1588
  return rows.map(row => ({
@@ -1599,10 +1599,10 @@ class QueryBuilder {
1599
1599
  */
1600
1600
  deleteArkTSCrossFileCallEdges() {
1601
1601
  const result = this.db
1602
- .prepare(`DELETE FROM edges
1603
- WHERE kind = 'calls'
1604
- AND provenance = 'heuristic'
1605
- AND metadata LIKE '%"synthesizedBy":"arkanalyzer"%'
1602
+ .prepare(`DELETE FROM edges
1603
+ WHERE kind = 'calls'
1604
+ AND provenance = 'heuristic'
1605
+ AND metadata LIKE '%"synthesizedBy":"arkanalyzer"%'
1606
1606
  AND metadata LIKE '%"sourceFile"%'`)
1607
1607
  .run();
1608
1608
  return result.changes;
@@ -1615,17 +1615,17 @@ class QueryBuilder {
1615
1615
  */
1616
1616
  upsertFile(file) {
1617
1617
  if (!this.stmts.upsertFile) {
1618
- this.stmts.upsertFile = this.db.prepare(`
1619
- INSERT INTO files (path, content_hash, language, size, modified_at, indexed_at, node_count, errors)
1620
- VALUES (@path, @contentHash, @language, @size, @modifiedAt, @indexedAt, @nodeCount, @errors)
1621
- ON CONFLICT(path) DO UPDATE SET
1622
- content_hash = @contentHash,
1623
- language = @language,
1624
- size = @size,
1625
- modified_at = @modifiedAt,
1626
- indexed_at = @indexedAt,
1627
- node_count = @nodeCount,
1628
- errors = @errors
1618
+ this.stmts.upsertFile = this.db.prepare(`
1619
+ INSERT INTO files (path, content_hash, language, size, modified_at, indexed_at, node_count, errors)
1620
+ VALUES (@path, @contentHash, @language, @size, @modifiedAt, @indexedAt, @nodeCount, @errors)
1621
+ ON CONFLICT(path) DO UPDATE SET
1622
+ content_hash = @contentHash,
1623
+ language = @language,
1624
+ size = @size,
1625
+ modified_at = @modifiedAt,
1626
+ indexed_at = @indexedAt,
1627
+ node_count = @nodeCount,
1628
+ errors = @errors
1629
1629
  `);
1630
1630
  }
1631
1631
  this.stmts.upsertFile.run({
@@ -1699,9 +1699,9 @@ class QueryBuilder {
1699
1699
  */
1700
1700
  insertUnresolvedRef(ref) {
1701
1701
  if (!this.stmts.insertUnresolved) {
1702
- this.stmts.insertUnresolved = this.db.prepare(`
1703
- INSERT INTO unresolved_refs (from_node_id, reference_name, reference_kind, line, col, candidates, file_path, language)
1704
- VALUES (@fromNodeId, @referenceName, @referenceKind, @line, @col, @candidates, @filePath, @language)
1702
+ this.stmts.insertUnresolved = this.db.prepare(`
1703
+ INSERT INTO unresolved_refs (from_node_id, reference_name, reference_kind, line, col, candidates, file_path, language)
1704
+ VALUES (@fromNodeId, @referenceName, @referenceKind, @line, @col, @candidates, @filePath, @language)
1705
1705
  `);
1706
1706
  }
1707
1707
  this.stmts.insertUnresolved.run({
@@ -2085,11 +2085,11 @@ class QueryBuilder {
2085
2085
  */
2086
2086
  getStats() {
2087
2087
  // Single query for all three aggregate counts
2088
- const counts = this.db.prepare(`
2089
- SELECT
2090
- (SELECT COUNT(*) FROM nodes) AS node_count,
2091
- (SELECT COUNT(*) FROM edges) AS edge_count,
2092
- (SELECT COUNT(*) FROM files) AS file_count
2088
+ const counts = this.db.prepare(`
2089
+ SELECT
2090
+ (SELECT COUNT(*) FROM nodes) AS node_count,
2091
+ (SELECT COUNT(*) FROM edges) AS edge_count,
2092
+ (SELECT COUNT(*) FROM files) AS file_count
2093
2093
  `).get();
2094
2094
  const nodesByKind = {};
2095
2095
  const nodeKindRows = this.db