@quolu/lattice 0.52.0 → 0.52.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 (182) hide show
  1. package/LICENSE +147 -147
  2. package/README.ja.md +355 -355
  3. package/README.md +258 -258
  4. package/bin/lattice-mcp.mjs +0 -0
  5. package/bin/lattice-scripted-adapter.mjs +0 -0
  6. package/bin/lattice-scripted-worker.mjs +0 -0
  7. package/bin/lattice-work-order-adapter.mjs +0 -0
  8. package/bin/lattice.mjs +0 -0
  9. package/docs/bridge-setup.md +132 -132
  10. package/docs/schemas/lattice.executor_packet.v1.schema.json +57 -57
  11. package/docs/schemas/lattice.executor_receipt.v1.schema.json +66 -66
  12. package/docs/schemas/lattice.phase_todo_revision.v3.schema.json +360 -360
  13. package/docs/schemas/lattice.plan_create_input.v1.schema.json +56 -56
  14. package/docs/schemas/lattice.plan_create_input.v2.schema.json +72 -72
  15. package/docs/schemas/lattice.plan_create_input.v3.schema.json +81 -81
  16. package/docs/schemas/lattice.plan_create_input.v4.schema.json +85 -85
  17. package/docs/schemas/lattice.run_request.v1.schema.json +238 -238
  18. package/docs/schemas/lattice.runtime_adapter_capabilities.v2.schema.json +55 -55
  19. package/docs/schemas/lattice.runtime_adapter_registration_input.v1.schema.json +78 -78
  20. package/docs/schemas/lattice.runtime_adapter_registration_input.v2.schema.json +86 -86
  21. package/docs/schemas/lattice.todo_extraction.v2.schema.json +298 -298
  22. package/docs/schemas/lattice.todo_extraction.v3.schema.json +146 -146
  23. package/docs/schemas/lattice.todo_revision.v2.schema.json +260 -260
  24. package/docs/schemas/lattice.todo_revision_set.v3.schema.json +363 -363
  25. package/package.json +103 -103
  26. package/sensor/LICENSE +21 -21
  27. package/sensor/NOTICE +19 -19
  28. package/sensor/dist/bin/lattice-sensor.js +9 -9
  29. package/sensor/dist/db/index.js +24 -24
  30. package/sensor/dist/db/migrations.js +41 -41
  31. package/sensor/dist/db/queries.js +164 -164
  32. package/sensor/dist/db/schema.sql +205 -205
  33. package/sensor/dist/directory.js +5 -5
  34. package/sensor/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
  35. package/sensor/dist/extraction/wasm/tree-sitter-cfml.wasm +0 -0
  36. package/sensor/dist/extraction/wasm/tree-sitter-cfquery.wasm +0 -0
  37. package/sensor/dist/extraction/wasm/tree-sitter-cfscript.wasm +0 -0
  38. package/sensor/dist/extraction/wasm/tree-sitter-cobol.wasm +0 -0
  39. package/sensor/dist/extraction/wasm/tree-sitter-erlang.wasm +0 -0
  40. package/sensor/dist/extraction/wasm/tree-sitter-go.wasm +0 -0
  41. package/sensor/dist/extraction/wasm/tree-sitter-java.wasm +0 -0
  42. package/sensor/dist/extraction/wasm/tree-sitter-javascript.wasm +0 -0
  43. package/sensor/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
  44. package/sensor/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  45. package/sensor/dist/extraction/wasm/tree-sitter-python.wasm +0 -0
  46. package/sensor/dist/extraction/wasm/tree-sitter-tsx.wasm +0 -0
  47. package/sensor/dist/extraction/wasm/tree-sitter-typescript.wasm +0 -0
  48. package/sensor/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
  49. package/sensor/dist/mcp/liveness-watchdog.js +53 -53
  50. package/sensor/dist/mcp/server-instructions.js +95 -95
  51. package/sensor/package.json +56 -56
  52. package/src/artifact-contracts-v2.mjs +325 -325
  53. package/src/artifact-contracts.mjs +895 -895
  54. package/src/boundary-compiler.mjs +712 -712
  55. package/src/boundary-observation-compiler-v2.mjs +344 -344
  56. package/src/bounded-seam.mjs +230 -230
  57. package/src/bridge-address.mjs +107 -107
  58. package/src/bridge-cli.mjs +297 -297
  59. package/src/bridge-config.mjs +346 -346
  60. package/src/bridge-daemon.mjs +378 -378
  61. package/src/bridge-launch-agent.mjs +323 -323
  62. package/src/bridge-registrar.mjs +102 -102
  63. package/src/bridge-server.mjs +376 -376
  64. package/src/cli-help.mjs +308 -308
  65. package/src/cli-stdio.mjs +40 -40
  66. package/src/control-compiler.mjs +532 -532
  67. package/src/dag-chain.mjs +261 -261
  68. package/src/factory-diagnostics.mjs +188 -188
  69. package/src/hash-chain.mjs +76 -76
  70. package/src/hooks-cli.mjs +1057 -1053
  71. package/src/isolation-runner.mjs +409 -409
  72. package/src/node-version-guard.mjs +44 -44
  73. package/src/project-cli.mjs +697 -697
  74. package/src/project-identity.mjs +130 -130
  75. package/src/rc1-black-box-oracle.mjs +906 -906
  76. package/src/rc1-comparison.mjs +154 -154
  77. package/src/rc1-evidence-bundle.mjs +456 -456
  78. package/src/rc1-v4-campaign.mjs +708 -708
  79. package/src/rc1-v4-transform.mjs +467 -467
  80. package/src/rc1-v5-artifact-set.mjs +855 -855
  81. package/src/rc1-v5-behavior-evidence.mjs +594 -594
  82. package/src/rc1-v5-campaign.mjs +797 -797
  83. package/src/rc1-v5-transform.mjs +421 -421
  84. package/src/rc1-v6-artifact-set.mjs +807 -807
  85. package/src/rc1-v6-behavior-evidence.mjs +273 -273
  86. package/src/rc1-v6-campaign.mjs +623 -623
  87. package/src/rc1-v6-causal-binding.mjs +473 -473
  88. package/src/rc1-v6-measurement.mjs +313 -313
  89. package/src/rc2-artifact-set.mjs +1584 -1584
  90. package/src/rc2-campaign.mjs +1506 -1502
  91. package/src/rc2-delivery-policy-front-end.mjs +1079 -1079
  92. package/src/rc2-delivery-policy-oracle.mjs +134 -134
  93. package/src/rc2-delivery-policy-transform.mjs +1127 -1127
  94. package/src/rc2-rc1-transfer-front-end.mjs +511 -511
  95. package/src/rc3-actual-dogfood.mjs +652 -652
  96. package/src/rc3-dogfood-scaffold.mjs +315 -315
  97. package/src/rc3-scripted-campaign.mjs +1383 -1383
  98. package/src/rc4-stage1-dogfood.mjs +673 -673
  99. package/src/runtime-adapter-registry.mjs +524 -520
  100. package/src/runtime-cli.mjs +4588 -4584
  101. package/src/runtime-contracts.mjs +824 -824
  102. package/src/runtime-control-store.mjs +604 -600
  103. package/src/runtime-controller-protocol.mjs +587 -587
  104. package/src/runtime-decision-verifier.mjs +701 -701
  105. package/src/runtime-diff-observer.mjs +361 -361
  106. package/src/runtime-direct-os-observer.mjs +301 -301
  107. package/src/runtime-driver-state.mjs +166 -162
  108. package/src/runtime-engine.mjs +779 -779
  109. package/src/runtime-errors.mjs +356 -356
  110. package/src/runtime-event-store.mjs +189 -189
  111. package/src/runtime-front-end.mjs +925 -925
  112. package/src/runtime-gate-store.mjs +481 -477
  113. package/src/runtime-hold-recompile.mjs +916 -916
  114. package/src/runtime-io-sentinel.mjs +391 -391
  115. package/src/runtime-lifecycle-lock.mjs +294 -290
  116. package/src/runtime-managed-supervisor.mjs +1490 -1490
  117. package/src/runtime-multi-epoch-store.mjs +838 -834
  118. package/src/runtime-projection.mjs +269 -269
  119. package/src/runtime-pull-intake.mjs +1192 -1188
  120. package/src/runtime-scripted-adapter-controller.mjs +1160 -1156
  121. package/src/runtime-scripted-executor.mjs +163 -163
  122. package/src/runtime-scripted-worktree.mjs +104 -104
  123. package/src/runtime-seam-resolve.mjs +428 -428
  124. package/src/runtime-seam-treatment.mjs +173 -173
  125. package/src/runtime-socket-owner.mjs +125 -125
  126. package/src/runtime-work-order-contracts.mjs +91 -91
  127. package/src/runtime-work-order-controller.mjs +1171 -1167
  128. package/src/runtime-worktree-executor.mjs +199 -199
  129. package/src/schedulability-compiler-v2.mjs +303 -303
  130. package/src/schedulability-verifier-v2.mjs +317 -317
  131. package/src/seam-apply.mjs +549 -549
  132. package/src/seam-commit-shared.mjs +22 -22
  133. package/src/seam-commit-transform.mjs +81 -81
  134. package/src/seam-commit.mjs +18 -18
  135. package/src/seam-cost.mjs +322 -322
  136. package/src/seam-derivation.mjs +188 -188
  137. package/src/seam-gate.mjs +146 -146
  138. package/src/seam-proposal-contracts.mjs +446 -446
  139. package/src/seam-proposal-queries.mjs +521 -521
  140. package/src/seam-proposal.mjs +2011 -2011
  141. package/src/seam-ref.mjs +33 -33
  142. package/src/seam-rewrite.mjs +286 -286
  143. package/src/seam-transform.mjs +554 -554
  144. package/src/seam-verification.mjs +260 -260
  145. package/src/sensor-adapter.mjs +432 -432
  146. package/src/sensor-cli.mjs +139 -139
  147. package/src/sensor-diff.mjs +661 -661
  148. package/src/sensor-node-runtime.mjs +53 -53
  149. package/src/sensor-runtime.mjs +52 -52
  150. package/src/timestamp-contract.mjs +8 -8
  151. package/src/todo-audit-pending.mjs +91 -91
  152. package/src/todo-chain.mjs +178 -178
  153. package/src/todo-cli.mjs +3141 -3126
  154. package/src/todo-contracts.mjs +728 -728
  155. package/src/todo-dashboard-registry.mjs +573 -573
  156. package/src/todo-dispatch-shape.mjs +190 -190
  157. package/src/todo-gantt-html-independence.mjs +239 -239
  158. package/src/todo-gantt-html-shared.mjs +226 -226
  159. package/src/todo-gantt-html-style.mjs +131 -131
  160. package/src/todo-gantt-html.mjs +248 -248
  161. package/src/todo-gantt-layout.mjs +974 -974
  162. package/src/todo-gantt-live.mjs +361 -361
  163. package/src/todo-gantt-nested.mjs +263 -263
  164. package/src/todo-gantt-presentation.mjs +217 -217
  165. package/src/todo-gantt-scope.mjs +123 -123
  166. package/src/todo-gantt-svg.mjs +353 -353
  167. package/src/todo-independence-contracts.mjs +595 -595
  168. package/src/todo-independence-guidance.mjs +322 -322
  169. package/src/todo-independence.mjs +640 -640
  170. package/src/todo-markdown-renderer.mjs +260 -260
  171. package/src/todo-migration.mjs +448 -448
  172. package/src/todo-narrative-anchor.mjs +130 -130
  173. package/src/todo-note-store.mjs +629 -625
  174. package/src/todo-parallel-candidates.mjs +114 -114
  175. package/src/todo-revision.mjs +995 -995
  176. package/src/todo-split.mjs +472 -472
  177. package/src/todo-status.mjs +690 -690
  178. package/src/todo-store-git-transaction.mjs +418 -418
  179. package/src/todo-store.mjs +4322 -4314
  180. package/src/treatment-compiler.mjs +728 -728
  181. package/src/treatment-runner.mjs +656 -656
  182. package/src/witness-scaffold.mjs +180 -180
