@vyuhlabs/dxkit 2.4.4 → 2.4.5

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 (48) hide show
  1. package/CHANGELOG.md +202 -0
  2. package/README.md +15 -11
  3. package/dist/analyzers/tools/jacoco.d.ts +76 -0
  4. package/dist/analyzers/tools/jacoco.d.ts.map +1 -0
  5. package/dist/analyzers/tools/jacoco.js +228 -0
  6. package/dist/analyzers/tools/jacoco.js.map +1 -0
  7. package/dist/analyzers/tools/osv-scanner-fix.d.ts +20 -0
  8. package/dist/analyzers/tools/osv-scanner-fix.d.ts.map +1 -1
  9. package/dist/analyzers/tools/osv-scanner-fix.js +45 -20
  10. package/dist/analyzers/tools/osv-scanner-fix.js.map +1 -1
  11. package/dist/analyzers/tools/osv-scanner-maven.d.ts +42 -0
  12. package/dist/analyzers/tools/osv-scanner-maven.d.ts.map +1 -0
  13. package/dist/analyzers/tools/osv-scanner-maven.js +161 -0
  14. package/dist/analyzers/tools/osv-scanner-maven.js.map +1 -0
  15. package/dist/analyzers/tools/runner.d.ts +47 -0
  16. package/dist/analyzers/tools/runner.d.ts.map +1 -1
  17. package/dist/analyzers/tools/runner.js +79 -0
  18. package/dist/analyzers/tools/runner.js.map +1 -1
  19. package/dist/analyzers/tools/tool-registry.d.ts.map +1 -1
  20. package/dist/analyzers/tools/tool-registry.js +22 -0
  21. package/dist/analyzers/tools/tool-registry.js.map +1 -1
  22. package/dist/cli.d.ts.map +1 -1
  23. package/dist/cli.js +36 -2
  24. package/dist/cli.js.map +1 -1
  25. package/dist/constants.d.ts +1 -0
  26. package/dist/constants.d.ts.map +1 -1
  27. package/dist/languages/index.d.ts.map +1 -1
  28. package/dist/languages/index.js +10 -1
  29. package/dist/languages/index.js.map +1 -1
  30. package/dist/languages/java.d.ts +67 -0
  31. package/dist/languages/java.d.ts.map +1 -0
  32. package/dist/languages/java.js +419 -0
  33. package/dist/languages/java.js.map +1 -0
  34. package/dist/languages/kotlin.d.ts +1 -52
  35. package/dist/languages/kotlin.d.ts.map +1 -1
  36. package/dist/languages/kotlin.js +14 -286
  37. package/dist/languages/kotlin.js.map +1 -1
  38. package/dist/languages/types.d.ts +9 -1
  39. package/dist/languages/types.d.ts.map +1 -1
  40. package/dist/tools-cli.d.ts +16 -1
  41. package/dist/tools-cli.d.ts.map +1 -1
  42. package/dist/tools-cli.js +69 -6
  43. package/dist/tools-cli.js.map +1 -1
  44. package/dist/types.d.ts +1 -1
  45. package/dist/types.d.ts.map +1 -1
  46. package/package.json +2 -1
  47. package/templates/.claude/rules/java.md +11 -0
  48. package/templates/configs/java/README.md +6 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,208 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.4.5] - 2026-04-29
