Hotspot Analysis
Git churn x ESLint complexity cross-reference script that identifies the most dangerous files -- high change frequency AND high complexity.
scripts/hotspot-analysis.sh cross-references git churn (files changed most frequently over a configurable period) with ESLint complexity violations to identify the most dangerous files -- those that change frequently AND are complex. These files have the highest probability of introducing bugs.
This script replaced CodeScene (EUR 18/month). It lacks CodeScene's temporal coupling analysis but provides the most actionable metric (churn x complexity) at zero cost.
Running Locally
# Default: 90 days, top 20 files, table output
pnpm hotspots
# Custom: 180 days, top 30 files
bash scripts/hotspot-analysis.sh 180 30
# JSON output (for CI artifacts)
bash scripts/hotspot-analysis.sh 90 20 json
How It Works
The script runs in four steps:
Step 1: Git Churn
Queries git log for the most-changed files over the configurable period. Only .ts and .tsx files are included. Excluded: node_modules, dist, .next, migrations, seeds, test files.
Step 2: ESLint Complexity
Runs ESLint in JSON format across apps/ and packages/, extracting violations for these rules:
complexity(cyclomatic)sonarjs/cognitive-complexitymax-linesmax-lines-per-functionmax-depth
Step 3: Hotspot Score
For each file: score = churn * (1 + complexity_violations). Files with both high churn and complexity violations score highest. A file changed 20 times with 3 complexity violations scores 20 * 4 = 80. A file changed 20 times with zero violations scores 20 * 1 = 20.
Step 4: Output
Table output with color-coded risk levels:
| Color | Meaning | Criteria |
|---|---|---|
| RED | Refactor priority | High churn AND complexity violations > 0 |
| YELLOW | Monitor | High churn (>10 changes), no complexity violations |
| GREEN | Healthy | Moderate churn, no complexity violations |
Example Output
Hotspot Analysis — files with high churn + high complexity (last 90 days)
File Churn Cmplx Hotspot
------------------------------------------------------------ -------- -------- ------------
packages/api/src/routers/research.ts 18 2 54
apps/web/src/app/(app)/research/page.tsx 15 0 15
packages/db/src/schema/research.ts 12 0 12
In this example, research.ts in the routers would be RED (18 changes, 2 complexity violations), while the other two would be YELLOW (high churn but clean).
Scheduled Usage
The hotspot analysis runs as part of the monthly architecture audit. See Review and Audits for the full scheduled audit workflow.
JSON Output
The json format outputs an array for programmatic consumption:
[
{
"file": "packages/api/src/routers/research.ts",
"score": 54,
"churn": 18,
"complexityViolations": 2
},
{
"file": "apps/web/src/app/(app)/research/page.tsx",
"score": 15,
"churn": 15,
"complexityViolations": 0
}
]
Limitations
- No temporal coupling -- the script does not detect files that always change together (CodeScene does). Use
git log --name-onlymanually if you suspect coupling. - Complexity data depends on ESLint -- if ESLint fails to parse a file, it is treated as having zero complexity violations.
- Churn counts file-level changes -- a one-line typo fix counts the same as a 200-line rewrite.
Related Pages
- Complexity and Naming -- the ESLint complexity rules whose violations feed the hotspot score
- Review and Audits -- hotspot analysis is part of the monthly audit workflow