@optave/codegraph 3.13.0 → 3.15.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.
- package/README.md +35 -34
- package/dist/ast-analysis/engine.d.ts.map +1 -1
- package/dist/ast-analysis/engine.js +38 -40
- package/dist/ast-analysis/engine.js.map +1 -1
- package/dist/ast-analysis/rules/b2.d.ts +7 -0
- package/dist/ast-analysis/rules/b2.d.ts.map +1 -0
- package/dist/ast-analysis/rules/b2.js +240 -0
- package/dist/ast-analysis/rules/b2.js.map +1 -0
- package/dist/ast-analysis/rules/b3.d.ts +6 -0
- package/dist/ast-analysis/rules/b3.d.ts.map +1 -0
- package/dist/ast-analysis/rules/b3.js +105 -0
- package/dist/ast-analysis/rules/b3.js.map +1 -0
- package/dist/ast-analysis/rules/b4.d.ts +9 -0
- package/dist/ast-analysis/rules/b4.d.ts.map +1 -0
- package/dist/ast-analysis/rules/b4.js +361 -0
- package/dist/ast-analysis/rules/b4.js.map +1 -0
- package/dist/ast-analysis/rules/b5.d.ts +4 -0
- package/dist/ast-analysis/rules/b5.d.ts.map +1 -0
- package/dist/ast-analysis/rules/b5.js +52 -0
- package/dist/ast-analysis/rules/b5.js.map +1 -0
- package/dist/ast-analysis/rules/c.d.ts +4 -0
- package/dist/ast-analysis/rules/c.d.ts.map +1 -0
- package/dist/ast-analysis/rules/c.js +143 -0
- package/dist/ast-analysis/rules/c.js.map +1 -0
- package/dist/ast-analysis/rules/index.d.ts.map +1 -1
- package/dist/ast-analysis/rules/index.js +34 -0
- package/dist/ast-analysis/rules/index.js.map +1 -1
- package/dist/ast-analysis/rules/javascript.d.ts.map +1 -1
- package/dist/ast-analysis/rules/javascript.js +3 -0
- package/dist/ast-analysis/rules/javascript.js.map +1 -1
- package/dist/ast-analysis/shared.d.ts.map +1 -1
- package/dist/ast-analysis/shared.js +2 -0
- package/dist/ast-analysis/shared.js.map +1 -1
- package/dist/ast-analysis/visitor-utils.d.ts +1 -0
- package/dist/ast-analysis/visitor-utils.d.ts.map +1 -1
- package/dist/ast-analysis/visitor-utils.js +5 -0
- package/dist/ast-analysis/visitor-utils.js.map +1 -1
- package/dist/ast-analysis/visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitor.js +60 -47
- package/dist/ast-analysis/visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/cfg-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/cfg-visitor.js +126 -76
- package/dist/ast-analysis/visitors/cfg-visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/complexity-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/complexity-visitor.js +27 -15
- package/dist/ast-analysis/visitors/complexity-visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/dataflow-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/dataflow-visitor.js +54 -21
- package/dist/ast-analysis/visitors/dataflow-visitor.js.map +1 -1
- package/dist/cli/commands/config.d.ts.map +1 -1
- package/dist/cli/commands/config.js +137 -134
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/roles.d.ts.map +1 -1
- package/dist/cli/commands/roles.js +6 -1
- package/dist/cli/commands/roles.js.map +1 -1
- package/dist/db/better-sqlite3.d.ts +2 -1
- package/dist/db/better-sqlite3.d.ts.map +1 -1
- package/dist/db/better-sqlite3.js.map +1 -1
- package/dist/db/connection.d.ts +7 -1
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +20 -5
- package/dist/db/connection.js.map +1 -1
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +68 -0
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/repository/build-stmts.d.ts.map +1 -1
- package/dist/db/repository/build-stmts.js +18 -0
- package/dist/db/repository/build-stmts.js.map +1 -1
- package/dist/db/repository/dataflow.d.ts +5 -0
- package/dist/db/repository/dataflow.d.ts.map +1 -1
- package/dist/db/repository/dataflow.js +14 -0
- package/dist/db/repository/dataflow.js.map +1 -1
- package/dist/db/repository/index.d.ts +1 -1
- package/dist/db/repository/index.d.ts.map +1 -1
- package/dist/db/repository/index.js +1 -1
- package/dist/db/repository/index.js.map +1 -1
- package/dist/db/repository/native-repository.d.ts.map +1 -1
- package/dist/db/repository/native-repository.js +47 -34
- package/dist/db/repository/native-repository.js.map +1 -1
- package/dist/domain/analysis/context.d.ts +2 -2
- package/dist/domain/analysis/dependencies.d.ts +2 -2
- package/dist/domain/analysis/diff-impact.d.ts +2 -2
- package/dist/domain/analysis/fn-impact.d.ts +3 -1
- package/dist/domain/analysis/fn-impact.d.ts.map +1 -1
- package/dist/domain/analysis/fn-impact.js +4 -0
- package/dist/domain/analysis/fn-impact.js.map +1 -1
- package/dist/domain/analysis/implementations.d.ts +2 -2
- package/dist/domain/analysis/module-map.d.ts.map +1 -1
- package/dist/domain/analysis/module-map.js +32 -5
- package/dist/domain/analysis/module-map.js.map +1 -1
- package/dist/domain/analysis/roles.d.ts +7 -1
- package/dist/domain/analysis/roles.d.ts.map +1 -1
- package/dist/domain/analysis/roles.js +16 -0
- package/dist/domain/analysis/roles.js.map +1 -1
- package/dist/domain/analysis/symbol-lookup.d.ts +4 -4
- package/dist/domain/graph/builder/call-resolver.d.ts +17 -5
- package/dist/domain/graph/builder/call-resolver.d.ts.map +1 -1
- package/dist/domain/graph/builder/call-resolver.js +85 -220
- package/dist/domain/graph/builder/call-resolver.js.map +1 -1
- package/dist/domain/graph/builder/context.d.ts +1 -0
- package/dist/domain/graph/builder/context.d.ts.map +1 -1
- package/dist/domain/graph/builder/context.js.map +1 -1
- package/dist/domain/graph/builder/helpers.d.ts +16 -1
- package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
- package/dist/domain/graph/builder/helpers.js +162 -72
- package/dist/domain/graph/builder/helpers.js.map +1 -1
- package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
- package/dist/domain/graph/builder/incremental.js +166 -97
- package/dist/domain/graph/builder/incremental.js.map +1 -1
- package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
- package/dist/domain/graph/builder/pipeline.js +10 -4
- package/dist/domain/graph/builder/pipeline.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.js +496 -250
- package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
- package/dist/domain/graph/builder/stages/collect-files.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/collect-files.js +10 -7
- package/dist/domain/graph/builder/stages/collect-files.js.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.js +2 -1
- package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
- package/dist/domain/graph/builder/stages/native-orchestrator.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/native-orchestrator.js +895 -545
- package/dist/domain/graph/builder/stages/native-orchestrator.js.map +1 -1
- package/dist/domain/graph/resolver/points-to.d.ts.map +1 -1
- package/dist/domain/graph/resolver/points-to.js +105 -57
- package/dist/domain/graph/resolver/points-to.js.map +1 -1
- package/dist/domain/graph/resolver/strategy.d.ts +61 -0
- package/dist/domain/graph/resolver/strategy.d.ts.map +1 -0
- package/dist/domain/graph/resolver/strategy.js +222 -0
- package/dist/domain/graph/resolver/strategy.js.map +1 -0
- package/dist/domain/graph/watcher.d.ts.map +1 -1
- package/dist/domain/graph/watcher.js +16 -9
- package/dist/domain/graph/watcher.js.map +1 -1
- package/dist/domain/parser.d.ts +12 -0
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +12 -2
- package/dist/domain/parser.js.map +1 -1
- package/dist/domain/queries.d.ts +1 -1
- package/dist/domain/queries.d.ts.map +1 -1
- package/dist/domain/queries.js +1 -1
- package/dist/domain/queries.js.map +1 -1
- package/dist/domain/wasm-worker-entry.js +3 -0
- package/dist/domain/wasm-worker-entry.js.map +1 -1
- package/dist/domain/wasm-worker-pool.d.ts.map +1 -1
- package/dist/domain/wasm-worker-pool.js +24 -5
- package/dist/domain/wasm-worker-pool.js.map +1 -1
- package/dist/domain/wasm-worker-protocol.d.ts +7 -0
- package/dist/domain/wasm-worker-protocol.d.ts.map +1 -1
- package/dist/extractors/dart.js +48 -3
- package/dist/extractors/dart.js.map +1 -1
- package/dist/extractors/groovy.js +62 -3
- package/dist/extractors/groovy.js.map +1 -1
- package/dist/extractors/helpers.d.ts +4 -2
- package/dist/extractors/helpers.d.ts.map +1 -1
- package/dist/extractors/helpers.js +5 -1
- package/dist/extractors/helpers.js.map +1 -1
- package/dist/extractors/java.js +77 -1
- package/dist/extractors/java.js.map +1 -1
- package/dist/extractors/javascript.d.ts.map +1 -1
- package/dist/extractors/javascript.js +549 -163
- package/dist/extractors/javascript.js.map +1 -1
- package/dist/extractors/kotlin.js +58 -3
- package/dist/extractors/kotlin.js.map +1 -1
- package/dist/extractors/objc.js +25 -2
- package/dist/extractors/objc.js.map +1 -1
- package/dist/extractors/scala.js +62 -2
- package/dist/extractors/scala.js.map +1 -1
- package/dist/extractors/swift.js +52 -3
- package/dist/extractors/swift.js.map +1 -1
- package/dist/features/audit.js +26 -23
- package/dist/features/audit.js.map +1 -1
- package/dist/features/boundaries.d.ts.map +1 -1
- package/dist/features/boundaries.js +12 -9
- package/dist/features/boundaries.js.map +1 -1
- package/dist/features/cfg.d.ts.map +1 -1
- package/dist/features/cfg.js +25 -18
- package/dist/features/cfg.js.map +1 -1
- package/dist/features/check.d.ts.map +1 -1
- package/dist/features/check.js +18 -5
- package/dist/features/check.js.map +1 -1
- package/dist/features/communities.d.ts +4 -2
- package/dist/features/communities.d.ts.map +1 -1
- package/dist/features/communities.js +6 -4
- package/dist/features/communities.js.map +1 -1
- package/dist/features/dataflow.d.ts +60 -0
- package/dist/features/dataflow.d.ts.map +1 -1
- package/dist/features/dataflow.js +530 -6
- package/dist/features/dataflow.js.map +1 -1
- package/dist/features/manifesto.d.ts.map +1 -1
- package/dist/features/manifesto.js +59 -72
- package/dist/features/manifesto.js.map +1 -1
- package/dist/features/sequence.d.ts.map +1 -1
- package/dist/features/sequence.js +27 -22
- package/dist/features/sequence.js.map +1 -1
- package/dist/features/snapshot.d.ts.map +1 -1
- package/dist/features/snapshot.js +36 -28
- package/dist/features/snapshot.js.map +1 -1
- package/dist/features/structure.d.ts.map +1 -1
- package/dist/features/structure.js +150 -62
- package/dist/features/structure.js.map +1 -1
- package/dist/features/triage.d.ts.map +1 -1
- package/dist/features/triage.js +18 -11
- package/dist/features/triage.js.map +1 -1
- package/dist/graph/algorithms/bfs.d.ts +1 -1
- package/dist/graph/algorithms/bfs.d.ts.map +1 -1
- package/dist/graph/algorithms/bfs.js +14 -13
- package/dist/graph/algorithms/bfs.js.map +1 -1
- package/dist/graph/algorithms/tarjan.d.ts.map +1 -1
- package/dist/graph/algorithms/tarjan.js +5 -0
- package/dist/graph/algorithms/tarjan.js.map +1 -1
- package/dist/graph/builders/dependency.js +28 -22
- package/dist/graph/builders/dependency.js.map +1 -1
- package/dist/graph/classifiers/roles.d.ts +10 -1
- package/dist/graph/classifiers/roles.d.ts.map +1 -1
- package/dist/graph/classifiers/roles.js +60 -6
- package/dist/graph/classifiers/roles.js.map +1 -1
- package/dist/infrastructure/config.d.ts +10 -0
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +31 -3
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/infrastructure/registry.d.ts +0 -7
- package/dist/infrastructure/registry.d.ts.map +1 -1
- package/dist/infrastructure/registry.js +29 -13
- package/dist/infrastructure/registry.js.map +1 -1
- package/dist/infrastructure/update-check.d.ts.map +1 -1
- package/dist/infrastructure/update-check.js +49 -31
- package/dist/infrastructure/update-check.js.map +1 -1
- package/dist/mcp/server.d.ts +2 -10
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/ast-query.d.ts +1 -1
- package/dist/mcp/tools/ast-query.d.ts.map +1 -1
- package/dist/mcp/tools/audit.d.ts +1 -1
- package/dist/mcp/tools/audit.d.ts.map +1 -1
- package/dist/mcp/tools/batch-query.d.ts +1 -1
- package/dist/mcp/tools/batch-query.d.ts.map +1 -1
- package/dist/mcp/tools/branch-compare.d.ts +1 -1
- package/dist/mcp/tools/branch-compare.d.ts.map +1 -1
- package/dist/mcp/tools/brief.d.ts +1 -1
- package/dist/mcp/tools/brief.d.ts.map +1 -1
- package/dist/mcp/tools/cfg.d.ts +1 -1
- package/dist/mcp/tools/cfg.d.ts.map +1 -1
- package/dist/mcp/tools/check.d.ts +1 -1
- package/dist/mcp/tools/check.d.ts.map +1 -1
- package/dist/mcp/tools/co-changes.d.ts +1 -1
- package/dist/mcp/tools/co-changes.d.ts.map +1 -1
- package/dist/mcp/tools/code-owners.d.ts +1 -1
- package/dist/mcp/tools/code-owners.d.ts.map +1 -1
- package/dist/mcp/tools/communities.d.ts +1 -1
- package/dist/mcp/tools/communities.d.ts.map +1 -1
- package/dist/mcp/tools/complexity.d.ts +1 -1
- package/dist/mcp/tools/complexity.d.ts.map +1 -1
- package/dist/mcp/tools/context.d.ts +1 -1
- package/dist/mcp/tools/context.d.ts.map +1 -1
- package/dist/mcp/tools/dataflow.d.ts +1 -1
- package/dist/mcp/tools/dataflow.d.ts.map +1 -1
- package/dist/mcp/tools/diff-impact.d.ts +1 -1
- package/dist/mcp/tools/diff-impact.d.ts.map +1 -1
- package/dist/mcp/tools/execution-flow.d.ts +1 -1
- package/dist/mcp/tools/execution-flow.d.ts.map +1 -1
- package/dist/mcp/tools/export-graph.d.ts +1 -1
- package/dist/mcp/tools/export-graph.d.ts.map +1 -1
- package/dist/mcp/tools/file-deps.d.ts +1 -1
- package/dist/mcp/tools/file-deps.d.ts.map +1 -1
- package/dist/mcp/tools/file-exports.d.ts +1 -1
- package/dist/mcp/tools/file-exports.d.ts.map +1 -1
- package/dist/mcp/tools/find-cycles.d.ts +1 -1
- package/dist/mcp/tools/find-cycles.d.ts.map +1 -1
- package/dist/mcp/tools/fn-impact.d.ts +1 -1
- package/dist/mcp/tools/fn-impact.d.ts.map +1 -1
- package/dist/mcp/tools/impact-analysis.d.ts +1 -1
- package/dist/mcp/tools/impact-analysis.d.ts.map +1 -1
- package/dist/mcp/tools/implementations.d.ts +1 -1
- package/dist/mcp/tools/implementations.d.ts.map +1 -1
- package/dist/mcp/tools/index.d.ts +2 -5
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/interfaces.d.ts +1 -1
- package/dist/mcp/tools/interfaces.d.ts.map +1 -1
- package/dist/mcp/tools/list-functions.d.ts +1 -1
- package/dist/mcp/tools/list-functions.d.ts.map +1 -1
- package/dist/mcp/tools/list-repos.d.ts +1 -1
- package/dist/mcp/tools/list-repos.d.ts.map +1 -1
- package/dist/mcp/tools/module-map.d.ts +1 -1
- package/dist/mcp/tools/module-map.d.ts.map +1 -1
- package/dist/mcp/tools/node-roles.d.ts +1 -1
- package/dist/mcp/tools/node-roles.d.ts.map +1 -1
- package/dist/mcp/tools/path.d.ts +1 -1
- package/dist/mcp/tools/path.d.ts.map +1 -1
- package/dist/mcp/tools/query.d.ts +1 -1
- package/dist/mcp/tools/query.d.ts.map +1 -1
- package/dist/mcp/tools/semantic-search.d.ts +1 -1
- package/dist/mcp/tools/semantic-search.d.ts.map +1 -1
- package/dist/mcp/tools/sequence.d.ts +1 -1
- package/dist/mcp/tools/sequence.d.ts.map +1 -1
- package/dist/mcp/tools/structure.d.ts +1 -1
- package/dist/mcp/tools/structure.d.ts.map +1 -1
- package/dist/mcp/tools/symbol-children.d.ts +1 -1
- package/dist/mcp/tools/symbol-children.d.ts.map +1 -1
- package/dist/mcp/tools/triage.d.ts +1 -1
- package/dist/mcp/tools/triage.d.ts.map +1 -1
- package/dist/mcp/tools/where.d.ts +1 -1
- package/dist/mcp/tools/where.d.ts.map +1 -1
- package/dist/mcp/types.d.ts +19 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +6 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/presentation/queries-cli/index.d.ts +1 -1
- package/dist/presentation/queries-cli/index.d.ts.map +1 -1
- package/dist/presentation/queries-cli/index.js +1 -1
- package/dist/presentation/queries-cli/index.js.map +1 -1
- package/dist/presentation/queries-cli/overview.d.ts +1 -0
- package/dist/presentation/queries-cli/overview.d.ts.map +1 -1
- package/dist/presentation/queries-cli/overview.js +20 -1
- package/dist/presentation/queries-cli/overview.js.map +1 -1
- package/dist/presentation/queries-cli.d.ts +1 -1
- package/dist/presentation/queries-cli.d.ts.map +1 -1
- package/dist/presentation/queries-cli.js +1 -1
- package/dist/presentation/queries-cli.js.map +1 -1
- package/dist/presentation/viewer.d.ts.map +1 -1
- package/dist/presentation/viewer.js +45 -32
- package/dist/presentation/viewer.js.map +1 -1
- package/dist/shared/constants.d.ts +21 -0
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/constants.js +25 -0
- package/dist/shared/constants.js.map +1 -1
- package/dist/shared/normalize.d.ts.map +1 -1
- package/dist/shared/normalize.js +12 -22
- package/dist/shared/normalize.js.map +1 -1
- package/dist/shared/paginate.d.ts +4 -17
- package/dist/shared/paginate.d.ts.map +1 -1
- package/dist/shared/paginate.js.map +1 -1
- package/dist/types.d.ts +76 -1
- package/dist/types.d.ts.map +1 -1
- package/grammars/tree-sitter-erlang.wasm +0 -0
- package/package.json +7 -7
- package/src/ast-analysis/engine.ts +43 -63
- package/src/ast-analysis/rules/b2.ts +263 -0
- package/src/ast-analysis/rules/b3.ts +127 -0
- package/src/ast-analysis/rules/b4.ts +378 -0
- package/src/ast-analysis/rules/b5.ts +65 -0
- package/src/ast-analysis/rules/c.ts +157 -0
- package/src/ast-analysis/rules/index.ts +34 -0
- package/src/ast-analysis/rules/javascript.ts +3 -0
- package/src/ast-analysis/shared.ts +2 -0
- package/src/ast-analysis/visitor-utils.ts +5 -0
- package/src/ast-analysis/visitor.ts +82 -52
- package/src/ast-analysis/visitors/cfg-visitor.ts +198 -84
- package/src/ast-analysis/visitors/complexity-visitor.ts +44 -16
- package/src/ast-analysis/visitors/dataflow-visitor.ts +68 -29
- package/src/cli/commands/config.ts +184 -184
- package/src/cli/commands/roles.ts +6 -1
- package/src/db/better-sqlite3.ts +5 -4
- package/src/db/connection.ts +23 -5
- package/src/db/index.ts +1 -0
- package/src/db/migrations.ts +68 -0
- package/src/db/repository/build-stmts.ts +30 -0
- package/src/db/repository/dataflow.ts +16 -0
- package/src/db/repository/index.ts +1 -1
- package/src/db/repository/native-repository.ts +56 -40
- package/src/domain/analysis/fn-impact.ts +4 -0
- package/src/domain/analysis/module-map.ts +38 -6
- package/src/domain/analysis/roles.ts +23 -0
- package/src/domain/graph/builder/call-resolver.ts +112 -232
- package/src/domain/graph/builder/context.ts +1 -0
- package/src/domain/graph/builder/helpers.ts +190 -72
- package/src/domain/graph/builder/incremental.ts +249 -120
- package/src/domain/graph/builder/pipeline.ts +11 -5
- package/src/domain/graph/builder/stages/build-edges.ts +696 -296
- package/src/domain/graph/builder/stages/collect-files.ts +12 -6
- package/src/domain/graph/builder/stages/detect-changes.ts +3 -1
- package/src/domain/graph/builder/stages/native-orchestrator.ts +1102 -590
- package/src/domain/graph/resolver/points-to.ts +182 -59
- package/src/domain/graph/resolver/strategy.ts +265 -0
- package/src/domain/graph/watcher.ts +19 -9
- package/src/domain/parser.ts +12 -2
- package/src/domain/queries.ts +1 -1
- package/src/domain/wasm-worker-entry.ts +3 -0
- package/src/domain/wasm-worker-pool.ts +28 -4
- package/src/domain/wasm-worker-protocol.ts +4 -0
- package/src/extractors/dart.ts +48 -3
- package/src/extractors/groovy.ts +62 -2
- package/src/extractors/helpers.ts +5 -2
- package/src/extractors/java.ts +80 -1
- package/src/extractors/javascript.ts +566 -161
- package/src/extractors/kotlin.ts +57 -3
- package/src/extractors/objc.ts +25 -1
- package/src/extractors/scala.ts +63 -1
- package/src/extractors/swift.ts +46 -3
- package/src/features/audit.ts +43 -34
- package/src/features/boundaries.ts +17 -9
- package/src/features/cfg.ts +31 -22
- package/src/features/check.ts +21 -5
- package/src/features/communities.ts +28 -19
- package/src/features/dataflow.ts +755 -6
- package/src/features/manifesto.ts +76 -75
- package/src/features/sequence.ts +29 -23
- package/src/features/snapshot.ts +36 -25
- package/src/features/structure.ts +185 -55
- package/src/features/triage.ts +28 -15
- package/src/graph/algorithms/bfs.ts +13 -12
- package/src/graph/algorithms/tarjan.ts +5 -0
- package/src/graph/builders/dependency.ts +35 -23
- package/src/graph/classifiers/roles.ts +74 -7
- package/src/infrastructure/config.ts +32 -3
- package/src/infrastructure/registry.ts +44 -20
- package/src/infrastructure/update-check.ts +55 -33
- package/src/mcp/server.ts +2 -8
- package/src/mcp/tools/ast-query.ts +1 -1
- package/src/mcp/tools/audit.ts +1 -1
- package/src/mcp/tools/batch-query.ts +1 -1
- package/src/mcp/tools/branch-compare.ts +1 -1
- package/src/mcp/tools/brief.ts +1 -1
- package/src/mcp/tools/cfg.ts +1 -1
- package/src/mcp/tools/check.ts +1 -1
- package/src/mcp/tools/co-changes.ts +1 -1
- package/src/mcp/tools/code-owners.ts +1 -1
- package/src/mcp/tools/communities.ts +1 -1
- package/src/mcp/tools/complexity.ts +1 -1
- package/src/mcp/tools/context.ts +1 -1
- package/src/mcp/tools/dataflow.ts +1 -1
- package/src/mcp/tools/diff-impact.ts +1 -1
- package/src/mcp/tools/execution-flow.ts +1 -1
- package/src/mcp/tools/export-graph.ts +1 -1
- package/src/mcp/tools/file-deps.ts +1 -1
- package/src/mcp/tools/file-exports.ts +1 -1
- package/src/mcp/tools/find-cycles.ts +1 -1
- package/src/mcp/tools/fn-impact.ts +1 -1
- package/src/mcp/tools/impact-analysis.ts +1 -1
- package/src/mcp/tools/implementations.ts +1 -1
- package/src/mcp/tools/index.ts +2 -5
- package/src/mcp/tools/interfaces.ts +1 -1
- package/src/mcp/tools/list-functions.ts +1 -1
- package/src/mcp/tools/list-repos.ts +1 -1
- package/src/mcp/tools/module-map.ts +1 -1
- package/src/mcp/tools/node-roles.ts +1 -1
- package/src/mcp/tools/path.ts +1 -1
- package/src/mcp/tools/query.ts +1 -1
- package/src/mcp/tools/semantic-search.ts +1 -1
- package/src/mcp/tools/sequence.ts +1 -1
- package/src/mcp/tools/structure.ts +1 -1
- package/src/mcp/tools/symbol-children.ts +1 -1
- package/src/mcp/tools/triage.ts +1 -1
- package/src/mcp/tools/where.ts +1 -1
- package/src/mcp/types.ts +21 -0
- package/src/presentation/queries-cli/index.ts +1 -1
- package/src/presentation/queries-cli/overview.ts +35 -1
- package/src/presentation/queries-cli.ts +1 -0
- package/src/presentation/viewer.ts +98 -87
- package/src/shared/constants.ts +26 -0
- package/src/shared/normalize.ts +13 -22
- package/src/shared/paginate.ts +4 -18
- package/src/types.ts +86 -1
package/src/features/triage.ts
CHANGED
|
@@ -116,6 +116,33 @@ interface TriageDataOpts {
|
|
|
116
116
|
repo?: Repository;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
interface ResolvedRiskConfig {
|
|
120
|
+
weights: RiskWeights;
|
|
121
|
+
riskOpts: { roleWeights?: Record<string, number>; defaultRoleWeight?: number };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Resolve risk weights and role-weight options from config + opts overrides. */
|
|
125
|
+
function resolveRiskConfig(opts: TriageDataOpts): ResolvedRiskConfig {
|
|
126
|
+
const config = opts.config || loadConfig();
|
|
127
|
+
const riskConfig = ((config as unknown as Record<string, unknown>).risk || {}) as {
|
|
128
|
+
weights?: Partial<RiskWeights>;
|
|
129
|
+
roleWeights?: Record<string, number>;
|
|
130
|
+
defaultRoleWeight?: number;
|
|
131
|
+
};
|
|
132
|
+
const weights: RiskWeights = {
|
|
133
|
+
...DEFAULT_WEIGHTS,
|
|
134
|
+
...(riskConfig.weights || {}),
|
|
135
|
+
...(opts.weights || {}),
|
|
136
|
+
};
|
|
137
|
+
return {
|
|
138
|
+
weights,
|
|
139
|
+
riskOpts: {
|
|
140
|
+
roleWeights: riskConfig.roleWeights,
|
|
141
|
+
defaultRoleWeight: riskConfig.defaultRoleWeight,
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
119
146
|
export function triageData(
|
|
120
147
|
customDbPath?: string,
|
|
121
148
|
opts: TriageDataOpts = {},
|
|
@@ -125,21 +152,7 @@ export function triageData(
|
|
|
125
152
|
const noTests = opts.noTests || false;
|
|
126
153
|
const minScore = opts.minScore != null ? Number(opts.minScore) : null;
|
|
127
154
|
const sort = opts.sort || 'risk';
|
|
128
|
-
const
|
|
129
|
-
const riskConfig = ((config as unknown as Record<string, unknown>).risk || {}) as {
|
|
130
|
-
weights?: Partial<RiskWeights>;
|
|
131
|
-
roleWeights?: Record<string, number>;
|
|
132
|
-
defaultRoleWeight?: number;
|
|
133
|
-
};
|
|
134
|
-
const weights: RiskWeights = {
|
|
135
|
-
...DEFAULT_WEIGHTS,
|
|
136
|
-
...(riskConfig.weights || {}),
|
|
137
|
-
...(opts.weights || {}),
|
|
138
|
-
};
|
|
139
|
-
const riskOpts = {
|
|
140
|
-
roleWeights: riskConfig.roleWeights,
|
|
141
|
-
defaultRoleWeight: riskConfig.defaultRoleWeight,
|
|
142
|
-
};
|
|
155
|
+
const { weights, riskOpts } = resolveRiskConfig(opts);
|
|
143
156
|
|
|
144
157
|
let rows: TriageNodeRow[];
|
|
145
158
|
try {
|
|
@@ -6,10 +6,17 @@ export interface BfsOpts {
|
|
|
6
6
|
direction?: 'forward' | 'backward' | 'both';
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
/** Resolve the neighbor list for a node given traversal direction. */
|
|
10
|
+
function getNeighbors(graph: CodeGraph, node: string, direction: string): string[] {
|
|
11
|
+
if (direction === 'forward') return graph.successors(node);
|
|
12
|
+
if (direction === 'backward') return graph.predecessors(node);
|
|
13
|
+
return graph.neighbors(node);
|
|
14
|
+
}
|
|
15
|
+
|
|
9
16
|
/**
|
|
10
17
|
* Breadth-first traversal on a CodeGraph.
|
|
11
18
|
*
|
|
12
|
-
* Tries the native Rust implementation first, falls back to JS.
|
|
19
|
+
* Tries the native Rust implementation first, falls back to a pure-JS queue.
|
|
13
20
|
*
|
|
14
21
|
* @returns nodeId → depth from nearest start node
|
|
15
22
|
*/
|
|
@@ -46,7 +53,10 @@ export function bfs(
|
|
|
46
53
|
return bfsJS(graph, starts, maxDepth, direction);
|
|
47
54
|
}
|
|
48
55
|
|
|
49
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* Pure-JS BFS queue (used when native addon is unavailable).
|
|
58
|
+
* Separated from bfs() to keep each function's complexity within thresholds.
|
|
59
|
+
*/
|
|
50
60
|
function bfsJS(
|
|
51
61
|
graph: CodeGraph,
|
|
52
62
|
starts: string[],
|
|
@@ -70,16 +80,7 @@ function bfsJS(
|
|
|
70
80
|
const depth = depths.get(current)!;
|
|
71
81
|
if (depth >= maxDepth) continue;
|
|
72
82
|
|
|
73
|
-
|
|
74
|
-
if (direction === 'forward') {
|
|
75
|
-
neighbors = graph.successors(current);
|
|
76
|
-
} else if (direction === 'backward') {
|
|
77
|
-
neighbors = graph.predecessors(current);
|
|
78
|
-
} else {
|
|
79
|
-
neighbors = graph.neighbors(current);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
for (const n of neighbors) {
|
|
83
|
+
for (const n of getNeighbors(graph, current, direction)) {
|
|
83
84
|
if (!depths.has(n)) {
|
|
84
85
|
depths.set(n, depth + 1);
|
|
85
86
|
queue.push(n);
|
|
@@ -15,6 +15,7 @@ export function tarjan(graph: CodeGraph): string[][] {
|
|
|
15
15
|
const sccs: string[][] = [];
|
|
16
16
|
|
|
17
17
|
function strongconnect(v: string): void {
|
|
18
|
+
// Assign the next discovery index and initialise lowlink to self
|
|
18
19
|
indices.set(v, index);
|
|
19
20
|
lowlinks.set(v, index);
|
|
20
21
|
index++;
|
|
@@ -23,13 +24,16 @@ export function tarjan(graph: CodeGraph): string[][] {
|
|
|
23
24
|
|
|
24
25
|
for (const w of graph.successors(v)) {
|
|
25
26
|
if (!indices.has(w)) {
|
|
27
|
+
// Tree edge: recurse then propagate lowlink upward
|
|
26
28
|
strongconnect(w);
|
|
27
29
|
lowlinks.set(v, Math.min(lowlinks.get(v)!, lowlinks.get(w)!));
|
|
28
30
|
} else if (onStack.has(w)) {
|
|
31
|
+
// Back/cross edge to a node still on the stack: update lowlink via index
|
|
29
32
|
lowlinks.set(v, Math.min(lowlinks.get(v)!, indices.get(w)!));
|
|
30
33
|
}
|
|
31
34
|
}
|
|
32
35
|
|
|
36
|
+
// v is the root of an SCC when its lowlink equals its own discovery index
|
|
33
37
|
if (lowlinks.get(v) === indices.get(v)) {
|
|
34
38
|
const scc: string[] = [];
|
|
35
39
|
let w: string | undefined;
|
|
@@ -38,6 +42,7 @@ export function tarjan(graph: CodeGraph): string[][] {
|
|
|
38
42
|
onStack.delete(w);
|
|
39
43
|
scc.push(w);
|
|
40
44
|
} while (w !== v);
|
|
45
|
+
// Only report non-trivial SCCs (length > 1 = a real cycle)
|
|
41
46
|
if (scc.length > 1) sccs.push(scc);
|
|
42
47
|
}
|
|
43
48
|
}
|
|
@@ -78,6 +78,37 @@ interface MinConfidenceEdgeRow {
|
|
|
78
78
|
target_id: number;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Fetch call edges from `dbOrRepo`, optionally filtered by a minimum confidence
|
|
83
|
+
* threshold. When `minConfidence` is unset, all call edges are returned.
|
|
84
|
+
*/
|
|
85
|
+
function resolveCallEdges(
|
|
86
|
+
dbOrRepo: BetterSqlite3Database | Repository,
|
|
87
|
+
isRepo: boolean,
|
|
88
|
+
minConfidence?: number,
|
|
89
|
+
): CallEdgeRow[] | MinConfidenceEdgeRow[] {
|
|
90
|
+
if (minConfidence == null) {
|
|
91
|
+
return isRepo
|
|
92
|
+
? (dbOrRepo as Repository).getCallEdges()
|
|
93
|
+
: getCallEdges(dbOrRepo as BetterSqlite3Database);
|
|
94
|
+
}
|
|
95
|
+
if (isRepo) {
|
|
96
|
+
// Trade-off: Repository.getCallEdges() returns all call edges, so we
|
|
97
|
+
// filter in JS. This is O(all call edges) rather than the SQL path's
|
|
98
|
+
// indexed WHERE clause. Acceptable for current data sizes; a dedicated
|
|
99
|
+
// getCallEdgesByMinConfidence(threshold) method on the Repository
|
|
100
|
+
// interface would be the proper fix if this becomes a bottleneck.
|
|
101
|
+
return (dbOrRepo as Repository)
|
|
102
|
+
.getCallEdges()
|
|
103
|
+
.filter((e) => e.confidence != null && e.confidence >= minConfidence);
|
|
104
|
+
}
|
|
105
|
+
return (dbOrRepo as BetterSqlite3Database)
|
|
106
|
+
.prepare<MinConfidenceEdgeRow>(
|
|
107
|
+
"SELECT source_id, target_id FROM edges WHERE kind = 'calls' AND confidence >= ?",
|
|
108
|
+
)
|
|
109
|
+
.all(minConfidence);
|
|
110
|
+
}
|
|
111
|
+
|
|
81
112
|
function buildFunctionLevelGraph(
|
|
82
113
|
dbOrRepo: BetterSqlite3Database | Repository,
|
|
83
114
|
noTests: boolean,
|
|
@@ -86,7 +117,9 @@ function buildFunctionLevelGraph(
|
|
|
86
117
|
const graph = new CodeGraph();
|
|
87
118
|
const isRepo = dbOrRepo instanceof Repository;
|
|
88
119
|
|
|
89
|
-
let nodes: CallableNodeRow[] = isRepo
|
|
120
|
+
let nodes: CallableNodeRow[] = isRepo
|
|
121
|
+
? (dbOrRepo as Repository).getCallableNodes()
|
|
122
|
+
: getCallableNodes(dbOrRepo as BetterSqlite3Database);
|
|
90
123
|
if (noTests) nodes = nodes.filter((n) => !isTestFile(n.file));
|
|
91
124
|
|
|
92
125
|
const nodeIds = new Set<number>();
|
|
@@ -100,28 +133,7 @@ function buildFunctionLevelGraph(
|
|
|
100
133
|
nodeIds.add(n.id);
|
|
101
134
|
}
|
|
102
135
|
|
|
103
|
-
|
|
104
|
-
if (minConfidence != null) {
|
|
105
|
-
if (isRepo) {
|
|
106
|
-
// Trade-off: Repository.getCallEdges() returns all call edges, so we
|
|
107
|
-
// filter in JS. This is O(all call edges) rather than the SQL path's
|
|
108
|
-
// indexed WHERE clause. Acceptable for current data sizes; a dedicated
|
|
109
|
-
// getCallEdgesByMinConfidence(threshold) method on the Repository
|
|
110
|
-
// interface would be the proper fix if this becomes a bottleneck.
|
|
111
|
-
edges = dbOrRepo
|
|
112
|
-
.getCallEdges()
|
|
113
|
-
.filter((e) => e.confidence != null && e.confidence >= minConfidence);
|
|
114
|
-
} else {
|
|
115
|
-
edges = (dbOrRepo as BetterSqlite3Database)
|
|
116
|
-
.prepare<MinConfidenceEdgeRow>(
|
|
117
|
-
"SELECT source_id, target_id FROM edges WHERE kind = 'calls' AND confidence >= ?",
|
|
118
|
-
)
|
|
119
|
-
.all(minConfidence);
|
|
120
|
-
}
|
|
121
|
-
} else {
|
|
122
|
-
edges = isRepo ? dbOrRepo.getCallEdges() : getCallEdges(dbOrRepo);
|
|
123
|
-
}
|
|
124
|
-
|
|
136
|
+
const edges = resolveCallEdges(dbOrRepo, isRepo, minConfidence);
|
|
125
137
|
for (const e of edges) {
|
|
126
138
|
if (!nodeIds.has(e.source_id) || !nodeIds.has(e.target_id)) continue;
|
|
127
139
|
const src = String(e.source_id);
|
|
@@ -18,6 +18,14 @@ export const FRAMEWORK_ENTRY_PREFIXES: readonly string[] = ['route:', 'event:',
|
|
|
18
18
|
|
|
19
19
|
const LEAF_KINDS = new Set(['parameter', 'property', 'constant']);
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Type definition kinds that are consumed via type annotations rather than calls.
|
|
23
|
+
* These have no inbound call edges by design — they are "used" by type references,
|
|
24
|
+
* struct literals, and generic parameters, none of which produce call edges.
|
|
25
|
+
* If the same file has active callables, type definitions are almost certainly live.
|
|
26
|
+
*/
|
|
27
|
+
const TYPE_DEF_KINDS = new Set(['struct', 'enum', 'trait', 'type', 'interface', 'record']);
|
|
28
|
+
|
|
21
29
|
const FFI_EXTENSIONS = new Set(['.rs', '.c', '.cpp', '.h', '.go', '.java', '.cs']);
|
|
22
30
|
|
|
23
31
|
/** Path patterns indicating framework-dispatched entry points. */
|
|
@@ -29,6 +37,17 @@ const ENTRY_PATH_PATTERNS: readonly RegExp[] = [
|
|
|
29
37
|
/middleware[/\\]/,
|
|
30
38
|
];
|
|
31
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Well-known Commander.js dispatch method names.
|
|
42
|
+
* When a method with one of these names lives in a file that matches
|
|
43
|
+
* ENTRY_PATH_PATTERNS, it is the actual framework entry point — not merely a
|
|
44
|
+
* candidate — so it must be classified as `entry` rather than `dead-entry`.
|
|
45
|
+
*
|
|
46
|
+
* `execute` — the action callback invoked by Commander on `program.action()`.
|
|
47
|
+
* `validate` — a pre-execution argument/option validator called before `execute`.
|
|
48
|
+
*/
|
|
49
|
+
const COMMANDER_DISPATCH_NAMES = new Set(['execute', 'validate']);
|
|
50
|
+
|
|
32
51
|
export interface ClassifiableNode {
|
|
33
52
|
kind?: string;
|
|
34
53
|
file?: string;
|
|
@@ -74,7 +93,16 @@ export interface RoleClassificationNode {
|
|
|
74
93
|
isExported: boolean;
|
|
75
94
|
testOnlyFanIn?: number;
|
|
76
95
|
productionFanIn?: number;
|
|
77
|
-
/**
|
|
96
|
+
/**
|
|
97
|
+
* True when the same file contains at least one callable connected to the graph
|
|
98
|
+
* (fanIn > 0 or fanOut > 0) that is not itself an annotation-only kind.
|
|
99
|
+
* Annotation-only kinds are `constant` and all members of `TYPE_DEF_KINDS`
|
|
100
|
+
* (struct, enum, trait, type, interface, record) — these are excluded because
|
|
101
|
+
* they are consumed via references/type-annotations rather than call edges and
|
|
102
|
+
* would otherwise produce a circular dependency in the active-file heuristic.
|
|
103
|
+
* Populated only for `constant` and `TYPE_DEF_KINDS` nodes; `undefined` for
|
|
104
|
+
* regular callables (functions, methods, classes, etc.) which don't need it.
|
|
105
|
+
*/
|
|
78
106
|
hasActiveFileSiblings?: boolean;
|
|
79
107
|
}
|
|
80
108
|
|
|
@@ -99,11 +127,37 @@ function computeFanMedians(nodes: RoleClassificationNode[]): { fanIn: number; fa
|
|
|
99
127
|
* Covers framework-active constants, test-only callables, and the dead-* family.
|
|
100
128
|
*/
|
|
101
129
|
function classifyUnreferencedNode(node: RoleClassificationNode): Role {
|
|
102
|
-
if (node.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
130
|
+
if (node.hasActiveFileSiblings) {
|
|
131
|
+
if (node.kind === 'constant') {
|
|
132
|
+
// Constants consumed via identifier reference (not calls) have no
|
|
133
|
+
// inbound call edges. If the same file has active callables, the
|
|
134
|
+
// constant is almost certainly used locally — classify as leaf.
|
|
135
|
+
return 'leaf';
|
|
136
|
+
}
|
|
137
|
+
if (node.kind && TYPE_DEF_KINDS.has(node.kind)) {
|
|
138
|
+
// Type definitions (struct, enum, trait, type, interface, record) are
|
|
139
|
+
// consumed via type annotations and struct literals — not calls — so they
|
|
140
|
+
// never get inbound call edges. If the same file has active callables,
|
|
141
|
+
// these types are almost certainly live — classify as leaf.
|
|
142
|
+
return 'leaf';
|
|
143
|
+
}
|
|
144
|
+
if (node.kind === 'method' && node.fanOut > 0) {
|
|
145
|
+
// Methods implementing interfaces are dispatched via conditional property
|
|
146
|
+
// access e.g. `if (v.enterFunction) v.enterFunction(...)`. Codegraph
|
|
147
|
+
// resolves the call to the property accessor rather than to the concrete
|
|
148
|
+
// method implementation, so the method has no inbound call edge. We
|
|
149
|
+
// require `fanOut > 0` as evidence of non-triviality, mirroring the
|
|
150
|
+
// function case — trivially-inert dead helper methods remain visible.
|
|
151
|
+
return 'leaf';
|
|
152
|
+
}
|
|
153
|
+
if (node.kind === 'function' && node.fanOut > 0) {
|
|
154
|
+
// Functions referenced as logical-or fallback defaults — e.g.
|
|
155
|
+
// `const fn = options._fetchLatest || fetchLatestVersion` — appear as
|
|
156
|
+
// value references, not call sites, so no call edge is produced. We
|
|
157
|
+
// require `fanOut > 0` as evidence that the function is non-trivial
|
|
158
|
+
// (i.e. it calls something), ruling out truly inert dead helpers.
|
|
159
|
+
return 'leaf';
|
|
160
|
+
}
|
|
107
161
|
}
|
|
108
162
|
if (node.testOnlyFanIn != null && node.testOnlyFanIn > 0) return 'test-only';
|
|
109
163
|
return classifyDeadSubRole(node);
|
|
@@ -129,7 +183,20 @@ function classifyNodeRole(node: RoleClassificationNode, medFanIn: number, medFan
|
|
|
129
183
|
if (FRAMEWORK_ENTRY_PREFIXES.some((p) => node.name.startsWith(p))) return 'entry';
|
|
130
184
|
|
|
131
185
|
if (node.fanIn === 0) {
|
|
132
|
-
|
|
186
|
+
if (!node.isExported) {
|
|
187
|
+
// Well-known Commander.js dispatch methods (execute, validate) in framework
|
|
188
|
+
// directories are confirmed entry points, not candidates. Promote them to
|
|
189
|
+
// `entry` directly so they don't appear in `--role dead` output.
|
|
190
|
+
if (
|
|
191
|
+
node.file &&
|
|
192
|
+
COMMANDER_DISPATCH_NAMES.has(node.name) &&
|
|
193
|
+
ENTRY_PATH_PATTERNS.some((p) => p.test(node.file!))
|
|
194
|
+
) {
|
|
195
|
+
return 'entry';
|
|
196
|
+
}
|
|
197
|
+
return classifyUnreferencedNode(node);
|
|
198
|
+
}
|
|
199
|
+
return 'entry';
|
|
133
200
|
}
|
|
134
201
|
|
|
135
202
|
const hasProdFanIn = typeof node.productionFanIn === 'number';
|
|
@@ -21,6 +21,7 @@ export const DEFAULTS = {
|
|
|
21
21
|
include: [] as string[],
|
|
22
22
|
exclude: [] as string[],
|
|
23
23
|
ignoreDirs: [] as string[],
|
|
24
|
+
ignoreAdditionalDirs: [] as string[],
|
|
24
25
|
extensions: [] as string[],
|
|
25
26
|
aliases: {} as Record<string, string>,
|
|
26
27
|
build: {
|
|
@@ -29,6 +30,8 @@ export const DEFAULTS = {
|
|
|
29
30
|
driftThreshold: 0.2,
|
|
30
31
|
smallFilesThreshold: 5,
|
|
31
32
|
typescriptResolver: true,
|
|
33
|
+
engine: 'auto' as 'auto' | 'native' | 'wasm',
|
|
34
|
+
fastSkipDiag: false,
|
|
32
35
|
},
|
|
33
36
|
query: {
|
|
34
37
|
defaultDepth: 3,
|
|
@@ -87,9 +90,16 @@ export const DEFAULTS = {
|
|
|
87
90
|
// TODO(Phase 8.3): wire these into the points-to solver and type-propagation path
|
|
88
91
|
// once config is threaded through to extractSymbols / buildPointsToMap. Currently
|
|
89
92
|
// controlled by hardcoded constants in src/extractors/javascript.ts
|
|
90
|
-
// (MAX_PROPAGATION_DEPTH, PROPAGATION_HOP_PENALTY) and in
|
|
93
|
+
// (MAX_PROPAGATION_DEPTH, PROPAGATION_HOP_PENALTY, INFERRED_RETURN_TYPE_CONFIDENCE) and in
|
|
91
94
|
// src/domain/graph/resolver/points-to.ts (MAX_SOLVER_ITERATIONS).
|
|
92
95
|
typePropagationDepth: 3,
|
|
96
|
+
/**
|
|
97
|
+
* Confidence score assigned to a return type inferred from `return new Constructor()`
|
|
98
|
+
* when no explicit TypeScript annotation is present.
|
|
99
|
+
* Mirrors `INFERRED_RETURN_TYPE_CONFIDENCE` in `src/extractors/javascript.ts`.
|
|
100
|
+
* @reserved — not yet wired; see TODO above.
|
|
101
|
+
*/
|
|
102
|
+
typeInferenceConfidence: 0.85,
|
|
93
103
|
/**
|
|
94
104
|
* Maximum fixed-point iterations for the Phase 8.3 points-to solver.
|
|
95
105
|
* @reserved — currently not wired to either the WASM solver
|
|
@@ -443,6 +453,7 @@ const BUILD_HASH_KEYS: ReadonlyArray<keyof CodegraphConfig> = [
|
|
|
443
453
|
'include',
|
|
444
454
|
'exclude',
|
|
445
455
|
'ignoreDirs',
|
|
456
|
+
'ignoreAdditionalDirs',
|
|
446
457
|
'extensions',
|
|
447
458
|
'aliases',
|
|
448
459
|
'build',
|
|
@@ -658,8 +669,8 @@ export function loadConfigWithProvenance(
|
|
|
658
669
|
const raw = JSON.parse(fs.readFileSync(filePath, 'utf-8')) as Record<string, unknown>;
|
|
659
670
|
for (const k of Object.keys(raw)) provenance[k] = 'project';
|
|
660
671
|
break;
|
|
661
|
-
} catch {
|
|
662
|
-
|
|
672
|
+
} catch (err) {
|
|
673
|
+
debug(`loadConfigWithProvenance: failed to parse ${filePath}: ${toErrorMessage(err)}`);
|
|
663
674
|
}
|
|
664
675
|
}
|
|
665
676
|
}
|
|
@@ -686,6 +697,24 @@ export function applyEnvOverrides(config: CodegraphConfig): CodegraphConfig {
|
|
|
686
697
|
process.env[envKey as keyof NodeJS.ProcessEnv];
|
|
687
698
|
}
|
|
688
699
|
}
|
|
700
|
+
// Engine selection: CODEGRAPH_ENGINE env always wins over config-file value.
|
|
701
|
+
if (process.env.CODEGRAPH_ENGINE !== undefined) {
|
|
702
|
+
const raw = process.env.CODEGRAPH_ENGINE;
|
|
703
|
+
const valid = ['auto', 'native', 'wasm'] as const;
|
|
704
|
+
if ((valid as readonly string[]).includes(raw)) {
|
|
705
|
+
(config.build as Record<string, unknown>).engine = raw as 'auto' | 'native' | 'wasm';
|
|
706
|
+
} else {
|
|
707
|
+
warn(
|
|
708
|
+
`CODEGRAPH_ENGINE="${raw}" is not a valid engine value (expected auto|native|wasm). Falling back to "auto".`,
|
|
709
|
+
);
|
|
710
|
+
(config.build as Record<string, unknown>).engine = 'auto';
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
// Fast-skip diagnostic flag.
|
|
714
|
+
if (process.env.CODEGRAPH_FAST_SKIP_DIAG !== undefined) {
|
|
715
|
+
(config.build as Record<string, unknown>).fastSkipDiag =
|
|
716
|
+
process.env.CODEGRAPH_FAST_SKIP_DIAG === '1';
|
|
717
|
+
}
|
|
689
718
|
return config;
|
|
690
719
|
}
|
|
691
720
|
|
|
@@ -242,19 +242,18 @@ interface PrunedEntry {
|
|
|
242
242
|
*
|
|
243
243
|
* When `dryRun` is true, entries are identified but not removed from disk.
|
|
244
244
|
*/
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
245
|
+
/**
|
|
246
|
+
* Walk `registry.repos`, identify entries that are missing on disk or have
|
|
247
|
+
* exceeded the TTL, and optionally delete them (when `dryRun` is false).
|
|
248
|
+
* Returns the list of entries that were (or would be) pruned.
|
|
249
|
+
*/
|
|
250
|
+
function pruneRepoEntries(
|
|
251
|
+
registry: Registry,
|
|
252
|
+
cutoff: number,
|
|
253
|
+
excludeSet: Set<string>,
|
|
254
|
+
dryRun: boolean,
|
|
250
255
|
): PrunedEntry[] {
|
|
251
|
-
const registry = loadRegistry(registryPath);
|
|
252
256
|
const pruned: PrunedEntry[] = [];
|
|
253
|
-
const cutoff = Date.now() - ttlDays * 24 * 60 * 60 * 1000;
|
|
254
|
-
const excludeSet = new Set(
|
|
255
|
-
excludeNames.filter((n) => typeof n === 'string' && n.trim().length > 0),
|
|
256
|
-
);
|
|
257
|
-
|
|
258
257
|
for (const [name, entry] of Object.entries(registry.repos)) {
|
|
259
258
|
if (excludeSet.has(name)) continue;
|
|
260
259
|
if (!fs.existsSync(entry.path)) {
|
|
@@ -268,18 +267,43 @@ export function pruneRegistry(
|
|
|
268
267
|
if (!dryRun) delete registry.repos[name];
|
|
269
268
|
}
|
|
270
269
|
}
|
|
270
|
+
return pruned;
|
|
271
|
+
}
|
|
271
272
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
273
|
+
/**
|
|
274
|
+
* Prune consent entries whose repo paths no longer exist on disk.
|
|
275
|
+
* Consent entries are TTL-exempt — only the missing-path rule applies.
|
|
276
|
+
* Returns true when at least one entry was removed.
|
|
277
|
+
*/
|
|
278
|
+
function pruneConsentEntries(consent: Record<string, ConsentDecision>): boolean {
|
|
279
|
+
let changed = false;
|
|
280
|
+
for (const p of Object.keys(consent)) {
|
|
281
|
+
if (!fs.existsSync(p)) {
|
|
282
|
+
delete consent[p];
|
|
283
|
+
changed = true;
|
|
281
284
|
}
|
|
282
285
|
}
|
|
286
|
+
return changed;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function pruneRegistry(
|
|
290
|
+
registryPath: string = REGISTRY_PATH,
|
|
291
|
+
ttlDays: number = DEFAULT_TTL_DAYS,
|
|
292
|
+
excludeNames: string[] = [],
|
|
293
|
+
dryRun = false,
|
|
294
|
+
): PrunedEntry[] {
|
|
295
|
+
const registry = loadRegistry(registryPath);
|
|
296
|
+
const cutoff = Date.now() - ttlDays * 24 * 60 * 60 * 1000;
|
|
297
|
+
const excludeSet = new Set(
|
|
298
|
+
excludeNames.filter((n) => typeof n === 'string' && n.trim().length > 0),
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
const pruned = pruneRepoEntries(registry, cutoff, excludeSet, dryRun);
|
|
302
|
+
|
|
303
|
+
const consentChanged =
|
|
304
|
+
!dryRun && registry.userConfig?.consent
|
|
305
|
+
? pruneConsentEntries(registry.userConfig.consent)
|
|
306
|
+
: false;
|
|
283
307
|
|
|
284
308
|
if (!dryRun && (pruned.length > 0 || consentChanged)) {
|
|
285
309
|
saveRegistry(registry, registryPath);
|
|
@@ -61,6 +61,33 @@ function saveCache(cache: UpdateCache, cachePath: string = CACHE_PATH): void {
|
|
|
61
61
|
fs.renameSync(tmp, cachePath);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Collect the full response body from an IncomingMessage stream.
|
|
66
|
+
* Resolves with the body string, or null on parse/status error.
|
|
67
|
+
*/
|
|
68
|
+
function collectResponseBody(res: import('node:http').IncomingMessage): Promise<string | null> {
|
|
69
|
+
return new Promise((resolve) => {
|
|
70
|
+
if (res.statusCode !== 200) {
|
|
71
|
+
res.resume();
|
|
72
|
+
resolve(null);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
let body = '';
|
|
76
|
+
res.setEncoding('utf-8');
|
|
77
|
+
res.on('data', (chunk: string) => {
|
|
78
|
+
body += chunk;
|
|
79
|
+
});
|
|
80
|
+
res.on('end', () => {
|
|
81
|
+
try {
|
|
82
|
+
const data = JSON.parse(body);
|
|
83
|
+
resolve(typeof data.version === 'string' ? data.version : null);
|
|
84
|
+
} catch {
|
|
85
|
+
resolve(null);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
64
91
|
/**
|
|
65
92
|
* Fetch the latest version string from the npm registry.
|
|
66
93
|
* Returns the version string or null on failure.
|
|
@@ -71,24 +98,7 @@ function fetchLatestVersion(): Promise<string | null> {
|
|
|
71
98
|
REGISTRY_URL,
|
|
72
99
|
{ timeout: FETCH_TIMEOUT_MS, headers: { Accept: 'application/json' } },
|
|
73
100
|
(res) => {
|
|
74
|
-
|
|
75
|
-
res.resume();
|
|
76
|
-
resolve(null);
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
let body = '';
|
|
80
|
-
res.setEncoding('utf-8');
|
|
81
|
-
res.on('data', (chunk: string) => {
|
|
82
|
-
body += chunk;
|
|
83
|
-
});
|
|
84
|
-
res.on('end', () => {
|
|
85
|
-
try {
|
|
86
|
-
const data = JSON.parse(body);
|
|
87
|
-
resolve(typeof data.version === 'string' ? data.version : null);
|
|
88
|
-
} catch {
|
|
89
|
-
resolve(null);
|
|
90
|
-
}
|
|
91
|
-
});
|
|
101
|
+
collectResponseBody(res).then(resolve);
|
|
92
102
|
},
|
|
93
103
|
);
|
|
94
104
|
req.on('error', () => resolve(null));
|
|
@@ -109,6 +119,32 @@ interface CheckForUpdatesOptions {
|
|
|
109
119
|
_fetchLatest?: () => Promise<string | null>;
|
|
110
120
|
}
|
|
111
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Return the latest version from cache if fresh, or fetch it from the registry.
|
|
124
|
+
* Persists the fetched version to the cache only when a network fetch occurs
|
|
125
|
+
* (i.e. the cache is stale or missing). Returns the cached value directly
|
|
126
|
+
* without updating the cache when the cache is still within `CACHE_TTL_MS`.
|
|
127
|
+
* Returns null when the network fetch fails or the cache is corrupt.
|
|
128
|
+
*/
|
|
129
|
+
async function resolveLatestVersion(
|
|
130
|
+
cachePath: string,
|
|
131
|
+
fetchFn: () => Promise<string | null>,
|
|
132
|
+
): Promise<string | null> {
|
|
133
|
+
const cache = loadCache(cachePath);
|
|
134
|
+
|
|
135
|
+
if (cache && Date.now() - cache.lastCheckedAt < CACHE_TTL_MS) {
|
|
136
|
+
// Cache is fresh — use stored value directly
|
|
137
|
+
return cache.latestVersion;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Cache is stale or missing — fetch from registry
|
|
141
|
+
const latest = await fetchFn();
|
|
142
|
+
if (!latest) return null;
|
|
143
|
+
|
|
144
|
+
saveCache({ lastCheckedAt: Date.now(), latestVersion: latest }, cachePath);
|
|
145
|
+
return latest;
|
|
146
|
+
}
|
|
147
|
+
|
|
112
148
|
/**
|
|
113
149
|
* Check whether a newer version of codegraph is available.
|
|
114
150
|
*
|
|
@@ -129,23 +165,9 @@ export async function checkForUpdates(
|
|
|
129
165
|
const fetchFn = options._fetchLatest || fetchLatestVersion;
|
|
130
166
|
|
|
131
167
|
try {
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
// Cache is fresh — use it
|
|
135
|
-
if (cache && Date.now() - cache.lastCheckedAt < CACHE_TTL_MS) {
|
|
136
|
-
if (semverCompare(currentVersion, cache.latestVersion) < 0) {
|
|
137
|
-
return { current: currentVersion, latest: cache.latestVersion };
|
|
138
|
-
}
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Cache is stale or missing — fetch
|
|
143
|
-
const latest = await fetchFn();
|
|
168
|
+
const latest = await resolveLatestVersion(cachePath, fetchFn);
|
|
144
169
|
if (!latest) return null;
|
|
145
170
|
|
|
146
|
-
// Update cache regardless of result
|
|
147
|
-
saveCache({ lastCheckedAt: Date.now(), latestVersion: latest }, cachePath);
|
|
148
|
-
|
|
149
171
|
if (semverCompare(currentVersion, latest) < 0) {
|
|
150
172
|
return { current: currentVersion, latest };
|
|
151
173
|
}
|
package/src/mcp/server.ts
CHANGED
|
@@ -20,6 +20,7 @@ import type { CodegraphConfig, MCPServerOptions } from '../types.js';
|
|
|
20
20
|
import { initMcpDefaults } from './middleware.js';
|
|
21
21
|
import { buildToolList } from './tool-registry.js';
|
|
22
22
|
import { TOOL_HANDLERS } from './tools/index.js';
|
|
23
|
+
import type { McpToolContext } from './types.js';
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* Module-level guard to register shutdown handlers only once per process.
|
|
@@ -28,14 +29,7 @@ import { TOOL_HANDLERS } from './tools/index.js';
|
|
|
28
29
|
*/
|
|
29
30
|
let _activeServer: any = null;
|
|
30
31
|
|
|
31
|
-
export
|
|
32
|
-
dbPath: string | undefined;
|
|
33
|
-
getQueries(): Promise<any>;
|
|
34
|
-
getDatabase(): any;
|
|
35
|
-
findDbPath: typeof findDbPath;
|
|
36
|
-
allowedRepos: string[] | undefined;
|
|
37
|
-
MCP_MAX_LIMIT: number;
|
|
38
|
-
}
|
|
32
|
+
export type { McpToolContext };
|
|
39
33
|
|
|
40
34
|
interface MCPServerOptionsInternal extends MCPServerOptions {
|
|
41
35
|
config?: CodegraphConfig;
|
package/src/mcp/tools/audit.ts
CHANGED
package/src/mcp/tools/brief.ts
CHANGED