@optave/codegraph 3.1.4 → 3.1.5

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 (181) hide show
  1. package/README.md +26 -70
  2. package/package.json +10 -8
  3. package/src/ast-analysis/engine.js +32 -12
  4. package/src/ast-analysis/shared.js +2 -2
  5. package/src/cli/commands/ast.js +2 -6
  6. package/src/cli/commands/audit.js +9 -10
  7. package/src/cli/commands/batch.js +4 -4
  8. package/src/cli/commands/branch-compare.js +1 -1
  9. package/src/cli/commands/build.js +1 -1
  10. package/src/cli/commands/cfg.js +3 -7
  11. package/src/cli/commands/check.js +12 -17
  12. package/src/cli/commands/children.js +3 -6
  13. package/src/cli/commands/co-change.js +5 -3
  14. package/src/cli/commands/communities.js +2 -6
  15. package/src/cli/commands/complexity.js +3 -2
  16. package/src/cli/commands/context.js +3 -7
  17. package/src/cli/commands/cycles.js +12 -8
  18. package/src/cli/commands/dataflow.js +3 -7
  19. package/src/cli/commands/deps.js +2 -6
  20. package/src/cli/commands/diff-impact.js +2 -6
  21. package/src/cli/commands/embed.js +1 -1
  22. package/src/cli/commands/export.js +34 -31
  23. package/src/cli/commands/exports.js +2 -6
  24. package/src/cli/commands/flow.js +3 -7
  25. package/src/cli/commands/fn-impact.js +3 -7
  26. package/src/cli/commands/impact.js +2 -6
  27. package/src/cli/commands/info.js +2 -2
  28. package/src/cli/commands/map.js +1 -1
  29. package/src/cli/commands/mcp.js +1 -1
  30. package/src/cli/commands/models.js +1 -1
  31. package/src/cli/commands/owners.js +1 -1
  32. package/src/cli/commands/path.js +2 -2
  33. package/src/cli/commands/plot.js +40 -31
  34. package/src/cli/commands/query.js +3 -7
  35. package/src/cli/commands/registry.js +2 -2
  36. package/src/cli/commands/roles.js +3 -7
  37. package/src/cli/commands/search.js +1 -1
  38. package/src/cli/commands/sequence.js +3 -7
  39. package/src/cli/commands/snapshot.js +6 -1
  40. package/src/cli/commands/stats.js +1 -1
  41. package/src/cli/commands/structure.js +5 -4
  42. package/src/cli/commands/triage.js +4 -4
  43. package/src/cli/commands/watch.js +1 -1
  44. package/src/cli/commands/where.js +2 -6
  45. package/src/cli/index.js +11 -5
  46. package/src/cli/shared/open-graph.js +13 -0
  47. package/src/cli/shared/options.js +22 -2
  48. package/src/cli.js +1 -1
  49. package/src/db/connection.js +127 -4
  50. package/src/{db.js → db/index.js} +12 -5
  51. package/src/db/migrations.js +1 -1
  52. package/src/db/query-builder.js +15 -8
  53. package/src/db/repository/base.js +1 -1
  54. package/src/db/repository/graph-read.js +3 -3
  55. package/src/db/repository/in-memory-repository.js +4 -13
  56. package/src/db/repository/nodes.js +3 -8
  57. package/src/{analysis → domain/analysis}/context.js +6 -6
  58. package/src/{analysis → domain/analysis}/dependencies.js +5 -5
  59. package/src/{analysis → domain/analysis}/exports.js +8 -4
  60. package/src/{analysis → domain/analysis}/impact.js +61 -58
  61. package/src/{analysis → domain/analysis}/module-map.js +3 -3
  62. package/src/{analysis → domain/analysis}/roles.js +4 -4
  63. package/src/{analysis → domain/analysis}/symbol-lookup.js +13 -7
  64. package/src/{builder → domain/graph/builder}/helpers.js +3 -3
  65. package/src/{builder → domain/graph/builder}/incremental.js +3 -3
  66. package/src/{builder → domain/graph/builder}/pipeline.js +4 -4
  67. package/src/{builder → domain/graph/builder}/stages/build-edges.js +2 -2
  68. package/src/{builder → domain/graph/builder}/stages/build-structure.js +4 -4
  69. package/src/{builder → domain/graph/builder}/stages/collect-files.js +2 -2
  70. package/src/{builder → domain/graph/builder}/stages/detect-changes.js +6 -6
  71. package/src/{builder → domain/graph/builder}/stages/finalize.js +4 -4
  72. package/src/{builder → domain/graph/builder}/stages/insert-nodes.js +1 -1
  73. package/src/{builder → domain/graph/builder}/stages/parse-files.js +2 -2
  74. package/src/{builder → domain/graph/builder}/stages/resolve-imports.js +1 -1
  75. package/src/{builder → domain/graph/builder}/stages/run-analyses.js +2 -2
  76. package/src/{change-journal.js → domain/graph/change-journal.js} +1 -1
  77. package/src/{cycles.js → domain/graph/cycles.js} +4 -4
  78. package/src/{journal.js → domain/graph/journal.js} +1 -1
  79. package/src/{resolve.js → domain/graph/resolve.js} +2 -2
  80. package/src/{watcher.js → domain/graph/watcher.js} +5 -5
  81. package/src/{parser.js → domain/parser.js} +5 -5
  82. package/src/{queries.js → domain/queries.js} +16 -16
  83. package/src/{embeddings → domain/search}/generator.js +3 -3
  84. package/src/{embeddings → domain/search}/models.js +2 -2
  85. package/src/{embeddings → domain/search}/search/cli-formatter.js +1 -1
  86. package/src/{embeddings → domain/search}/search/hybrid.js +1 -1
  87. package/src/{embeddings → domain/search}/search/keyword.js +1 -1
  88. package/src/{embeddings → domain/search}/search/prepare.js +2 -2
  89. package/src/{embeddings → domain/search}/search/semantic.js +1 -1
  90. package/src/{embeddings → domain/search}/strategies/structured.js +1 -1
  91. package/src/extractors/javascript.js +1 -1
  92. package/src/{ast.js → features/ast.js} +8 -8
  93. package/src/{audit.js → features/audit.js} +16 -44
  94. package/src/{batch.js → features/batch.js} +5 -5
  95. package/src/{boundaries.js → features/boundaries.js} +2 -2
  96. package/src/{branch-compare.js → features/branch-compare.js} +3 -3
  97. package/src/{cfg.js → features/cfg.js} +10 -10
  98. package/src/{check.js → features/check.js} +13 -30
  99. package/src/{cochange.js → features/cochange.js} +5 -5
  100. package/src/{communities.js → features/communities.js} +7 -7
  101. package/src/{complexity.js → features/complexity.js} +13 -13
  102. package/src/{dataflow.js → features/dataflow.js} +11 -11
  103. package/src/{export.js → features/export.js} +3 -3
  104. package/src/{flow.js → features/flow.js} +4 -4
  105. package/src/{viewer.js → features/graph-enrichment.js} +6 -6
  106. package/src/{manifesto.js → features/manifesto.js} +6 -6
  107. package/src/{owners.js → features/owners.js} +2 -2
  108. package/src/{sequence.js → features/sequence.js} +15 -15
  109. package/src/{snapshot.js → features/snapshot.js} +3 -3
  110. package/src/{structure.js → features/structure.js} +7 -7
  111. package/src/{triage.js → features/triage.js} +8 -8
  112. package/src/graph/builders/dependency.js +33 -14
  113. package/src/index.cjs +16 -0
  114. package/src/index.js +39 -39
  115. package/src/{native.js → infrastructure/native.js} +1 -1
  116. package/src/mcp/middleware.js +1 -1
  117. package/src/mcp/server.js +5 -5
  118. package/src/mcp/tool-registry.js +2 -2
  119. package/src/mcp/tools/ast-query.js +1 -1
  120. package/src/mcp/tools/audit.js +1 -1
  121. package/src/mcp/tools/batch-query.js +1 -1
  122. package/src/mcp/tools/branch-compare.js +3 -1
  123. package/src/mcp/tools/cfg.js +1 -1
  124. package/src/mcp/tools/check.js +3 -3
  125. package/src/mcp/tools/co-changes.js +1 -1
  126. package/src/mcp/tools/code-owners.js +1 -1
  127. package/src/mcp/tools/communities.js +1 -1
  128. package/src/mcp/tools/complexity.js +1 -1
  129. package/src/mcp/tools/dataflow.js +2 -2
  130. package/src/mcp/tools/execution-flow.js +2 -2
  131. package/src/mcp/tools/export-graph.js +2 -2
  132. package/src/mcp/tools/find-cycles.js +2 -2
  133. package/src/mcp/tools/list-repos.js +1 -1
  134. package/src/mcp/tools/sequence.js +1 -1
  135. package/src/mcp/tools/structure.js +1 -1
  136. package/src/mcp/tools/triage.js +2 -2
  137. package/src/{commands → presentation}/audit.js +2 -2
  138. package/src/{commands → presentation}/batch.js +1 -1
  139. package/src/{commands → presentation}/branch-compare.js +2 -2
  140. package/src/{commands → presentation}/cfg.js +1 -1
  141. package/src/{commands → presentation}/check.js +2 -2
  142. package/src/{commands → presentation}/communities.js +1 -1
  143. package/src/{commands → presentation}/complexity.js +1 -1
  144. package/src/{commands → presentation}/dataflow.js +1 -1
  145. package/src/{commands → presentation}/flow.js +2 -2
  146. package/src/{commands → presentation}/manifesto.js +1 -1
  147. package/src/{commands → presentation}/owners.js +1 -1
  148. package/src/presentation/queries-cli/exports.js +46 -0
  149. package/src/presentation/queries-cli/impact.js +198 -0
  150. package/src/presentation/queries-cli/index.js +5 -0
  151. package/src/presentation/queries-cli/inspect.js +334 -0
  152. package/src/presentation/queries-cli/overview.js +197 -0
  153. package/src/presentation/queries-cli/path.js +58 -0
  154. package/src/presentation/queries-cli.js +27 -0
  155. package/src/{commands → presentation}/query.js +1 -1
  156. package/src/presentation/result-formatter.js +126 -3
  157. package/src/{commands → presentation}/sequence.js +2 -2
  158. package/src/{commands → presentation}/structure.js +1 -1
  159. package/src/{commands → presentation}/triage.js +1 -1
  160. package/src/{constants.js → shared/constants.js} +1 -1
  161. package/src/shared/file-utils.js +2 -2
  162. package/src/shared/generators.js +2 -2
  163. package/src/shared/hierarchy.js +1 -1
  164. package/src/mcp.js +0 -2
  165. package/src/queries-cli.js +0 -866
  166. /package/src/{builder → domain/graph/builder}/context.js +0 -0
  167. /package/src/{builder.js → domain/graph/builder.js} +0 -0
  168. /package/src/{embeddings → domain/search}/index.js +0 -0
  169. /package/src/{embeddings → domain/search}/search/filters.js +0 -0
  170. /package/src/{embeddings → domain/search}/stores/fts5.js +0 -0
  171. /package/src/{embeddings → domain/search}/stores/sqlite-blob.js +0 -0
  172. /package/src/{embeddings → domain/search}/strategies/source.js +0 -0
  173. /package/src/{embeddings → domain/search}/strategies/text-utils.js +0 -0
  174. /package/src/{config.js → infrastructure/config.js} +0 -0
  175. /package/src/{logger.js → infrastructure/logger.js} +0 -0
  176. /package/src/{registry.js → infrastructure/registry.js} +0 -0
  177. /package/src/{update-check.js → infrastructure/update-check.js} +0 -0
  178. /package/src/{commands → presentation}/cochange.js +0 -0
  179. /package/src/{errors.js → shared/errors.js} +0 -0
  180. /package/src/{kinds.js → shared/kinds.js} +0 -0
  181. /package/src/{paginate.js → shared/paginate.js} +0 -0
