@vyuhlabs/dxkit 2.2.0 → 2.3.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.
- package/CHANGELOG.md +160 -0
- package/README.md +40 -29
- package/dist/analyzers/bom/discovery.d.ts +38 -0
- package/dist/analyzers/bom/discovery.d.ts.map +1 -0
- package/dist/analyzers/bom/discovery.js +166 -0
- package/dist/analyzers/bom/discovery.js.map +1 -0
- package/dist/analyzers/bom/gather.d.ts +28 -0
- package/dist/analyzers/bom/gather.d.ts.map +1 -1
- package/dist/analyzers/bom/gather.js +98 -0
- package/dist/analyzers/bom/gather.js.map +1 -1
- package/dist/analyzers/bom/index.d.ts +49 -2
- package/dist/analyzers/bom/index.d.ts.map +1 -1
- package/dist/analyzers/bom/index.js +188 -12
- package/dist/analyzers/bom/index.js.map +1 -1
- package/dist/analyzers/bom/types.d.ts +33 -1
- package/dist/analyzers/bom/types.d.ts.map +1 -1
- package/dist/analyzers/licenses/index.d.ts +1 -1
- package/dist/analyzers/licenses/index.d.ts.map +1 -1
- package/dist/analyzers/licenses/index.js +22 -7
- package/dist/analyzers/licenses/index.js.map +1 -1
- package/dist/analyzers/security/detailed.d.ts.map +1 -1
- package/dist/analyzers/security/detailed.js +21 -8
- package/dist/analyzers/security/detailed.js.map +1 -1
- package/dist/analyzers/security/gather.d.ts.map +1 -1
- package/dist/analyzers/security/gather.js +76 -1
- package/dist/analyzers/security/gather.js.map +1 -1
- package/dist/analyzers/security/index.d.ts.map +1 -1
- package/dist/analyzers/security/index.js +20 -7
- package/dist/analyzers/security/index.js.map +1 -1
- package/dist/analyzers/tools/epss.d.ts +55 -0
- package/dist/analyzers/tools/epss.d.ts.map +1 -0
- package/dist/analyzers/tools/epss.js +133 -0
- package/dist/analyzers/tools/epss.js.map +1 -0
- package/dist/analyzers/tools/graphify.d.ts.map +1 -1
- package/dist/analyzers/tools/graphify.js +17 -7
- package/dist/analyzers/tools/graphify.js.map +1 -1
- package/dist/analyzers/tools/kev.d.ts +52 -0
- package/dist/analyzers/tools/kev.d.ts.map +1 -0
- package/dist/analyzers/tools/kev.js +95 -0
- package/dist/analyzers/tools/kev.js.map +1 -0
- package/dist/analyzers/tools/npm-registry.d.ts +43 -0
- package/dist/analyzers/tools/npm-registry.d.ts.map +1 -0
- package/dist/analyzers/tools/npm-registry.js +107 -0
- package/dist/analyzers/tools/npm-registry.js.map +1 -0
- package/dist/analyzers/tools/osv.d.ts +12 -0
- package/dist/analyzers/tools/osv.d.ts.map +1 -1
- package/dist/analyzers/tools/osv.js +45 -2
- package/dist/analyzers/tools/osv.js.map +1 -1
- package/dist/analyzers/tools/reachability.d.ts +60 -0
- package/dist/analyzers/tools/reachability.d.ts.map +1 -0
- package/dist/analyzers/tools/reachability.js +104 -0
- package/dist/analyzers/tools/reachability.js.map +1 -0
- package/dist/analyzers/tools/risk-score.d.ts +69 -0
- package/dist/analyzers/tools/risk-score.d.ts.map +1 -0
- package/dist/analyzers/tools/risk-score.js +86 -0
- package/dist/analyzers/tools/risk-score.js.map +1 -0
- package/dist/analyzers/tools/tool-registry.d.ts +10 -0
- package/dist/analyzers/tools/tool-registry.d.ts.map +1 -1
- package/dist/analyzers/tools/tool-registry.js +35 -20
- package/dist/analyzers/tools/tool-registry.js.map +1 -1
- package/dist/analyzers/xlsx/bom.d.ts.map +1 -1
- package/dist/analyzers/xlsx/bom.js +1 -2
- package/dist/analyzers/xlsx/bom.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +41 -10
- package/dist/cli.js.map +1 -1
- package/dist/languages/capabilities/types.d.ts +6 -0
- package/dist/languages/capabilities/types.d.ts.map +1 -1
- package/dist/languages/csharp.d.ts.map +1 -1
- package/dist/languages/csharp.js +8 -0
- package/dist/languages/csharp.js.map +1 -1
- package/dist/languages/go.d.ts.map +1 -1
- package/dist/languages/go.js +24 -7
- package/dist/languages/go.js.map +1 -1
- package/dist/languages/python.d.ts.map +1 -1
- package/dist/languages/python.js +8 -0
- package/dist/languages/python.js.map +1 -1
- package/dist/languages/rust.d.ts.map +1 -1
- package/dist/languages/rust.js +9 -0
- package/dist/languages/rust.js.map +1 -1
- package/dist/languages/typescript.d.ts.map +1 -1
- package/dist/languages/typescript.js +23 -1
- package/dist/languages/typescript.js.map +1 -1
- package/package.json +4 -3
- package/templates/.claude/agents-available/dashboard-builder.md +7 -7
- package/templates/.claude/agents-available/dev-report.md +4 -4
- package/templates/.claude/agents-available/health-auditor.md +1 -1
- package/templates/.claude/agents-available/strategic-planner.md +7 -7
- package/templates/.claude/agents-available/vulnerability-scanner.md +3 -3
- package/templates/.claude/commands/dashboard.md +1 -1
- package/templates/.claude/commands/deps.md +1 -1
- package/templates/.claude/commands/dev-report.md +2 -2
- package/templates/.claude/commands/docs.md +1 -1
- package/templates/.claude/commands/export-pdf.md +3 -3
- package/templates/.claude/commands/health.md +3 -3
- package/templates/.claude/commands/plan.md +1 -1
- package/templates/.claude/commands/quality.md.template +2 -2
- package/templates/.claude/commands/stealth-mode.md +1 -1
- package/templates/.claude/commands/test-gaps.md +2 -2
- package/templates/.claude/commands/vulnerabilities.md +3 -3
- package/dist/agents/extract.d.ts +0 -25
- package/dist/agents/extract.d.ts.map +0 -1
- package/dist/agents/extract.js +0 -186
- package/dist/agents/extract.js.map +0 -1
- package/dist/agents/schemas.d.ts +0 -106
- package/dist/agents/schemas.d.ts.map +0 -1
- package/dist/agents/schemas.js +0 -86
- package/dist/agents/schemas.js.map +0 -1
- package/dist/agents/session.d.ts +0 -28
- package/dist/agents/session.d.ts.map +0 -1
- package/dist/agents/session.js +0 -223
- package/dist/agents/session.js.map +0 -1
- package/dist/analyzers/index.d.ts +0 -3
- package/dist/analyzers/index.d.ts.map +0 -1
- package/dist/analyzers/index.js +0 -6
- package/dist/analyzers/index.js.map +0 -1
- package/dist/analyzers/security/report.d.ts +0 -6
- package/dist/analyzers/security/report.d.ts.map +0 -1
- package/dist/analyzers/security/report.js +0 -118
- package/dist/analyzers/security/report.js.map +0 -1
- package/dist/analyzers/tools/dotnet.d.ts +0 -8
- package/dist/analyzers/tools/dotnet.d.ts.map +0 -1
- package/dist/analyzers/tools/dotnet.js +0 -81
- package/dist/analyzers/tools/dotnet.js.map +0 -1
- package/dist/analyzers/tools/gather-cache.d.ts +0 -16
- package/dist/analyzers/tools/gather-cache.d.ts.map +0 -1
- package/dist/analyzers/tools/gather-cache.js +0 -126
- package/dist/analyzers/tools/gather-cache.js.map +0 -1
- package/dist/analyzers/tools/go.d.ts +0 -8
- package/dist/analyzers/tools/go.d.ts.map +0 -1
- package/dist/analyzers/tools/go.js +0 -84
- package/dist/analyzers/tools/go.js.map +0 -1
- package/dist/analyzers/tools/node.d.ts +0 -8
- package/dist/analyzers/tools/node.d.ts.map +0 -1
- package/dist/analyzers/tools/node.js +0 -160
- package/dist/analyzers/tools/node.js.map +0 -1
- package/dist/analyzers/tools/python.d.ts +0 -8
- package/dist/analyzers/tools/python.d.ts.map +0 -1
- package/dist/analyzers/tools/python.js +0 -81
- package/dist/analyzers/tools/python.js.map +0 -1
- package/dist/analyzers/tools/rust.d.ts +0 -8
- package/dist/analyzers/tools/rust.d.ts.map +0 -1
- package/dist/analyzers/tools/rust.js +0 -86
- package/dist/analyzers/tools/rust.js.map +0 -1
- package/templates/.ai/templates/session-checkpoint-template.md +0 -97
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,166 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.3.0] - 2026-04-24
|
|
11
|
+
|
|
12
|
+
Minor release — turns the `bom` report from enumeration (1700+ rows
|
|
13
|
+
of noise) into a **decision doc** (top 10 triage queue ranked by
|
|
14
|
+
composite exploit-risk). Every `DepVulnFinding` now carries five
|
|
15
|
+
exploitability signals — CVSS, EPSS, CISA KEV, reachability,
|
|
16
|
+
composite `riskScore` — that consumers can read individually or as
|
|
17
|
+
the ranked `Risk` column. `licenses` + `vulnerabilities` renders
|
|
18
|
+
gain parity with the new bom surface so any dxkit command shows the
|
|
19
|
+
same triage-relevant data.
|
|
20
|
+
|
|
21
|
+
Nine sub-commits (Phase 10h.5) landed behind PRs #4 / #5 / #6 /
|
|
22
|
+
#7 / #8 / #9 / #10 / #11 through the hardened 2.2.1 pipeline —
|
|
23
|
+
the first full release cut where every commit flowed PR → CI-green →
|
|
24
|
+
merge → tag → CI-publishes without deviation.
|
|
25
|
+
|
|
26
|
+
### Added — exploitability enrichers
|
|
27
|
+
|
|
28
|
+
- **EPSS** (`DepVulnFinding.epssScore`, 0.0–1.0) from FIRST.org's
|
|
29
|
+
`api.first.org/data/v1/epss`. Batched (≤100 CVEs/call), session-
|
|
30
|
+
cached, graceful offline fallback. Non-CVE primaries (GHSA /
|
|
31
|
+
RUSTSEC / GO / PYSEC) resolve via OSV.dev alias lookup — no
|
|
32
|
+
coverage gap across packs. (10h.5.1)
|
|
33
|
+
|
|
34
|
+
- **CISA KEV** (`DepVulnFinding.kev`, boolean) from the official
|
|
35
|
+
catalog at `cisa.gov/.../known_exploited_vulnerabilities.json`.
|
|
36
|
+
Single bulk fetch per process, O(1) lookup. Badge `⚠` in every
|
|
37
|
+
render. (10h.5.2)
|
|
38
|
+
|
|
39
|
+
- **Reachability** (`DepVulnFinding.reachable`, tri-state) — does
|
|
40
|
+
this repo's source actually import the vulnerable package?
|
|
41
|
+
Built from per-pack `ImportsResult`'s specifier extraction;
|
|
42
|
+
`specifierToPackage` handles TS scoped/bare, Python dotted
|
|
43
|
+
modules, Go 3-segment module paths. Coarse name-level
|
|
44
|
+
matching; undefined when no imports data available. (10h.5.3)
|
|
45
|
+
|
|
46
|
+
- **Composite riskScore** (`DepVulnFinding.riskScore`, 0–100) —
|
|
47
|
+
`clamp(cvss*10 × kev? × (1+2*epss) × reach?, 0, 100)`. Formula
|
|
48
|
+
documented in `src/analyzers/tools/risk-score.ts`. Null when
|
|
49
|
+
CVSS missing (no fabrication from side signals). (10h.5.4)
|
|
50
|
+
|
|
51
|
+
- **"This Week's Triage"** section at the top of every bom report —
|
|
52
|
+
top 10 advisories with riskScore ≥ 15, rationale composed from
|
|
53
|
+
most decisive signals (KEV → reachable → CVSS → EPSS), fix
|
|
54
|
+
column with "PROPOSAL:" prefix stripped. (10h.5.5)
|
|
55
|
+
|
|
56
|
+
### Added — decision-doc UX
|
|
57
|
+
|
|
58
|
+
- **`bom --filter=top-level`** drops transitive rows (1700+ → ~150
|
|
59
|
+
on typical repos) while the `byTopLevelDep` rollup still reflects
|
|
60
|
+
full blast radius — "upgrading `@loopback/cli` resolves 29
|
|
61
|
+
advisories" survives when those 29 transitive rows are hidden.
|
|
62
|
+
`BomEntry.isTopLevel` + `summary.filter` + `summary.unfilteredTotalPackages`
|
|
63
|
+
ride the shape. (10h.5.0)
|
|
64
|
+
|
|
65
|
+
- **Nested-project aggregation** (default ON; `--no-nested` opts
|
|
66
|
+
out). `src/analyzers/bom/discovery.ts` walks the repo,
|
|
67
|
+
discovers every directory with a language manifest
|
|
68
|
+
(package.json, pyproject.toml/requirements.txt/setup.py/Pipfile,
|
|
69
|
+
go.mod, Cargo.toml, *.csproj/*.sln), runs per-root gather, and
|
|
70
|
+
merges with dedup on `(package, version)`. `BomEntry.sources`
|
|
71
|
+
unions the roots each package was found in; `isTopLevel`
|
|
72
|
+
OR-merges; vulns dedup on `(id, package, installedVersion)`.
|
|
73
|
+
Closes **D001a** — `bom platform/` previously missed
|
|
74
|
+
`platform/userserver/` entirely. Side-benefit: naturally
|
|
75
|
+
addresses **D003** (C# multi-project) since each `.csproj`
|
|
76
|
+
becomes its own root. (10h.5.0b)
|
|
77
|
+
|
|
78
|
+
- **`LicenseFinding.releaseDate`** populated from the npm registry
|
|
79
|
+
for every TS-ecosystem package. Closes **D006** — xlsx col 10
|
|
80
|
+
("Component Release Date") was previously empty. Bundled with
|
|
81
|
+
the EPSS fetcher roundtrip. (10h.5.1)
|
|
82
|
+
|
|
83
|
+
- **`licenses` render** sorts top-level deps (⭐) first, transitive
|
|
84
|
+
below. Adds `Direct` + `Released` columns. Matches bom's
|
|
85
|
+
`--filter=top-level` ordering so cross-referencing the two
|
|
86
|
+
reports Just Works. (10h.5.6)
|
|
87
|
+
|
|
88
|
+
- **`vulnerabilities` render (main, not --detailed)** per-advisory
|
|
89
|
+
table now sorted by `riskScore` desc with `Risk` / `KEV` /
|
|
90
|
+
`Reach` / `EPSS` columns alongside the existing fields. (10h.5.6)
|
|
91
|
+
|
|
92
|
+
### Fixed
|
|
93
|
+
|
|
94
|
+
- **D013** — graphify's shared Python venv moved from
|
|
95
|
+
`/tmp/graphify-venv` (subject to systemd-tmpfiles sweep + race
|
|
96
|
+
on first install) to `~/.cache/dxkit/tools-venv` (XDG persistent).
|
|
97
|
+
Also fixed `Date.now()` script-tempfile collision class in
|
|
98
|
+
graphify.ts via `fs.mkdtempSync`. Affects every Python-based
|
|
99
|
+
tool dxkit installs (graphify, semgrep, ruff, pip-audit,
|
|
100
|
+
pip-licenses, coverage). Legacy `/tmp/graphify-venv` path still
|
|
101
|
+
probed, so existing installations aren't forced into a
|
|
102
|
+
reinstall. (10f.2)
|
|
103
|
+
|
|
104
|
+
- **OSV.dev GHSA case-sensitivity** — `api.osv.dev/v1/vulns/<GHSA>`
|
|
105
|
+
expects lowercase; npm-audit emits uppercase. `osv.ts`
|
|
106
|
+
`DEFAULT_FETCHER` normalizes the alphabetic portion. Silently
|
|
107
|
+
broke alias resolution for every TS finding pre-2.3.0.
|
|
108
|
+
|
|
109
|
+
### Changed — output directory
|
|
110
|
+
|
|
111
|
+
- **Reports moved from `.ai/reports/` to `.dxkit/reports/`**.
|
|
112
|
+
Separates tool output (regenerated each run, can be gitignored)
|
|
113
|
+
from AI-agent context (`.ai/sessions/`, `.ai/prompts/` —
|
|
114
|
+
human-authored, version-controlled). All CLI commands + every
|
|
115
|
+
scaffolded slash command / agent / template updated to the new
|
|
116
|
+
path. Existing `.ai/reports/*.md` files become orphans after
|
|
117
|
+
upgrade — acceptable since reports regenerate each run.
|
|
118
|
+
|
|
119
|
+
### Process
|
|
120
|
+
|
|
121
|
+
- First full release cut through the 2.2.1-hardened publish
|
|
122
|
+
pipeline: 8 PRs, every one PR→CI→admin-squash-merge→main. Each
|
|
123
|
+
dog-fooded the pre-push CI-mirror hooks landed in PR #3.
|
|
124
|
+
|
|
125
|
+
## [2.2.1] - 2026-04-23
|
|
126
|
+
|
|
127
|
+
Patch release hardening the publish pipeline after `v2.2.0`'s Publish
|
|
128
|
+
workflow failed with `403 — version already published`. The failure
|
|
129
|
+
was caused by a local `npm publish` that preceded the
|
|
130
|
+
Release-triggered CI publish, not a code defect — the tarball on npm
|
|
131
|
+
byte-matches main. No functional changes in this release; all work
|
|
132
|
+
is on the release path (tracked internally as D015).
|
|
133
|
+
|
|
134
|
+
### Added — publish pipeline guardrails
|
|
135
|
+
|
|
136
|
+
- **`scripts/require-ci.js` + `prepublishOnly` guard** — any `npm publish`
|
|
137
|
+
invocation outside GitHub Actions now fails at the script hook with
|
|
138
|
+
a clear error pointing to `CLAUDE.md §"Release procedure"`. Prevents
|
|
139
|
+
accidental local publish before the registry is ever contacted.
|
|
140
|
+
|
|
141
|
+
- **`publishConfig.provenance: true`** — npm publishes now carry a
|
|
142
|
+
GitHub Actions provenance attestation. Provenance requires an OIDC
|
|
143
|
+
token that only exists inside Actions; tarball-mode publishes
|
|
144
|
+
(`npm publish *.tgz`, which skips `prepublishOnly`) also fail outside
|
|
145
|
+
CI. Belt-and-suspenders with the script guard.
|
|
146
|
+
|
|
147
|
+
- **Publish-workflow preflights** (`.github/workflows/publish.yml`) —
|
|
148
|
+
before `npm publish` runs, the workflow now verifies (in order):
|
|
149
|
+
1. tag `vX.Y.Z` matches `package.json` version `X.Y.Z`
|
|
150
|
+
2. tagged commit is reachable from `origin/main` (blocks
|
|
151
|
+
feature-branch tags)
|
|
152
|
+
3. the `CI` workflow succeeded on the tagged commit SHA
|
|
153
|
+
4. `X.Y.Z` is not already on npm (catches the exact 2.2.0 failure)
|
|
154
|
+
|
|
155
|
+
- **Explicit pack + publish + verify** — workflow packs the tarball,
|
|
156
|
+
records its sha1, publishes that exact file, then fetches
|
|
157
|
+
`npm view dist.shasum` and fails on mismatch. Eliminates drift
|
|
158
|
+
between "what npm packed" and "what we audited."
|
|
159
|
+
|
|
160
|
+
- **Tarball workflow artifact** — every release archives the published
|
|
161
|
+
`.tgz` as a workflow artifact (90-day retention) for post-mortem
|
|
162
|
+
auditability.
|
|
163
|
+
|
|
164
|
+
### Documented — `CLAUDE.md`
|
|
165
|
+
|
|
166
|
+
New "Release procedure" section codifying PR → CI-green → merge → tag
|
|
167
|
+
→ CI publishes as the only path. Explicit "no local `npm publish`"
|
|
168
|
+
rule.
|
|
169
|
+
|
|
10
170
|
## [2.2.0] - 2026-04-23
|
|
11
171
|
|
|
12
172
|
Minor release adding Snyk-style top-level dep attribution across every
|
package/README.md
CHANGED
|
@@ -15,8 +15,12 @@ Built so agent-written code has deterministic guardrails before it ships. Scores
|
|
|
15
15
|
cd your-repo
|
|
16
16
|
npx @vyuhlabs/dxkit tools install --yes # one-time: install cloc, gitleaks, etc.
|
|
17
17
|
npx @vyuhlabs/dxkit health --detailed # 6-dimension score + remediation plan
|
|
18
|
-
npx @vyuhlabs/dxkit vulnerabilities # secret + SAST + dep-audit
|
|
18
|
+
npx @vyuhlabs/dxkit vulnerabilities # secret + SAST + dep-audit (ranked by risk)
|
|
19
|
+
npx @vyuhlabs/dxkit bom --filter=top-level # Bill of Materials w/ "This Week's Triage"
|
|
19
20
|
npx @vyuhlabs/dxkit test-gaps # import-graph + coverage-aware
|
|
21
|
+
npx @vyuhlabs/dxkit quality # slop + duplication + lint
|
|
22
|
+
npx @vyuhlabs/dxkit licenses # dependency license inventory
|
|
23
|
+
npx @vyuhlabs/dxkit dev-report # git activity + contributors
|
|
20
24
|
```
|
|
21
25
|
|
|
22
26
|
**Scaffold AI tooling into a repo:**
|
|
@@ -32,31 +36,33 @@ The two modes are complementary. The analyzers run anywhere; the scaffolder writ
|
|
|
32
36
|
|
|
33
37
|
## Analyzer CLI (`vyuh-dxkit <command>`)
|
|
34
38
|
|
|
35
|
-
Seven deterministic analyzers. Each emits a markdown report to `.
|
|
39
|
+
Seven deterministic analyzers. Each emits a markdown report to `.dxkit/reports/` and optional structured JSON.
|
|
36
40
|
|
|
37
|
-
| Command | What it does
|
|
38
|
-
| ----------------- |
|
|
39
|
-
| `health` | 6-dimension score (Testing, Quality, Docs, Security, Maint, DX)
|
|
40
|
-
| `vulnerabilities` | gitleaks + semgrep + per-pack dep-audit (per-advisory detail in `--detailed`)
|
|
41
|
-
| `test-gaps` | Coverage artifact → import-graph → filename (strongest wins)
|
|
42
|
-
| `quality` | Slop score + jscpd duplication + eslint/ruff + hygiene
|
|
43
|
-
| `dev-report` | Commits, contributors, hot files, velocity, conventional %
|
|
44
|
-
| `licenses` | Dependency license inventory across every active pack (TS/Python/Go/Rust/C#)
|
|
45
|
-
| `bom` | **Bill of Materials** — joins licenses +
|
|
41
|
+
| Command | What it does | Runtime | Output |
|
|
42
|
+
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | --------------------------------------------- |
|
|
43
|
+
| `health` | 6-dimension score (Testing, Quality, Docs, Security, Maint, DX) | 10–20s | `.dxkit/reports/health-audit-<date>.md` |
|
|
44
|
+
| `vulnerabilities` | gitleaks + semgrep + per-pack dep-audit (per-advisory detail in `--detailed`) | 5–30s | `.dxkit/reports/vulnerability-scan-<date>.md` |
|
|
45
|
+
| `test-gaps` | Coverage artifact → import-graph → filename (strongest wins) | <1s | `.dxkit/reports/test-gaps-<date>.md` |
|
|
46
|
+
| `quality` | Slop score + jscpd duplication + eslint/ruff + hygiene | 5–15s | `.dxkit/reports/quality-review-<date>.md` |
|
|
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` |
|
|
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}` |
|
|
46
50
|
|
|
47
51
|
Plus a converter: `vyuh-dxkit to-xlsx <json-file>` renders any `licenses` or `bom` detailed JSON as the canonical 15-column XLSX.
|
|
48
52
|
|
|
49
53
|
### Flags (apply to all analyzer commands)
|
|
50
54
|
|
|
51
|
-
| Flag | Effect
|
|
52
|
-
| ---------------- |
|
|
53
|
-
| `--detailed` | Also writes `<name>-detailed.md` + `.json` with evidence + ranked remediation actions
|
|
54
|
-
| `--json` | Emit pure JSON on stdout. Logs go to stderr so pipes stay clean
|
|
55
|
-
| `--verbose` | Print per-tool timing to stderr
|
|
56
|
-
| `--no-save` | Skip writing markdown; useful with `--json`
|
|
57
|
-
| `--xlsx` | (`licenses`, `bom` only) Also write 15-col `.xlsx` — drop-in for spreadsheet workflows
|
|
58
|
-
| `-o <file>` | (`licenses`, `bom`, `to-xlsx`) Override output path for xlsx / converted file
|
|
59
|
-
| `--since <date>` | (`dev-report` only) Analyze commits on or after `YYYY-MM-DD`
|
|
55
|
+
| Flag | Effect |
|
|
56
|
+
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
57
|
+
| `--detailed` | Also writes `<name>-detailed.md` + `.json` with evidence + ranked remediation actions |
|
|
58
|
+
| `--json` | Emit pure JSON on stdout. Logs go to stderr so pipes stay clean |
|
|
59
|
+
| `--verbose` | Print per-tool timing to stderr |
|
|
60
|
+
| `--no-save` | Skip writing markdown; useful with `--json` |
|
|
61
|
+
| `--xlsx` | (`licenses`, `bom` only) Also write 15-col `.xlsx` — drop-in for spreadsheet workflows |
|
|
62
|
+
| `-o <file>` | (`licenses`, `bom`, `to-xlsx`) Override output path for xlsx / converted file |
|
|
63
|
+
| `--since <date>` | (`dev-report` only) Analyze commits on or after `YYYY-MM-DD` |
|
|
64
|
+
| `--filter` | (`bom` only) `all` (default) or `top-level` — keep only root manifest deps; the byTopLevelDep rollup still reflects transitives |
|
|
65
|
+
| `--no-nested` | (`bom` only) Disable nested-project aggregation. Default discovers every sub-project with a language manifest under cwd and merges their BOMs |
|
|
60
66
|
|
|
61
67
|
### Detailed mode — evidence + ranked fixes
|
|
62
68
|
|
|
@@ -188,7 +194,7 @@ CLAUDE.md # Main context file for Claude Code
|
|
|
188
194
|
|
|
189
195
|
The scaffolded slash commands (`/health`, `/vulnerabilities`, `/test-gaps`, `/quality`, `/dev-report`) use a three-tier fallback:
|
|
190
196
|
|
|
191
|
-
1. **Check for an existing report** in `.
|
|
197
|
+
1. **Check for an existing report** in `.dxkit/reports/` from today
|
|
192
198
|
2. **Run `vyuh-dxkit <command>`** — deterministic, fast, same output
|
|
193
199
|
3. **Fall back to LLM analysis** only if the CLI isn't available
|
|
194
200
|
|
|
@@ -313,10 +319,10 @@ Both loops use the session framework — checkpoints, skill evolution, progress
|
|
|
313
319
|
|
|
314
320
|
## Reports
|
|
315
321
|
|
|
316
|
-
All analyzer commands save timestamped reports to `.
|
|
322
|
+
All analyzer commands save timestamped reports to `.dxkit/reports/`:
|
|
317
323
|
|
|
318
324
|
```
|
|
319
|
-
.
|
|
325
|
+
.dxkit/reports/
|
|
320
326
|
health-audit-<date>.md
|
|
321
327
|
health-audit-<date>-detailed.md # with --detailed
|
|
322
328
|
health-audit-<date>-detailed.json # agent-consumable
|
|
@@ -359,12 +365,17 @@ When create-devstack writes `.project.yaml` before calling dxkit, detection and
|
|
|
359
365
|
## CLI Reference
|
|
360
366
|
|
|
361
367
|
```bash
|
|
362
|
-
# Analyzer commands
|
|
363
|
-
vyuh-dxkit health [path]
|
|
364
|
-
vyuh-dxkit vulnerabilities [path]
|
|
365
|
-
vyuh-dxkit test-gaps [path]
|
|
366
|
-
vyuh-dxkit quality [path]
|
|
367
|
-
vyuh-dxkit dev-report [path]
|
|
368
|
+
# Analyzer commands — each writes to .dxkit/reports/<name>-<date>.md
|
|
369
|
+
vyuh-dxkit health [path] # 6-dimension score
|
|
370
|
+
vyuh-dxkit vulnerabilities [path] # Security scan, ranked by composite risk
|
|
371
|
+
vyuh-dxkit test-gaps [path] # Coverage + gaps + actions
|
|
372
|
+
vyuh-dxkit quality [path] # Slop + duplication + lint
|
|
373
|
+
vyuh-dxkit dev-report [path] [--since <date>] # Git activity report
|
|
374
|
+
vyuh-dxkit licenses [path] # Dependency license inventory
|
|
375
|
+
vyuh-dxkit bom [path] [--filter=top-level] # Bill of Materials + risk-ranked triage
|
|
376
|
+
|
|
377
|
+
# Data conversion
|
|
378
|
+
vyuh-dxkit to-xlsx <json-file> # render licenses/bom detailed JSON as 15-col XLSX
|
|
368
379
|
|
|
369
380
|
# Tool management
|
|
370
381
|
vyuh-dxkit tools # status
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-root discovery for nested BOM aggregation.
|
|
3
|
+
*
|
|
4
|
+
* `vyuh-dxkit bom <path>` historically scanned `<path>` as a single
|
|
5
|
+
* project root. Repos like `vyuhlabs-platform/` (root devtools +
|
|
6
|
+
* `userserver/` product) fell through the cracks — the scanner saw
|
|
7
|
+
* only whichever `package.json`/lockfile lived at `<path>`, missing
|
|
8
|
+
* every sibling or nested sub-project. See D001a in the internal
|
|
9
|
+
* defect log for the incident write-up.
|
|
10
|
+
*
|
|
11
|
+
* This module walks the filesystem starting at cwd and returns every
|
|
12
|
+
* directory that looks like an independent project root (i.e. has any
|
|
13
|
+
* language manifest, regardless of whether a parent also does). The
|
|
14
|
+
* BOM analyzer then runs the existing per-root gather against each
|
|
15
|
+
* and merges the results.
|
|
16
|
+
*
|
|
17
|
+
* Why a hardcoded skip-set rather than `exclusions.ts`: this is a
|
|
18
|
+
* structural traversal, not a gitignore-based code scan. `exclusions.ts`
|
|
19
|
+
* is tuned for "which files does the user consider source code?" and
|
|
20
|
+
* pulls in `.gitignore` rules that would incorrectly hide sibling
|
|
21
|
+
* projects (e.g. `.gitignore: dist/` would skip a sub-project under
|
|
22
|
+
* `dist/` even though it might legitimately be a shippable artifact
|
|
23
|
+
* the user wants inventoried).
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Walk `cwd` and return every directory that contains at least one
|
|
27
|
+
* language manifest. Always includes `cwd` itself when it has one,
|
|
28
|
+
* even if nested sub-projects also exist (the aggregator treats all
|
|
29
|
+
* roots symmetrically and dedupes findings across them).
|
|
30
|
+
*
|
|
31
|
+
* Pure over the filesystem: no caching, no side effects beyond
|
|
32
|
+
* filesystem reads. Returns absolute paths, sorted alphabetically
|
|
33
|
+
* for deterministic output.
|
|
34
|
+
*
|
|
35
|
+
* Exported for unit tests.
|
|
36
|
+
*/
|
|
37
|
+
export declare function discoverProjectRoots(cwd: string, maxDepth?: number): string[];
|
|
38
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../../src/analyzers/bom/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA2DH;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,MAA0B,GAAG,MAAM,EAAE,CAIhG"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Project-root discovery for nested BOM aggregation.
|
|
4
|
+
*
|
|
5
|
+
* `vyuh-dxkit bom <path>` historically scanned `<path>` as a single
|
|
6
|
+
* project root. Repos like `vyuhlabs-platform/` (root devtools +
|
|
7
|
+
* `userserver/` product) fell through the cracks — the scanner saw
|
|
8
|
+
* only whichever `package.json`/lockfile lived at `<path>`, missing
|
|
9
|
+
* every sibling or nested sub-project. See D001a in the internal
|
|
10
|
+
* defect log for the incident write-up.
|
|
11
|
+
*
|
|
12
|
+
* This module walks the filesystem starting at cwd and returns every
|
|
13
|
+
* directory that looks like an independent project root (i.e. has any
|
|
14
|
+
* language manifest, regardless of whether a parent also does). The
|
|
15
|
+
* BOM analyzer then runs the existing per-root gather against each
|
|
16
|
+
* and merges the results.
|
|
17
|
+
*
|
|
18
|
+
* Why a hardcoded skip-set rather than `exclusions.ts`: this is a
|
|
19
|
+
* structural traversal, not a gitignore-based code scan. `exclusions.ts`
|
|
20
|
+
* is tuned for "which files does the user consider source code?" and
|
|
21
|
+
* pulls in `.gitignore` rules that would incorrectly hide sibling
|
|
22
|
+
* projects (e.g. `.gitignore: dist/` would skip a sub-project under
|
|
23
|
+
* `dist/` even though it might legitimately be a shippable artifact
|
|
24
|
+
* the user wants inventoried).
|
|
25
|
+
*/
|
|
26
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
27
|
+
if (k2 === undefined) k2 = k;
|
|
28
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
29
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
30
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
31
|
+
}
|
|
32
|
+
Object.defineProperty(o, k2, desc);
|
|
33
|
+
}) : (function(o, m, k, k2) {
|
|
34
|
+
if (k2 === undefined) k2 = k;
|
|
35
|
+
o[k2] = m[k];
|
|
36
|
+
}));
|
|
37
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
38
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
39
|
+
}) : function(o, v) {
|
|
40
|
+
o["default"] = v;
|
|
41
|
+
});
|
|
42
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
43
|
+
var ownKeys = function(o) {
|
|
44
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
45
|
+
var ar = [];
|
|
46
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
47
|
+
return ar;
|
|
48
|
+
};
|
|
49
|
+
return ownKeys(o);
|
|
50
|
+
};
|
|
51
|
+
return function (mod) {
|
|
52
|
+
if (mod && mod.__esModule) return mod;
|
|
53
|
+
var result = {};
|
|
54
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
55
|
+
__setModuleDefault(result, mod);
|
|
56
|
+
return result;
|
|
57
|
+
};
|
|
58
|
+
})();
|
|
59
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
60
|
+
exports.discoverProjectRoots = discoverProjectRoots;
|
|
61
|
+
const fs = __importStar(require("fs"));
|
|
62
|
+
const path = __importStar(require("path"));
|
|
63
|
+
/** File basenames that mark a directory as a project root. */
|
|
64
|
+
const MANIFEST_BASENAMES = new Set([
|
|
65
|
+
'package.json', // Node
|
|
66
|
+
'pyproject.toml', // Python (PEP 621 / poetry)
|
|
67
|
+
'requirements.txt', // Python (pip)
|
|
68
|
+
'setup.py', // Python (legacy)
|
|
69
|
+
'Pipfile', // Python (pipenv)
|
|
70
|
+
'go.mod', // Go
|
|
71
|
+
'Cargo.toml', // Rust
|
|
72
|
+
]);
|
|
73
|
+
/** File extensions that mark a directory as a project root. */
|
|
74
|
+
const MANIFEST_EXTENSIONS = [
|
|
75
|
+
'.csproj', // C# project
|
|
76
|
+
'.sln', // C# solution
|
|
77
|
+
];
|
|
78
|
+
/**
|
|
79
|
+
* Directories we never descend into during discovery.
|
|
80
|
+
*
|
|
81
|
+
* - Dependency trees (`node_modules`, `vendor`, `venv`, `.venv`,
|
|
82
|
+
* `target`, `bin`, `obj`): contain manifests from installed
|
|
83
|
+
* packages, not user projects.
|
|
84
|
+
* - Build output (`dist`, `build`, `out`, `.next`, `.turbo`,
|
|
85
|
+
* `.cache`): derived, not source-of-truth.
|
|
86
|
+
* - VCS / tool metadata (`.git`, `.svn`, `.hg`): never has
|
|
87
|
+
* meaningful manifests.
|
|
88
|
+
*
|
|
89
|
+
* Any dotfile directory is also skipped — caches, IDE state, etc.
|
|
90
|
+
*/
|
|
91
|
+
const SKIP_DIR_BASENAMES = new Set([
|
|
92
|
+
'node_modules',
|
|
93
|
+
'vendor',
|
|
94
|
+
'venv',
|
|
95
|
+
'.venv',
|
|
96
|
+
'target',
|
|
97
|
+
'bin',
|
|
98
|
+
'obj',
|
|
99
|
+
'dist',
|
|
100
|
+
'build',
|
|
101
|
+
'out',
|
|
102
|
+
'.next',
|
|
103
|
+
'.turbo',
|
|
104
|
+
'.cache',
|
|
105
|
+
'.git',
|
|
106
|
+
'.svn',
|
|
107
|
+
'.hg',
|
|
108
|
+
'TestResults',
|
|
109
|
+
'packages',
|
|
110
|
+
]);
|
|
111
|
+
/** Default depth cap: enough for `packages/foo/sub`, excess discouraged. */
|
|
112
|
+
const DEFAULT_MAX_DEPTH = 4;
|
|
113
|
+
/**
|
|
114
|
+
* Walk `cwd` and return every directory that contains at least one
|
|
115
|
+
* language manifest. Always includes `cwd` itself when it has one,
|
|
116
|
+
* even if nested sub-projects also exist (the aggregator treats all
|
|
117
|
+
* roots symmetrically and dedupes findings across them).
|
|
118
|
+
*
|
|
119
|
+
* Pure over the filesystem: no caching, no side effects beyond
|
|
120
|
+
* filesystem reads. Returns absolute paths, sorted alphabetically
|
|
121
|
+
* for deterministic output.
|
|
122
|
+
*
|
|
123
|
+
* Exported for unit tests.
|
|
124
|
+
*/
|
|
125
|
+
function discoverProjectRoots(cwd, maxDepth = DEFAULT_MAX_DEPTH) {
|
|
126
|
+
const roots = new Set();
|
|
127
|
+
walk(cwd, 0, maxDepth, roots);
|
|
128
|
+
return [...roots].sort();
|
|
129
|
+
}
|
|
130
|
+
function walk(dir, depth, maxDepth, roots) {
|
|
131
|
+
if (depth > maxDepth)
|
|
132
|
+
return;
|
|
133
|
+
let entries;
|
|
134
|
+
try {
|
|
135
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
let isRoot = false;
|
|
141
|
+
for (const e of entries) {
|
|
142
|
+
if (!e.isFile())
|
|
143
|
+
continue;
|
|
144
|
+
if (MANIFEST_BASENAMES.has(e.name)) {
|
|
145
|
+
isRoot = true;
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
if (MANIFEST_EXTENSIONS.some((ext) => e.name.endsWith(ext))) {
|
|
149
|
+
isRoot = true;
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (isRoot)
|
|
154
|
+
roots.add(dir);
|
|
155
|
+
for (const e of entries) {
|
|
156
|
+
if (!e.isDirectory())
|
|
157
|
+
continue;
|
|
158
|
+
if (SKIP_DIR_BASENAMES.has(e.name))
|
|
159
|
+
continue;
|
|
160
|
+
// Skip dotfile directories (caches, IDE state) except the repo root's own.
|
|
161
|
+
if (e.name.startsWith('.') && depth > 0)
|
|
162
|
+
continue;
|
|
163
|
+
walk(path.join(dir, e.name), depth + 1, maxDepth, roots);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../../src/analyzers/bom/discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -58,6 +58,34 @@ export interface BomGatherResult {
|
|
|
58
58
|
entries: BomEntry[];
|
|
59
59
|
toolsUsed: string[];
|
|
60
60
|
toolsUnavailable: string[];
|
|
61
|
+
/** Cwd-relative project-root paths the gather walked. Length 1 for
|
|
62
|
+
* single-root scans ("." ); length >1 for nested aggregation. */
|
|
63
|
+
projectRoots: string[];
|
|
61
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Merge per-root gather results into one deduplicated set.
|
|
67
|
+
*
|
|
68
|
+
* Dedupe key is `(package, version)` — the same logical package at
|
|
69
|
+
* the same version installed under two roots is the same artifact,
|
|
70
|
+
* so reporting two rows would be noise. When the same key appears
|
|
71
|
+
* under multiple roots:
|
|
72
|
+
*
|
|
73
|
+
* - `sources` unions the sub-paths
|
|
74
|
+
* - `isTopLevel` OR-merges — if any root treats the package as
|
|
75
|
+
* top-level, the merged entry is top-level (upgrade decisions
|
|
76
|
+
* surface under Top-Level Dep Groups)
|
|
77
|
+
* - `vulns` unions with dedup on `(id, package, installedVersion)`
|
|
78
|
+
* — the same advisory reported from two roots collapses into
|
|
79
|
+
* one finding but its `topLevelDep` list unions
|
|
80
|
+
* - license metadata (licenseType, sourceUrl, etc.) prefers the
|
|
81
|
+
* first root with non-UNKNOWN data, falling back to whatever
|
|
82
|
+
* the first-seen entry carried
|
|
83
|
+
*
|
|
84
|
+
* Pure function; unit-testable without filesystem.
|
|
85
|
+
*/
|
|
86
|
+
export declare function mergeNestedBomEntries(perRoot: ReadonlyArray<{
|
|
87
|
+
relPath: string;
|
|
88
|
+
result: BomGatherResult;
|
|
89
|
+
}>): BomGatherResult;
|
|
62
90
|
export declare function gatherBomEntries(cwd: string): Promise<BomGatherResult>;
|
|
63
91
|
//# sourceMappingURL=gather.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gather.d.ts","sourceRoot":"","sources":["../../../src/analyzers/bom/gather.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,oCAAoC,CAAC;AACzF,OAAO,KAAK,EAAE,QAAQ,EAAe,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAIxE;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAgB1D;AAED;mDACmD;AACnD,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAGpD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,MAAM,CAQrE;AAYD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAkCzF;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"gather.d.ts","sourceRoot":"","sources":["../../../src/analyzers/bom/gather.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,oCAAoC,CAAC;AACzF,OAAO,KAAK,EAAE,QAAQ,EAAe,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAIxE;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAgB1D;AAED;mDACmD;AACnD,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAGpD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,MAAM,CAQrE;AAYD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAkCzF;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B;sEACkE;IAClE,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,aAAa,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,CAAC,GACnE,eAAe,CAkEjB;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAkF5E"}
|