homegraph 1.5.8 → 1.6.0

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 (40) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/extraction/grammars.d.ts +19 -0
  3. package/dist/extraction/grammars.js +44 -1
  4. package/dist/extraction/index.js +17 -12
  5. package/dist/extraction/languages/arkts.d.ts +40 -7
  6. package/dist/extraction/languages/arkts.js +290 -84
  7. package/dist/extraction/tree-sitter.js +12 -3
  8. package/dist/index.js +23 -12
  9. package/dist/mcp/arkts-evidence-packs.js +1 -0
  10. package/dist/mcp/daemon.d.ts +21 -3
  11. package/dist/mcp/daemon.js +60 -6
  12. package/dist/mcp/engine.d.ts +26 -0
  13. package/dist/mcp/engine.js +143 -7
  14. package/dist/mcp/index-availability.d.ts +40 -10
  15. package/dist/mcp/index-availability.js +89 -23
  16. package/dist/mcp/index.js +9 -0
  17. package/dist/mcp/indexable-root.d.ts +22 -0
  18. package/dist/mcp/indexable-root.js +140 -0
  19. package/dist/mcp/liveness-watchdog.d.ts +6 -1
  20. package/dist/mcp/liveness-watchdog.js +17 -5
  21. package/dist/mcp/locate-contract.d.ts +50 -0
  22. package/dist/mcp/locate-contract.js +146 -0
  23. package/dist/mcp/server-instructions.d.ts +2 -6
  24. package/dist/mcp/server-instructions.js +15 -5
  25. package/dist/mcp/session.js +15 -0
  26. package/dist/mcp/tools.d.ts +52 -0
  27. package/dist/mcp/tools.js +750 -103
  28. package/dist/project-map/index.d.ts +45 -0
  29. package/dist/project-map/index.js +373 -45
  30. package/dist/resolution/callback-synthesizer.js +251 -0
  31. package/dist/resolution/frameworks/arkts-entry.d.ts +35 -6
  32. package/dist/resolution/frameworks/arkts-entry.js +513 -30
  33. package/dist/resolution/index.js +25 -21
  34. package/dist/runtime-log.d.ts +52 -0
  35. package/dist/runtime-log.js +199 -0
  36. package/dist/search/query-plan-provider.js +3 -2
  37. package/dist/search/query-plan.js +21 -19
  38. package/dist/search/query-utils.d.ts +13 -0
  39. package/dist/search/query-utils.js +64 -0
  40. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -10,6 +10,38 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
10
10
  ## [Unreleased]
11
11
 
12
12
 
