@optave/codegraph 3.12.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 +83 -46
- 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/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +2 -1
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/batch.d.ts.map +1 -1
- package/dist/cli/commands/batch.js +1 -0
- package/dist/cli/commands/batch.js.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +6 -1
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/config.d.ts +3 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +275 -0
- package/dist/cli/commands/config.js.map +1 -0
- 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/cli/commands/triage.js +1 -1
- package/dist/cli/commands/triage.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +10 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/shared/options.d.ts +2 -1
- package/dist/cli/shared/options.d.ts.map +1 -1
- package/dist/cli/shared/options.js +11 -1
- package/dist/cli/shared/options.js.map +1 -1
- package/dist/cli/types.d.ts +2 -0
- package/dist/cli/types.d.ts.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 +69 -1
- 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 +29 -13
- package/dist/domain/graph/builder/call-resolver.d.ts.map +1 -1
- package/dist/domain/graph/builder/call-resolver.js +125 -205
- package/dist/domain/graph/builder/call-resolver.js.map +1 -1
- package/dist/domain/graph/builder/cha.d.ts +9 -1
- package/dist/domain/graph/builder/cha.d.ts.map +1 -1
- package/dist/domain/graph/builder/cha.js +17 -2
- package/dist/domain/graph/builder/cha.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 +24 -1
- package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
- package/dist/domain/graph/builder/helpers.js +174 -65
- 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 +46 -5
- package/dist/domain/graph/builder/pipeline.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.d.ts +0 -2
- package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.js +554 -538
- 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 +3 -2
- package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.js +4 -0
- package/dist/domain/graph/builder/stages/finalize.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 +952 -343
- package/dist/domain/graph/builder/stages/native-orchestrator.js.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.js +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.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 +16 -5
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +58 -17
- 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 +13 -2
- 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 +26 -5
- package/dist/domain/wasm-worker-pool.js.map +1 -1
- package/dist/domain/wasm-worker-protocol.d.ts +8 -0
- package/dist/domain/wasm-worker-protocol.d.ts.map +1 -1
- package/dist/extractors/cpp.d.ts.map +1 -1
- package/dist/extractors/cpp.js +42 -1
- package/dist/extractors/cpp.js.map +1 -1
- package/dist/extractors/cuda.d.ts.map +1 -1
- package/dist/extractors/cuda.js +42 -1
- package/dist/extractors/cuda.js.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 +15 -2
- package/dist/extractors/helpers.d.ts.map +1 -1
- package/dist/extractors/helpers.js +45 -1
- package/dist/extractors/helpers.js.map +1 -1
- package/dist/extractors/java.d.ts.map +1 -1
- package/dist/extractors/java.js +85 -8
- package/dist/extractors/java.js.map +1 -1
- package/dist/extractors/javascript.d.ts.map +1 -1
- package/dist/extractors/javascript.js +686 -169
- 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-query.d.ts +1 -1
- package/dist/features/structure-query.d.ts.map +1 -1
- package/dist/features/structure-query.js +6 -6
- package/dist/features/structure-query.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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/config.d.ts +87 -4
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +424 -22
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/infrastructure/registry.d.ts +27 -7
- package/dist/infrastructure/registry.d.ts.map +1 -1
- package/dist/infrastructure/registry.js +79 -5
- 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/structure.d.ts +1 -1
- package/dist/presentation/structure.d.ts.map +1 -1
- package/dist/presentation/structure.js +2 -2
- package/dist/presentation/structure.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 +113 -1
- package/dist/types.d.ts.map +1 -1
- package/grammars/tree-sitter-erlang.wasm +0 -0
- package/grammars/tree-sitter-gleam.wasm +0 -0
- package/package.json +7 -8
- 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/audit.ts +2 -1
- package/src/cli/commands/batch.ts +1 -0
- package/src/cli/commands/build.ts +6 -1
- package/src/cli/commands/config.ts +353 -0
- package/src/cli/commands/roles.ts +6 -1
- package/src/cli/commands/triage.ts +1 -1
- package/src/cli/index.ts +10 -0
- package/src/cli/shared/options.ts +11 -1
- package/src/cli/types.ts +2 -0
- 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 +69 -1
- 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 +156 -218
- package/src/domain/graph/builder/cha.ts +18 -1
- package/src/domain/graph/builder/context.ts +1 -0
- package/src/domain/graph/builder/helpers.ts +205 -67
- package/src/domain/graph/builder/incremental.ts +249 -119
- package/src/domain/graph/builder/pipeline.ts +59 -6
- package/src/domain/graph/builder/stages/build-edges.ts +783 -652
- package/src/domain/graph/builder/stages/collect-files.ts +12 -6
- package/src/domain/graph/builder/stages/detect-changes.ts +4 -2
- package/src/domain/graph/builder/stages/finalize.ts +4 -0
- package/src/domain/graph/builder/stages/native-orchestrator.ts +1214 -398
- package/src/domain/graph/builder/stages/resolve-imports.ts +1 -1
- 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 +57 -16
- package/src/domain/queries.ts +1 -1
- package/src/domain/wasm-worker-entry.ts +13 -2
- package/src/domain/wasm-worker-pool.ts +29 -4
- package/src/domain/wasm-worker-protocol.ts +5 -0
- package/src/extractors/cpp.ts +44 -1
- package/src/extractors/cuda.ts +44 -1
- package/src/extractors/dart.ts +48 -3
- package/src/extractors/groovy.ts +62 -2
- package/src/extractors/helpers.ts +48 -2
- package/src/extractors/java.ts +88 -8
- package/src/extractors/javascript.ts +693 -167
- 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-query.ts +7 -7
- 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/index.ts +5 -1
- package/src/infrastructure/config.ts +511 -23
- package/src/infrastructure/registry.ts +117 -12
- 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/structure.ts +3 -3
- 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 +127 -1
|
@@ -287,6 +287,28 @@ function handleAssignment(
|
|
|
287
287
|
}
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
+
/** Unwrap argument wrapper and spread nodes to get the core argument node. */
|
|
291
|
+
function unwrapArg(
|
|
292
|
+
arg: TreeSitterNode,
|
|
293
|
+
rules: AnyRules,
|
|
294
|
+
): { unwrapped: TreeSitterNode; raw: TreeSitterNode } {
|
|
295
|
+
let raw = arg;
|
|
296
|
+
if (rules.argumentWrapperType && arg.type === rules.argumentWrapperType) {
|
|
297
|
+
raw = arg.namedChildren[0] || arg;
|
|
298
|
+
}
|
|
299
|
+
const unwrapped =
|
|
300
|
+
rules.spreadType && raw.type === rules.spreadType ? raw.namedChildren[0] || raw : raw;
|
|
301
|
+
return { unwrapped, raw };
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/** Resolve the tracked name for a call argument (identifier or member receiver). */
|
|
305
|
+
function resolveArgTrackedName(node: TreeSitterNode, rules: AnyRules): string | null {
|
|
306
|
+
const argName = isIdent(node.type, rules) ? node.text : null;
|
|
307
|
+
const argMember =
|
|
308
|
+
rules.memberNode && node.type === rules.memberNode ? memberReceiver(node, rules) : null;
|
|
309
|
+
return argName || argMember;
|
|
310
|
+
}
|
|
311
|
+
|
|
290
312
|
function handleCallExpr(
|
|
291
313
|
node: TreeSitterNode,
|
|
292
314
|
rules: AnyRules,
|
|
@@ -299,24 +321,14 @@ function handleCallExpr(
|
|
|
299
321
|
if (!callee || !argsNode || !scope?.funcName) return;
|
|
300
322
|
|
|
301
323
|
let argIndex = 0;
|
|
302
|
-
for (
|
|
303
|
-
|
|
304
|
-
arg = arg.namedChildren[0] || arg;
|
|
305
|
-
}
|
|
306
|
-
const unwrapped =
|
|
307
|
-
rules.spreadType && arg.type === rules.spreadType ? arg.namedChildren[0] || arg : arg;
|
|
324
|
+
for (const arg of argsNode.namedChildren) {
|
|
325
|
+
const { unwrapped, raw } = unwrapArg(arg, rules);
|
|
308
326
|
if (!unwrapped) {
|
|
309
327
|
argIndex++;
|
|
310
328
|
continue;
|
|
311
329
|
}
|
|
312
330
|
|
|
313
|
-
const
|
|
314
|
-
const argMember =
|
|
315
|
-
rules.memberNode && unwrapped.type === rules.memberNode
|
|
316
|
-
? memberReceiver(unwrapped, rules)
|
|
317
|
-
: null;
|
|
318
|
-
const trackedName = argName || argMember;
|
|
319
|
-
|
|
331
|
+
const trackedName = resolveArgTrackedName(unwrapped, rules);
|
|
320
332
|
if (trackedName) {
|
|
321
333
|
const binding = findBinding(trackedName, scopeStack);
|
|
322
334
|
if (binding) {
|
|
@@ -327,7 +339,7 @@ function handleCallExpr(
|
|
|
327
339
|
argName: trackedName,
|
|
328
340
|
binding,
|
|
329
341
|
confidence: bindingConfidence(binding),
|
|
330
|
-
expression: truncate(
|
|
342
|
+
expression: truncate(raw.text),
|
|
331
343
|
line: node.startPosition.row + 1,
|
|
332
344
|
});
|
|
333
345
|
}
|
|
@@ -336,17 +348,11 @@ function handleCallExpr(
|
|
|
336
348
|
}
|
|
337
349
|
}
|
|
338
350
|
|
|
339
|
-
|
|
340
|
-
|
|
351
|
+
/** Resolve the method name and receiver from a call expression node. */
|
|
352
|
+
function resolveMutationCallParts(
|
|
353
|
+
expr: TreeSitterNode,
|
|
341
354
|
rules: AnyRules,
|
|
342
|
-
|
|
343
|
-
mutations: DataflowMutation[],
|
|
344
|
-
isCallNode: (t: string) => boolean,
|
|
345
|
-
): void {
|
|
346
|
-
if (rules.mutatingMethods.size === 0) return;
|
|
347
|
-
const expr = node.namedChildren[0];
|
|
348
|
-
if (!expr || !isCall(expr, isCallNode)) return;
|
|
349
|
-
|
|
355
|
+
): { methodName: string | null; receiver: string | null } {
|
|
350
356
|
let methodName: string | null = null;
|
|
351
357
|
let receiver: string | null = null;
|
|
352
358
|
|
|
@@ -366,6 +372,21 @@ function handleExprStmtMutation(
|
|
|
366
372
|
}
|
|
367
373
|
}
|
|
368
374
|
|
|
375
|
+
return { methodName, receiver };
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function handleExprStmtMutation(
|
|
379
|
+
node: TreeSitterNode,
|
|
380
|
+
rules: AnyRules,
|
|
381
|
+
scopeStack: ScopeEntry[],
|
|
382
|
+
mutations: DataflowMutation[],
|
|
383
|
+
isCallNode: (t: string) => boolean,
|
|
384
|
+
): void {
|
|
385
|
+
if (rules.mutatingMethods.size === 0) return;
|
|
386
|
+
const expr = node.namedChildren[0];
|
|
387
|
+
if (!expr || !isCall(expr, isCallNode)) return;
|
|
388
|
+
|
|
389
|
+
const { methodName, receiver } = resolveMutationCallParts(expr, rules);
|
|
369
390
|
if (!methodName || !rules.mutatingMethods.has(methodName)) return;
|
|
370
391
|
|
|
371
392
|
const scope = currentScope(scopeStack);
|
|
@@ -405,15 +426,27 @@ function handleReturn(
|
|
|
405
426
|
}
|
|
406
427
|
}
|
|
407
428
|
|
|
408
|
-
/**
|
|
429
|
+
/**
|
|
430
|
+
* Collect parameter entries for a function and push a new scope onto the stack.
|
|
431
|
+
*
|
|
432
|
+
* Returns `true` if a scope was pushed, `false` if the node was skipped (i.e.
|
|
433
|
+
* `nameExtractor` rejected it). Callers must pop the stack only when this
|
|
434
|
+
* returns `true` to keep push/pop symmetric.
|
|
435
|
+
*/
|
|
409
436
|
function enterFunctionScope(
|
|
410
437
|
funcNode: TreeSitterNode,
|
|
411
438
|
rules: AnyRules,
|
|
412
439
|
scopeStack: ScopeEntry[],
|
|
413
440
|
parameters: DataflowParam[],
|
|
414
|
-
):
|
|
441
|
+
): boolean {
|
|
442
|
+
// When nameExtractor is set it acts as a gate: null means this node is not a function
|
|
443
|
+
// definition. Needed for languages (Elixir, Clojure) where functionNodes includes generic
|
|
444
|
+
// node types (call/list_lit) that are only sometimes function definitions.
|
|
445
|
+
if (rules.nameExtractor && !rules.nameExtractor(funcNode)) return false;
|
|
415
446
|
const name = functionName(funcNode, rules);
|
|
416
|
-
const paramsNode =
|
|
447
|
+
const paramsNode = rules.getParamListNode
|
|
448
|
+
? rules.getParamListNode(funcNode)
|
|
449
|
+
: funcNode.childForFieldName(rules.paramListField);
|
|
417
450
|
const paramList = extractParams(paramsNode, rules);
|
|
418
451
|
const paramMap = new Map<string, number>();
|
|
419
452
|
for (const p of paramList) {
|
|
@@ -428,6 +461,7 @@ function enterFunctionScope(
|
|
|
428
461
|
}
|
|
429
462
|
}
|
|
430
463
|
scopeStack.push({ funcName: name, funcNode, params: paramMap, locals: new Map() });
|
|
464
|
+
return true;
|
|
431
465
|
}
|
|
432
466
|
|
|
433
467
|
interface DataflowDispatchCtx {
|
|
@@ -489,6 +523,11 @@ export function createDataflowVisitor(rules: AnyRules): Visitor {
|
|
|
489
523
|
const argFlows: DataflowArgFlow[] = [];
|
|
490
524
|
const mutations: DataflowMutation[] = [];
|
|
491
525
|
const scopeStack: ScopeEntry[] = [];
|
|
526
|
+
// Parallel stack that records whether each enterFunction call actually pushed a
|
|
527
|
+
// scope frame. exitFunction pops scopeStack only when the matching entry is true,
|
|
528
|
+
// keeping push/pop symmetric even for languages (Elixir, Clojure) where
|
|
529
|
+
// enterFunctionScope may return early without pushing.
|
|
530
|
+
const pushRecord: boolean[] = [];
|
|
492
531
|
|
|
493
532
|
const dispatchCtx: DataflowDispatchCtx = {
|
|
494
533
|
rules,
|
|
@@ -509,7 +548,7 @@ export function createDataflowVisitor(rules: AnyRules): Visitor {
|
|
|
509
548
|
_funcName: string | null,
|
|
510
549
|
_context: VisitorContext,
|
|
511
550
|
): void {
|
|
512
|
-
enterFunctionScope(funcNode, rules, scopeStack, parameters);
|
|
551
|
+
pushRecord.push(enterFunctionScope(funcNode, rules, scopeStack, parameters));
|
|
513
552
|
},
|
|
514
553
|
|
|
515
554
|
exitFunction(
|
|
@@ -517,7 +556,7 @@ export function createDataflowVisitor(rules: AnyRules): Visitor {
|
|
|
517
556
|
_funcName: string | null,
|
|
518
557
|
_context: VisitorContext,
|
|
519
558
|
): void {
|
|
520
|
-
scopeStack.pop();
|
|
559
|
+
if (pushRecord.pop()) scopeStack.pop();
|
|
521
560
|
},
|
|
522
561
|
|
|
523
562
|
enterNode(node: TreeSitterNode, _context: VisitorContext): EnterNodeResult | undefined {
|
|
@@ -7,7 +7,8 @@ import type { CommandDefinition } from '../types.js';
|
|
|
7
7
|
|
|
8
8
|
export const command: CommandDefinition = {
|
|
9
9
|
name: 'audit <target>',
|
|
10
|
-
|
|
10
|
+
alias: 'explain',
|
|
11
|
+
description: 'Composite report: explain + impact + health metrics per function (alias: explain)',
|
|
11
12
|
options: [
|
|
12
13
|
['-d, --db <path>', 'Path to graph.db'],
|
|
13
14
|
['--quick', 'Structural summary only (skip impact analysis and health metrics)'],
|
|
@@ -18,6 +18,7 @@ export const command: CommandDefinition = {
|
|
|
18
18
|
['-k, --kind <kind>', 'Filter by symbol kind'],
|
|
19
19
|
['-T, --no-tests', 'Exclude test/spec files from results'],
|
|
20
20
|
['--include-tests', 'Include test/spec files (overrides excludeTests config)'],
|
|
21
|
+
['-j, --json', 'Accepted for script compatibility (batch always outputs JSON)'],
|
|
21
22
|
],
|
|
22
23
|
validate([_command, _targets], opts) {
|
|
23
24
|
if (opts.kind && !(EVERY_SYMBOL_KIND as readonly string[]).includes(opts.kind)) {
|
|
@@ -16,7 +16,10 @@ export const command: CommandDefinition = {
|
|
|
16
16
|
],
|
|
17
17
|
async execute([dir], opts, ctx) {
|
|
18
18
|
const root = path.resolve(dir || '.');
|
|
19
|
-
const
|
|
19
|
+
const globalOpts = ctx.program.opts();
|
|
20
|
+
const engine = globalOpts.engine;
|
|
21
|
+
// Prompt for global-config consent on interactive TTY builds (§4.3).
|
|
22
|
+
const promptForConsent = !process.env.CI && !!process.stdin.isTTY && !!process.stdout.isTTY;
|
|
20
23
|
await buildGraph(root, {
|
|
21
24
|
incremental: opts.incremental as boolean,
|
|
22
25
|
ast: opts.ast as boolean,
|
|
@@ -25,6 +28,8 @@ export const command: CommandDefinition = {
|
|
|
25
28
|
dataflow: opts.dataflow as boolean,
|
|
26
29
|
cfg: opts.cfg as boolean,
|
|
27
30
|
dbPath: opts.db ? path.resolve(opts.db as string) : undefined,
|
|
31
|
+
userConfig: globalOpts.userConfig as string | boolean | undefined,
|
|
32
|
+
promptForConsent,
|
|
28
33
|
});
|
|
29
34
|
},
|
|
30
35
|
};
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import {
|
|
5
|
+
clearConfigCache,
|
|
6
|
+
DEFAULTS,
|
|
7
|
+
getDefaultUserConfigPath,
|
|
8
|
+
loadConfig,
|
|
9
|
+
loadConfigWithProvenance,
|
|
10
|
+
resolveUserConfigPath,
|
|
11
|
+
} from '../../infrastructure/config.js';
|
|
12
|
+
import {
|
|
13
|
+
getUserConfigConsent,
|
|
14
|
+
listUserConfigConsent,
|
|
15
|
+
REGISTRY_PATH,
|
|
16
|
+
setUserConfigConsent,
|
|
17
|
+
} from '../../infrastructure/registry.js';
|
|
18
|
+
import { formatTable } from '../../presentation/table.js';
|
|
19
|
+
import type { ConfigSource } from '../../types.js';
|
|
20
|
+
import type { CommandDefinition } from '../types.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Recursively flatten a nested config object to dot-notation key/value pairs.
|
|
24
|
+
* Arrays and null values are serialised to strings.
|
|
25
|
+
*/
|
|
26
|
+
function flattenConfig(
|
|
27
|
+
obj: Record<string, unknown>,
|
|
28
|
+
prefix = '',
|
|
29
|
+
): Array<{ key: string; value: string }> {
|
|
30
|
+
const out: Array<{ key: string; value: string }> = [];
|
|
31
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
32
|
+
const fullKey = prefix ? `${prefix}.${k}` : k;
|
|
33
|
+
if (v !== null && typeof v === 'object' && !Array.isArray(v)) {
|
|
34
|
+
out.push(...flattenConfig(v as Record<string, unknown>, fullKey));
|
|
35
|
+
} else if (Array.isArray(v)) {
|
|
36
|
+
out.push({ key: fullKey, value: v.length === 0 ? '[]' : JSON.stringify(v) });
|
|
37
|
+
} else {
|
|
38
|
+
out.push({ key: fullKey, value: v === null ? 'null' : String(v) });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Expand a top-level provenance map (e.g. { build: 'project' }) to cover every
|
|
46
|
+
* flattened dot-notation key (e.g. 'build.incremental' → 'project').
|
|
47
|
+
*/
|
|
48
|
+
function expandProvenance(
|
|
49
|
+
flatEntries: Array<{ key: string; value: string }>,
|
|
50
|
+
provenance: Record<string, ConfigSource>,
|
|
51
|
+
): Map<string, ConfigSource> {
|
|
52
|
+
const map = new Map<string, ConfigSource>();
|
|
53
|
+
for (const { key } of flatEntries) {
|
|
54
|
+
// Provenance is keyed by top-level section (e.g. 'build', 'llm'), so
|
|
55
|
+
// extract the first segment to find the governing provenance entry.
|
|
56
|
+
const topLevel = key.split('.')[0] ?? key;
|
|
57
|
+
map.set(key, provenance[topLevel] ?? 'default');
|
|
58
|
+
}
|
|
59
|
+
return map;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Render the effective config as a human-readable Key/Value/Source table.
|
|
64
|
+
* All rows are shown, sorted so non-default overrides appear first, then
|
|
65
|
+
* remaining defaults alphabetically.
|
|
66
|
+
*/
|
|
67
|
+
function renderConfigTable(
|
|
68
|
+
config: Record<string, unknown>,
|
|
69
|
+
provenance: Record<string, ConfigSource>,
|
|
70
|
+
): string {
|
|
71
|
+
const flat = flattenConfig(config);
|
|
72
|
+
const sourceMap = expandProvenance(flat, provenance);
|
|
73
|
+
|
|
74
|
+
// Show all entries — sorting non-defaults first, then alphabetically
|
|
75
|
+
const rows = flat
|
|
76
|
+
.slice()
|
|
77
|
+
.sort((a, b) => {
|
|
78
|
+
const sa = sourceMap.get(a.key) ?? 'default';
|
|
79
|
+
const sb = sourceMap.get(b.key) ?? 'default';
|
|
80
|
+
// Non-defaults first
|
|
81
|
+
if (sa !== 'default' && sb === 'default') return -1;
|
|
82
|
+
if (sa === 'default' && sb !== 'default') return 1;
|
|
83
|
+
return a.key.localeCompare(b.key);
|
|
84
|
+
})
|
|
85
|
+
.map(({ key, value }) => [key, value, sourceMap.get(key) ?? 'default']);
|
|
86
|
+
|
|
87
|
+
const keyWidth = Math.max(3, ...rows.map((r) => r[0]!.length));
|
|
88
|
+
const valWidth = Math.max(5, ...rows.map((r) => r[1]!.length));
|
|
89
|
+
// Source column is always short ('default', 'user', 'project', 'env')
|
|
90
|
+
const srcWidth = 7;
|
|
91
|
+
|
|
92
|
+
return `${formatTable({
|
|
93
|
+
columns: [
|
|
94
|
+
{ header: 'Key', width: keyWidth },
|
|
95
|
+
{ header: 'Value', width: valWidth },
|
|
96
|
+
{ header: 'Source', width: srcWidth },
|
|
97
|
+
],
|
|
98
|
+
rows: rows as string[][],
|
|
99
|
+
indent: 0,
|
|
100
|
+
})}\n`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Build a scaffolded global config JSON file.
|
|
105
|
+
* Produces valid JSON with common sections pre-populated at their defaults.
|
|
106
|
+
* Uses DEFAULTS so the values always reflect the current schema.
|
|
107
|
+
*
|
|
108
|
+
* All keys are optional — users can delete sections they don't need.
|
|
109
|
+
*/
|
|
110
|
+
function buildInitTemplate(): string {
|
|
111
|
+
// Build a plain object — no comments in JSON, but keep it self-explanatory.
|
|
112
|
+
// Unknown top-level keys are silently ignored by mergeConfig.
|
|
113
|
+
const template: Record<string, unknown> = {
|
|
114
|
+
// LLM provider for AI features (codegraph explain, context, etc.)
|
|
115
|
+
// Use apiKeyCommand to pull the key from a secret manager at runtime.
|
|
116
|
+
// Scope to specific repos with:
|
|
117
|
+
// { "appliesTo": ["~/projects/*"], "config": { ... } }
|
|
118
|
+
llm: {
|
|
119
|
+
provider: DEFAULTS.llm.provider,
|
|
120
|
+
model: DEFAULTS.llm.model,
|
|
121
|
+
baseUrl: DEFAULTS.llm.baseUrl,
|
|
122
|
+
apiKey: DEFAULTS.llm.apiKey,
|
|
123
|
+
apiKeyCommand: DEFAULTS.llm.apiKeyCommand,
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
query: {
|
|
127
|
+
defaultDepth: DEFAULTS.query.defaultDepth,
|
|
128
|
+
defaultLimit: DEFAULTS.query.defaultLimit,
|
|
129
|
+
excludeTests: DEFAULTS.query.excludeTests,
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
build: {
|
|
133
|
+
incremental: DEFAULTS.build.incremental,
|
|
134
|
+
typescriptResolver: DEFAULTS.build.typescriptResolver,
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
ci: {
|
|
138
|
+
failOnCycles: DEFAULTS.ci.failOnCycles,
|
|
139
|
+
impactThreshold: DEFAULTS.ci.impactThreshold,
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
search: {
|
|
143
|
+
defaultMinScore: DEFAULTS.search.defaultMinScore,
|
|
144
|
+
topK: DEFAULTS.search.topK,
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
return `${JSON.stringify(template, null, 2)}\n`;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ─── Subcommand handlers ───────────────────────────────────────────────
|
|
152
|
+
|
|
153
|
+
function handleInit(): void {
|
|
154
|
+
const targetPath = getDefaultUserConfigPath();
|
|
155
|
+
if (fs.existsSync(targetPath)) {
|
|
156
|
+
process.stderr.write(
|
|
157
|
+
`Global config already exists at ${targetPath}\n` +
|
|
158
|
+
`Run \`codegraph config --edit\` to open it, or delete it and re-run --init.\n`,
|
|
159
|
+
);
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
163
|
+
fs.writeFileSync(targetPath, buildInitTemplate(), 'utf-8');
|
|
164
|
+
process.stdout.write(`Created global config at ${targetPath}\n`);
|
|
165
|
+
process.stdout.write(
|
|
166
|
+
`Next steps:\n` +
|
|
167
|
+
` 1. Edit the file: codegraph config --edit\n` +
|
|
168
|
+
` 2. Enable it for this repo: codegraph config --enable-global\n`,
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function handleEdit(): void {
|
|
173
|
+
// Prefer the existing file; fall back to the default path so the user
|
|
174
|
+
// can create-and-edit in one step even before running --init.
|
|
175
|
+
const filePath = resolveUserConfigPath() ?? getDefaultUserConfigPath();
|
|
176
|
+
|
|
177
|
+
const editor = process.env.EDITOR || process.env.VISUAL;
|
|
178
|
+
if (!editor) {
|
|
179
|
+
process.stdout.write(`${filePath}\n`);
|
|
180
|
+
process.stderr.write(
|
|
181
|
+
`$EDITOR is not set. Set it in your shell profile (e.g. export EDITOR=nano)\n` +
|
|
182
|
+
`or open the file manually at the path printed above.\n`,
|
|
183
|
+
);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Ensure the directory exists so the editor can create the file
|
|
188
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
189
|
+
|
|
190
|
+
const result = spawnSync(editor, [filePath], { stdio: 'inherit' });
|
|
191
|
+
if (result.error) {
|
|
192
|
+
process.stderr.write(`Failed to launch editor "${editor}": ${result.error.message}\n`);
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
if (result.status !== 0) {
|
|
196
|
+
process.exit(result.status ?? 1);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function handleEnableGlobal(rootDir: string): void {
|
|
201
|
+
setUserConfigConsent(rootDir, 'enabled');
|
|
202
|
+
clearConfigCache();
|
|
203
|
+
const globalPath = resolveUserConfigPath();
|
|
204
|
+
if (!globalPath) {
|
|
205
|
+
process.stderr.write(
|
|
206
|
+
`Consent recorded: "enabled" for ${rootDir}\n` +
|
|
207
|
+
`Note: no global config file found. Create one at ~/.config/codegraph/config.json\n`,
|
|
208
|
+
);
|
|
209
|
+
} else {
|
|
210
|
+
process.stderr.write(
|
|
211
|
+
`Consent recorded: "enabled" for ${rootDir}\n` + `Global config: ${globalPath}\n`,
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function handleDisableGlobal(rootDir: string): void {
|
|
217
|
+
setUserConfigConsent(rootDir, 'disabled');
|
|
218
|
+
clearConfigCache();
|
|
219
|
+
process.stderr.write(`Consent recorded: "disabled" for ${rootDir}\n`);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function handleListGlobal(json: boolean): void {
|
|
223
|
+
const entries = listUserConfigConsent(REGISTRY_PATH);
|
|
224
|
+
if (json) {
|
|
225
|
+
process.stdout.write(`${JSON.stringify(entries, null, 2)}\n`);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (entries.length === 0) {
|
|
229
|
+
process.stdout.write('No repos have a recorded global-config consent decision.\n');
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
process.stdout.write('Global config consent decisions:\n\n');
|
|
233
|
+
for (const { path: p, decision } of entries) {
|
|
234
|
+
process.stdout.write(` ${decision === 'enabled' ? '✔' : '✘'} ${decision.padEnd(8)} ${p}\n`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function handleExplain(
|
|
239
|
+
rootDir: string,
|
|
240
|
+
json: boolean,
|
|
241
|
+
userConfigOverride: string | undefined,
|
|
242
|
+
): void {
|
|
243
|
+
const { config, provenance, appliedGlobalPath, consentDecision } = loadConfigWithProvenance(
|
|
244
|
+
rootDir,
|
|
245
|
+
{ userConfig: userConfigOverride },
|
|
246
|
+
);
|
|
247
|
+
const globalPath = resolveUserConfigPath();
|
|
248
|
+
const consent = getUserConfigConsent(rootDir);
|
|
249
|
+
|
|
250
|
+
if (json) {
|
|
251
|
+
process.stdout.write(
|
|
252
|
+
`${JSON.stringify(
|
|
253
|
+
{
|
|
254
|
+
config,
|
|
255
|
+
provenance,
|
|
256
|
+
appliedGlobalPath,
|
|
257
|
+
globalFilePath: globalPath,
|
|
258
|
+
consentDecision: consentDecision ?? consent ?? 'undecided',
|
|
259
|
+
},
|
|
260
|
+
null,
|
|
261
|
+
2,
|
|
262
|
+
)}\n`,
|
|
263
|
+
);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Human-readable explain output
|
|
268
|
+
process.stdout.write('=== Codegraph config provenance ===\n\n');
|
|
269
|
+
|
|
270
|
+
const consentStr = consentDecision ?? consent ?? 'undecided';
|
|
271
|
+
process.stdout.write(`Global config file : ${globalPath ?? '(none found)'}\n`);
|
|
272
|
+
process.stdout.write(`Applied this run : ${appliedGlobalPath ? 'yes' : 'no'}\n`);
|
|
273
|
+
process.stdout.write(`Consent for repo : ${consentStr}\n`);
|
|
274
|
+
process.stdout.write(
|
|
275
|
+
` (change with \`codegraph config --enable-global\` or \`--disable-global\`)\n`,
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
if (!globalPath) {
|
|
279
|
+
process.stdout.write(
|
|
280
|
+
`\nDiscovery hint: create a global config at ~/.config/codegraph/config.json\n` +
|
|
281
|
+
`then run \`codegraph config --enable-global\` in repos where you want it applied.\n`,
|
|
282
|
+
);
|
|
283
|
+
} else if (!appliedGlobalPath) {
|
|
284
|
+
process.stdout.write(
|
|
285
|
+
`\nDiscovery hint: global config exists but is not applied to this repo.\n` +
|
|
286
|
+
`Run \`codegraph config --enable-global\` to enable it here.\n`,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
process.stdout.write('\n--- Per-key provenance ---\n\n');
|
|
291
|
+
const provenanceEntries = Object.entries(provenance).sort(([a], [b]) => a.localeCompare(b));
|
|
292
|
+
for (const [key, source] of provenanceEntries) {
|
|
293
|
+
process.stdout.write(` ${source.padEnd(8)} ${key}\n`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function handleShowConfig(
|
|
298
|
+
rootDir: string,
|
|
299
|
+
json: boolean,
|
|
300
|
+
userConfigOverride: string | undefined,
|
|
301
|
+
): void {
|
|
302
|
+
const globalPath = resolveUserConfigPath();
|
|
303
|
+
const consent = getUserConfigConsent(rootDir);
|
|
304
|
+
|
|
305
|
+
if (json) {
|
|
306
|
+
const config = loadConfig(rootDir, { userConfig: userConfigOverride });
|
|
307
|
+
process.stdout.write(`${JSON.stringify(config, null, 2)}\n`);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Human-readable table: Key | Value | Source
|
|
312
|
+
const { config, provenance } = loadConfigWithProvenance(rootDir, {
|
|
313
|
+
userConfig: userConfigOverride,
|
|
314
|
+
});
|
|
315
|
+
process.stdout.write(renderConfigTable(config as unknown as Record<string, unknown>, provenance));
|
|
316
|
+
|
|
317
|
+
if (globalPath && !consent) {
|
|
318
|
+
process.stderr.write(
|
|
319
|
+
`\nℹ Global config found at ${globalPath} — not applied to this repo.\n` +
|
|
320
|
+
` Run \`codegraph config --enable-global\` to opt in, or\n` +
|
|
321
|
+
` \`codegraph config --disable-global\` to dismiss this notice.\n`,
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export const command: CommandDefinition = {
|
|
327
|
+
name: 'config',
|
|
328
|
+
description: 'Show or manage codegraph configuration (project + user-level global config)',
|
|
329
|
+
options: [
|
|
330
|
+
['-j, --json', 'Output as JSON'],
|
|
331
|
+
['--explain', 'Show per-key provenance (default / user / project / env)'],
|
|
332
|
+
['--enable-global', 'Record consent to apply the global config to this repo'],
|
|
333
|
+
['--disable-global', 'Record consent to skip the global config for this repo'],
|
|
334
|
+
['--list-global', 'List all repos with a recorded consent decision'],
|
|
335
|
+
[
|
|
336
|
+
'--init',
|
|
337
|
+
'Scaffold a global config file at the default XDG location with all sections pre-populated',
|
|
338
|
+
],
|
|
339
|
+
['--edit', 'Open the global config file in $EDITOR (prints the path if $EDITOR is unset)'],
|
|
340
|
+
],
|
|
341
|
+
execute(_args, opts, ctx) {
|
|
342
|
+
const rootDir = path.resolve('.');
|
|
343
|
+
const userConfigOverride = ctx.program.opts().userConfig as string | undefined;
|
|
344
|
+
|
|
345
|
+
if (opts.init) return handleInit();
|
|
346
|
+
if (opts.edit) return handleEdit();
|
|
347
|
+
if (opts.enableGlobal) return handleEnableGlobal(rootDir);
|
|
348
|
+
if (opts.disableGlobal) return handleDisableGlobal(rootDir);
|
|
349
|
+
if (opts.listGlobal) return handleListGlobal(opts.json);
|
|
350
|
+
if (opts.explain) return handleExplain(rootDir, opts.json, userConfigOverride);
|
|
351
|
+
return handleShowConfig(rootDir, opts.json, userConfigOverride);
|
|
352
|
+
},
|
|
353
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { collectFile } from '../../db/query-builder.js';
|
|
2
2
|
import { VALID_ROLES } from '../../domain/queries.js';
|
|
3
|
-
import { roles } from '../../presentation/queries-cli.js';
|
|
3
|
+
import { dynamicCalls, roles } from '../../presentation/queries-cli.js';
|
|
4
4
|
import type { CommandDefinition } from '../types.js';
|
|
5
5
|
|
|
6
6
|
export const command: CommandDefinition = {
|
|
@@ -17,6 +17,7 @@ export const command: CommandDefinition = {
|
|
|
17
17
|
['-n, --limit <number>', 'Max results to return'],
|
|
18
18
|
['--offset <number>', 'Skip N results (default: 0)'],
|
|
19
19
|
['--ndjson', 'Newline-delimited JSON output'],
|
|
20
|
+
['--dynamic', 'Show flagged dynamic call sites instead of symbol roles'],
|
|
20
21
|
],
|
|
21
22
|
validate(_args, opts) {
|
|
22
23
|
if (opts.role && !(VALID_ROLES as readonly string[]).includes(opts.role)) {
|
|
@@ -24,6 +25,10 @@ export const command: CommandDefinition = {
|
|
|
24
25
|
}
|
|
25
26
|
},
|
|
26
27
|
execute(_args, opts, ctx) {
|
|
28
|
+
if (opts.dynamic) {
|
|
29
|
+
dynamicCalls(opts.db, ctx.resolveQueryOpts(opts));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
27
32
|
roles(opts.db, {
|
|
28
33
|
role: opts.role,
|
|
29
34
|
file: opts.file,
|
|
@@ -31,7 +31,7 @@ async function runHotspots(opts: CommandOpts, ctx: CliContext): Promise<void> {
|
|
|
31
31
|
offset: opts.offset ? parseInt(opts.offset as string, 10) : undefined,
|
|
32
32
|
noTests: ctx.resolveNoTests(opts),
|
|
33
33
|
});
|
|
34
|
-
if (!ctx.outputResult(data, '
|
|
34
|
+
if (!ctx.outputResult(data, 'items', opts)) {
|
|
35
35
|
console.log(formatHotspots(data));
|
|
36
36
|
}
|
|
37
37
|
}
|
package/src/cli/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
4
4
|
import { Command } from 'commander';
|
|
5
|
+
import { setUserConfigOverride } from '../infrastructure/config.js';
|
|
5
6
|
import { setVerbose } from '../infrastructure/logger.js';
|
|
6
7
|
import { checkForUpdates, printUpdateNotification } from '../infrastructure/update-check.js';
|
|
7
8
|
import { ConfigError } from '../shared/errors.js';
|
|
@@ -25,9 +26,16 @@ program
|
|
|
25
26
|
.version(pkg.version)
|
|
26
27
|
.option('-v, --verbose', 'Enable verbose/debug output')
|
|
27
28
|
.option('--engine <engine>', 'Parser engine: native, wasm, or auto (default: auto)', 'auto')
|
|
29
|
+
.option('--user-config [path]', 'Apply global user config for this run (optional custom path)')
|
|
30
|
+
.option('--no-user-config', 'Skip global user config for this run')
|
|
28
31
|
.hook('preAction', (thisCommand) => {
|
|
29
32
|
const opts = thisCommand.opts();
|
|
30
33
|
if (opts.verbose) setVerbose(true);
|
|
34
|
+
// Wire user-config flags into the config loader before any command runs.
|
|
35
|
+
// Commander sets opts.userConfig = true (bare flag), a string (path), or undefined.
|
|
36
|
+
// opts.userConfig is false when --no-user-config is passed (Commander negation).
|
|
37
|
+
const uc = opts.userConfig as string | boolean | undefined;
|
|
38
|
+
setUserConfigOverride(uc);
|
|
31
39
|
})
|
|
32
40
|
.hook('postAction', async (_thisCommand, actionCommand) => {
|
|
33
41
|
const name = actionCommand.name();
|
|
@@ -67,6 +75,8 @@ const ctx: CliContext = {
|
|
|
67
75
|
function registerCommand(parent: Command, def: CommandDefinition): Command {
|
|
68
76
|
const cmd = parent.command(def.name).description(def.description);
|
|
69
77
|
|
|
78
|
+
if (def.alias) cmd.alias(def.alias);
|
|
79
|
+
|
|
70
80
|
if (def.queryOpts) applyQueryOpts(cmd);
|
|
71
81
|
|
|
72
82
|
for (const opt of def.options || []) {
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import type { Command } from 'commander';
|
|
2
2
|
import { loadConfig } from '../../infrastructure/config.js';
|
|
3
|
+
import type { CodegraphConfig } from '../../types.js';
|
|
3
4
|
import type { CommandOpts } from '../types.js';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
// Deferred so global --user-config / --no-user-config flags are parsed
|
|
7
|
+
// before config is first accessed (Commander parses flags before any command
|
|
8
|
+
// action runs, but module-level code executes at import time).
|
|
9
|
+
let _config: CodegraphConfig | undefined;
|
|
10
|
+
const config: CodegraphConfig = new Proxy({} as CodegraphConfig, {
|
|
11
|
+
get(_t, prop: string) {
|
|
12
|
+
if (_config === undefined) _config = loadConfig(process.cwd());
|
|
13
|
+
return _config[prop as keyof CodegraphConfig];
|
|
14
|
+
},
|
|
15
|
+
}) as CodegraphConfig;
|
|
6
16
|
|
|
7
17
|
/**
|
|
8
18
|
* Attach the common query options shared by most analysis commands.
|
package/src/cli/types.ts
CHANGED
|
@@ -25,6 +25,8 @@ export interface CliContext {
|
|
|
25
25
|
export interface CommandDefinition {
|
|
26
26
|
name: string;
|
|
27
27
|
description: string;
|
|
28
|
+
/** Optional Commander.js alias (e.g. 'explain' for the 'audit' command). */
|
|
29
|
+
alias?: string;
|
|
28
30
|
queryOpts?: boolean;
|
|
29
31
|
options?: Array<[string, string, ...unknown[]]>;
|
|
30
32
|
validate?(args: string[], opts: CommandOpts, ctx: CliContext): string | undefined;
|