@theihtisham/agent-shadow-brain 2.1.0 → 3.0.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 (56) hide show
  1. package/dist/brain/accessibility-checker.d.ts +10 -0
  2. package/dist/brain/accessibility-checker.d.ts.map +1 -0
  3. package/dist/brain/accessibility-checker.js +379 -0
  4. package/dist/brain/accessibility-checker.js.map +1 -0
  5. package/dist/brain/api-contract-analyzer.d.ts +19 -0
  6. package/dist/brain/api-contract-analyzer.d.ts.map +1 -0
  7. package/dist/brain/api-contract-analyzer.js +251 -0
  8. package/dist/brain/api-contract-analyzer.js.map +1 -0
  9. package/dist/brain/ast-analyzer.d.ts +23 -0
  10. package/dist/brain/ast-analyzer.d.ts.map +1 -0
  11. package/dist/brain/ast-analyzer.js +462 -0
  12. package/dist/brain/ast-analyzer.js.map +1 -0
  13. package/dist/brain/code-age-analyzer.d.ts +11 -0
  14. package/dist/brain/code-age-analyzer.d.ts.map +1 -0
  15. package/dist/brain/code-age-analyzer.js +152 -0
  16. package/dist/brain/code-age-analyzer.js.map +1 -0
  17. package/dist/brain/config-drift-detector.d.ts +13 -0
  18. package/dist/brain/config-drift-detector.d.ts.map +1 -0
  19. package/dist/brain/config-drift-detector.js +198 -0
  20. package/dist/brain/config-drift-detector.js.map +1 -0
  21. package/dist/brain/dead-code-eliminator.d.ts +16 -0
  22. package/dist/brain/dead-code-eliminator.d.ts.map +1 -0
  23. package/dist/brain/dead-code-eliminator.js +359 -0
  24. package/dist/brain/dead-code-eliminator.js.map +1 -0
  25. package/dist/brain/env-analyzer.d.ts +13 -0
  26. package/dist/brain/env-analyzer.d.ts.map +1 -0
  27. package/dist/brain/env-analyzer.js +277 -0
  28. package/dist/brain/env-analyzer.js.map +1 -0
  29. package/dist/brain/i18n-detector.d.ts +12 -0
  30. package/dist/brain/i18n-detector.d.ts.map +1 -0
  31. package/dist/brain/i18n-detector.js +242 -0
  32. package/dist/brain/i18n-detector.js.map +1 -0
  33. package/dist/brain/license-compliance.d.ts +13 -0
  34. package/dist/brain/license-compliance.d.ts.map +1 -0
  35. package/dist/brain/license-compliance.js +213 -0
  36. package/dist/brain/license-compliance.js.map +1 -0
  37. package/dist/brain/llm-client.d.ts.map +1 -1
  38. package/dist/brain/llm-client.js +3 -0
  39. package/dist/brain/llm-client.js.map +1 -1
  40. package/dist/brain/mutation-advisor.d.ts +11 -0
  41. package/dist/brain/mutation-advisor.d.ts.map +1 -0
  42. package/dist/brain/mutation-advisor.js +154 -0
  43. package/dist/brain/mutation-advisor.js.map +1 -0
  44. package/dist/brain/orchestrator.d.ts +48 -1
  45. package/dist/brain/orchestrator.d.ts.map +1 -1
  46. package/dist/brain/orchestrator.js +178 -2
  47. package/dist/brain/orchestrator.js.map +1 -1
  48. package/dist/cli.js +408 -3
  49. package/dist/cli.js.map +1 -1
  50. package/dist/index.d.ts +11 -1
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +12 -1
  53. package/dist/index.js.map +1 -1
  54. package/dist/types.d.ts +151 -2
  55. package/dist/types.d.ts.map +1 -1
  56. package/package.json +2 -2