@@ -12,22 +12,28 @@ import {
12
12
  findNodesWithFanIn,
13
13
  listFunctionNodes,
14
14
  openReadonlyOrFail,
15
- } from '../db.js';
16
- import { isTestFile } from '../infrastructure/test-filter.js';
17
- import { ALL_SYMBOL_KINDS } from '../kinds.js';
18
- import { paginateResult } from '../paginate.js';
19
- import { getFileHash, normalizeSymbol } from '../shared/normalize.js';
15
+ Repository,
16
+ } from '../../db/index.js';
17
+ import { isTestFile } from '../../infrastructure/test-filter.js';
18
+ import { ALL_SYMBOL_KINDS } from '../../shared/kinds.js';
19
+ import { getFileHash, normalizeSymbol } from '../../shared/normalize.js';
20
+ import { paginateResult } from '../../shared/paginate.js';
20
21
 
21
22
  const FUNCTION_KINDS = ['function', 'method', 'class'];
22
23
 
23
24
  /**
24
25
  * Find nodes matching a name query, ranked by relevance.
25
26
  * Scoring: exact=100, prefix=60, word-boundary=40, substring=10, plus fan-in tiebreaker.
27
+ *
28
+ * @param {object} dbOrRepo - A better-sqlite3 Database or a Repository instance
26
29
  */
