@vyuhlabs/dxkit 1.5.1 → 1.6.1

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