@vyuhlabs/dxkit 2.4.8 → 2.5.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 (243) hide show
  1. package/CHANGELOG.md +235 -0
  2. package/README.md +360 -439
  3. package/dist/analyzers/security/aggregator.d.ts.map +1 -1
  4. package/dist/analyzers/security/aggregator.js +4 -46
  5. package/dist/analyzers/security/aggregator.js.map +1 -1
  6. package/dist/analyzers/tools/fingerprint.d.ts +91 -26
  7. package/dist/analyzers/tools/fingerprint.d.ts.map +1 -1
  8. package/dist/analyzers/tools/fingerprint.js +111 -22
  9. package/dist/analyzers/tools/fingerprint.js.map +1 -1
  10. package/dist/analyzers/tools/generic.d.ts.map +1 -1
  11. package/dist/analyzers/tools/generic.js +6 -1
  12. package/dist/analyzers/tools/generic.js.map +1 -1
  13. package/dist/analyzers/tools/gitleaks.d.ts +24 -1
  14. package/dist/analyzers/tools/gitleaks.d.ts.map +1 -1
  15. package/dist/analyzers/tools/gitleaks.js +20 -11
  16. package/dist/analyzers/tools/gitleaks.js.map +1 -1
  17. package/dist/analyzers/types.d.ts +6 -4
  18. package/dist/analyzers/types.d.ts.map +1 -1
  19. package/dist/baseline/baseline-file.d.ts +104 -0
  20. package/dist/baseline/baseline-file.d.ts.map +1 -0
  21. package/dist/baseline/baseline-file.js +110 -0
  22. package/dist/baseline/baseline-file.js.map +1 -0
  23. package/dist/baseline/check-renderers.d.ts +108 -0
  24. package/dist/baseline/check-renderers.d.ts.map +1 -0
  25. package/dist/baseline/check-renderers.js +379 -0
  26. package/dist/baseline/check-renderers.js.map +1 -0
  27. package/dist/baseline/check.d.ts +127 -0
  28. package/dist/baseline/check.d.ts.map +1 -0
  29. package/dist/baseline/check.js +462 -0
  30. package/dist/baseline/check.js.map +1 -0
  31. package/dist/baseline/content-hash.d.ts +83 -0
  32. package/dist/baseline/content-hash.d.ts.map +1 -0
  33. package/dist/baseline/content-hash.js +131 -0
  34. package/dist/baseline/content-hash.js.map +1 -0
  35. package/dist/baseline/create.d.ts +96 -0
  36. package/dist/baseline/create.d.ts.map +1 -0
  37. package/dist/baseline/create.js +339 -0
  38. package/dist/baseline/create.js.map +1 -0
  39. package/dist/baseline/entry-to-located.d.ts +35 -0
  40. package/dist/baseline/entry-to-located.d.ts.map +1 -0
  41. package/dist/baseline/entry-to-located.js +72 -0
  42. package/dist/baseline/entry-to-located.js.map +1 -0
  43. package/dist/baseline/finding-identity.d.ts +47 -0
  44. package/dist/baseline/finding-identity.d.ts.map +1 -0
  45. package/dist/baseline/finding-identity.js +292 -0
  46. package/dist/baseline/finding-identity.js.map +1 -0
  47. package/dist/baseline/git-aware-match.d.ts +146 -0
  48. package/dist/baseline/git-aware-match.d.ts.map +1 -0
  49. package/dist/baseline/git-aware-match.js +439 -0
  50. package/dist/baseline/git-aware-match.js.map +1 -0
  51. package/dist/baseline/policy.d.ts +171 -0
  52. package/dist/baseline/policy.d.ts.map +1 -0
  53. package/dist/baseline/policy.js +206 -0
  54. package/dist/baseline/policy.js.map +1 -0
  55. package/dist/baseline/producers/health.d.ts +30 -0
  56. package/dist/baseline/producers/health.d.ts.map +1 -0
  57. package/dist/baseline/producers/health.js +42 -0
  58. package/dist/baseline/producers/health.js.map +1 -0
  59. package/dist/baseline/producers/index.d.ts +164 -0
  60. package/dist/baseline/producers/index.d.ts.map +1 -0
  61. package/dist/baseline/producers/index.js +200 -0
  62. package/dist/baseline/producers/index.js.map +1 -0
  63. package/dist/baseline/producers/licenses.d.ts +23 -0
  64. package/dist/baseline/producers/licenses.d.ts.map +1 -0
  65. package/dist/baseline/producers/licenses.js +46 -0
  66. package/dist/baseline/producers/licenses.js.map +1 -0
  67. package/dist/baseline/producers/quality.d.ts +39 -0
  68. package/dist/baseline/producers/quality.d.ts.map +1 -0
  69. package/dist/baseline/producers/quality.js +84 -0
  70. package/dist/baseline/producers/quality.js.map +1 -0
  71. package/dist/baseline/producers/secret-hmac.d.ts +45 -0
  72. package/dist/baseline/producers/secret-hmac.d.ts.map +1 -0
  73. package/dist/baseline/producers/secret-hmac.js +70 -0
  74. package/dist/baseline/producers/secret-hmac.js.map +1 -0
  75. package/dist/baseline/producers/security.d.ts +59 -0
  76. package/dist/baseline/producers/security.d.ts.map +1 -0
  77. package/dist/baseline/producers/security.js +135 -0
  78. package/dist/baseline/producers/security.js.map +1 -0
  79. package/dist/baseline/producers/tests.d.ts +36 -0
  80. package/dist/baseline/producers/tests.d.ts.map +1 -0
  81. package/dist/baseline/producers/tests.js +69 -0
  82. package/dist/baseline/producers/tests.js.map +1 -0
  83. package/dist/baseline/salt.d.ts +45 -0
  84. package/dist/baseline/salt.d.ts.map +1 -0
  85. package/dist/baseline/salt.js +113 -0
  86. package/dist/baseline/salt.js.map +1 -0
  87. package/dist/baseline/show.d.ts +79 -0
  88. package/dist/baseline/show.d.ts.map +1 -0
  89. package/dist/baseline/show.js +233 -0
  90. package/dist/baseline/show.js.map +1 -0
  91. package/dist/baseline/types.d.ts +482 -0
  92. package/dist/baseline/types.d.ts.map +1 -0
  93. package/dist/baseline/types.js +53 -0
  94. package/dist/baseline/types.js.map +1 -0
  95. package/dist/cli.d.ts.map +1 -1
  96. package/dist/cli.js +360 -81
  97. package/dist/cli.js.map +1 -1
  98. package/dist/codebase-scanner.d.ts.map +1 -1
  99. package/dist/codebase-scanner.js +0 -1
  100. package/dist/codebase-scanner.js.map +1 -1
  101. package/dist/constants.d.ts.map +1 -1
  102. package/dist/constants.js +0 -4
  103. package/dist/constants.js.map +1 -1
  104. package/dist/doctor.d.ts.map +1 -1
  105. package/dist/doctor.js +22 -25
  106. package/dist/doctor.js.map +1 -1
  107. package/dist/fail-on.d.ts +84 -0
  108. package/dist/fail-on.d.ts.map +1 -0
  109. package/dist/fail-on.js +128 -0
  110. package/dist/fail-on.js.map +1 -0
  111. package/dist/generator.d.ts.map +1 -1
  112. package/dist/generator.js +2 -141
  113. package/dist/generator.js.map +1 -1
  114. package/dist/languages/csharp.d.ts.map +1 -1
  115. package/dist/languages/csharp.js +0 -9
  116. package/dist/languages/csharp.js.map +1 -1
  117. package/dist/languages/go.d.ts.map +1 -1
  118. package/dist/languages/go.js +0 -15
  119. package/dist/languages/go.js.map +1 -1
  120. package/dist/languages/index.d.ts +1 -1
  121. package/dist/languages/index.d.ts.map +1 -1
  122. package/dist/languages/index.js.map +1 -1
  123. package/dist/languages/java.d.ts.map +1 -1
  124. package/dist/languages/java.js +0 -6
  125. package/dist/languages/java.js.map +1 -1
  126. package/dist/languages/kotlin.d.ts.map +1 -1
  127. package/dist/languages/kotlin.js +0 -11
  128. package/dist/languages/kotlin.js.map +1 -1
  129. package/dist/languages/python.d.ts.map +1 -1
  130. package/dist/languages/python.js +0 -15
  131. package/dist/languages/python.js.map +1 -1
  132. package/dist/languages/ruby.d.ts.map +1 -1
  133. package/dist/languages/ruby.js +0 -6
  134. package/dist/languages/ruby.js.map +1 -1
  135. package/dist/languages/rust.d.ts.map +1 -1
  136. package/dist/languages/rust.js +0 -4
  137. package/dist/languages/rust.js.map +1 -1
  138. package/dist/languages/types.d.ts +2 -28
  139. package/dist/languages/types.d.ts.map +1 -1
  140. package/dist/languages/typescript.d.ts.map +1 -1
  141. package/dist/languages/typescript.js +26 -4
  142. package/dist/languages/typescript.js.map +1 -1
  143. package/dist/lib.d.ts +2 -3
  144. package/dist/lib.d.ts.map +1 -1
  145. package/dist/lib.js +3 -6
  146. package/dist/lib.js.map +1 -1
  147. package/dist/prompts.d.ts.map +1 -1
  148. package/dist/prompts.js +0 -10
  149. package/dist/prompts.js.map +1 -1
  150. package/dist/report-schema.d.ts +42 -0
  151. package/dist/report-schema.d.ts.map +1 -0
  152. package/dist/report-schema.js +54 -0
  153. package/dist/report-schema.js.map +1 -0
  154. package/dist/ship-installers.d.ts +106 -0
  155. package/dist/ship-installers.d.ts.map +1 -0
  156. package/dist/ship-installers.js +415 -0
  157. package/dist/ship-installers.js.map +1 -0
  158. package/dist/types.d.ts +0 -4
  159. package/dist/types.d.ts.map +1 -1
  160. package/dist/update.d.ts.map +1 -1
  161. package/dist/update.js +0 -4
  162. package/dist/update.js.map +1 -1
  163. package/package.json +17 -11
  164. package/templates/.claude/agents/onboarding.md +5 -4
  165. package/templates/.claude/agents-available/codebase-explorer.md +1 -1
  166. package/templates/.claude/agents-available/debugger.md +2 -2
  167. package/templates/.claude/agents-available/health-auditor.md +2 -2
  168. package/templates/.claude/commands/doctor.md +20 -12
  169. package/templates/.claude/skills/build/SKILL.md.template +22 -30
  170. package/templates/.claude/skills/deploy/SKILL.md.template +5 -25
  171. package/templates/.claude/skills/doctor/SKILL.md +24 -47
  172. package/templates/.claude/skills/gcloud/SKILL.md +5 -5
  173. package/templates/.claude/skills/learned/SKILL.md +1 -1
  174. package/templates/.claude/skills/pulumi/SKILL.md +2 -2
  175. package/templates/.claude/skills/quality/SKILL.md.template +4 -23
  176. package/templates/.claude/skills/review/SKILL.md.template +4 -3
  177. package/templates/.claude/skills/scaffold/SKILL.md.template +5 -15
  178. package/templates/.claude/skills/secrets/SKILL.md +20 -21
  179. package/templates/.claude/skills/session/SKILL.md +20 -31
  180. package/templates/.claude/skills/test/SKILL.md.template +1 -7
  181. package/templates/.devcontainer/devcontainer.json +81 -0
  182. package/templates/.devcontainer/install-agent-clis.sh +42 -0
  183. package/templates/.devcontainer/post-create.sh +67 -0
  184. package/templates/.githooks/pre-commit +55 -0
  185. package/templates/.githooks/pre-push +63 -0
  186. package/templates/.github/workflows/dxkit-baseline-refresh.yml +78 -0
  187. package/templates/.github/workflows/dxkit-guardrails.yml +98 -0
  188. package/templates/CLAUDE.md.template +62 -196
  189. package/dist/project-yaml.d.ts +0 -13
  190. package/dist/project-yaml.d.ts.map +0 -1
  191. package/dist/project-yaml.js +0 -188
  192. package/dist/project-yaml.js.map +0 -1
  193. package/templates/.ai/README.md +0 -117
  194. package/templates/.ai/prompts/execution-prompt.md +0 -9
  195. package/templates/.ai/prompts/planning-prompt.md +0 -18
  196. package/templates/.ai/prompts/session-end-template.md +0 -182
  197. package/templates/.ai/prompts/session-end.md +0 -132
  198. package/templates/.ai/prompts/session-start.md +0 -109
  199. package/templates/.ai/prompts/step-by-step.md +0 -113
  200. package/templates/.ai/sessions/.gitkeep +0 -0
  201. package/templates/.claude/commands/setup-pr-review.md +0 -72
  202. package/templates/.devcontainer/Dockerfile.dev.template +0 -89
  203. package/templates/.devcontainer/devcontainer.json.template +0 -184
  204. package/templates/.devcontainer/docker-compose.yml.template +0 -105
  205. package/templates/.devcontainer/init-scripts/01-init.sql.template +0 -12
  206. package/templates/.devcontainer/post-create.sh.template +0 -298
  207. package/templates/.github/workflows/ci.yml.template +0 -399
  208. package/templates/.github/workflows/quality.yml.template +0 -376
  209. package/templates/.pre-commit-config.yaml.template +0 -106
  210. package/templates/.project/config/edit_config.py +0 -275
  211. package/templates/.project/config/project_config.py +0 -894
  212. package/templates/.project/scripts/codegen/generate-all.sh +0 -20
  213. package/templates/.project/scripts/codegen/validate-all.sh +0 -17
  214. package/templates/.project/scripts/docs/generate-all.sh +0 -30
  215. package/templates/.project/scripts/docs/serve.sh +0 -20
  216. package/templates/.project/scripts/quality/fix-all.sh +0 -138
  217. package/templates/.project/scripts/quality/lint-go.sh +0 -34
  218. package/templates/.project/scripts/quality/lint-python.sh +0 -54
  219. package/templates/.project/scripts/quality/run-all.sh +0 -497
  220. package/templates/.project/scripts/session/commit.sh +0 -70
  221. package/templates/.project/scripts/session/create-pr.sh +0 -165
  222. package/templates/.project/scripts/session/end.sh +0 -207
  223. package/templates/.project/scripts/session/start.sh +0 -233
  224. package/templates/.project/scripts/setup/doctor.sh +0 -404
  225. package/templates/.project/scripts/setup/interactive-setup.sh +0 -585
  226. package/templates/.project/scripts/sync/sync-template.sh +0 -328
  227. package/templates/.project/scripts/test/run-all.sh +0 -179
  228. package/templates/.project/scripts/test/run-quick.sh +0 -25
  229. package/templates/Makefile +0 -514
  230. package/templates/config/versions.yaml +0 -57
  231. package/templates/configs/go/.golangci.yml.template +0 -172
  232. package/templates/configs/go/go.mod.template +0 -15
  233. package/templates/configs/java/README.md +0 -6
  234. package/templates/configs/kotlin/README.md +0 -6
  235. package/templates/configs/node/package.json.template +0 -67
  236. package/templates/configs/node/tsconfig.json.template +0 -53
  237. package/templates/configs/python/pyproject.toml.template +0 -92
  238. package/templates/configs/python/pytest.ini.template +0 -64
  239. package/templates/configs/python/ruff.toml.template +0 -79
  240. package/templates/configs/ruby/README.md +0 -6
  241. package/templates/configs/rust/Cargo.toml.template +0 -51
  242. package/templates/configs/shared/.editorconfig +0 -67
  243. package/templates/scripts/validate-templates.sh +0 -449