13
+ ## [1.6.0] - 2026-09-23
14
+
15
+ ### Improvements
16
+
17
+ - MCP auto-init (Spec 0049): empty workspace roots no longer create `.homegraph/` on `--auto-init` / `HOMEGRAPH_AUTO_INIT` (fixes DevEco in-place `devecocli create` hitting `PROJECT_EXISTS` because only an index dir existed). A 60s probe (`HOMEGRAPH_DEFER_PROBE_MS`; `0` = tool-kick only) and the first `homegraph_*` call re-check `isIndexableRoot` (root `build-profile.json5` or any indexable source); once non-empty, the existing fast-map + background full index path runs once. Status footers stay the product empty/fast/full/dirty/syncing lines. Lifecycle logging no longer mkdir's `.homegraph/` just to write `daemon.log`.
18
+ - Harmony locate seams (Spec 0048): index `form_config.json` / `shortcuts_config.json` (plus module.json5 form extensionAbilities and shortcuts/form metadata) as searchable capability nodes — explore may lead with **Capability profiles**, or an explicit no-in-repo form note instead of SDK `.d.ts`. Resource hits can append in-repo `$r('app.string.<key>')` **bound** `.ets` anchors. `homegraph_project` adds a **Module roster** (oh-package + local `file:` deps) and lists capability profile paths separately from rawfile. Explore may prepend **Seam notes** for nearby profiles and empty/log-only stubs.
19
+ - MCP product lifecycle (Spec 0047): main-thread liveness watchdog is **off by default** (enable with `HOMEGRAPH_WATCHDOG=1`; `HOMEGRAPH_NO_WATCHDOG=1` still forces off) so concurrent DevEco init no longer gets false "Main thread unresponsive" kills — file watch / incremental sync unchanged. Shared daemon idle linger defaults to **60s** after the last client disconnects; if auto-init/full index is still in `building_fast`/`indexing`, idle exit waits until that build settles, then starts the 60s linger. While any client is connected the daemon never idle-exits.
20
+ - MCP runtime log (Spec 0046): always-on coarse lifecycle lines (`mcp.start` / `mcp.initialize` / `auto-init.*` / `index.*` / `watcher.degraded`) go to stderr and `.homegraph/daemon.log` (same file daemon stdio already uses); soft-rotate at ~5 MiB to `daemon.log.1`. Set `HOMEGRAPH_DEBUG=1` for per-tool summaries (`tool.<name>` with duration / error / truncated query). No new `logs/` directory; default is not a full request ledger.
21
+ - ArkUI index-time edge synthesis (Spec 0045): `build` / `@Builder` bodies that call another in-repo `@Component` / `@Builder` gain `arkui-child` edges (ambiguous names dropped); literal `pushPathByName` / `replacePathByName` / `pushNamedRoute({ name })` link to indexed `route` nodes as `arkui-named-nav`. Complements existing `arkui-route` (`pushUrl`) and Spec 0039 route_map edges — no query-time synthesis.
22
+ - Explore locate contract (Spec 0044): Chinese/UI **literal witness** files stay in the first pack and rank ahead of Logger/hilog/Toast spines unless the query names those APIs; **Located** / **Partial** / **Miss** banners (Partial next-step → `node`/`usages`/`search`, no same-name Grep); Miss omits source bodies and lists fuzzy paths; filename≠primary-declaration risk note; `homegraph_node` for symbols already on the explore locate list bypasses the Partial depth-fuse cap. Dynamic-edge synthesis (10.3) remains deferred.
23
+ - When an MCP session already has a bound default project (`--path` / opened root), a tool `projectPath` that resolves to a **different** `.homegraph/` index root is soft-pinned: HomeGraph keeps answering from the bound root and prepends a short English notice (not `isError`). Same-root nested paths are unchanged; sessions with no default project still open cross-project indexes (Spec 0043).
24
+ - In-repo locate for explore: `taskContext` no longer enters the lexical/FTS query string (quoted literals from it still merge); PascalCase identifiers (≥8 chars) seed exact file/symbol roots like `Foo.ets`; business-oriented queries default `sourceScope=local` so SDK `.d.ts` stubs do not become roots; MCP trails / used-by / evidence packs hide `@dummyFile` and `%AM*` noise. `homegraph_project` adds a bounded HarmonyOS **resources path inventory** (string.json / rawfile / media dir counts / on-disk modules with zero indexed sources) — paths only, no JSON bodies or edges (Spec 0042).
25
+ - Harmony `resources/**/element/string.json` is indexed as searchable `constant` nodes (key + UI value in FTS). Explore may lead with a short **Resource hits** table and a `$r('app.string.<key>')` Grep hint — **no** graph edges to controls. Color/media/rawfile stay out of scope (Spec 0041).
26
+ - `homegraph_project` on Harmony repos now prints a **skeleton summary**: `bundle` from `app.json5`, a note that modules come from `build-profile.json5`, per-module `route profile:` paths (`route_map` / `router_map` / `main_pages`), and `oh-package` names when present. Still no call edges or profile JSON bodies — use explore for route→page (Spec 0039) and Read to edit. Tool descriptions and MCP initialize instructions spell out project vs explore (Spec 0040).
27
+ - Harmony `route_map.json` / `router_map.json` / `main_pages.json` are indexed (basename allowlist) and linked into the graph as `route` nodes → page / `buildFunction` symbols. Edges carry `synthesizedBy: arkts-route-map` and `registeredAt` pointing at the config file so explore/trails show the JSON wiring site. When an explore query mentions those filenames, replies lead with a short **Registration sources** table — evidence from those profiles, reducing blind re-Read of the JSON (Spec 0039).
28
+ - MCP tool replies that know the indexed project now begin with `HomeGraph project root: \`<absolute>\`` plus a one-line join rule: repo-relative paths below that root should be passed to Read/Grep as-is (or `<root>/<relative>` with `/`), without inventing experiment/result prefixes. MCP initialize instructions mention the same join base. Indexed path storage stays repo-relative (Spec 0038).
29
+
30
+ ## [1.5.10] - 2026-09-20
31
+
32
+ ### Fixes
33
+
34
+ - ArkTS synthetic PROJECT modules are limited to Node `package.json` trees (e.g. hvigor plugins). Forgotten Harmony HARs that only have `oh-package.json5` / loose `.ets` outside root `build-profile.json5` are no longer registered for `analyseByModule` BODIES — on SceneBoard-scale repos that was reloading already-indexed monorepo deps into ModuleCache and inflating wall time and peak RSS. Those orphans are indexed via tree-sitter instead. Parent-dir swallow of real Harmony modules (e.g. `synthetic:feature/`) remains blocked (Spec 0036).
35
+ - After a streamed ArkTS modular batch finishes and releases the Scene, orphan `.ets` files that were never PROJECT-persisted no longer trigger a second full `analyseByModule` (the “127/127 done → starts again at 1/127” loop). They use the TypeScript tree-sitter fallback instead (Spec 0036).
36
+ - `homegraph init`/`index` reported duration now covers the full wall clock (extract + FTS rebuild + resolve/link + maintenance), not only the extraction orchestrator phase (Spec 0036).
37
+ - Harmony `build-profile.json5` files that use single-quoted strings (e.g. `'2in1'`) and bare keys now parse correctly, so multi-module ArkTS dirty sync can map changed `.ets` files to PROJECT modules instead of always falling back to a full rebuild (Spec 0034).
38
+
39
+ ### Improvements
40
+
41
+ - Bump `arkanalyzer` to **1.0.94**.
42
+ - Harmony projects with a root `build-profile.json5` now default to **serial indexing** after ArkAnalyzer: one parse worker and no resolve/synthesis worker pool. On SceneBoard-scale repos this cut peak process-tree PrivateMemory from ~8.5GB to ~3.8GB with only ~6% more wall clock. Opt out with `HOMEGRAPH_HARMONY_SERIAL=0`; force on with `=1`. Explicit `CODEGRAPH_PARSE_WORKERS` still overrides parse concurrency (Spec 0037).
43
+ - MCP product index readiness is now five short states (`empty` / `fast` / `full` / `dirty` / `syncing`): tool replies use a one-line `HomeGraph status=…` footer (or that line alone when the tool cannot answer yet). Pending edits surface as `dirty` with path list instead of the long stale banner; write locks stay `syncing`. MCP initialize includes a one-line status glossary (Spec 0035).
44
+
13
45
  ## [1.5.8] - 2026-09-15