27
- export function findMatchingNodes(db, name, opts = {}) {
30
+ export function findMatchingNodes(dbOrRepo, name, opts = {}) {
28
31
  const kinds = opts.kind ? [opts.kind] : opts.kinds?.length ? opts.kinds : FUNCTION_KINDS;
29
32
 
30
- const rows = findNodesWithFanIn(db, `%${name}%`, { kinds, file: opts.file });
33
+ const isRepo = dbOrRepo instanceof Repository;
34
+ const rows = isRepo
35
+ ? dbOrRepo.findNodesWithFanIn(`%${name}%`, { kinds, file: opts.file })
36
+ : findNodesWithFanIn(dbOrRepo, `%${name}%`, { kinds, file: opts.file });
31
37
 
32
38
  const nodes = opts.noTests ? rows.filter((n) => !isTestFile(n.file)) : rows;
33
39
 
@@ -6,9 +6,9 @@
6
6
  import { createHash } from 'node:crypto';
7
7
  import fs from 'node:fs';
8
8
  import path from 'node:path';
9
- import { EXTENSIONS, IGNORE_DIRS } from '../constants.js';
10
- import { purgeFilesData } from '../db.js';
11
- import { warn } from '../logger.js';
9
+ import { purgeFilesData } from '../../../db/index.js';
10
+ import { warn } from '../../../infrastructure/logger.js';
11
+ import { EXTENSIONS, IGNORE_DIRS } from '../../../shared/constants.js';
12
12
 
13
13
  export const BUILTIN_RECEIVERS = new Set([
14
14
  'console',
@@ -6,9 +6,9 @@
6
6
  */
7
7
  import fs from 'node:fs';
8
8
  import path from 'node:path';
9
- import { normalizePath } from '../constants.js';
10
- import { warn } from '../logger.js';
11
- import { parseFileIncremental } from '../parser.js';
9
+ import { warn } from '../../../infrastructure/logger.js';
10
+ import { normalizePath } from '../../../shared/constants.js';
11
+ import { parseFileIncremental } from '../../parser.js';
12
12
  import { computeConfidence, resolveImportPath } from '../resolve.js';
13
13
  import { BUILTIN_RECEIVERS, readFileSafe } from './helpers.js';
14
14
 
@@ -6,10 +6,10 @@
6
6
  */
7
7
  import path from 'node:path';
8
8
  import { performance } from 'node:perf_hooks';
9
- import { loadConfig } from '../config.js';
10
- import { closeDb, getBuildMeta, initSchema, MIGRATIONS, openDb } from '../db.js';
11
- import { info } from '../logger.js';
12
- import { getActiveEngine } from '../parser.js';
9
+ import { closeDb, getBuildMeta, initSchema, MIGRATIONS, openDb } from '../../../db/index.js';
10
+ import { loadConfig } from '../../../infrastructure/config.js';
11
+ import { info } from '../../../infrastructure/logger.js';
12
+ import { getActiveEngine } from '../../parser.js';
13
13
  import { PipelineContext } from './context.js';
14
14
  import { loadPathAliases } from './helpers.js';
15
15
  import { buildEdges } from './stages/build-edges.js';
@@ -6,8 +6,8 @@
6
6
  */
7
7
  import path from 'node:path';
8
8
  import { performance } from 'node:perf_hooks';
9
- import { getNodeId } from '../../db.js';
10
- import { loadNative } from '../../native.js';
9
+ import { getNodeId } from '../../../../db/index.js';
10
+ import { loadNative } from '../../../../infrastructure/native.js';
11
11
  import { computeConfidence } from '../../resolve.js';
12
12
  import { BUILTIN_RECEIVERS, batchInsertEdges } from '../helpers.js';
13
13
  import { getResolved, isBarrelFile, resolveBarrelExport } from './resolve-imports.js';
@@ -5,8 +5,8 @@
5
5
  */
6
6
  import path from 'node:path';
7
7
  import { performance } from 'node:perf_hooks';
8
- import { normalizePath } from '../../constants.js';
9
- import { debug } from '../../logger.js';
8
+ import { debug } from '../../../../infrastructure/logger.js';
9
+ import { normalizePath } from '../../../../shared/constants.js';
10
10
  import { readFileSafe } from '../helpers.js';
11
11
 
12
12
  /**
@@ -88,7 +88,7 @@ export async function buildStructure(ctx) {
88
88
  relDirs.add(normalizePath(path.relative(rootDir, absDir)));
89
89
  }
90
90
  try {
91
- const { buildStructure: buildStructureFn } = await import('../../structure.js');
91
+ const { buildStructure: buildStructureFn } = await import('../../../../features/structure.js');
92
92
  const changedFilePaths = isFullBuild ? null : [...allSymbols.keys()];
93
93
  buildStructureFn(db, fileSymbols, rootDir, ctx.lineCountMap, relDirs, changedFilePaths);
94
94
  } catch (err) {
@@ -99,7 +99,7 @@ export async function buildStructure(ctx) {
99
99
  // Classify node roles
100
100
  const t1 = performance.now();
101
101
  try {
102
- const { classifyNodeRoles } = await import('../../structure.js');
102
+ const { classifyNodeRoles } = await import('../../../../features/structure.js');
103
103
  const roleSummary = classifyNodeRoles(db);
104
104
  debug(
105
105
  `Roles: ${Object.entries(roleSummary)
@@ -5,8 +5,8 @@
5
5
  */
6
6
  import fs from 'node:fs';
7
7
  import path from 'node:path';
8
- import { normalizePath } from '../../constants.js';
9
- import { info } from '../../logger.js';
8
+ import { info } from '../../../../infrastructure/logger.js';
9
+ import { normalizePath } from '../../../../shared/constants.js';
10
10
  import { collectFiles as collectFilesUtil } from '../helpers.js';
11
11
 
12
12
  /**
@@ -6,11 +6,11 @@
6
6
  */
7
7
  import fs from 'node:fs';
8
8
  import path from 'node:path';
9
- import { normalizePath } from '../../constants.js';
10
- import { closeDb } from '../../db.js';
9
+ import { closeDb } from '../../../../db/index.js';
10
+ import { debug, info } from '../../../../infrastructure/logger.js';
11
+ import { normalizePath } from '../../../../shared/constants.js';
12
+ import { parseFilesAuto } from '../../../parser.js';
11
13
  import { readJournal, writeJournalHeader } from '../../journal.js';
12
- import { debug, info } from '../../logger.js';
13
- import { parseFilesAuto } from '../../parser.js';
14
14
  import { fileHash, fileStat, purgeFilesFromGraph, readFileSafe } from '../helpers.js';
15
15
 
16
16
  /**
@@ -203,11 +203,11 @@ async function runPendingAnalysis(ctx) {
203
203
  };
204
204
  const analysisSymbols = await parseFilesAuto(allFiles, rootDir, analysisOpts);
205
205
  if (needsCfg) {
206
- const { buildCFGData } = await import('../../cfg.js');
206
+ const { buildCFGData } = await import('../../../../features/cfg.js');
207
207
  await buildCFGData(db, analysisSymbols, rootDir, engineOpts);
208
208
  }
209
209
  if (needsDataflow) {
210
- const { buildDataflowEdges } = await import('../../dataflow.js');
210
+ const { buildDataflowEdges } = await import('../../../../features/dataflow.js');
211
211
  await buildDataflowEdges(db, analysisSymbols, rootDir, engineOpts);
212
212
  }
213
213
  return true;
@@ -6,13 +6,13 @@
6
6
  import fs from 'node:fs';
7
7
  import path from 'node:path';
8
8
  import { performance } from 'node:perf_hooks';
9
- import { closeDb, getBuildMeta, setBuildMeta } from '../../db.js';
9
+ import { closeDb, getBuildMeta, setBuildMeta } from '../../../../db/index.js';
10
+ import { debug, info, warn } from '../../../../infrastructure/logger.js';
10
11
  import { writeJournalHeader } from '../../journal.js';
11
- import { debug, info, warn } from '../../logger.js';
12
12
 
13
13
  const __builderDir = path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Z]:)/i, '$1'));
14
14
  const CODEGRAPH_VERSION = JSON.parse(
15
- fs.readFileSync(path.join(__builderDir, '..', '..', '..', 'package.json'), 'utf-8'),
15
+ fs.readFileSync(path.join(__builderDir, '..', '..', '..', '..', '..', 'package.json'), 'utf-8'),
16
16
  ).version;
17
17
 
18
18
  /**
@@ -127,7 +127,7 @@ export async function finalize(ctx) {
127
127
  debug(`Skipping auto-registration for temp directory: ${resolvedRoot}`);
128
128
  } else {
129
129
  try {
130
- const { registerRepo } = await import('../../registry.js');
130
+ const { registerRepo } = await import('../../../../infrastructure/registry.js');
131
131
  registerRepo(rootDir);
132
132
  } catch (err) {
133
133
  debug(`Auto-registration failed: ${err.message}`);
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import path from 'node:path';
8
8
  import { performance } from 'node:perf_hooks';
9
- import { bulkNodeIdsByFile } from '../../db.js';
9
+ import { bulkNodeIdsByFile } from '../../../../db/index.js';
10
10
  import {
11
11
  batchInsertEdges,
12
12
  batchInsertNodes,
@@ -5,8 +5,8 @@
5
5
  * Populates ctx.allSymbols, ctx.fileSymbols, ctx.filesToParse.
6
6
  */
7
7
  import { performance } from 'node:perf_hooks';
8
- import { info } from '../../logger.js';
9
- import { parseFilesAuto } from '../../parser.js';
8
+ import { info } from '../../../../infrastructure/logger.js';
9
+ import { parseFilesAuto } from '../../../parser.js';
10
10
 
11
11
  /**
12
12
  * @param {import('../context.js').PipelineContext} ctx
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import path from 'node:path';
8
8
  import { performance } from 'node:perf_hooks';
9
- import { parseFilesAuto } from '../../parser.js';
9
+ import { parseFilesAuto } from '../../../parser.js';
10
10
  import { resolveImportPath, resolveImportsBatch } from '../../resolve.js';
11
11
 
12
12
  /**
@@ -4,7 +4,7 @@
4
4
  * Dispatches to the unified AST analysis engine (AST nodes, complexity, CFG, dataflow).
5
5
  * Filters out reverse-dep files for incremental builds.
6
6
  */
7
- import { debug, warn } from '../../logger.js';
7
+ import { debug, warn } from '../../../../infrastructure/logger.js';
8
8
 
9
9
  /**
10
10
  * @param {import('../context.js').PipelineContext} ctx
@@ -31,7 +31,7 @@ export async function runAnalyses(ctx) {
31
31
  }
32
32
  }
33
33
 
34
- const { runAnalyses: runAnalysesFn } = await import('../../ast-analysis/engine.js');
34
+ const { runAnalyses: runAnalysesFn } = await import('../../../../ast-analysis/engine.js');
35
35
  try {
36
36
  const analysisTiming = await runAnalysesFn(db, astComplexitySymbols, rootDir, opts, engineOpts);
37
37
  ctx.timing.astMs = analysisTiming.astMs;
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { debug, warn } from './logger.js';
3
+ import { debug, warn } from '../../infrastructure/logger.js';
4
4
 
5
5
  export const CHANGE_EVENTS_FILENAME = 'change-events.ndjson';
6
6
  export const DEFAULT_MAX_BYTES = 1024 * 1024; // 1 MB
@@ -1,7 +1,7 @@
1
- import { tarjan } from './graph/algorithms/tarjan.js';
2
- import { buildDependencyGraph } from './graph/builders/dependency.js';
3
- import { CodeGraph } from './graph/model.js';
4
- import { loadNative } from './native.js';
1
+ import { tarjan } from '../../graph/algorithms/tarjan.js';
2
+ import { buildDependencyGraph } from '../../graph/builders/dependency.js';
3
+ import { CodeGraph } from '../../graph/model.js';
4
+ import { loadNative } from '../../infrastructure/native.js';
5
5
 
6
6
  /**
7
7
  * Detect circular dependencies in the codebase using Tarjan's SCC algorithm.
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { debug, warn } from './logger.js';
3
+ import { debug, warn } from '../../infrastructure/logger.js';
4
4
 
5
5
  export const JOURNAL_FILENAME = 'changes.journal';
6
6
  const HEADER_PREFIX = '# codegraph-journal v1 ';
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { normalizePath } from './constants.js';
4
- import { loadNative } from './native.js';
3
+ import { loadNative } from '../../infrastructure/native.js';
4
+ import { normalizePath } from '../../shared/constants.js';
5
5
 
6
6
  // ── Alias format conversion ─────────────────────────────────────────
7
7
 
@@ -1,13 +1,13 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
+ import { closeDb, getNodeId as getNodeIdQuery, initSchema, openDb } from '../../db/index.js';
4
+ import { info } from '../../infrastructure/logger.js';
5
+ import { EXTENSIONS, IGNORE_DIRS, normalizePath } from '../../shared/constants.js';
6
+ import { DbError } from '../../shared/errors.js';
7
+ import { createParseTreeCache, getActiveEngine } from '../parser.js';
3
8
  import { rebuildFile } from './builder/incremental.js';
4
9
  import { appendChangeEvents, buildChangeEvent, diffSymbols } from './change-journal.js';
5
- import { EXTENSIONS, IGNORE_DIRS, normalizePath } from './constants.js';
6
- import { closeDb, getNodeId as getNodeIdQuery, initSchema, openDb } from './db.js';
7
- import { DbError } from './errors.js';
8
10
  import { appendJournalEntries } from './journal.js';
9
- import { info } from './logger.js';
10
- import { createParseTreeCache, getActiveEngine } from './parser.js';
11
11
 
12
12
  function shouldIgnore(filePath) {
13
13
  const parts = filePath.split(path.sep);
@@ -2,8 +2,8 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { Language, Parser, Query } from 'web-tree-sitter';
5
- import { warn } from './logger.js';
6
- import { getNative, getNativePackageVersion, loadNative } from './native.js';
5
+ import { warn } from '../infrastructure/logger.js';
6
+ import { getNative, getNativePackageVersion, loadNative } from '../infrastructure/native.js';
7
7
 
8
8
  // Re-export all extractors for backward compatibility
9
9
  export {
@@ -16,7 +16,7 @@ export {
16
16
  extractRubySymbols,
17
17
  extractRustSymbols,
18
18
  extractSymbols,
19
- } from './extractors/index.js';
19
+ } from '../extractors/index.js';
20
20
 
21
21
  import {
22
22
  extractCSharpSymbols,
@@ -28,12 +28,12 @@ import {
28
28
  extractRubySymbols,
29
29
  extractRustSymbols,
30
30
  extractSymbols,
31
- } from './extractors/index.js';
31
+ } from '../extractors/index.js';
32
32
 
33
33
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
34
34
 
35
35
  function grammarPath(name) {
36
- return path.join(__dirname, '..', 'grammars', name);
36
+ return path.join(__dirname, '..', '..', 'grammars', name);
37
37
  }
38
38
 
39
39
  let _initialized = false;
@@ -6,6 +6,22 @@
6
6
  * importers continue to work without changes.
7
7
  */
8
8
 
9
+ // ── Re-export from dedicated module for backward compat ───────────────────
10
+ export { isTestFile, TEST_PATTERN } from '../infrastructure/test-filter.js';
11
+ export { iterListFunctions, iterRoles, iterWhere } from '../shared/generators.js';
12
+ // ── Kind/edge constants (canonical source: kinds.js) ─────────────────────
13
+ export {
14
+ ALL_SYMBOL_KINDS,
15
+ CORE_EDGE_KINDS,
16
+ CORE_SYMBOL_KINDS,
17
+ EVERY_EDGE_KIND,
18
+ EVERY_SYMBOL_KIND,
19
+ EXTENDED_SYMBOL_KINDS,
20
+ STRUCTURAL_EDGE_KINDS,
21
+ VALID_ROLES,
22
+ } from '../shared/kinds.js';
23
+ // ── Shared utilities ─────────────────────────────────────────────────────
24
+ export { kindIcon, normalizeSymbol } from '../shared/normalize.js';
9
25
  export { contextData, explainData } from './analysis/context.js';
10
26
  export { fileDepsData, fnDepsData, pathData } from './analysis/dependencies.js';
11
27
  export { exportsData } from './analysis/exports.js';
@@ -30,19 +46,3 @@ export {
30
46
  queryNameData,
31
47
  whereData,
32
48
  } from './analysis/symbol-lookup.js';
33
- // ── Re-export from dedicated module for backward compat ───────────────────
34
- export { isTestFile, TEST_PATTERN } from './infrastructure/test-filter.js';
35
- // ── Kind/edge constants (canonical source: kinds.js) ─────────────────────
36
- export {
37
- ALL_SYMBOL_KINDS,
38
- CORE_EDGE_KINDS,
39
- CORE_SYMBOL_KINDS,
40
- EVERY_EDGE_KIND,
41
- EVERY_SYMBOL_KIND,
42
- EXTENDED_SYMBOL_KINDS,
43
- STRUCTURAL_EDGE_KINDS,
44
- VALID_ROLES,
45
- } from './kinds.js';
46
- export { iterListFunctions, iterRoles, iterWhere } from './shared/generators.js';
47
- // ── Shared utilities ─────────────────────────────────────────────────────
48
- export { kindIcon, normalizeSymbol } from './shared/normalize.js';
@@ -1,8 +1,8 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { closeDb, findDbPath, openDb } from '../db.js';
4
- import { DbError } from '../errors.js';
5
- import { warn } from '../logger.js';
3
+ import { closeDb, findDbPath, openDb } from '../../db/index.js';
4
+ import { warn } from '../../infrastructure/logger.js';
5
+ import { DbError } from '../../shared/errors.js';
6
6
  import { embed, getModelConfig } from './models.js';
7
7
  import { buildSourceText } from './strategies/source.js';
8
8
  import { buildStructuredText } from './strategies/structured.js';
@@ -1,7 +1,7 @@
1
1
  import { execFileSync } from 'node:child_process';
2
2
  import { createInterface } from 'node:readline';
3
- import { ConfigError, EngineError } from '../errors.js';
4
- import { info } from '../logger.js';
3
+ import { info } from '../../infrastructure/logger.js';
4
+ import { ConfigError, EngineError } from '../../shared/errors.js';
5
5
 
6
6
  // Lazy-load transformers (heavy, optional module)
7
7
  let pipeline = null;
@@ -1,4 +1,4 @@
1
- import { warn } from '../../logger.js';
1
+ import { warn } from '../../../infrastructure/logger.js';
2
2
  import { hybridSearchData } from './hybrid.js';
3
3
  import { ftsSearchData } from './keyword.js';
4
4
  import { multiSearchData, searchData } from './semantic.js';
@@ -1,4 +1,4 @@
1
- import { openReadonlyOrFail } from '../../db.js';
1
+ import { openReadonlyOrFail } from '../../../db/index.js';
2
2
  import { hasFtsIndex } from '../stores/fts5.js';
3
3
  import { ftsSearchData } from './keyword.js';
4
4
  import { searchData } from './semantic.js';
@@ -1,4 +1,4 @@
1
- import { openReadonlyOrFail } from '../../db.js';
1
+ import { openReadonlyOrFail } from '../../../db/index.js';
2
2
  import { normalizeSymbol } from '../../queries.js';
3
3
  import { hasFtsIndex, sanitizeFtsQuery } from '../stores/fts5.js';
4
4
  import { applyFilters } from './filters.js';
@@ -1,5 +1,5 @@
1
- import { getEmbeddingCount, getEmbeddingMeta } from '../../db/repository/embeddings.js';
2
- import { openReadonlyOrFail } from '../../db.js';
1
+ import { openReadonlyOrFail } from '../../../db/index.js';
2
+ import { getEmbeddingCount, getEmbeddingMeta } from '../../../db/repository/embeddings.js';
3
3
  import { MODELS } from '../models.js';
4
4
  import { applyFilters } from './filters.js';
5
5
 
@@ -1,4 +1,4 @@
1
- import { warn } from '../../logger.js';
1
+ import { warn } from '../../../infrastructure/logger.js';
2
2
  import { normalizeSymbol } from '../../queries.js';
3
3
  import { embed } from '../models.js';
4
4
  import { cosineSim } from '../stores/sqlite-blob.js';
@@ -1,4 +1,4 @@
1
- import { findCalleeNames, findCallerNames } from '../../db.js';
1
+ import { findCalleeNames, findCallerNames } from '../../../db/index.js';
2
2
  import { extractLeadingComment, splitIdentifier } from './text-utils.js';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { debug } from '../logger.js';
1
+ import { debug } from '../infrastructure/logger.js';
2
2
  import { findChild, nodeEndLine } from './helpers.js';
3
3
 
4
4
  /**
@@ -7,14 +7,14 @@
7
7
  */
8
8
 
9
9
  import path from 'node:path';
10
- import { AST_TYPE_MAPS } from './ast-analysis/rules/index.js';
11
- import { buildExtensionSet } from './ast-analysis/shared.js';
12
- import { walkWithVisitors } from './ast-analysis/visitor.js';
13
- import { createAstStoreVisitor } from './ast-analysis/visitors/ast-store-visitor.js';
14
- import { bulkNodeIdsByFile, openReadonlyOrFail } from './db.js';
15
- import { outputResult } from './infrastructure/result-formatter.js';
16
- import { debug } from './logger.js';
17
- import { paginateResult } from './paginate.js';
10
+ import { AST_TYPE_MAPS } from '../ast-analysis/rules/index.js';
11
+ import { buildExtensionSet } from '../ast-analysis/shared.js';
12
+ import { walkWithVisitors } from '../ast-analysis/visitor.js';
13
+ import { createAstStoreVisitor } from '../ast-analysis/visitors/ast-store-visitor.js';
14
+ import { bulkNodeIdsByFile, openReadonlyOrFail } from '../db/index.js';
15
+ import { debug } from '../infrastructure/logger.js';
16
+ import { outputResult } from '../infrastructure/result-formatter.js';
17
+ import { paginateResult } from '../shared/paginate.js';
18
18
 
19
19
  // ─── Constants ────────────────────────────────────────────────────────
20
20
 
@@ -7,21 +7,26 @@
7
7
  */
8
8
 
9
9
  import path from 'node:path';
10
- import { loadConfig } from './config.js';
11
- import { openReadonlyOrFail } from './db.js';
12
- import { isTestFile } from './infrastructure/test-filter.js';
10
+ import { openReadonlyOrFail } from '../db/index.js';
11
+ import { bfsTransitiveCallers } from '../domain/analysis/impact.js';
12
+ import { explainData } from '../domain/queries.js';
13
+ import { loadConfig } from '../infrastructure/config.js';
14
+ import { isTestFile } from '../infrastructure/test-filter.js';
13
15
  import { RULE_DEFS } from './manifesto.js';
14
- import { explainData } from './queries.js';
15
16
 
16
17
  // ─── Threshold resolution ───────────────────────────────────────────
17
18
 
18
19
  const FUNCTION_RULES = RULE_DEFS.filter((d) => d.level === 'function');
19
20
 
20
- function resolveThresholds(customDbPath) {
21
+ function resolveThresholds(customDbPath, config) {
21
22
  try {
22
- const dbDir = path.dirname(customDbPath);
23
- const repoRoot = path.resolve(dbDir, '..');
24
- const cfg = loadConfig(repoRoot);
23
+ const cfg =
24
+ config ||
25
+ (() => {
26
+ const dbDir = path.dirname(customDbPath);
27
+ const repoRoot = path.resolve(dbDir, '..');
28
+ return loadConfig(repoRoot);
29
+ })();
25
30
  const userRules = cfg.manifesto || {};
26
31
  const resolved = {};
27
32
  for (const def of FUNCTION_RULES) {
@@ -70,39 +75,6 @@ function checkBreaches(row, thresholds) {
70
75
  return breaches;
71
76
  }
72
77
 
73
- // ─── BFS impact (inline, same algorithm as fnImpactData) ────────────
74
-
75
- function computeImpact(db, nodeId, noTests, maxDepth) {
76
- const visited = new Set([nodeId]);
77
- const levels = {};
78
- let frontier = [nodeId];
79
-
80
- for (let d = 1; d <= maxDepth; d++) {
81
- const nextFrontier = [];
82
- for (const fid of frontier) {
83
- const callers = db
84
- .prepare(
85
- `SELECT DISTINCT n.id, n.name, n.kind, n.file, n.line
86
- FROM edges e JOIN nodes n ON e.source_id = n.id
87
- WHERE e.target_id = ? AND e.kind = 'calls'`,
88
- )
89
- .all(fid);
90
- for (const c of callers) {
91
- if (!visited.has(c.id) && (!noTests || !isTestFile(c.file))) {
92
- visited.add(c.id);
93
- nextFrontier.push(c.id);
94
- if (!levels[d]) levels[d] = [];
95
- levels[d].push({ name: c.name, kind: c.kind, file: c.file, line: c.line });
96
- }
97
- }
98
- }
99
- frontier = nextFrontier;
100
- if (frontier.length === 0) break;
101
- }
102
-
103
- return { totalDependents: visited.size - 1, levels };
104
- }
105
-
106
78
  // ─── Phase 4.4 fields (graceful null fallback) ─────────────────────
107
79
 
108
80
  function readPhase44(db, nodeId) {
@@ -147,7 +119,7 @@ export function auditData(target, customDbPath, opts = {}) {
147
119
 
148
120
  // 2. Open DB for enrichment
149
121
  const db = openReadonlyOrFail(customDbPath);
150
- const thresholds = resolveThresholds(customDbPath);
122
+ const thresholds = resolveThresholds(customDbPath, opts.config);
151
123
 
152
124
  let functions;
153
125
  try {
@@ -189,7 +161,7 @@ function enrichFunction(db, r, noTests, maxDepth, thresholds) {
189
161
  const nodeId = nodeRow?.id;
190
162
  const health = nodeId ? buildHealth(db, nodeId, thresholds) : defaultHealth();
191
163
  const impact = nodeId
192
- ? computeImpact(db, nodeId, noTests, maxDepth)
164
+ ? bfsTransitiveCallers(db, nodeId, { noTests, maxDepth })
193
165
  : { totalDependents: 0, levels: {} };
194
166
  const phase44 = nodeId
195
167
  ? readPhase44(db, nodeId)
@@ -260,7 +232,7 @@ function enrichSymbol(db, sym, file, noTests, maxDepth, thresholds) {
260
232
 
261
233
  const health = nodeId ? buildHealth(db, nodeId, thresholds) : defaultHealth();
262
234
  const impact = nodeId
263
- ? computeImpact(db, nodeId, noTests, maxDepth)
235
+ ? bfsTransitiveCallers(db, nodeId, { noTests, maxDepth })
264
236
  : { totalDependents: 0, levels: {} };
265
237
  const phase44 = nodeId
266
238
  ? readPhase44(db, nodeId)
@@ -5,10 +5,6 @@
5
5
  * Designed for multi-agent swarms that need to dispatch 20+ queries in one call.
6
6
  */
7
7
 
8
- import { complexityData } from './complexity.js';
9
- import { dataflowData } from './dataflow.js';
10
- import { ConfigError } from './errors.js';
11
- import { flowData } from './flow.js';
12
8
  import {
13
9
  contextData,
14
10
  explainData,
@@ -18,7 +14,11 @@ import {
18
14
  fnImpactData,
19
15
  impactAnalysisData,
20
16
  whereData,
21
- } from './queries.js';
17
+ } from '../domain/queries.js';
18
+ import { ConfigError } from '../shared/errors.js';
19
+ import { complexityData } from './complexity.js';
20
+ import { dataflowData } from './dataflow.js';
21
+ import { flowData } from './flow.js';
22
22
 
23
23
  /**
24
24
  * Map of supported batch commands → their data function + first-arg semantics.
@@ -1,5 +1,5 @@
1
- import { isTestFile } from './infrastructure/test-filter.js';
2
- import { debug } from './logger.js';
1
+ import { debug } from '../infrastructure/logger.js';
2
+ import { isTestFile } from '../infrastructure/test-filter.js';
3
3
 
4
4
  // ─── Glob-to-Regex ───────────────────────────────────────────────────
5
5