Swadhin Biswas Feature/ai code reviewer (#73) · 8/2/2026
105a287
90 lines · 2.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/**
 * Review Analysis Pipeline
 * Orchestrates all analysis engines into a single pipeline.
 */

import { simpleGit } from "simple-git";
import { chunkDiff, getDiffStats, type DiffChunk } from "./diff-chunker";
import { buildDependencyGraph, type DependencyGraph } from "./dep-graph";
import { assessArchitectureImpact, type ArchImpact } from "./arch-impact";
import { analyzeAllComplexity, type ComplexityResult } from "./complexity-engine";
import { groupChanges, type ChangeGroup } from "./change-grouper";
import { calculateBlastRadius, type BlastRadius } from "./blast-radius";
import { calculateHealthScore, type HealthScore } from "./scoring";

export interface ReviewAnalysis {
  chunks: DiffChunk[];
  depGraph: DependencyGraph;
  archImpact: ArchImpact;
  complexity: {
    perFile: Map<string, ComplexityResult>;
    aggregate: ComplexityResult;
  };
  groups: ChangeGroup[];
  blastRadius: BlastRadius;
  healthScore: HealthScore;
  stats: ReturnType<typeof getDiffStats>;
}

export async function getDiff(repoPath: string, baseSha: string, headSha: string): Promise<string> {
  const git = simpleGit(repoPath);
  try {
    const diff = await git.diff([baseSha, headSha, "--no-color"]);
    return diff;
  } catch (err) {
    // Fallback: try to get diff between commits
    const diff = await git.diff(["--no-color", baseSha, headSha]);
    return diff;
  }
}

export async function runAnalysisPipeline(
  repoPath: string,
  baseSha: string,
  headSha: string,
): Promise<ReviewAnalysis> {
  // 1. Extract diff
  const rawDiff = await getDiff(repoPath, baseSha, headSha);

  // 2. Chunk diff
  const chunks = chunkDiff(rawDiff);

  // 3. Build dependency graph
  const depGraph = buildDependencyGraph(chunks, repoPath);

  // 4. Analyze complexity per chunk
  const complexity = analyzeAllComplexity(chunks);

  // 5. Assess architecture impact
  const archImpact = assessArchitectureImpact(chunks);

  // 6. Group changes
  const groups = groupChanges(chunks, depGraph);

  // 7. Calculate blast radius
  const blastRadius = calculateBlastRadius(chunks, depGraph, archImpact);

  // 8. Calculate health score
  const healthScore = calculateHealthScore(
    complexity.aggregate,
    blastRadius,
    archImpact,
    chunks.reduce((s, c) => s + c.additions, 0),
    chunks.reduce((s, c) => s + c.deletions, 0),
  );

  // 9. Get overall stats
  const stats = getDiffStats(chunks);

  return {
    chunks,
    depGraph,
    archImpact,
    complexity,
    groups,
    blastRadius,
    healthScore,
    stats,
  };
}