@ophan/core 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +56 -93
  2. package/dist/community-detectors/index.d.ts +20 -0
  3. package/dist/community-detectors/index.d.ts.map +1 -0
  4. package/dist/community-detectors/index.js +45 -0
  5. package/dist/community-detectors/label-prop.d.ts +20 -0
  6. package/dist/community-detectors/label-prop.d.ts.map +1 -0
  7. package/dist/community-detectors/label-prop.js +77 -0
  8. package/dist/community-detectors/leiden.d.ts +22 -0
  9. package/dist/community-detectors/leiden.d.ts.map +1 -0
  10. package/dist/community-detectors/leiden.js +312 -0
  11. package/dist/community-detectors/louvain.d.ts +13 -0
  12. package/dist/community-detectors/louvain.d.ts.map +1 -0
  13. package/dist/community-detectors/louvain.js +29 -0
  14. package/dist/community-detectors/types.d.ts +36 -0
  15. package/dist/community-detectors/types.d.ts.map +1 -0
  16. package/dist/{parsers/__fixtures__/no-functions.js → community-detectors/types.js} +0 -2
  17. package/dist/edge-resolvers/call.d.ts +13 -0
  18. package/dist/edge-resolvers/call.d.ts.map +1 -0
  19. package/dist/edge-resolvers/call.js +40 -0
  20. package/dist/edge-resolvers/co-location.d.ts +16 -0
  21. package/dist/edge-resolvers/co-location.d.ts.map +1 -0
  22. package/dist/edge-resolvers/co-location.js +129 -0
  23. package/dist/edge-resolvers/import.d.ts +16 -0
  24. package/dist/edge-resolvers/import.d.ts.map +1 -0
  25. package/dist/edge-resolvers/import.js +118 -0
  26. package/dist/edge-resolvers/index.d.ts +9 -0
  27. package/dist/edge-resolvers/index.d.ts.map +1 -0
  28. package/dist/edge-resolvers/index.js +29 -0
  29. package/dist/edge-resolvers/jsx-ref.d.ts +13 -0
  30. package/dist/edge-resolvers/jsx-ref.d.ts.map +1 -0
  31. package/dist/edge-resolvers/jsx-ref.js +40 -0
  32. package/dist/edge-resolvers/types.d.ts +40 -0
  33. package/dist/edge-resolvers/types.d.ts.map +1 -0
  34. package/dist/edge-resolvers/types.js +2 -0
  35. package/dist/graph.d.ts +293 -0
  36. package/dist/graph.d.ts.map +1 -0
  37. package/dist/graph.js +1295 -0
  38. package/dist/index.d.ts +37 -8
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +385 -183
  41. package/dist/migrations.d.ts +25 -0
  42. package/dist/migrations.d.ts.map +1 -0
  43. package/dist/migrations.js +323 -0
  44. package/dist/module-resolvers/index.d.ts +11 -0
  45. package/dist/module-resolvers/index.d.ts.map +1 -0
  46. package/dist/module-resolvers/index.js +67 -0
  47. package/dist/module-resolvers/javascript.d.ts +18 -0
  48. package/dist/module-resolvers/javascript.d.ts.map +1 -0
  49. package/dist/module-resolvers/javascript.js +130 -0
  50. package/dist/module-resolvers/types.d.ts +18 -0
  51. package/dist/module-resolvers/types.d.ts.map +1 -0
  52. package/dist/module-resolvers/types.js +2 -0
  53. package/dist/parsers/python.d.ts.map +1 -1
  54. package/dist/parsers/python.js +38 -4
  55. package/dist/parsers/typescript.d.ts.map +1 -1
  56. package/dist/parsers/typescript.js +133 -0
  57. package/dist/practices.d.ts +28 -0
  58. package/dist/practices.d.ts.map +1 -0
  59. package/dist/practices.js +95 -0
  60. package/dist/schemas.d.ts +251 -3
  61. package/dist/schemas.d.ts.map +1 -1
  62. package/dist/schemas.js +121 -6
  63. package/dist/shared.d.ts +8 -0
  64. package/dist/shared.d.ts.map +1 -1
  65. package/dist/summarize.d.ts +165 -0
  66. package/dist/summarize.d.ts.map +1 -0
  67. package/dist/summarize.js +1067 -0
  68. package/ophan_logo.png +0 -0
  69. package/package.json +11 -2
  70. package/dist/index.test.d.ts +0 -2
  71. package/dist/index.test.d.ts.map +0 -1
  72. package/dist/index.test.js +0 -492
  73. package/dist/parsers/__fixtures__/arrow-functions.d.ts +0 -5
  74. package/dist/parsers/__fixtures__/arrow-functions.d.ts.map +0 -1
  75. package/dist/parsers/__fixtures__/arrow-functions.js +0 -16
  76. package/dist/parsers/__fixtures__/class-methods.d.ts +0 -6
  77. package/dist/parsers/__fixtures__/class-methods.d.ts.map +0 -1
  78. package/dist/parsers/__fixtures__/class-methods.js +0 -12
  79. package/dist/parsers/__fixtures__/no-functions.d.ts +0 -9
  80. package/dist/parsers/__fixtures__/no-functions.d.ts.map +0 -1
  81. package/dist/parsers/python.test.d.ts +0 -2
  82. package/dist/parsers/python.test.d.ts.map +0 -1
  83. package/dist/parsers/python.test.js +0 -96
  84. package/dist/parsers/typescript.test.d.ts +0 -2
  85. package/dist/parsers/typescript.test.d.ts.map +0 -1
  86. package/dist/parsers/typescript.test.js +0 -106
  87. package/dist/test-utils.d.ts +0 -46
  88. package/dist/test-utils.d.ts.map +0 -1
  89. package/dist/test-utils.js +0 -141
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImportEdgeResolver = void 0;
4
+ const module_resolvers_1 = require("../module-resolvers");
5
+ /**
6
+ * Resolves import edges from import statements.
7
+ * Three resolution paths:
8
+ * 1. Direct: imported name found in the resolved target file
9
+ * 2. Barrel fallback: imported name found via package-scoped search (re-exports)
10
+ * 3. Namespace fallback: intersect fn.calls with target file's functions
11
+ *
12
+ * Owns importAdded Set for deduplication (import edges are undirected).
13
+ */
14
+ class ImportEdgeResolver {
15
+ constructor() {
16
+ this.edgeTypes = ["import"];
17
+ }
18
+ resolve(ctx) {
19
+ const edges = [];
20
+ const importAdded = new Set();
21
+ for (const fn of ctx.functions) {
22
+ if (ctx.affectedHashes && !ctx.affectedHashes.has(fn.contentHash))
23
+ continue;
24
+ if (!fn.imports)
25
+ continue;
26
+ for (const imp of fn.imports) {
27
+ const langResolver = (0, module_resolvers_1.getModuleResolverForFile)(fn.filePath);
28
+ const targetFile = langResolver?.resolveModuleToFile(imp.module, fn.filePath, ctx.fileToHashes, ctx.resolver);
29
+ // Determine package scope for fallback through barrel file re-exports
30
+ let pkgScope;
31
+ if (ctx.resolver) {
32
+ for (const [pkgName] of ctx.resolver.workspacePackages) {
33
+ if (imp.module === pkgName ||
34
+ imp.module.startsWith(pkgName + "/")) {
35
+ pkgScope = ctx.pkgNameToHashes.get(pkgName);
36
+ break;
37
+ }
38
+ }
39
+ }
40
+ if (!targetFile && !pkgScope)
41
+ continue;
42
+ // Create edges to the specific functions named in the import
43
+ let matched = false;
44
+ for (const importedName of imp.names) {
45
+ // Direct lookup: function defined in the resolved target file
46
+ const directHash = targetFile
47
+ ? ctx.fileNameToHash.get(`${targetFile}::${importedName}`)
48
+ : undefined;
49
+ if (directHash && directHash !== fn.contentHash) {
50
+ matched = true;
51
+ const a = fn.contentHash < directHash ? fn.contentHash : directHash;
52
+ const b = fn.contentHash < directHash ? directHash : fn.contentHash;
53
+ const importKey = `${a}|${b}`;
54
+ if (!importAdded.has(importKey)) {
55
+ importAdded.add(importKey);
56
+ edges.push({
57
+ sourceHash: a,
58
+ targetHash: b,
59
+ edgeType: "import",
60
+ weight: ctx.config.edgeWeights.import,
61
+ });
62
+ }
63
+ }
64
+ else if (pkgScope) {
65
+ // Fallback: imported name is a re-export through a barrel file
66
+ const targetHashes = pkgScope.get(importedName);
67
+ if (targetHashes) {
68
+ for (const targetHash of targetHashes) {
69
+ if (targetHash === fn.contentHash)
70
+ continue;
71
+ matched = true;
72
+ const a = fn.contentHash < targetHash ? fn.contentHash : targetHash;
73
+ const b = fn.contentHash < targetHash ? targetHash : fn.contentHash;
74
+ const importKey = `${a}|${b}`;
75
+ if (!importAdded.has(importKey)) {
76
+ importAdded.add(importKey);
77
+ edges.push({
78
+ sourceHash: a,
79
+ targetHash: b,
80
+ edgeType: "import",
81
+ weight: ctx.config.edgeWeights.import,
82
+ });
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
88
+ // Fallback for namespace imports: intersect fn.calls with target file's functions
89
+ if (!matched && fn.calls && targetFile) {
90
+ const targetFnsInFile = ctx.fileToHashes.get(targetFile);
91
+ if (targetFnsInFile) {
92
+ for (const calledName of fn.calls) {
93
+ const targetHash = ctx.fileNameToHash.get(`${targetFile}::${calledName}`);
94
+ if (targetHash &&
95
+ targetHash !== fn.contentHash &&
96
+ targetFnsInFile.has(targetHash)) {
97
+ const a = fn.contentHash < targetHash ? fn.contentHash : targetHash;
98
+ const b = fn.contentHash < targetHash ? targetHash : fn.contentHash;
99
+ const importKey = `${a}|${b}`;
100
+ if (!importAdded.has(importKey)) {
101
+ importAdded.add(importKey);
102
+ edges.push({
103
+ sourceHash: a,
104
+ targetHash: b,
105
+ edgeType: "import",
106
+ weight: ctx.config.edgeWeights.import,
107
+ });
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
113
+ }
114
+ }
115
+ return edges;
116
+ }
117
+ }
118
+ exports.ImportEdgeResolver = ImportEdgeResolver;
@@ -0,0 +1,9 @@
1
+ export type { EdgeResolver, EdgeResolverContext } from "./types";
2
+ export { CallEdgeResolver } from "./call";
3
+ export { JsxRefEdgeResolver } from "./jsx-ref";
4
+ export { CoLocationEdgeResolver } from "./co-location";
5
+ export { ImportEdgeResolver } from "./import";
6
+ import type { EdgeResolver } from "./types";
7
+ export declare function registerEdgeResolver(resolver: EdgeResolver): void;
8
+ export declare function getEdgeResolvers(): readonly EdgeResolver[];
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/edge-resolvers/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAQ5C,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAEjE;AAED,wBAAgB,gBAAgB,IAAI,SAAS,YAAY,EAAE,CAE1D"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImportEdgeResolver = exports.CoLocationEdgeResolver = exports.JsxRefEdgeResolver = exports.CallEdgeResolver = void 0;
4
+ exports.registerEdgeResolver = registerEdgeResolver;
5
+ exports.getEdgeResolvers = getEdgeResolvers;
6
+ var call_1 = require("./call");
7
+ Object.defineProperty(exports, "CallEdgeResolver", { enumerable: true, get: function () { return call_1.CallEdgeResolver; } });
8
+ var jsx_ref_1 = require("./jsx-ref");
9
+ Object.defineProperty(exports, "JsxRefEdgeResolver", { enumerable: true, get: function () { return jsx_ref_1.JsxRefEdgeResolver; } });
10
+ var co_location_1 = require("./co-location");
11
+ Object.defineProperty(exports, "CoLocationEdgeResolver", { enumerable: true, get: function () { return co_location_1.CoLocationEdgeResolver; } });
12
+ var import_1 = require("./import");
13
+ Object.defineProperty(exports, "ImportEdgeResolver", { enumerable: true, get: function () { return import_1.ImportEdgeResolver; } });
14
+ const call_2 = require("./call");
15
+ const jsx_ref_2 = require("./jsx-ref");
16
+ const co_location_2 = require("./co-location");
17
+ const import_2 = require("./import");
18
+ const registry = [];
19
+ function registerEdgeResolver(resolver) {
20
+ registry.push(resolver);
21
+ }
22
+ function getEdgeResolvers() {
23
+ return registry;
24
+ }
25
+ // Register built-in resolvers
26
+ registerEdgeResolver(new call_2.CallEdgeResolver());
27
+ registerEdgeResolver(new jsx_ref_2.JsxRefEdgeResolver());
28
+ registerEdgeResolver(new co_location_2.CoLocationEdgeResolver());
29
+ registerEdgeResolver(new import_2.ImportEdgeResolver());
@@ -0,0 +1,13 @@
1
+ import type { EdgeResolver, EdgeResolverContext } from "./types";
2
+ import type { FunctionEdge } from "../graph";
3
+ /**
4
+ * Resolves JSX component reference edges.
5
+ * When a function renders <Component />, creates a weak edge to that component.
6
+ * Separated from call edges because UI composition is a weaker domain signal
7
+ * than direct function calls.
8
+ */
9
+ export declare class JsxRefEdgeResolver implements EdgeResolver {
10
+ readonly edgeTypes: readonly ["jsx_ref"];
11
+ resolve(ctx: EdgeResolverContext): FunctionEdge[];
12
+ }
13
+ //# sourceMappingURL=jsx-ref.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-ref.d.ts","sourceRoot":"","sources":["../../src/edge-resolvers/jsx-ref.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C;;;;;GAKG;AACH,qBAAa,kBAAmB,YAAW,YAAY;IACrD,QAAQ,CAAC,SAAS,uBAAwB;IAE1C,OAAO,CAAC,GAAG,EAAE,mBAAmB,GAAG,YAAY,EAAE;CAqBlD"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JsxRefEdgeResolver = void 0;
4
+ /**
5
+ * Resolves JSX component reference edges.
6
+ * When a function renders <Component />, creates a weak edge to that component.
7
+ * Separated from call edges because UI composition is a weaker domain signal
8
+ * than direct function calls.
9
+ */
10
+ class JsxRefEdgeResolver {
11
+ constructor() {
12
+ this.edgeTypes = ["jsx_ref"];
13
+ }
14
+ resolve(ctx) {
15
+ const edges = [];
16
+ for (const fn of ctx.functions) {
17
+ if (ctx.affectedHashes && !ctx.affectedHashes.has(fn.contentHash))
18
+ continue;
19
+ if (!fn.jsxRefs)
20
+ continue;
21
+ for (const refName of fn.jsxRefs) {
22
+ const targetHashes = ctx.nameToHashes.get(refName);
23
+ if (!targetHashes)
24
+ continue;
25
+ for (const targetHash of targetHashes) {
26
+ if (targetHash === fn.contentHash)
27
+ continue;
28
+ edges.push({
29
+ sourceHash: fn.contentHash,
30
+ targetHash,
31
+ edgeType: "jsx_ref",
32
+ weight: ctx.config.edgeWeights.jsx_ref,
33
+ });
34
+ }
35
+ }
36
+ }
37
+ return edges;
38
+ }
39
+ }
40
+ exports.JsxRefEdgeResolver = JsxRefEdgeResolver;
@@ -0,0 +1,40 @@
1
+ import type { FunctionInfo } from "../shared";
2
+ import type { GraphConfig, FunctionEdge, ModuleResolver } from "../graph";
3
+ /**
4
+ * Shared context built once per resolveEdges() invocation.
5
+ * Contains pre-built lookup maps that edge resolvers need.
6
+ * The orchestrator builds this — resolvers consume it.
7
+ */
8
+ export interface EdgeResolverContext {
9
+ /** function_name → Set<content_hash> (handles name collisions across files) */
10
+ nameToHashes: Map<string, Set<string>>;
11
+ /** file_path → Set<content_hash> */
12
+ fileToHashes: Map<string, Set<string>>;
13
+ /** "file_path::function_name" → content_hash (targeted import lookup) */
14
+ fileNameToHash: Map<string, string>;
15
+ /** package_name → Map<function_name, Set<content_hash>> (barrel file fallback) */
16
+ pkgNameToHashes: Map<string, Map<string, Set<string>>>;
17
+ /** file_path → FunctionInfo[] sorted by startLine */
18
+ fileToSortedFns: Map<string, FunctionInfo[]>;
19
+ /** All extracted functions for this scan */
20
+ functions: FunctionInfo[];
21
+ /** Graph configuration (edge weights, etc.) */
22
+ config: GraphConfig;
23
+ /** Optional: limit resolution to these hashes (incremental mode) */
24
+ affectedHashes?: Set<string>;
25
+ /** Optional: workspace module resolver for import resolution */
26
+ resolver?: ModuleResolver;
27
+ }
28
+ /**
29
+ * Strategy interface for edge resolution.
30
+ * Each implementation handles one category of edges (calls, imports, co-location, etc.).
31
+ *
32
+ * Resolvers own their own deduplication — the orchestrator concatenates results.
33
+ */
34
+ export interface EdgeResolver {
35
+ /** Edge type identifier(s) this resolver produces */
36
+ readonly edgeTypes: readonly string[];
37
+ /** Resolve edges from the shared context */
38
+ resolve(ctx: EdgeResolverContext): FunctionEdge[];
39
+ }
40
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/edge-resolvers/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1E;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,+EAA+E;IAC/E,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACvC,oCAAoC;IACpC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACvC,yEAAyE;IACzE,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,kFAAkF;IAClF,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACvD,qDAAqD;IACrD,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;IAC7C,4CAA4C;IAC5C,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,+CAA+C;IAC/C,MAAM,EAAE,WAAW,CAAC;IACpB,oEAAoE;IACpE,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,gEAAgE;IAChE,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,4CAA4C;IAC5C,OAAO,CAAC,GAAG,EAAE,mBAAmB,GAAG,YAAY,EAAE,CAAC;CACnD"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,293 @@
1
+ import type Database from "better-sqlite3";
2
+ import Graph from "graphology";
3
+ import type { EdgeResolverContext } from "./edge-resolvers";
4
+ import type { FunctionInfo } from "./shared";
5
+ export interface GraphConfig {
6
+ /** Which community detection algorithm to use (extensible via registerDetector()) */
7
+ algorithm: string;
8
+ /** Relative edge weights by type (higher = stronger signal for community detection) */
9
+ edgeWeights: {
10
+ call: number;
11
+ type_ref: number;
12
+ import: number;
13
+ co_location: number;
14
+ jsx_ref: number;
15
+ transitive_call: number;
16
+ co_caller: number;
17
+ };
18
+ /** Louvain/Leiden resolution parameter. Higher = more, smaller communities */
19
+ resolution: number;
20
+ /** Minimum functions in a community (smaller clusters are dissolved) */
21
+ minCommunitySize: number;
22
+ /** Maximum functions in a community (larger clusters may indicate poor resolution) */
23
+ maxCommunitySize: number;
24
+ /** When true, resolution scales up automatically with codebase size */
25
+ autoResolution?: boolean;
26
+ /** Exponential decay factor for directory distance between files.
27
+ * Applied as exp(-directoryDecay * distance) to cross-directory edges.
28
+ * 0 = no penalty, higher = stronger penalty for distant files.
29
+ * Default: 0.1 */
30
+ directoryDecay?: number;
31
+ }
32
+ /**
33
+ * Default edge weights for graph construction.
34
+ *
35
+ * These control how strongly each relationship type pulls functions into the
36
+ * same community. All weights are relative — what matters is the ratio between
37
+ * them, not the absolute values. Weights from different edge types between the
38
+ * same function pair are summed in the merged graph.
39
+ *
40
+ * Edit these to tune community detection. After changing, re-run:
41
+ * pnpm dev graph --compare --path .
42
+ * to see the effect across all algorithms.
43
+ */
44
+ export declare const DEFAULT_EDGE_WEIGHTS: GraphConfig["edgeWeights"];
45
+ export declare const DEFAULT_GRAPH_CONFIG: GraphConfig;
46
+ /**
47
+ * Compute directory-level distance between two files relative to rootPath.
48
+ * Distance = number of unique directory segments when traversing from one file's
49
+ * directory to the other via their common ancestor.
50
+ *
51
+ * Examples (relative to root):
52
+ * src/components/Button.tsx vs src/components/Input.tsx → 0 (same dir)
53
+ * src/components/Button.tsx vs src/utils/format.ts → 2 (sibling dirs)
54
+ * packages/core/src/graph.ts vs packages/webapp/src/App.tsx → 4
55
+ */
56
+ export declare function computeDirectoryDistance(filePathA: string, filePathB: string, rootPath: string): number;
57
+ /**
58
+ * Extract a human-readable package label for a file.
59
+ * Uses the ModuleResolver to find the containing workspace package if available.
60
+ * Falls back to the first directory segment relative to root.
61
+ */
62
+ export declare function computePackage(filePath: string, rootPath: string, resolver?: ModuleResolver): string;
63
+ export interface ModuleResolver {
64
+ /** Map workspace package names (e.g. "@ophan/core") to their directory + exports */
65
+ workspacePackages: Map<string, {
66
+ dir: string;
67
+ exports: Record<string, string>;
68
+ }>;
69
+ /** Map package directory to its tsconfig path aliases */
70
+ pathAliases: Map<string, {
71
+ baseUrl: string;
72
+ paths: Record<string, string[]>;
73
+ }>;
74
+ }
75
+ /**
76
+ * Build a ModuleResolver by discovering packages via marker files.
77
+ * Walks up from analyzed file directories to find package.json, pyproject.toml, etc.
78
+ * Reads package.json (for name + exports) and tsconfig.json (for path aliases).
79
+ * Runs once per graph command invocation — not per-edge.
80
+ */
81
+ export declare function buildModuleResolver(rootPath: string, functions?: FunctionInfo[]): ModuleResolver;
82
+ export interface FunctionEdge {
83
+ sourceHash: string;
84
+ targetHash: string;
85
+ edgeType: "call" | "type_ref" | "import" | "co_location" | "jsx_ref" | "transitive_call" | "co_caller";
86
+ weight: number;
87
+ }
88
+ export interface CommunityEdge {
89
+ sourceCommunity: string;
90
+ targetCommunity: string;
91
+ algorithm: string;
92
+ weight: number;
93
+ edgeCount: number;
94
+ }
95
+ export interface CommunityAssignment {
96
+ contentHash: string;
97
+ level: number;
98
+ communityId: string;
99
+ algorithm: string;
100
+ }
101
+ export declare function loadGraphConfig(db: Database.Database): GraphConfig;
102
+ export declare function saveGraphConfig(db: Database.Database, config: GraphConfig): void;
103
+ /**
104
+ * Given extracted functions with call-site data, resolve name-based calls to
105
+ * content hash edges. Uses the file_functions index for name→hash lookup.
106
+ *
107
+ * Returns edges ready to insert into function_edges table.
108
+ */
109
+ /**
110
+ * Build shared lookup context for edge resolvers.
111
+ * Queries file_functions once and constructs all lookup maps that resolvers need.
112
+ * Called once per resolveEdges() invocation.
113
+ */
114
+ export declare function buildEdgeResolverContext(db: Database.Database, functions: FunctionInfo[], config: GraphConfig, affectedHashes?: Set<string>, resolver?: ModuleResolver): EdgeResolverContext;
115
+ export declare function resolveEdges(db: Database.Database, functions: FunctionInfo[], config: GraphConfig, affectedHashes?: Set<string>, resolver?: ModuleResolver): FunctionEdge[];
116
+ /**
117
+ * Derive transitive edges from the call graph to increase connectivity.
118
+ * Pure function — no DB access.
119
+ *
120
+ * Two derived edge types:
121
+ * 1. **transitive_call** (A→B→C creates A↔C): 2-hop call chain connectivity.
122
+ * 2. **co_caller** (A→B, A→C creates B↔C): Functions called by the same caller.
123
+ *
124
+ * Edges are NOT deduped against direct edges — being related in multiple ways
125
+ * (e.g., direct call + transitive chain) intentionally increases connection strength.
126
+ * buildGraph() merges parallel edges by summing weights.
127
+ */
128
+ export declare function addTransitiveEdges(edges: FunctionEdge[], config: GraphConfig): FunctionEdge[];
129
+ /**
130
+ * Store resolved edges in the function_edges table.
131
+ * Clears existing edges first (they're rebuilt from source each scan).
132
+ */
133
+ export declare function storeEdges(db: Database.Database, edges: FunctionEdge[]): void;
134
+ /**
135
+ * Incremental edge storage: delete edges for affected hashes, then insert new edges.
136
+ * Used when only a subset of functions changed — keeps unaffected edges in place.
137
+ */
138
+ export declare function storeEdgesIncremental(db: Database.Database, affectedHashes: Set<string>, newEdges: FunctionEdge[]): void;
139
+ /**
140
+ * Load all edges from the database.
141
+ */
142
+ export declare function loadEdges(db: Database.Database): FunctionEdge[];
143
+ /**
144
+ * Store community assignments in the communities table.
145
+ */
146
+ export declare function storeCommunities(db: Database.Database, assignments: CommunityAssignment[]): void;
147
+ /**
148
+ * Load community assignments from the database.
149
+ */
150
+ export declare function loadCommunities(db: Database.Database, algorithm: string, level: number): CommunityAssignment[];
151
+ /**
152
+ * Aggregate function-level edges into community-level edges.
153
+ * For each pair of distinct L0 communities, sums the weights of all
154
+ * function edges that cross between them.
155
+ */
156
+ export declare function computeCommunityEdges(db: Database.Database, algorithm: string, edges?: FunctionEdge[]): CommunityEdge[];
157
+ /**
158
+ * Store community edges (full replace per algorithm).
159
+ */
160
+ export declare function storeCommunityEdges(db: Database.Database, edges: CommunityEdge[]): void;
161
+ /**
162
+ * Load community edges from the database.
163
+ */
164
+ export declare function loadCommunityEdges(db: Database.Database, algorithm: string): CommunityEdge[];
165
+ export interface DetectionResult {
166
+ assignments: CommunityAssignment[];
167
+ communityCount: number;
168
+ modularity: number | null;
169
+ nodesInGraph: number;
170
+ edgesInGraph: number;
171
+ dissolvedCount: number;
172
+ effectiveResolution?: number;
173
+ }
174
+ /**
175
+ * Build a graphology graph from function edges.
176
+ * Creates an undirected weighted graph — multiple edges between the same
177
+ * pair (different edge types) are merged by summing weights.
178
+ */
179
+ export declare function buildGraph(edges: FunctionEdge[], hashToFilePath?: Map<string, string>, rootPath?: string, directoryDecay?: number, allHashes?: Set<string>): Graph;
180
+ export interface CentralityResult {
181
+ /** Map of content_hash → betweenness centrality score (0–1, normalized) */
182
+ scores: Map<string, number>;
183
+ /** Functions ranked by centrality descending — top bridge functions first */
184
+ ranked: {
185
+ contentHash: string;
186
+ score: number;
187
+ }[];
188
+ }
189
+ /**
190
+ * Compute betweenness centrality for all nodes in the graph.
191
+ * High-centrality nodes are "bridge" functions that many shortest paths
192
+ * pass through — coupling points between communities.
193
+ */
194
+ export declare function computeCentrality(graph: Graph): CentralityResult;
195
+ /**
196
+ * Rescue dissolved nodes by assigning each to the community with the strongest
197
+ * total edge weight. Mutates assignments in-place. Returns the number rescued.
198
+ *
199
+ * Nodes with zero connections to any non-dissolved community stay dissolved.
200
+ * Rescued nodes update the membership map so subsequent rescues see them as
201
+ * placed (enabling chained rescue where node B is rescued into a community
202
+ * that node A was just rescued into).
203
+ */
204
+ export declare function rescueDissolvedNodes(assignments: CommunityAssignment[], edges: FunctionEdge[], dissolvedMarker: string): number;
205
+ /**
206
+ * Run community detection on the given edges using the configured algorithm.
207
+ * Returns assignments ready for storage, plus stats about the detection run.
208
+ *
209
+ * Small communities (< minCommunitySize) are dissolved — their members are
210
+ * assigned to a special "__dissolved" community. Dissolved nodes are then
211
+ * rescued: each is assigned to the community it's most connected to by total
212
+ * edge weight. Truly isolated nodes (zero connections) stay dissolved.
213
+ */
214
+ export declare function detectCommunities(edges: FunctionEdge[], config: GraphConfig, hashToFilePath?: Map<string, string>, rootPath?: string, allHashes?: Set<string>): DetectionResult;
215
+ /**
216
+ * Match new community assignments to old ones by Jaccard similarity.
217
+ * Remaps new community IDs to reuse old IDs where membership overlaps significantly.
218
+ * This prevents summary cache misses caused by Louvain's arbitrary ID renumbering.
219
+ *
220
+ * Algorithm: greedy 1:1 matching — sort all (new, old, Jaccard) triples by score
221
+ * descending, accept matches where J ≥ threshold, each ID used at most once.
222
+ */
223
+ export declare function matchCommunities(oldAssignments: CommunityAssignment[], newAssignments: CommunityAssignment[], threshold?: number): CommunityAssignment[];
224
+ /**
225
+ * Label Propagation Algorithm (LPA) for community detection.
226
+ * Delegates to LabelPropDetector — kept as a standalone export for backward compatibility.
227
+ */
228
+ export declare function labelPropagation(graph: Graph, maxIterations?: number): Record<string, number>;
229
+ /**
230
+ * Compute the set of content hashes that changed between old and new function sets.
231
+ * Returns the symmetric difference: hashes that appeared or disappeared.
232
+ */
233
+ export declare function computeChangedHashes(oldHashes: Set<string>, newHashes: Set<string>): Set<string>;
234
+ /**
235
+ * Full graph analysis pipeline: resolve edges → build graph → detect communities → store.
236
+ * Call after file scanning to update the relationship graph.
237
+ *
238
+ * When `oldHashes` is provided, uses incremental edge resolution: only recomputes edges
239
+ * for changed functions + their neighbors, keeping the rest of the graph stable.
240
+ */
241
+ export declare function analyzeGraph(db: Database.Database, functions: FunctionInfo[], config?: GraphConfig, oldHashes?: Set<string>, rootPath?: string): DetectionResult;
242
+ export interface HierarchicalDetectionResult {
243
+ l0: DetectionResult;
244
+ communityEdges: CommunityEdge[];
245
+ l1Assignments: CommunityAssignment[];
246
+ l1GroupCount: number;
247
+ }
248
+ /**
249
+ * Detect hierarchical communities: first L0 (function-level), then L1 (community-level).
250
+ *
251
+ * After L0 detection + community edge computation, builds a meta-graph where:
252
+ * - Nodes = L0 community IDs (excluding __dissolved)
253
+ * - Edges = community_edges (weighted by aggregate function edge weight)
254
+ *
255
+ * Runs Louvain on meta-graph to produce L1 group assignments.
256
+ * Stores L1 assignments in the communities table with level=1,
257
+ * where content_hash = L0 community_id.
258
+ *
259
+ * When `oldHashes` is provided, enables incremental edge resolution in the L0 step.
260
+ */
261
+ export declare function detectHierarchicalCommunities(db: Database.Database, functions: FunctionInfo[], config?: GraphConfig, oldHashes?: Set<string>, rootPath?: string): HierarchicalDetectionResult;
262
+ export interface ComparisonMetrics {
263
+ label: string;
264
+ algorithm: string;
265
+ resolution: number | null;
266
+ communityCount: number;
267
+ dissolvedCount: number;
268
+ dissolvedPct: number;
269
+ coverage: number;
270
+ minSize: number;
271
+ medianSize: number;
272
+ maxSize: number;
273
+ modularity: number | null;
274
+ nodesInGraph: number;
275
+ edgesInGraph: number;
276
+ }
277
+ export interface ComparisonConfig {
278
+ label: string;
279
+ algorithm: string;
280
+ resolution: number;
281
+ }
282
+ export declare const DEFAULT_COMPARISONS: ComparisonConfig[];
283
+ /**
284
+ * Compute comparison metrics from a DetectionResult.
285
+ * Pure function — no DB or side effects.
286
+ */
287
+ export declare function computeComparisonMetrics(result: DetectionResult, label: string, algorithm: string, resolution: number | null): ComparisonMetrics;
288
+ /**
289
+ * Run community detection at multiple configurations on the same edges.
290
+ * Does NOT write to DB — pure computation for comparison.
291
+ */
292
+ export declare function runComparison(edges: FunctionEdge[], baseConfig: GraphConfig, configurations: ComparisonConfig[], hashToFilePath?: Map<string, string>, rootPath?: string, allHashes?: Set<string>): ComparisonMetrics[];
293
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"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"}