kiri-mcp-server 0.13.0 → 0.16.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 (61) hide show
  1. package/README.md +13 -17
  2. package/config/scoring-profiles.yml +78 -0
  3. package/config/stop-words.yml +307 -0
  4. package/dist/config/scoring-profiles.yml +78 -0
  5. package/dist/config/stop-words.yml +307 -0
  6. package/dist/package.json +2 -2
  7. package/dist/src/indexer/cli.d.ts +1 -0
  8. package/dist/src/indexer/cli.d.ts.map +1 -1
  9. package/dist/src/indexer/cli.js +22 -2
  10. package/dist/src/indexer/cli.js.map +1 -1
  11. package/dist/src/indexer/cochange.d.ts +97 -0
  12. package/dist/src/indexer/cochange.d.ts.map +1 -0
  13. package/dist/src/indexer/cochange.js +315 -0
  14. package/dist/src/indexer/cochange.js.map +1 -0
  15. package/dist/src/indexer/graph-metrics.d.ts +68 -0
  16. package/dist/src/indexer/graph-metrics.d.ts.map +1 -0
  17. package/dist/src/indexer/graph-metrics.js +239 -0
  18. package/dist/src/indexer/graph-metrics.js.map +1 -0
  19. package/dist/src/indexer/schema.d.ts +15 -0
  20. package/dist/src/indexer/schema.d.ts.map +1 -1
  21. package/dist/src/indexer/schema.js +86 -0
  22. package/dist/src/indexer/schema.js.map +1 -1
  23. package/dist/src/server/config.d.ts.map +1 -1
  24. package/dist/src/server/config.js +22 -16
  25. package/dist/src/server/config.js.map +1 -1
  26. package/dist/src/server/handlers/snippets-get.d.ts +10 -0
  27. package/dist/src/server/handlers/snippets-get.d.ts.map +1 -1
  28. package/dist/src/server/handlers/snippets-get.js +40 -3
  29. package/dist/src/server/handlers/snippets-get.js.map +1 -1
  30. package/dist/src/server/handlers.d.ts +1 -1
  31. package/dist/src/server/handlers.d.ts.map +1 -1
  32. package/dist/src/server/handlers.js +195 -51
  33. package/dist/src/server/handlers.js.map +1 -1
  34. package/dist/src/server/idf-provider.d.ts +110 -0
  35. package/dist/src/server/idf-provider.d.ts.map +1 -0
  36. package/dist/src/server/idf-provider.js +233 -0
  37. package/dist/src/server/idf-provider.js.map +1 -0
  38. package/dist/src/server/rpc.d.ts.map +1 -1
  39. package/dist/src/server/rpc.js +43 -4
  40. package/dist/src/server/rpc.js.map +1 -1
  41. package/dist/src/server/scoring.d.ts +10 -0
  42. package/dist/src/server/scoring.d.ts.map +1 -1
  43. package/dist/src/server/scoring.js +73 -0
  44. package/dist/src/server/scoring.js.map +1 -1
  45. package/dist/src/server/services/index.d.ts +2 -0
  46. package/dist/src/server/services/index.d.ts.map +1 -1
  47. package/dist/src/server/services/index.js +3 -0
  48. package/dist/src/server/services/index.js.map +1 -1
  49. package/dist/src/server/stop-words.d.ts +106 -0
  50. package/dist/src/server/stop-words.d.ts.map +1 -0
  51. package/dist/src/server/stop-words.js +312 -0
  52. package/dist/src/server/stop-words.js.map +1 -0
  53. package/dist/src/shared/adaptive-k-categories.d.ts +5 -0
  54. package/dist/src/shared/adaptive-k-categories.d.ts.map +1 -0
  55. package/dist/src/shared/adaptive-k-categories.js +17 -0
  56. package/dist/src/shared/adaptive-k-categories.js.map +1 -0
  57. package/dist/src/shared/duckdb.d.ts +8 -2
  58. package/dist/src/shared/duckdb.d.ts.map +1 -1
  59. package/dist/src/shared/duckdb.js +37 -62
  60. package/dist/src/shared/duckdb.js.map +1 -1
  61. package/package.json +2 -2
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Co-change Graph Extraction (Phase 4: Graph Layer)
3
+ *
4
+ * This module extracts co-change relationships from git commit history.
5
+ * Files that frequently change together in commits have higher co-change scores.
6
+ *
7
+ * Invariants (from Alloy/TLA+ specs):
8
+ * - CC1: Canonical ordering (file1 < file2 lexicographically)
9
+ * - CC2: Both files exist in the file table
10
+ * - CC3: Positive weight (cochange_count > 0)
11
+ * - CC4: Idempotent commit processing
12
+ *
13
+ * Metrics computed:
14
+ * - cochange_count: Number of commits where both files changed together
15
+ * - confidence: Jaccard similarity = |A ∩ B| / |A ∪ B|
16
+ */
17
+ import type { DuckDBClient } from "../shared/duckdb.js";
18
+ /**
19
+ * Configuration for co-change extraction
20
+ */
21
+ export interface CochangeConfig {
22
+ /** Maximum number of commits to analyze (default: 1000) */
23
+ maxCommits: number;
24
+ /** Minimum co-change count to persist (default: 2) */
25
+ minCochangeCount: number;
26
+ /** Maximum files per commit to avoid mega-commits (default: 50) */
27
+ maxFilesPerCommit: number;
28
+ /** Only consider commits within this many days (default: 365) */
29
+ maxAgeDays: number;
30
+ }
31
+ /**
32
+ * Parsed commit from git log
33
+ */
34
+ interface GitCommit {
35
+ hash: string;
36
+ files: string[];
37
+ timestamp: Date;
38
+ }
39
+ /**
40
+ * Create canonical pair ensuring file1 < file2 (CC1)
41
+ * Uses lexicographic comparison for deterministic ordering.
42
+ */
43
+ export declare function canonicalPair(file1: string, file2: string): [string, string];
44
+ /**
45
+ * Generate all unique pairs from a set of files.
46
+ * Returns pairs in canonical order (file1 < file2).
47
+ */
48
+ export declare function generatePairs(files: string[]): [string, string][];
49
+ /**
50
+ * Extract commits from git log.
51
+ * Returns commits with their changed files.
52
+ */
53
+ export declare function extractCommitsFromGit(repoPath: string, config: CochangeConfig): GitCommit[];
54
+ /**
55
+ * Compute co-change graph from git history.
56
+ * Main entry point for co-change extraction.
57
+ *
58
+ * @param db - DuckDB client
59
+ * @param repoId - Repository ID
60
+ * @param repoPath - Path to git repository
61
+ * @param config - Optional configuration
62
+ */
63
+ export declare function computeCochangeGraph(db: DuckDBClient, repoId: number, repoPath: string, config?: Partial<CochangeConfig>): Promise<{
64
+ processedCommits: number;
65
+ edges: number;
66
+ prunedEdges: number;
67
+ }>;
68
+ /**
69
+ * Incremental co-change update for new commits.
70
+ * Called during watch mode or incremental indexing.
71
+ *
72
+ * @param db - DuckDB client
73
+ * @param repoId - Repository ID
74
+ * @param repoPath - Path to git repository
75
+ * @param sinceCommit - Only process commits after this one
76
+ */
77
+ export declare function incrementalCochangeUpdate(db: DuckDBClient, repoId: number, repoPath: string, sinceCommit?: string): Promise<{
78
+ processedCommits: number;
79
+ }>;
80
+ /**
81
+ * Remove co-change edges involving a deleted file.
82
+ * Called when files are removed from the index.
83
+ *
84
+ * Maintains CC2 invariant (both files exist).
85
+ */
86
+ export declare function removeFileCochange(db: DuckDBClient, repoId: number, filePath: string): Promise<number>;
87
+ /**
88
+ * Get co-change neighbors for a file.
89
+ * Returns files that frequently change together with the target file.
90
+ */
91
+ export declare function getCochangeNeighbors(db: DuckDBClient, repoId: number, filePath: string, limit?: number): Promise<{
92
+ path: string;
93
+ count: number;
94
+ confidence: number;
95
+ }[]>;
96
+ export {};
97
+ //# sourceMappingURL=cochange.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cochange.d.ts","sourceRoot":"","sources":["../../../src/indexer/cochange.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,gBAAgB,EAAE,MAAM,CAAC;IACzB,mEAAmE;IACnE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;CACpB;AASD;;GAEG;AACH,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAE5E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAejE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,SAAS,EAAE,CA2D3F;AA8ID;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,YAAY,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,OAAO,CAAC,cAAc,CAAM,GACnC,OAAO,CAAC;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CA4D3E;AAED;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,YAAY,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC;IAAE,gBAAgB,EAAE,MAAM,CAAA;CAAE,CAAC,CA+CvC;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,YAAY,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,YAAY,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,SAAK,GACT,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAehE"}
@@ -0,0 +1,315 @@
1
+ /**
2
+ * Co-change Graph Extraction (Phase 4: Graph Layer)
3
+ *
4
+ * This module extracts co-change relationships from git commit history.
5
+ * Files that frequently change together in commits have higher co-change scores.
6
+ *
7
+ * Invariants (from Alloy/TLA+ specs):
8
+ * - CC1: Canonical ordering (file1 < file2 lexicographically)
9
+ * - CC2: Both files exist in the file table
10
+ * - CC3: Positive weight (cochange_count > 0)
11
+ * - CC4: Idempotent commit processing
12
+ *
13
+ * Metrics computed:
14
+ * - cochange_count: Number of commits where both files changed together
15
+ * - confidence: Jaccard similarity = |A ∩ B| / |A ∪ B|
16
+ */
17
+ import { execSync } from "node:child_process";
18
+ const DEFAULT_CONFIG = {
19
+ maxCommits: 1000,
20
+ minCochangeCount: 2,
21
+ maxFilesPerCommit: 50,
22
+ maxAgeDays: 365,
23
+ };
24
+ /**
25
+ * Create canonical pair ensuring file1 < file2 (CC1)
26
+ * Uses lexicographic comparison for deterministic ordering.
27
+ */
28
+ export function canonicalPair(file1, file2) {
29
+ return file1 < file2 ? [file1, file2] : [file2, file1];
30
+ }
31
+ /**
32
+ * Generate all unique pairs from a set of files.
33
+ * Returns pairs in canonical order (file1 < file2).
34
+ */
35
+ export function generatePairs(files) {
36
+ const pairs = [];
37
+ const sorted = [...files].sort();
38
+ for (let i = 0; i < sorted.length; i++) {
39
+ for (let j = i + 1; j < sorted.length; j++) {
40
+ const f1 = sorted[i];
41
+ const f2 = sorted[j];
42
+ if (f1 !== undefined && f2 !== undefined) {
43
+ pairs.push([f1, f2]);
44
+ }
45
+ }
46
+ }
47
+ return pairs;
48
+ }
49
+ /**
50
+ * Extract commits from git log.
51
+ * Returns commits with their changed files.
52
+ */
53
+ export function extractCommitsFromGit(repoPath, config) {
54
+ const commits = [];
55
+ try {
56
+ // Get commit hashes with timestamps
57
+ // Format: hash|timestamp (ISO 8601)
58
+ const sinceDate = new Date();
59
+ sinceDate.setDate(sinceDate.getDate() - config.maxAgeDays);
60
+ const sinceArg = sinceDate.toISOString().split("T")[0];
61
+ const logOutput = execSync(`git log --format="%H|%aI" --since="${sinceArg}" -n ${config.maxCommits}`, {
62
+ cwd: repoPath,
63
+ encoding: "utf-8",
64
+ maxBuffer: 50 * 1024 * 1024, // 50MB buffer for large repos
65
+ });
66
+ const commitLines = logOutput.trim().split("\n").filter(Boolean);
67
+ for (const line of commitLines) {
68
+ const [hash, timestampStr] = line.split("|");
69
+ if (!hash || !timestampStr)
70
+ continue;
71
+ // Get files changed in this commit
72
+ const filesOutput = execSync(`git diff-tree --no-commit-id --name-only -r ${hash}`, {
73
+ cwd: repoPath,
74
+ encoding: "utf-8",
75
+ maxBuffer: 10 * 1024 * 1024,
76
+ });
77
+ const files = filesOutput
78
+ .trim()
79
+ .split("\n")
80
+ .filter(Boolean)
81
+ .filter((f) => !f.startsWith(".git/"));
82
+ // Skip mega-commits (likely auto-generated or initial commits)
83
+ if (files.length > config.maxFilesPerCommit) {
84
+ continue;
85
+ }
86
+ // Skip single-file commits (no pairs possible)
87
+ if (files.length < 2) {
88
+ continue;
89
+ }
90
+ commits.push({
91
+ hash,
92
+ files,
93
+ timestamp: new Date(timestampStr),
94
+ });
95
+ }
96
+ }
97
+ catch (error) {
98
+ console.warn("[Cochange] Failed to extract git history:", error);
99
+ }
100
+ return commits;
101
+ }
102
+ /**
103
+ * Check if a commit has already been processed (CC4: Idempotent)
104
+ */
105
+ async function isCommitProcessed(db, repoId, commitHash) {
106
+ const result = await db.all(`SELECT COUNT(*) as count FROM processed_commits
107
+ WHERE repo_id = ? AND commit_hash = ?`, [repoId, commitHash]);
108
+ return (result[0]?.count ?? 0) > 0;
109
+ }
110
+ /**
111
+ * Mark a commit as processed (CC4: Idempotent)
112
+ */
113
+ async function markCommitProcessed(db, repoId, commitHash) {
114
+ await db.run(`INSERT INTO processed_commits (repo_id, commit_hash, processed_at)
115
+ VALUES (?, ?, CURRENT_TIMESTAMP)
116
+ ON CONFLICT DO NOTHING`, [repoId, commitHash]);
117
+ }
118
+ /**
119
+ * Get set of indexed files for a repo (CC2: Both files exist)
120
+ */
121
+ async function getIndexedFiles(db, repoId) {
122
+ const files = await db.all(`SELECT path FROM file WHERE repo_id = ?`, [repoId]);
123
+ return new Set(files.map((f) => f.path));
124
+ }
125
+ /**
126
+ * Update co-change counts for a single commit.
127
+ * Creates pairs for all changed files and increments counts.
128
+ */
129
+ async function processCommitCochange(db, repoId, commit, indexedFiles, fileChangeCounts) {
130
+ // Filter to only indexed files (CC2)
131
+ const validFiles = commit.files.filter((f) => indexedFiles.has(f));
132
+ if (validFiles.length < 2) {
133
+ return; // Need at least 2 files for pairs
134
+ }
135
+ // Update file change counts
136
+ for (const file of validFiles) {
137
+ fileChangeCounts.set(file, (fileChangeCounts.get(file) ?? 0) + 1);
138
+ }
139
+ // Generate all pairs (CC1: canonical ordering)
140
+ const pairs = generatePairs(validFiles);
141
+ // Update co-change counts
142
+ for (const [file1, file2] of pairs) {
143
+ await db.run(`INSERT INTO cochange (repo_id, file1, file2, cochange_count, last_commit, last_cochange_at)
144
+ VALUES (?, ?, ?, 1, ?, CURRENT_TIMESTAMP)
145
+ ON CONFLICT (repo_id, file1, file2) DO UPDATE SET
146
+ cochange_count = cochange_count + 1,
147
+ last_commit = excluded.last_commit,
148
+ last_cochange_at = excluded.last_cochange_at`, [repoId, file1, file2, commit.hash]);
149
+ }
150
+ }
151
+ /**
152
+ * Calculate Jaccard confidence for all co-change edges.
153
+ * confidence = cochange_count / (changes_file1 + changes_file2 - cochange_count)
154
+ *
155
+ * This is run after all commits are processed.
156
+ */
157
+ async function updateJaccardConfidence(db, repoId, fileChangeCounts) {
158
+ // Get all co-change edges
159
+ const edges = await db.all(`SELECT file1, file2, cochange_count FROM cochange WHERE repo_id = ?`, [repoId]);
160
+ for (const edge of edges) {
161
+ const count1 = fileChangeCounts.get(edge.file1) ?? 0;
162
+ const count2 = fileChangeCounts.get(edge.file2) ?? 0;
163
+ // Jaccard = intersection / union
164
+ // intersection = cochange_count
165
+ // union = changes_file1 + changes_file2 - cochange_count
166
+ const union = count1 + count2 - edge.cochange_count;
167
+ const confidence = union > 0 ? edge.cochange_count / union : 0;
168
+ await db.run(`UPDATE cochange SET confidence = ?
169
+ WHERE repo_id = ? AND file1 = ? AND file2 = ?`, [confidence, repoId, edge.file1, edge.file2]);
170
+ }
171
+ }
172
+ /**
173
+ * Prune co-change edges below minimum threshold (CC3: Positive weight)
174
+ */
175
+ async function pruneWeakEdges(db, repoId, minCochangeCount) {
176
+ // Count rows to be deleted first
177
+ const countResult = await db.all(`SELECT COUNT(*) as count FROM cochange
178
+ WHERE repo_id = ? AND cochange_count < ?`, [repoId, minCochangeCount]);
179
+ const toDelete = countResult[0]?.count ?? 0;
180
+ // Delete the rows
181
+ await db.run(`DELETE FROM cochange
182
+ WHERE repo_id = ? AND cochange_count < ?`, [repoId, minCochangeCount]);
183
+ return toDelete;
184
+ }
185
+ /**
186
+ * Compute co-change graph from git history.
187
+ * Main entry point for co-change extraction.
188
+ *
189
+ * @param db - DuckDB client
190
+ * @param repoId - Repository ID
191
+ * @param repoPath - Path to git repository
192
+ * @param config - Optional configuration
193
+ */
194
+ export async function computeCochangeGraph(db, repoId, repoPath, config = {}) {
195
+ const cfg = { ...DEFAULT_CONFIG, ...config };
196
+ console.info(`[Cochange] Computing co-change graph for repo ${repoId}...`);
197
+ // Get indexed files (CC2)
198
+ const indexedFiles = await getIndexedFiles(db, repoId);
199
+ if (indexedFiles.size === 0) {
200
+ console.info("[Cochange] No indexed files, skipping");
201
+ return { processedCommits: 0, edges: 0, prunedEdges: 0 };
202
+ }
203
+ // Extract commits from git
204
+ const commits = extractCommitsFromGit(repoPath, cfg);
205
+ console.info(`[Cochange] Found ${commits.length} commits to analyze`);
206
+ // Track file change counts for Jaccard calculation
207
+ const fileChangeCounts = new Map();
208
+ let processedCount = 0;
209
+ // Process each commit
210
+ for (const commit of commits) {
211
+ // Check idempotency (CC4)
212
+ const alreadyProcessed = await isCommitProcessed(db, repoId, commit.hash);
213
+ if (alreadyProcessed) {
214
+ continue;
215
+ }
216
+ // Process co-change pairs
217
+ await processCommitCochange(db, repoId, commit, indexedFiles, fileChangeCounts);
218
+ // Mark as processed (CC4)
219
+ await markCommitProcessed(db, repoId, commit.hash);
220
+ processedCount++;
221
+ }
222
+ console.info(`[Cochange] Processed ${processedCount} new commits`);
223
+ // Update Jaccard confidence scores only if we processed new commits
224
+ // Skip when processedCount is 0 to avoid zeroing existing confidence values
225
+ if (processedCount > 0) {
226
+ await updateJaccardConfidence(db, repoId, fileChangeCounts);
227
+ }
228
+ // Prune weak edges (CC3)
229
+ const prunedCount = await pruneWeakEdges(db, repoId, cfg.minCochangeCount);
230
+ // Get final edge count
231
+ const edgeCount = await db.all(`SELECT COUNT(*) as count FROM cochange WHERE repo_id = ?`, [repoId]);
232
+ console.info(`[Cochange] Completed: ${edgeCount[0]?.count ?? 0} edges, ${prunedCount} pruned`);
233
+ return {
234
+ processedCommits: processedCount,
235
+ edges: edgeCount[0]?.count ?? 0,
236
+ prunedEdges: prunedCount,
237
+ };
238
+ }
239
+ /**
240
+ * Incremental co-change update for new commits.
241
+ * Called during watch mode or incremental indexing.
242
+ *
243
+ * @param db - DuckDB client
244
+ * @param repoId - Repository ID
245
+ * @param repoPath - Path to git repository
246
+ * @param sinceCommit - Only process commits after this one
247
+ */
248
+ export async function incrementalCochangeUpdate(db, repoId, repoPath, sinceCommit) {
249
+ console.info(`[Cochange] Incremental update for repo ${repoId}...`);
250
+ const indexedFiles = await getIndexedFiles(db, repoId);
251
+ const fileChangeCounts = new Map();
252
+ // Build file change counts from existing data
253
+ const existingEdges = await db.all(`SELECT DISTINCT file1, file2 FROM cochange WHERE repo_id = ?`, [repoId]);
254
+ // Note: This is a simplified approximation. Full recalc would be more accurate.
255
+ for (const edge of existingEdges) {
256
+ fileChangeCounts.set(edge.file1, (fileChangeCounts.get(edge.file1) ?? 0) + 1);
257
+ fileChangeCounts.set(edge.file2, (fileChangeCounts.get(edge.file2) ?? 0) + 1);
258
+ }
259
+ // Extract recent commits
260
+ const cfg = { ...DEFAULT_CONFIG, maxCommits: 100, maxAgeDays: 30 };
261
+ const commits = extractCommitsFromGit(repoPath, cfg);
262
+ let processedCount = 0;
263
+ for (const commit of commits) {
264
+ // Skip if already processed
265
+ if (await isCommitProcessed(db, repoId, commit.hash)) {
266
+ continue;
267
+ }
268
+ // Skip if before sinceCommit (optimization)
269
+ if (sinceCommit && commit.hash === sinceCommit) {
270
+ break;
271
+ }
272
+ await processCommitCochange(db, repoId, commit, indexedFiles, fileChangeCounts);
273
+ await markCommitProcessed(db, repoId, commit.hash);
274
+ processedCount++;
275
+ }
276
+ // Update confidence scores
277
+ if (processedCount > 0) {
278
+ await updateJaccardConfidence(db, repoId, fileChangeCounts);
279
+ }
280
+ console.info(`[Cochange] Incremental update: ${processedCount} commits`);
281
+ return { processedCommits: processedCount };
282
+ }
283
+ /**
284
+ * Remove co-change edges involving a deleted file.
285
+ * Called when files are removed from the index.
286
+ *
287
+ * Maintains CC2 invariant (both files exist).
288
+ */
289
+ export async function removeFileCochange(db, repoId, filePath) {
290
+ // Count rows to be deleted first
291
+ const countResult = await db.all(`SELECT COUNT(*) as count FROM cochange
292
+ WHERE repo_id = ? AND (file1 = ? OR file2 = ?)`, [repoId, filePath, filePath]);
293
+ const toDelete = countResult[0]?.count ?? 0;
294
+ // Delete the rows
295
+ await db.run(`DELETE FROM cochange
296
+ WHERE repo_id = ? AND (file1 = ? OR file2 = ?)`, [repoId, filePath, filePath]);
297
+ return toDelete;
298
+ }
299
+ /**
300
+ * Get co-change neighbors for a file.
301
+ * Returns files that frequently change together with the target file.
302
+ */
303
+ export async function getCochangeNeighbors(db, repoId, filePath, limit = 10) {
304
+ // Query both directions (file can be in file1 or file2)
305
+ const results = await db.all(`SELECT
306
+ CASE WHEN file1 = ? THEN file2 ELSE file1 END as path,
307
+ cochange_count as count,
308
+ confidence
309
+ FROM cochange
310
+ WHERE repo_id = ? AND (file1 = ? OR file2 = ?)
311
+ ORDER BY cochange_count DESC, confidence DESC
312
+ LIMIT ?`, [filePath, repoId, filePath, filePath, limit]);
313
+ return results;
314
+ }
315
+ //# sourceMappingURL=cochange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cochange.js","sourceRoot":"","sources":["../../../src/indexer/cochange.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Graph Metrics Computation (Phase 3.2: Graph Layer)
3
+ *
4
+ * This module computes graph centrality metrics from the dependency table
5
+ * and stores them in precomputed tables for fast query-time lookup.
6
+ *
7
+ * Invariants (from Alloy spec):
8
+ * - DG1: All path edges reference indexed files
9
+ * - DG2: No self-loops
10
+ * - DG4: Closure symmetry (outbound/inbound consistency)
11
+ *
12
+ * Metrics computed:
13
+ * - Degree centrality (inbound/outbound counts)
14
+ * - Importance score (PageRank-like)
15
+ * - Inbound closure (BFS up to depth 3)
16
+ */
17
+ import type { DuckDBClient } from "../shared/duckdb.js";
18
+ /**
19
+ * Configuration for graph metrics computation
20
+ */
21
+ export interface GraphMetricsConfig {
22
+ /** Maximum BFS depth for inbound closure (default: 3) */
23
+ maxDepth: number;
24
+ /** PageRank damping factor (default: 0.85) */
25
+ dampingFactor: number;
26
+ /** Number of PageRank iterations (default: 10) */
27
+ iterations: number;
28
+ }
29
+ /**
30
+ * Compute all graph metrics for a repository.
31
+ * Called after dependency extraction during indexing.
32
+ *
33
+ * @param db - DuckDB client
34
+ * @param repoId - Repository ID
35
+ * @param config - Optional configuration
36
+ */
37
+ export declare function computeGraphMetrics(db: DuckDBClient, repoId: number, config?: Partial<GraphMetricsConfig>): Promise<void>;
38
+ /**
39
+ * Compute degree centrality (inbound and outbound counts).
40
+ *
41
+ * Uses SQL aggregation for efficiency.
42
+ */
43
+ export declare function computeDegreeCentrality(db: DuckDBClient, repoId: number): Promise<void>;
44
+ /**
45
+ * Precompute inbound closure using BFS up to maxDepth.
46
+ *
47
+ * Uses recursive CTE for efficient computation.
48
+ */
49
+ export declare function precomputeInboundClosure(db: DuckDBClient, repoId: number, maxDepth: number): Promise<void>;
50
+ /**
51
+ * Compute importance scores using PageRank-like algorithm.
52
+ *
53
+ * This is a simplified PageRank that:
54
+ * - Uses inbound edges for importance propagation
55
+ * - Runs for a fixed number of iterations
56
+ * - Normalizes scores to [0, 1]
57
+ */
58
+ export declare function computeImportanceScores(db: DuckDBClient, repoId: number, dampingFactor: number, iterations: number): Promise<void>;
59
+ /**
60
+ * Incrementally update graph metrics for changed files.
61
+ * Used during incremental indexing to avoid full recomputation.
62
+ *
63
+ * @param db - DuckDB client
64
+ * @param repoId - Repository ID
65
+ * @param changedPaths - Paths that were added, modified, or removed
66
+ */
67
+ export declare function incrementalGraphUpdate(db: DuckDBClient, repoId: number, changedPaths: string[]): Promise<void>;
68
+ //# sourceMappingURL=graph-metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-metrics.d.ts","sourceRoot":"","sources":["../../../src/indexer/graph-metrics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,aAAa,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;CACpB;AAWD;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,YAAY,EAChB,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,OAAO,CAAC,kBAAkB,CAAM,GACvC,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0D7F;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,YAAY,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAyCf;AAED;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,YAAY,EAChB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAgFf;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,YAAY,EAChB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,IAAI,CAAC,CAyCf"}