package/CHANGELOG.md CHANGED
@@ -7,6 +7,241 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.5.0] - 2026-05-18
11
+
12
+ ### Summary
13
+
14
+ 2.5.0 introduces **commit-time guardrails** — a per-finding baseline
15
+ captured once on a brownfield repo, then diffed against every
16
+ subsequent scan to detect net-new regressions while grandfathering
17
+ existing debt. Existing issues stay where they are, new ones block.
18
+
19
+ This release also **prunes the legacy task-runner scaffolding** that
20
+ prior versions of `init --full` bundled (Makefile, `.project/` task
21
+ scripts, `.ai/` prompt scaffolding, per-language config templates,
22
+ non-dxkit CI workflows, `.editorconfig`, `.pre-commit-config.yaml`).
23
+ The agent DX surface is now the sole `init --full` output —
24
+ `init --full` lands 73 files (down from 119), every one of them
25
+ focused on equipping AI coding agents to operate safely on the
26
+ codebase. Customers who relied on the legacy scaffolding can use
27
+ `@vyuhlabs/create-devstack` for greenfield project bootstrap.
28
+
29
+ The release ships three coordinated surfaces:
30
+
31
+ 1. **A new `baseline` / `guardrail` CLI** that captures stable
32
+ per-finding identities, diffs current scans against them, and
33
+ classifies each pair (`added` / `relocated` / `tooling_drift` /
34
+ `config_drift` / `persisted` / `removed` / `fixed`) with a
35
+ confidence score and structured reasons. The classifier ships
36
+ with a **scanner-wobble demotion** that converts `added` findings
37
+ on UNCHANGED lines into `uncertain` (warn) for high-wobble kinds
38
+ (`code`, `hygiene`), so semgrep's per-run non-determinism on
39
+ large codebases doesn't trigger false-positive blocks. Findings
40
+ inside the diff's changed lines still block — real regressions
41
+ are caught. Customers can extend or clear the kind list via
42
+ `addedRequiresChangedLines` in `.dxkit/policy.json`.
43
+ 2. **Init-installable templates** for the pre-push guardrail hook,
44
+ a devcontainer with pinned toolchains + Claude Code & Codex
45
+ CLIs, a GitHub Actions PR-gate workflow that posts a markdown
46
+ summary as a PR comment, and a post-merge baseline-refresh
47
+ workflow that keeps the anchor current. Pre-commit + AI-PR-
48
+ review are opt-in via `--with-precommit-hook` and
49
+ `--with-pr-review` respectively (slow on large repos / requires
50
+ API-cost opt-in). Every `init` also seeds `.gitignore` entries
51
+ for the analyzer runtime outputs (`.dxkit/reports/`,
52
+ `.dxkit/dashboard.html`) and writes a starter `.dxkit-ignore`
53
+ template for dxkit-specific scan-exclusion tuning.
54
+ 3. **Aggregate-gate flags** (`--fail-on-score`, `--fail-on-severity`)
55
+ on every analyzer command, plus a stable JSON schema banner on
56
+ every `--json` output so consumers can version-gate.
57
+
58
+ Tests: ~1530 unit + integration cases pass on the integrated branch
59
+ (up from 1265 at the 2.4.8 baseline; +265 across fingerprinting,
60
+ producers, policy, matcher, ship installers, the smart classifier,
61
+ opt-in hook + workflow installers, and the CLI surface).
62
+
63
+ #### New CLI surface
64
+
65
+ ```bash
66
+ vyuh-dxkit baseline create [path] [--name <name>] [--force]
67
+ [--verbose]
68
+ vyuh-dxkit baseline show [path] [--name <name>] [--baseline <p>]
69
+ [--kind <kind>] [--json]
70
+ vyuh-dxkit guardrail check [path] [--name <name>] [--baseline <p>]
71
+ [--changed-only] [--policy <p>]
72
+ [--json | --markdown]
73
+ ```
74
+
75
+ - `baseline create` runs every analyzer, fingerprints each per-
76
+ finding entity through the canonical identity dispatcher
77
+ (`src/baseline/finding-identity.ts`), and writes
78
+ `.dxkit/baselines/<name>.json`. Schema-versioned
79
+ (`dxkit-baseline/v1`); commit it.
80
+ - `baseline show` pretty-prints the on-disk baseline, optionally
81
+ filtered by kind or emitted as a schema-banner-wrapped JSON.
82
+ - `guardrail check` loads the baseline, re-runs the analyzers,
83
+ matches via the git-aware matcher (`-M` renames, ±2 line fuzz,
84
+ content-hash fallback for shallow clones), classifies each pair
85
+ through the brownfield policy, and exits 1 when the policy
86
+ blocks. Output modes: console (default), `--json` (schema
87
+ `dxkit.guardrail-check.v1`), or `--markdown` (used by the PR-
88
+ gate workflow to post a comment).
89
+
90
+ The full read/write/compare triplet flows through a registered
91
+ producer pipeline (`src/baseline/producers/index.ts:PRODUCERS`) —
92
+ adding a new identity kind means registering a producer, not
93
+ editing the orchestrator. Architectural rule documented in
94
+ `CLAUDE.md` Rule 10 with three enforcement gates (arch check +
95
+ contract test + synthetic-producer playbook).
96
+
97
+ #### Aggregate gates + schema banner
98
+
99
+ Every analyzer command (`health`, `test-gaps`, `quality`,
100
+ `vulnerabilities`, `bom`) gains composable exit-code gates:
101
+
102
+ - `--fail-on-score <N>` — exit 1 when the headline score drops
103
+ below N (applies to `health`, `test-gaps`).
104
+ - `--fail-on-severity <tier>` — exit 1 when any finding at `<tier>`
105
+ or higher exists (applies to `vulnerabilities`, `bom`; tier ∈
106
+ critical / high / medium / low).
107
+
108
+ Every `--json` output carries a top-level
109
+ `schema: 'dxkit.<kind>-report.v1'` banner so consumers can version-
110
+ gate against future schema migrations.
111
+
112
+ #### `vyuh-dxkit init` ship flags
113
+
114
+ `init` gains four new flags, all implied by `--full`:
115
+
116
+ - `--with-hooks` writes `.githooks/pre-commit` (fast,
117
+ `--changed-only`) and `.githooks/pre-push` (full).
118
+ - `--with-devcontainer` writes a lightweight `.devcontainer/`
119
+ layering all seven supported language toolchains via devcontainer
120
+ features + a `post-create.sh` that runs `vyuh-dxkit tools install
121
+ --yes` to provision the scanner toolchain pinned in the registry
122
+ + `install-agent-clis.sh` that installs Claude Code + OpenAI
123
+ Codex CLIs (opt out of either with `CLAUDE_CODE_VERSION=skip` /
124
+ `CODEX_VERSION=skip`).
125
+ - `--with-ci` writes `.github/workflows/dxkit-guardrails.yml` (PR-
126
+ gate that posts a markdown summary as a PR comment, updating in
127
+ place across pushes via an HTML marker).
128
+ - `--with-baseline-refresh` writes
129
+ `.github/workflows/dxkit-baseline-refresh.yml` (regenerates the
130
+ baseline on every push to the consumer's default branch and
131
+ auto-commits with `[skip ci]`). The default-branch name is
132
+ detected at install time from the consumer's git state, with
133
+ fallbacks for `main` / `master` / `trunk` / `develop`.
134
+
135
+ Installs are **additive by default**. Existing `.githooks/<hook>`
136
+ or `.husky/<hook>` files trigger a `.dxkit` sidecar + merge note
137
+ instead of an overwrite. An existing `.devcontainer/devcontainer.json`
138
+ stashes the full dxkit set under `.devcontainer/.dxkit-reference/`
139
+ for manual merge. Workflow files are uniquely named so they don't
140
+ collide; if our exact filename already exists, init skips it. The
141
+ `--force` flag overrides every additive fallback and writes in
142
+ place.
143
+
144
+ #### Brownfield policy
145
+
146
+ `.dxkit/policy.json` (auto-discovered at the repo root) tunes which
147
+ classifications block vs warn, per-severity confidence thresholds
148
+ that demote low-quality matches to `uncertain`, and per-finding-kind
149
+ block rules (`newSecret`, `newCriticalSecurity`,
150
+ `newCriticalDependencyVulnerability`, etc.). Compiled-in defaults
151
+ ship a conservative posture: block on `added`, warn on
152
+ `tooling_drift` / `config_drift` / `newly_detected` /
153
+ `probable_existing` / `uncertain`. The `--policy <path>` flag
154
+ overrides auto-discovery; when no policy is found, the defaults
155
+ apply.
156
+
157
+ #### Architectural fixes surfaced by the customer-repo audit
158
+
159
+ A pre-ship audit on three real customer repositories (a 444-source
160
+ TypeScript backend, a 553-source TypeScript frontend, and a
161
+ .NET WinForms project) surfaced four drift classes between the
162
+ report aggregates and the per-finding identity sets the baseline
163
+ captures. All four are closed in 2.5.0:
164
+
165
+ 1. **Large-file producer was capped at top 10.** The gather layer
166
+ pre-sliced `largestFiles` to ten entries for the markdown
167
+ renderer's "Top Files by Size" table; the baseline producer
168
+ inherited the cap and silently dropped per-file identity for
169
+ every oversized file beyond the first ten. A real customer
170
+ brownfield with 47 files over 500 lines saw 10 baseline entries;
171
+ the .NET project with 926 oversized files saw 10. The gather now
172
+ emits every file over the 500-line threshold sorted descending;
173
+ the renderer adds an explicit `.slice(0, 10)` at the table site.
174
+ `HealthMetrics.filesOver500Lines` aggregate now matches the
175
+ per-kind count in the baseline byte for byte. Combined recovery
176
+ across the three audit repos: 1,087 previously-silently-missed
177
+ `large-file` findings now flow into baselines.
178
+
179
+ 2. **Secret-HMAC producer emitted duplicates.** When the same
180
+ secret value appeared at multiple locations — the same token on
181
+ two lines of one file, a leaked key in both `.env` and
182
+ `src/config.ts`, or two overlapping gitleaks rules firing on the
183
+ same line — the producer wrote multiple entries with identical
184
+ `(rule, hmac)` identity. Identity sets aren't supposed to have
185
+ duplicates by definition. Now a per-call `Set<string>` keyed on
186
+ the computed identity collapses repeats; first write wins,
187
+ output order is stable.
188
+
189
+ 3. **Tools-map version probes occasionally cached `'present'`
190
+ under load.** The per-process version cache locks the first
191
+ probe's outcome to keep `toolchainHash` byte-stable across two
192
+ back-to-back gathers (a previously-shipped flake closure). But
193
+ when the first `execSync(<tool> --version)` raced its 5-second
194
+ timeout under heavy CPU load — parallel scanner pools or the
195
+ post-merge workflow doing two scans in series — the cache locked
196
+ the `'present'` fallback for the rest of the process. The tools
197
+ map in the baseline file then read `gitleaks@present` instead of
198
+ a real version, and the next run flagged spurious tooling-drift.
199
+ The fix retries the version probe up to three times before
200
+ falling back; each attempt is fresh. The cache layer is
201
+ unchanged — once a value settles (real version or genuine
202
+ `'present'`), it's locked for the rest of the process.
203
+
204
+ 4. **TypeScript license enrichment could stall the entire licenses
205
+ capability.** `gatherTsLicensesResult` calls `enrichReleaseDates`
206
+ after license-checker returns to populate the optional
207
+ `releaseDate` field from the npm registry. The enrichment runs
208
+ with 20-way concurrency, 10s per request — usually fast — but a
209
+ flaky network or rate-limited registry can push a 700-package
210
+ run past the dispatcher's 720-second deadline. When that
211
+ happens, the entire licenses capability is dropped and the
212
+ baseline silently loses every license entry. On the TypeScript
213
+ frontend audit repo, license-checker itself returned 749KB of
214
+ JSON in under 10 seconds when invoked manually; the enrichment
215
+ stalled the whole capability. Now the enrichment is raced
216
+ against a 60-second wall-clock budget; on timeout, the license
217
+ findings still emit with their static fields and `releaseDate`
218
+ is left unset on the unenriched ones. A previously-zero baseline
219
+ now captures 1,897 license entries on that repo.
220
+
221
+ Together these four fixes recover **~3,000 baseline findings** that
222
+ were being silently dropped on real customer repos pre-2.5.0.
223
+
224
+ #### Migration guidance for 2.4.x users
225
+
226
+ No breaking changes. Existing analyzer commands continue to work
227
+ exactly as before. The new commands and flags are additive.
228
+
229
+ To start using guardrails on an existing repo:
230
+
231
+ ```bash
232
+ vyuh-dxkit init --with-hooks --with-ci --with-baseline-refresh
233
+ git config core.hooksPath .githooks
234
+ vyuh-dxkit baseline create
235
+ git add .dxkit/baselines/main.json .githooks .github/workflows/dxkit-*.yml
236
+ git commit -m "chore: enable dxkit guardrails"
237
+ ```
238
+
239
+ See [`docs/getting-started.md`](docs/getting-started.md),
240
+ [`docs/commands/baseline.md`](docs/commands/baseline.md),
241
+ [`docs/commands/guardrail.md`](docs/commands/guardrail.md), and
242
+ [`docs/configuration/policy.md`](docs/configuration/policy.md) for
243
+ the full walkthrough.
244
+
10
245
  ## [2.4.8] - 2026-05-18
11
246
 
12
247
  ### Summary