@@ -0,0 +1,462 @@
1
+ // src/brain/ast-analyzer.ts — AST-level code analysis: function complexity, nesting depth, parameter count
2
+ // v3.0.0 — Deep structural code analysis without external AST dependencies
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ const IGNORE_DIRS = new Set([
6
+ 'node_modules', '.git', 'dist', 'build', 'out', 'target', 'vendor',
7
+ '__pycache__', '.next', '.nuxt', 'coverage', '.cache', '.tox',
8
+ 'venv', '.venv', 'env', '.env', 'bin', 'obj', 'Pods', '.gradle',
9
+ ]);
10
+ const CODE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.py', '.rs', '.go', '.java']);
11
+ export class ASTAnalyzer {
12
+ constructor(projectDir) {
13
+ this.projectDir = projectDir;
14
+ }
15
+ async analyzeProject(maxFiles = 100) {
16
+ const files = this.collectFiles(this.projectDir, maxFiles);
17
+ const insights = [];
18
+ for (const filePath of files) {
19
+ const functions = this.extractFunctionInfo(filePath);
20
+ for (const fn of functions) {
21
+ const fnInsights = this.analyzeFunction(fn, filePath);
22
+ insights.push(...fnInsights);
23
+ }
24
+ // File-level analysis
25
+ const fileInsights = this.analyzeFileStructure(filePath);
26
+ insights.push(...fileInsights);
27
+ }
28
+ return insights;
29
+ }
30
+ extractFunctionInfo(filePath) {
31
+ const ext = path.extname(filePath);
32
+ if (['.ts', '.tsx', '.js', '.jsx'].includes(ext)) {
33
+ return this.extractJSFunctions(filePath);
34
+ }
35
+ else if (ext === '.py') {
36
+ return this.extractPythonFunctions(filePath);
37
+ }
38
+ return [];
39
+ }
40
+ extractJSFunctions(filePath) {
41
+ let content;
42
+ try {
43
+ content = fs.readFileSync(filePath, 'utf-8');
44
+ }
45
+ catch {
46
+ return [];
47
+ }
48
+ const functions = [];
49
+ const lines = content.split('\n');
50
+ // Match function declarations, arrow functions, method definitions
51
+ const patterns = [
52
+ // Named function: function name(...) { or =>
53
+ /^(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(([^)]*)\)/,
54
+ // Arrow function: const name = (...) => { or const name = (...) =>
55
+ /^(?:export\s+)?(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s*)?\(([^)]*)\)\s*=>/,
56
+ // Method: name(...) { (in class)
57
+ /^\s+(?:async\s+)?(\w+)\s*\(([^)]*)\)\s*\{/,
58
+ // Class method shorthand
59
+ /^(?:public|private|protected|static)?\s*(?:async\s+)?(\w+)\s*\(([^)]*)\)\s*[:(]/,
60
+ ];
61
+ for (let i = 0; i < lines.length; i++) {
62
+ const line = lines[i];
63
+ for (const pattern of patterns) {
64
+ const match = line.match(pattern);
65
+ if (match) {
66
+ const name = match[1];
67
+ const params = match[2].split(',').filter(p => p.trim().length > 0).length;
68
+ const startLine = i + 1;
69
+ const endLine = this.findFunctionEnd(lines, i);
70
+ const body = lines.slice(i, endLine).join('\n');
71
+ const nestingDepth = this.calculateNestingDepth(body);
72
+ const returnPaths = this.countReturnPaths(body);
73
+ const cyclomaticComplexity = this.calculateCyclomaticComplexity(body);
74
+ const cognitiveComplexity = this.calculateCognitiveComplexity(body);
75
+ const isExported = /^(export|module\.exports)/.test(line.trim());
76
+ const isAsync = /async\s/.test(line);
77
+ functions.push({
78
+ name,
79
+ file: path.relative(this.projectDir, filePath),
80
+ startLine,
81
+ endLine: endLine + 1,
82
+ params,
83
+ nestingDepth,
84
+ returnPaths,
85
+ cyclomaticComplexity,
86
+ cognitiveComplexity,
87
+ linesOfCode: endLine - i + 1,
88
+ isExported,
89
+ isAsync,
90
+ isPure: this.assessPurity(body),
91
+ });
92
+ break; // matched one pattern, skip remaining
93
+ }
94
+ }
95
+ }
96
+ return functions;
97
+ }
98
+ extractPythonFunctions(filePath) {
99
+ let content;
100
+ try {
101
+ content = fs.readFileSync(filePath, 'utf-8');
102
+ }
103
+ catch {
104
+ return [];
105
+ }
106
+ const functions = [];
107
+ const lines = content.split('\n');
108
+ for (let i = 0; i < lines.length; i++) {
109
+ const match = lines[i].match(/^(?:async\s+)?def\s+(\w+)\s*\(([^)]*)\)/);
110
+ if (match) {
111
+ const name = match[1];
112
+ const params = match[2].split(',').filter(p => p.trim().length > 0 && p.trim() !== 'self').length;
113
+ const startLine = i + 1;
114
+ const endLine = this.findPythonFunctionEnd(lines, i);
115
+ const body = lines.slice(i, endLine).join('\n');
116
+ functions.push({
117
+ name,
118
+ file: path.relative(this.projectDir, filePath),
119
+ startLine,
120
+ endLine: endLine + 1,
121
+ params,
122
+ nestingDepth: this.calculatePythonNesting(body),
123
+ returnPaths: (body.match(/\breturn\b/g) || []).length,
124
+ cyclomaticComplexity: this.calculatePythonComplexity(body),
125
+ cognitiveComplexity: this.calculatePythonCognitiveComplexity(body),
126
+ linesOfCode: endLine - i + 1,
127
+ isExported: !lines[i].startsWith('_'),
128
+ isAsync: /async\s+def/.test(lines[i]),
129
+ isPure: true, // conservative
130
+ });
131
+ }
132
+ }
133
+ return functions;
134
+ }
135
+ analyzeFunction(fn, filePath) {
136
+ const insights = [];
137
+ const relPath = path.relative(this.projectDir, filePath);
138
+ // High cyclomatic complexity
139
+ if (fn.cyclomaticComplexity > 10) {
140
+ insights.push({
141
+ type: 'warning',
142
+ priority: fn.cyclomaticComplexity > 20 ? 'critical' : 'high',
143
+ title: `[complexity] Function "${fn.name}" has cyclomatic complexity of ${fn.cyclomaticComplexity}`,
144
+ content: `Function \`${fn.name}\` in ${relPath}:${fn.startLine} has cyclomatic complexity ${fn.cyclomaticComplexity} (threshold: 10).\n` +
145
+ ` Parameters: ${fn.params}, Nesting depth: ${fn.nestingDepth}, Return paths: ${fn.returnPaths}\n` +
146
+ ` Lines of code: ${fn.linesOfCode}\n` +
147
+ ` High complexity makes code hard to test, understand, and maintain.\n` +
148
+ ` Consider: Extract helper functions, use early returns, simplify conditionals, apply guard clauses.`,
149
+ files: [relPath],
150
+ timestamp: new Date(),
151
+ confidence: 0.95,
152
+ metadata: { complexity: fn.cyclomaticComplexity, lines: fn.linesOfCode },
153
+ });
154
+ }
155
+ else if (fn.cyclomaticComplexity > 5) {
156
+ insights.push({
157
+ type: 'suggestion',
158
+ priority: 'medium',
159
+ title: `[complexity] Function "${fn.name}" complexity ${fn.cyclomaticComplexity} (moderate)`,
160
+ content: `Function \`${fn.name}\` in ${relPath}:${fn.startLine} has moderate complexity (${fn.cyclomaticComplexity}).\n` +
161
+ ` Consider simplifying if possible — complexity above 5 increases testing difficulty.`,
162
+ files: [relPath],
163
+ timestamp: new Date(),
164
+ confidence: 0.9,
165
+ });
166
+ }
167
+ // Too many parameters
168
+ if (fn.params > 5) {
169
+ insights.push({
170
+ type: 'suggestion',
171
+ priority: fn.params > 7 ? 'high' : 'medium',
172
+ title: `[design] Function "${fn.name}" has ${fn.params} parameters`,
173
+ content: `Function \`${fn.name}\` in ${relPath}:${fn.startLine} accepts ${fn.params} parameters.\n` +
174
+ ` Functions with more than 3-4 parameters are hard to call correctly.\n` +
175
+ ` Consider: Use an options/config object, extract a builder, or group related parameters.`,
176
+ files: [relPath],
177
+ timestamp: new Date(),
178
+ confidence: 0.9,
179
+ });
180
+ }
181
+ // Deep nesting
182
+ if (fn.nestingDepth > 4) {
183
+ insights.push({
184
+ type: 'warning',
185
+ priority: fn.nestingDepth > 6 ? 'critical' : 'high',
186
+ title: `[complexity] Deep nesting (${fn.nestingDepth} levels) in "${fn.name}"`,
187
+ content: `Function \`${fn.name}\` in ${relPath}:${fn.startLine} has ${fn.nestingDepth} levels of nesting.\n` +
188
+ ` Deep nesting reduces readability and increases bug surface.\n` +
189
+ ` Consider: Early returns, extract nested logic into separate functions, use guard clauses.`,
190
+ files: [relPath],
191
+ timestamp: new Date(),
192
+ confidence: 0.95,
193
+ });
194
+ }
195
+ // Very long functions
196
+ if (fn.linesOfCode > 50) {
197
+ insights.push({
198
+ type: 'suggestion',
199
+ priority: fn.linesOfCode > 100 ? 'high' : 'medium',
200
+ title: `[quality] Function "${fn.name}" is ${fn.linesOfCode} lines long`,
201
+ content: `Function \`${fn.name}\` in ${relPath}:${fn.startLine} spans ${fn.linesOfCode} lines.\n` +
202
+ ` Long functions are harder to understand, test, and reuse.\n` +
203
+ ` Consider: Extract logical sections into named helper functions.`,
204
+ files: [relPath],
205
+ timestamp: new Date(),
206
+ confidence: 0.85,
207
+ });
208
+ }
209
+ // Too many return paths
210
+ if (fn.returnPaths > 5) {
211
+ insights.push({
212
+ type: 'suggestion',
213
+ priority: 'medium',
214
+ title: `[quality] Function "${fn.name}" has ${fn.returnPaths} return paths`,
215
+ content: `Function \`${fn.name}\` in ${relPath}:${fn.startLine} has ${fn.returnPaths} distinct return paths.\n` +
216
+ ` Multiple return paths increase testing complexity and can hide edge cases.\n` +
217
+ ` Consider: Consolidate return logic, use result objects, or apply the single-exit principle.`,
218
+ files: [relPath],
219
+ timestamp: new Date(),
220
+ confidence: 0.8,
221
+ });
222
+ }
223
+ return insights;
224
+ }
225
+ analyzeFileStructure(filePath) {
226
+ const insights = [];
227
+ let content;
228
+ try {
229
+ content = fs.readFileSync(filePath, 'utf-8');
230
+ }
231
+ catch {
232
+ return insights;
233
+ }
234
+ const lines = content.split('\n');
235
+ const relPath = path.relative(this.projectDir, filePath);
236
+ const lineCount = lines.length;
237
+ // Very large files
238
+ if (lineCount > 500) {
239
+ insights.push({
240
+ type: 'warning',
241
+ priority: lineCount > 1000 ? 'high' : 'medium',
242
+ title: `[architecture] Large file: ${relPath} (${lineCount} lines)`,
243
+ content: `File ${relPath} has ${lineCount} lines. Large files indicate potential SRP violations.\n` +
244
+ ` Consider splitting into focused modules with clear responsibilities.`,
245
+ files: [relPath],
246
+ timestamp: new Date(),
247
+ confidence: 0.85,
248
+ });
249
+ }
250
+ // Too many imports
251
+ const importLines = lines.filter(l => /^\s*(import\s|from\s|require\s*\()/.test(l));
252
+ if (importLines.length > 20) {
253
+ insights.push({
254
+ type: 'suggestion',
255
+ priority: 'medium',
256
+ title: `[architecture] High import count in ${relPath} (${importLines.length})`,
257
+ content: `File ${relPath} has ${importLines.length} imports. This may indicate the module has too many responsibilities.\n` +
258
+ ` Consider: Split into smaller modules, consolidate related imports, use barrel exports.`,
259
+ files: [relPath],
260
+ timestamp: new Date(),
261
+ confidence: 0.8,
262
+ });
263
+ }
264
+ // TODO/FIXME/HACK comments
265
+ const todoPatterns = [
266
+ { regex: /TODO|FIXME|HACK|XXX|OPTIMIZE/gi, label: 'action item' },
267
+ ];
268
+ for (const { regex, label } of todoPatterns) {
269
+ const matches = [...content.matchAll(regex)];
270
+ if (matches.length > 3) {
271
+ insights.push({
272
+ type: 'suggestion',
273
+ priority: 'low',
274
+ title: `[quality] ${matches.length} ${label}s in ${relPath}`,
275
+ content: `File ${relPath} contains ${matches.length} ${label} comments (TODO/FIXME/HACK/XXX).\n` +
276
+ ` Consider addressing these or converting to tracked issues.`,
277
+ files: [relPath],
278
+ timestamp: new Date(),
279
+ confidence: 0.95,
280
+ });
281
+ }
282
+ }
283
+ return insights;
284
+ }
285
+ // ── Complexity Calculators ──────────────────────────────────────────────────
286
+ calculateCyclomaticComplexity(code) {
287
+ // McCabe's cyclomatic complexity: 1 + number of decisions
288
+ let complexity = 1;
289
+ const decisionPatterns = [
290
+ /\bif\b/g, /\belse\s+if\b/g, /\bfor\b/g, /\bwhile\b/g,
291
+ /\bcase\b/g, /\?.*:/g, /&&/g, /\|\|/g, /\?\?/g,
292
+ /\.catch\b/g, /\btry\b/g,
293
+ ];
294
+ for (const pattern of decisionPatterns) {
295
+ const matches = code.match(pattern);
296
+ if (matches)
297
+ complexity += matches.length;
298
+ }
299
+ return complexity;
300
+ }
301
+ calculateCognitiveComplexity(code) {
302
+ let complexity = 0;
303
+ let nestingLevel = 0;
304
+ const lines = code.split('\n');
305
+ for (const line of lines) {
306
+ const trimmed = line.trim();
307
+ // Increment nesting
308
+ if (/[{(]\s*$/.test(trimmed) || /\bthen\b\s*$/.test(trimmed)) {
309
+ nestingLevel++;
310
+ }
311
+ // Structural increments (with nesting bonus)
312
+ if (/\bif\b/.test(trimmed))
313
+ complexity += 1 + nestingLevel;
314
+ if (/\belse\b/.test(trimmed) || /\belif\b/.test(trimmed))
315
+ complexity += 1;
316
+ if (/\bfor\b/.test(trimmed) || /\bwhile\b/.test(trimmed))
317
+ complexity += 1 + nestingLevel;
318
+ if (/\bswitch\b/.test(trimmed))
319
+ complexity += 1 + nestingLevel;
320
+ if (/\bcase\b/.test(trimmed))
321
+ complexity += 1;
322
+ // Fundamental increments (no nesting bonus)
323
+ if (/&&|\|\||\?\?/.test(trimmed))
324
+ complexity += 1;
325
+ if (/\?\s*[^:]+\s*:/.test(trimmed))
326
+ complexity += 1;
327
+ // Decrement nesting
328
+ if (/^[)}]/.test(trimmed)) {
329
+ nestingLevel = Math.max(0, nestingLevel - 1);
330
+ }
331
+ }
332
+ return complexity;
333
+ }
334
+ calculateNestingDepth(code) {
335
+ let maxDepth = 0;
336
+ let currentDepth = 0;
337
+ let inString = false;
338
+ let stringChar = '';
339
+ for (let i = 0; i < code.length; i++) {
340
+ const ch = code[i];
341
+ if (inString) {
342
+ if (ch === stringChar && code[i - 1] !== '\\')
343
+ inString = false;
344
+ continue;
345
+ }
346
+ if (ch === '"' || ch === "'" || ch === '`') {
347
+ inString = true;
348
+ stringChar = ch;
349
+ continue;
350
+ }
351
+ if (ch === '{' || ch === '(') {
352
+ currentDepth++;
353
+ maxDepth = Math.max(maxDepth, currentDepth);
354
+ }
355
+ else if (ch === '}' || ch === ')') {
356
+ currentDepth = Math.max(0, currentDepth - 1);
357
+ }
358
+ }
359
+ return maxDepth;
360
+ }
361
+ countReturnPaths(code) {
362
+ const matches = code.match(/\breturn\b/g);
363
+ return matches ? matches.length : 0;
364
+ }
365
+ assessPurity(code) {
366
+ // Heuristic: if function accesses globals, modifies external state, or does I/O, it's not pure
367
+ const impurityIndicators = [
368
+ /\bconsole\./, /\bprocess\./, /\brequire\(/, /\bimport\s/,
369
+ /\bfs\./, /\bfetch\(/, /\bawait\b/, /\bDate\.now\(\)/,
370
+ /\bMath\.random\(\)/, /\bdocument\./, /\bwindow\./,
371
+ ];
372
+ for (const indicator of impurityIndicators) {
373
+ if (indicator.test(code))
374
+ return false;
375
+ }
376
+ return true;
377
+ }
378
+ findFunctionEnd(lines, startIdx) {
379
+ let braceCount = 0;
380
+ let foundFirstBrace = false;
381
+ for (let i = startIdx; i < lines.length; i++) {
382
+ for (const ch of lines[i]) {
383
+ if (ch === '{') {
384
+ braceCount++;
385
+ foundFirstBrace = true;
386
+ }
387
+ if (ch === '}')
388
+ braceCount--;
389
+ }
390
+ if (foundFirstBrace && braceCount <= 0)
391
+ return i;
392
+ }
393
+ return lines.length - 1;
394
+ }
395
+ findPythonFunctionEnd(lines, startIdx) {
396
+ const baseIndent = lines[startIdx].search(/\S/);
397
+ for (let i = startIdx + 1; i < lines.length; i++) {
398
+ const lineIndent = lines[i].search(/\S/);
399
+ if (lineIndent >= 0 && lineIndent <= baseIndent && lines[i].trim().length > 0) {
400
+ return i - 1;
401
+ }
402
+ }
403
+ return lines.length - 1;
404
+ }
405
+ calculatePythonNesting(code) {
406
+ let maxDepth = 0;
407
+ let currentDepth = 0;
408
+ for (const line of code.split('\n')) {
409
+ const indent = line.search(/\S/);
410
+ if (indent >= 0) {
411
+ currentDepth = Math.floor(indent / 4);
412
+ maxDepth = Math.max(maxDepth, currentDepth);
413
+ }
414
+ }
415
+ return maxDepth;
416
+ }
417
+ calculatePythonComplexity(code) {
418
+ let complexity = 1;
419
+ const patterns = [/\bif\b/g, /\belif\b/g, /\bfor\b/g, /\bwhile\b/g, /\band\b/g, /\bor\b/g, /\bexcept\b/g];
420
+ for (const p of patterns) {
421
+ const m = code.match(p);
422
+ if (m)
423
+ complexity += m.length;
424
+ }
425
+ return complexity;
426
+ }
427
+ calculatePythonCognitiveComplexity(code) {
428
+ return this.calculatePythonComplexity(code); // simplified
429
+ }
430
+ collectFiles(dir, maxFiles) {
431
+ const results = [];
432
+ const walk = (currentDir, depth) => {
433
+ if (results.length >= maxFiles || depth > 10)
434
+ return;
435
+ let entries;
436
+ try {
437
+ entries = fs.readdirSync(currentDir, { withFileTypes: true });
438
+ }
439
+ catch {
440
+ return;
441
+ }
442
+ for (const entry of entries) {
443
+ if (results.length >= maxFiles)
444
+ return;
445
+ if (entry.name.startsWith('.') && entry.name !== '.env.example')
446
+ continue;
447
+ const fullPath = path.join(currentDir, entry.name);
448
+ if (entry.isDirectory()) {
449
+ if (IGNORE_DIRS.has(entry.name))
450
+ continue;
451
+ walk(fullPath, depth + 1);
452
+ }
453
+ else if (entry.isFile() && CODE_EXTENSIONS.has(path.extname(entry.name))) {
454
+ results.push(fullPath);
455
+ }
456
+ }
457
+ };
458
+ walk(dir, 0);
459
+ return results;
460
+ }
461
+ }
462
+ //# sourceMappingURL=ast-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-analyzer.js","sourceRoot":"","sources":["../../src/brain/ast-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { BrainInsight } from '../types.js';
2
+ export declare class CodeAgeAnalyzer {
3
+ private projectDir;
4
+ constructor(projectDir: string);
5
+ analyzeProject(maxFiles?: number): Promise<BrainInsight[]>;
6
+ private analyzeFileAge;
7
+ private getFileAuthors;
8
+ private ageToInsight;
9
+ private collectFiles;
10
+ }
11
+ //# sourceMappingURL=code-age-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-age-analyzer.d.ts","sourceRoot":"","sources":["../../src/brain/code-age-analyzer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAiB,MAAM,aAAa,CAAC;AAU1D,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,EAAE,MAAM;IAIxB,cAAc,CAAC,QAAQ,GAAE,MAAY,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IA8CrE,OAAO,CAAC,cAAc;IAkCtB,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,YAAY;IAsBpB,OAAO,CAAC,YAAY;CAqBrB"}
@@ -0,0 +1,152 @@
1
+ // src/brain/code-age-analyzer.ts — Code staleness and age analysis
2
+ // v3.0.0 — Tracks file modification age, churn, and staleness risk
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ const IGNORE_DIRS = new Set([
6
+ 'node_modules', '.git', 'dist', 'build', 'out', 'coverage', '.next', '.nuxt', '.cache',
7
+ ]);
8
+ const CODE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.py', '.rs', '.go', '.java']);
9
+ export class CodeAgeAnalyzer {
10
+ constructor(projectDir) {
11
+ this.projectDir = projectDir;
12
+ }
13
+ async analyzeProject(maxFiles = 300) {
14
+ const files = this.collectFiles(this.projectDir, maxFiles);
15
+ const insights = [];
16
+ const results = [];
17
+ const now = Date.now();
18
+ for (const filePath of files) {
19
+ const result = this.analyzeFileAge(filePath, now);
20
+ if (result) {
21
+ results.push(result);
22
+ }
23
+ }
24
+ // Sort by staleness score descending
25
+ results.sort((a, b) => b.stalenessScore - a.stalenessScore);
26
+ // Generate insights for stale files
27
+ for (const result of results) {
28
+ if (result.risk === 'ancient' || result.risk === 'stale') {
29
+ insights.push(this.ageToInsight(result));
30
+ }
31
+ }
32
+ // Summary insight if many stale files
33
+ const staleCount = results.filter(r => r.risk === 'stale' || r.risk === 'ancient').length;
34
+ const totalFiles = results.length;
35
+ if (staleCount > totalFiles * 0.3 && totalFiles > 10) {
36
+ insights.push({
37
+ type: 'warning',
38
+ priority: 'medium',
39
+ title: `[age] ${(staleCount / totalFiles * 100).toFixed(0)}% of code is stale (>180 days since modification)`,
40
+ content: `Project has ${staleCount}/${totalFiles} files that haven't been modified in over 180 days.\n` +
41
+ ` This may indicate: dead code, abandoned features, or stable-but-untested modules.\n` +
42
+ ` Consider reviewing stale files for removal or adding test coverage.`,
43
+ files: results.filter(r => r.risk === 'stale' || r.risk === 'ancient').map(r => r.file).slice(0, 20),
44
+ timestamp: new Date(),
45
+ confidence: 0.7,
46
+ metadata: { stalePercentage: staleCount / totalFiles, totalFiles, staleCount },
47
+ });
48
+ }
49
+ return insights;
50
+ }
51
+ analyzeFileAge(filePath, now) {
52
+ let stat;
53
+ try {
54
+ stat = fs.statSync(filePath);
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ const relPath = path.relative(this.projectDir, filePath);
60
+ const lastModified = stat.mtime;
61
+ const daysSinceModification = Math.floor((now - lastModified.getTime()) / (1000 * 60 * 60 * 24));
62
+ // Determine risk level
63
+ let risk;
64
+ if (daysSinceModification <= 7)
65
+ risk = 'fresh';
66
+ else if (daysSinceModification <= 30)
67
+ risk = 'stable';
68
+ else if (daysSinceModification <= 90)
69
+ risk = 'aging';
70
+ else if (daysSinceModification <= 365)
71
+ risk = 'stale';
72
+ else
73
+ risk = 'ancient';
74
+ // Staleness score: 0 = fresh, 1 = very stale
75
+ const stalenessScore = Math.min(1, daysSinceModification / 365);
76
+ // Try to get git blame info (simplified — just count unique authors from recent changes)
77
+ const authors = this.getFileAuthors(filePath);
78
+ return {
79
+ file: relPath,
80
+ lastModified,
81
+ daysSinceModification,
82
+ linesChangedRecently: 0, // would need git log for exact count
83
+ stalenessScore,
84
+ risk,
85
+ authors,
86
+ churnRate: 0, // would need git history for exact rate
87
+ };
88
+ }
89
+ getFileAuthors(filePath) {
90
+ // Try reading git log for authors (best-effort)
91
+ try {
92
+ const { execSync } = require('child_process');
93
+ const output = execSync(`git log --format="%an" --follow -- "${path.relative(this.projectDir, filePath)}"`, { cwd: this.projectDir, timeout: 5000, encoding: 'utf-8' });
94
+ const authors = [...new Set(output.trim().split('\n').filter(Boolean))];
95
+ return authors.slice(0, 5);
96
+ }
97
+ catch {
98
+ return [];
99
+ }
100
+ }
101
+ ageToInsight(result) {
102
+ const daysText = result.daysSinceModification > 365
103
+ ? `${(result.daysSinceModification / 365).toFixed(1)} years`
104
+ : `${result.daysSinceModification} days`;
105
+ return {
106
+ type: 'warning',
107
+ priority: result.risk === 'ancient' ? 'high' : 'medium',
108
+ title: `[age] ${result.risk} file: ${result.file} (${daysText} since last change)`,
109
+ content: `File ${result.file} hasn't been modified in ${daysText}.\n` +
110
+ ` Risk level: ${result.risk}\n` +
111
+ ` Staleness score: ${(result.stalenessScore * 100).toFixed(0)}%\n` +
112
+ (result.authors.length > 0 ? ` Previous authors: ${result.authors.join(', ')}\n` : '') +
113
+ ` Consider: Review for relevance, add tests if still needed, or remove if obsolete.`,
114
+ files: [result.file],
115
+ timestamp: new Date(),
116
+ confidence: 0.75,
117
+ metadata: { daysSinceModification: result.daysSinceModification, risk: result.risk, stalenessScore: result.stalenessScore },
118
+ };
119
+ }
120
+ collectFiles(dir, maxFiles) {
121
+ const results = [];
122
+ const walk = (currentDir, depth) => {
123
+ if (results.length >= maxFiles || depth > 10)
124
+ return;
125
+ let entries;
126
+ try {
127
+ entries = fs.readdirSync(currentDir, { withFileTypes: true });
128
+ }
129
+ catch {
130
+ return;
131
+ }
132
+ for (const entry of entries) {
133
+ if (results.length >= maxFiles)
134
+ return;
135
+ if (entry.name.startsWith('.'))
136
+ continue;
137
+ const fullPath = path.join(currentDir, entry.name);
138
+ if (entry.isDirectory()) {
139
+ if (IGNORE_DIRS.has(entry.name))
140
+ continue;
141
+ walk(fullPath, depth + 1);
142
+ }
143
+ else if (entry.isFile() && CODE_EXTENSIONS.has(path.extname(entry.name))) {
144
+ results.push(fullPath);
145
+ }
146
+ }
147
+ };
148
+ walk(dir, 0);
149
+ return results;
150
+ }
151
+ }
152
+ //# sourceMappingURL=code-age-analyzer.js.map