14
46
 
15
47
  ### Improvements
@@ -240,3 +272,5 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
240
272
  [1.5.6]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.5.6
241
273
  [1.5.7]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.5.7
242
274
  [1.5.8]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.5.8
275
+ [1.5.10]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.5.10
276
+ [1.6.0]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.6.0
@@ -45,6 +45,25 @@ export declare function isErlangAppFile(filePath: string): boolean;
45
45
  export declare function isPlayRoutesFile(filePath: string): boolean;
46
46
  /** HarmonyOS module manifest — parsed by the arkts-entry framework extractor. */
47
47
  export declare function isArkModuleJson5(filePath: string): boolean;
48
+ /**
49
+ * Harmony Navigation / pages profile JSON (Spec 0039) — basename allowlist only.
50
+ * Parsed by arkts-entry; not general `.json` indexing.
51
+ */
52
+ export declare function isHarmonyRouteProfileJson(filePath: string): boolean;
53
+ /**
54
+ * Harmony element string resources (Spec 0041) — path allowlist only.
55
+ * `…/resources/…/element/string.json` (not bare string.json, not color/media).
56
+ * Indexed as yaml file-level + arkts-entry constants for FTS; no graph edges.
57
+ */
58
+ export declare function isHarmonyElementStringJson(filePath: string): boolean;
59
+ /**
60
+ * Harmony capability profiles (Spec 0048) — basename allowlist only.
61
+ * `form_config.json` (service widgets) and `shortcuts_config.json` (home-screen shortcuts).
62
+ * Indexed as yaml + arkts-entry constants; no UI call edges.
63
+ */
64
+ export declare function isHarmonyCapabilityProfileJson(filePath: string): boolean;
65
+ /** Config files that host ArkTS `route` nodes (module manifest + Spec 0039 profiles). */
66
+ export declare function isHarmonyRouteConfigFile(filePath: string): boolean;
48
67
  /**
49
68
  * Initialize the tree-sitter WASM runtime. Must be called before loading grammars.
50
69
  * Does NOT load any grammar WASM files — use loadGrammarsForLanguages() for that.
@@ -46,6 +46,10 @@ exports.isShopifyLiquidJson = isShopifyLiquidJson;
46
46
  exports.isErlangAppFile = isErlangAppFile;
47
47
  exports.isPlayRoutesFile = isPlayRoutesFile;
48
48
  exports.isArkModuleJson5 = isArkModuleJson5;
49
+ exports.isHarmonyRouteProfileJson = isHarmonyRouteProfileJson;
50
+ exports.isHarmonyElementStringJson = isHarmonyElementStringJson;
51
+ exports.isHarmonyCapabilityProfileJson = isHarmonyCapabilityProfileJson;
52
+ exports.isHarmonyRouteConfigFile = isHarmonyRouteConfigFile;
49
53
  exports.initGrammars = initGrammars;
50
54
  exports.vendoredWasmFilenames = vendoredWasmFilenames;
51
55
  exports.readGrammarWasmBytes = readGrammarWasmBytes;
@@ -235,6 +239,12 @@ function isSourceFile(filePath, overrides) {
235
239
  return true; // Play `conf/routes` is extensionless
236
240
  if (isArkModuleJson5(filePath))
237
241
  return true;
242
+ if (isHarmonyRouteProfileJson(filePath))
243
+ return true; // Spec 0039
244
+ if (isHarmonyElementStringJson(filePath))
245
+ return true; // Spec 0041
246
+ if (isHarmonyCapabilityProfileJson(filePath))
247
+ return true; // Spec 0048
238
248
  if (isShopifyLiquidJson(filePath))
239
249
  return true; // Shopify OS 2.0 JSON templates / section groups
240
250
  if (isErlangAppFile(filePath))
@@ -280,6 +290,35 @@ function isPlayRoutesFile(filePath) {
280
290
  function isArkModuleJson5(filePath) {
281
291
  return filePath.endsWith('module.json5');
282
292
  }
293
+ /**
294
+ * Harmony Navigation / pages profile JSON (Spec 0039) — basename allowlist only.
295
+ * Parsed by arkts-entry; not general `.json` indexing.
296
+ */
297
+ function isHarmonyRouteProfileJson(filePath) {
298
+ const base = filePath.replace(/\\/g, '/').split('/').pop()?.toLowerCase() ?? '';
299
+ return base === 'route_map.json' || base === 'router_map.json' || base === 'main_pages.json';
300
+ }
301
+ /**
302
+ * Harmony element string resources (Spec 0041) — path allowlist only.
303
+ * `…/resources/…/element/string.json` (not bare string.json, not color/media).
304
+ * Indexed as yaml file-level + arkts-entry constants for FTS; no graph edges.
305
+ */
306
+ function isHarmonyElementStringJson(filePath) {
307
+ return /(?:^|\/)resources\/(?:[^/]+\/)*element\/string\.json$/i.test(filePath.replace(/\\/g, '/'));
308
+ }
309
+ /**
310
+ * Harmony capability profiles (Spec 0048) — basename allowlist only.
311
+ * `form_config.json` (service widgets) and `shortcuts_config.json` (home-screen shortcuts).
312
+ * Indexed as yaml + arkts-entry constants; no UI call edges.
313
+ */
314
+ function isHarmonyCapabilityProfileJson(filePath) {
315
+ const base = filePath.replace(/\\/g, '/').split('/').pop()?.toLowerCase() ?? '';
316
+ return base === 'form_config.json' || base === 'shortcuts_config.json';
317
+ }
318
+ /** Config files that host ArkTS `route` nodes (module manifest + Spec 0039 profiles). */
319
+ function isHarmonyRouteConfigFile(filePath) {
320
+ return isArkModuleJson5(filePath) || isHarmonyRouteProfileJson(filePath);
321
+ }
283
322
  /**
284
323
  * Caches for loaded grammars and parsers
285
324
  */
