homegraph 1.5.8 → 1.5.10

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.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,21 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
10
10
  ## [Unreleased]
11
11
 
12
12
 
13
+ ## [1.5.10] - 2026-09-20
14
+
15
+ ### Fixes
16
+
17
+ - 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).
18
+ - 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).
19
+ - `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).
20
+ - 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).
21
+
22
+ ### Improvements
23
+
24
+ - Bump `arkanalyzer` to **1.0.94**.
25
+ - 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).
26
+ - 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).
27
+
13
28
  ## [1.5.8] - 2026-09-15
14
29
 
15
30
  ### Improvements
@@ -240,3 +255,4 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
240
255
  [1.5.6]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.5.6
241
256
  [1.5.7]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.5.7
242
257
  [1.5.8]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.5.8
258
+ [1.5.10]: https://github.com/fujiaxin-coder/homegraph/releases/tag/v1.5.10
@@ -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;