@vyuhlabs/dxkit 1.5.0 → 1.6.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 (258) hide show
  1. package/CHANGELOG.md +272 -0
  2. package/README.md +272 -358
  3. package/THIRD_PARTY_NOTICES.md +40 -0
  4. package/dist/analyzers/developer/detailed.d.ts +26 -0
  5. package/dist/analyzers/developer/detailed.d.ts.map +1 -0
  6. package/dist/analyzers/developer/detailed.js +193 -0
  7. package/dist/analyzers/developer/detailed.js.map +1 -0
  8. package/dist/analyzers/developer/gather.d.ts +11 -0
  9. package/dist/analyzers/developer/gather.d.ts.map +1 -0
  10. package/dist/analyzers/developer/gather.js +167 -0
  11. package/dist/analyzers/developer/gather.js.map +1 -0
  12. package/dist/analyzers/developer/index.d.ts +8 -0
  13. package/dist/analyzers/developer/index.d.ts.map +1 -0
  14. package/dist/analyzers/developer/index.js +168 -0
  15. package/dist/analyzers/developer/index.js.map +1 -0
  16. package/dist/analyzers/developer/types.d.ts +49 -0
  17. package/dist/analyzers/developer/types.d.ts.map +1 -0
  18. package/dist/analyzers/developer/types.js +6 -0
  19. package/dist/analyzers/developer/types.js.map +1 -0
  20. package/dist/analyzers/docs/shallow.d.ts +9 -0
  21. package/dist/analyzers/docs/shallow.d.ts.map +1 -0
  22. package/dist/analyzers/docs/shallow.js +8 -0
  23. package/dist/analyzers/docs/shallow.js.map +1 -0
  24. package/dist/analyzers/dx/shallow.d.ts +9 -0
  25. package/dist/analyzers/dx/shallow.d.ts.map +1 -0
  26. package/dist/analyzers/dx/shallow.js +8 -0
  27. package/dist/analyzers/dx/shallow.js.map +1 -0
  28. package/dist/analyzers/evidence.d.ts +36 -0
  29. package/dist/analyzers/evidence.d.ts.map +1 -0
  30. package/dist/analyzers/evidence.js +3 -0
  31. package/dist/analyzers/evidence.js.map +1 -0
  32. package/dist/analyzers/health/actions.d.ts +10 -0
  33. package/dist/analyzers/health/actions.d.ts.map +1 -0
  34. package/dist/analyzers/health/actions.js +284 -0
  35. package/dist/analyzers/health/actions.js.map +1 -0
  36. package/dist/analyzers/health/detailed.d.ts +26 -0
  37. package/dist/analyzers/health/detailed.d.ts.map +1 -0
  38. package/dist/analyzers/health/detailed.js +147 -0
  39. package/dist/analyzers/health/detailed.js.map +1 -0
  40. package/dist/analyzers/health.d.ts +22 -0
  41. package/dist/analyzers/health.d.ts.map +1 -0
  42. package/dist/analyzers/health.js +270 -0
  43. package/dist/analyzers/health.js.map +1 -0
  44. package/dist/analyzers/index.d.ts +3 -0
  45. package/dist/analyzers/index.d.ts.map +1 -0
  46. package/dist/analyzers/index.js +6 -0
  47. package/dist/analyzers/index.js.map +1 -0
  48. package/dist/analyzers/maintainability/shallow.d.ts +9 -0
  49. package/dist/analyzers/maintainability/shallow.d.ts.map +1 -0
  50. package/dist/analyzers/maintainability/shallow.js +8 -0
  51. package/dist/analyzers/maintainability/shallow.js.map +1 -0
  52. package/dist/analyzers/quality/actions.d.ts +5 -0
  53. package/dist/analyzers/quality/actions.d.ts.map +1 -0
  54. package/dist/analyzers/quality/actions.js +158 -0
  55. package/dist/analyzers/quality/actions.js.map +1 -0
  56. package/dist/analyzers/quality/detailed.d.ts +17 -0
  57. package/dist/analyzers/quality/detailed.d.ts.map +1 -0
  58. package/dist/analyzers/quality/detailed.js +122 -0
  59. package/dist/analyzers/quality/detailed.js.map +1 -0
  60. package/dist/analyzers/quality/gather.d.ts +38 -0
  61. package/dist/analyzers/quality/gather.d.ts.map +1 -0
  62. package/dist/analyzers/quality/gather.js +279 -0
  63. package/dist/analyzers/quality/gather.js.map +1 -0
  64. package/dist/analyzers/quality/index.d.ts +12 -0
  65. package/dist/analyzers/quality/index.d.ts.map +1 -0
  66. package/dist/analyzers/quality/index.js +281 -0
  67. package/dist/analyzers/quality/index.js.map +1 -0
  68. package/dist/analyzers/quality/shallow.d.ts +9 -0
  69. package/dist/analyzers/quality/shallow.d.ts.map +1 -0
  70. package/dist/analyzers/quality/shallow.js +8 -0
  71. package/dist/analyzers/quality/shallow.js.map +1 -0
  72. package/dist/analyzers/quality/types.d.ts +66 -0
  73. package/dist/analyzers/quality/types.d.ts.map +1 -0
  74. package/dist/analyzers/quality/types.js +3 -0
  75. package/dist/analyzers/quality/types.js.map +1 -0
  76. package/dist/analyzers/remediation.d.ts +42 -0
  77. package/dist/analyzers/remediation.d.ts.map +1 -0
  78. package/dist/analyzers/remediation.js +28 -0
  79. package/dist/analyzers/remediation.js.map +1 -0
  80. package/dist/analyzers/scoring.d.ts +32 -0
  81. package/dist/analyzers/scoring.d.ts.map +1 -0
  82. package/dist/analyzers/scoring.js +410 -0
  83. package/dist/analyzers/scoring.js.map +1 -0
  84. package/dist/analyzers/security/actions.d.ts +7 -0
  85. package/dist/analyzers/security/actions.d.ts.map +1 -0
  86. package/dist/analyzers/security/actions.js +104 -0
  87. package/dist/analyzers/security/actions.js.map +1 -0
  88. package/dist/analyzers/security/detailed.d.ts +14 -0
  89. package/dist/analyzers/security/detailed.d.ts.map +1 -0
  90. package/dist/analyzers/security/detailed.js +124 -0
  91. package/dist/analyzers/security/detailed.js.map +1 -0
  92. package/dist/analyzers/security/gather.d.ts +12 -0
  93. package/dist/analyzers/security/gather.d.ts.map +1 -0
  94. package/dist/analyzers/security/gather.js +195 -0
  95. package/dist/analyzers/security/gather.js.map +1 -0
  96. package/dist/analyzers/security/index.d.ts +8 -0
  97. package/dist/analyzers/security/index.d.ts.map +1 -0
  98. package/dist/analyzers/security/index.js +173 -0
  99. package/dist/analyzers/security/index.js.map +1 -0
  100. package/dist/analyzers/security/scoring.d.ts +29 -0
  101. package/dist/analyzers/security/scoring.d.ts.map +1 -0
  102. package/dist/analyzers/security/scoring.js +40 -0
  103. package/dist/analyzers/security/scoring.js.map +1 -0
  104. package/dist/analyzers/security/shallow.d.ts +10 -0
  105. package/dist/analyzers/security/shallow.d.ts.map +1 -0
  106. package/dist/analyzers/security/shallow.js +8 -0
  107. package/dist/analyzers/security/shallow.js.map +1 -0
  108. package/dist/analyzers/security/types.d.ts +43 -0
  109. package/dist/analyzers/security/types.d.ts.map +1 -0
  110. package/dist/analyzers/security/types.js +6 -0
  111. package/dist/analyzers/security/types.js.map +1 -0
  112. package/dist/analyzers/tests/actions.d.ts +6 -0
  113. package/dist/analyzers/tests/actions.d.ts.map +1 -0
  114. package/dist/analyzers/tests/actions.js +80 -0
  115. package/dist/analyzers/tests/actions.js.map +1 -0
  116. package/dist/analyzers/tests/detailed.d.ts +14 -0
  117. package/dist/analyzers/tests/detailed.d.ts.map +1 -0
  118. package/dist/analyzers/tests/detailed.js +121 -0
  119. package/dist/analyzers/tests/detailed.js.map +1 -0
  120. package/dist/analyzers/tests/gather.d.ts +5 -0
  121. package/dist/analyzers/tests/gather.d.ts.map +1 -0
  122. package/dist/analyzers/tests/gather.js +270 -0
  123. package/dist/analyzers/tests/gather.js.map +1 -0
  124. package/dist/analyzers/tests/import-graph.d.ts +48 -0
  125. package/dist/analyzers/tests/import-graph.d.ts.map +1 -0
  126. package/dist/analyzers/tests/import-graph.js +231 -0
  127. package/dist/analyzers/tests/import-graph.js.map +1 -0
  128. package/dist/analyzers/tests/index.d.ts +8 -0
  129. package/dist/analyzers/tests/index.d.ts.map +1 -0
  130. package/dist/analyzers/tests/index.js +247 -0
  131. package/dist/analyzers/tests/index.js.map +1 -0
  132. package/dist/analyzers/tests/scoring.d.ts +27 -0
  133. package/dist/analyzers/tests/scoring.d.ts.map +1 -0
  134. package/dist/analyzers/tests/scoring.js +38 -0
  135. package/dist/analyzers/tests/scoring.js.map +1 -0
  136. package/dist/analyzers/tests/shallow.d.ts +9 -0
  137. package/dist/analyzers/tests/shallow.d.ts.map +1 -0
  138. package/dist/analyzers/tests/shallow.js +8 -0
  139. package/dist/analyzers/tests/shallow.js.map +1 -0
  140. package/dist/analyzers/tests/types.d.ts +49 -0
  141. package/dist/analyzers/tests/types.d.ts.map +1 -0
  142. package/dist/analyzers/tests/types.js +6 -0
  143. package/dist/analyzers/tests/types.js.map +1 -0
  144. package/dist/analyzers/tools/cloc.d.ts +8 -0
  145. package/dist/analyzers/tools/cloc.d.ts.map +1 -0
  146. package/dist/analyzers/tools/cloc.js +49 -0
  147. package/dist/analyzers/tools/cloc.js.map +1 -0
  148. package/dist/analyzers/tools/coverage.d.ts +59 -0
  149. package/dist/analyzers/tools/coverage.d.ts.map +1 -0
  150. package/dist/analyzers/tools/coverage.js +280 -0
  151. package/dist/analyzers/tools/coverage.js.map +1 -0
  152. package/dist/analyzers/tools/cvss-v4-lookup.d.ts +10 -0
  153. package/dist/analyzers/tools/cvss-v4-lookup.d.ts.map +1 -0
  154. package/dist/analyzers/tools/cvss-v4-lookup.js +284 -0
  155. package/dist/analyzers/tools/cvss-v4-lookup.js.map +1 -0
  156. package/dist/analyzers/tools/cvss-v4.d.ts +24 -0
  157. package/dist/analyzers/tools/cvss-v4.d.ts.map +1 -0
  158. package/dist/analyzers/tools/cvss-v4.js +362 -0
  159. package/dist/analyzers/tools/cvss-v4.js.map +1 -0
  160. package/dist/analyzers/tools/default-exclusions.gitignore +56 -0
  161. package/dist/analyzers/tools/exclusions.d.ts +70 -0
  162. package/dist/analyzers/tools/exclusions.d.ts.map +1 -0
  163. package/dist/analyzers/tools/exclusions.js +250 -0
  164. package/dist/analyzers/tools/exclusions.js.map +1 -0
  165. package/dist/analyzers/tools/generic.d.ts +4 -0
  166. package/dist/analyzers/tools/generic.d.ts.map +1 -0
  167. package/dist/analyzers/tools/generic.js +198 -0
  168. package/dist/analyzers/tools/generic.js.map +1 -0
  169. package/dist/analyzers/tools/gitleaks.d.ts +8 -0
  170. package/dist/analyzers/tools/gitleaks.d.ts.map +1 -0
  171. package/dist/analyzers/tools/gitleaks.js +58 -0
  172. package/dist/analyzers/tools/gitleaks.js.map +1 -0
  173. package/dist/analyzers/tools/graphify.d.ts +4 -0
  174. package/dist/analyzers/tools/graphify.d.ts.map +1 -0
  175. package/dist/analyzers/tools/graphify.js +222 -0
  176. package/dist/analyzers/tools/graphify.js.map +1 -0
  177. package/dist/analyzers/tools/osv.d.ts +51 -0
  178. package/dist/analyzers/tools/osv.d.ts.map +1 -0
  179. package/dist/analyzers/tools/osv.js +188 -0
  180. package/dist/analyzers/tools/osv.js.map +1 -0
  181. package/dist/analyzers/tools/parallel.d.ts +8 -0
  182. package/dist/analyzers/tools/parallel.d.ts.map +1 -0
  183. package/dist/analyzers/tools/parallel.js +195 -0
  184. package/dist/analyzers/tools/parallel.js.map +1 -0
  185. package/dist/analyzers/tools/runner.d.ts +13 -0
  186. package/dist/analyzers/tools/runner.d.ts.map +1 -0
  187. package/dist/analyzers/tools/runner.js +109 -0
  188. package/dist/analyzers/tools/runner.js.map +1 -0
  189. package/dist/analyzers/tools/suppressions.d.ts +55 -0
  190. package/dist/analyzers/tools/suppressions.d.ts.map +1 -0
  191. package/dist/analyzers/tools/suppressions.js +203 -0
  192. package/dist/analyzers/tools/suppressions.js.map +1 -0
  193. package/dist/analyzers/tools/timing.d.ts +9 -0
  194. package/dist/analyzers/tools/timing.d.ts.map +1 -0
  195. package/dist/analyzers/tools/timing.js +29 -0
  196. package/dist/analyzers/tools/timing.js.map +1 -0
  197. package/dist/analyzers/tools/tool-registry.d.ts +86 -0
  198. package/dist/analyzers/tools/tool-registry.d.ts.map +1 -0
  199. package/dist/analyzers/tools/tool-registry.js +705 -0
  200. package/dist/analyzers/tools/tool-registry.js.map +1 -0
  201. package/dist/analyzers/types.d.ts +125 -0
  202. package/dist/analyzers/types.d.ts.map +1 -0
  203. package/dist/analyzers/types.js +11 -0
  204. package/dist/analyzers/types.js.map +1 -0
  205. package/dist/cli.d.ts.map +1 -1
  206. package/dist/cli.js +462 -0
  207. package/dist/cli.js.map +1 -1
  208. package/dist/detect.d.ts.map +1 -1
  209. package/dist/detect.js +24 -15
  210. package/dist/detect.js.map +1 -1
  211. package/dist/languages/csharp.d.ts +5 -0
  212. package/dist/languages/csharp.d.ts.map +1 -0
  213. package/dist/languages/csharp.js +265 -0
  214. package/dist/languages/csharp.js.map +1 -0
  215. package/dist/languages/go.d.ts +11 -0
  216. package/dist/languages/go.d.ts.map +1 -0
  217. package/dist/languages/go.js +321 -0
  218. package/dist/languages/go.js.map +1 -0
  219. package/dist/languages/index.d.ts +6 -0
  220. package/dist/languages/index.d.ts.map +1 -0
  221. package/dist/languages/index.js +18 -0
  222. package/dist/languages/index.js.map +1 -0
  223. package/dist/languages/python.d.ts +3 -0
  224. package/dist/languages/python.d.ts.map +1 -0
  225. package/dist/languages/python.js +284 -0
  226. package/dist/languages/python.js.map +1 -0
  227. package/dist/languages/rust.d.ts +17 -0
  228. package/dist/languages/rust.d.ts.map +1 -0
  229. package/dist/languages/rust.js +333 -0
  230. package/dist/languages/rust.js.map +1 -0
  231. package/dist/languages/types.d.ts +38 -0
  232. package/dist/languages/types.d.ts.map +1 -0
  233. package/dist/languages/types.js +3 -0
  234. package/dist/languages/types.js.map +1 -0
  235. package/dist/languages/typescript.d.ts +15 -0
  236. package/dist/languages/typescript.d.ts.map +1 -0
  237. package/dist/languages/typescript.js +353 -0
  238. package/dist/languages/typescript.js.map +1 -0
  239. package/dist/logger.d.ts +1 -0
  240. package/dist/logger.d.ts.map +1 -1
  241. package/dist/logger.js +25 -12
  242. package/dist/logger.js.map +1 -1
  243. package/dist/project-yaml.d.ts.map +1 -1
  244. package/dist/project-yaml.js +1 -0
  245. package/dist/project-yaml.js.map +1 -1
  246. package/dist/tools-cli.d.ts +2 -0
  247. package/dist/tools-cli.d.ts.map +1 -0
  248. package/dist/tools-cli.js +231 -0
  249. package/dist/tools-cli.js.map +1 -0
  250. package/dist/types.d.ts +10 -0
  251. package/dist/types.d.ts.map +1 -1
  252. package/package.json +6 -2
  253. package/templates/.claude/commands/dev-report.md +34 -4
  254. package/templates/.claude/commands/health.md +45 -2
  255. package/templates/.claude/commands/quality.md.template +38 -15
  256. package/templates/.claude/commands/test-gaps.md +36 -2
  257. package/templates/.claude/commands/vulnerabilities.md +36 -2
  258. package/templates/.project/scripts/setup/interactive-setup.sh +6 -2
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.analyzeDevActivity = analyzeDevActivity;
37
+ exports.formatDevReport = formatDevReport;
38
+ /**
39
+ * Developer activity analyzer — public API.
40
+ * Orthogonal to health (no dimension score).
41
+ */
42
+ const path = __importStar(require("path"));
43
+ const detect_1 = require("../../detect");
44
+ const runner_1 = require("../tools/runner");
45
+ const timing_1 = require("../tools/timing");
46
+ const gather_1 = require("./gather");
47
+ function analyzeDevActivity(repoPath, since, options = {}) {
48
+ const verbose = !!options.verbose;
49
+ const stack = (0, detect_1.detect)(repoPath);
50
+ // Default: last 3 months
51
+ const sinceDate = since || new Date(Date.now() - 90 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
52
+ const summary = (0, timing_1.timed)('summary', verbose, () => (0, gather_1.gatherSummary)(repoPath, sinceDate));
53
+ const contributors = (0, timing_1.timed)('contributors', verbose, () => (0, gather_1.gatherContributors)(repoPath, sinceDate));
54
+ const commitQuality = (0, timing_1.timed)('commit-quality', verbose, () => (0, gather_1.gatherCommitQuality)(repoPath, sinceDate));
55
+ const hotFiles = (0, timing_1.timed)('hot-files', verbose, () => (0, gather_1.gatherHotFiles)(repoPath, sinceDate));
56
+ const velocity = (0, timing_1.timed)('velocity', verbose, () => (0, gather_1.gatherVelocity)(repoPath, sinceDate));
57
+ const nonMerge = summary.totalCommits - summary.mergeCommits;
58
+ const mergeRatio = summary.totalCommits > 0
59
+ ? Math.round((summary.mergeCommits / summary.totalCommits) * 1000) / 1000
60
+ : 0;
61
+ return {
62
+ repo: stack.projectName || path.basename(repoPath),
63
+ analyzedAt: new Date().toISOString(),
64
+ commitSha: (0, runner_1.run)('git rev-parse --short HEAD 2>/dev/null', repoPath),
65
+ branch: (0, runner_1.run)('git rev-parse --abbrev-ref HEAD 2>/dev/null', repoPath),
66
+ period: { since: sinceDate, until: new Date().toISOString().slice(0, 10) },
67
+ summary: {
68
+ totalCommits: summary.totalCommits,
69
+ nonMergeCommits: nonMerge,
70
+ mergeCommits: summary.mergeCommits,
71
+ mergeRatio,
72
+ contributors: contributors.length,
73
+ },
74
+ contributors,
75
+ commitQuality,
76
+ hotFiles,
77
+ velocity,
78
+ toolsUsed: ['git'],
79
+ };
80
+ }
81
+ function formatDevReport(report, elapsed) {
82
+ const L = [];
83
+ L.push('# Developer Activity Report');
84
+ L.push('');
85
+ L.push(`**Date:** ${report.analyzedAt.slice(0, 10)}`);
86
+ L.push(`**Period:** ${report.period.since} to ${report.period.until}`);
87
+ L.push(`**Repository:** ${report.repo}`);
88
+ L.push(`**Branch:** ${report.branch} (${report.commitSha})`);
89
+ L.push('');
90
+ L.push('---');
91
+ L.push('');
92
+ // Executive summary
93
+ const s = report.summary;
94
+ L.push('## Executive Summary');
95
+ L.push('');
96
+ L.push(`**${s.totalCommits} commits** (${s.nonMergeCommits} non-merge, ${s.mergeCommits} merge) ` +
97
+ `from **${s.contributors} contributors**. ` +
98
+ `Merge ratio: ${(s.mergeRatio * 100).toFixed(1)}%. ` +
99
+ `Commit message quality: ${report.commitQuality.conventionalPercent}% conventional.`);
100
+ L.push('');
101
+ L.push('---');
102
+ L.push('');
103
+ // Contributors
104
+ L.push('## 1. Developer Contributions');
105
+ L.push('');
106
+ L.push('| Rank | Developer | Commits | +Lines | -Lines | Net | Merges |');
107
+ L.push('|------|-----------|---------|--------|--------|-----|--------|');
108
+ report.contributors.forEach((c, i) => {
109
+ const total = c.commits + c.mergeCommits;
110
+ L.push(`| ${i + 1} | ${c.name} | ${total} | +${c.linesAdded.toLocaleString()} | -${c.linesRemoved.toLocaleString()} | ${c.netChange >= 0 ? '+' : ''}${c.netChange.toLocaleString()} | ${c.mergeCommits} |`);
111
+ });
112
+ L.push('');
113
+ L.push('---');
114
+ L.push('');
115
+ // Commit quality
116
+ const q = report.commitQuality;
117
+ L.push('## 2. Commit Message Quality');
118
+ L.push('');
119
+ L.push('| Type | Count | % |');
120
+ L.push('|------|-------|---|');
121
+ L.push(`| Conventional (feat:, fix:, etc.) | ${q.conventional} | ${q.conventionalPercent}% |`);
122
+ L.push(`| Descriptive | ${q.descriptive} | ${q.total > 0 ? ((q.descriptive / q.total) * 100).toFixed(1) : 0}% |`);
123
+ L.push(`| Vague | ${q.vague} | ${q.total > 0 ? ((q.vague / q.total) * 100).toFixed(1) : 0}% |`);
124
+ L.push('');
125
+ if (q.conventionalPercent < 10) {
126
+ L.push('> **Poor commit message quality.** Consider adopting [Conventional Commits](https://www.conventionalcommits.org/) for automated changelogs and clearer git history.');
127
+ }
128
+ L.push('');
129
+ L.push('---');
130
+ L.push('');
131
+ // Hot files
132
+ L.push('## 3. Hot Files (Most Changed)');
133
+ L.push('');
134
+ L.push('| File | Changes |');
135
+ L.push('|------|---------|');
136
+ for (const f of report.hotFiles) {
137
+ L.push(`| \`${f.path}\` | ${f.changes} |`);
138
+ }
139
+ L.push('');
140
+ L.push('---');
141
+ L.push('');
142
+ // Velocity
143
+ L.push('## 4. Weekly Velocity');
144
+ L.push('');
145
+ if (report.velocity.length > 0) {
146
+ L.push('| Week | Commits |');
147
+ L.push('|------|---------|');
148
+ for (const v of report.velocity) {
149
+ const bar = '█'.repeat(Math.min(Math.round(v.commits / 2), 30));
150
+ L.push(`| ${v.week} | ${v.commits} ${bar} |`);
151
+ }
152
+ const avgPerWeek = report.velocity.length > 0
153
+ ? Math.round(report.velocity.reduce((sum, v) => sum + v.commits, 0) / report.velocity.length)
154
+ : 0;
155
+ L.push('');
156
+ L.push(`**Average:** ${avgPerWeek} commits/week.`);
157
+ }
158
+ L.push('');
159
+ L.push('---');
160
+ L.push('');
161
+ // Footer
162
+ L.push(`**Tools used:** ${report.toolsUsed.join(', ')}`);
163
+ L.push(`**Analysis time:** ${elapsed}s`);
164
+ L.push('');
165
+ L.push('*Generated by [VyuhLabs DXKit](https://www.npmjs.com/package/@vyuhlabs/dxkit)*');
166
+ return L.join('\n');
167
+ }
168
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzers/developer/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Developer activity report types.
3
+ */
4
+ export interface ContributorStats {
5
+ name: string;
6
+ commits: number;
7
+ linesAdded: number;
8
+ linesRemoved: number;
9
+ netChange: number;
10
+ mergeCommits: number;
11
+ }
12
+ export interface HotFile {
13
+ path: string;
14
+ changes: number;
15
+ }
16
+ export interface CommitQuality {
17
+ conventional: number;
18
+ descriptive: number;
19
+ vague: number;
20
+ total: number;
21
+ conventionalPercent: number;
22
+ }
23
+ export interface WeeklyVelocity {
24
+ week: string;
25
+ commits: number;
26
+ }
27
+ export interface DevReport {
28
+ repo: string;
29
+ analyzedAt: string;
30
+ commitSha: string;
31
+ branch: string;
32
+ period: {
33
+ since: string;
34
+ until: string;
35
+ };
36
+ summary: {
37
+ totalCommits: number;
38
+ nonMergeCommits: number;
39
+ mergeCommits: number;
40
+ mergeRatio: number;
41
+ contributors: number;
42
+ };
43
+ contributors: ContributorStats[];
44
+ commitQuality: CommitQuality;
45
+ hotFiles: HotFile[];
46
+ velocity: WeeklyVelocity[];
47
+ toolsUsed: string[];
48
+ }
49
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/analyzers/developer/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,OAAO,EAAE;QACP,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * Developer activity report types.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/analyzers/developer/types.ts"],"names":[],"mappings":";AAAA;;GAEG"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Documentation dimension — shallow score for health aggregation.
3
+ *
4
+ * Phase 3: delegates to scoring.ts (identical behavior).
5
+ * Future: may expand to include docstring coverage via graphify AST.
6
+ */
7
+ import { HealthMetrics, DimensionScore } from '../types';
8
+ export declare function scoreDocsDimension(m: HealthMetrics): DimensionScore;
9
+ //# sourceMappingURL=shallow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shallow.d.ts","sourceRoot":"","sources":["../../../src/analyzers/docs/shallow.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAGzD,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,aAAa,GAAG,cAAc,CAEnE"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scoreDocsDimension = scoreDocsDimension;
4
+ const scoring_1 = require("../scoring");
5
+ function scoreDocsDimension(m) {
6
+ return (0, scoring_1.scoreDocumentation)(m);
7
+ }
8
+ //# sourceMappingURL=shallow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shallow.js","sourceRoot":"","sources":["../../../src/analyzers/docs/shallow.ts"],"names":[],"mappings":";;AASA,gDAEC;AAJD,wCAAgD;AAEhD,SAAgB,kBAAkB,CAAC,CAAgB;IACjD,OAAO,IAAA,4BAAkB,EAAC,CAAC,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Developer Experience dimension — shallow score for health aggregation.
3
+ *
4
+ * Phase 3: delegates to scoring.ts (identical behavior).
5
+ * Future: may expand with more DX indicators (devcontainer, IDE config, etc).
6
+ */
7
+ import { HealthMetrics, DimensionScore } from '../types';
8
+ export declare function scoreDxDimension(m: HealthMetrics): DimensionScore;
9
+ //# sourceMappingURL=shallow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shallow.d.ts","sourceRoot":"","sources":["../../../src/analyzers/dx/shallow.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAGzD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,aAAa,GAAG,cAAc,CAEjE"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scoreDxDimension = scoreDxDimension;
4
+ const scoring_1 = require("../scoring");
5
+ function scoreDxDimension(m) {
6
+ return (0, scoring_1.scoreDeveloperExperience)(m);
7
+ }
8
+ //# sourceMappingURL=shallow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shallow.js","sourceRoot":"","sources":["../../../src/analyzers/dx/shallow.ts"],"names":[],"mappings":";;AASA,4CAEC;AAJD,wCAAsD;AAEtD,SAAgB,gBAAgB,CAAC,CAAgB;IAC/C,OAAO,IAAA,kCAAwB,EAAC,CAAC,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Generic evidence type used across all analyzers for detailed reports.
3
+ *
4
+ * A piece of evidence points at a specific location in the codebase that
5
+ * motivated a score deduction or remediation action. Tools produce evidence;
6
+ * formatters consume it.
7
+ *
8
+ * Distinct from SecurityFinding (security/types.ts) which adds severity + CWE
9
+ * for the security-specific findings pipeline.
10
+ */
11
+ export interface Evidence {
12
+ /** Relative or absolute file path. */
13
+ file: string;
14
+ /** 1-indexed line number. Omit for file-level findings. */
15
+ line?: number;
16
+ /** Inclusive end line for a range. */
17
+ endLine?: number;
18
+ /** Optional code excerpt for human readers. Truncated to ~200 chars. */
19
+ snippet?: string;
20
+ /** Short stable id for the rule, e.g. "console-log", "god-file". */
21
+ rule: string;
22
+ /** Tool that produced this, e.g. "grep", "graphify", "jscpd". */
23
+ tool: string;
24
+ /** Optional one-line description shown to humans. */
25
+ message?: string;
26
+ }
27
+ /** A ranked list of offenders for a single metric (e.g. top god files). */
28
+ export interface TopOffenders<T> {
29
+ /** Rule id this list is ranked by. */
30
+ rule: string;
31
+ /** Human-readable title for the list ("Files with most functions"). */
32
+ title: string;
33
+ /** Items sorted by severity/size descending. */
34
+ items: T[];
35
+ }
36
+ //# sourceMappingURL=evidence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.d.ts","sourceRoot":"","sources":["../../src/analyzers/evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,QAAQ;IACvB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,2EAA2E;AAC3E,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,KAAK,EAAE,CAAC,EAAE,CAAC;CACZ"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../src/analyzers/evidence.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import { RankedAction } from '../remediation';
2
+ import { HealthMetrics } from '../types';
3
+ export interface DimensionPlan {
4
+ dimension: string;
5
+ baseline: number;
6
+ ideal: number;
7
+ actions: RankedAction<HealthMetrics>[];
8
+ }
9
+ export declare function buildHealthPlans(metrics: HealthMetrics): DimensionPlan[];
10
+ //# sourceMappingURL=actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/analyzers/health/actions.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAA2B,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AA6RzC,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC,aAAa,CAAC,EAAE,CAAC;CACxC;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,EAAE,CA0BxE"}
@@ -0,0 +1,284 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildHealthPlans = buildHealthPlans;
4
+ const remediation_1 = require("../remediation");
5
+ const scoring_1 = require("../scoring");
6
+ // ─── Testing dimension ──────────────────────────────────────────────────────
7
+ function testingActions(m) {
8
+ const actions = [];
9
+ if (m.commentedCodeRatio !== null && m.commentedCodeRatio > 0.5) {
10
+ actions.push({
11
+ id: 'health.testing.restore-commented-tests',
12
+ title: 'Restore commented-out test files',
13
+ rationale: 'High commented-code ratio across test files indicates atrophied tests. See test-gaps-detailed.md.',
14
+ evidence: [],
15
+ patch: (cur) => ({ ...cur, commentedCodeRatio: 0.1 }),
16
+ });
17
+ }
18
+ if (m.testFiles < m.sourceFiles * 0.1 && m.sourceFiles > 0) {
19
+ const target = Math.ceil(m.sourceFiles * 0.2);
20
+ actions.push({
21
+ id: 'health.testing.raise-test-ratio',
22
+ title: `Raise test-to-source ratio (${m.testFiles} tests for ${m.sourceFiles} source files)`,
23
+ rationale: 'Under 10% test-to-source ratio is critical. Start with top CRITICAL untested files — see test-gaps-detailed.md for the ranked list.',
24
+ evidence: [],
25
+ patch: (cur) => ({ ...cur, testFiles: target }),
26
+ });
27
+ }
28
+ if (!m.coverageConfigExists) {
29
+ actions.push({
30
+ id: 'health.testing.add-coverage-config',
31
+ title: 'Add test coverage tooling',
32
+ rationale: 'No coverage config (nyc/c8/jest.coverage/coverage.py). Configure + set threshold.',
33
+ evidence: [],
34
+ patch: (cur) => ({ ...cur, coverageConfigExists: true }),
35
+ });
36
+ }
37
+ return actions;
38
+ }
39
+ // ─── Quality dimension ──────────────────────────────────────────────────────
40
+ function qualityActions(m) {
41
+ const actions = [];
42
+ if (m.consoleLogCount > 20) {
43
+ actions.push({
44
+ id: 'health.quality.remove-console',
45
+ title: `Remove console statements (${m.consoleLogCount})`,
46
+ rationale: 'See quality-review-detailed.md for top offender files.',
47
+ evidence: m.largestFilePath
48
+ ? [{ file: m.largestFilePath, rule: 'console-log', tool: 'grep' }]
49
+ : [],
50
+ patch: (cur) => ({ ...cur, consoleLogCount: 10 }),
51
+ });
52
+ }
53
+ if (m.anyTypeCount > 100 && m.lintTool?.includes('eslint')) {
54
+ actions.push({
55
+ id: 'health.quality.remove-any-types',
56
+ title: `Replace ${m.anyTypeCount} \`: any\` type annotations`,
57
+ rationale: 'Loose any-types defeat TypeScript. Most can be inferred or narrowed.',
58
+ evidence: [],
59
+ patch: (cur) => ({ ...cur, anyTypeCount: 50 }),
60
+ });
61
+ }
62
+ if (m.lintErrors > 10) {
63
+ actions.push({
64
+ id: 'health.quality.fix-lint-errors',
65
+ title: `Fix ${m.lintErrors} lint errors`,
66
+ rationale: `Run \`${m.lintTool || 'lint'} --fix\` for auto-fixable ones.`,
67
+ evidence: [],
68
+ patch: (cur) => ({ ...cur, lintErrors: 0 }),
69
+ });
70
+ }
71
+ if (m.maxFunctionsInFile !== null && m.maxFunctionsInFile > 50) {
72
+ const ev = m.maxFunctionsFilePath
73
+ ? [
74
+ {
75
+ file: m.maxFunctionsFilePath,
76
+ rule: 'god-file',
77
+ tool: 'graphify',
78
+ message: `${m.maxFunctionsInFile} functions`,
79
+ },
80
+ ]
81
+ : [];
82
+ actions.push({
83
+ id: 'health.quality.split-god-file',
84
+ title: `Split densest file (${m.maxFunctionsInFile} functions)`,
85
+ rationale: 'Files with 50+ functions are hard to test and review.',
86
+ evidence: ev,
87
+ patch: (cur) => ({ ...cur, maxFunctionsInFile: 40 }),
88
+ });
89
+ }
90
+ return actions;
91
+ }
92
+ // ─── Documentation dimension ────────────────────────────────────────────────
93
+ function docsActions(m) {
94
+ const actions = [];
95
+ if (!m.readmeExists || m.readmeLines < 50) {
96
+ actions.push({
97
+ id: 'health.docs.expand-readme',
98
+ title: m.readmeExists
99
+ ? `Expand README (currently ${m.readmeLines} lines)`
100
+ : 'Create a README.md',
101
+ rationale: 'README is the first impression. Target 50+ lines covering setup, run, test.',
102
+ evidence: [],
103
+ patch: (cur) => ({ ...cur, readmeExists: true, readmeLines: 120 }),
104
+ });
105
+ }
106
+ if (!m.contributingExists) {
107
+ actions.push({
108
+ id: 'health.docs.add-contributing',
109
+ title: 'Add CONTRIBUTING.md',
110
+ rationale: 'Codifies contribution expectations, PR template, commit conventions.',
111
+ evidence: [],
112
+ patch: (cur) => ({ ...cur, contributingExists: true }),
113
+ });
114
+ }
115
+ if (!m.architectureDocsExist) {
116
+ actions.push({
117
+ id: 'health.docs.add-architecture',
118
+ title: 'Add architecture/ADR documentation',
119
+ rationale: 'System design context prevents tribal-knowledge debt.',
120
+ evidence: [],
121
+ patch: (cur) => ({ ...cur, architectureDocsExist: true }),
122
+ });
123
+ }
124
+ if (!m.apiDocsExist && (m.controllers > 0 || m.sourceFiles > 100)) {
125
+ actions.push({
126
+ id: 'health.docs.add-api-docs',
127
+ title: 'Add API documentation',
128
+ rationale: 'With controllers/routes present, API surface should be documented.',
129
+ evidence: [],
130
+ patch: (cur) => ({ ...cur, apiDocsExist: true }),
131
+ });
132
+ }
133
+ return actions;
134
+ }
135
+ // ─── Security dimension ─────────────────────────────────────────────────────
136
+ function securityActions(m) {
137
+ const actions = [];
138
+ if (m.secretFindings > 0) {
139
+ actions.push({
140
+ id: 'health.security.remove-secrets',
141
+ title: `Rotate & remove ${m.secretFindings} hardcoded secret${m.secretFindings === 1 ? '' : 's'}`,
142
+ rationale: 'Git history retains secrets — rotate credentials AND purge via git-filter-repo. See vulnerability-scan-detailed.md.',
143
+ evidence: [],
144
+ patch: (cur) => ({ ...cur, secretFindings: 0 }),
145
+ });
146
+ }
147
+ if (m.privateKeyFiles > 0) {
148
+ actions.push({
149
+ id: 'health.security.remove-private-keys',
150
+ title: `Remove ${m.privateKeyFiles} private key file${m.privateKeyFiles === 1 ? '' : 's'} from git`,
151
+ rationale: 'Private keys in git are compromised. Rotate + remove + add to .gitignore.',
152
+ evidence: [],
153
+ patch: (cur) => ({ ...cur, privateKeyFiles: 0 }),
154
+ });
155
+ }
156
+ if (m.depVulnCritical > 0 || m.depVulnHigh > 0) {
157
+ actions.push({
158
+ id: 'health.security.update-deps',
159
+ title: `Update vulnerable dependencies (${m.depVulnCritical}C ${m.depVulnHigh}H)`,
160
+ rationale: `Run \`${m.depAuditTool || 'audit tool'} fix\` or bump affected packages.`,
161
+ evidence: [],
162
+ patch: (cur) => ({
163
+ ...cur,
164
+ depVulnCritical: 0,
165
+ depVulnHigh: 0,
166
+ depVulnMedium: 0,
167
+ depVulnLow: 0,
168
+ }),
169
+ });
170
+ }
171
+ if (m.evalCount > 0) {
172
+ actions.push({
173
+ id: 'health.security.remove-eval',
174
+ title: `Remove ${m.evalCount} eval() call${m.evalCount === 1 ? '' : 's'}`,
175
+ rationale: 'eval() enables arbitrary code execution. Replace with explicit parsing.',
176
+ evidence: [],
177
+ patch: (cur) => ({ ...cur, evalCount: 0 }),
178
+ });
179
+ }
180
+ return actions;
181
+ }
182
+ // ─── Maintainability dimension ──────────────────────────────────────────────
183
+ function maintainabilityActions(m) {
184
+ const actions = [];
185
+ if (m.largestFileLines > 2000) {
186
+ actions.push({
187
+ id: 'health.maint.split-largest-file',
188
+ title: `Split ${m.largestFilePath} (${m.largestFileLines} lines)`,
189
+ rationale: 'Files over 2000 lines are too large for effective code review.',
190
+ evidence: m.largestFilePath
191
+ ? [{ file: m.largestFilePath, rule: 'large-file', tool: 'wc' }]
192
+ : [],
193
+ patch: (cur) => ({ ...cur, largestFileLines: 500 }),
194
+ });
195
+ }
196
+ if (m.nodeEngineVersion) {
197
+ const major = parseInt(m.nodeEngineVersion.match(/(\d+)/)?.[1] || '20');
198
+ if (major < 18) {
199
+ actions.push({
200
+ id: 'health.maint.upgrade-node',
201
+ title: `Upgrade Node engine (currently ${m.nodeEngineVersion})`,
202
+ rationale: 'Node < 18 is out of LTS. Upgrade package.json engines.node.',
203
+ evidence: [{ file: 'package.json', rule: 'outdated-node', tool: 'npm' }],
204
+ patch: (cur) => ({ ...cur, nodeEngineVersion: '>=20' }),
205
+ });
206
+ }
207
+ }
208
+ if (m.filesOver500Lines > 15) {
209
+ actions.push({
210
+ id: 'health.maint.reduce-large-files',
211
+ title: `Reduce ${m.filesOver500Lines} files > 500 lines`,
212
+ rationale: 'Large files are hard to navigate and review.',
213
+ evidence: [],
214
+ patch: (cur) => ({ ...cur, filesOver500Lines: 5 }),
215
+ });
216
+ }
217
+ return actions;
218
+ }
219
+ // ─── Developer Experience dimension ─────────────────────────────────────────
220
+ function dxActions(m) {
221
+ const actions = [];
222
+ if (m.ciConfigCount === 0) {
223
+ actions.push({
224
+ id: 'health.dx.add-ci',
225
+ title: 'Add CI configuration',
226
+ rationale: 'No CI on this branch — lint/test/typecheck should block merges. Add .github/workflows or equivalent.',
227
+ evidence: [],
228
+ patch: (cur) => ({ ...cur, ciConfigCount: 1 }),
229
+ });
230
+ }
231
+ if (m.dockerConfigCount === 0) {
232
+ actions.push({
233
+ id: 'health.dx.add-dockerfile',
234
+ title: 'Add Dockerfile / containerization',
235
+ rationale: 'Containerized setup eliminates "works on my machine" onboarding friction.',
236
+ evidence: [],
237
+ patch: (cur) => ({ ...cur, dockerConfigCount: 1 }),
238
+ });
239
+ }
240
+ if (m.precommitConfigCount === 0) {
241
+ actions.push({
242
+ id: 'health.dx.add-precommit',
243
+ title: 'Add pre-commit hooks (husky / pre-commit)',
244
+ rationale: 'Catch lint/format issues before code leaves the developer machine.',
245
+ evidence: [],
246
+ patch: (cur) => ({ ...cur, precommitConfigCount: 1 }),
247
+ });
248
+ }
249
+ if (!m.envExampleExists) {
250
+ actions.push({
251
+ id: 'health.dx.add-env-example',
252
+ title: 'Add .env.example',
253
+ rationale: 'Documents required environment variables without leaking secrets.',
254
+ evidence: [],
255
+ patch: (cur) => ({ ...cur, envExampleExists: true }),
256
+ });
257
+ }
258
+ return actions;
259
+ }
260
+ function buildHealthPlans(metrics) {
261
+ const dims = [
262
+ { name: 'Testing', scorer: scoring_1.scoreTest, build: testingActions },
263
+ { name: 'Quality', scorer: scoring_1.scoreQuality, build: qualityActions },
264
+ { name: 'Documentation', scorer: scoring_1.scoreDocumentation, build: docsActions },
265
+ { name: 'Security', scorer: scoring_1.scoreSecurity, build: securityActions },
266
+ { name: 'Maintainability', scorer: scoring_1.scoreMaintainability, build: maintainabilityActions },
267
+ { name: 'Developer Experience', scorer: scoring_1.scoreDeveloperExperience, build: dxActions },
268
+ ];
269
+ return dims.map((d) => {
270
+ const baseline = d.scorer(metrics).score;
271
+ const actions = (0, remediation_1.rank)(d.build(metrics), metrics, d.scorer);
272
+ // "Ideal" = apply every action's patch in sequence, then score.
273
+ let ideal = metrics;
274
+ for (const a of actions)
275
+ ideal = a.patch(ideal);
276
+ return {
277
+ dimension: d.name,
278
+ baseline,
279
+ ideal: d.scorer(ideal).score,
280
+ actions,
281
+ };
282
+ });
283
+ }
284
+ //# sourceMappingURL=actions.js.map