@@ -450,8 +489,12 @@ function detectLanguage(filePath, source, overrides) {
450
489
  return 'yaml';
451
490
  if (isArkModuleJson5(filePath))
452
491
  return 'yaml';
453
- if (isArkModuleJson5(filePath))
492
+ if (isHarmonyRouteProfileJson(filePath))
454
493
  return 'yaml';
494
+ if (isHarmonyElementStringJson(filePath))
495
+ return 'yaml'; // Spec 0041
496
+ if (isHarmonyCapabilityProfileJson(filePath))
497
+ return 'yaml'; // Spec 0048
455
498
  const ext = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();
456
499
  // Shopify OS 2.0 JSON templates / section groups → the Liquid extractor (it
457
500
  // links each section `"type"` to its `sections/<type>.liquid`).
@@ -1475,17 +1475,25 @@ class ExtractionOrchestrator {
1475
1475
  await (0, arkts_1.primeArkTSBatch)(this.rootDir, this.queries, firstEtsFile);
1476
1476
  errors.push(...(0, arkts_1.drainArkTSIndexNotices)());
1477
1477
  }
1478
- // Start parse pool only after Scene teardown — most .ets are already in DB.
1479
- const remainingToParse = files.filter((f) => !((0, arkts_1.isArkTSBatchPersisted)(f) || ((0, arkts_1.isArkTSBatchCommitted)() && (0, arkts_1.isArkAnalyzerSourcePath)(f)))).length;
1478
+ // Start parse pool only after Scene teardown — AA-persisted .ets are already
1479
+ // in DB. Ark sources that never entered a PROJECT module (forgotten HARs /
1480
+ // packageless orphans) are NOT skipped here — they fall through to tree-sitter.
1481
+ const remainingToParse = files.filter((f) => !(0, arkts_1.isArkTSBatchPersisted)(f)).length;
1480
1482
  if (useWorker) {
1481
1483
  // CODEGRAPH_PARSE_WORKERS: explicit worker count; 1 = the old single-worker
1482
1484
  // behaviour (the conservative rollback). Unset → clamp(cores-1, 1, 8).
1485
+ // Harmony modular repos default to 1 worker (Spec 0037) unless overridden.
1483
1486
  let poolSize = (0, parse_pool_1.resolveParsePoolSize)(process.env.CODEGRAPH_PARSE_WORKERS, os.cpus().length);
1484
- if (!process.env.CODEGRAPH_PARSE_WORKERS?.trim() && remainingToParse < 500) {
1485
- poolSize = Math.min(poolSize, 2);
1486
- }
1487
- else if (!process.env.CODEGRAPH_PARSE_WORKERS?.trim() && remainingToParse < 2000) {
1488
- poolSize = Math.min(poolSize, 4);
1487
+ if (!process.env.CODEGRAPH_PARSE_WORKERS?.trim()) {
1488
+ if ((0, arkts_1.preferHarmonySerialIndexing)(this.rootDir)) {
1489
+ poolSize = 1;
1490
+ }
1491
+ else if (remainingToParse < 500) {
1492
+ poolSize = Math.min(poolSize, 2);
1493
+ }
1494
+ else if (remainingToParse < 2000) {
1495
+ poolSize = Math.min(poolSize, 4);
1496
+ }
1489
1497
  }
1490
1498
  pool = new parse_pool_1.ParseWorkerPool({
1491
1499
  languages: neededLanguages,
@@ -1523,8 +1531,7 @@ class ExtractionOrchestrator {
1523
1531
  const batch = files.slice(i, i + FILE_IO_BATCH_SIZE);
1524
1532
  // Read files in parallel (with path validation before any I/O)
1525
1533
  const fileContents = await Promise.all(batch.map(async (fp) => {
1526
- if ((0, arkts_1.isArkTSBatchPersisted)(fp) ||
1527
- ((0, arkts_1.isArkTSBatchCommitted)() && (0, arkts_1.isArkAnalyzerSourcePath)(fp))) {
1534
+ if ((0, arkts_1.isArkTSBatchPersisted)(fp)) {
1528
1535
  return {
1529
1536
  filePath: fp,
1530
1537
  content: null,
@@ -1559,9 +1566,7 @@ class ExtractionOrchestrator {
1559
1566
  aborted = true;
1560
1567
  break;
1561
1568
  }
1562
- if ((0, arkts_1.isArkTSBatchPersisted)(filePath) ||
1563
- arktsBatchSkipped ||
1564
- ((0, arkts_1.isArkTSBatchCommitted)() && (0, arkts_1.isArkAnalyzerSourcePath)(filePath))) {
1569
+ if ((0, arkts_1.isArkTSBatchPersisted)(filePath) || arktsBatchSkipped) {
1565
1570
  processed++;
1566
1571
  filesIndexed++;
1567
1572
  onProgress?.({ phase: 'parsing', current: processed, total, currentFile: filePath });
@@ -49,6 +49,16 @@ export declare function buildArkMethodSignatureFields(method: ArkMethod): {
49
49
  * the indexer (rare Photos-scale Windows cases).
50
50
  */
51
51
  export declare function shouldUseIsolatedArkTSBuild(): boolean;
52
+ /**
53
+ * Default to serial parse + no resolve worker pool on Harmony modular repos.
54
+ * analyseByModule dominates wall clock; worker pools mainly spike peak RSS after
55
+ * Scene release (Spec 0037). Explicit CODEGRAPH_PARSE_WORKERS still wins when set.
56
+ *
57
+ * - unset: true iff root `build-profile.json5` exists
58
+ * - `HOMEGRAPH_HARMONY_SERIAL=0`/`false`: never
59
+ * - `HOMEGRAPH_HARMONY_SERIAL=1`/`true`: always
60
+ */
61
+ export declare function preferHarmonySerialIndexing(rootDir: string): boolean;
52
62
  /** One PROJECT module from root `build-profile.json5`. */
53
63
  export interface HarmonyModuleRef {
54
64
  name: string;
@@ -63,19 +73,38 @@ export declare function normalizeHarmonyModuleSrcPath(srcPath: string): string;
63
73
  */
64
74
  export declare function listHarmonyProjectModules(rootDir: string): HarmonyModuleRef[];
65
75
  /**
66
- * Nearest package-like directory for an orphan Ark source, or the first path
67
- * segment. Never returns the project root (registering `.` would re-scan every
68
- * Harmony module). Lone files directly under the root return null.
76
+ * True when registering `srcPath` as a synthetic PROJECT would re-load real
77
+ * Harmony modules: exact path collision, or a parent of existing `srcPath`s
78
+ * (e.g. synthetic `feature/` swallowing `feature/appcenter`).
69
79
  */
70
- export declare function findSyntheticArkModuleRoot(rootDir: string, relFile: string): string | null;
80
+ export declare function syntheticRootConflictsWithHarmonyModules(srcPath: string, modules: readonly HarmonyModuleRef[]): boolean;
81
+ /**
82
+ * Nearest **Node** `package.json` directory for an orphan Ark/TS source.
83
+ * Never returns the project root (registering `.` would re-scan every Harmony
84
+ * module). Lone files directly under the root return null.
85
+ *
86
+ * Only `package.json` counts — not `oh-package.json5`. Forgotten Harmony HARs
87
+ * left out of root `build-profile.json5` (scene_board `feature/visionglass`
88
+ * etc.) often declare heavy `file:`/`../` deps on modules already indexed as
89
+ * real PROJECT modules; registering them as synthetic PROJECT→BODIES reloads
90
+ * those deps into ModuleCache and spikes wall time + RSS for almost no unique
91
+ * coverage. Those orphans fall through to tree-sitter instead.
92
+ *
93
+ * When `harmonyModules` is provided, skips roots that would swallow those
94
+ * modules (e.g. a plugin under `feature/intelligent` must not become
95
+ * `synthetic:feature/` and re-BODIES the whole `feature/` tree).
96
+ */
97
+ export declare function findSyntheticArkModuleRoot(rootDir: string, relFile: string, harmonyModules?: readonly HarmonyModuleRef[]): string | null;
71
98
  /**
72
99
  * ArkAnalyzer sources under `scannedFiles` that are not inside any
73
100
  * build-profile PROJECT module `srcPath`.
74
101
  */
75
102
  export declare function listOrphanArkAnalyzerSources(scannedFiles: Iterable<string>, harmonyModules: HarmonyModuleRef[]): string[];
76
103
  /**
77
- * Cluster orphan `.ets`/`.ts`/`.d.ts` into synthetic PROJECT module roots
78
- * (e.g. `HMRouterPlugin` for a Node hvigor plugin living beside HAP modules).
104
+ * Cluster orphan `.ets`/`.ts`/`.d.ts` into synthetic PROJECT module roots for
105
+ * Node-style packages only (`package.json`, e.g. HMRouterPlugin). Harmony
106
+ * `oh-package.json5` trees omitted from build-profile are not registered —
107
+ * analyseByModule would re-SIGNATURES their monorepo deps at high RSS cost.
79
108
  */
80
109
  export declare function listSyntheticArkModuleRoots(rootDir: string, scannedFiles: Iterable<string>, harmonyModules?: HarmonyModuleRef[]): HarmonyModuleRef[];
81
110
  export type DirtyHarmonyModuleResolution = {
@@ -273,7 +302,11 @@ export interface BindOhosApiDbOptions extends EnsureOhosApiDbOptions {
273
302
  /** Prefix applied to API db node file paths so explore can render without disk reads. */
274
303
  export declare function markOhosApiFilePath(relativePath: string): string;
275
304
  export declare function isOhosApiFilePath(filePath: string): boolean;
276
- /** Strip json5 comments/trailing commas enough for compileSdkVersion extraction. */
305
+ /**
306
+ * DevEco / Harmony JSON5 subset → JSON.parse.
307
+ * Supports: line/block comments, trailing commas, bare keys, single-quoted strings
308
+ * (e.g. deviceTypes: ['phone', '2in1']). Not a full JSON5 implementation.
309
+ */
277
310
  export declare function parseJson5Minimal(text: string): unknown;
278
311
  /** Normalize compileSdkVersion values like "6.0.1(21)" → "6.0.1". */
279
312
  export declare function normalizeOhosApiVersion(raw: unknown): string | null;