homegraph 1.5.2 → 1.5.4

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 (242) hide show
  1. package/CHANGELOG.md +156 -0
  2. package/README.md +63 -10
  3. package/dist/addons/dynamic-import.d.ts +18 -0
  4. package/dist/addons/dynamic-import.d.ts.map +1 -0
  5. package/dist/addons/dynamic-import.js +25 -0
  6. package/dist/addons/dynamic-import.js.map +1 -0
  7. package/dist/addons/init-template.d.ts +15 -0
  8. package/dist/addons/init-template.d.ts.map +1 -0
  9. package/dist/addons/init-template.js +290 -0
  10. package/dist/addons/init-template.js.map +1 -0
  11. package/dist/addons/loader.d.ts +18 -0
  12. package/dist/addons/loader.d.ts.map +1 -0
  13. package/dist/addons/loader.js +88 -0
  14. package/dist/addons/loader.js.map +1 -0
  15. package/dist/addons/manager.d.ts +106 -0
  16. package/dist/addons/manager.d.ts.map +1 -0
  17. package/dist/addons/manager.js +437 -0
  18. package/dist/addons/manager.js.map +1 -0
  19. package/dist/addons/paths.d.ts +22 -0
  20. package/dist/addons/paths.d.ts.map +1 -0
  21. package/dist/addons/paths.js +65 -0
  22. package/dist/addons/paths.js.map +1 -0
  23. package/dist/addons/registry.d.ts +38 -0
  24. package/dist/addons/registry.d.ts.map +1 -0
  25. package/dist/addons/registry.js +160 -0
  26. package/dist/addons/registry.js.map +1 -0
  27. package/dist/addons/semver.d.ts +21 -0
  28. package/dist/addons/semver.d.ts.map +1 -0
  29. package/dist/addons/semver.js +79 -0
  30. package/dist/addons/semver.js.map +1 -0
  31. package/dist/addons/types.d.ts +51 -0
  32. package/dist/addons/types.d.ts.map +1 -0
  33. package/dist/addons/types.js +14 -0
  34. package/dist/addons/types.js.map +1 -0
  35. package/dist/addons/validate.d.ts +38 -0
  36. package/dist/addons/validate.d.ts.map +1 -0
  37. package/dist/addons/validate.js +165 -0
  38. package/dist/addons/validate.js.map +1 -0
  39. package/dist/arkui/index.d.ts +4 -0
  40. package/dist/arkui/index.d.ts.map +1 -0
  41. package/dist/arkui/index.js +23 -0
  42. package/dist/arkui/index.js.map +1 -0
  43. package/dist/arkui/migrate-passage.d.ts +28 -0
  44. package/dist/arkui/migrate-passage.d.ts.map +1 -0
  45. package/dist/arkui/migrate-passage.js +310 -0
  46. package/dist/arkui/migrate-passage.js.map +1 -0
  47. package/dist/arkui/migrate-semantics.d.ts +47 -0
  48. package/dist/arkui/migrate-semantics.d.ts.map +1 -0
  49. package/dist/arkui/migrate-semantics.js +229 -0
  50. package/dist/arkui/migrate-semantics.js.map +1 -0
  51. package/dist/arkui/migrate-snapshot.d.ts +79 -0
  52. package/dist/arkui/migrate-snapshot.d.ts.map +1 -0
  53. package/dist/arkui/migrate-snapshot.js +364 -0
  54. package/dist/arkui/migrate-snapshot.js.map +1 -0
  55. package/dist/bin/addon-commands.d.ts +27 -0
  56. package/dist/bin/addon-commands.d.ts.map +1 -0
  57. package/dist/bin/addon-commands.js +254 -0
  58. package/dist/bin/addon-commands.js.map +1 -0
  59. package/dist/bin/fatal-handler.js +2 -2
  60. package/dist/bin/homegraph.js +111 -157
  61. package/dist/bin/homegraph.js.map +1 -1
  62. package/dist/bin/node-version-check.d.ts +6 -15
  63. package/dist/bin/node-version-check.d.ts.map +1 -1
  64. package/dist/bin/node-version-check.js +8 -37
  65. package/dist/bin/node-version-check.js.map +1 -1
  66. package/dist/db/index.d.ts +36 -1
  67. package/dist/db/index.d.ts.map +1 -1
  68. package/dist/db/index.js +92 -6
  69. package/dist/db/index.js.map +1 -1
  70. package/dist/db/migrations.d.ts +1 -1
  71. package/dist/db/migrations.d.ts.map +1 -1
  72. package/dist/db/migrations.js +15 -1
  73. package/dist/db/migrations.js.map +1 -1
  74. package/dist/db/queries.d.ts +42 -0
  75. package/dist/db/queries.d.ts.map +1 -1
  76. package/dist/db/queries.js +177 -10
  77. package/dist/db/queries.js.map +1 -1
  78. package/dist/db/schema.sql +6 -1
  79. package/dist/db/sqlite-adapter.d.ts +7 -3
  80. package/dist/db/sqlite-adapter.d.ts.map +1 -1
  81. package/dist/db/sqlite-adapter.js +44 -3
  82. package/dist/db/sqlite-adapter.js.map +1 -1
  83. package/dist/extraction/extraction-version.d.ts +1 -1
  84. package/dist/extraction/extraction-version.js +1 -1
  85. package/dist/extraction/generated-detection.d.ts +42 -11
  86. package/dist/extraction/generated-detection.d.ts.map +1 -1
  87. package/dist/extraction/generated-detection.js +141 -20
  88. package/dist/extraction/generated-detection.js.map +1 -1
  89. package/dist/extraction/index.d.ts +42 -0
  90. package/dist/extraction/index.d.ts.map +1 -1
  91. package/dist/extraction/index.js +96 -0
  92. package/dist/extraction/index.js.map +1 -1
  93. package/dist/extraction/languages/arkts.d.ts +33 -2
  94. package/dist/extraction/languages/arkts.d.ts.map +1 -1
  95. package/dist/extraction/languages/arkts.js +525 -129
  96. package/dist/extraction/languages/arkts.js.map +1 -1
  97. package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -1
  98. package/dist/extraction/wasm-runtime-flags.js +9 -6
  99. package/dist/extraction/wasm-runtime-flags.js.map +1 -1
  100. package/dist/graph-sources.d.ts +41 -0
  101. package/dist/graph-sources.d.ts.map +1 -0
  102. package/dist/graph-sources.js +82 -0
  103. package/dist/graph-sources.js.map +1 -0
  104. package/dist/index.d.ts +20 -1
  105. package/dist/index.d.ts.map +1 -1
  106. package/dist/index.js +79 -9
  107. package/dist/index.js.map +1 -1
  108. package/dist/installer/index.d.ts.map +1 -1
  109. package/dist/installer/index.js +0 -48
  110. package/dist/installer/index.js.map +1 -1
  111. package/dist/installer/targets/antigravity.js +1 -1
  112. package/dist/installer/targets/antigravity.js.map +1 -1
  113. package/dist/installer/targets/deveco.js +1 -1
  114. package/dist/installer/targets/deveco.js.map +1 -1
  115. package/dist/installer/targets/hermes.d.ts +1 -1
  116. package/dist/installer/targets/hermes.js +2 -2
  117. package/dist/installer/targets/hermes.js.map +1 -1
  118. package/dist/installer/targets/opencode.js +1 -1
  119. package/dist/installer/targets/opencode.js.map +1 -1
  120. package/dist/installer/targets/shared.js +1 -1
  121. package/dist/installer/targets/shared.js.map +1 -1
  122. package/dist/mcp/daemon-paths.d.ts +5 -4
  123. package/dist/mcp/daemon-paths.d.ts.map +1 -1
  124. package/dist/mcp/daemon-paths.js +28 -13
  125. package/dist/mcp/daemon-paths.js.map +1 -1
  126. package/dist/mcp/daemon-registry.d.ts.map +1 -1
  127. package/dist/mcp/daemon-registry.js +4 -1
  128. package/dist/mcp/daemon-registry.js.map +1 -1
  129. package/dist/mcp/daemon.d.ts +1 -1
  130. package/dist/mcp/daemon.js +1 -1
  131. package/dist/mcp/engine.d.ts.map +1 -1
  132. package/dist/mcp/engine.js +12 -3
  133. package/dist/mcp/engine.js.map +1 -1
  134. package/dist/mcp/explore-dedup.d.ts +137 -0
  135. package/dist/mcp/explore-dedup.d.ts.map +1 -0
  136. package/dist/mcp/explore-dedup.js +236 -0
  137. package/dist/mcp/explore-dedup.js.map +1 -0
  138. package/dist/mcp/explore-repeat-guard.d.ts +123 -0
  139. package/dist/mcp/explore-repeat-guard.d.ts.map +1 -0
  140. package/dist/mcp/explore-repeat-guard.js +503 -0
  141. package/dist/mcp/explore-repeat-guard.js.map +1 -0
  142. package/dist/mcp/explore-session-state.d.ts +237 -0
  143. package/dist/mcp/explore-session-state.d.ts.map +1 -0
  144. package/dist/mcp/explore-session-state.js +353 -0
  145. package/dist/mcp/explore-session-state.js.map +1 -0
  146. package/dist/mcp/index.d.ts.map +1 -1
  147. package/dist/mcp/index.js +4 -7
  148. package/dist/mcp/index.js.map +1 -1
  149. package/dist/mcp/proxy.d.ts.map +1 -1
  150. package/dist/mcp/proxy.js +20 -18
  151. package/dist/mcp/proxy.js.map +1 -1
  152. package/dist/mcp/query-pool.d.ts.map +1 -1
  153. package/dist/mcp/query-pool.js +10 -13
  154. package/dist/mcp/query-pool.js.map +1 -1
  155. package/dist/mcp/query-worker.d.ts +1 -1
  156. package/dist/mcp/query-worker.js +1 -1
  157. package/dist/mcp/server-instructions.d.ts +5 -2
  158. package/dist/mcp/server-instructions.d.ts.map +1 -1
  159. package/dist/mcp/server-instructions.js +43 -32
  160. package/dist/mcp/server-instructions.js.map +1 -1
  161. package/dist/mcp/session.d.ts +14 -3
  162. package/dist/mcp/session.d.ts.map +1 -1
  163. package/dist/mcp/session.js +17 -14
  164. package/dist/mcp/session.js.map +1 -1
  165. package/dist/mcp/startup-handshake.d.ts +1 -1
  166. package/dist/mcp/startup-handshake.js +1 -1
  167. package/dist/mcp/tools.d.ts +149 -8
  168. package/dist/mcp/tools.d.ts.map +1 -1
  169. package/dist/mcp/tools.js +4265 -575
  170. package/dist/mcp/tools.js.map +1 -1
  171. package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
  172. package/dist/resolution/callback-synthesizer.js +166 -0
  173. package/dist/resolution/callback-synthesizer.js.map +1 -1
  174. package/dist/resolution/frameworks/arkts-napi.d.ts +14 -0
  175. package/dist/resolution/frameworks/arkts-napi.d.ts.map +1 -1
  176. package/dist/resolution/frameworks/arkts-napi.js +169 -49
  177. package/dist/resolution/frameworks/arkts-napi.js.map +1 -1
  178. package/dist/search/query-utils.d.ts +157 -5
  179. package/dist/search/query-utils.d.ts.map +1 -1
  180. package/dist/search/query-utils.js +1105 -70
  181. package/dist/search/query-utils.js.map +1 -1
  182. package/dist/spec/build/scan.js +1 -1
  183. package/dist/spec/build/scan.js.map +1 -1
  184. package/dist/spec/build/scope-resolver.d.ts +24 -5
  185. package/dist/spec/build/scope-resolver.d.ts.map +1 -1
  186. package/dist/spec/build/scope-resolver.js +76 -10
  187. package/dist/spec/build/scope-resolver.js.map +1 -1
  188. package/dist/spec/config.d.ts +8 -0
  189. package/dist/spec/config.d.ts.map +1 -1
  190. package/dist/spec/config.js +3 -0
  191. package/dist/spec/config.js.map +1 -1
  192. package/dist/spec/evolve/pipeline.d.ts.map +1 -1
  193. package/dist/spec/evolve/pipeline.js +2 -1
  194. package/dist/spec/evolve/pipeline.js.map +1 -1
  195. package/dist/spec/git/commits.d.ts +8 -3
  196. package/dist/spec/git/commits.d.ts.map +1 -1
  197. package/dist/spec/git/commits.js +12 -11
  198. package/dist/spec/git/commits.js.map +1 -1
  199. package/dist/spec/mine/addon/adapter.d.ts +45 -0
  200. package/dist/spec/mine/addon/adapter.d.ts.map +1 -0
  201. package/dist/spec/mine/addon/adapter.js +118 -0
  202. package/dist/spec/mine/addon/adapter.js.map +1 -0
  203. package/dist/spec/mine/addon/render.d.ts +20 -0
  204. package/dist/spec/mine/addon/render.d.ts.map +1 -0
  205. package/dist/spec/mine/addon/render.js +41 -0
  206. package/dist/spec/mine/addon/render.js.map +1 -0
  207. package/dist/spec/mine/addon/types.d.ts +70 -0
  208. package/dist/spec/mine/addon/types.d.ts.map +1 -0
  209. package/dist/spec/mine/addon/types.js +14 -0
  210. package/dist/spec/mine/addon/types.js.map +1 -0
  211. package/dist/spec/mine/generator.d.ts +5 -1
  212. package/dist/spec/mine/generator.d.ts.map +1 -1
  213. package/dist/spec/mine/generator.js +69 -7
  214. package/dist/spec/mine/generator.js.map +1 -1
  215. package/dist/spec/mine/pipeline.d.ts.map +1 -1
  216. package/dist/spec/mine/pipeline.js +5 -1
  217. package/dist/spec/mine/pipeline.js.map +1 -1
  218. package/dist/spec/mine/scanner.d.ts +1 -0
  219. package/dist/spec/mine/scanner.d.ts.map +1 -1
  220. package/dist/spec/mine/scanner.js +1 -1
  221. package/dist/spec/mine/scanner.js.map +1 -1
  222. package/dist/spec/types.d.ts +1 -1
  223. package/dist/spec/types.d.ts.map +1 -1
  224. package/dist/types.d.ts +8 -0
  225. package/dist/types.d.ts.map +1 -1
  226. package/dist/upgrade/index.d.ts +14 -26
  227. package/dist/upgrade/index.d.ts.map +1 -1
  228. package/dist/upgrade/index.js +28 -123
  229. package/dist/upgrade/index.js.map +1 -1
  230. package/dist/upgrade/remove-binary.d.ts +19 -19
  231. package/dist/upgrade/remove-binary.d.ts.map +1 -1
  232. package/dist/upgrade/remove-binary.js +20 -21
  233. package/dist/upgrade/remove-binary.js.map +1 -1
  234. package/dist/upgrade/update-check.d.ts +4 -3
  235. package/dist/upgrade/update-check.d.ts.map +1 -1
  236. package/dist/upgrade/update-check.js +4 -3
  237. package/dist/upgrade/update-check.js.map +1 -1
  238. package/package.json +13 -9
  239. package/dist/telemetry/index.d.ts +0 -143
  240. package/dist/telemetry/index.d.ts.map +0 -1
  241. package/dist/telemetry/index.js +0 -541
  242. package/dist/telemetry/index.js.map +0 -1
