@bugsbunnycodes1998/cartographer-core 0.1.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.
Files changed (220) hide show
  1. package/dist/__tests__/pipeline.test.d.ts +2 -0
  2. package/dist/__tests__/pipeline.test.d.ts.map +1 -0
  3. package/dist/__tests__/pipeline.test.js +58 -0
  4. package/dist/__tests__/pipeline.test.js.map +1 -0
  5. package/dist/analysis/call-graph.d.ts +13 -0
  6. package/dist/analysis/call-graph.d.ts.map +1 -0
  7. package/dist/analysis/call-graph.js +133 -0
  8. package/dist/analysis/call-graph.js.map +1 -0
  9. package/dist/analysis/dependency-graph.d.ts +8 -0
  10. package/dist/analysis/dependency-graph.d.ts.map +1 -0
  11. package/dist/analysis/dependency-graph.js +101 -0
  12. package/dist/analysis/dependency-graph.js.map +1 -0
  13. package/dist/analysis/git/archaeology.d.ts +20 -0
  14. package/dist/analysis/git/archaeology.d.ts.map +1 -0
  15. package/dist/analysis/git/archaeology.js +61 -0
  16. package/dist/analysis/git/archaeology.js.map +1 -0
  17. package/dist/analysis/git/bus-factor.d.ts +17 -0
  18. package/dist/analysis/git/bus-factor.d.ts.map +1 -0
  19. package/dist/analysis/git/bus-factor.js +90 -0
  20. package/dist/analysis/git/bus-factor.js.map +1 -0
  21. package/dist/analysis/git/churn.d.ts +26 -0
  22. package/dist/analysis/git/churn.d.ts.map +1 -0
  23. package/dist/analysis/git/churn.js +127 -0
  24. package/dist/analysis/git/churn.js.map +1 -0
  25. package/dist/analysis/git/contributors.d.ts +14 -0
  26. package/dist/analysis/git/contributors.d.ts.map +1 -0
  27. package/dist/analysis/git/contributors.js +60 -0
  28. package/dist/analysis/git/contributors.js.map +1 -0
  29. package/dist/analysis/git/evolution.d.ts +10 -0
  30. package/dist/analysis/git/evolution.d.ts.map +1 -0
  31. package/dist/analysis/git/evolution.js +127 -0
  32. package/dist/analysis/git/evolution.js.map +1 -0
  33. package/dist/analysis/git/index.d.ts +6 -0
  34. package/dist/analysis/git/index.d.ts.map +1 -0
  35. package/dist/analysis/git/index.js +6 -0
  36. package/dist/analysis/git/index.js.map +1 -0
  37. package/dist/analysis/go-visitor.d.ts +4 -0
  38. package/dist/analysis/go-visitor.d.ts.map +1 -0
  39. package/dist/analysis/go-visitor.js +295 -0
  40. package/dist/analysis/go-visitor.js.map +1 -0
  41. package/dist/analysis/health/indicators.d.ts +25 -0
  42. package/dist/analysis/health/indicators.d.ts.map +1 -0
  43. package/dist/analysis/health/indicators.js +53 -0
  44. package/dist/analysis/health/indicators.js.map +1 -0
  45. package/dist/analysis/health/scorer.d.ts +26 -0
  46. package/dist/analysis/health/scorer.d.ts.map +1 -0
  47. package/dist/analysis/health/scorer.js +97 -0
  48. package/dist/analysis/health/scorer.js.map +1 -0
  49. package/dist/analysis/health/test-coverage.d.ts +19 -0
  50. package/dist/analysis/health/test-coverage.d.ts.map +1 -0
  51. package/dist/analysis/health/test-coverage.js +67 -0
  52. package/dist/analysis/health/test-coverage.js.map +1 -0
  53. package/dist/analysis/import-resolver.d.ts +10 -0
  54. package/dist/analysis/import-resolver.d.ts.map +1 -0
  55. package/dist/analysis/import-resolver.js +353 -0
  56. package/dist/analysis/import-resolver.js.map +1 -0
  57. package/dist/analysis/index.d.ts +22 -0
  58. package/dist/analysis/index.d.ts.map +1 -0
  59. package/dist/analysis/index.js +24 -0
  60. package/dist/analysis/index.js.map +1 -0
  61. package/dist/analysis/java-visitor.d.ts +4 -0
  62. package/dist/analysis/java-visitor.d.ts.map +1 -0
  63. package/dist/analysis/java-visitor.js +257 -0
  64. package/dist/analysis/java-visitor.js.map +1 -0
  65. package/dist/analysis/metrics.d.ts +19 -0
  66. package/dist/analysis/metrics.d.ts.map +1 -0
  67. package/dist/analysis/metrics.js +70 -0
  68. package/dist/analysis/metrics.js.map +1 -0
  69. package/dist/analysis/module-detector.d.ts +3 -0
  70. package/dist/analysis/module-detector.d.ts.map +1 -0
  71. package/dist/analysis/module-detector.js +257 -0
  72. package/dist/analysis/module-detector.js.map +1 -0
  73. package/dist/analysis/parser.d.ts +13 -0
  74. package/dist/analysis/parser.d.ts.map +1 -0
  75. package/dist/analysis/parser.js +92 -0
  76. package/dist/analysis/parser.js.map +1 -0
  77. package/dist/analysis/python-visitor.d.ts +4 -0
  78. package/dist/analysis/python-visitor.d.ts.map +1 -0
  79. package/dist/analysis/python-visitor.js +306 -0
  80. package/dist/analysis/python-visitor.js.map +1 -0
  81. package/dist/analysis/rust-visitor.d.ts +4 -0
  82. package/dist/analysis/rust-visitor.d.ts.map +1 -0
  83. package/dist/analysis/rust-visitor.js +318 -0
  84. package/dist/analysis/rust-visitor.js.map +1 -0
  85. package/dist/analysis/semantic/cache.d.ts +16 -0
  86. package/dist/analysis/semantic/cache.d.ts.map +1 -0
  87. package/dist/analysis/semantic/cache.js +26 -0
  88. package/dist/analysis/semantic/cache.js.map +1 -0
  89. package/dist/analysis/semantic/openai-client.d.ts +21 -0
  90. package/dist/analysis/semantic/openai-client.d.ts.map +1 -0
  91. package/dist/analysis/semantic/openai-client.js +73 -0
  92. package/dist/analysis/semantic/openai-client.js.map +1 -0
  93. package/dist/analysis/semantic/prompts.d.ts +32 -0
  94. package/dist/analysis/semantic/prompts.d.ts.map +1 -0
  95. package/dist/analysis/semantic/prompts.js +134 -0
  96. package/dist/analysis/semantic/prompts.js.map +1 -0
  97. package/dist/analysis/semantic/summarizer.d.ts +36 -0
  98. package/dist/analysis/semantic/summarizer.d.ts.map +1 -0
  99. package/dist/analysis/semantic/summarizer.js +229 -0
  100. package/dist/analysis/semantic/summarizer.js.map +1 -0
  101. package/dist/analysis/ts-js-visitor.d.ts +4 -0
  102. package/dist/analysis/ts-js-visitor.d.ts.map +1 -0
  103. package/dist/analysis/ts-js-visitor.js +390 -0
  104. package/dist/analysis/ts-js-visitor.js.map +1 -0
  105. package/dist/analysis/visitor-registry.d.ts +5 -0
  106. package/dist/analysis/visitor-registry.d.ts.map +1 -0
  107. package/dist/analysis/visitor-registry.js +17 -0
  108. package/dist/analysis/visitor-registry.js.map +1 -0
  109. package/dist/analysis/visitor-utils.d.ts +38 -0
  110. package/dist/analysis/visitor-utils.d.ts.map +1 -0
  111. package/dist/analysis/visitor-utils.js +110 -0
  112. package/dist/analysis/visitor-utils.js.map +1 -0
  113. package/dist/errors.d.ts +20 -0
  114. package/dist/errors.d.ts.map +1 -0
  115. package/dist/errors.js +39 -0
  116. package/dist/errors.js.map +1 -0
  117. package/dist/expeditions/custom.d.ts +11 -0
  118. package/dist/expeditions/custom.d.ts.map +1 -0
  119. package/dist/expeditions/custom.js +61 -0
  120. package/dist/expeditions/custom.js.map +1 -0
  121. package/dist/expeditions/danger-zones.d.ts +9 -0
  122. package/dist/expeditions/danger-zones.d.ts.map +1 -0
  123. package/dist/expeditions/danger-zones.js +42 -0
  124. package/dist/expeditions/danger-zones.js.map +1 -0
  125. package/dist/expeditions/generator.d.ts +21 -0
  126. package/dist/expeditions/generator.d.ts.map +1 -0
  127. package/dist/expeditions/generator.js +78 -0
  128. package/dist/expeditions/generator.js.map +1 -0
  129. package/dist/expeditions/grand-tour.d.ts +10 -0
  130. package/dist/expeditions/grand-tour.d.ts.map +1 -0
  131. package/dist/expeditions/grand-tour.js +96 -0
  132. package/dist/expeditions/grand-tour.js.map +1 -0
  133. package/dist/expeditions/request-flow.d.ts +11 -0
  134. package/dist/expeditions/request-flow.d.ts.map +1 -0
  135. package/dist/expeditions/request-flow.js +138 -0
  136. package/dist/expeditions/request-flow.js.map +1 -0
  137. package/dist/grammars/tree-sitter-go.wasm +0 -0
  138. package/dist/grammars/tree-sitter-java.wasm +0 -0
  139. package/dist/grammars/tree-sitter-javascript.wasm +0 -0
  140. package/dist/grammars/tree-sitter-python.wasm +0 -0
  141. package/dist/grammars/tree-sitter-rust.wasm +0 -0
  142. package/dist/grammars/tree-sitter-tsx.wasm +0 -0
  143. package/dist/grammars/tree-sitter-typescript.wasm +0 -0
  144. package/dist/graph/builder.d.ts +23 -0
  145. package/dist/graph/builder.d.ts.map +1 -0
  146. package/dist/graph/builder.js +131 -0
  147. package/dist/graph/builder.js.map +1 -0
  148. package/dist/graph/exporter.d.ts +5 -0
  149. package/dist/graph/exporter.d.ts.map +1 -0
  150. package/dist/graph/exporter.js +20 -0
  151. package/dist/graph/exporter.js.map +1 -0
  152. package/dist/graph/layout.d.ts +3 -0
  153. package/dist/graph/layout.d.ts.map +1 -0
  154. package/dist/graph/layout.js +257 -0
  155. package/dist/graph/layout.js.map +1 -0
  156. package/dist/graph/store.d.ts +13 -0
  157. package/dist/graph/store.d.ts.map +1 -0
  158. package/dist/graph/store.js +145 -0
  159. package/dist/graph/store.js.map +1 -0
  160. package/dist/index.d.ts +17 -0
  161. package/dist/index.d.ts.map +1 -0
  162. package/dist/index.js +12 -0
  163. package/dist/index.js.map +1 -0
  164. package/dist/ingestion/cloner.d.ts +18 -0
  165. package/dist/ingestion/cloner.d.ts.map +1 -0
  166. package/dist/ingestion/cloner.js +62 -0
  167. package/dist/ingestion/cloner.js.map +1 -0
  168. package/dist/ingestion/file-tree.d.ts +3 -0
  169. package/dist/ingestion/file-tree.d.ts.map +1 -0
  170. package/dist/ingestion/file-tree.js +85 -0
  171. package/dist/ingestion/file-tree.js.map +1 -0
  172. package/dist/ingestion/index.d.ts +5 -0
  173. package/dist/ingestion/index.d.ts.map +1 -0
  174. package/dist/ingestion/index.js +5 -0
  175. package/dist/ingestion/index.js.map +1 -0
  176. package/dist/ingestion/language-detector.d.ts +8 -0
  177. package/dist/ingestion/language-detector.d.ts.map +1 -0
  178. package/dist/ingestion/language-detector.js +37 -0
  179. package/dist/ingestion/language-detector.js.map +1 -0
  180. package/dist/ingestion/path-resolver.d.ts +7 -0
  181. package/dist/ingestion/path-resolver.d.ts.map +1 -0
  182. package/dist/ingestion/path-resolver.js +30 -0
  183. package/dist/ingestion/path-resolver.js.map +1 -0
  184. package/dist/logger.d.ts +3 -0
  185. package/dist/logger.d.ts.map +1 -0
  186. package/dist/logger.js +11 -0
  187. package/dist/logger.js.map +1 -0
  188. package/dist/pipeline.d.ts +3 -0
  189. package/dist/pipeline.d.ts.map +1 -0
  190. package/dist/pipeline.js +223 -0
  191. package/dist/pipeline.js.map +1 -0
  192. package/dist/types/analysis.d.ts +51 -0
  193. package/dist/types/analysis.d.ts.map +1 -0
  194. package/dist/types/analysis.js +2 -0
  195. package/dist/types/analysis.js.map +1 -0
  196. package/dist/types/config.d.ts +19 -0
  197. package/dist/types/config.d.ts.map +1 -0
  198. package/dist/types/config.js +2 -0
  199. package/dist/types/config.js.map +1 -0
  200. package/dist/types/edges.d.ts +8 -0
  201. package/dist/types/edges.d.ts.map +1 -0
  202. package/dist/types/edges.js +2 -0
  203. package/dist/types/edges.js.map +1 -0
  204. package/dist/types/expeditions.d.ts +19 -0
  205. package/dist/types/expeditions.d.ts.map +1 -0
  206. package/dist/types/expeditions.js +2 -0
  207. package/dist/types/expeditions.js.map +1 -0
  208. package/dist/types/graph.d.ts +29 -0
  209. package/dist/types/graph.d.ts.map +1 -0
  210. package/dist/types/graph.js +2 -0
  211. package/dist/types/graph.js.map +1 -0
  212. package/dist/types/index.d.ts +7 -0
  213. package/dist/types/index.d.ts.map +1 -0
  214. package/dist/types/index.js +2 -0
  215. package/dist/types/index.js.map +1 -0
  216. package/dist/types/nodes.d.ts +35 -0
  217. package/dist/types/nodes.d.ts.map +1 -0
  218. package/dist/types/nodes.js +2 -0
  219. package/dist/types/nodes.js.map +1 -0
  220. package/package.json +36 -0
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pipeline.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/pipeline.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,58 @@
1
+ import { describe, it, expect, afterEach } from "vitest";
2
+ import { resolve, join } from "node:path";
3
+ import { existsSync, rmSync } from "node:fs";
4
+ import { analyze } from "../pipeline.js";
5
+ const FIXTURE_DIR = resolve(import.meta.dirname, "..", "..", "..", "..", "test", "fixtures", "tiny-ts");
6
+ const OUTPUT_DIR = join(FIXTURE_DIR, ".cartographer-test");
7
+ afterEach(() => {
8
+ if (existsSync(OUTPUT_DIR)) {
9
+ rmSync(OUTPUT_DIR, { recursive: true, force: true });
10
+ }
11
+ });
12
+ describe("analyze pipeline", () => {
13
+ it("analyzes the tiny-ts fixture and produces a valid graph", async () => {
14
+ const graph = await analyze({
15
+ rootDir: FIXTURE_DIR,
16
+ outputDir: OUTPUT_DIR,
17
+ });
18
+ // Check meta
19
+ expect(graph.meta.languages).toContain("typescript");
20
+ expect(graph.meta.totalFiles).toBeGreaterThan(0);
21
+ expect(graph.meta.totalModules).toBeGreaterThan(0);
22
+ // Check nodes exist
23
+ const modules = graph.nodes.filter((n) => n.kind === "module");
24
+ const files = graph.nodes.filter((n) => n.kind === "file");
25
+ expect(modules.length).toBeGreaterThanOrEqual(2); // at least auth, utils
26
+ expect(files.length).toBeGreaterThanOrEqual(5);
27
+ // Check module names
28
+ const moduleNames = modules.map((m) => m.name);
29
+ expect(moduleNames).toContain("auth");
30
+ expect(moduleNames).toContain("utils");
31
+ // Check files have LOC > 0
32
+ for (const file of files) {
33
+ expect(file.loc).toBeGreaterThan(0);
34
+ }
35
+ // Check file-to-module relationships
36
+ for (const file of files) {
37
+ expect(file.parentId).toBeTruthy();
38
+ expect(modules.some((m) => m.id === file.parentId)).toBe(true);
39
+ }
40
+ // auth -> utils dependency (login.ts imports hash.ts)
41
+ expect(graph.edges.length).toBeGreaterThan(0);
42
+ const authToUtils = graph.edges.find((e) => e.sourceId === "mod:auth" && e.targetId === "mod:utils");
43
+ expect(authToUtils).toBeDefined();
44
+ // Check layout: modules have non-zero positions
45
+ const modulesWithPositions = modules.filter((n) => n.position.x !== 0 || n.position.z !== 0);
46
+ expect(modulesWithPositions.length).toBeGreaterThan(0);
47
+ // Check file buildings have dimensions
48
+ for (const file of files) {
49
+ expect(file.dimensions.width).toBeGreaterThan(0);
50
+ expect(file.dimensions.height).toBeGreaterThan(0);
51
+ expect(file.dimensions.depth).toBeGreaterThan(0);
52
+ }
53
+ // Check output files were created
54
+ expect(existsSync(join(OUTPUT_DIR, "cartographer.db"))).toBe(true);
55
+ expect(existsSync(join(OUTPUT_DIR, "graph.json"))).toBe(true);
56
+ }, 30000);
57
+ });
58
+ //# sourceMappingURL=pipeline.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.test.js","sourceRoot":"","sources":["../../src/__tests__/pipeline.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { GraphNode, GraphEdge, FileAnalysis, ModuleInfo } from "../types/index.js";
2
+ export interface CallGraphResult {
3
+ functionNodes: GraphNode[];
4
+ callEdges: GraphEdge[];
5
+ }
6
+ /**
7
+ * Build function-level nodes and call edges from file analyses.
8
+ *
9
+ * Creates a `GraphNode` for each function declaration and a `GraphEdge`
10
+ * for each resolved function-to-function call (same-file and cross-file).
11
+ */
12
+ export declare function buildCallGraph(analyses: FileAnalysis[], modules: ModuleInfo[], rootDir: string): CallGraphResult;
13
+ //# sourceMappingURL=call-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-graph.d.ts","sourceRoot":"","sources":["../../src/analysis/call-graph.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAOxF,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,SAAS,EAAE,CAAC;IAC3B,SAAS,EAAE,SAAS,EAAE,CAAC;CACxB;AA2BD;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,EAAE,UAAU,EAAE,EACrB,OAAO,EAAE,MAAM,GACd,eAAe,CA+GjB"}
@@ -0,0 +1,133 @@
1
+ import { relative } from "node:path";
2
+ import { logger } from "../logger.js";
3
+ function normalizePath(p) {
4
+ return p.replace(/\\/g, "/");
5
+ }
6
+ function makeDefaultNode(id, kind, name) {
7
+ return {
8
+ id,
9
+ kind,
10
+ name,
11
+ path: null,
12
+ parentId: null,
13
+ loc: 0,
14
+ complexity: 0,
15
+ healthScore: 50,
16
+ createdAt: null,
17
+ lastModified: null,
18
+ totalCommits: 0,
19
+ busFactor: 0,
20
+ primaryOwner: null,
21
+ churnScore: 0,
22
+ summary: null,
23
+ explanation: null,
24
+ layer: null,
25
+ tags: [],
26
+ position: { x: 0, y: 0, z: 0 },
27
+ dimensions: { width: 1, height: 1, depth: 1 },
28
+ };
29
+ }
30
+ /**
31
+ * Build function-level nodes and call edges from file analyses.
32
+ *
33
+ * Creates a `GraphNode` for each function declaration and a `GraphEdge`
34
+ * for each resolved function-to-function call (same-file and cross-file).
35
+ */
36
+ export function buildCallGraph(analyses, modules, rootDir) {
37
+ const functionNodes = [];
38
+ const callEdgeMap = new Map();
39
+ // Maps for resolution
40
+ // relPath -> function name[]
41
+ const functionsByFile = new Map();
42
+ // relPath -> Map<importedName, sourceRelPath>
43
+ const importedNamesByFile = new Map();
44
+ // Set of all function node IDs for validation
45
+ const functionNodeIds = new Set();
46
+ // Pass 1: Create function nodes and build lookup maps
47
+ for (const analysis of analyses) {
48
+ const relPath = normalizePath(relative(rootDir, analysis.filePath));
49
+ const fileId = `file:${relPath}`;
50
+ // Find parent module for the file
51
+ let parentModuleId = null;
52
+ for (const mod of modules) {
53
+ if (mod.files.includes(relPath)) {
54
+ parentModuleId = mod.id;
55
+ break;
56
+ }
57
+ }
58
+ // Track functions declared in this file
59
+ const fnNames = new Set();
60
+ for (const fn of analysis.functions) {
61
+ const fnId = `fn:${relPath}:${fn.name}`;
62
+ const node = makeDefaultNode(fnId, "function", fn.name);
63
+ node.path = relPath;
64
+ node.parentId = fileId;
65
+ node.loc = fn.endLine - fn.startLine + 1;
66
+ node.complexity = fn.complexity;
67
+ // Inherit module's layer if no direct semantic info
68
+ // (Semantic data would be attached in a later enrichment pass)
69
+ functionNodes.push(node);
70
+ fnNames.add(fn.name);
71
+ functionNodeIds.add(fnId);
72
+ }
73
+ functionsByFile.set(relPath, fnNames);
74
+ // Build imported name -> source file mapping
75
+ const nameToSource = new Map();
76
+ for (const imp of analysis.imports) {
77
+ if (!imp.resolvedPath)
78
+ continue;
79
+ const targetRelPath = normalizePath(relative(rootDir, imp.resolvedPath));
80
+ for (const name of imp.names) {
81
+ nameToSource.set(name, targetRelPath);
82
+ }
83
+ }
84
+ importedNamesByFile.set(relPath, nameToSource);
85
+ }
86
+ // Pass 2: Resolve calls to edges
87
+ for (const analysis of analyses) {
88
+ const relPath = normalizePath(relative(rootDir, analysis.filePath));
89
+ const localFns = functionsByFile.get(relPath) ?? new Set();
90
+ const importedNames = importedNamesByFile.get(relPath) ?? new Map();
91
+ for (const fn of analysis.functions) {
92
+ const callerId = `fn:${relPath}:${fn.name}`;
93
+ for (const call of fn.calls) {
94
+ let calleeId = null;
95
+ // Case 1: callee is a local function in the same file
96
+ if (localFns.has(call.calleeName)) {
97
+ calleeId = `fn:${relPath}:${call.calleeName}`;
98
+ }
99
+ // Case 2: callee matches an imported name
100
+ else if (importedNames.has(call.calleeName)) {
101
+ const sourceRelPath = importedNames.get(call.calleeName);
102
+ const sourceFns = functionsByFile.get(sourceRelPath);
103
+ if (sourceFns?.has(call.calleeName)) {
104
+ calleeId = `fn:${sourceRelPath}:${call.calleeName}`;
105
+ }
106
+ }
107
+ if (!calleeId)
108
+ continue;
109
+ if (calleeId === callerId)
110
+ continue; // Skip self-calls (recursion edge not useful here)
111
+ if (!functionNodeIds.has(calleeId))
112
+ continue; // Validate target exists
113
+ const edgeKey = `${callerId}|${calleeId}`;
114
+ const existing = callEdgeMap.get(edgeKey);
115
+ if (existing) {
116
+ existing.weight += 1;
117
+ }
118
+ else {
119
+ callEdgeMap.set(edgeKey, {
120
+ sourceId: callerId,
121
+ targetId: calleeId,
122
+ kind: "calls",
123
+ weight: 1,
124
+ });
125
+ }
126
+ }
127
+ }
128
+ }
129
+ const callEdges = Array.from(callEdgeMap.values());
130
+ logger.debug(`Call graph: ${functionNodes.length} function nodes, ${callEdges.length} call edges`);
131
+ return { functionNodes, callEdges };
132
+ }
133
+ //# sourceMappingURL=call-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-graph.js","sourceRoot":"","sources":["../../src/analysis/call-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,SAAS,aAAa,CAAC,CAAS;IAC9B,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC;AAOD,SAAS,eAAe,CAAC,EAAU,EAAE,IAAuB,EAAE,IAAY;IACxE,OAAO;QACL,EAAE;QACF,IAAI;QACJ,IAAI;QACJ,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,IAAI;QACd,GAAG,EAAE,CAAC;QACN,UAAU,EAAE,CAAC;QACb,WAAW,EAAE,EAAE;QACf,SAAS,EAAE,IAAI;QACf,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,CAAC;QACf,SAAS,EAAE,CAAC;QACZ,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,CAAC;QACb,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,IAAI;QACjB,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,EAAE;QACR,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;QAC9B,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;KAC9C,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,QAAwB,EACxB,OAAqB,EACrB,OAAe;IAEf,MAAM,aAAa,GAAgB,EAAE,CAAC;IACtC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAqB,CAAC;IAEjD,sBAAsB;IACtB,6BAA6B;IAC7B,MAAM,eAAe,GAAG,IAAI,GAAG,EAAuB,CAAC;IACvD,8CAA8C;IAC9C,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAA+B,CAAC;IACnE,8CAA8C;IAC9C,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;IAE1C,sDAAsD;IACtD,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,QAAQ,OAAO,EAAE,CAAC;QAEjC,kCAAkC;QAClC,IAAI,cAAc,GAAkB,IAAI,CAAC;QACzC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAChC,cAAc,GAAG,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM;YACR,CAAC;QACH,CAAC;QAED,wCAAwC;QACxC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAElC,KAAK,MAAM,EAAE,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,MAAM,OAAO,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;YACxD,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC;YACpB,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC;YACvB,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC,OAAO,GAAG,EAAE,CAAC,SAAS,GAAG,CAAC,CAAC;YACzC,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC;YAEhC,oDAAoD;YACpD,+DAA+D;YAE/D,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YACrB,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAED,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAEtC,6CAA6C;QAC7C,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC/C,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACnC,IAAI,CAAC,GAAG,CAAC,YAAY;gBAAE,SAAS;YAChC,MAAM,aAAa,GAAG,aAAa,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;YACzE,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBAC7B,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;QACD,mBAAmB,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACjD,CAAC;IAED,iCAAiC;IACjC,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QACpE,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,GAAG,EAAU,CAAC;QACnE,MAAM,aAAa,GAAG,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,GAAG,EAAkB,CAAC;QAEpF,KAAK,MAAM,EAAE,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAG,MAAM,OAAO,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YAE5C,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;gBAC5B,IAAI,QAAQ,GAAkB,IAAI,CAAC;gBAEnC,sDAAsD;gBACtD,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;oBAClC,QAAQ,GAAG,MAAM,OAAO,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChD,CAAC;gBACD,0CAA0C;qBACrC,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC5C,MAAM,aAAa,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAE,CAAC;oBAC1D,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;oBACrD,IAAI,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;wBACpC,QAAQ,GAAG,MAAM,aAAa,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;oBACtD,CAAC;gBACH,CAAC;gBAED,IAAI,CAAC,QAAQ;oBAAE,SAAS;gBACxB,IAAI,QAAQ,KAAK,QAAQ;oBAAE,SAAS,CAAC,mDAAmD;gBACxF,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAAE,SAAS,CAAC,yBAAyB;gBAEvE,MAAM,OAAO,GAAG,GAAG,QAAQ,IAAI,QAAQ,EAAE,CAAC;gBAC1C,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC1C,IAAI,QAAQ,EAAE,CAAC;oBACb,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;gBACvB,CAAC;qBAAM,CAAC;oBACN,WAAW,CAAC,GAAG,CAAC,OAAO,EAAE;wBACvB,QAAQ,EAAE,QAAQ;wBAClB,QAAQ,EAAE,QAAQ;wBAClB,IAAI,EAAE,OAAO;wBACb,MAAM,EAAE,CAAC;qBACV,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;IAEnD,MAAM,CAAC,KAAK,CACV,eAAe,aAAa,CAAC,MAAM,oBAAoB,SAAS,CAAC,MAAM,aAAa,CACrF,CAAC;IAEF,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC;AACtC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { FileAnalysis, ModuleInfo, GraphEdge } from "../types/index.js";
2
+ export interface DependencyGraphResult {
3
+ fileEdges: GraphEdge[];
4
+ moduleEdges: GraphEdge[];
5
+ circularDeps: string[][];
6
+ }
7
+ export declare function buildDependencyGraph(analyses: FileAnalysis[], modules: ModuleInfo[], rootDir: string): DependencyGraphResult;
8
+ //# sourceMappingURL=dependency-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-graph.d.ts","sourceRoot":"","sources":["../../src/analysis/dependency-graph.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAiB7E,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,WAAW,EAAE,SAAS,EAAE,CAAC;IACzB,YAAY,EAAE,MAAM,EAAE,EAAE,CAAC;CAC1B;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,EAAE,UAAU,EAAE,EACrB,OAAO,EAAE,MAAM,GACd,qBAAqB,CAwDvB"}
@@ -0,0 +1,101 @@
1
+ import { relative } from "node:path";
2
+ import { logger } from "../logger.js";
3
+ function normalizePath(p) {
4
+ return p.replace(/\\/g, "/");
5
+ }
6
+ function fileToModule(filePath, modules) {
7
+ const relPath = normalizePath(filePath);
8
+ for (const mod of modules) {
9
+ if (mod.files.includes(relPath)) {
10
+ return mod.id;
11
+ }
12
+ }
13
+ return null;
14
+ }
15
+ export function buildDependencyGraph(analyses, modules, rootDir) {
16
+ const fileEdges = [];
17
+ const moduleEdgeMap = new Map();
18
+ // Build file-to-file edges from resolved imports
19
+ for (const analysis of analyses) {
20
+ const sourceRelPath = normalizePath(relative(rootDir, analysis.filePath));
21
+ const sourceFileId = `file:${sourceRelPath}`;
22
+ for (const imp of analysis.imports) {
23
+ if (!imp.resolvedPath)
24
+ continue;
25
+ if (imp.isTypeOnly)
26
+ continue; // Skip type-only imports for dependency edges
27
+ const targetRelPath = normalizePath(relative(rootDir, imp.resolvedPath));
28
+ const targetFileId = `file:${targetRelPath}`;
29
+ if (sourceFileId === targetFileId)
30
+ continue;
31
+ fileEdges.push({
32
+ sourceId: sourceFileId,
33
+ targetId: targetFileId,
34
+ kind: "imports",
35
+ weight: imp.names.length || 1,
36
+ });
37
+ // Aggregate to module-level edges
38
+ const sourceModule = fileToModule(sourceRelPath, modules);
39
+ const targetModule = fileToModule(targetRelPath, modules);
40
+ if (sourceModule && targetModule && sourceModule !== targetModule) {
41
+ const edgeKey = `${sourceModule}→${targetModule}`;
42
+ moduleEdgeMap.set(edgeKey, (moduleEdgeMap.get(edgeKey) ?? 0) + 1);
43
+ }
44
+ }
45
+ }
46
+ // Convert module edge map to GraphEdge[]
47
+ const moduleEdges = [];
48
+ for (const [key, weight] of moduleEdgeMap) {
49
+ const [sourceId, targetId] = key.split("→");
50
+ moduleEdges.push({
51
+ sourceId,
52
+ targetId,
53
+ kind: "imports",
54
+ weight,
55
+ });
56
+ }
57
+ // Detect circular dependencies at module level
58
+ const circularDeps = detectCycles(moduleEdges);
59
+ if (circularDeps.length > 0) {
60
+ logger.warn(`Circular dependencies detected: ${circularDeps.map((c) => c.join(" → ")).join("; ")}`);
61
+ }
62
+ logger.debug(`Dependency graph: ${fileEdges.length} file edges, ${moduleEdges.length} module edges`);
63
+ return { fileEdges, moduleEdges, circularDeps };
64
+ }
65
+ function detectCycles(edges) {
66
+ const adj = new Map();
67
+ for (const edge of edges) {
68
+ const neighbors = adj.get(edge.sourceId) ?? [];
69
+ neighbors.push(edge.targetId);
70
+ adj.set(edge.sourceId, neighbors);
71
+ }
72
+ const cycles = [];
73
+ const visited = new Set();
74
+ const inStack = new Set();
75
+ const path = [];
76
+ function dfs(node) {
77
+ if (inStack.has(node)) {
78
+ // Found a cycle
79
+ const cycleStart = path.indexOf(node);
80
+ if (cycleStart !== -1) {
81
+ cycles.push([...path.slice(cycleStart), node]);
82
+ }
83
+ return;
84
+ }
85
+ if (visited.has(node))
86
+ return;
87
+ visited.add(node);
88
+ inStack.add(node);
89
+ path.push(node);
90
+ for (const neighbor of adj.get(node) ?? []) {
91
+ dfs(neighbor);
92
+ }
93
+ path.pop();
94
+ inStack.delete(node);
95
+ }
96
+ for (const node of adj.keys()) {
97
+ dfs(node);
98
+ }
99
+ return cycles;
100
+ }
101
+ //# sourceMappingURL=dependency-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-graph.js","sourceRoot":"","sources":["../../src/analysis/dependency-graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { ModuleInfo, EvolutionSnapshot } from "../../types/index.js";
2
+ import { type ChurnData } from "./churn.js";
3
+ import { type BusFactorData } from "./bus-factor.js";
4
+ import { type ContributorInfo } from "./contributors.js";
5
+ export interface GitArchaeologyResult {
6
+ churnMap: Map<string, ChurnData>;
7
+ busFactorMap: Map<string, BusFactorData>;
8
+ contributors: ContributorInfo[];
9
+ evolution: EvolutionSnapshot[];
10
+ }
11
+ /**
12
+ * Run all git archaeology analyses on a repository.
13
+ *
14
+ * Orchestrates churn computation, bus factor analysis, contributor
15
+ * extraction, and evolution timeline building. Each sub-module handles
16
+ * its own errors gracefully — partial results are returned if some
17
+ * analyses fail.
18
+ */
19
+ export declare function analyzeGitHistory(gitDir: string, filePaths: string[], modules: ModuleInfo[]): Promise<GitArchaeologyResult>;
20
+ //# sourceMappingURL=archaeology.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archaeology.d.ts","sourceRoot":"","sources":["../../../src/analysis/git/archaeology.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAG1E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACjC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACzC,YAAY,EAAE,eAAe,EAAE,CAAC;IAChC,SAAS,EAAE,iBAAiB,EAAE,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,EAAE,UAAU,EAAE,GACpB,OAAO,CAAC,oBAAoB,CAAC,CA+B/B"}
@@ -0,0 +1,61 @@
1
+ import { logger } from "../../logger.js";
2
+ import { computeChurn } from "./churn.js";
3
+ import { computeBusFactors } from "./bus-factor.js";
4
+ import { getContributors } from "./contributors.js";
5
+ import { buildEvolutionTimeline } from "./evolution.js";
6
+ /**
7
+ * Run all git archaeology analyses on a repository.
8
+ *
9
+ * Orchestrates churn computation, bus factor analysis, contributor
10
+ * extraction, and evolution timeline building. Each sub-module handles
11
+ * its own errors gracefully — partial results are returned if some
12
+ * analyses fail.
13
+ */
14
+ export async function analyzeGitHistory(gitDir, filePaths, modules) {
15
+ logger.info(`Git archaeology: analyzing ${filePaths.length} files in ${modules.length} modules`);
16
+ // Run churn and contributors in parallel (they don't depend on each other)
17
+ const [churnMap, contributors] = await Promise.all([
18
+ safeRunMap("churn", () => computeChurn(gitDir, filePaths)),
19
+ safeRunArray("contributors", () => getContributors(gitDir)),
20
+ ]);
21
+ // Bus factor depends on modules
22
+ const busFactorMap = await safeRunMap("bus-factor", () => computeBusFactors(gitDir, modules));
23
+ // Evolution timeline
24
+ const evolution = await safeRunArray("evolution", () => buildEvolutionTimeline(gitDir, filePaths));
25
+ logger.info(`Git archaeology complete: ${churnMap.size} churn entries, ` +
26
+ `${busFactorMap.size} bus factors, ${contributors.length} contributors, ` +
27
+ `${evolution.length} evolution snapshots`);
28
+ return {
29
+ churnMap,
30
+ busFactorMap,
31
+ contributors,
32
+ evolution,
33
+ };
34
+ }
35
+ /**
36
+ * Run an async function that returns a Map, with error handling.
37
+ * Returns an empty Map on failure.
38
+ */
39
+ async function safeRunMap(name, fn) {
40
+ try {
41
+ return await fn();
42
+ }
43
+ catch (err) {
44
+ logger.warn(`Git archaeology: ${name} failed — ${err instanceof Error ? err.message : err}`);
45
+ return new Map();
46
+ }
47
+ }
48
+ /**
49
+ * Run an async function that returns an array, with error handling.
50
+ * Returns an empty array on failure.
51
+ */
52
+ async function safeRunArray(name, fn) {
53
+ try {
54
+ return await fn();
55
+ }
56
+ catch (err) {
57
+ logger.warn(`Git archaeology: ${name} failed — ${err instanceof Error ? err.message : err}`);
58
+ return [];
59
+ }
60
+ }
61
+ //# sourceMappingURL=archaeology.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archaeology.js","sourceRoot":"","sources":["../../../src/analysis/git/archaeology.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAkB,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAsB,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,eAAe,EAAwB,MAAM,mBAAmB,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AASxD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAc,EACd,SAAmB,EACnB,OAAqB;IAErB,MAAM,CAAC,IAAI,CAAC,8BAA8B,SAAS,CAAC,MAAM,aAAa,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;IAEjG,2EAA2E;IAC3E,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACjD,UAAU,CAAoB,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAC7E,YAAY,CAAkB,cAAc,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;KAC7E,CAAC,CAAC;IAEH,gCAAgC;IAChC,MAAM,YAAY,GAAG,MAAM,UAAU,CAAwB,YAAY,EAAE,GAAG,EAAE,CAC9E,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CACnC,CAAC;IAEF,qBAAqB;IACrB,MAAM,SAAS,GAAG,MAAM,YAAY,CAAoB,WAAW,EAAE,GAAG,EAAE,CACxE,sBAAsB,CAAC,MAAM,EAAE,SAAS,CAAC,CAC1C,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,6BAA6B,QAAQ,CAAC,IAAI,kBAAkB;QAC5D,GAAG,YAAY,CAAC,IAAI,iBAAiB,YAAY,CAAC,MAAM,iBAAiB;QACzE,GAAG,SAAS,CAAC,MAAM,sBAAsB,CAC1C,CAAC;IAEF,OAAO;QACL,QAAQ;QACR,YAAY;QACZ,YAAY;QACZ,SAAS;KACV,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,UAAU,CACvB,IAAY,EACZ,EAA4B;IAE5B,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CACT,oBAAoB,IAAI,aAAa,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAChF,CAAC;QACF,OAAO,IAAI,GAAG,EAAQ,CAAC;IACzB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,YAAY,CACzB,IAAY,EACZ,EAAsB;IAEtB,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CACT,oBAAoB,IAAI,aAAa,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAChF,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { ModuleInfo } from "../../types/index.js";
2
+ export interface BusFactorData {
3
+ busFactor: number;
4
+ primaryOwner: string;
5
+ ownershipShare: number;
6
+ }
7
+ /**
8
+ * Compute the bus factor for each module.
9
+ *
10
+ * Since isomorphic-git has no blame command, we approximate:
11
+ * for each commit that touches files in a module, attribute all changes
12
+ * to the commit author. Then count author commits as a proxy for contribution.
13
+ *
14
+ * Bus factor = minimum N such that sum(top N knowledge shares) > 0.70
15
+ */
16
+ export declare function computeBusFactors(gitDir: string, modules: ModuleInfo[]): Promise<Map<string, BusFactorData>>;
17
+ //# sourceMappingURL=bus-factor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bus-factor.d.ts","sourceRoot":"","sources":["../../../src/analysis/git/bus-factor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,UAAU,EAAE,GACpB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAyFrC"}
@@ -0,0 +1,90 @@
1
+ import fs from "node:fs";
2
+ import git from "isomorphic-git";
3
+ import { logger } from "../../logger.js";
4
+ /**
5
+ * Compute the bus factor for each module.
6
+ *
7
+ * Since isomorphic-git has no blame command, we approximate:
8
+ * for each commit that touches files in a module, attribute all changes
9
+ * to the commit author. Then count author commits as a proxy for contribution.
10
+ *
11
+ * Bus factor = minimum N such that sum(top N knowledge shares) > 0.70
12
+ */
13
+ export async function computeBusFactors(gitDir, modules) {
14
+ const result = new Map();
15
+ // First, get full log (limited for perf)
16
+ let allCommits;
17
+ try {
18
+ const logs = await git.log({ fs, dir: gitDir, depth: 500 });
19
+ allCommits = logs.map((entry) => ({
20
+ oid: entry.oid,
21
+ author: entry.commit.author.name,
22
+ timestamp: entry.commit.author.timestamp,
23
+ }));
24
+ }
25
+ catch (err) {
26
+ logger.warn(`Bus factor: failed to read git log — ${err instanceof Error ? err.message : err}`);
27
+ // Return default bus factor for all modules
28
+ for (const mod of modules) {
29
+ result.set(mod.id, { busFactor: 0, primaryOwner: "unknown", ownershipShare: 0 });
30
+ }
31
+ return result;
32
+ }
33
+ // For each module, gather commits that touch its files
34
+ for (const mod of modules) {
35
+ try {
36
+ const authorCommitCounts = new Map();
37
+ let totalModuleCommits = 0;
38
+ // Get commits for each file in the module
39
+ for (const filePath of mod.files) {
40
+ try {
41
+ const fileCommits = await git.log({
42
+ fs,
43
+ dir: gitDir,
44
+ filepath: filePath,
45
+ depth: 500,
46
+ });
47
+ for (const entry of fileCommits) {
48
+ const author = entry.commit.author.name;
49
+ authorCommitCounts.set(author, (authorCommitCounts.get(author) ?? 0) + 1);
50
+ totalModuleCommits++;
51
+ }
52
+ }
53
+ catch {
54
+ // File may not exist in git (untracked); skip silently
55
+ }
56
+ }
57
+ if (totalModuleCommits === 0 || authorCommitCounts.size === 0) {
58
+ result.set(mod.id, { busFactor: 0, primaryOwner: "unknown", ownershipShare: 0 });
59
+ continue;
60
+ }
61
+ // Sort authors by their share (descending)
62
+ const shares = [];
63
+ for (const [author, count] of authorCommitCounts) {
64
+ shares.push({ author, share: count / totalModuleCommits });
65
+ }
66
+ shares.sort((a, b) => b.share - a.share);
67
+ // Bus factor = min N where sum(top N shares) > 0.70
68
+ let cumulative = 0;
69
+ let busFactor = 0;
70
+ for (const entry of shares) {
71
+ cumulative += entry.share;
72
+ busFactor++;
73
+ if (cumulative > 0.70)
74
+ break;
75
+ }
76
+ const primary = shares[0];
77
+ result.set(mod.id, {
78
+ busFactor,
79
+ primaryOwner: primary.author,
80
+ ownershipShare: primary.share,
81
+ });
82
+ }
83
+ catch (err) {
84
+ logger.debug(`Bus factor: error for module ${mod.id} — ${err instanceof Error ? err.message : err}`);
85
+ result.set(mod.id, { busFactor: 0, primaryOwner: "unknown", ownershipShare: 0 });
86
+ }
87
+ }
88
+ return result;
89
+ }
90
+ //# sourceMappingURL=bus-factor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bus-factor.js","sourceRoot":"","sources":["../../../src/analysis/git/bus-factor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export interface ChurnData {
2
+ distinctAuthors: number;
3
+ totalCommits: number;
4
+ commitsLast90d: number;
5
+ linesChangedLast90d: number;
6
+ churnScore: number;
7
+ createdAt: string | null;
8
+ lastModified: string | null;
9
+ primaryAuthor: string | null;
10
+ }
11
+ /**
12
+ * Compute churn data for all files in the repository.
13
+ *
14
+ * Uses isomorphic-git.log() with filepath to get per-file commit history.
15
+ * Lines changed is approximated using commit count as a proxy (actual line
16
+ * diffs are expensive with isomorphic-git).
17
+ *
18
+ * Formula:
19
+ * rawChurn = (distinctAuthors/maxAuthors * 0.3)
20
+ * + (commitsLast90d/max(totalCommits,1) * 0.3)
21
+ * + (commitsLast90d/max(totalCommits,1) * 0.4) // simplified proxy
22
+ *
23
+ * Result is then normalized across all files to 0-1 range.
24
+ */
25
+ export declare function computeChurn(gitDir: string, filePaths: string[]): Promise<Map<string, ChurnData>>;
26
+ //# sourceMappingURL=churn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"churn.d.ts","sourceRoot":"","sources":["../../../src/analysis/git/churn.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAQD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAmEjC"}