git-archaeologist 1.0.0 → 1.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.
package/README.md CHANGED
@@ -1,26 +1,20 @@
1
1
  # git-archaeologist
2
2
 
3
- Run one command. Find the time bombs in any codebase.
4
-
5
3
  ![demo](./demo.gif)
6
4
 
7
- ---
8
-
9
- I wrote this after two days tracking a bug that started because I touched a file 53 different people had already destroyed. This tool finds those files before you touch them.
10
-
11
- ---
12
-
13
- ## What it does
5
+ [![npm](https://img.shields.io/npm/v/git-archaeologist?color=a78bfa&labelColor=1a1d27)](https://www.npmjs.com/package/git-archaeologist)
6
+ [![license](https://img.shields.io/badge/license-MIT-a78bfa?labelColor=1a1d27)](LICENSE)
7
+ [![node](https://img.shields.io/badge/node-%3E%3D18-a78bfa?labelColor=1a1d27)](https://nodejs.org)
14
8
 
15
- **Cursed file score** not just most changed. A file touched 100 times in 6 months by 12 developers who never talked scores way higher than one touched 100 times over 5 years by the same person.
9
+ > Dig through your git history and find what's actually dangerous.
16
10
 
17
- **Bus factor per folder** not per repo. Knowing the lib/ folder will be orphaned the day Douglas leaves is actionable. Knowing the whole repo has bus factor 2 is useless.
11
+ [Install](#install) [Usage](#usage) [What it finds](#what-it-finds) [How scoring works](#how-scoring-works)
18
12
 
19
- **Implicit coupling** — files that always change together even though nothing in the code connects them. Hidden dependencies. Future outages.
13
+ ---
20
14
 
21
- **Ownership** not who created the file. Who owns the lines still alive in HEAD right now.
15
+ You inherit a codebase. You touch a file. Three things break that you had no idea were connected.
22
16
 
23
- ---
17
+ This tool reads your entire git history and surfaces four things: which files are ticking time bombs, who will take a whole module down when they quit, which files are secretly coupled even though nothing in the code shows it, and who truly owns what right now — not who created it.
24
18
 
25
19
  ## Install
26
20
 
@@ -28,57 +22,47 @@ I wrote this after two days tracking a bug that started because I touched a file
28
22
  npm install -g git-archaeologist
29
23
  ```
30
24
 
31
- ---
32
-
33
25
  ## Usage
34
26
 
35
27
  ```bash
36
- # full report
37
28
  git-arch analyze /path/to/repo
29
+ git-arch analyze /path/to/repo --html # dark-themed shareable report
30
+ git-arch cursed --top 10 # just the danger ranking
31
+ git-arch analyze /path/to/repo --json # pipe into other tools
32
+ ```
38
33
 
39
- # just cursed files
40
- git-arch cursed --top 10
34
+ ## What it finds
41
35
 
42
- # shareable HTML report
43
- git-arch analyze /path/to/repo --html
36
+ **Cursed files** ranked by instability score, not just change count. A file touched 100 times in 6 months by 15 different developers scores way higher than one changed 200 times over a decade by the same person. The score weights recency, author chaos, and churn rate together.
44
37
 
45
- # raw JSON
46
- git-arch analyze /path/to/repo --json
47
- ```
38
+ **Bus factor per folder** — not per repo. "The whole repo has bus factor 2" is useless. "The lib/ folder will be orphaned the day this one person leaves" is something you can act on.
48
39
 
49
- ---
40
+ **Implicit coupling** — pairs of files that always appear in the same commit, even though nothing in the code connects them. These are your hidden dependencies and your future bugs.
50
41
 
51
- ## What it found on Express.js
42
+ **Ownership** who owns the lines that are actually alive in HEAD right now. Not who created the file. Not who committed most recently.
52
43
 
53
- Express has 1716 commits and 230 contributors.
44
+ ## Tested on Express.js
54
45
 
55
- `lib/response.js` 128 changes, 53 authors, curse score 2261. The core of Express. A disaster waiting to happen.
46
+ Express is one of the most downloaded npm packages in history. 230 contributors. 16 years old.
56
47
 
57
- Every single module lib/, test/, examples/, benchmarks/ — has bus factor 1. One person. Douglas Christopher Wilson. If he stops tomorrow nobody else fully understands any of it.
48
+ Running git-archaeologist on it takes 3 seconds and finds:
58
49
 
59
- `benchmarks/Makefile` and `benchmarks/run` have 100% coupling. They are one file pretending to be two.
60
-
61
- ---
50
+ - `lib/response.js` 128 changes, 53 different authors, curse score 2261. The core HTTP response logic of the framework has been touched by 53 people and nobody fully owns it.
51
+ - Bus factor across every module (lib/, test/, examples/, benchmarks/) is 1. One person. The entire project depends on Douglas Christopher Wilson continuing to show up.
52
+ - `benchmarks/Makefile` and `benchmarks/run` have been committed together 100% of the time. They have never changed separately. They are one file.
62
53
 
63
- ## The formula
54
+ ## How scoring works
64
55
 
65
56
  ```
66
- curse_score = changes x log2(authors+1) x exp(-0.5 x age_years) x log2(churn_rate+2)
57
+ curse_score = changes × log₂(authors+1) × exp(-0.5 × age_years) × log₂(churn_rate+2)
67
58
  ```
68
59
 
69
- The exponential decay on age means old chaos that stabilized does not show up. Only current danger.
60
+ The exponential decay on age is the important part. A file that was chaotic 5 years ago and has been stable since will not show up. Only files that are actively dangerous right now.
70
61
 
71
- ---
62
+ ## Requirements
72
63
 
73
- ## Run locally
64
+ Node.js >= 18 and git >= 2.30. Works on Linux, macOS, and Windows (WSL).
74
65
 
75
- ```bash
76
- git clone https://github.com/SushantVerma7969/git-archaeologist.git
77
- cd git-archaeologist
78
- npm install && npm run build
79
- node dist/index.js analyze /any/repo
80
- ```
81
-
82
- ---
66
+ ## License
83
67
 
84
- MIT. Use it however you want.
68
+ MIT
@@ -1 +1 @@
1
- {"version":3,"file":"htmlReport.d.ts","sourceRoot":"","sources":["../../src/output/htmlReport.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AA6B1C,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAmInF"}
1
+ {"version":3,"file":"htmlReport.d.ts","sourceRoot":"","sources":["../../src/output/htmlReport.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AA8B1C,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAsLnF"}
@@ -35,158 +35,211 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.generateHtmlReport = generateHtmlReport;
37
37
  const fs = __importStar(require("fs"));
38
- function escapeHtml(str) {
39
- return str
40
- .replace(/&/g, '&')
41
- .replace(/</g, '&lt;')
42
- .replace(/>/g, '&gt;')
43
- .replace(/"/g, '&quot;');
38
+ function esc(s) {
39
+ return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
44
40
  }
45
- function scoreColor(score) {
46
- if (score >= 800)
47
- return '#f87171';
48
- if (score >= 400)
49
- return '#fbbf24';
50
- if (score >= 100)
51
- return '#34d399';
52
- return '#6ee7b7';
41
+ function col(score, max) {
42
+ const r = Math.min(score / Math.max(max, 1), 1);
43
+ if (r > 0.7)
44
+ return '#ef4444';
45
+ if (r > 0.4)
46
+ return '#f97316';
47
+ if (r > 0.2)
48
+ return '#eab308';
49
+ if (r > 0.05)
50
+ return '#22c55e';
51
+ return '#3b82f6';
53
52
  }
54
- function busColor(n) {
55
- if (n === 1)
56
- return '#f87171';
57
- if (n === 2)
58
- return '#fbbf24';
59
- return '#34d399';
60
- }
61
- function pctColor(p) {
62
- if (p >= 90)
63
- return '#c084fc';
64
- if (p >= 70)
65
- return '#60a5fa';
66
- return '#94a3b8';
53
+ function buildTree(result) {
54
+ const sm = new Map();
55
+ for (const f of result.cursedFiles)
56
+ sm.set(f.filepath, f.curseScore);
57
+ const fm = new Map();
58
+ for (const [fp, stats] of result.fileStats) {
59
+ const parts = fp.split('/');
60
+ const folder = parts.length > 1 ? parts[0] : '(root)';
61
+ const score = sm.get(fp) ?? 0;
62
+ const last = new Date(stats.lastChanged * 1000).toISOString().split('T')[0];
63
+ if (!fm.has(folder))
64
+ fm.set(folder, []);
65
+ fm.get(folder).push({ name: parts[parts.length - 1], filepath: fp, value: Math.max(stats.totalChanges, 1), score, changes: stats.totalChanges, authors: stats.uniqueAuthors.size, lastTouched: last });
66
+ }
67
+ return { name: result.repoName, children: Array.from(fm.entries()).map(([f, files]) => ({ name: f, children: files })) };
67
68
  }
68
69
  function generateHtmlReport(result, outputPath) {
69
70
  const from = result.dateRange.from.toISOString().split('T')[0];
70
71
  const to = result.dateRange.to.toISOString().split('T')[0];
71
- const cursedRows = result.cursedFiles.slice(0, 20).map((f, i) => `
72
- <tr>
73
- <td class="rank">${i + 1}</td>
74
- <td class="filepath" title="${escapeHtml(f.filepath)}">${escapeHtml(f.filepath)}</td>
75
- <td><span class="badge" style="background:${scoreColor(f.curseScore)}">${f.curseScore.toFixed(1)}</span></td>
76
- <td>${f.totalChanges}</td>
77
- <td>${f.uniqueAuthors}</td>
78
- <td class="muted">${escapeHtml(f.reasons.join(', '))}</td>
79
- </tr>`).join('');
80
- const busRows = result.busFactor.map((b) => `
81
- <tr>
82
- <td>${escapeHtml(b.scope)}</td>
83
- <td><span class="badge" style="background:${busColor(b.busFactor)}">${b.busFactor}</span></td>
84
- <td>${b.filesAtRisk}</td>
85
- <td>${escapeHtml(b.atRiskAuthors.slice(0, 3).join(', '))}</td>
86
- <td class="muted">${escapeHtml(b.warning.replace(/[⚠️⚡✓]/gu, ''))}</td>
87
- </tr>`).join('');
88
- const ownerRows = result.ownership
89
- .filter((o) => o.ownershipPercent >= 60)
90
- .slice(0, 20)
91
- .map((o) => `
92
- <tr>
93
- <td class="filepath" title="${escapeHtml(o.filepath)}">${escapeHtml(o.filepath)}</td>
94
- <td>${escapeHtml(o.owner)}</td>
95
- <td><span class="badge" style="background:${pctColor(o.ownershipPercent)}">${o.ownershipPercent}%</span></td>
96
- <td class="muted">${o.contributors.slice(1, 3).map(c => escapeHtml(`${c.name} (${c.percent}%)`)).join(', ') || '—'}</td>
97
- </tr>`).join('');
98
- const couplingRows = result.coupling.slice(0, 15).map((c) => `
99
- <tr>
100
- <td class="filepath" title="${escapeHtml(c.fileA)}">${escapeHtml(c.fileA)}</td>
101
- <td class="filepath" title="${escapeHtml(c.fileB)}">${escapeHtml(c.fileB)}</td>
102
- <td>${c.coChanges}</td>
103
- <td><span class="badge" style="background:${scoreColor(c.couplingScore * 8)}">${c.couplingScore}%</span></td>
104
- </tr>`).join('');
72
+ const maxS = result.cursedFiles[0]?.curseScore ?? 1;
73
+ const treeJSON = JSON.stringify(buildTree(result));
74
+ const cursedRows = result.cursedFiles.slice(0, 20).map((f, i) => {
75
+ const c = col(f.curseScore, maxS);
76
+ const stats = result.fileStats.get(f.filepath);
77
+ const last = stats ? new Date(stats.lastChanged * 1000).toISOString().split('T')[0] : '—';
78
+ return `<tr onclick="hl('${esc(f.filepath)}')" style="cursor:pointer">
79
+ <td style="color:#64748b;width:32px">${i + 1}</td>
80
+ <td style="font-family:monospace;font-size:12px">${esc(f.filepath)}</td>
81
+ <td><span style="background:${c};color:#000;padding:2px 10px;border-radius:20px;font-size:12px;font-weight:700">${f.curseScore.toFixed(0)}</span></td>
82
+ <td style="color:#94a3b8">${f.totalChanges}</td>
83
+ <td style="color:#94a3b8">${f.uniqueAuthors}</td>
84
+ <td style="color:#64748b;font-size:12px">${last}</td>
85
+ </tr>`;
86
+ }).join('');
87
+ const busRows = result.busFactor.map(b => {
88
+ const bc = b.busFactor === 1 ? '#ef4444' : b.busFactor === 2 ? '#f97316' : '#22c55e';
89
+ const icon = b.busFactor === 1 ? '⚠' : b.busFactor === 2 ? '⚡' : '✓';
90
+ return `<tr>
91
+ <td style="font-family:monospace;font-size:12px">${esc(b.scope)}</td>
92
+ <td><span style="background:${bc};color:#000;padding:2px 10px;border-radius:20px;font-weight:700">${icon} ${b.busFactor}</span></td>
93
+ <td style="color:#94a3b8">${b.filesAtRisk}</td>
94
+ <td style="color:#94a3b8;font-size:12px">${esc(b.atRiskAuthors.slice(0, 2).join(', '))}</td>
95
+ </tr>`;
96
+ }).join('');
97
+ const couplingRows = result.coupling.slice(0, 15).map(c2 => {
98
+ const cc = c2.couplingScore >= 80 ? '#ef4444' : c2.couplingScore >= 50 ? '#f97316' : '#eab308';
99
+ return `<tr>
100
+ <td style="font-family:monospace;font-size:11px">${esc(c2.fileA)}</td>
101
+ <td style="color:#475569;text-align:center;padding:0 8px">↔</td>
102
+ <td style="font-family:monospace;font-size:11px">${esc(c2.fileB)}</td>
103
+ <td><span style="background:${cc};color:#000;padding:2px 10px;border-radius:20px;font-weight:600">${c2.couplingScore}%</span></td>
104
+ </tr>`;
105
+ }).join('');
105
106
  const html = `<!DOCTYPE html>
106
107
  <html lang="en">
107
108
  <head>
108
- <meta charset="UTF-8"/>
109
- <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
110
- <title>⛏ Git Archaeologist — ${escapeHtml(result.repoName)}</title>
111
- <style>
112
- *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
113
- :root {
114
- --bg: #0f1117; --surface: #1a1d27; --border: #2a2d3a;
115
- --text: #e2e8f0; --muted: #64748b; --accent: #a78bfa;
116
- }
117
- body { background: var(--bg); color: var(--text); font-family: 'Inter', system-ui, sans-serif; font-size: 14px; line-height: 1.6; }
118
- header { background: var(--surface); border-bottom: 1px solid var(--border); padding: 24px 40px; display: flex; align-items: center; gap: 16px; }
119
- header h1 { font-size: 20px; font-weight: 600; color: var(--accent); }
120
- header p { color: var(--muted); font-size: 13px; }
121
- .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 16px; padding: 32px 40px 0; }
122
- .stat-card { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 16px 20px; }
123
- .stat-card .label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; margin-bottom: 6px; }
124
- .stat-card .value { font-size: 28px; font-weight: 700; color: var(--accent); }
125
- .stat-card .sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
126
- main { padding: 32px 40px; display: flex; flex-direction: column; gap: 40px; }
127
- section h2 { font-size: 15px; font-weight: 600; color: var(--accent); margin-bottom: 16px; display: flex; align-items: center; gap: 8px; }
128
- table { width: 100%; border-collapse: collapse; background: var(--surface); border-radius: 10px; overflow: hidden; border: 1px solid var(--border); }
129
- th { background: #12151f; color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: .05em; padding: 10px 14px; text-align: left; font-weight: 500; }
130
- td { padding: 10px 14px; border-top: 1px solid var(--border); vertical-align: middle; }
131
- tr:hover td { background: #1e2130; }
132
- .rank { color: var(--muted); font-size: 12px; width: 40px; }
133
- .filepath { font-family: 'JetBrains Mono', 'Fira Code', monospace; font-size: 12px; max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
134
- .muted { color: var(--muted); font-size: 12px; }
135
- .badge { display: inline-block; padding: 2px 10px; border-radius: 20px; font-size: 12px; font-weight: 600; color: #0f1117; }
136
- footer { text-align: center; padding: 32px; color: var(--muted); font-size: 12px; border-top: 1px solid var(--border); }
137
- </style>
109
+ <meta charset="UTF-8"/>
110
+ <meta name="viewport" content="width=device-width,initial-scale=1"/>
111
+ <title>⛏ ${esc(result.repoName)} — Git Archaeologist</title>
112
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"><\/script>
113
+ <style>
114
+ *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
115
+ :root{--bg:#0a0d14;--s1:#111520;--s2:#161b28;--bd:#1e2535;--tx:#e2e8f0;--mu:#64748b;--ac:#a78bfa}
116
+ body{background:var(--bg);color:var(--tx);font-family:Inter,system-ui,sans-serif;font-size:14px;line-height:1.6}
117
+ header{background:var(--s1);border-bottom:1px solid var(--bd);padding:18px 32px;display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:100}
118
+ header h1{font-size:18px;font-weight:700;color:var(--ac)}
119
+ header p{font-size:12px;color:var(--mu);margin-top:2px}
120
+ .legend{font-size:12px;color:var(--mu);display:flex;gap:12px;align-items:center}
121
+ .legend span{display:flex;align-items:center;gap:4px}
122
+ .dot{width:10px;height:10px;border-radius:50%;display:inline-block}
123
+ .stats{display:grid;grid-template-columns:repeat(6,1fr);gap:12px;padding:24px 32px 0}
124
+ .stat{background:var(--s1);border:1px solid var(--bd);border-radius:12px;padding:16px;text-align:center}
125
+ .stat .n{font-size:30px;font-weight:800;color:var(--ac);letter-spacing:-0.03em}
126
+ .stat .l{font-size:11px;color:var(--mu);text-transform:uppercase;letter-spacing:.06em;margin-top:4px}
127
+ .stat.d .n{color:#ef4444}
128
+ .tm-wrap{padding:20px 32px}
129
+ .tm-wrap h2{font-size:12px;font-weight:600;color:var(--mu);text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px}
130
+ #tm{width:100%;height:500px;background:var(--s1);border:1px solid var(--bd);border-radius:12px;overflow:hidden}
131
+ #tip{position:fixed;background:rgba(10,13,20,.97);border:1px solid var(--bd);border-radius:10px;padding:12px 16px;pointer-events:none;font-size:12px;z-index:999;max-width:300px;display:none;box-shadow:0 8px 32px rgba(0,0,0,.5)}
132
+ .tn{font-family:monospace;font-weight:600;color:var(--ac);margin-bottom:8px;word-break:break-all;font-size:11px}
133
+ .tr{display:flex;justify-content:space-between;gap:20px;color:var(--mu);margin-top:3px}
134
+ .tr span:last-child{color:var(--tx);font-weight:500}
135
+ .tables{display:grid;grid-template-columns:1fr 1fr;gap:16px;padding:20px 32px 32px}
136
+ .full{grid-column:1/-1}
137
+ .card{background:var(--s1);border:1px solid var(--bd);border-radius:12px;overflow:hidden}
138
+ .ch{padding:14px 20px;border-bottom:1px solid var(--bd);font-size:13px;font-weight:600;color:var(--ac)}
139
+ table{width:100%;border-collapse:collapse}
140
+ th{padding:9px 20px;text-align:left;font-size:11px;font-weight:500;color:var(--mu);text-transform:uppercase;letter-spacing:.06em;background:var(--s2)}
141
+ td{padding:10px 20px;border-top:1px solid var(--bd);vertical-align:middle}
142
+ tr:hover td{background:rgba(167,139,250,.04)}
143
+ footer{text-align:center;padding:24px;color:var(--mu);font-size:12px;border-top:1px solid var(--bd)}
144
+ footer a{color:var(--ac);text-decoration:none}
145
+ @media(max-width:900px){.stats{grid-template-columns:repeat(3,1fr)}.tables{grid-template-columns:1fr}}
146
+ </style>
138
147
  </head>
139
148
  <body>
140
- <header>
141
- <div>
142
- <h1>⛏ Git Archaeologist</h1>
143
- <p>${escapeHtml(result.repoName)} &nbsp;·&nbsp; ${result.totalCommits.toLocaleString()} commits &nbsp;·&nbsp; ${from} → ${to} &nbsp;·&nbsp; analyzed ${result.analyzedAt.toLocaleString()}</p>
144
- </div>
145
- </header>
146
-
147
- <div class="stats-grid">
148
- <div class="stat-card"><div class="label">Total Commits</div><div class="value">${result.totalCommits.toLocaleString()}</div></div>
149
- <div class="stat-card"><div class="label">Files Tracked</div><div class="value">${result.totalFiles.toLocaleString()}</div></div>
150
- <div class="stat-card"><div class="label">Contributors</div><div class="value">${result.totalAuthors.toLocaleString()}</div></div>
151
- <div class="stat-card"><div class="label">Cursed Files</div><div class="value" style="color:#f87171">${result.cursedFiles.length}</div><div class="sub">top instability</div></div>
152
- <div class="stat-card"><div class="label">Bus Factor 1</div><div class="value" style="color:#f87171">${result.busFactor.filter(b => b.busFactor === 1).length}</div><div class="sub">single-owner modules</div></div>
153
- <div class="stat-card"><div class="label">Coupled Pairs</div><div class="value" style="color:#fbbf24">${result.coupling.length}</div><div class="sub">implicit links</div></div>
149
+ <header>
150
+ <div>
151
+ <h1>⛏ Git Archaeologist</h1>
152
+ <p>${esc(result.repoName)} · ${result.totalCommits.toLocaleString()} commits · ${from} → ${to} · analyzed ${result.analyzedAt.toLocaleString()}</p>
153
+ </div>
154
+ <div class="legend">
155
+ <span><i class="dot" style="background:#ef4444"></i>Critical</span>
156
+ <span><i class="dot" style="background:#f97316"></i>High</span>
157
+ <span><i class="dot" style="background:#eab308"></i>Medium</span>
158
+ <span><i class="dot" style="background:#22c55e"></i>Low</span>
159
+ <span><i class="dot" style="background:#3b82f6"></i>Safe</span>
154
160
  </div>
155
-
156
- <main>
157
- <section>
158
- <h2>💀 Cursed Files — highest instability score</h2>
159
- <table>
160
- <thead><tr><th>#</th><th>File</th><th>Score</th><th>Changes</th><th>Authors</th><th>Why</th></tr></thead>
161
- <tbody>${cursedRows}</tbody>
162
- </table>
163
- </section>
164
-
165
- <section>
166
- <h2>🚌 Bus Factor — single points of failure</h2>
167
- <table>
168
- <thead><tr><th>Module</th><th>Bus Factor</th><th>Files</th><th>Key People</th><th>Risk</th></tr></thead>
169
- <tbody>${busRows}</tbody>
170
- </table>
171
- </section>
172
-
173
- <section>
174
- <h2>👑 Ownership — who truly owns each file</h2>
175
- <table>
176
- <thead><tr><th>File</th><th>Owner</th><th>Ownership</th><th>Other Contributors</th></tr></thead>
177
- <tbody>${ownerRows}</tbody>
178
- </table>
179
- </section>
180
-
181
- <section>
182
- <h2>🔗 Implicit Coupling — files that always change together</h2>
183
- <table>
184
- <thead><tr><th>File A</th><th>File B</th><th>Co-changes</th><th>Coupling</th></tr></thead>
185
- <tbody>${couplingRows}</tbody>
186
- </table>
187
- </section>
188
- </main>
189
- <footer>Generated by ⛏ Git Archaeologist</footer>
161
+ </header>
162
+ <div class="stats">
163
+ <div class="stat"><div class="n">${result.totalCommits.toLocaleString()}</div><div class="l">Commits</div></div>
164
+ <div class="stat"><div class="n">${result.totalFiles.toLocaleString()}</div><div class="l">Files</div></div>
165
+ <div class="stat"><div class="n">${result.totalAuthors.toLocaleString()}</div><div class="l">Authors</div></div>
166
+ <div class="stat d"><div class="n">${result.cursedFiles.length}</div><div class="l">Cursed Files</div></div>
167
+ <div class="stat d"><div class="n">${result.busFactor.filter((b) => b.busFactor === 1).length}</div><div class="l">Bus Factor 1</div></div>
168
+ <div class="stat d"><div class="n">${result.coupling.length}</div><div class="l">Coupled Pairs</div></div>
169
+ </div>
170
+ <div class="tm-wrap">
171
+ <h2>🗺 Codebase Risk Map — size = commit frequency · color = curse score</h2>
172
+ <div id="tm"></div>
173
+ </div>
174
+ <div id="tip">
175
+ <div class="tn" id="tt-fp"></div>
176
+ <div class="tr"><span>Curse score</span><span id="tt-sc"></span></div>
177
+ <div class="tr"><span>Changes</span><span id="tt-ch"></span></div>
178
+ <div class="tr"><span>Authors</span><span id="tt-au"></span></div>
179
+ <div class="tr"><span>Last touched</span><span id="tt-lt"></span></div>
180
+ </div>
181
+ <div class="tables">
182
+ <div class="card full"><div class="ch">💀 Cursed Files — highest instability score</div>
183
+ <table><thead><tr><th>#</th><th>File</th><th>Score</th><th>Changes</th><th>Authors</th><th>Last touched</th></tr></thead>
184
+ <tbody>${cursedRows}</tbody></table></div>
185
+ <div class="card"><div class="ch">🚌 Bus Factor — single points of failure</div>
186
+ <table><thead><tr><th>Module</th><th>Factor</th><th>Files</th><th>Key people</th></tr></thead>
187
+ <tbody>${busRows}</tbody></table></div>
188
+ <div class="card"><div class="ch">🔗 Implicit Coupling</div>
189
+ <table><thead><tr><th>File A</th><th></th><th>File B</th><th>Score</th></tr></thead>
190
+ <tbody>${couplingRows}</tbody></table></div>
191
+ </div>
192
+ <footer>Generated by <a href="https://github.com/SushantVerma7969/git-archaeologist">⛏ git-archaeologist</a> · <a href="https://www.npmjs.com/package/git-archaeologist">npm</a></footer>
193
+ <script>
194
+ const DATA=${treeJSON};
195
+ const MAX=${maxS};
196
+ function sc(s){const r=Math.min(s/Math.max(MAX,1),1);if(r>.7)return"#ef4444";if(r>.4)return"#f97316";if(r>.2)return"#eab308";if(r>.05)return"#22c55e";return"#3b82f6";}
197
+ function dk(h,a){const n=parseInt(h.slice(1),16);return"#"+[Math.max(0,(n>>16)-a),Math.max(0,((n>>8)&255)-a),Math.max(0,(n&255)-a)].map(v=>v.toString(16).padStart(2,"0")).join("");}
198
+ const el=document.getElementById("tm");
199
+ const W=el.clientWidth,H=el.clientHeight;
200
+ const svg=d3.select("#tm").append("svg").attr("width",W).attr("height",H);
201
+ const root=d3.hierarchy(DATA).sum(d=>d.value||0).sort((a,b)=>(b.value||0)-(a.value||0));
202
+ d3.treemap().size([W,H]).padding(2).paddingTop(22).round(true)(root);
203
+ const tip=document.getElementById("tip");
204
+ function show(e,d){
205
+ if(!d.data.filepath)return;
206
+ document.getElementById("tt-fp").textContent=d.data.filepath;
207
+ document.getElementById("tt-sc").textContent=d.data.score?d.data.score.toFixed(1):"—";
208
+ document.getElementById("tt-ch").textContent=d.data.changes||"—";
209
+ document.getElementById("tt-au").textContent=d.data.authors||"—";
210
+ document.getElementById("tt-lt").textContent=d.data.lastTouched||"—";
211
+ tip.style.display="block";mv(e);
212
+ }
213
+ function mv(e){
214
+ const x=e.clientX+16,y=e.clientY-10;
215
+ const tw=tip.offsetWidth,th=tip.offsetHeight;
216
+ tip.style.left=(x+tw>window.innerWidth?x-tw-32:x)+"px";
217
+ tip.style.top=(y+th>window.innerHeight?y-th:y)+"px";
218
+ }
219
+ svg.selectAll("g.fd").data(root.children||[]).join("g").attr("class","fd").call(g=>{
220
+ g.append("rect").attr("x",d=>d.x0).attr("y",d=>d.y0).attr("width",d=>d.x1-d.x0).attr("height",d=>d.y1-d.y0).attr("fill","none").attr("stroke","#1e2535").attr("stroke-width",1);
221
+ g.append("text").attr("x",d=>d.x0+6).attr("y",d=>d.y0+15).attr("fill","#64748b").attr("font-size","11px").attr("font-weight","600").attr("font-family","monospace").text(d=>d.data.name);
222
+ });
223
+ const lv=svg.selectAll("g.lf").data(root.leaves()).join("g").attr("class","lf");
224
+ lv.append("rect")
225
+ .attr("x",d=>d.x0+1).attr("y",d=>d.y0+1)
226
+ .attr("width",d=>Math.max(0,d.x1-d.x0-2)).attr("height",d=>Math.max(0,d.y1-d.y0-2))
227
+ .attr("rx",3).attr("fill",d=>sc(d.data.score||0)).attr("fill-opacity",.82)
228
+ .attr("stroke",d=>dk(sc(d.data.score||0),40)).attr("stroke-width",.5)
229
+ .style("cursor","pointer")
230
+ .on("mouseenter",function(e,d){d3.select(this).attr("fill-opacity",1).attr("stroke-width",2);show(e,d);})
231
+ .on("mousemove",mv)
232
+ .on("mouseleave",function(){d3.select(this).attr("fill-opacity",.82).attr("stroke-width",.5);tip.style.display="none";});
233
+ lv.filter(d=>(d.x1-d.x0)>55&&(d.y1-d.y0)>22).append("text")
234
+ .attr("x",d=>d.x0+5).attr("y",d=>d.y0+14)
235
+ .attr("fill","rgba(0,0,0,.85)").attr("font-size","10px").attr("font-family","monospace").attr("pointer-events","none")
236
+ .text(d=>{const nm=d.data.name;const mx=Math.floor((d.x1-d.x0-10)/6);return nm.length>mx?nm.slice(0,mx-1)+"…":nm;});
237
+ window.hl=function(fp){
238
+ lv.selectAll("rect").attr("stroke-width",d=>d.data.filepath===fp?3:.5).attr("stroke",d=>d.data.filepath===fp?"#fff":dk(sc(d.data.score||0),40)).attr("fill-opacity",d=>d.data.filepath===fp?1:.82);
239
+ const node=root.leaves().find(d=>d.data.filepath===fp);
240
+ if(node){const cx=(node.x0+node.x1)/2,cy=(node.y0+node.y1)/2;svg.transition().duration(400);}
241
+ };
242
+ <\/script>
190
243
  </body>
191
244
  </html>`;
192
245
  fs.writeFileSync(outputPath, html, 'utf8');
@@ -1 +1 @@
1
- {"version":3,"file":"htmlReport.js","sourceRoot":"","sources":["../../src/output/htmlReport.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"htmlReport.js","sourceRoot":"","sources":["../../src/output/htmlReport.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-archaeologist",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Uncover the hidden history, ownership, and tech debt in any git repository",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -43,4 +43,4 @@
43
43
  "engines": {
44
44
  "node": ">=18"
45
45
  }
46
- }
46
+ }