@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
package/CHANGELOG.md CHANGED
@@ -7,6 +7,278 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.6.0] - 2026-04-18
11
+
12
+ This release transforms dxkit from a scaffolder into an analyzer-and-scaffolder.
13
+ Five native CLI commands run deterministic analyses against any repo — no LLM
14
+ required, reproducible scores, agent-consumable JSON output. The scaffolding
15
+ capability is unchanged.
16
+
17
+ ### Added
18
+
19
+ #### Native analyzer CLI (new primary capability)
20
+
21
+ - **`vyuh-dxkit health [path]`** — 6-dimension score (Testing, Code Quality,
22
+ Documentation, Security, Maintainability, Developer Experience) with
23
+ overall grade A–F. Runs in 10–20s on mid-size repos.
24
+ - **`vyuh-dxkit vulnerabilities [path]`** — gitleaks secret scan + semgrep SAST
25
+ + `npm audit` / `pip-audit` / `govulncheck` / `cargo-audit` dependency
26
+ vulnerabilities. Findings grouped by rule with severity + CWE category.
27
+ - **`vyuh-dxkit test-gaps [path]`** — coverage artifact import with
28
+ import-graph reachability fallback. Ranks untested files by risk tier
29
+ (CRITICAL for auth/security, HIGH for large services, etc.).
30
+ - **`vyuh-dxkit quality [path]`** — Slop score (0–100) combining lint errors,
31
+ `: any` density, console statements, TODO/FIXME, duplication % (jscpd),
32
+ comment ratio, and hygiene markers. Ranked remediation actions.
33
+ - **`vyuh-dxkit dev-report [path]`** — git activity: commits, contributors,
34
+ hot files, merge ratio, conventional-commit compliance, weekly velocity.
35
+ - **`--detailed` flag** on all analyzers — writes paired `<name>-detailed.md`
36
+ + `<name>-detailed.json` with Evidence (file, line, rule, tool) and
37
+ `RemediationAction<M>` entries ranked by projected score delta.
38
+ - **`--json` flag** — pure JSON on stdout, logs on stderr for clean piping.
39
+ - **`--verbose` flag** — per-tool timing to stderr.
40
+ - **`--no-save` flag** — skip markdown output.
41
+ - **`--since <date>`** (dev-report only) — bound the git activity window.
42
+
43
+ #### Tool registry and installer
44
+
45
+ - **`vyuh-dxkit tools`** — list detection status for all tools required by
46
+ the detected stack. Multi-path detection (PATH → brew → npm-g → pipx →
47
+ cargo → go → project `node_modules` → system probes).
48
+ - **`vyuh-dxkit tools install [--yes]`** — interactive or non-interactive
49
+ install of missing tools via platform-specific commands (brew on macOS,
50
+ user-local on Linux). No `sudo` required; tools install to `~/.local/bin`
51
+ or equivalent.
52
+ - **21 tools integrated** across 6 languages:
53
+ - Universal: `cloc`, `gitleaks`, `semgrep`, `jscpd`, `graphify`
54
+ - Node/TS: `eslint`, `npm audit`, `@vitest/coverage-v8`
55
+ - Python: `ruff`, `pip-audit`, `coverage` (coverage.py)
56
+ - Go: `golangci-lint`, `govulncheck`
57
+ - Rust: `clippy`, `cargo-audit`, `cargo-llvm-cov`
58
+ - C#: `dotnet-format`
59
+ - **`nodePackage` field** on `ToolDefinition` — detects Node packages that
60
+ have no CLI binary (e.g. vitest plugins) via `node_modules/<pkg>/package.json`.
61
+ - **`runRegisteredTool()`** — sanctioned path to run any registered tool,
62
+ ensures all tool invocation goes through detection instead of hardcoded
63
+ binary paths.
64
+
65
+ #### Coverage artifact import
66
+
67
+ - **Istanbul** (`coverage/coverage-summary.json` + `coverage-final.json`) —
68
+ used by vitest, nyc, c8. Parses per-file line coverage + overall %.
69
+ - **coverage.py** (`coverage.json`) — Python.
70
+ - **Go coverprofile** (`coverage.out` / `cover.out`) — text format with
71
+ module-prefix path resolution.
72
+ - **Cobertura XML** (`coverage.cobertura.xml`, `TestResults/<guid>/...`) —
73
+ C# (coverlet) and Rust (`cargo llvm-cov --cobertura`).
74
+ - **lcov** (`lcov.info`) — Rust (`cargo llvm-cov --lcov`).
75
+
76
+ #### Import-graph test matching
77
+
78
+ - **TS/JS extractor** — static imports, `import(...)` dynamic, `require()`,
79
+ `export * from` re-exports, multi-line imports, comment-stripping.
80
+ - **Python extractor** — `import X`, `from X import Y`, relative-dot imports.
81
+ - **Go extractor** — single-line `import "fmt"` + multi-line `import (...)`
82
+ blocks with alias support. Module-based resolution via `go.mod`.
83
+ - **Rust extractor** — `use std::io`, nested paths, block `use std::{io, fs}`.
84
+ - **C# extractor** — `using X.Y;`, `using static`, `using Alias = X.Y;`.
85
+ - **Resolver** — relative-path resolution with extension fallback and
86
+ directory-as-`index.ts` probing (TS/JS) or `__init__.py` (Python).
87
+ Go resolves internal module paths via `go.mod` module prefix.
88
+ - **BFS walker** — up to 3 hops transitively, cycle-safe. External packages
89
+ are correctly skipped.
90
+
91
+ #### Suppressions
92
+
93
+ - **`.dxkit-suppressions.json`** — silence known-false positives per tool
94
+ without editing code. Format:
95
+ ```json
96
+ {
97
+ "gitleaks": [
98
+ { "rule": "generic-api-key", "paths": ["test/fixtures/**"], "reason": "..." }
99
+ ]
100
+ }
101
+ ```
102
+ - Glob matcher supports `**`, `*`, `?`. A finding is suppressed when rule
103
+ matches (exact or `*`) AND at least one path glob matches.
104
+ - Wired to gitleaks. Semgrep and slop-hook integrations follow.
105
+
106
+ #### CI + hooks hardening
107
+
108
+ - **CI enforces everything pre-push does, plus slop-vs-base diff.**
109
+ `.github/workflows/ci.yml` now runs architecture check, slop check
110
+ (diffing against the PR base branch via `DXKIT_SLOP_BASE`), tests with
111
+ coverage, and coverage-threshold enforcement. `--no-verify` can no longer
112
+ ship code that introduces slop.
113
+ - **`scripts/check-coverage.sh`** — reads `coverage/coverage-summary.json`,
114
+ fails if line coverage below threshold (default 50%, configurable via
115
+ `DXKIT_COVERAGE_THRESHOLD`). Wired into `.husky/pre-push` and CI.
116
+ - **`scripts/check-slop.sh` CI mode** — when `DXKIT_SLOP_BASE` env var is
117
+ set, diffs against that ref instead of `--cached`. Pre-commit behavior
118
+ unchanged.
119
+
120
+ #### Dogfood
121
+
122
+ - dxkit's own line coverage raised from ~19% to 59% in the course of
123
+ building these analyzers. 423 tests across 21 files, all passing.
124
+ Coverage threshold of 50% enforced on every push and PR.
125
+
126
+ #### Language-pack rearchitecture (10d.1.6)
127
+
128
+ - **`LanguageSupport` interface** — single-file-per-language architecture.
129
+ Each language implements: detection, tool bindings, semgrep rulesets,
130
+ coverage parsing, import extraction/resolution, metric gathering, and
131
+ lint severity mapping. `src/languages/{python,typescript,csharp,go,rust}.ts`.
132
+ - **Registry dispatch** — `health.ts`, `tool-registry.ts`, `import-graph.ts`,
133
+ `gather.ts`, and `quality/gather.ts` all dispatch through
134
+ `detectActiveLanguages()` instead of per-language if-chains.
135
+ - **Old scattered code deleted** — `src/analyzers/tools/{node,python,go,
136
+ rust,dotnet}.ts` removed (~583 LOC). Net reduction despite adding 5
137
+ language packs + coverage parsers + import extractors.
138
+ - **Ruff severity mapping** — Python lint results now bucket ruff codes by
139
+ prefix: S→critical, F/B→high, E/C→medium, W/N/D/I→low. Previously all
140
+ results were counted as errors regardless of code.
141
+ - **C# `*Tests.cs` pattern** — test-gap analyzer now recognizes the C#
142
+ naming convention (`FooTests.cs`, `Foo.Tests.cs`) that the old
143
+ `*.test.*`/`*.spec.*`-only patterns missed.
144
+ - **`cargo-llvm-cov`** registered in TOOL_DEFS with detection + install.
145
+ - **Contract tests** — 46 tests validate every language pack: TOOL_DEFS
146
+ key validity, extension format, wildcard patterns, detect() idempotency,
147
+ completeness (all 5 required IDs registered).
148
+
149
+ #### OSV.dev severity enrichment + CVSS v4 (10d.2)
150
+
151
+ - **OSV.dev integration** — `src/analyzers/tools/osv.ts` looks up
152
+ vulnerability IDs against `https://api.osv.dev/v1/vulns/{id}` and
153
+ classifies them into critical/high/medium/low tiers. Session-scoped
154
+ in-memory cache. 10s per-request timeout with offline fallback.
155
+ - **Full CVSS v4.0 calculator** — `src/analyzers/tools/cvss-v4.ts` with
156
+ the 270-entry macrovector → base-score lookup table (BSD-2-Clause,
157
+ ported verbatim from FIRST.ORG's reference implementation, attributed
158
+ in `THIRD_PARTY_NOTICES.md`). Handles equivalence-class computation,
159
+ severity-distance refinement, and rounding per spec. Critical for
160
+ modern CVEs (2025+) that publish v4 vectors exclusively.
161
+ - **Python pack (`pip-audit`)** — previously bucketed every finding as
162
+ medium. Now extracts vuln IDs and looks each up via OSV. Unknown or
163
+ unreachable IDs keep the legacy medium bucket. Verified on
164
+ CVE-2025-8869 (pip tar symlink → v4 5.9 → medium, matches NVD).
165
+ - **Go pack (`govulncheck`)** — ndjson findings reference OSV IDs.
166
+ We now prefer the advisory's embedded severity (govulncheck inlines
167
+ the full OSV record), only falling back to the OSV.dev API when
168
+ severity data is missing. Unknown IDs bucket as high (govulncheck's
169
+ legacy default).
170
+
171
+ #### Lint severity tiers across all packs
172
+
173
+ Each language pack now exposes `mapLintSeverity(ruleId)` that tiers
174
+ findings into critical/high/medium/low. `gatherMetrics` still collapses
175
+ to the legacy `lintErrors`/`lintWarnings` fields (critical+high →
176
+ errors, medium+low → warnings) for backcompat.
177
+
178
+ - **TypeScript (ESLint)** — security plugins (`security/*`,
179
+ `security-node/*`) and code-injection built-ins (`no-eval`,
180
+ `no-new-func`, `@typescript-eslint/no-unsafe-eval`) → critical;
181
+ correctness bugs (`no-undef`, `no-unreachable`, `no-dupe-*`,
182
+ `@typescript-eslint/no-unsafe-*`, `react-hooks/rules-of-hooks`) → high;
183
+ best practices (`no-console`, `prefer-const`,
184
+ `@typescript-eslint/no-explicit-any|no-unused-vars`,
185
+ `react-hooks/exhaustive-deps`) → medium; style plugins
186
+ (`prettier/*`, `import/*`, `react/*`, `jsx-a11y/*`, `unicorn/*`) → low.
187
+ Unknown rules fall back to ESLint's severity floor.
188
+ - **Go (golangci-lint)** — tier by `FromLinter`: `gosec` → critical;
189
+ `govet`/`staticcheck`/`typecheck`/`errorlint`/`ineffassign`/`unused`/
190
+ `bodyclose`/`sqlclosecheck`/`noctx` → high; `errcheck`/`gocritic`/
191
+ `revive`/`gocyclo`/`gosimple`/`unparam`/`gocognit` → medium; `gofmt`/
192
+ `goimports`/`stylecheck`/`whitespace`/`misspell`/`lll` → low.
193
+ - **Rust (clippy)** — hand-catalogued correctness-group lints:
194
+ 15 memory-safety / UB lints (`uninit_*`, `transmuting_null`, `cast_ref_to_mut`,
195
+ `invalid_atomic_ordering`, …) → critical; 35+ correctness-bug lints
196
+ (`panicking_unwrap`, `never_loop`, `out_of_bounds_indexing`,
197
+ `ifs_same_cond`, `logic_bug`, …) → high; rustc-native lints → medium;
198
+ all other clippy groups (style, perf, pedantic, nursery, cargo) → low.
199
+ - **C#** — `mapLintSeverity` intentionally omitted: `dotnet-format` is
200
+ a formatter, not a tiered linter. Documented in pack source with a
201
+ TODO pointer to a future `dotnet build --verbosity quiet` integration
202
+ that would extract CS*/CA*/IDE* diagnostic codes.
203
+
204
+ #### Dep-vuln aggregation across language packs
205
+
206
+ - **`mergeMetrics` now sums `depVuln*` counts** instead of overwriting.
207
+ Mixed-stack repos (e.g. Node + Python) previously had whichever pack
208
+ ran last silently clobber earlier packs' vuln counts. Now pip-audit
209
+ and npm-audit findings add together. `depAuditTool` likewise joins
210
+ with `, ` (e.g. `"pip-audit, npm-audit"`).
211
+ - **Meta-tool classifier fix** — `src/analyzers/security/*.ts` files
212
+ matched `CRITICAL_PATTERNS` by name (`/security/i`) and showed up in
213
+ test-gaps as critical untested code. They're analyzer modules, not
214
+ app security code. Added path-prefix exception (`^src/analyzers/`,
215
+ `^tmp/`, `^scripts/`) that downgrades these to their structural tier.
216
+ - **C# dotnet-format violations** reclassified from `lintErrors` to
217
+ `lintWarnings` — they're formatting issues (indentation, spacing),
218
+ not correctness errors. No longer inflates the quality/slop error
219
+ count.
220
+
221
+ #### Async language-pack contract
222
+
223
+ - **`gatherMetrics` is now async** (`Promise<Partial<HealthMetrics>>`).
224
+ Enables network-dependent enrichment (OSV lookups). The full analyzer
225
+ chain — `analyzeHealth`, `analyzeQuality`, and the CLI commands —
226
+ threads async end-to-end. Bonus: the 5 language packs now run through
227
+ `Promise.all` in health.ts instead of sequentially.
228
+ - **`timedAsync`** helper added alongside existing `timed` in
229
+ `src/analyzers/tools/timing.ts` for per-tool verbose timing of
230
+ async gatherers.
231
+
232
+ ### Changed
233
+
234
+ - **`vitest.config.ts`** now generates Istanbul summary + JSON reporters when
235
+ `--coverage` is passed. Coverage output in `coverage/`.
236
+ - **Signal precedence in `test-gaps`** — coverage artifact now *overrides*
237
+ filename match for files it measured. Previously all three signals OR'd
238
+ together, which wrongly credited files like `cli.ts` when a test had a
239
+ similar basename but didn't actually import the module. Now: artifact
240
+ authoritative where present, import-graph for files it didn't see,
241
+ filename-match as last resort.
242
+ - **`.husky/pre-push`** — now runs `npm run build && vitest run --coverage &&
243
+ bash scripts/check-coverage.sh`. Previously ran `vitest run --changed @{u}`
244
+ without coverage.
245
+ - **`--json` output** — clean JSON on stdout now. Previously the logger
246
+ header (`━━━ vyuh-dxkit ...`) leaked into stdout before the JSON payload.
247
+
248
+ ### Fixed
249
+
250
+ - **`--json` stdout pollution** — `logger.header/info/success/warn/fail/dim/
251
+ detected` route to stderr when JSON mode is active.
252
+ - **Filename matcher false positives** — `cli-init.test.ts` used to credit
253
+ `cli.ts` via basename similarity even though it doesn't import it in
254
+ process (uses `execFileSync`). After the precedence fix and import-graph
255
+ matcher, dxkit's `test-gaps` agrees with V8 on every measured file.
256
+ - **Unused import warnings** — cleaned up six pre-existing unused imports
257
+ that CI's `--max-warnings 0` would now catch.
258
+
259
+ ### Internal / Architecture
260
+
261
+ - New modules: `src/analyzers/tools/coverage.ts`, `tools/suppressions.ts`,
262
+ `tests/import-graph.ts`.
263
+ - `HealthMetrics.coveragePercent` now populated from the imported artifact
264
+ when present; the existing Testing-dimension coverage bonus fires against
265
+ line-level truth instead of being null.
266
+ - `HealthMetrics.secretSuppressed` — count of gitleaks findings filtered by
267
+ `.dxkit-suppressions.json`.
268
+ - `ToolDefinition.nodePackage` — optional field for Node packages detected
269
+ via `node_modules/<pkg>/package.json` rather than a binary in `.bin`.
270
+ - `vitest.integration.config.ts` — separate config for running only the
271
+ `test/integration/**` suite (kept for developers who want to run the slow
272
+ integration tests without the rest of the suite).
273
+
274
+ ## [1.5.1] - 2026-04-10
275
+
276
+ ### Fixed
277
+ - **`make setup` no longer aborts on npm install failure.** Peer dependency
278
+ conflicts now show a helpful message instead of killing the entire script.
279
+ - **`--stealth` flag** for `dxkit init` — gitignore only files created in
280
+ this run.
281
+
10
282
  ## [1.5.0] - 2026-04-10
11
283
 
12
284
  ### Fixed