@@ -71,7 +71,7 @@ const fatal_handler_1 = require("./fatal-handler");
71
71
  const wasm_runtime_flags_1 = require("../extraction/wasm-runtime-flags");
72
72
  const command_supervision_1 = require("./command-supervision");
73
73
  const extraction_version_1 = require("../extraction/extraction-version");
74
- const telemetry_1 = require("../telemetry");
74
+ const addon_commands_1 = require("./addon-commands");
75
75
  // Lazy-load heavy modules (HomeGraph, runInstaller) to keep CLI startup fast.
76
76
  async function loadHomeGraph() {
77
77
  try {
@@ -90,25 +90,13 @@ async function loadHomeGraph() {
90
90
  // which fails for ESM-only packages. This bypasses the transformation.
91
91
  // eslint-disable-next-line @typescript-eslint/no-implied-eval
92
92
  const importESM = new Function('specifier', 'return import(specifier)');
93
- // Block HomeGraph on Node.js 25.x — V8's turboshaft WASM JIT has a Zone
94
- // allocator bug that reliably crashes when compiling tree-sitter
95
- // grammars (see #54, #81, #140). The previous behaviour was a soft
96
- // console.warn that scrolls off-screen before the OOM crash 30 seconds
97
- // later, leading to a steady stream of "what is this OOM" reports.
98
- // Hard-exit before any WASM work; allow override via env var for users
99
- // who patched V8 themselves or want to test a future fix.
100
- const nodeVersion = process.versions.node;
101
- const nodeMajor = parseInt(nodeVersion.split('.')[0] ?? '0', 10);
102
- if (nodeMajor >= 25) {
103
- process.stderr.write((0, node_version_check_1.buildNode25BlockBanner)(nodeVersion) + '\n');
104
- if (!process.env.HOMEGRAPH_ALLOW_UNSAFE_NODE) {
105
- process.exit(1);
106
- }
107
- // Override active — banner shown for visibility, continuing.
108
- }
109
93
  // Enforce the supported Node floor. `engines` in package.json only *warns* on
110
94
  // install (unless engine-strict), so hard-block here to actually keep users off
111
- // unsupported versions. Mirrors the 25+ block above. See package.json `engines`.
95
+ // unsupported versions. See package.json `engines` and ./node-version-check.
96
+ // Node ≥22 WASM Zone OOM is mitigated by --liftoff-only relaunch below — not by
97
+ // blocking majors (Node 25+ is supported when that flag is applied).
98
+ const nodeVersion = process.versions.node;
99
+ const nodeMajor = parseInt(nodeVersion.split('.')[0] ?? '0', 10);
112
100
  if (nodeMajor < node_version_check_1.MIN_NODE_MAJOR) {
113
101
  process.stderr.write((0, node_version_check_1.buildNodeTooOldBanner)(nodeVersion) + '\n');
114
102
  if (!process.env.HOMEGRAPH_ALLOW_UNSAFE_NODE) {
@@ -184,30 +172,6 @@ function main() {
184
172
  .name('homegraph')
185
173
  .description('Code intelligence and knowledge graph for any codebase')
186
174
  .version(packageJson.version);
187
- // Anonymous usage telemetry (see TELEMETRY.md): record the invoked subcommand
188
- // NAME only — never arguments or paths. Counts buffer locally; network sends
189
- // piggyback on commands that run long anyway (quick commands only append to
190
- // the local buffer at exit, costing nothing).
191
- // install/uninstall are absent on purpose: the installer flushes at its own
192
- // end, AFTER its consent prompt — a flush here would fire the first-run
193
- // notice before the user ever sees the toggle.
194
- const TELEMETRY_FLUSH_COMMANDS = new Set(['init', 'uninit', 'index', 'sync', 'upgrade']);
195
- program.hook('preAction', (_thisCommand, actionCommand) => {
196
- try {
197
- // The detached daemon re-invokes `serve --mcp` internally — not a user action.
198
- if (process.env.HOMEGRAPH_DAEMON_INTERNAL)
199
- return;
200
- const name = actionCommand.name();
201
- if (name === 'telemetry')
202
- return; // managing telemetry is not usage
203
- (0, telemetry_1.getTelemetry)().recordUsage('cli_command', name, true);
204
- if (TELEMETRY_FLUSH_COMMANDS.has(name))
205
- (0, telemetry_1.getTelemetry)().maybeFlush();
206
- }
207
- catch {
208
- /* telemetry must never break the CLI */
209
- }
210
- });
211
175
  // =============================================================================
212
176
  // Helper Functions
213
177
  // =============================================================================
@@ -473,15 +437,6 @@ function main() {
473
437
  }
474
438
  fs.writeFileSync(logPath, lines.join('\n') + '\n');
475
439
  }
476
- /**
477
- * Telemetry for a completed full index (see TELEMETRY.md). The bounded flush
478
- * keeps init/index responsive (these commands just ran for seconds anyway)
479
- * while delivering the event promptly.
480
- */
481
- async function recordIndexTelemetry(cg, result) {
482
- (0, telemetry_1.recordIndexEvent)(cg, result);
483
- await (0, telemetry_1.getTelemetry)().flushNow();
484
- }
485
440
  // =============================================================================
486
441
  // Commands
487
442
  // =============================================================================
@@ -550,7 +505,6 @@ function main() {
550
505
  supervision.stop();
551
506
  }
552
507
  printIndexResult(clack, result, projectPath);
553
- await recordIndexTelemetry(cg, result);
554
508
  try {
555
509
  const { offerWatchFallback } = await Promise.resolve().then(() => __importStar(require('../installer')));
556
510
  await offerWatchFallback(clack, projectPath);
@@ -604,13 +558,6 @@ function main() {
604
558
  }
605
559
  catch { /* non-fatal */ }
606
560
  success(`Removed HomeGraph from ${projectPath}`);
607
- // Churn signal — and flush now, since after an uninit there may be no
608
- // "next run" to deliver it.
609
- try {
610
- (0, telemetry_1.getTelemetry)().recordLifecycle('uninstall', {});
611
- await (0, telemetry_1.getTelemetry)().flushNow();
612
- }
613
- catch { /* non-fatal */ }
614
561
  }
615
562
  catch (err) {
616
563
  error(`Failed to uninitialize: ${err instanceof Error ? err.message : String(err)}`);
@@ -682,7 +629,6 @@ function main() {
682
629
  await progress.stop();
683
630
  }
684
631
  printIndexResult(clack, result, projectPath);
685
- await recordIndexTelemetry(cg, result);
686
632
  if (!result.success) {
687
633
  process.exit(1);
688
634
  }
@@ -715,7 +661,7 @@ function main() {
715
661
  process.exit(1);
716
662
  }
717
663
  const { default: HomeGraph } = await loadHomeGraph();
718
- const cg = await HomeGraph.open(projectPath);
664
+ const cg = await HomeGraph.open(projectPath, { sources: 'both' });
719
665
  if (options.quiet) {
720
666
  await cg.sync();
721
667
  cg.destroy();
@@ -809,6 +755,7 @@ function main() {
809
755
  nodeCount: stats.nodeCount,
810
756
  edgeCount: stats.edgeCount,
811
757
  dbSizeBytes: stats.dbSizeBytes,
758
+ walSizeBytes: stats.walSizeBytes,
812
759
  backend,
813
760
  journalMode,
814
761
  nodesByKind: stats.nodesByKind,
@@ -824,6 +771,7 @@ function main() {
824
771
  ohosApi: ohosApi
825
772
  ? { version: ohosApi.version, packageName: ohosApi.packageName, dbPath: ohosApi.dbPath }
826
773
  : null,
774
+ graphSources: cg.getGraphSources(),
827
775
  index: {
828
776
  state: indexState,
829
777
  builtWithVersion: buildInfo.version,
@@ -848,6 +796,19 @@ function main() {
848
796
  console.log(` Nodes: ${formatNumber(stats.nodeCount)}`);
849
797
  console.log(` Edges: ${formatNumber(stats.edgeCount)}`);
850
798
  console.log(` DB Size: ${(stats.dbSizeBytes / 1024 / 1024).toFixed(2)} MB`);
799
+ // Surface the WAL sidecar (#1431): a WAL that dwarfs the DB at rest is
800
+ // the killed-session leak — invisible before this line, it only showed
801
+ // up as a mysteriously full disk. open() above already kicked off the
802
+ // automatic heal for the oversized case.
803
+ if (stats.walSizeBytes > 0) {
804
+ const { WAL_HEAL_THRESHOLD_BYTES } = await Promise.resolve().then(() => __importStar(require('../db/index')));
805
+ const oversized = stats.walSizeBytes > Math.max(WAL_HEAL_THRESHOLD_BYTES, stats.dbSizeBytes);
806
+ const walLabel = `${(stats.walSizeBytes / 1024 / 1024).toFixed(2)} MB`;
807
+ console.log(` WAL Size: ${oversized ? chalk.yellow(walLabel) : walLabel}`);
808
+ if (oversized) {
809
+ warn('The write-ahead log is larger than the database — killed sessions left it behind. It is reclaimed automatically on open; if it persists across runs, another live HomeGraph process is holding it.');
810
+ }
811
+ }
851
812
  // Prefer node:sqlite → better-sqlite3; wasm is last-resort (no WAL).
852
813
  const backendLabel = backend === 'node-sqlite' ? chalk.green('node-sqlite')
853
814
  : backend === 'native' ? chalk.green('native (better-sqlite3)')
@@ -857,6 +818,7 @@ function main() {
857
818
  ? chalk.green('wal')
858
819
  : chalk.yellow(`${journalMode || 'unknown'} ${(0, glyphs_1.getGlyphs)().dash} WAL inactive; reads can block on writes`);
859
820
  console.log(` Journal: ${journalLabel}`);
821
+ console.log(` Sources: ${cg.getGraphSources()} (project index / OHOS SDK API)`);
860
822
  console.log();
861
823
  // Node breakdown
862
824
  console.log(chalk.bold('Nodes by Kind:'));
@@ -1441,75 +1403,102 @@ function main() {
1441
1403
  });
1442
1404
  });
1443
1405
  /**
1444
- * homegraph serve
1406
+ * homegraph serve / homegraph serve mcp
1407
+ *
1408
+ * Preferred: `homegraph serve mcp`
1409
+ * Legacy (still supported): `homegraph serve --mcp`
1410
+ *
1411
+ * Hidden from `--help`: this is the stdio entry point an AI agent launches
1412
+ * for itself (the installer wires it into every agent's MCP config), not a
1413
+ * command a human runs. It still works when invoked — hiding only removes it
1414
+ * from the listing. See the interactive-TTY guard in `runServeMcp`, which
1415
+ * explains this to anyone who runs it by hand.
1445
1416
  */
1446
- program
1447
- // Hidden from `--help`: this is the stdio entry point an AI agent launches
1448
- // for itself (the installer wires `args: ['serve','--mcp']` into every
1449
- // agent's MCP config), not a command a human runs. It still works when
1450
- // invoked — hiding only removes it from the listing. See the interactive-TTY
1451
- // guard below, which explains this to anyone who runs it by hand.
1452
- .command('serve', { hidden: true })
1453
- .description('Start HomeGraph as an MCP server for AI assistants')
1454
- .option('-p, --path <path>', 'Project path (optional for MCP mode, uses rootUri from client)')
1455
- .option('--mcp', 'Run as MCP server (stdio transport)')
1456
- .option('--no-watch', 'Disable the file watcher (no auto-sync; useful on slow filesystems like WSL2 /mnt drives)')
1457
- .action(async (options) => {
1417
+ async function runServeMcp(options) {
1458
1418
  const projectPath = options.path ? resolveProjectPath(options.path) : undefined;
1459
1419
  // Commander sets watch=false when --no-watch is passed. Route it through
1460
1420
  // the same env-var chokepoint the watcher and MCP server already honor.
1461
1421
  if (options.watch === false) {
1462
1422
  process.env.HOMEGRAPH_NO_WATCH = '1';
1463
1423
  }
1424
+ // Spec 0005: resolve --sources over HOMEGRAPH_SOURCES, then stamp env so
1425
+ // detached daemons and in-process opens share the same mode.
1426
+ const { resolveGraphSources, applyGraphSourcesToEnv, GRAPH_SOURCES_MODES } = await Promise.resolve().then(() => __importStar(require('../graph-sources')));
1464
1427
  try {
1465
- if (options.mcp) {
1466
- // `serve --mcp` is the stdio MCP server an AI agent launches for itself,
1467
- // not a command to run by hand. A human in a terminal would otherwise
1468
- // see it hang waiting for JSON-RPC on stdin, which reads as broken. If
1469
- // stdin is an interactive TTY, explain instead of hanging. The agent's
1470
- // pipe and the detached daemon both have a non-TTY stdin, so this only
1471
- // ever fires for a person who typed it.
1472
- if (process.stdin.isTTY && !process.env.HOMEGRAPH_DAEMON_INTERNAL) {
1473
- console.error(chalk.bold('\nHomeGraph MCP server\n'));
1474
- console.error("This is the MCP server your AI agent (Claude Code, Cursor, Codex, opencode, …)");
1475
- console.error("starts automatically you don't run it yourself.");
1476
- console.error(`\nIt's already wired up by ${chalk.cyan('homegraph install')}. To check on things:`);
1477
- console.error(` ${chalk.cyan('homegraph status')} ${chalk.dim('— is this project indexed and healthy?')}`);
1478
- console.error(` ${chalk.cyan('homegraph daemon')} ${chalk.dim('— list or stop background MCP servers')}`);
1479
- console.error(chalk.dim('\n(Running it directly only does something when an MCP client drives it over stdin.)'));
1480
- return;
1481
- }
1482
- // Start MCP server - it handles initialization lazily based on rootUri from client
1483
- const { MCPServer } = await Promise.resolve().then(() => __importStar(require('../mcp/index')));
1484
- const server = new MCPServer(projectPath);
1485
- await server.start();
1486
- // Server will run until terminated
1487
- }
1488
- else {
1489
- // Default: show info about MCP mode.
1490
- // Use stderr so stdout stays clean for any piped/stdio usage.
1491
- console.error(chalk.bold('\nHomeGraph MCP Server\n'));
1492
- console.error(chalk.blue((0, glyphs_1.getGlyphs)().info) + ' Use --mcp flag to start the MCP server');
1493
- console.error('\nTo use with Claude Code, add to your MCP configuration:');
1494
- console.error(chalk.dim(`
1428
+ const mode = resolveGraphSources(options.sources);
1429
+ applyGraphSourcesToEnv(mode);
1430
+ }
1431
+ catch (err) {
1432
+ error(err instanceof Error ? err.message : String(err));
1433
+ error(`Valid values: ${GRAPH_SOURCES_MODES.join(', ')}`);
1434
+ process.exit(1);
1435
+ }
1436
+ // The stdio MCP server an AI agent launches for itself — not a command to
1437
+ // run by hand. A human in a terminal would otherwise see it hang waiting
1438
+ // for JSON-RPC on stdin. The agent's pipe and the detached daemon both
1439
+ // have a non-TTY stdin, so this only ever fires for a person who typed it.
1440
+ if (process.stdin.isTTY && !process.env.HOMEGRAPH_DAEMON_INTERNAL) {
1441
+ console.error(chalk.bold('\nHomeGraph MCP server\n'));
1442
+ console.error("This is the MCP server your AI agent (Claude Code, Cursor, Codex, opencode, )");
1443
+ console.error("starts automatically — you don't run it yourself.");
1444
+ console.error(`\nIt's already wired up by ${chalk.cyan('homegraph install')}. To check on things:`);
1445
+ console.error(` ${chalk.cyan('homegraph status')} ${chalk.dim('— is this project indexed and healthy?')}`);
1446
+ console.error(` ${chalk.cyan('homegraph daemon')} ${chalk.dim('— list or stop background MCP servers')}`);
1447
+ console.error(chalk.dim('\n(Running it directly only does something when an MCP client drives it over stdin.)'));
1448
+ return;
1449
+ }
1450
+ const { MCPServer } = await Promise.resolve().then(() => __importStar(require('../mcp/index')));
1451
+ const server = new MCPServer(projectPath);
1452
+ await server.start();
1453
+ }
1454
+ function printServeUsage() {
1455
+ // Use stderr so stdout stays clean for any piped/stdio usage.
1456
+ console.error(chalk.bold('\nHomeGraph MCP Server\n'));
1457
+ console.error(chalk.blue((0, glyphs_1.getGlyphs)().info) + ' Start with: ' + chalk.cyan('homegraph serve mcp'));
1458
+ console.error(chalk.dim(' (legacy alias also works: homegraph serve --mcp)'));
1459
+ console.error('\nTo use with Claude Code, add to your MCP configuration:');
1460
+ console.error(chalk.dim(`
1495
1461
  {
1496
1462
  "mcpServers": {
1497
1463
  "homegraph": {
1498
1464
  "command": "homegraph",
1499
- "args": ["serve", "--mcp"]
1465
+ "args": ["serve", "mcp"]
1500
1466
  }
1501
1467
  }
1502
1468
  }
1503
1469
  `));
1504
- console.error('Available tools:');
1505
- console.error(chalk.cyan(' homegraph_explore') + ' - Primary: source of the relevant symbols for any question');
1506
- console.error(chalk.cyan(' homegraph_search') + ' - Search for code symbols');
1507
- console.error(chalk.cyan(' homegraph_callers') + ' - Find callers of a symbol');
1508
- console.error(chalk.cyan(' homegraph_callees') + ' - Find what a symbol calls');
1509
- console.error(chalk.cyan(' homegraph_impact') + ' - Analyze impact of changes');
1510
- console.error(chalk.cyan(' homegraph_node') + ' - Get symbol details');
1511
- console.error(chalk.cyan(' homegraph_files') + ' - Get project file structure');
1512
- console.error(chalk.cyan(' homegraph_status') + ' - Get index status');
1470
+ console.error('Optional: --sources both|project|sdk|none (or HOMEGRAPH_SOURCES) to limit project vs OHOS SDK graphs.');
1471
+ console.error('Available tools:');
1472
+ console.error(chalk.cyan(' homegraph_explore') + ' - Primary: source of the relevant symbols for any question');
1473
+ console.error(chalk.cyan(' homegraph_search') + ' - Search for code symbols');
1474
+ console.error(chalk.cyan(' homegraph_callers') + ' - Find callers of a symbol');
1475
+ console.error(chalk.cyan(' homegraph_callees') + ' - Find what a symbol calls');
1476
+ console.error(chalk.cyan(' homegraph_impact') + ' - Analyze impact of changes');
1477
+ console.error(chalk.cyan(' homegraph_node') + ' - Get symbol details');
1478
+ console.error(chalk.cyan(' homegraph_files') + ' - Get project file structure');
1479
+ console.error(chalk.cyan(' homegraph_status') + ' - Get index status');
1480
+ }
1481
+ // IMPORTANT: keep `mcp` as an argument (not a nested Commander subcommand).
1482
+ // Nested `serve.command('mcp')` + a parent `-p/--path` made Commander 14 drop
1483
+ // `--path` on `serve mcp --path <repo>` — the daemon then keyed off cwd, so
1484
+ // prewarm/eval looked "timed out" while a useless daemon bound the wrong root.
1485
+ // `spawnDetachedDaemon` also invokes `serve mcp --path <root>`; that path must
1486
+ // stick. Legacy `serve --mcp` stays supported.
1487
+ program
1488
+ .command('serve', { hidden: true })
1489
+ .description('Start HomeGraph protocol servers for AI assistants')
1490
+ .argument('[mode]', 'Run as MCP server (stdio transport)', undefined)
1491
+ .option('-p, --path <path>', 'Project path (optional for MCP mode, uses rootUri from client)')
1492
+ .option('--mcp', 'Legacy alias for `serve mcp` (stdio MCP server)')
1493
+ .option('--no-watch', 'Disable the file watcher (no auto-sync; useful on slow filesystems like WSL2 /mnt drives)')
1494
+ .option('--sources <mode>', 'Graph sources for MCP queries: both|project|sdk|none (default both; env HOMEGRAPH_SOURCES)')
1495
+ .action(async (mode, options) => {
1496
+ try {
1497
+ if (mode === 'mcp' || options.mcp) {
1498
+ await runServeMcp(options);
1499
+ }
1500
+ else {
1501
+ printServeUsage();
1513
1502
  }
1514
1503
  }
1515
1504
  catch (err) {
@@ -2301,7 +2290,7 @@ function main() {
2301
2290
  for (const r of results) {
2302
2291
  console.log(chalk.bold(r.title));
2303
2292
  for (const commit of r.commits) {
2304
- console.log(` ${chalk.yellow(commit.hash.slice(0, 7))} ${commit.message}`);
2293
+ console.log(` ${chalk.yellow(commit.hash.slice(0, 7))} ${commit.message.split('\n', 1)[0] ?? ''}`);
2305
2294
  if (includeFragments && commit.fragments && commit.fragments.length > 0) {
2306
2295
  for (const fragment of commit.fragments.slice(0, profile.maxFragments || 3)) {
2307
2296
  console.log(chalk.dim(` ${fragment.file_path}:${fragment.start_line}-${fragment.end_line} [${fragment.change_type}]`));
@@ -2971,45 +2960,10 @@ function main() {
2971
2960
  catch { /* best effort */ }
2972
2961
  }
2973
2962
  });
2974
- /**
2975
- * homegraph telemetry [on|off|status]
2976
- */
2977
- program
2978
- .command('telemetry [action]')
2979
- .description('Show or change anonymous usage telemetry (status, on, off)')
2980
- .action((action) => {
2981
- const t = (0, telemetry_1.getTelemetry)();
2982
- if (action === 'on' || action === 'off') {
2983
- t.setEnabled(action === 'on', 'cli');
2984
- if (action === 'on') {
2985
- success('Telemetry enabled — anonymous usage stats only (no code, paths, or names).');
2986
- }
2987
- else {
2988
- success('Telemetry disabled. Buffered, unsent data was deleted.');
2989
- }
2990
- const effective = t.getStatus();
2991
- if (effective.decidedBy === 'DO_NOT_TRACK' || effective.decidedBy === 'HOMEGRAPH_TELEMETRY') {
2992
- warn(`The ${effective.decidedBy} environment variable overrides this choice — ` +
2993
- `effective state right now: ${effective.enabled ? 'enabled' : 'disabled'}.`);
2994
- }
2995
- return;
2996
- }
2997
- if (action !== undefined && action !== 'status') {
2998
- error(`Unknown action: ${action} (expected status, on, or off)`);
2999
- process.exit(1);
3000
- }
3001
- const s = t.getStatus();
3002
- const decidedBy = {
3003
- DO_NOT_TRACK: 'DO_NOT_TRACK environment variable',
3004
- HOMEGRAPH_TELEMETRY: 'HOMEGRAPH_TELEMETRY environment variable',
3005
- config: 'your saved choice',
3006
- default: 'default',
3007
- };
3008
- console.log(`\nTelemetry: ${s.enabled ? chalk.green('enabled') : chalk.yellow('disabled')} ${chalk.dim(`(${decidedBy[s.decidedBy]})`)}`);
3009
- console.log(`Machine ID: ${s.machineId ?? chalk.dim('(random UUID, created on first use)')}`);
3010
- console.log(`Config: ${s.configPath}`);
3011
- console.log(chalk.dim(`\nExactly what is collected (and never collected): ${telemetry_1.TELEMETRY_DOCS}\n`));
3012
- });
2963
+ // =============================================================================
2964
+ // Addon commands (HomeGraph addon management)
2965
+ // =============================================================================
2966
+ (0, addon_commands_1.registerAddonCommands)(program, { success, info, warn, error });
3013
2967
  /**
3014
2968
  * homegraph index-api <input> [version]
3015
2969
  * Build a standalone OHOS API database from command-line-tools SDK.
@@ -3070,9 +3024,9 @@ function main() {
3070
3024
  /**
3071
3025
  * homegraph upgrade [version]
3072
3026
  *
3073
- * Self-update, however HomeGraph was installed (bundle via install.sh/.ps1,
3074
- * npm-global, npx, or a source checkout). See ../upgrade for the detection and
3075
- * per-method upgrade logic.
3027
+ * Self-update for npm-global / npx / source installs. A leftover standalone
3028
+ * bundle install is detected and refused (guide the user to `npm i -g`).
3029
+ * See ../upgrade for detection and per-method upgrade logic.
3076
3030
  */
3077
3031
  program
3078
3032
  .command('upgrade [version]')