@@ -265,20 +265,20 @@ class QueryBuilder {
265
265
  */
266
266
  insertNode(node) {
267
267
  if (!this.stmts.insertNode) {
268
- this.stmts.insertNode = this.db.prepare(`
269
- INSERT OR REPLACE INTO nodes (
270
- id, kind, name, qualified_name, file_path, language,
271
- start_line, end_line, start_column, end_column,
272
- docstring, signature, visibility,
273
- is_exported, is_async, is_static, is_abstract,
274
- decorators, type_parameters, return_type, extent_start_line, updated_at
275
- ) VALUES (
276
- @id, @kind, @name, @qualifiedName, @filePath, @language,
277
- @startLine, @endLine, @startColumn, @endColumn,
278
- @docstring, @signature, @visibility,
279
- @isExported, @isAsync, @isStatic, @isAbstract,
280
- @decorators, @typeParameters, @returnType, @extentStartLine, @updatedAt
281
- )
268
+ this.stmts.insertNode = this.db.prepare(`
269
+ INSERT OR REPLACE INTO nodes (
270
+ id, kind, name, qualified_name, file_path, language,
271
+ start_line, end_line, start_column, end_column,
272
+ docstring, signature, visibility,
273
+ is_exported, is_async, is_static, is_abstract,
274
+ decorators, type_parameters, return_type, extent_start_line, updated_at
275
+ ) VALUES (
276
+ @id, @kind, @name, @qualifiedName, @filePath, @language,
277
+ @startLine, @endLine, @startColumn, @endColumn,
278
+ @docstring, @signature, @visibility,
279
+ @isExported, @isAsync, @isStatic, @isAbstract,
280
+ @decorators, @typeParameters, @returnType, @extentStartLine, @updatedAt
281
+ )
282
282
  `);
283
283
  }
284
284
  // Validate required fields to prevent SQLite bind errors
@@ -396,12 +396,12 @@ class QueryBuilder {
396
396
  if (this.isSegmentableKind(node.kind))
397
397
  this.collectNameSegmentRows(node.name, segmentRows);
398
398
  }
399
- this.runBatched('insertNodes', `INSERT OR REPLACE INTO nodes (
400
- id, kind, name, qualified_name, file_path, language,
401
- start_line, end_line, start_column, end_column,
402
- docstring, signature, visibility,
403
- is_exported, is_async, is_static, is_abstract,
404
- decorators, type_parameters, return_type, extent_start_line, updated_at
399
+ this.runBatched('insertNodes', `INSERT OR REPLACE INTO nodes (
400
+ id, kind, name, qualified_name, file_path, language,
401
+ start_line, end_line, start_column, end_column,
402
+ docstring, signature, visibility,
403
+ is_exported, is_async, is_static, is_abstract,
404
+ decorators, type_parameters, return_type, extent_start_line, updated_at
405
405
  ) VALUES `, '(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', rows);
406
406
  this.runBatched('insertNameSegments', 'INSERT OR IGNORE INTO name_segment_vocab (segment, name) VALUES ', '(?,?)', segmentRows);
407
407
  })();
@@ -460,30 +460,30 @@ class QueryBuilder {
460
460
  */
461
461
  updateNode(node) {
462
462
  if (!this.stmts.updateNode) {
463
- this.stmts.updateNode = this.db.prepare(`
464
- UPDATE nodes SET
465
- kind = @kind,
466
- name = @name,
467
- qualified_name = @qualifiedName,
468
- file_path = @filePath,
469
- language = @language,
470
- start_line = @startLine,
471
- end_line = @endLine,
472
- start_column = @startColumn,
473
- end_column = @endColumn,
474
- docstring = @docstring,
475
- signature = @signature,
476
- visibility = @visibility,
477
- is_exported = @isExported,
478
- is_async = @isAsync,
479
- is_static = @isStatic,
480
- is_abstract = @isAbstract,
481
- decorators = @decorators,
482
- type_parameters = @typeParameters,
483
- return_type = @returnType,
484
- extent_start_line = @extentStartLine,
485
- updated_at = @updatedAt
486
- WHERE id = @id
463
+ this.stmts.updateNode = this.db.prepare(`
464
+ UPDATE nodes SET
465
+ kind = @kind,
466
+ name = @name,
467
+ qualified_name = @qualifiedName,
468
+ file_path = @filePath,
469
+ language = @language,
470
+ start_line = @startLine,
471
+ end_line = @endLine,
472
+ start_column = @startColumn,
473
+ end_column = @endColumn,
474
+ docstring = @docstring,
475
+ signature = @signature,
476
+ visibility = @visibility,
477
+ is_exported = @isExported,
478
+ is_async = @isAsync,
479
+ is_static = @isStatic,
480
+ is_abstract = @isAbstract,
481
+ decorators = @decorators,
482
+ type_parameters = @typeParameters,
483
+ return_type = @returnType,
484
+ extent_start_line = @extentStartLine,
485
+ updated_at = @updatedAt
486
+ WHERE id = @id
487
487
  `);
488
488
  }
489
489
  // Invalidate cache before update
@@ -607,12 +607,12 @@ class QueryBuilder {
607
607
  const placeholders = variants.map(() => '?').join(', ');
608
608
  const whens = variants.map(() => 'WHEN ? THEN ?').join(' ');
609
609
  const rows = this.db
610
- .prepare(`SELECT name, COUNT(DISTINCT CASE segment ${whens} END) AS matches
611
- FROM name_segment_vocab
612
- WHERE segment IN (${placeholders})
613
- GROUP BY name
614
- HAVING matches >= ?
615
- ORDER BY matches DESC, length(name) ASC
610
+ .prepare(`SELECT name, COUNT(DISTINCT CASE segment ${whens} END) AS matches
611
+ FROM name_segment_vocab
612
+ WHERE segment IN (${placeholders})
613
+ GROUP BY name
614
+ HAVING matches >= ?
615
+ ORDER BY matches DESC, length(name) ASC
616
616
  LIMIT ?`)
617
617
  .all(...variants.flatMap((v) => [v.segment, v.word]), ...variants.map((v) => v.segment), minWords, limit);
618
618
  return rows;
@@ -624,7 +624,7 @@ class QueryBuilder {
624
624
  return new Map();
625
625
  const placeholders = segments.map(() => '?').join(', ');
626
626
  const rows = this.db
627
- .prepare(`SELECT segment, COUNT(*) AS n FROM name_segment_vocab
627
+ .prepare(`SELECT segment, COUNT(*) AS n FROM name_segment_vocab
628
628
  WHERE segment IN (${placeholders}) GROUP BY segment`)
629
629
  .all(...segments);
630
630
  return new Map(rows.map((r) => [r.segment, r.n]));
@@ -784,15 +784,15 @@ class QueryBuilder {
784
784
  // protobuf stub) outranks the real `server/etcdserver/server.go`
785
785
  // (470 edges) by 4×, and the boost would push the agent toward
786
786
  // generated code.
787
- this.stmts.getDominantFile = this.db.prepare(`
788
- SELECT n.file_path AS file_path, COUNT(*) AS edge_count
789
- FROM edges e
790
- JOIN nodes n ON e.source = n.id
791
- JOIN nodes m ON e.target = m.id
792
- WHERE n.file_path = m.file_path
793
- GROUP BY n.file_path
794
- ORDER BY edge_count DESC
795
- LIMIT 20
787
+ this.stmts.getDominantFile = this.db.prepare(`
788
+ SELECT n.file_path AS file_path, COUNT(*) AS edge_count
789
+ FROM edges e
790
+ JOIN nodes n ON e.source = n.id
791
+ JOIN nodes m ON e.target = m.id
792
+ WHERE n.file_path = m.file_path
793
+ GROUP BY n.file_path
794
+ ORDER BY edge_count DESC
795
+ LIMIT 20
796
796
  `);
797
797
  }
798
798
  const rows = this.stmts.getDominantFile.all();
@@ -819,13 +819,13 @@ class QueryBuilder {
819
819
  */
820
820
  getTopRouteFile() {
821
821
  if (!this.stmts.getTopRouteFile) {
822
- this.stmts.getTopRouteFile = this.db.prepare(`
823
- SELECT file_path, COUNT(*) AS cnt
824
- FROM nodes
825
- WHERE kind = 'route'
826
- GROUP BY file_path
827
- ORDER BY cnt DESC
828
- LIMIT 20
822
+ this.stmts.getTopRouteFile = this.db.prepare(`
823
+ SELECT file_path, COUNT(*) AS cnt
824
+ FROM nodes
825
+ WHERE kind = 'route'
826
+ GROUP BY file_path
827
+ ORDER BY cnt DESC
828
+ LIMIT 20
829
829
  `);
830
830
  }
831
831
  const rows = this.stmts.getTopRouteFile.all();
@@ -856,21 +856,21 @@ class QueryBuilder {
856
856
  // Edge kind varies across framework resolvers: Spring/Rails/
857
857
  // Laravel/Drupal emit `references`, Express emits `calls`. Accept
858
858
  // both — the semantic is the same (route → its handler).
859
- this.stmts.getRoutingManifest = this.db.prepare(`
860
- SELECT
861
- r.name AS url,
862
- h.name AS handler,
863
- h.file_path AS handler_file,
864
- h.start_line AS handler_line,
865
- h.kind AS handler_kind
866
- FROM nodes r
867
- JOIN edges e ON e.source = r.id
868
- JOIN nodes h ON e.target = h.id
869
- WHERE r.kind = 'route'
870
- AND e.kind IN ('references', 'calls')
871
- AND h.kind IN ('function', 'method', 'class')
872
- ORDER BY r.file_path, r.start_line
873
- LIMIT ?
859
+ this.stmts.getRoutingManifest = this.db.prepare(`
860
+ SELECT
861
+ r.name AS url,
862
+ h.name AS handler,
863
+ h.file_path AS handler_file,
864
+ h.start_line AS handler_line,
865
+ h.kind AS handler_kind
866
+ FROM nodes r
867
+ JOIN edges e ON e.source = r.id
868
+ JOIN nodes h ON e.target = h.id
869
+ WHERE r.kind = 'route'
870
+ AND e.kind IN ('references', 'calls')
871
+ AND h.kind IN ('function', 'method', 'class')
872
+ ORDER BY r.file_path, r.start_line
873
+ LIMIT ?
874
874
  `);
875
875
  }
876
876
  const rows = this.stmts.getRoutingManifest.all(limit);
@@ -1234,11 +1234,11 @@ class QueryBuilder {
1234
1234
  // Fetch 5x requested limit so post-hoc rescoring (kindBonus, pathRelevance,
1235
1235
  // nameMatchBonus) can promote results that BM25 alone undervalues.
1236
1236
  const ftsLimit = Math.max(limit * 5, 100);
1237
- let sql = `
1238
- SELECT nodes.*, bm25(nodes_fts, 0, 20, 5, 1, 2) as score
1239
- FROM nodes_fts
1240
- JOIN nodes ON nodes_fts.id = nodes.id
1241
- WHERE nodes_fts MATCH ?
1237
+ let sql = `
1238
+ SELECT nodes.*, bm25(nodes_fts, 0, 20, 5, 1, 2) as score
1239
+ FROM nodes_fts
1240
+ JOIN nodes ON nodes_fts.id = nodes.id
1241
+ WHERE nodes_fts MATCH ?
1242
1242
  `;
1243
1243
  const params = [ftsQuery];
1244
1244
  if (kinds && kinds.length > 0) {
@@ -1269,21 +1269,21 @@ class QueryBuilder {
1269
1269
  */
1270
1270
  searchNodesLike(query, options) {
1271
1271
  const { kinds, languages, limit = 100, offset = 0 } = options;
1272
- let sql = `
1273
- SELECT nodes.*,
1274
- CASE
1275
- WHEN name = ? THEN 1.0
1276
- WHEN name LIKE ? THEN 0.9
1277
- WHEN name LIKE ? THEN 0.8
1278
- WHEN qualified_name LIKE ? THEN 0.7
1279
- ELSE 0.5
1280
- END as score
1281
- FROM nodes
1282
- WHERE (
1283
- name LIKE ? OR
1284
- qualified_name LIKE ? OR
1285
- name LIKE ?
1286
- )
1272
+ let sql = `
1273
+ SELECT nodes.*,
1274
+ CASE
1275
+ WHEN name = ? THEN 1.0
1276
+ WHEN name LIKE ? THEN 0.9
1277
+ WHEN name LIKE ? THEN 0.8
1278
+ WHEN qualified_name LIKE ? THEN 0.7
1279
+ ELSE 0.5
1280
+ END as score
1281
+ FROM nodes
1282
+ WHERE (
1283
+ name LIKE ? OR
1284
+ qualified_name LIKE ? OR
1285
+ name LIKE ?
1286
+ )
1287
1287
  `;
1288
1288
  // Pattern variants for better matching
1289
1289
  const exactMatch = query;
@@ -1357,10 +1357,10 @@ class QueryBuilder {
1357
1357
  const allResults = [];
1358
1358
  const seenIds = new Set();
1359
1359
  for (const name of names) {
1360
- let sql = `
1361
- SELECT nodes.*, 1.0 as score
1362
- FROM nodes
1363
- WHERE name COLLATE NOCASE = ?
1360
+ let sql = `
1361
+ SELECT nodes.*, 1.0 as score
1362
+ FROM nodes
1363
+ WHERE name COLLATE NOCASE = ?
1364
1364
  `;
1365
1365
  const params = [name];
1366
1366
  if (kinds && kinds.length > 0) {
@@ -1404,10 +1404,10 @@ class QueryBuilder {
1404
1404
  */
1405
1405
  findNodesByNameSubstring(substring, options = {}) {
1406
1406
  const { kinds, languages, limit = 30, excludePrefix } = options;
1407
- let sql = `
1408
- SELECT nodes.*, 1.0 as score
1409
- FROM nodes
1410
- WHERE name LIKE ?
1407
+ let sql = `
1408
+ SELECT nodes.*, 1.0 as score
1409
+ FROM nodes
1410
+ WHERE name LIKE ?
1411
1411
  `;
1412
1412
  const params = [`%${substring}%`];
1413
1413
  // Exclude prefix matches (handled by FTS-based prefix search in Step 2b)
@@ -1439,9 +1439,9 @@ class QueryBuilder {
1439
1439
  */
1440
1440
  insertEdge(edge) {
1441
1441
  if (!this.stmts.insertEdge) {
1442
- this.stmts.insertEdge = this.db.prepare(`
1443
- INSERT OR IGNORE INTO edges (source, target, kind, metadata, line, col, provenance, confidence, resolved_by)
1444
- VALUES (@source, @target, @kind, @metadata, @line, @col, @provenance, @confidence, @resolvedBy)
1442
+ this.stmts.insertEdge = this.db.prepare(`
1443
+ INSERT OR IGNORE INTO edges (source, target, kind, metadata, line, col, provenance, confidence, resolved_by)
1444
+ VALUES (@source, @target, @kind, @metadata, @line, @col, @provenance, @confidence, @resolvedBy)
1445
1445
  `);
1446
1446
  }
1447
1447
  this.stmts.insertEdge.run({
@@ -1571,18 +1571,18 @@ class QueryBuilder {
1571
1571
  * it. One indexed query (idx_nodes_file_path + idx_edges_target_kind).
1572
1572
  */
1573
1573
  getDependentFilePaths(filePath) {
1574
- const sql = `SELECT DISTINCT src.file_path AS fp
1575
- FROM edges e
1576
- JOIN nodes tgt ON tgt.id = e.target
1577
- JOIN nodes src ON src.id = e.source
1578
- WHERE tgt.file_path = ?
1579
- AND e.kind != 'contains'
1580
- AND src.file_path != ?
1581
- AND (
1582
- e.kind = 'imports'
1583
- OR src.language NOT IN (${UNCORROBORATED_FILTER_LANGUAGES_SQL_LIST})
1584
- OR e.resolved_by IS NULL
1585
- OR e.resolved_by NOT IN (${UNCORROBORATED_RESOLVED_BY_SQL_LIST})
1574
+ const sql = `SELECT DISTINCT src.file_path AS fp
1575
+ FROM edges e
1576
+ JOIN nodes tgt ON tgt.id = e.target
1577
+ JOIN nodes src ON src.id = e.source
1578
+ WHERE tgt.file_path = ?
1579
+ AND e.kind != 'contains'
1580
+ AND src.file_path != ?
1581
+ AND (
1582
+ e.kind = 'imports'
1583
+ OR src.language NOT IN (${UNCORROBORATED_FILTER_LANGUAGES_SQL_LIST})
1584
+ OR e.resolved_by IS NULL
1585
+ OR e.resolved_by NOT IN (${UNCORROBORATED_RESOLVED_BY_SQL_LIST})
1586
1586
  )`;
1587
1587
  const rows = this.db.prepare(sql).all(filePath, filePath);
1588
1588
  return rows.map((r) => r.fp);
@@ -1594,18 +1594,18 @@ class QueryBuilder {
1594
1594
  * (all kinds except `contains`); same reason imports-only is insufficient.
1595
1595
  */
1596
1596
  getDependencyFilePaths(filePath) {
1597
- const sql = `SELECT DISTINCT tgt.file_path AS fp
1598
- FROM edges e
1599
- JOIN nodes src ON src.id = e.source
1600
- JOIN nodes tgt ON tgt.id = e.target
1601
- WHERE src.file_path = ?
1602
- AND e.kind != 'contains'
1603
- AND tgt.file_path != ?
1604
- AND (
1605
- e.kind = 'imports'
1606
- OR src.language NOT IN (${UNCORROBORATED_FILTER_LANGUAGES_SQL_LIST})
1607
- OR e.resolved_by IS NULL
1608
- OR e.resolved_by NOT IN (${UNCORROBORATED_RESOLVED_BY_SQL_LIST})
1597
+ const sql = `SELECT DISTINCT tgt.file_path AS fp
1598
+ FROM edges e
1599
+ JOIN nodes src ON src.id = e.source
1600
+ JOIN nodes tgt ON tgt.id = e.target
1601
+ WHERE src.file_path = ?
1602
+ AND e.kind != 'contains'
1603
+ AND tgt.file_path != ?
1604
+ AND (
1605
+ e.kind = 'imports'
1606
+ OR src.language NOT IN (${UNCORROBORATED_FILTER_LANGUAGES_SQL_LIST})
1607
+ OR e.resolved_by IS NULL
1608
+ OR e.resolved_by NOT IN (${UNCORROBORATED_RESOLVED_BY_SQL_LIST})
1609
1609
  )`;
1610
1610
  const rows = this.db.prepare(sql).all(filePath, filePath);
1611
1611
  return rows.map((r) => r.fp);
@@ -1621,13 +1621,13 @@ class QueryBuilder {
1621
1621
  * {@link getDependentFilePaths}: all kinds except `contains`.
1622
1622
  */
1623
1623
  getCrossFileIncomingEdgesWithTarget(filePath) {
1624
- const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind,
1625
- src.file_path AS source_file_path, src.language AS source_language
1626
- FROM edges e
1627
- JOIN nodes tgt ON tgt.id = e.target
1628
- JOIN nodes src ON src.id = e.source
1629
- WHERE tgt.file_path = ?
1630
- AND e.kind != 'contains'
1624
+ const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind,
1625
+ src.file_path AS source_file_path, src.language AS source_language
1626
+ FROM edges e
1627
+ JOIN nodes tgt ON tgt.id = e.target
1628
+ JOIN nodes src ON src.id = e.source
1629
+ WHERE tgt.file_path = ?
1630
+ AND e.kind != 'contains'
1631
1631
  AND src.file_path != ?`;
1632
1632
  const rows = this.db.prepare(sql).all(filePath, filePath);
1633
1633
  return rows.map(row => ({
@@ -1646,18 +1646,18 @@ class QueryBuilder {
1646
1646
  */
1647
1647
  upsertFile(file) {
1648
1648
  if (!this.stmts.upsertFile) {
1649
- this.stmts.upsertFile = this.db.prepare(`
1650
- INSERT INTO files (path, content_hash, language, size, modified_at, indexed_at, node_count, extraction_version, errors)
1651
- VALUES (@path, @contentHash, @language, @size, @modifiedAt, @indexedAt, @nodeCount, @extractionVersion, @errors)
1652
- ON CONFLICT(path) DO UPDATE SET
1653
- content_hash = @contentHash,
1654
- language = @language,
1655
- size = @size,
1656
- modified_at = @modifiedAt,
1657
- indexed_at = @indexedAt,
1658
- node_count = @nodeCount,
1659
- extraction_version = @extractionVersion,
1660
- errors = @errors
1649
+ this.stmts.upsertFile = this.db.prepare(`
1650
+ INSERT INTO files (path, content_hash, language, size, modified_at, indexed_at, node_count, extraction_version, errors)
1651
+ VALUES (@path, @contentHash, @language, @size, @modifiedAt, @indexedAt, @nodeCount, @extractionVersion, @errors)
1652
+ ON CONFLICT(path) DO UPDATE SET
1653
+ content_hash = @contentHash,
1654
+ language = @language,
1655
+ size = @size,
1656
+ modified_at = @modifiedAt,
1657
+ indexed_at = @indexedAt,
1658
+ node_count = @nodeCount,
1659
+ extraction_version = @extractionVersion,
1660
+ errors = @errors
1661
1661
  `);
1662
1662
  }
1663
1663
  this.stmts.upsertFile.run({
@@ -1771,9 +1771,9 @@ class QueryBuilder {
1771
1771
  */
1772
1772
  insertUnresolvedRef(ref) {
1773
1773
  if (!this.stmts.insertUnresolved) {
1774
- this.stmts.insertUnresolved = this.db.prepare(`
1775
- INSERT INTO unresolved_refs (from_node_id, reference_name, reference_kind, line, col, candidates, file_path, language, binding_form, imported_name)
1776
- VALUES (@fromNodeId, @referenceName, @referenceKind, @line, @col, @candidates, @filePath, @language, @bindingForm, @importedName)
1774
+ this.stmts.insertUnresolved = this.db.prepare(`
1775
+ INSERT INTO unresolved_refs (from_node_id, reference_name, reference_kind, line, col, candidates, file_path, language, binding_form, imported_name)
1776
+ VALUES (@fromNodeId, @referenceName, @referenceKind, @line, @col, @candidates, @filePath, @language, @bindingForm, @importedName)
1777
1777
  `);
1778
1778
  }
1779
1779
  this.stmts.insertUnresolved.run({
@@ -2246,11 +2246,11 @@ class QueryBuilder {
2246
2246
  */
2247
2247
  getStats() {
2248
2248
  // Single query for all three aggregate counts
2249
- const counts = this.db.prepare(`
2250
- SELECT
2251
- (SELECT COUNT(*) FROM nodes) AS node_count,
2252
- (SELECT COUNT(*) FROM edges) AS edge_count,
2253
- (SELECT COUNT(*) FROM files) AS file_count
2249
+ const counts = this.db.prepare(`
2250
+ SELECT
2251
+ (SELECT COUNT(*) FROM nodes) AS node_count,
2252
+ (SELECT COUNT(*) FROM edges) AS edge_count,
2253
+ (SELECT COUNT(*) FROM files) AS file_count
2254
2254
  `).get();
2255
2255
  const nodesByKind = {};
2256
2256
  const nodeKindRows = this.db