@monoes/monograph 1.2.0 → 1.2.1
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/__tests__/mcp-tools/cypher.test.ts +10 -6
- package/__tests__/mcp-tools/detect-changes.test.ts +14 -11
- package/__tests__/pipeline/phases/wildcard-synthesis.test.ts +4 -4
- package/__tests__/search/embed-batch-config.test.ts +7 -7
- package/__tests__/search/hybrid-query.test.ts +3 -1
- package/__tests__/web/api.test.ts +1 -1
- package/dist/src/analysis/churn-cache.d.ts.map +1 -1
- package/dist/src/analysis/churn-cache.js +19 -6
- package/dist/src/analysis/churn-cache.js.map +1 -1
- package/dist/src/analysis/churn-trend.d.ts.map +1 -1
- package/dist/src/analysis/churn-trend.js +50 -6
- package/dist/src/analysis/churn-trend.js.map +1 -1
- package/dist/src/analysis/cluster-quality.d.ts +3 -0
- package/dist/src/analysis/cluster-quality.d.ts.map +1 -1
- package/dist/src/analysis/cluster-quality.js +18 -12
- package/dist/src/analysis/cluster-quality.js.map +1 -1
- package/dist/src/analysis/coverage-gaps.d.ts +3 -0
- package/dist/src/analysis/coverage-gaps.d.ts.map +1 -1
- package/dist/src/analysis/coverage-gaps.js +40 -1
- package/dist/src/analysis/coverage-gaps.js.map +1 -1
- package/dist/src/analysis/dep-classification.d.ts +2 -0
- package/dist/src/analysis/dep-classification.d.ts.map +1 -1
- package/dist/src/analysis/dep-classification.js +30 -0
- package/dist/src/analysis/dep-classification.js.map +1 -1
- package/dist/src/analysis/dependency-health.d.ts +4 -0
- package/dist/src/analysis/dependency-health.d.ts.map +1 -1
- package/dist/src/analysis/dependency-health.js +28 -0
- package/dist/src/analysis/dependency-health.js.map +1 -1
- package/dist/src/analysis/duplicate-exports.d.ts +9 -5
- package/dist/src/analysis/duplicate-exports.d.ts.map +1 -1
- package/dist/src/analysis/duplicate-exports.js +26 -2
- package/dist/src/analysis/duplicate-exports.js.map +1 -1
- package/dist/src/analysis/feature-flags.d.ts.map +1 -1
- package/dist/src/analysis/feature-flags.js +36 -17
- package/dist/src/analysis/feature-flags.js.map +1 -1
- package/dist/src/analysis/node-similarity.d.ts +19 -0
- package/dist/src/analysis/node-similarity.d.ts.map +1 -1
- package/dist/src/analysis/node-similarity.js +34 -3
- package/dist/src/analysis/node-similarity.js.map +1 -1
- package/dist/src/analysis/private-type-leaks.d.ts +4 -0
- package/dist/src/analysis/private-type-leaks.d.ts.map +1 -1
- package/dist/src/analysis/private-type-leaks.js +43 -2
- package/dist/src/analysis/private-type-leaks.js.map +1 -1
- package/dist/src/analysis/project-state.d.ts +2 -0
- package/dist/src/analysis/project-state.d.ts.map +1 -1
- package/dist/src/analysis/project-state.js +18 -7
- package/dist/src/analysis/project-state.js.map +1 -1
- package/dist/src/analysis/suppressions.d.ts.map +1 -1
- package/dist/src/analysis/suppressions.js +3 -1
- package/dist/src/analysis/suppressions.js.map +1 -1
- package/dist/src/analysis/trace.d.ts +5 -3
- package/dist/src/analysis/trace.d.ts.map +1 -1
- package/dist/src/analysis/trace.js +59 -53
- package/dist/src/analysis/trace.js.map +1 -1
- package/dist/src/analysis/unused-class-members.d.ts.map +1 -1
- package/dist/src/analysis/unused-class-members.js +7 -1
- package/dist/src/analysis/unused-class-members.js.map +1 -1
- package/dist/src/analysis/worker-pool.d.ts +3 -0
- package/dist/src/analysis/worker-pool.d.ts.map +1 -1
- package/dist/src/analysis/worker-pool.js +30 -8
- package/dist/src/analysis/worker-pool.js.map +1 -1
- package/dist/src/cli/augment.d.ts.map +1 -1
- package/dist/src/cli/augment.js +10 -3
- package/dist/src/cli/augment.js.map +1 -1
- package/dist/src/export/sarif.js +5 -5
- package/dist/src/export/sarif.js.map +1 -1
- package/dist/src/graph/analyzer.d.ts.map +1 -1
- package/dist/src/graph/analyzer.js +17 -2
- package/dist/src/graph/analyzer.js.map +1 -1
- package/dist/src/graph/author-analytics.d.ts +2 -0
- package/dist/src/graph/author-analytics.d.ts.map +1 -1
- package/dist/src/graph/author-analytics.js +39 -5
- package/dist/src/graph/author-analytics.js.map +1 -1
- package/dist/src/graph/baseline.d.ts +5 -0
- package/dist/src/graph/baseline.d.ts.map +1 -1
- package/dist/src/graph/baseline.js +65 -18
- package/dist/src/graph/baseline.js.map +1 -1
- package/dist/src/graph/clone-detector.d.ts.map +1 -1
- package/dist/src/graph/clone-detector.js +19 -33
- package/dist/src/graph/clone-detector.js.map +1 -1
- package/dist/src/graph/clone-families.d.ts +2 -0
- package/dist/src/graph/clone-families.d.ts.map +1 -1
- package/dist/src/graph/clone-families.js +38 -10
- package/dist/src/graph/clone-families.js.map +1 -1
- package/dist/src/graph/codeowners-extended.d.ts +17 -0
- package/dist/src/graph/codeowners-extended.d.ts.map +1 -1
- package/dist/src/graph/codeowners-extended.js +42 -0
- package/dist/src/graph/codeowners-extended.js.map +1 -1
- package/dist/src/graph/codeowners-gitlab.d.ts +21 -0
- package/dist/src/graph/codeowners-gitlab.d.ts.map +1 -1
- package/dist/src/graph/codeowners-gitlab.js +37 -0
- package/dist/src/graph/codeowners-gitlab.js.map +1 -1
- package/dist/src/graph/codeowners.d.ts +10 -0
- package/dist/src/graph/codeowners.d.ts.map +1 -1
- package/dist/src/graph/codeowners.js +24 -2
- package/dist/src/graph/codeowners.js.map +1 -1
- package/dist/src/graph/complexity.d.ts +10 -0
- package/dist/src/graph/complexity.d.ts.map +1 -1
- package/dist/src/graph/complexity.js +93 -43
- package/dist/src/graph/complexity.js.map +1 -1
- package/dist/src/graph/cross-reference-findings.d.ts.map +1 -1
- package/dist/src/graph/cross-reference-findings.js +19 -2
- package/dist/src/graph/cross-reference-findings.js.map +1 -1
- package/dist/src/graph/cross-reference.d.ts +4 -0
- package/dist/src/graph/cross-reference.d.ts.map +1 -1
- package/dist/src/graph/cross-reference.js +23 -0
- package/dist/src/graph/cross-reference.js.map +1 -1
- package/dist/src/graph/cycle-detection.d.ts +2 -0
- package/dist/src/graph/cycle-detection.d.ts.map +1 -1
- package/dist/src/graph/cycle-detection.js +26 -3
- package/dist/src/graph/cycle-detection.js.map +1 -1
- package/dist/src/graph/cycles.d.ts +11 -3
- package/dist/src/graph/cycles.d.ts.map +1 -1
- package/dist/src/graph/cycles.js +121 -83
- package/dist/src/graph/cycles.js.map +1 -1
- package/dist/src/graph/dead-code.d.ts +23 -0
- package/dist/src/graph/dead-code.d.ts.map +1 -1
- package/dist/src/graph/dead-code.js +53 -13
- package/dist/src/graph/dead-code.js.map +1 -1
- package/dist/src/graph/dependency-closure.d.ts.map +1 -1
- package/dist/src/graph/dependency-closure.js +20 -4
- package/dist/src/graph/dependency-closure.js.map +1 -1
- package/dist/src/graph/dfs.d.ts +14 -0
- package/dist/src/graph/dfs.d.ts.map +1 -1
- package/dist/src/graph/dfs.js +61 -0
- package/dist/src/graph/dfs.js.map +1 -1
- package/dist/src/graph/duplication-stats.d.ts.map +1 -1
- package/dist/src/graph/duplication-stats.js +19 -3
- package/dist/src/graph/duplication-stats.js.map +1 -1
- package/dist/src/graph/edge-filter.d.ts +2 -0
- package/dist/src/graph/edge-filter.d.ts.map +1 -1
- package/dist/src/graph/edge-filter.js +26 -12
- package/dist/src/graph/edge-filter.js.map +1 -1
- package/dist/src/graph/health-score.d.ts +8 -0
- package/dist/src/graph/health-score.d.ts.map +1 -1
- package/dist/src/graph/health-score.js +48 -17
- package/dist/src/graph/health-score.js.map +1 -1
- package/dist/src/graph/hotspots.d.ts +7 -0
- package/dist/src/graph/hotspots.d.ts.map +1 -1
- package/dist/src/graph/hotspots.js +50 -5
- package/dist/src/graph/hotspots.js.map +1 -1
- package/dist/src/graph/import-chain.d.ts +17 -1
- package/dist/src/graph/import-chain.d.ts.map +1 -1
- package/dist/src/graph/import-chain.js +68 -19
- package/dist/src/graph/import-chain.js.map +1 -1
- package/dist/src/graph/loader.d.ts.map +1 -1
- package/dist/src/graph/loader.js +9 -10
- package/dist/src/graph/loader.js.map +1 -1
- package/dist/src/graph/maintainability.d.ts +8 -0
- package/dist/src/graph/maintainability.d.ts.map +1 -1
- package/dist/src/graph/maintainability.js +65 -10
- package/dist/src/graph/maintainability.js.map +1 -1
- package/dist/src/graph/mirrored-dirs.d.ts +4 -0
- package/dist/src/graph/mirrored-dirs.d.ts.map +1 -1
- package/dist/src/graph/mirrored-dirs.js +48 -13
- package/dist/src/graph/mirrored-dirs.js.map +1 -1
- package/dist/src/graph/narrowing.d.ts +15 -0
- package/dist/src/graph/narrowing.d.ts.map +1 -1
- package/dist/src/graph/narrowing.js +33 -0
- package/dist/src/graph/narrowing.js.map +1 -1
- package/dist/src/graph/node-search.d.ts +3 -0
- package/dist/src/graph/node-search.d.ts.map +1 -1
- package/dist/src/graph/node-search.js +37 -4
- package/dist/src/graph/node-search.js.map +1 -1
- package/dist/src/graph/normalize-id.d.ts +4 -0
- package/dist/src/graph/normalize-id.d.ts.map +1 -1
- package/dist/src/graph/normalize-id.js +25 -2
- package/dist/src/graph/normalize-id.js.map +1 -1
- package/dist/src/graph/pagerank.d.ts +7 -0
- package/dist/src/graph/pagerank.d.ts.map +1 -1
- package/dist/src/graph/pagerank.js +49 -2
- package/dist/src/graph/pagerank.js.map +1 -1
- package/dist/src/graph/prune.d.ts +31 -0
- package/dist/src/graph/prune.d.ts.map +1 -1
- package/dist/src/graph/prune.js +65 -0
- package/dist/src/graph/prune.js.map +1 -1
- package/dist/src/graph/regex-search.d.ts +10 -2
- package/dist/src/graph/regex-search.d.ts.map +1 -1
- package/dist/src/graph/regex-search.js +33 -4
- package/dist/src/graph/regex-search.js.map +1 -1
- package/dist/src/graph/regression.d.ts +5 -0
- package/dist/src/graph/regression.d.ts.map +1 -1
- package/dist/src/graph/regression.js +45 -23
- package/dist/src/graph/regression.js.map +1 -1
- package/dist/src/graph/ripple-impact.d.ts +27 -0
- package/dist/src/graph/ripple-impact.d.ts.map +1 -1
- package/dist/src/graph/ripple-impact.js +55 -7
- package/dist/src/graph/ripple-impact.js.map +1 -1
- package/dist/src/graph/risk-profile.d.ts +7 -0
- package/dist/src/graph/risk-profile.d.ts.map +1 -1
- package/dist/src/graph/risk-profile.js +82 -48
- package/dist/src/graph/risk-profile.js.map +1 -1
- package/dist/src/graph/shingle-filter.d.ts.map +1 -1
- package/dist/src/graph/shingle-filter.js +25 -26
- package/dist/src/graph/shingle-filter.js.map +1 -1
- package/dist/src/graph/statistics.d.ts +19 -0
- package/dist/src/graph/statistics.d.ts.map +1 -1
- package/dist/src/graph/statistics.js +53 -40
- package/dist/src/graph/statistics.js.map +1 -1
- package/dist/src/graph/stats.d.ts +2 -0
- package/dist/src/graph/stats.d.ts.map +1 -1
- package/dist/src/graph/stats.js +54 -8
- package/dist/src/graph/stats.js.map +1 -1
- package/dist/src/graph/subgraph.d.ts +5 -0
- package/dist/src/graph/subgraph.d.ts.map +1 -1
- package/dist/src/graph/subgraph.js +73 -9
- package/dist/src/graph/subgraph.js.map +1 -1
- package/dist/src/graph/topo-sort.d.ts +15 -0
- package/dist/src/graph/topo-sort.d.ts.map +1 -1
- package/dist/src/graph/topo-sort.js +83 -10
- package/dist/src/graph/topo-sort.js.map +1 -1
- package/dist/src/graph/wcc.d.ts +29 -0
- package/dist/src/graph/wcc.d.ts.map +1 -1
- package/dist/src/graph/wcc.js +122 -39
- package/dist/src/graph/wcc.js.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp-tools/api-impact.d.ts.map +1 -1
- package/dist/src/mcp-tools/api-impact.js +13 -6
- package/dist/src/mcp-tools/api-impact.js.map +1 -1
- package/dist/src/mcp-tools/context.d.ts.map +1 -1
- package/dist/src/mcp-tools/context.js +19 -29
- package/dist/src/mcp-tools/context.js.map +1 -1
- package/dist/src/mcp-tools/cypher.d.ts +11 -0
- package/dist/src/mcp-tools/cypher.d.ts.map +1 -1
- package/dist/src/mcp-tools/cypher.js +13 -1
- package/dist/src/mcp-tools/cypher.js.map +1 -1
- package/dist/src/mcp-tools/detect-changes.d.ts.map +1 -1
- package/dist/src/mcp-tools/detect-changes.js +35 -20
- package/dist/src/mcp-tools/detect-changes.js.map +1 -1
- package/dist/src/mcp-tools/explain.d.ts.map +1 -1
- package/dist/src/mcp-tools/explain.js +4 -1
- package/dist/src/mcp-tools/explain.js.map +1 -1
- package/dist/src/mcp-tools/graph-query.d.ts +2 -0
- package/dist/src/mcp-tools/graph-query.d.ts.map +1 -1
- package/dist/src/mcp-tools/graph-query.js +20 -3
- package/dist/src/mcp-tools/graph-query.js.map +1 -1
- package/dist/src/mcp-tools/group-list.d.ts +1 -0
- package/dist/src/mcp-tools/group-list.d.ts.map +1 -1
- package/dist/src/mcp-tools/group-list.js +7 -9
- package/dist/src/mcp-tools/group-list.js.map +1 -1
- package/dist/src/mcp-tools/impact.d.ts.map +1 -1
- package/dist/src/mcp-tools/impact.js +20 -59
- package/dist/src/mcp-tools/impact.js.map +1 -1
- package/dist/src/mcp-tools/neighbors.d.ts.map +1 -1
- package/dist/src/mcp-tools/neighbors.js +24 -33
- package/dist/src/mcp-tools/neighbors.js.map +1 -1
- package/dist/src/mcp-tools/query.d.ts +2 -0
- package/dist/src/mcp-tools/query.d.ts.map +1 -1
- package/dist/src/mcp-tools/query.js +1 -0
- package/dist/src/mcp-tools/query.js.map +1 -1
- package/dist/src/mcp-tools/rename.d.ts.map +1 -1
- package/dist/src/mcp-tools/rename.js +12 -7
- package/dist/src/mcp-tools/rename.js.map +1 -1
- package/dist/src/mcp-tools/route-map.d.ts.map +1 -1
- package/dist/src/mcp-tools/route-map.js +19 -23
- package/dist/src/mcp-tools/route-map.js.map +1 -1
- package/dist/src/mcp-tools/shape-check.d.ts.map +1 -1
- package/dist/src/mcp-tools/shape-check.js +17 -13
- package/dist/src/mcp-tools/shape-check.js.map +1 -1
- package/dist/src/parsers/loader.js +6 -5
- package/dist/src/parsers/loader.js.map +1 -1
- package/dist/src/pipeline/cluster-only.d.ts.map +1 -1
- package/dist/src/pipeline/cluster-only.js +8 -4
- package/dist/src/pipeline/cluster-only.js.map +1 -1
- package/dist/src/pipeline/orchestrator.d.ts.map +1 -1
- package/dist/src/pipeline/orchestrator.js +19 -0
- package/dist/src/pipeline/orchestrator.js.map +1 -1
- package/dist/src/pipeline/phases/boundary.d.ts +2 -0
- package/dist/src/pipeline/phases/boundary.d.ts.map +1 -1
- package/dist/src/pipeline/phases/boundary.js +31 -2
- package/dist/src/pipeline/phases/boundary.js.map +1 -1
- package/dist/src/pipeline/phases/communities.d.ts +14 -0
- package/dist/src/pipeline/phases/communities.d.ts.map +1 -1
- package/dist/src/pipeline/phases/communities.js +58 -5
- package/dist/src/pipeline/phases/communities.js.map +1 -1
- package/dist/src/pipeline/phases/contextual-proximity.d.ts.map +1 -1
- package/dist/src/pipeline/phases/contextual-proximity.js +21 -14
- package/dist/src/pipeline/phases/contextual-proximity.js.map +1 -1
- package/dist/src/pipeline/phases/cross-file.d.ts.map +1 -1
- package/dist/src/pipeline/phases/cross-file.js +35 -14
- package/dist/src/pipeline/phases/cross-file.js.map +1 -1
- package/dist/src/pipeline/phases/field-access.d.ts.map +1 -1
- package/dist/src/pipeline/phases/field-access.js +9 -4
- package/dist/src/pipeline/phases/field-access.js.map +1 -1
- package/dist/src/pipeline/phases/god-nodes.d.ts +4 -0
- package/dist/src/pipeline/phases/god-nodes.d.ts.map +1 -1
- package/dist/src/pipeline/phases/god-nodes.js +43 -9
- package/dist/src/pipeline/phases/god-nodes.js.map +1 -1
- package/dist/src/pipeline/phases/import-resolver.d.ts +11 -0
- package/dist/src/pipeline/phases/import-resolver.d.ts.map +1 -1
- package/dist/src/pipeline/phases/import-resolver.js +34 -7
- package/dist/src/pipeline/phases/import-resolver.js.map +1 -1
- package/dist/src/pipeline/phases/leiden.d.ts.map +1 -1
- package/dist/src/pipeline/phases/leiden.js +27 -19
- package/dist/src/pipeline/phases/leiden.js.map +1 -1
- package/dist/src/pipeline/phases/markdown.d.ts.map +1 -1
- package/dist/src/pipeline/phases/markdown.js +10 -5
- package/dist/src/pipeline/phases/markdown.js.map +1 -1
- package/dist/src/pipeline/phases/pdf-parse.d.ts.map +1 -1
- package/dist/src/pipeline/phases/pdf-parse.js +18 -3
- package/dist/src/pipeline/phases/pdf-parse.js.map +1 -1
- package/dist/src/pipeline/phases/processes.d.ts.map +1 -1
- package/dist/src/pipeline/phases/processes.js +26 -9
- package/dist/src/pipeline/phases/processes.js.map +1 -1
- package/dist/src/pipeline/phases/re-export-propagation.d.ts.map +1 -1
- package/dist/src/pipeline/phases/re-export-propagation.js +33 -14
- package/dist/src/pipeline/phases/re-export-propagation.js.map +1 -1
- package/dist/src/pipeline/phases/reachability.d.ts.map +1 -1
- package/dist/src/pipeline/phases/reachability.js +42 -26
- package/dist/src/pipeline/phases/reachability.js.map +1 -1
- package/dist/src/pipeline/phases/routes.d.ts.map +1 -1
- package/dist/src/pipeline/phases/routes.js +30 -21
- package/dist/src/pipeline/phases/routes.js.map +1 -1
- package/dist/src/pipeline/phases/scope-resolution.d.ts.map +1 -1
- package/dist/src/pipeline/phases/scope-resolution.js +93 -63
- package/dist/src/pipeline/phases/scope-resolution.js.map +1 -1
- package/dist/src/pipeline/runner.d.ts +4 -0
- package/dist/src/pipeline/runner.d.ts.map +1 -1
- package/dist/src/pipeline/runner.js +30 -11
- package/dist/src/pipeline/runner.js.map +1 -1
- package/dist/src/query/cypher-parser.d.ts +20 -0
- package/dist/src/query/cypher-parser.d.ts.map +1 -1
- package/dist/src/query/cypher-parser.js +73 -0
- package/dist/src/query/cypher-parser.js.map +1 -1
- package/dist/src/search/embed-batch.d.ts.map +1 -1
- package/dist/src/search/embed-batch.js +4 -1
- package/dist/src/search/embed-batch.js.map +1 -1
- package/dist/src/search/hybrid-query.d.ts +4 -0
- package/dist/src/search/hybrid-query.d.ts.map +1 -1
- package/dist/src/search/hybrid-query.js +5 -1
- package/dist/src/search/hybrid-query.js.map +1 -1
- package/dist/src/staleness/git-staleness.js +3 -3
- package/dist/src/staleness/git-staleness.js.map +1 -1
- package/dist/src/storage/db.d.ts.map +1 -1
- package/dist/src/storage/db.js +12 -0
- package/dist/src/storage/db.js.map +1 -1
- package/dist/src/storage/edge-store.d.ts +2 -0
- package/dist/src/storage/edge-store.d.ts.map +1 -1
- package/dist/src/storage/edge-store.js +26 -1
- package/dist/src/storage/edge-store.js.map +1 -1
- package/dist/src/storage/embedding-store.d.ts +16 -0
- package/dist/src/storage/embedding-store.d.ts.map +1 -1
- package/dist/src/storage/embedding-store.js +26 -2
- package/dist/src/storage/embedding-store.js.map +1 -1
- package/dist/src/storage/file-cache.d.ts +5 -0
- package/dist/src/storage/file-cache.d.ts.map +1 -1
- package/dist/src/storage/file-cache.js +35 -9
- package/dist/src/storage/file-cache.js.map +1 -1
- package/dist/src/storage/fts-store.d.ts +4 -0
- package/dist/src/storage/fts-store.d.ts.map +1 -1
- package/dist/src/storage/fts-store.js +8 -3
- package/dist/src/storage/fts-store.js.map +1 -1
- package/dist/src/storage/node-store.d.ts +2 -0
- package/dist/src/storage/node-store.d.ts.map +1 -1
- package/dist/src/storage/node-store.js +28 -1
- package/dist/src/storage/node-store.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/__tests__/pipeline/runner.parallel.test.ts +2 -2
- package/src/analysis/churn-cache.ts +18 -7
- package/src/analysis/churn-trend.ts +35 -6
- package/src/analysis/cluster-quality.ts +20 -11
- package/src/analysis/coverage-gaps.ts +44 -1
- package/src/analysis/dep-classification.ts +34 -0
- package/src/analysis/dependency-health.ts +25 -0
- package/src/analysis/duplicate-exports.ts +40 -4
- package/src/analysis/feature-flags.ts +37 -17
- package/src/analysis/node-similarity.ts +45 -4
- package/src/analysis/private-type-leaks.ts +49 -2
- package/src/analysis/project-state.ts +19 -9
- package/src/analysis/suppressions.ts +4 -1
- package/src/analysis/trace.ts +73 -54
- package/src/analysis/unused-class-members.ts +8 -1
- package/src/analysis/worker-pool.ts +40 -8
- package/src/cli/augment.ts +10 -3
- package/src/export/sarif.ts +5 -5
- package/src/graph/analyzer.ts +26 -2
- package/src/graph/author-analytics.ts +45 -5
- package/src/graph/baseline.ts +78 -24
- package/src/graph/clone-detector.ts +22 -36
- package/src/graph/clone-families.ts +34 -10
- package/src/graph/codeowners-extended.ts +54 -0
- package/src/graph/codeowners-gitlab.ts +46 -0
- package/src/graph/codeowners.ts +33 -2
- package/src/graph/complexity.ts +102 -47
- package/src/graph/cross-reference-findings.ts +23 -2
- package/src/graph/cross-reference.ts +26 -0
- package/src/graph/cycle-detection.ts +22 -3
- package/src/graph/cycles.ts +155 -96
- package/src/graph/dead-code.ts +76 -17
- package/src/graph/dependency-closure.ts +24 -7
- package/src/graph/dfs.ts +78 -0
- package/src/graph/duplication-stats.ts +17 -6
- package/src/graph/edge-filter.ts +26 -12
- package/src/graph/health-score.ts +47 -17
- package/src/graph/hotspots.ts +57 -8
- package/src/graph/import-chain.ts +89 -19
- package/src/graph/loader.ts +10 -7
- package/src/graph/maintainability.ts +72 -22
- package/src/graph/mirrored-dirs.ts +45 -14
- package/src/graph/narrowing.ts +44 -0
- package/src/graph/node-search.ts +49 -4
- package/src/graph/normalize-id.ts +26 -2
- package/src/graph/pagerank.ts +69 -2
- package/src/graph/prune.ts +76 -0
- package/src/graph/regex-search.ts +38 -4
- package/src/graph/regression.ts +48 -23
- package/src/graph/ripple-impact.ts +71 -11
- package/src/graph/risk-profile.ts +98 -53
- package/src/graph/shingle-filter.ts +33 -27
- package/src/graph/statistics.ts +73 -45
- package/src/graph/stats.ts +50 -16
- package/src/graph/subgraph.ts +96 -25
- package/src/graph/topo-sort.ts +101 -16
- package/src/graph/wcc.ts +146 -37
- package/src/index.ts +1 -1
- package/src/mcp-tools/api-impact.ts +13 -6
- package/src/mcp-tools/context.ts +31 -40
- package/src/mcp-tools/cypher.ts +14 -1
- package/src/mcp-tools/detect-changes.ts +38 -23
- package/src/mcp-tools/explain.ts +4 -1
- package/src/mcp-tools/graph-query.ts +24 -3
- package/src/mcp-tools/group-list.ts +9 -11
- package/src/mcp-tools/impact.ts +26 -66
- package/src/mcp-tools/neighbors.ts +34 -39
- package/src/mcp-tools/query.ts +3 -0
- package/src/mcp-tools/rename.ts +9 -8
- package/src/mcp-tools/route-map.ts +21 -23
- package/src/mcp-tools/shape-check.ts +18 -14
- package/src/parsers/loader.ts +5 -5
- package/src/pipeline/cluster-only.ts +8 -4
- package/src/pipeline/orchestrator.ts +22 -0
- package/src/pipeline/phases/boundary.ts +40 -2
- package/src/pipeline/phases/communities.ts +66 -5
- package/src/pipeline/phases/contextual-proximity.ts +15 -14
- package/src/pipeline/phases/cross-file.ts +35 -14
- package/src/pipeline/phases/field-access.ts +11 -4
- package/src/pipeline/phases/god-nodes.ts +47 -10
- package/src/pipeline/phases/import-resolver.ts +37 -5
- package/src/pipeline/phases/leiden.ts +25 -18
- package/src/pipeline/phases/markdown.ts +12 -7
- package/src/pipeline/phases/pdf-parse.ts +19 -2
- package/src/pipeline/phases/processes.ts +27 -15
- package/src/pipeline/phases/re-export-propagation.ts +40 -18
- package/src/pipeline/phases/reachability.ts +39 -24
- package/src/pipeline/phases/routes.ts +32 -21
- package/src/pipeline/phases/scope-resolution.ts +110 -71
- package/src/pipeline/runner.ts +28 -11
- package/src/query/cypher-parser.ts +83 -0
- package/src/search/embed-batch.ts +4 -1
- package/src/search/hybrid-query.ts +11 -1
- package/src/staleness/git-staleness.ts +3 -3
- package/src/storage/db.ts +11 -0
- package/src/storage/edge-store.ts +34 -1
- package/src/storage/embedding-store.ts +38 -6
- package/src/storage/file-cache.ts +35 -21
- package/src/storage/fts-store.ts +12 -3
- package/src/storage/node-store.ts +39 -1
- package/src/coverage/runtime.ts +0 -249
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { MonographDb } from '../storage/db.js';
|
|
2
|
+
/**
|
|
3
|
+
* Evict the cached graph for a given DB instance (call after writes).
|
|
4
|
+
*/
|
|
5
|
+
export declare function invalidateGraphCache(db: MonographDb): void;
|
|
2
6
|
/**
|
|
3
7
|
* Graph density: ratio of actual edges to maximum possible directed edges.
|
|
4
8
|
* For a directed graph with n nodes: max = n * (n - 1).
|
|
@@ -13,14 +17,29 @@ export declare function graphDensity(db: MonographDb): number;
|
|
|
13
17
|
* We use the undirected approximation: treat edges as undirected, count triangles.
|
|
14
18
|
*/
|
|
15
19
|
export declare function clusteringCoefficient(db: MonographDb): number;
|
|
20
|
+
export interface PathStats {
|
|
21
|
+
/** Average shortest path length across all reachable pairs (i ≠ j). */
|
|
22
|
+
averagePathLength: number;
|
|
23
|
+
/** Maximum shortest path length (diameter) across all reachable pairs. */
|
|
24
|
+
diameter: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Compute both average path length and graph diameter in a single BFS pass.
|
|
28
|
+
* Unreachable pairs are excluded from averagePathLength.
|
|
29
|
+
*/
|
|
30
|
+
export declare function pathStats(db: MonographDb): PathStats;
|
|
16
31
|
/**
|
|
17
32
|
* Average shortest path length across all reachable node pairs (i, j) where i ≠ j.
|
|
18
33
|
* Computed using BFS from each node. Unreachable pairs are excluded from the average.
|
|
34
|
+
*
|
|
35
|
+
* @deprecated Prefer `pathStats(db).averagePathLength` to share BFS with `graphDiameter`.
|
|
19
36
|
*/
|
|
20
37
|
export declare function averagePathLength(db: MonographDb): number;
|
|
21
38
|
/**
|
|
22
39
|
* Graph diameter: the maximum shortest path length across all reachable node pairs.
|
|
23
40
|
* Returns 0 for empty or single-node graphs.
|
|
41
|
+
*
|
|
42
|
+
* @deprecated Prefer `pathStats(db).diameter` to share BFS with `averagePathLength`.
|
|
24
43
|
*/
|
|
25
44
|
export declare function graphDiameter(db: MonographDb): number;
|
|
26
45
|
//# sourceMappingURL=statistics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statistics.d.ts","sourceRoot":"","sources":["../../../src/graph/statistics.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"statistics.d.ts","sourceRoot":"","sources":["../../../src/graph/statistics.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AA0BpD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI,CAG1D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAWpD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAsC7D;AAMD,MAAM,WAAW,SAAS;IACxB,uEAAuE;IACvE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,WAAW,GAAG,SAAS,CAuBpD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAErD"}
|
|
@@ -1,12 +1,36 @@
|
|
|
1
1
|
import { bfsFromNode } from 'graphology-traversal/bfs.js';
|
|
2
2
|
import { loadGraphFromDb } from './loader.js';
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Module-level graph cache — avoids reloading the full graph on every call
|
|
5
|
+
// when multiple statistics functions are invoked in the same request cycle.
|
|
6
|
+
// TTL: 5 seconds; keyed by DB file path (better-sqlite3 exposes .name).
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
const GRAPH_CACHE_TTL_MS = 5_000;
|
|
9
|
+
const _graphCache = new Map();
|
|
10
|
+
function getGraph(db) {
|
|
11
|
+
const key = db.name ?? '__default__';
|
|
12
|
+
const now = Date.now();
|
|
13
|
+
const cached = _graphCache.get(key);
|
|
14
|
+
if (cached && now < cached.expiresAt)
|
|
15
|
+
return cached.graph;
|
|
16
|
+
const graph = loadGraphFromDb(db);
|
|
17
|
+
_graphCache.set(key, { graph, expiresAt: now + GRAPH_CACHE_TTL_MS });
|
|
18
|
+
return graph;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Evict the cached graph for a given DB instance (call after writes).
|
|
22
|
+
*/
|
|
23
|
+
export function invalidateGraphCache(db) {
|
|
24
|
+
const key = db.name ?? '__default__';
|
|
25
|
+
_graphCache.delete(key);
|
|
26
|
+
}
|
|
3
27
|
/**
|
|
4
28
|
* Graph density: ratio of actual edges to maximum possible directed edges.
|
|
5
29
|
* For a directed graph with n nodes: max = n * (n - 1).
|
|
6
30
|
* Ignores self-loops.
|
|
7
31
|
*/
|
|
8
32
|
export function graphDensity(db) {
|
|
9
|
-
const graph =
|
|
33
|
+
const graph = getGraph(db);
|
|
10
34
|
const n = graph.order;
|
|
11
35
|
if (n < 2)
|
|
12
36
|
return 0;
|
|
@@ -27,7 +51,7 @@ export function graphDensity(db) {
|
|
|
27
51
|
* We use the undirected approximation: treat edges as undirected, count triangles.
|
|
28
52
|
*/
|
|
29
53
|
export function clusteringCoefficient(db) {
|
|
30
|
-
const graph =
|
|
54
|
+
const graph = getGraph(db);
|
|
31
55
|
if (graph.order === 0)
|
|
32
56
|
return 0;
|
|
33
57
|
// Build undirected adjacency sets
|
|
@@ -63,59 +87,48 @@ export function clusteringCoefficient(db) {
|
|
|
63
87
|
return totalCoeff / countWithNeighbors;
|
|
64
88
|
}
|
|
65
89
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
90
|
+
* Compute both average path length and graph diameter in a single BFS pass.
|
|
91
|
+
* Unreachable pairs are excluded from averagePathLength.
|
|
68
92
|
*/
|
|
69
|
-
export function
|
|
70
|
-
const graph =
|
|
93
|
+
export function pathStats(db) {
|
|
94
|
+
const graph = getGraph(db);
|
|
71
95
|
const nodes = graph.nodes();
|
|
72
96
|
if (nodes.length < 2)
|
|
73
|
-
return 0;
|
|
97
|
+
return { averagePathLength: 0, diameter: 0 };
|
|
74
98
|
let totalLength = 0;
|
|
75
99
|
let reachablePairs = 0;
|
|
100
|
+
let maxDist = 0;
|
|
76
101
|
for (const source of nodes) {
|
|
77
|
-
const distances = new Map();
|
|
78
|
-
distances.set(source, 0);
|
|
79
102
|
bfsFromNode(graph, source, (node, _attr, depth) => {
|
|
80
|
-
if (node !== source) {
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
for (const [target, dist] of distances) {
|
|
85
|
-
if (target !== source && dist > 0) {
|
|
86
|
-
totalLength += dist;
|
|
103
|
+
if (node !== source && depth > 0) {
|
|
104
|
+
totalLength += depth;
|
|
87
105
|
reachablePairs++;
|
|
106
|
+
if (depth > maxDist)
|
|
107
|
+
maxDist = depth;
|
|
88
108
|
}
|
|
89
|
-
}
|
|
109
|
+
});
|
|
90
110
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
111
|
+
return {
|
|
112
|
+
averagePathLength: reachablePairs === 0 ? 0 : totalLength / reachablePairs,
|
|
113
|
+
diameter: maxDist,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Average shortest path length across all reachable node pairs (i, j) where i ≠ j.
|
|
118
|
+
* Computed using BFS from each node. Unreachable pairs are excluded from the average.
|
|
119
|
+
*
|
|
120
|
+
* @deprecated Prefer `pathStats(db).averagePathLength` to share BFS with `graphDiameter`.
|
|
121
|
+
*/
|
|
122
|
+
export function averagePathLength(db) {
|
|
123
|
+
return pathStats(db).averagePathLength;
|
|
94
124
|
}
|
|
95
125
|
/**
|
|
96
126
|
* Graph diameter: the maximum shortest path length across all reachable node pairs.
|
|
97
127
|
* Returns 0 for empty or single-node graphs.
|
|
128
|
+
*
|
|
129
|
+
* @deprecated Prefer `pathStats(db).diameter` to share BFS with `averagePathLength`.
|
|
98
130
|
*/
|
|
99
131
|
export function graphDiameter(db) {
|
|
100
|
-
|
|
101
|
-
const nodes = graph.nodes();
|
|
102
|
-
if (nodes.length < 2)
|
|
103
|
-
return 0;
|
|
104
|
-
let maxDist = 0;
|
|
105
|
-
for (const source of nodes) {
|
|
106
|
-
const distances = new Map();
|
|
107
|
-
distances.set(source, 0);
|
|
108
|
-
bfsFromNode(graph, source, (node, _attr, depth) => {
|
|
109
|
-
if (node !== source) {
|
|
110
|
-
distances.set(node, depth);
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
for (const [target, dist] of distances) {
|
|
114
|
-
if (target !== source && dist > maxDist) {
|
|
115
|
-
maxDist = dist;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return maxDist;
|
|
132
|
+
return pathStats(db).diameter;
|
|
120
133
|
}
|
|
121
134
|
//# sourceMappingURL=statistics.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statistics.js","sourceRoot":"","sources":["../../../src/graph/statistics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"statistics.js","sourceRoot":"","sources":["../../../src/graph/statistics.ts"],"names":[],"mappings":"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"}
|
|
@@ -35,4 +35,6 @@ export declare function computeCouplingProfile(db: Database.Database): CouplingP
|
|
|
35
35
|
* Quick stats summary (extends existing stats from monograph_stats MCP tool).
|
|
36
36
|
*/
|
|
37
37
|
export declare function computeGraphStats(db: Database.Database): GraphStatsSummary;
|
|
38
|
+
/** Format a GraphStatsSummary as structured text for LLM consumption. */
|
|
39
|
+
export declare function formatGraphStats(s: GraphStatsSummary): string;
|
|
38
40
|
//# sourceMappingURL=stats.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../../src/graph/stats.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../../src/graph/stats.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAwB3C,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;AAE7D,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,WAAW,CAAC;IAC1B,aAAa,EAAE,WAAW,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,eAAe,CAAC;CAClC;AA8BD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,eAAe,CA8B7E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,iBAAiB,CAkB1E;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAY7D"}
|
package/dist/src/graph/stats.js
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
// Per-DB prepared statement cache to avoid re-parsing SQL on repeated calls
|
|
2
|
+
const stmtCache = new WeakMap();
|
|
3
|
+
function stmt(db, sql) {
|
|
4
|
+
let dbCache = stmtCache.get(db);
|
|
5
|
+
if (!dbCache) {
|
|
6
|
+
dbCache = new Map();
|
|
7
|
+
stmtCache.set(db, dbCache);
|
|
8
|
+
}
|
|
9
|
+
let s = dbCache.get(sql);
|
|
10
|
+
if (!s) {
|
|
11
|
+
s = db.prepare(sql);
|
|
12
|
+
dbCache.set(sql, s);
|
|
13
|
+
}
|
|
14
|
+
return s;
|
|
15
|
+
}
|
|
16
|
+
/** Binary search: returns index of first element > value in a sorted ascending array. */
|
|
17
|
+
function upperBound(sorted, value) {
|
|
18
|
+
let lo = 0, hi = sorted.length;
|
|
19
|
+
while (lo < hi) {
|
|
20
|
+
const mid = (lo + hi) >>> 1;
|
|
21
|
+
if (sorted[mid] <= value)
|
|
22
|
+
lo = mid + 1;
|
|
23
|
+
else
|
|
24
|
+
hi = mid;
|
|
25
|
+
}
|
|
26
|
+
return lo;
|
|
27
|
+
}
|
|
1
28
|
function percentile(sorted, p) {
|
|
2
29
|
if (sorted.length === 0)
|
|
3
30
|
return 0;
|
|
@@ -33,13 +60,17 @@ function buildRiskProfile(values) {
|
|
|
33
60
|
* Compute full coupling profile from SQLite.
|
|
34
61
|
*/
|
|
35
62
|
export function computeCouplingProfile(db) {
|
|
36
|
-
const fanInRows = db
|
|
37
|
-
|
|
38
|
-
const
|
|
63
|
+
const fanInRows = stmt(db, 'SELECT target_id, COUNT(*) as c FROM edges GROUP BY target_id')
|
|
64
|
+
.all();
|
|
65
|
+
const fanOutRows = stmt(db, 'SELECT source_id, COUNT(*) as c FROM edges GROUP BY source_id')
|
|
66
|
+
.all();
|
|
67
|
+
const totalFiles = stmt(db, "SELECT COUNT(*) as n FROM nodes WHERE label = 'File'")
|
|
68
|
+
.get().n;
|
|
39
69
|
const fanInValues = fanInRows.map(r => r.c).sort((a, b) => a - b);
|
|
40
70
|
const fanOutValues = fanOutRows.map(r => r.c).sort((a, b) => a - b);
|
|
41
71
|
const p95FanIn = percentile(fanInValues, 95);
|
|
42
|
-
|
|
72
|
+
// Use binary search instead of O(N) filter to count elements above p95 threshold
|
|
73
|
+
const couplingHighCount = fanInValues.length - upperBound(fanInValues, p95FanIn);
|
|
43
74
|
const couplingHighPct = fanInValues.length > 0
|
|
44
75
|
? Math.round((couplingHighCount / fanInValues.length) * 100)
|
|
45
76
|
: 0;
|
|
@@ -58,10 +89,11 @@ export function computeCouplingProfile(db) {
|
|
|
58
89
|
* Quick stats summary (extends existing stats from monograph_stats MCP tool).
|
|
59
90
|
*/
|
|
60
91
|
export function computeGraphStats(db) {
|
|
61
|
-
const nodeCount = db
|
|
62
|
-
const edgeCount = db
|
|
63
|
-
const communityCount = db
|
|
64
|
-
const fileCount = db
|
|
92
|
+
const nodeCount = stmt(db, 'SELECT COUNT(*) as n FROM nodes').get().n;
|
|
93
|
+
const edgeCount = stmt(db, 'SELECT COUNT(*) as n FROM edges').get().n;
|
|
94
|
+
const communityCount = stmt(db, "SELECT COUNT(DISTINCT community_id) as n FROM nodes WHERE community_id IS NOT NULL").get().n;
|
|
95
|
+
const fileCount = stmt(db, "SELECT COUNT(*) as n FROM nodes WHERE label = 'File'")
|
|
96
|
+
.get().n;
|
|
65
97
|
const couplingProfile = computeCouplingProfile(db);
|
|
66
98
|
return {
|
|
67
99
|
nodeCount,
|
|
@@ -71,4 +103,18 @@ export function computeGraphStats(db) {
|
|
|
71
103
|
couplingProfile,
|
|
72
104
|
};
|
|
73
105
|
}
|
|
106
|
+
/** Format a GraphStatsSummary as structured text for LLM consumption. */
|
|
107
|
+
export function formatGraphStats(s) {
|
|
108
|
+
const cp = s.couplingProfile;
|
|
109
|
+
const lines = [
|
|
110
|
+
`Graph Stats`,
|
|
111
|
+
` Nodes: ${s.nodeCount} Edges: ${s.edgeCount} Communities: ${s.communityCount} Files: ${s.fileCount}`,
|
|
112
|
+
`Coupling Profile (${cp.totalFiles} files)`,
|
|
113
|
+
` Fan-in p50/p75/p90/p95: ${cp.p50FanIn}/${cp.p75FanIn}/${cp.p90FanIn}/${cp.p95FanIn}`,
|
|
114
|
+
` High-coupling (>p95): ${cp.couplingHighPct}%`,
|
|
115
|
+
`Fan-in Risk: low=${cp.fanInProfile.low}(${cp.fanInProfile.lowPct}%) med=${cp.fanInProfile.medium}(${cp.fanInProfile.mediumPct}%) high=${cp.fanInProfile.high}(${cp.fanInProfile.highPct}%) crit=${cp.fanInProfile.critical}(${cp.fanInProfile.criticalPct}%)`,
|
|
116
|
+
`Fan-out Risk: low=${cp.fanOutProfile.low}(${cp.fanOutProfile.lowPct}%) med=${cp.fanOutProfile.medium}(${cp.fanOutProfile.mediumPct}%) high=${cp.fanOutProfile.high}(${cp.fanOutProfile.highPct}%) crit=${cp.fanOutProfile.critical}(${cp.fanOutProfile.criticalPct}%)`,
|
|
117
|
+
];
|
|
118
|
+
return lines.join('\n');
|
|
119
|
+
}
|
|
74
120
|
//# sourceMappingURL=stats.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../../src/graph/stats.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../../src/graph/stats.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,4 +5,9 @@ export interface InducedSubgraph {
|
|
|
5
5
|
edges: MonographEdge[];
|
|
6
6
|
}
|
|
7
7
|
export declare function extractInducedSubgraph(db: MonographDb, nodeIds: string[]): InducedSubgraph;
|
|
8
|
+
/**
|
|
9
|
+
* Format an InducedSubgraph as structured text for LLM consumption.
|
|
10
|
+
* Groups nodes by file path and lists edges with relation + file:line hints.
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatInducedSubgraph(sg: InducedSubgraph): string;
|
|
8
13
|
//# sourceMappingURL=subgraph.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subgraph.d.ts","sourceRoot":"","sources":["../../../src/graph/subgraph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;
|
|
1
|
+
{"version":3,"file":"subgraph.d.ts","sourceRoot":"","sources":["../../../src/graph/subgraph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAwDD,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,eAAe,CA6D1F;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,eAAe,GAAG,MAAM,CA+BjE"}
|
|
@@ -12,26 +12,55 @@
|
|
|
12
12
|
// SQLite SQLITE_MAX_VARIABLE_NUMBER limit (32766). Edge query binds nodeIds once
|
|
13
13
|
// (source_id IN chunk), then filters target in-memory — full limit available per chunk.
|
|
14
14
|
const SQLITE_VAR_LIMIT = 32766;
|
|
15
|
+
/** Cache of placeholder strings keyed by count: 1 → "?", 2 → "?,?", etc. */
|
|
16
|
+
const placeholderCache = new Map();
|
|
17
|
+
function placeholders(n) {
|
|
18
|
+
let ph = placeholderCache.get(n);
|
|
19
|
+
if (!ph) {
|
|
20
|
+
ph = Array(n).fill('?').join(',');
|
|
21
|
+
placeholderCache.set(n, ph);
|
|
22
|
+
}
|
|
23
|
+
return ph;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Prepared-statement caches per db instance — stored on the db object to avoid
|
|
27
|
+
* cross-db pollution while ensuring each unique chunk size is prepared at most once.
|
|
28
|
+
*/
|
|
29
|
+
function getStmtCaches(db) {
|
|
30
|
+
const key = '__subgraphStmtCache__';
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
+
const dbAny = db;
|
|
33
|
+
if (!dbAny[key]) {
|
|
34
|
+
dbAny[key] = { nodes: new Map(), edges: new Map() };
|
|
35
|
+
}
|
|
36
|
+
return dbAny[key];
|
|
37
|
+
}
|
|
15
38
|
export function extractInducedSubgraph(db, nodeIds) {
|
|
16
39
|
if (nodeIds.length === 0)
|
|
17
40
|
return { nodes: [], edges: [] };
|
|
18
|
-
|
|
19
|
-
|
|
41
|
+
const stmts = getStmtCaches(db);
|
|
42
|
+
// Chunk helper — caches prepared statements by chunk size to avoid re-prepare per call.
|
|
43
|
+
function queryChunked(ids, chunkSize, stmtCache, sql) {
|
|
20
44
|
const results = [];
|
|
21
45
|
for (let i = 0; i < ids.length; i += chunkSize) {
|
|
22
46
|
const chunk = ids.slice(i, i + chunkSize);
|
|
23
|
-
const ph = chunk.
|
|
24
|
-
|
|
47
|
+
const ph = placeholders(chunk.length);
|
|
48
|
+
let stmt = stmtCache.get(chunk.length);
|
|
49
|
+
if (!stmt) {
|
|
50
|
+
stmt = db.prepare(sql(ph));
|
|
51
|
+
stmtCache.set(chunk.length, stmt);
|
|
52
|
+
}
|
|
53
|
+
results.push(...stmt.all(...chunk));
|
|
25
54
|
}
|
|
26
55
|
return results;
|
|
27
56
|
}
|
|
28
|
-
const rawNodes = queryChunked(nodeIds, SQLITE_VAR_LIMIT,
|
|
29
|
-
FROM nodes WHERE id IN (${ph})`).all(...chunk));
|
|
57
|
+
const rawNodes = queryChunked(nodeIds, SQLITE_VAR_LIMIT, stmts.nodes, ph => `SELECT id, label, name, file_path, start_line, end_line, community_id, is_exported, language, properties FROM nodes WHERE id IN (${ph})`);
|
|
30
58
|
// For edges: query by source_id chunks (1 bind per row), then filter target in-memory.
|
|
31
|
-
// Querying by both source+target would miss cross-chunk edges and requires 2× bind slots.
|
|
32
59
|
const nodeSet = new Set(nodeIds);
|
|
33
|
-
const
|
|
34
|
-
|
|
60
|
+
const allSourceEdges = queryChunked(nodeIds, SQLITE_VAR_LIMIT, stmts.edges,
|
|
61
|
+
// Drop unused 'evidence' column to reduce row data transfer
|
|
62
|
+
ph => `SELECT id, source_id, target_id, relation, confidence, confidence_score, reason FROM edges WHERE source_id IN (${ph})`);
|
|
63
|
+
const rawEdges = allSourceEdges.filter(e => nodeSet.has(e.target_id));
|
|
35
64
|
const nodes = rawNodes.map(n => ({
|
|
36
65
|
id: n.id,
|
|
37
66
|
label: n.label,
|
|
@@ -56,4 +85,39 @@ export function extractInducedSubgraph(db, nodeIds) {
|
|
|
56
85
|
}));
|
|
57
86
|
return { nodes, edges };
|
|
58
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Format an InducedSubgraph as structured text for LLM consumption.
|
|
90
|
+
* Groups nodes by file path and lists edges with relation + file:line hints.
|
|
91
|
+
*/
|
|
92
|
+
export function formatInducedSubgraph(sg) {
|
|
93
|
+
if (sg.nodes.length === 0)
|
|
94
|
+
return 'Subgraph is empty.';
|
|
95
|
+
const lines = [`Subgraph: ${sg.nodes.length} nodes, ${sg.edges.length} edges`];
|
|
96
|
+
// Group nodes by file
|
|
97
|
+
const byFile = new Map();
|
|
98
|
+
for (const n of sg.nodes) {
|
|
99
|
+
const file = n.filePath ?? '(unknown)';
|
|
100
|
+
let list = byFile.get(file);
|
|
101
|
+
if (!list) {
|
|
102
|
+
list = [];
|
|
103
|
+
byFile.set(file, list);
|
|
104
|
+
}
|
|
105
|
+
list.push(n);
|
|
106
|
+
}
|
|
107
|
+
lines.push('\nNodes:');
|
|
108
|
+
for (const [file, nodes] of byFile) {
|
|
109
|
+
lines.push(` ${file}`);
|
|
110
|
+
for (const n of nodes) {
|
|
111
|
+
const loc = n.startLine ? `:${n.startLine}` : '';
|
|
112
|
+
lines.push(` ${n.label} ${n.name}${loc}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (sg.edges.length > 0) {
|
|
116
|
+
lines.push('\nEdges:');
|
|
117
|
+
for (const e of sg.edges) {
|
|
118
|
+
lines.push(` ${e.sourceId} --[${e.relation}]--> ${e.targetId}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return lines.join('\n');
|
|
122
|
+
}
|
|
59
123
|
//# sourceMappingURL=subgraph.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subgraph.js","sourceRoot":"","sources":["../../../src/graph/subgraph.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;GAUG;AACH,iFAAiF;AACjF,wFAAwF;AACxF,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAE/B,MAAM,UAAU,sBAAsB,CAAC,EAAe,EAAE,OAAiB;IACvE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IAE1D,
|
|
1
|
+
{"version":3,"file":"subgraph.js","sourceRoot":"","sources":["../../../src/graph/subgraph.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,8 +14,23 @@ export interface TopoSortResult {
|
|
|
14
14
|
* Files with no incoming edges on the reverse graph (i.e., no one imports them)
|
|
15
15
|
* are leaves and appear in level 0.
|
|
16
16
|
*
|
|
17
|
+
* The in-degree computation is pushed into SQL (GROUP BY aggregation) to avoid
|
|
18
|
+
* materialising the full edge table into JavaScript memory.
|
|
19
|
+
*
|
|
17
20
|
* @param db - The MonographDb instance
|
|
18
21
|
* @returns Object with `levels` (array of independent groups, leaf-first) and `cycleCount`.
|
|
19
22
|
*/
|
|
20
23
|
export declare function topologicalLevelSort(db: MonographDb): TopoSortResult;
|
|
24
|
+
/**
|
|
25
|
+
* Format topological sort levels as structured text.
|
|
26
|
+
*
|
|
27
|
+
* Resolves node IDs to names and file paths so LLMs can navigate directly
|
|
28
|
+
* to the source. Cycle nodes (if any) are clearly labelled.
|
|
29
|
+
*
|
|
30
|
+
* @param db - The MonographDb instance (for name resolution)
|
|
31
|
+
* @param result - Result from topologicalLevelSort()
|
|
32
|
+
* @param maxLevels - Max levels to include in output (default: all)
|
|
33
|
+
* @returns Structured text suitable for injection into LLM context
|
|
34
|
+
*/
|
|
35
|
+
export declare function formatTopoSort(db: MonographDb, result: TopoSortResult, maxLevels?: number): string;
|
|
21
36
|
//# sourceMappingURL=topo-sort.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topo-sort.d.ts","sourceRoot":"","sources":["../../../src/graph/topo-sort.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,cAAc;IAC7B;;kFAE8E;IAC9E,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;IACnB,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED
|
|
1
|
+
{"version":3,"file":"topo-sort.d.ts","sourceRoot":"","sources":["../../../src/graph/topo-sort.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,cAAc;IAC7B;;kFAE8E;IAC9E,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;IACnB,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,WAAW,GAAG,cAAc,CAyEpE;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,WAAW,EACf,MAAM,EAAE,cAAc,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAoDR"}
|
|
@@ -5,30 +5,46 @@
|
|
|
5
5
|
* Files with no incoming edges on the reverse graph (i.e., no one imports them)
|
|
6
6
|
* are leaves and appear in level 0.
|
|
7
7
|
*
|
|
8
|
+
* The in-degree computation is pushed into SQL (GROUP BY aggregation) to avoid
|
|
9
|
+
* materialising the full edge table into JavaScript memory.
|
|
10
|
+
*
|
|
8
11
|
* @param db - The MonographDb instance
|
|
9
12
|
* @returns Object with `levels` (array of independent groups, leaf-first) and `cycleCount`.
|
|
10
13
|
*/
|
|
11
14
|
export function topologicalLevelSort(db) {
|
|
12
15
|
const nodeRows = db.prepare('SELECT id FROM nodes').all();
|
|
13
|
-
const edgeRows = db.prepare('SELECT source_id, target_id FROM edges').all();
|
|
14
16
|
if (nodeRows.length === 0)
|
|
15
17
|
return { levels: [], cycleCount: 0 };
|
|
16
18
|
const nodes = nodeRows.map(r => r.id);
|
|
17
|
-
//
|
|
18
|
-
// In
|
|
19
|
-
|
|
19
|
+
// Compute in-degree (on the reverse graph) via SQL aggregation.
|
|
20
|
+
// In the original graph each edge src→tgt means "src imports tgt".
|
|
21
|
+
// In the reverse graph the edge becomes tgt→src, so src gains in-degree +1.
|
|
22
|
+
// We aggregate target_id counts grouped by source_id to get reverse-in-degree per node.
|
|
23
|
+
const inDegreeRows = db
|
|
24
|
+
.prepare(`SELECT source_id AS node_id, COUNT(*) AS cnt
|
|
25
|
+
FROM edges
|
|
26
|
+
WHERE source_id != target_id
|
|
27
|
+
GROUP BY source_id`)
|
|
28
|
+
.all();
|
|
20
29
|
const inDegree = new Map();
|
|
21
|
-
for (const n of nodes)
|
|
22
|
-
reverseAdj.set(n, []);
|
|
30
|
+
for (const n of nodes)
|
|
23
31
|
inDegree.set(n, 0);
|
|
32
|
+
for (const { node_id, cnt } of inDegreeRows) {
|
|
33
|
+
if (inDegree.has(node_id))
|
|
34
|
+
inDegree.set(node_id, cnt);
|
|
24
35
|
}
|
|
36
|
+
// Build reverse adjacency list — still needed for Kahn's BFS relaxation step.
|
|
37
|
+
// Fetch only what Kahn needs: target_id → [source_id, ...] (reverse direction).
|
|
38
|
+
const reverseAdj = new Map();
|
|
39
|
+
for (const n of nodes)
|
|
40
|
+
reverseAdj.set(n, []);
|
|
41
|
+
const edgeRows = db
|
|
42
|
+
.prepare('SELECT source_id, target_id FROM edges WHERE source_id != target_id')
|
|
43
|
+
.all();
|
|
25
44
|
for (const { source_id: src, target_id: tgt } of edgeRows) {
|
|
26
|
-
if (src === tgt)
|
|
27
|
-
continue; // skip self-loops
|
|
28
45
|
if (!reverseAdj.has(tgt) || !reverseAdj.has(src))
|
|
29
46
|
continue;
|
|
30
47
|
reverseAdj.get(tgt).push(src);
|
|
31
|
-
inDegree.set(src, (inDegree.get(src) ?? 0) + 1);
|
|
32
48
|
}
|
|
33
49
|
// Kahn's BFS on the reverse graph
|
|
34
50
|
const queue = [];
|
|
@@ -39,7 +55,6 @@ export function topologicalLevelSort(db) {
|
|
|
39
55
|
const levels = [];
|
|
40
56
|
const visited = new Set();
|
|
41
57
|
while (queue.length > 0) {
|
|
42
|
-
// All nodes currently at in-degree 0 form one level
|
|
43
58
|
const level = [...queue];
|
|
44
59
|
queue.length = 0;
|
|
45
60
|
levels.push(level);
|
|
@@ -64,4 +79,62 @@ export function topologicalLevelSort(db) {
|
|
|
64
79
|
}
|
|
65
80
|
return { levels, cycleCount };
|
|
66
81
|
}
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// Structured text formatter for LLM consumption
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
/**
|
|
86
|
+
* Format topological sort levels as structured text.
|
|
87
|
+
*
|
|
88
|
+
* Resolves node IDs to names and file paths so LLMs can navigate directly
|
|
89
|
+
* to the source. Cycle nodes (if any) are clearly labelled.
|
|
90
|
+
*
|
|
91
|
+
* @param db - The MonographDb instance (for name resolution)
|
|
92
|
+
* @param result - Result from topologicalLevelSort()
|
|
93
|
+
* @param maxLevels - Max levels to include in output (default: all)
|
|
94
|
+
* @returns Structured text suitable for injection into LLM context
|
|
95
|
+
*/
|
|
96
|
+
export function formatTopoSort(db, result, maxLevels) {
|
|
97
|
+
if (result.levels.length === 0) {
|
|
98
|
+
return 'Topological sort: no nodes found.';
|
|
99
|
+
}
|
|
100
|
+
// Batch-resolve all node IDs
|
|
101
|
+
const allIds = result.levels.flat();
|
|
102
|
+
const CHUNK = 200;
|
|
103
|
+
const nodeInfo = new Map();
|
|
104
|
+
for (let i = 0; i < allIds.length; i += CHUNK) {
|
|
105
|
+
const chunk = allIds.slice(i, i + CHUNK);
|
|
106
|
+
const ph = chunk.map(() => '?').join(',');
|
|
107
|
+
const rows = db
|
|
108
|
+
.prepare(`SELECT id, name, file_path FROM nodes WHERE id IN (${ph})`)
|
|
109
|
+
.all(...chunk);
|
|
110
|
+
for (const row of rows) {
|
|
111
|
+
nodeInfo.set(row.id, { name: row.name ?? row.id, filePath: row.file_path });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const isCycleLevelIdx = result.cycleCount > 0 && result.levels.length > 0
|
|
115
|
+
? result.levels.length - 1
|
|
116
|
+
: -1;
|
|
117
|
+
const displayLevels = maxLevels !== undefined ? result.levels.slice(0, maxLevels) : result.levels;
|
|
118
|
+
const lines = [
|
|
119
|
+
`Topological sort: ${result.levels.length - (result.cycleCount > 0 ? 1 : 0)} level${result.levels.length === 1 ? '' : 's'}` +
|
|
120
|
+
(result.cycleCount > 0 ? `, ${result.cycleCount} node${result.cycleCount === 1 ? '' : 's'} in cycles` : ''),
|
|
121
|
+
'',
|
|
122
|
+
];
|
|
123
|
+
for (let li = 0; li < displayLevels.length; li++) {
|
|
124
|
+
const level = displayLevels[li];
|
|
125
|
+
const label = li === isCycleLevelIdx ? 'Cycle nodes (unresolvable order)' : `Level ${li}`;
|
|
126
|
+
lines.push(`${label} (${level.length} node${level.length === 1 ? '' : 's'}):`);
|
|
127
|
+
for (const id of level) {
|
|
128
|
+
const info = nodeInfo.get(id);
|
|
129
|
+
const name = info?.name ?? id;
|
|
130
|
+
const fp = info?.filePath;
|
|
131
|
+
lines.push(` ${name}${fp ? ` — ${fp}` : ''}`);
|
|
132
|
+
}
|
|
133
|
+
lines.push('');
|
|
134
|
+
}
|
|
135
|
+
if (maxLevels !== undefined && result.levels.length > maxLevels) {
|
|
136
|
+
lines.push(`... (${result.levels.length - maxLevels} more level${result.levels.length - maxLevels === 1 ? '' : 's'} omitted)`);
|
|
137
|
+
}
|
|
138
|
+
return lines.join('\n').trimEnd();
|
|
139
|
+
}
|
|
67
140
|
//# sourceMappingURL=topo-sort.js.map
|