11
+
12
+ ### Fixed (high-severity, discovered during 2.4.5 pre-ship regression)
13
+
14
+ - **`osv-scanner fix` was THREE bugs in one** (5-month-old bug shipped
15
+ since 2.4.0 / Phase 10h.6). osv-scanner v2's `fix` subcommand invokes
16
+ `npm install` internally to compute upgrade patches. dxkit was
17
+ invoking it in the user's project cwd, which caused all three of the
18
+ following:
19
+
20
+ 1. **Data mutation** — `npm install` wipes / reinstalls the cwd's
21
+ `node_modules` (often with `--legacy-peer-deps` fallback when
22
+ peer-deps don't resolve cleanly). Visible to users running
23
+ back-to-back commands: `dxkit vulnerabilities` followed by `npm
24
+ test` or any other step depending on stable `node_modules` would
25
+ fail cryptically. Discovered when dxkit-on-dxkit crashed mid-run
26
+ with `Cannot find module 'hosted-git-info'`.
27
+
28
+ 2. **Process orphan leak** — osv-scanner's `npm install` grandchildren
29
+ outlived dxkit's 120s `execSync` budget. `execSync(..., {timeout})`
30
+ SIGTERMs only the immediate child; npm install + its node-package
31
+ subprocesses orphaned to PID 1 and kept eating CPU/memory until
32
+ they finished or the shell exited. Each `dxkit vulnerabilities`
33
+ invocation could leak 1-3 orphans; in CI this polluted subsequent
34
+ steps.
35
+
36
+ 3. **Silent BoM under-reporting** — when osv-scanner's npm install
37
+ left a partially-broken `node_modules` (peer-dep mismatches that
38
+ `--legacy-peer-deps` couldn't fully resolve), dxkit's BoM
39
+ aggregator subsequently couldn't enumerate the affected
40
+ dependencies. Root-project deps got silently dropped from the
41
+ BoM. On dxkit-on-dxkit comparison, 2.4.4 reported only 7 BoM
42
+ entries (sub-fixture deps) vs 2.4.5's 24 (sub-fixtures + dxkit's
43
+ own 17 root deps including `hosted-git-info`, `eslint`,
44
+ `typescript`, etc.). `unfilteredTotalPackages` 22 → 353. The
45
+ analyzed project's own deps were missing from BoM whenever the
46
+ bug hit. Most repos that resolve peer-deps cleanly under
47
+ `--legacy-peer-deps` weren't affected (vyuhlabs-platform's BoM
48
+ stayed correct at 145 packages); repos with subtle peer-dep
49
+ issues silently lost root-dep enumeration.
50
+
51
+ **Fix** (split across 10k.1.5b and 10k.1.5c):
52
+
53
+ - **Temp-dir isolation (10k.1.5b)**: stage `package.json` +
54
+ `package-lock.json` in a fresh temp dir before invoking osv-scanner,
55
+ discard the temp dir after parsing JSON output. Project's tree is
56
+ now read-only treatment (the contract dxkit's analyzers always
57
+ claimed). Stops bug #1 (mutation) and #3 (BoM under-reporting,
58
+ since `node_modules` no longer gets clobbered).
59
+
60
+ - **Process-group SIGKILL on timeout (10k.1.5c)**: new
61
+ `runDetached(cmd, args, opts)` helper in `src/analyzers/tools/runner.ts`
62
+ spawns the child in its own process group via
63
+ `spawn({ detached: true })` and `process.kill(-pid, 'SIGKILL')` on
64
+ timeout — kills grandchildren atomically. Stops bug #2 (orphan
65
+ leak). Reusable for any future tool that may fork grandchildren
66
+ (PMD's JVM, mvn, gradle).
67
+
68
+ Regression tests added: `test/osv-scanner-fix.test.ts` for the
69
+ isolation contract; `test/runner.test.ts` for the process-group
70
+ group-kill semantics (sleep-30-grandchild + 200ms timeout asserts
71
+ elapsed < 2s — would block 30s if process-group regressed). Caught
72
+ by the discipline the user pushed for: "never ship broken;
73
+ understand the root cause and fix properly". The discipline was
74
+ validated end-to-end — the same scan that found bug #1 also
75
+ surfaced #2 and #3 once we knew where to look.
76
+
77
+ **Forensic evidence preserved** at
78
+ `tmp/regression/2.4.4/dxkit/bom.json` (gitignored — 2.4.4 baseline
79
+ with under-reported BoM) vs `tmp/regression/2.4.5-fixed/dxkit/bom.json`
80
+ (full enumeration after the fix).
81
+
82
+
83
+
84
+ Phase 10k.1 — Java language pack (recipe stress test #1, JVM-cousin
85
+ shape). 7th language pack lands the cross-ecosystem matrix at
86
+ **8 active language packs** including Java with full capability
87
+ coverage. Recipe v3 makes substantial progress (G2 + G5 + G9
88
+ delivered; G1 partial; G4/G6/G7 deferred). D008 + D011 + a vitest
89
+ hookTimeout flake closed in pre-flight commits.
90
+
91
+ No breaking changes for end users. New depVulns/lint/coverage/
92
+ imports/testFramework data on Java/Maven projects; existing analyzer
93
+ commands produce identical output for non-Java projects.
94
+
95
+ ### Added
96
+
97
+ - **Java language pack** (Phase 10k.1) with five capability providers:
98
+ - **depVulns** via `osv-scanner` against `pom.xml` /
99
+ `gradle.lockfile` / `gradle/verification-metadata.xml`.
100
+ Implementation lives in the new shared
101
+ `src/analyzers/tools/osv-scanner-maven.ts` module that both
102
+ kotlin and java packs delegate to (CLAUDE.md rule #2 SSOT).
103
+ - **lint** via PMD 7.x with `rulesets/java/quickstart.xml`.
104
+ `parsePmdOutput` tiers PMD's 1-5 priority into dxkit's
105
+ critical/high/medium/low scheme via `mapPmdRuleSeverity`.
106
+ Real-fixture-driven parser tests against captured PMD 7.24.0
107
+ output at `test/fixtures/raw/java/pmd-output.json`.
108
+ - **coverage** via JaCoCo XML — reuses the kotlin pack's parser
109
+ unchanged (the parser was source-language-agnostic from day 1
110
+ and is now hosted in `src/analyzers/tools/jacoco.ts`). Path
111
+ candidates extended for Maven (`target/site/jacoco/jacoco.xml`,
112
+ `target/site/jacoco-aggregate/jacoco.xml`) alongside the existing
113
+ Gradle paths.
114
+ - **imports** via regex extraction over `import [static]
115
+ <fqn>(.<Class>|.*)?;` after stripping line + block comments.
116
+ Best-effort resolution (matches kotlin/rust pack semantics —
117
+ Java package paths don't 1:1 map to filesystem paths in all
118
+ build layouts).
119
+ - **testFramework** via build-file substring scan of pom.xml +
120
+ build.gradle{,.kts} for canonical artifact names. Order honors
121
+ mixed-state migration: junit-jupiter > spock > testng > junit4.
122
+ - **PMD (`pmd`) in TOOL_DEFS**. PMD 7.x as the canonical Java linter,
123
+ with brew on macOS / GitHub releases zip on Linux / scoop on
124
+ Windows. CI install step added.
125
+ - **Java cross-ecosystem benchmark fixture**
126
+ (`test/fixtures/benchmarks/java/`) — five files (Secrets.java with
127
+ fake AWS key, BadLint.java with PMD violations, Duplications.java
128
+ with jscpd clone pair, UntestedModule.java for filename-match
129
+ test-gap, pom.xml with `commons-collections:3.2.1` for the original
130
+ "Mad Gadget" CVE-2015-7501 deserialization advisory + log4j-core
131
+ for Log4Shell). Matrix wins on all four dimensions (secret/dup/
132
+ test-gaps run unconditionally; lint matrix activates with
133
+ `requires: 'pmd'`).
134
+ - **`scripts/check-docs-coverage.sh` (Recipe v3 / G5).** Pre-commit +
135
+ CI gate that asserts every `LanguageId` in `src/languages/index.ts`
136
+ appears in canonical doc anchors (CLAUDE.md path glob; README.md
137
+ ecosystem coverage table row count + ID substring mention). Closes
138
+ the kotlin-PR-#23 follow-up class of failure where a pack ships in
139
+ main but docs go stale because nobody remembered to update them.
140
+ - **`vyuh-dxkit tools install <name>` and `--all` (D011).** Single-tool
141
+ install for cross-stack development (e.g. installing `spotbugs` /
142
+ `pmd` on a Node-only repo); `--all` enumerates every TOOL_DEFS
143
+ entry. Unknown names fail loudly with an "Unknown tool" message +
144
+ pointer to `tools list`. Used during this phase's PMD harvest.
145
+ - **CLAUDE.md merge-strategy guidance**. Codifies when PRs should
146
+ squash-merge (single logical unit) vs rebase-merge (multiple
147
+ independently-meaningful commits with prose-quality messages —
148
+ what this PR did to preserve D008/D011/G2/G5/G9 + 5 capability
149
+ commits as discrete history).
150
+
151
+ ### Refactored (architectural improvement)
152
+
153
+ - **`src/analyzers/tools/jacoco.ts`** — extracted from kotlin pack
154
+ in 10k.1.2. Owns `parseJaCoCoXml`, `findJaCoCoReport`,
155
+ `gatherJaCoCoCoverageResult`. Both JVM packs delegate. Parser was
156
+ always source-language-agnostic; just relocating to the right home.
157
+ - **`src/analyzers/tools/osv-scanner-maven.ts`** — extracted from
158
+ kotlin pack in 10k.1.4. Same pattern. Owns
159
+ `parseOsvScannerMavenFindings` + `gatherOsvScannerMavenDepVulnsResult`.
160
+ Both JVM packs delegate. Parser was already ecosystem-filtered to
161
+ Maven (not Kotlin-coupled); just relocating.
162
+ - **Capabilities contract is genuinely optional (Recipe v3 / G2).**
163
+ `capabilities-contract.test.ts:117` previously asserted
164
+ `providers.length === LANGUAGES.length` for the depVulns capability,
165
+ forcing packs without depVulns to register null-stub providers.
166
+ Now: `expect(providers.length).toBe(LANGUAGES.filter((l) =>
167
+ l.capabilities?.depVulns).length)` — precise contract, packs can
168
+ omit. Unblocks Swift's eventual graceful-degradation pattern.
169
+ Java's null-stub from intermediate commits retired.
170
+ - **`detectJava` is source-presence-driven, not manifest-driven
171
+ (Recipe v3 / G9).** Initial detection activated on bare `pom.xml`,
172
+ which broke kotlin's matrix lint test because kotlin's fixture has
173
+ pom.xml (for osv-scanner Maven). Both packs activated → lintTool
174
+ came back as `'detekt, pmd'`. Fix: require either `src/main/java/`
175
+ directory OR actual `.java` source within depth 5. Mixed Kotlin +
176
+ Java projects still activate both packs (correct). G9 noted as a
177
+ scaffolder-template fix candidate — the scaffolded `detect()` stub
178
+ currently suggests "manifest signals" which is the bug we just hit.
179
+
180
+ ### Fixed
181
+
182
+ - **D008 — stale test-fixture types + missing contract test.** 21 type
183
+ errors surfaced when `tsc --noEmit` runs against `src + test`
184
+ together (`DimensionScore.details` / `DuplicationStats.totalLines`
185
+ field drift; `DepVulnFinding.source` → renamed to `.tool`;
186
+ `mapLintSeverity` contract was narrower than every impl reality;
187
+ spread-duplication cleanups). Adds `tsconfig.test.json` +
188
+ `npm run typecheck:test` + wires into `.husky/pre-push` and
189
+ `.github/workflows/ci.yml`. The contract test paid for itself in the
190
+ same session — caught a `Record<LanguageId, boolean>` literal
191
+ regression introduced 30 minutes earlier.
192
+ - **`scripts/check-cross-ecosystem-coverage.sh` Prettier robustness
193
+ (Recipe v3 / G1, partial).** Auto-derive parser assumed single-line
194
+ `LANGUAGES = [...]`. Prettier reformatted to multi-line at the 7th
195
+ entry (line-length budget) and the gate parsed 0 entries silently.
196
+ Switched to awk block extract — robust to both shapes. One
197
+ instance fixed; class-wide audit of similar parsers deferred.
198
+ - **Vitest `hookTimeout` default of 10s caused C# `beforeAll` flakes.**
199
+ `dotnet restore` against a cold NuGet cache routinely takes 18-44s
200
+ on WSL2. Now matches `testTimeout` at 180s.
201
+
202
+ ### Phase 10k roadmap
203
+
204
+ After 10k.1 (Java) ships in 2.4.5, **10k.2 (Ruby) ships in 2.4.6** as
205
+ recipe stress test #2 — fully dynamic language outside the JVM family.
206
+ Then **2.5.0 (Phase 10i — fingerprints + exec summary across 8-language
207
+ matrix)**. Phase 10j.2 (Swift/iOS) is **deferred to post-10rr / pre-3.0.0
208
+ opportunistic slot** because Linux/WSL2 development can't validate the
209
+ xcodeproj-shape majority without macOS access. See
210
+ `tmp/phase-10k-backend-langs-roadmap.md` for the full phase plan.
211
+
10
212
  ## [2.4.4] - 2026-04-27
11
213
 
12
214
  Phase 10j.1 — first mobile language pack (Kotlin/Android), Recipe v2
package/README.md CHANGED
@@ -45,7 +45,7 @@ Seven deterministic analyzers. Each emits a markdown report to `.dxkit/reports/`
45
45
  | `test-gaps` | Coverage artifact → import-graph → filename (strongest wins) | <1s | `.dxkit/reports/test-gaps-<date>.md` |
46
46
  | `quality` | Slop score + jscpd duplication + eslint/ruff + hygiene | 5–15s | `.dxkit/reports/quality-review-<date>.md` |
47
47
  | `dev-report` | Commits, contributors, hot files, velocity, conventional % | <1s | `.dxkit/reports/developer-report-<date>.md` |
48
- | `licenses` | Dependency license inventory across every active pack (TS/Python/Go/Rust/C#) | 5–20s | `.dxkit/reports/licenses-<date>.md` |
48
+ | `licenses` | Dependency license inventory across every active pack (TS, Python, Go, Rust, C#; Kotlin + Java omitted — no canonical CLI license tool for Maven/Gradle ecosystems) | 5–20s | `.dxkit/reports/licenses-<date>.md` |
49
49
  | `bom` | **Bill of Materials** — joins licenses + vulns per package, groups by top-level manifest dep (Snyk-style), enriches with CISA KEV + EPSS + reachability, ranks by composite risk score with "This Week's Triage" summary, aggregates nested sub-projects, `--filter=top-level` collapses transitive rows, 15-col XLSX | 10–40s | `.dxkit/reports/bom-<date>.{md,xlsx}` |
50
50
 
51
51
  Plus a converter: `vyuh-dxkit to-xlsx <json-file>` renders any `licenses` or `bom` detailed JSON as the canonical 15-column XLSX.
@@ -77,7 +77,7 @@ Plus a converter: `vyuh-dxkit to-xlsx <json-file>` renders any `licenses` or `bo
77
77
 
78
78
  Three signals, strongest wins for files it covers:
79
79
 
80
- 1. **Coverage artifact** — Istanbul JSON (TS/JS), `coverage.json` (Python), `coverage.out` (Go), cobertura XML (C#/Rust), `lcov.info` (Rust). If the tool measured a file, that decision is authoritative.
80
+ 1. **Coverage artifact** — Istanbul JSON (TS/JS), `coverage.json` (Python), `coverage.out` (Go), cobertura XML (C#/Rust), `lcov.info` (Rust), JaCoCo XML (Kotlin). If the tool measured a file, that decision is authoritative.
81
81
  2. **Import-graph reachability** — files transitively imported from an active test file (up to 3 hops). Rescues integration tests + behavior-named tests the filename matcher misses.
82
82
  3. **Filename match** — last-resort basename similarity.
83
83
 
@@ -105,6 +105,8 @@ vyuh-dxkit tools install # interactive: prompts per tool
105
105
  | Go | `golangci-lint`, `govulncheck` |
106
106
  | Rust | `clippy`, `cargo-audit`, `cargo-llvm-cov` |
107
107
  | C# | `dotnet-format` (via SDK — formatter, not a linter) |
108
+ | Kotlin | `detekt` (Checkstyle XML), `osv-scanner` (Maven), JaCoCo XML |
109
+ | Java | `pmd` (PMD 7.x JSON), `osv-scanner` (Maven), JaCoCo XML reuse |
108
110
 
109
111
  Install commands are platform-aware (brew on macOS, user-local install on Linux, winget/scoop on Windows). Tools install into `~/.local/bin` or similar user paths — no `sudo` required.
110
112
 
@@ -167,15 +169,17 @@ npm run new-lang kotlin "Kotlin (Android)"
167
169
 
168
170
  This scaffolds the 7 recipe files (pack module, test stub, fixture skeleton, Claude rule file, template-config dir, plus `LanguageId` union extension and `LANGUAGES` registration). See [CONTRIBUTING.md](./CONTRIBUTING.md) for the full walkthrough. Recipe enforcement (architecture greps + contract tests + synthetic 6th-pack playbook) runs in pre-commit so packs that miss required metadata fail CI.
169
171
 
170
- | Language | Detection | Coverage import | Import-graph | Native tools | Lint severity tiers | Vuln severity tiers |
171
- | -------- | ------------------------------------ | ------------------- | -------------------------------------- | ----------------------------------- | ---------------------- | ----------------------------------- |
172
- | TS / JS | `package.json` | ✅ Istanbul | ✅ import/require/re-export | eslint, npm audit, vitest-coverage | ✅ ESLint rule ID | ✅ npm audit native |
173
- | Python | `pyproject.toml`, `setup.py`, `*.py` | ✅ coverage.py | ✅ import/from | ruff, pip-audit, coverage | ✅ ruff code prefix | ✅ pip-audit + OSV.dev (CVSS v3+v4) |
174
- | Go | `go.mod` | ✅ coverprofile | ✅ import blocks | golangci-lint, govulncheck | ✅ `FromLinter` family | ✅ govulncheck embedded + OSV.dev |
175
- | Rust | `Cargo.toml` | ✅ lcov + cobertura | ⚠️ use statements, extracted only¹ | clippy, cargo-audit, cargo-llvm-cov | ✅ clippy group | ✅ cargo-audit native |
176
- | C# | `*.csproj`, `*.sln` | ✅ cobertura XML | ⚠️ using declarations, extracted only¹ | dotnet-format (formatter) | ❌ (no linter yet) | ✅ dotnet list --vulnerable |
177
-
178
- ¹ Rust + C# packs populate `imports.extracted` but the file-level resolver is a no-op — Rust's `use` paths and C#'s `using` namespaces don't map 1:1 to source files. Downstream analyses that need an edge graph (reachability for dep-vulns, import-graph credit for test-gaps) degrade to conservative defaults for these two languages. Resolvers are planned; see Phase 10i-L.2 in the roadmap.
172
+ | Language | Detection | Coverage import | Import-graph | Native tools | Lint severity tiers | Vuln severity tiers |
173
+ | -------- | ------------------------------------- | ------------------- | -------------------------------------- | ----------------------------------- | ---------------------- | ----------------------------------- |
174
+ | TS / JS | `package.json` | ✅ Istanbul | ✅ import/require/re-export | eslint, npm audit, vitest-coverage | ✅ ESLint rule ID | ✅ npm audit native |
175
+ | Python | `pyproject.toml`, `setup.py`, `*.py` | ✅ coverage.py | ✅ import/from | ruff, pip-audit, coverage | ✅ ruff code prefix | ✅ pip-audit + OSV.dev (CVSS v3+v4) |
176
+ | Go | `go.mod` | ✅ coverprofile | ✅ import blocks | golangci-lint, govulncheck | ✅ `FromLinter` family | ✅ govulncheck embedded + OSV.dev |
177
+ | Rust | `Cargo.toml` | ✅ lcov + cobertura | ⚠️ use statements, extracted only¹ | clippy, cargo-audit, cargo-llvm-cov | ✅ clippy group | ✅ cargo-audit native |
178
+ | C# | `*.csproj`, `*.sln` | ✅ cobertura XML | ⚠️ using declarations, extracted only¹ | dotnet-format (formatter) | ❌ (no linter yet) | ✅ dotnet list --vulnerable |
179
+ | Kotlin | gradle/`*.gradle{.kts,}`, `*.kt` | ✅ JaCoCo XML | ⚠️ import statements, extracted only¹ | detekt, osv-scanner (Maven) | ✅ detekt severity | ✅ osv-scanner + OSV.dev (Maven) |
180
+ | Java | `pom.xml`, `src/main/java/`, `*.java` | JaCoCo XML | ⚠️ import statements, extracted only¹ | PMD, osv-scanner (Maven) | PMD priority tiers | osv-scanner + OSV.dev (Maven) |
181
+
182
+ ¹ Rust, C#, Kotlin, and Java packs populate `imports.extracted` but the file-level resolver is a no-op — Rust's `use` paths, C#'s `using` namespaces, Kotlin's and Java's `import` package paths don't map 1:1 to source files. Downstream analyses that need an edge graph (reachability for dep-vulns, import-graph credit for test-gaps) degrade to conservative defaults for these four languages. Resolvers are planned; see Phase 10i-L.2 in the roadmap.
179
183
 
180
184
  ✅ full support. Multi-language repos fully supported — every detected language's tools run, and dep-vuln counts aggregate across all language packs via the `depVulns` capability (pip-audit findings don't silently replace npm-audit ones).
181
185
 
@@ -0,0 +1,76 @@
1
+ import { type Coverage } from './coverage';
2
+ import type { CoverageResult } from '../../languages/capabilities/types';
3
+ /**
4
+ * Pure parser for JaCoCo's XML report (DTD: `report.dtd`). The structure:
5
+ *
6
+ * <report name="...">
7
+ * <package name="com/example">
8
+ * <class name="com/example/Foo" sourcefilename="Foo.kt">...</class>
9
+ * <sourcefile name="Foo.kt">
10
+ * <line nr="N" mi="..." ci="..." mb="..." cb="..."/>
11
+ * <counter type="LINE" missed="X" covered="Y"/>
12
+ * </sourcefile>
13
+ * <counter type="LINE" missed="X" covered="Y"/>
14
+ * </package>
15
+ * <counter type="LINE" missed="X" covered="Y"/>
16
+ * </report>
17
+ *
18
+ * Per-file coverage comes from `<sourcefile>` blocks: their LINE counter
19
+ * holds the file's missed/covered totals. Project-level total comes from
20
+ * the top-level `<counter type="LINE">` (last in the document).
21
+ *
22
+ * Path attribution joins `<package name>` (forward-slashed, JVM-style)
23
+ * with `<sourcefile name>` to produce the canonical relative path the
24
+ * downstream consumers expect (`com/example/Foo.kt` or
25
+ * `com/example/Foo.java`). JVM bytecode namespacing isn't 1:1 with
26
+ * on-disk source paths in multi-module projects — accepted limitation
27
+ * (matches C#'s cobertura attribution).
28
+ *
29
+ * Returns null when no `<counter type="LINE">` exists at the top level
30
+ * — that's JaCoCo's "no coverage data" signal, distinct from "0%
31
+ * coverage" (where the counter exists with covered=0).
32
+ *
33
+ * Language-agnostic: works for Kotlin (.kt), Java (.java), and any
34
+ * other JVM language whose JaCoCo output respects the `<package>` /
35
+ * `<sourcefile>` shape — `<sourcefile name>` carries the on-disk
36
+ * filename verbatim so the parser doesn't need to know the language.
37
+ */
38
+ export declare function parseJaCoCoXml(raw: string, sourceFile: string, _cwd: string): Coverage | null;
39
+ /**
40
+ * Standard JaCoCo report locations across JVM build tools and project
41
+ * layouts:
42
+ *
43
+ * GRADLE (kotlin + java):
44
+ * - app/build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml
45
+ * (Android default — `app` module, `jacocoTestReport` task)
46
+ * - build/reports/jacoco/test/jacocoTestReport.xml
47
+ * (plain JVM via the `jacoco` plugin's default `test` task)
48
+ * - build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml
49
+ * (multi-module aggregate; many builds rename the task)
50
+ *
51
+ * MAVEN (java):
52
+ * - target/site/jacoco/jacoco.xml
53
+ * (default Maven JaCoCo plugin — single-module Java)
54
+ * - target/site/jacoco-aggregate/jacoco.xml
55
+ * (Maven multi-module aggregate via jacoco-maven-plugin's
56
+ * `report-aggregate` goal)
57
+ *
58
+ * FALLBACKS:
59
+ * - jacocoTestReport.xml (top-level — fixture / direct path)
60
+ * - jacoco.xml (top-level — Maven fixture / direct path)
61
+ *
62
+ * Returns the first existing path, relative to cwd. Conservative
63
+ * priority: most specific build-tool conventions first, root
64
+ * fallbacks last.
65
+ */
66
+ export declare function findJaCoCoReport(cwd: string): string | null;
67
+ /**
68
+ * Locate + parse the JaCoCo XML report under cwd, wrap the result in a
69
+ * `CoverageResult` envelope. Identical glue across JVM packs (kotlin,
70
+ * java) — no language-specific dispatch needed because JaCoCo's
71
+ * `<sourcefile name>` carries the on-disk filename verbatim and the
72
+ * file extension survives intact through the parser. Both packs'
73
+ * `coverageProvider.gather` should delegate here.
74
+ */
75
+ export declare function gatherJaCoCoCoverageResult(cwd: string): CoverageResult | null;
76
+ //# sourceMappingURL=jacoco.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jacoco.d.ts","sourceRoot":"","sources":["../../../src/analyzers/tools/jacoco.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,KAAK,QAAQ,EAA6B,MAAM,YAAY,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAmE7F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkB3D;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAY7E"}
@@ -0,0 +1,228 @@
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.parseJaCoCoXml = parseJaCoCoXml;
37
+ exports.findJaCoCoReport = findJaCoCoReport;
38
+ exports.gatherJaCoCoCoverageResult = gatherJaCoCoCoverageResult;
39
+ /**
40
+ * JaCoCo XML report parser + standard-location finder. Shared across
41
+ * JVM-language packs (kotlin, java) — single source of truth per
42
+ * CLAUDE.md rule #2 ("Each tool has ONE gather function … if another
43
+ * module needs that tool's output, it MUST call the existing
44
+ * function").
45
+ *
46
+ * Extracted from `src/languages/kotlin.ts` in 10k.1.2 (Phase 10k.1
47
+ * SSOT validation) — when the Java pack needed JaCoCo coverage, the
48
+ * parser was already generic (kotlin's own tests cover it against
49
+ * Java source, see test/languages-kotlin.test.ts). Forking would
50
+ * have been the architectural violation; relocating to a shared
51
+ * tool module is the correct outcome.
52
+ */
53
+ const fs = __importStar(require("fs"));
54
+ const path = __importStar(require("path"));
55
+ const coverage_1 = require("./coverage");
56
+ /**
57
+ * Pure parser for JaCoCo's XML report (DTD: `report.dtd`). The structure:
58
+ *
59
+ * <report name="...">
60
+ * <package name="com/example">
61
+ * <class name="com/example/Foo" sourcefilename="Foo.kt">...</class>
62
+ * <sourcefile name="Foo.kt">
63
+ * <line nr="N" mi="..." ci="..." mb="..." cb="..."/>
64
+ * <counter type="LINE" missed="X" covered="Y"/>
65
+ * </sourcefile>
66
+ * <counter type="LINE" missed="X" covered="Y"/>
67
+ * </package>
68
+ * <counter type="LINE" missed="X" covered="Y"/>
69
+ * </report>
70
+ *
71
+ * Per-file coverage comes from `<sourcefile>` blocks: their LINE counter
72
+ * holds the file's missed/covered totals. Project-level total comes from
73
+ * the top-level `<counter type="LINE">` (last in the document).
74
+ *
75
+ * Path attribution joins `<package name>` (forward-slashed, JVM-style)
76
+ * with `<sourcefile name>` to produce the canonical relative path the
77
+ * downstream consumers expect (`com/example/Foo.kt` or
78
+ * `com/example/Foo.java`). JVM bytecode namespacing isn't 1:1 with
79
+ * on-disk source paths in multi-module projects — accepted limitation
80
+ * (matches C#'s cobertura attribution).
81
+ *
82
+ * Returns null when no `<counter type="LINE">` exists at the top level
83
+ * — that's JaCoCo's "no coverage data" signal, distinct from "0%
84
+ * coverage" (where the counter exists with covered=0).
85
+ *
86
+ * Language-agnostic: works for Kotlin (.kt), Java (.java), and any
87
+ * other JVM language whose JaCoCo output respects the `<package>` /
88
+ * `<sourcefile>` shape — `<sourcefile name>` carries the on-disk
89
+ * filename verbatim so the parser doesn't need to know the language.
90
+ */
91
+ function parseJaCoCoXml(raw, sourceFile, _cwd) {
92
+ const files = new Map();
93
+ // Iterate <package> blocks. Each block contains <sourcefile> children
94
+ // we tally and aggregate counters we can ignore (they're sums of the
95
+ // children, redundant given we sum the children ourselves).
96
+ const packageRe = /<package\s+name="([^"]+)">([\s\S]*?)<\/package>/g;
97
+ let pm;
98
+ while ((pm = packageRe.exec(raw)) !== null) {
99
+ const pkgPath = pm[1].replace(/\\/g, '/'); // JVM uses forward-slashes already; defensive
100
+ const pkgInner = pm[2];
101
+ // Within a <package>, <sourcefile> blocks own per-file counters.
102
+ const sourceFileRe = /<sourcefile\s+name="([^"]+)">([\s\S]*?)<\/sourcefile>/g;
103
+ let sm;
104
+ while ((sm = sourceFileRe.exec(pkgInner)) !== null) {
105
+ const fileName = sm[1];
106
+ const sourceInner = sm[2];
107
+ // The LAST <counter type="LINE"> in <sourcefile> is the
108
+ // file-level aggregate; earlier ones are per-method. We pick the
109
+ // last to get the full-file roll-up.
110
+ const counterRe = /<counter\s+type="LINE"\s+missed="(\d+)"\s+covered="(\d+)"\s*\/>/g;
111
+ let lastMissed = 0;
112
+ let lastCovered = 0;
113
+ let cm;
114
+ while ((cm = counterRe.exec(sourceInner)) !== null) {
115
+ lastMissed = parseInt(cm[1], 10);
116
+ lastCovered = parseInt(cm[2], 10);
117
+ }
118
+ const total = lastMissed + lastCovered;
119
+ const rel = pkgPath ? `${pkgPath}/${fileName}` : fileName;
120
+ files.set(rel, {
121
+ path: rel,
122
+ covered: lastCovered,
123
+ total,
124
+ pct: (0, coverage_1.round1)(total > 0 ? (lastCovered / total) * 100 : 0),
125
+ });
126
+ }
127
+ }
128
+ // Top-level project-wide LINE counter — JaCoCo emits it after the
129
+ // last </package>. Use a non-greedy match against the document tail
130
+ // to avoid grabbing per-package counters as project-level.
131
+ const tailMatch = raw.match(/<\/package>\s*<counter\s+type="LINE"\s+missed="(\d+)"\s+covered="(\d+)"\s*\/>\s*<\/report>/);
132
+ let totalMissed = 0;
133
+ let totalCovered = 0;
134
+ if (tailMatch) {
135
+ totalMissed = parseInt(tailMatch[1], 10);
136
+ totalCovered = parseInt(tailMatch[2], 10);
137
+ }
138
+ else {
139
+ // No project-level counter (degenerate report — single package, no
140
+ // explicit roll-up). Sum the per-file totals as the linePercent
141
+ // basis.
142
+ for (const f of files.values()) {
143
+ totalCovered += f.covered;
144
+ totalMissed += f.total - f.covered;
145
+ }
146
+ }
147
+ const grandTotal = totalCovered + totalMissed;
148
+ if (grandTotal === 0 && files.size === 0)
149
+ return null;
150
+ return {
151
+ source: 'jacoco',
152
+ sourceFile,
153
+ linePercent: (0, coverage_1.round1)(grandTotal > 0 ? (totalCovered / grandTotal) * 100 : 0),
154
+ files,
155
+ };
156
+ }
157
+ /**
158
+ * Standard JaCoCo report locations across JVM build tools and project
159
+ * layouts:
160
+ *
161
+ * GRADLE (kotlin + java):
162
+ * - app/build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml
163
+ * (Android default — `app` module, `jacocoTestReport` task)
164
+ * - build/reports/jacoco/test/jacocoTestReport.xml
165
+ * (plain JVM via the `jacoco` plugin's default `test` task)
166
+ * - build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml
167
+ * (multi-module aggregate; many builds rename the task)
168
+ *
169
+ * MAVEN (java):
170
+ * - target/site/jacoco/jacoco.xml
171
+ * (default Maven JaCoCo plugin — single-module Java)
172
+ * - target/site/jacoco-aggregate/jacoco.xml
173
+ * (Maven multi-module aggregate via jacoco-maven-plugin's
174
+ * `report-aggregate` goal)
175
+ *
176
+ * FALLBACKS:
177
+ * - jacocoTestReport.xml (top-level — fixture / direct path)
178
+ * - jacoco.xml (top-level — Maven fixture / direct path)
179
+ *
180
+ * Returns the first existing path, relative to cwd. Conservative
181
+ * priority: most specific build-tool conventions first, root
182
+ * fallbacks last.
183
+ */
184
+ function findJaCoCoReport(cwd) {
185
+ const candidates = [
186
+ // Gradle (Android + plain JVM)
187
+ 'app/build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml',
188
+ 'build/reports/jacoco/test/jacocoTestReport.xml',
189
+ 'build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml',
190
+ // Maven (single-module + multi-module aggregate)
191
+ 'target/site/jacoco/jacoco.xml',
192
+ 'target/site/jacoco-aggregate/jacoco.xml',
193
+ // Direct-path fallbacks (fixture / hand-placed)
194
+ 'jacocoTestReport.xml',
195
+ 'jacoco.xml',
196
+ ];
197
+ for (const rel of candidates) {
198
+ const abs = path.join(cwd, rel);
199
+ if (fs.existsSync(abs))
200
+ return rel;
201
+ }
202
+ return null;
203
+ }
204
+ /**
205
+ * Locate + parse the JaCoCo XML report under cwd, wrap the result in a
206
+ * `CoverageResult` envelope. Identical glue across JVM packs (kotlin,
207
+ * java) — no language-specific dispatch needed because JaCoCo's
208
+ * `<sourcefile name>` carries the on-disk filename verbatim and the
209
+ * file extension survives intact through the parser. Both packs'
210
+ * `coverageProvider.gather` should delegate here.
211
+ */
212
+ function gatherJaCoCoCoverageResult(cwd) {
213
+ const reportRel = findJaCoCoReport(cwd);
214
+ if (!reportRel)
215
+ return null;
216
+ let raw;
217
+ try {
218
+ raw = fs.readFileSync(path.join(cwd, reportRel), 'utf-8');
219
+ }
220
+ catch {
221
+ return null;
222
+ }
223
+ const coverage = parseJaCoCoXml(raw, reportRel, cwd);
224
+ if (!coverage)
225
+ return null;
226
+ return { schemaVersion: 1, tool: `coverage:${coverage.source}`, coverage };
227
+ }
228
+ //# sourceMappingURL=jacoco.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jacoco.js","sourceRoot":"","sources":["../../../src/analyzers/tools/jacoco.ts"],"names":[],"mappings":"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"}
@@ -32,6 +32,26 @@ import type { DepVulnFinding, DepVulnUpgradePlan } from '../../languages/capabil
32
32
  *
33
33
  * Never throws. `gatherTsDepVulnsResult` calls this unconditionally and
34
34
  * treats the empty map as "no enrichment available".
35
+ *
36
+ * **TEMP-DIR ISOLATION (10k.1.5b fix — discovered during 2.4.5 pre-ship
37
+ * regression):** osv-scanner v2's `fix` subcommand invokes `npm install`
38
+ * internally to compute upgrade patches. That `npm install` MUTATES the
39
+ * cwd's node_modules — wipes it then reinstalls (often with
40
+ * `--legacy-peer-deps` fallback if the project's deps don't resolve
41
+ * cleanly). On dxkit's own repo this caused subsequent dxkit subcommand
42
+ * invocations to crash with `Cannot find module 'hosted-git-info'`
43
+ * because osv-scanner's reinstall left an incomplete tree. On
44
+ * vyuhlabs-platform (835MB node_modules) the reinstall happened to
45
+ * succeed but still mutated state silently — a 5-month-old data-mutation
46
+ * bug shipped since 2.4.0 / Phase 10h.6 and only caught now because
47
+ * 2.4.5 pre-ship regression ran reports back-to-back on dxkit's own repo
48
+ * and tripped the chain.
49
+ *
50
+ * Mitigation: we copy `package.json` + `package-lock.json` to a fresh
51
+ * temp dir, run osv-scanner there, and discard the temp dir afterward.
52
+ * Output JSON identifies advisories by `(package, version, id)` tuples
53
+ * which are independent of cwd, so the upgrade-plan map we return is
54
+ * unchanged. The caller's project gets read-only treatment.
35
55
  */
36
56
  export declare function gatherOsvScannerFixPlans(cwd: string): Promise<Map<string, DepVulnUpgradePlan>>;
37
57
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"osv-scanner-fix.d.ts","sourceRoot":"","sources":["../../../src/analyzers/tools/osv-scanner-fix.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAqC7F;;;;;;;;;;;;GAYG;AACH,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CA+B1C;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAwCrF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,cAAc,EAAE,EAC1B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,GACrC,MAAM,CAaR;AAED;;;;;;;4BAO4B;AAC5B,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAEhF"}
1
+ {"version":3,"file":"osv-scanner-fix.d.ts","sourceRoot":"","sources":["../../../src/analyzers/tools/osv-scanner-fix.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAsC7F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAwC1C;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAwCrF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,cAAc,EAAE,EAC1B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,GACrC,MAAM,CAaR;AAED;;;;;;;4BAO4B;AAC5B,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAEhF"}