@vyuhlabs/dxkit 2.7.1 → 2.9.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 +145 -0
- package/README.md +20 -9
- package/dist/analyzers/cache.js +11 -0
- package/dist/analyzers/cache.js.map +1 -1
- package/dist/analyzers/security/aggregator.d.ts +20 -0
- package/dist/analyzers/security/aggregator.d.ts.map +1 -1
- package/dist/analyzers/security/aggregator.js +5 -0
- package/dist/analyzers/security/aggregator.js.map +1 -1
- package/dist/analyzers/security/gather.d.ts.map +1 -1
- package/dist/analyzers/security/gather.js +8 -0
- package/dist/analyzers/security/gather.js.map +1 -1
- package/dist/analyzers/tools/grep-secrets.d.ts +6 -1
- package/dist/analyzers/tools/grep-secrets.d.ts.map +1 -1
- package/dist/analyzers/tools/grep-secrets.js +80 -60
- package/dist/analyzers/tools/grep-secrets.js.map +1 -1
- package/dist/analyzers/tools/tool-registry.d.ts.map +1 -1
- package/dist/analyzers/tools/tool-registry.js +50 -0
- package/dist/analyzers/tools/tool-registry.js.map +1 -1
- package/dist/baseline/create.d.ts.map +1 -1
- package/dist/baseline/create.js +18 -6
- package/dist/baseline/create.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +58 -0
- package/dist/cli.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +85 -7
- package/dist/doctor.js.map +1 -1
- package/dist/explore/cli/context.d.ts +1 -1
- package/dist/explore/cli/context.d.ts.map +1 -1
- package/dist/explore/cli/context.js +173 -4
- package/dist/explore/cli/context.js.map +1 -1
- package/dist/explore/queries.d.ts +71 -0
- package/dist/explore/queries.d.ts.map +1 -1
- package/dist/explore/queries.js +76 -0
- package/dist/explore/queries.js.map +1 -1
- package/dist/explore/source-slice.d.ts +51 -0
- package/dist/explore/source-slice.d.ts.map +1 -0
- package/dist/explore/source-slice.js +88 -0
- package/dist/explore/source-slice.js.map +1 -0
- package/dist/explore-cli.js +6 -4
- package/dist/explore-cli.js.map +1 -1
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +18 -0
- package/dist/generator.js.map +1 -1
- package/dist/hooks-cli.d.ts.map +1 -1
- package/dist/hooks-cli.js +43 -0
- package/dist/hooks-cli.js.map +1 -1
- package/dist/ingest/codeql.d.ts +36 -0
- package/dist/ingest/codeql.d.ts.map +1 -0
- package/dist/ingest/codeql.js +166 -0
- package/dist/ingest/codeql.js.map +1 -0
- package/dist/ingest/config.d.ts +10 -0
- package/dist/ingest/config.d.ts.map +1 -0
- package/dist/ingest/config.js +69 -0
- package/dist/ingest/config.js.map +1 -0
- package/dist/ingest/engine-resolver.d.ts +42 -0
- package/dist/ingest/engine-resolver.d.ts.map +1 -0
- package/dist/ingest/engine-resolver.js +89 -0
- package/dist/ingest/engine-resolver.js.map +1 -0
- package/dist/ingest/normalize.d.ts +23 -0
- package/dist/ingest/normalize.d.ts.map +1 -0
- package/dist/ingest/normalize.js +18 -0
- package/dist/ingest/normalize.js.map +1 -0
- package/dist/ingest/sarif.d.ts +29 -0
- package/dist/ingest/sarif.d.ts.map +1 -0
- package/dist/ingest/sarif.js +136 -0
- package/dist/ingest/sarif.js.map +1 -0
- package/dist/ingest/snapshot.d.ts +26 -0
- package/dist/ingest/snapshot.d.ts.map +1 -0
- package/dist/ingest/snapshot.js +114 -0
- package/dist/ingest/snapshot.js.map +1 -0
- package/dist/ingest/snyk-api.d.ts +82 -0
- package/dist/ingest/snyk-api.d.ts.map +1 -0
- package/dist/ingest/snyk-api.js +114 -0
- package/dist/ingest/snyk-api.js.map +1 -0
- package/dist/ingest/snyk-cli.d.ts +22 -0
- package/dist/ingest/snyk-cli.d.ts.map +1 -0
- package/dist/ingest/snyk-cli.js +135 -0
- package/dist/ingest/snyk-cli.js.map +1 -0
- package/dist/ingest/types.d.ts +68 -0
- package/dist/ingest/types.d.ts.map +1 -0
- package/dist/ingest/types.js +3 -0
- package/dist/ingest/types.js.map +1 -0
- package/dist/ingest-cli.d.ts +21 -0
- package/dist/ingest-cli.d.ts.map +1 -0
- package/dist/ingest-cli.js +232 -0
- package/dist/ingest-cli.js.map +1 -0
- package/dist/languages/csharp.d.ts +9 -0
- package/dist/languages/csharp.d.ts.map +1 -1
- package/dist/languages/csharp.js +87 -7
- package/dist/languages/csharp.js.map +1 -1
- package/dist/languages/go.d.ts.map +1 -1
- package/dist/languages/go.js +2 -0
- package/dist/languages/go.js.map +1 -1
- package/dist/languages/index.d.ts +21 -1
- package/dist/languages/index.d.ts.map +1 -1
- package/dist/languages/index.js +32 -0
- package/dist/languages/index.js.map +1 -1
- package/dist/languages/java.d.ts.map +1 -1
- package/dist/languages/java.js +2 -0
- package/dist/languages/java.js.map +1 -1
- package/dist/languages/kotlin.d.ts.map +1 -1
- package/dist/languages/kotlin.js +8 -0
- package/dist/languages/kotlin.js.map +1 -1
- package/dist/languages/python.d.ts.map +1 -1
- package/dist/languages/python.js +2 -0
- package/dist/languages/python.js.map +1 -1
- package/dist/languages/ruby.d.ts.map +1 -1
- package/dist/languages/ruby.js +2 -0
- package/dist/languages/ruby.js.map +1 -1
- package/dist/languages/rust.d.ts.map +1 -1
- package/dist/languages/rust.js +3 -0
- package/dist/languages/rust.js.map +1 -1
- package/dist/languages/types.d.ts +40 -0
- package/dist/languages/types.d.ts.map +1 -1
- package/dist/languages/typescript.d.ts.map +1 -1
- package/dist/languages/typescript.js +3 -0
- package/dist/languages/typescript.js.map +1 -1
- package/dist/ship-installers.d.ts +22 -0
- package/dist/ship-installers.d.ts.map +1 -1
- package/dist/ship-installers.js +83 -3
- package/dist/ship-installers.js.map +1 -1
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +8 -0
- package/dist/update.js.map +1 -1
- package/package.json +1 -1
- package/templates/.claude/skills/dxkit-action/SKILL.md +9 -0
- package/templates/.claude/skills/dxkit-config/SKILL.md +23 -0
- package/templates/.claude/skills/dxkit-docs/SKILL.md +148 -0
- package/templates/.claude/skills/dxkit-feature/SKILL.md +189 -0
- package/templates/.claude/skills/dxkit-ingest/SKILL.md +99 -0
- package/templates/.claude/skills/dxkit-update/SKILL.md +10 -0
- package/templates/.github/workflows/dxkit-deep-sast-refresh.yml +104 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dxkit-docs
|
|
3
|
+
description: Generate the documentation a repo is missing — read the Documentation dimension's gaps, orient on the real code via the graph, then write a grounded README / docstrings / API + architecture docs that move the score without tripping the slop check. Use when the user says "write docs", "document this module", "improve the documentation score", "generate a README", "add docstrings", or after a health report flags Documentation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# dxkit-docs
|
|
7
|
+
|
|
8
|
+
This skill closes the gap `dxkit-action` doesn't: it **generates** missing
|
|
9
|
+
documentation rather than fixing flagged findings. It's built around one
|
|
10
|
+
hard constraint — dxkit's own quality scan flags AI-slop prose, so
|
|
11
|
+
documentation that reads like generated filler *lowers* the Quality score
|
|
12
|
+
while raising Documentation. The whole point of this skill is docs that
|
|
13
|
+
are **grounded in the real code** and **survive the slop check**.
|
|
14
|
+
|
|
15
|
+
## The docs loop
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
[1] Read the gap → health Documentation deductions + top actions
|
|
19
|
+
[2] Orient → graph: what are the real entry points, modules, public API
|
|
20
|
+
[3] Generate → write the missing artifact, grounded in actual symbols/paths
|
|
21
|
+
[4] De-slop → write like a human; re-run quality so it doesn't trip slop
|
|
22
|
+
[5] Verify → re-run health; Documentation up, slop not down
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Don't skip [2] or [4]. [2] is what keeps the docs true; [4] is what keeps
|
|
26
|
+
them from costing you on another dimension.
|
|
27
|
+
|
|
28
|
+
## [1] Read the gap — what's actually missing
|
|
29
|
+
|
|
30
|
+
The Documentation dimension scores a fixed checklist. Read its deductions
|
|
31
|
+
and ranked actions instead of guessing:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx vyuh-dxkit health --detailed --json | jq '.dimensions.documentation'
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The `deductions` array names each missing/substandard artifact; `topActions`
|
|
38
|
+
ranks them by score uplift. The scored artifacts are:
|
|
39
|
+
|
|
40
|
+
| Artifact | What moves the score |
|
|
41
|
+
|---|---|
|
|
42
|
+
| **README** | Present, and substantial (not a 5-line stub) |
|
|
43
|
+
| **Doc-comment density** | Share of source files carrying docstrings / JSDoc / Rustdoc |
|
|
44
|
+
| **API docs** | `docs/api/`, OpenAPI/Swagger spec |
|
|
45
|
+
| **Architecture docs** | `ARCHITECTURE.md` or `docs/architecture/` |
|
|
46
|
+
| **CONTRIBUTING** | `CONTRIBUTING.md` |
|
|
47
|
+
| **CHANGELOG** | `CHANGELOG.md` |
|
|
48
|
+
|
|
49
|
+
Work the `topActions` order — the README and doc-comment density weigh
|
|
50
|
+
heaviest, CHANGELOG lightest.
|
|
51
|
+
|
|
52
|
+
## [2] Orient — document the code that's actually there
|
|
53
|
+
|
|
54
|
+
Docs that describe code which doesn't exist are worse than no docs. Before
|
|
55
|
+
writing a word, learn the real shape from the graph (cheap, structural):
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npx vyuh-dxkit explore entry-points # what this repo does — the surfaces to lead a README with
|
|
59
|
+
npx vyuh-dxkit explore communities # the natural modules — the spine of an ARCHITECTURE.md
|
|
60
|
+
npx vyuh-dxkit explore api-surface # exported symbols — what API docs must cover
|
|
61
|
+
npx vyuh-dxkit explore hot-files # the foundational files — docstring these first
|
|
62
|
+
npx vyuh-dxkit context <symbol> # one area's structure before you docstring it
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Then **read the actual code** you're about to document — the graph points
|
|
66
|
+
you at it; it doesn't replace reading it. Also read any existing docs
|
|
67
|
+
first and match their voice, structure, and terminology.
|
|
68
|
+
|
|
69
|
+
## [3] Generate — grounded, specific, real
|
|
70
|
+
|
|
71
|
+
Per artifact:
|
|
72
|
+
|
|
73
|
+
- **README** — lead with what the repo *does* (from `entry-points`), then
|
|
74
|
+
real install + usage steps you've verified against the actual scripts /
|
|
75
|
+
entry points, not a generic template. Reference real commands, real file
|
|
76
|
+
paths, real module names.
|
|
77
|
+
- **Doc-comments** — docstring the highest-value undocumented files first
|
|
78
|
+
(public API from `api-surface`, foundational files from `hot-files`).
|
|
79
|
+
Describe *why* and the contract (params, returns, invariants, gotchas) —
|
|
80
|
+
not a restatement of the signature.
|
|
81
|
+
- **Architecture docs** — structure an `ARCHITECTURE.md` around the real
|
|
82
|
+
`communities` / `hot-files`: what each module owns, how they depend on
|
|
83
|
+
each other (the graph already knows the edges).
|
|
84
|
+
- **API docs** — generate from the actual exported surface; prefer the
|
|
85
|
+
ecosystem's doc generator (`typedoc`, `sphinx`, `godoc`, `yard`, …) over
|
|
86
|
+
hand-rolled prose when one fits.
|
|
87
|
+
- **CONTRIBUTING / CHANGELOG** — real build/test commands from the repo;
|
|
88
|
+
real recent changes from `git log` for a CHANGELOG seed.
|
|
89
|
+
|
|
90
|
+
## [4] De-slop — the rule that makes this skill different
|
|
91
|
+
|
|
92
|
+
dxkit's slop check flags AI-generated boilerplate. **Generated docs are
|
|
93
|
+
the single biggest source of slop**, so this step is mandatory, not
|
|
94
|
+
optional. Write to pass it:
|
|
95
|
+
|
|
96
|
+
- **No filler openers.** Not "This module provides functionality for
|
|
97
|
+
handling…" — say what it does and why it exists.
|
|
98
|
+
- **Be concrete.** Name real symbols, real paths, real commands. Specifics
|
|
99
|
+
don't read as slop; generic scaffolding does.
|
|
100
|
+
- **No hedging padding** ("it's worth noting that", "in order to",
|
|
101
|
+
"leverage", "robust", "seamless", "comprehensive solution").
|
|
102
|
+
- **Match the repo's register** — terse repos get terse docs.
|
|
103
|
+
|
|
104
|
+
Then prove it:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npx vyuh-dxkit quality # slop score must not drop
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
If a genuine false positive trips the slop check on prose you stand
|
|
111
|
+
behind, annotate the line (`// slop-ok: <reason>`, or `# slop-ok` for
|
|
112
|
+
hash-comment languages) — but fix first, suppress second.
|
|
113
|
+
|
|
114
|
+
## [5] Verify — Documentation up, nothing else down
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npx vyuh-dxkit health --detailed # Documentation score moved in the right direction
|
|
118
|
+
npx vyuh-dxkit quality # slop / quality did NOT regress
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The work is done when the Documentation deduction you targeted is gone
|
|
122
|
+
**and** the Quality score held. A docs change that raises Documentation by
|
|
123
|
+
moving slop into Quality is a net loss — re-do it more concretely.
|
|
124
|
+
|
|
125
|
+
Then run the guardrail before pushing, same as any change:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npx vyuh-dxkit guardrail check
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Scope — what NOT to document
|
|
132
|
+
|
|
133
|
+
- Don't docstring self-evident one-liners; density credit comes from
|
|
134
|
+
documenting the files that need it (public API, foundational modules),
|
|
135
|
+
not papering every getter.
|
|
136
|
+
- Don't document auto-generated or vendored code.
|
|
137
|
+
- Don't invent behavior to fill a section — if you're unsure what
|
|
138
|
+
something does, read it or ask, don't guess in prose.
|
|
139
|
+
|
|
140
|
+
## Hand-offs
|
|
141
|
+
|
|
142
|
+
- Running / interpreting the health report → `dxkit-reports`.
|
|
143
|
+
- Documentation surfaced as one finding inside a broader fix pass →
|
|
144
|
+
`dxkit-action`.
|
|
145
|
+
- Documenting a feature you're building → `dxkit-feature` (its build step
|
|
146
|
+
should leave the new surface documented).
|
|
147
|
+
- Slop findings outside docs (AI-generated code prose, CHANGELOG slop) →
|
|
148
|
+
`dxkit-action`'s slop recipe.
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dxkit-feature
|
|
3
|
+
description: Develop a new feature with the code graph as your map — orient cheaply by querying structure instead of reading whole files, implement following the patterns already in the repo, then verify the change did not regress security, tests, or quality before you push. Use when the user says "add a feature", "implement X", "build the Y flow", "where should this live", or otherwise starts net-new development in a dxkit-scaffolded repo.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# dxkit-feature
|
|
7
|
+
|
|
8
|
+
This skill drives forward development — building something new — the way
|
|
9
|
+
`dxkit-action` drives the reverse (fixing what's flagged). Its two jobs:
|
|
10
|
+
|
|
11
|
+
1. **Orient by graph, not by grep.** Use the code graph to find where the
|
|
12
|
+
feature plugs in, what patterns already exist, and what a change will
|
|
13
|
+
touch — at a fraction of the tokens that repeated whole-file reads cost.
|
|
14
|
+
2. **Close the loop a plain coding agent skips.** After the edit, run the
|
|
15
|
+
dxkit analyzers on the change and the guardrail check, so the new feature
|
|
16
|
+
doesn't quietly ship a vuln, a test gap, or a quality regression.
|
|
17
|
+
|
|
18
|
+
## The feature loop
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
[1] Clarify → what's the feature + what does "done" mean
|
|
22
|
+
[2] Orient → query the graph: where it lives, patterns, blast radius
|
|
23
|
+
[3] Plan → ordered edits, reusing the patterns found in [2]
|
|
24
|
+
[4] Build → read only the files the graph named, then implement
|
|
25
|
+
[5] Verify → run the analyzers on the change; confirm nothing regressed
|
|
26
|
+
[6] Decide baseline→ commit, or re-baseline if the change is deliberately accepted
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Don't skip [2] or [5]. [2] is where the token saving lives; [5] is the whole
|
|
30
|
+
reason to use dxkit for forward work instead of a generic agent.
|
|
31
|
+
|
|
32
|
+
## [2] Orient — query structure before you read files
|
|
33
|
+
|
|
34
|
+
This is the step that differentiates this skill. **Orientation (discovery)
|
|
35
|
+
is where direct agents burn the most tokens** — grep, read a 2,000-line
|
|
36
|
+
file, grep again, read another. The graph answers the same questions from a
|
|
37
|
+
budget-bounded slice instead.
|
|
38
|
+
|
|
39
|
+
Run `health` once first if there's no graph yet (it writes
|
|
40
|
+
`.dxkit/reports/graph.json` as a side effect), then query:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# "Where is this feature area implemented?" — clusters of matching symbols
|
|
44
|
+
npx vyuh-dxkit explore feature auth
|
|
45
|
+
|
|
46
|
+
# Token-budgeted structural slice for an area you're about to extend:
|
|
47
|
+
# anchor symbol, its callers/callees grouped by module, blast radius
|
|
48
|
+
npx vyuh-dxkit context "checkout session"
|
|
49
|
+
|
|
50
|
+
# Zoom into one symbol's exact neighborhood (curated AST chunk, not the
|
|
51
|
+
# whole file) — read 500 focused lines instead of ingesting 15k
|
|
52
|
+
npx vyuh-dxkit context src/payments/checkout.ts:142
|
|
53
|
+
|
|
54
|
+
# One file's structural neighborhood — symbols, callers, callees, imports
|
|
55
|
+
npx vyuh-dxkit explore file src/payments/checkout.ts
|
|
56
|
+
|
|
57
|
+
# The repo's public API / dead surface — useful when adding an entry point
|
|
58
|
+
npx vyuh-dxkit explore api-surface
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Use the answers to decide three things before you write anything:
|
|
62
|
+
|
|
63
|
+
- **Where the feature plugs in** — which module/cluster owns this area, so
|
|
64
|
+
the new code lands next to its neighbors rather than in a new island.
|
|
65
|
+
- **Which pattern to copy** — read the anchor symbol the graph points at;
|
|
66
|
+
it's the highest-in-degree example of "how this repo already does X."
|
|
67
|
+
Match its shape (error handling, validation, naming) so the feature reads
|
|
68
|
+
like the surrounding code.
|
|
69
|
+
- **The blast radius** — how many caller files a change to the touched
|
|
70
|
+
symbols reaches. That's your re-test list for step [5].
|
|
71
|
+
|
|
72
|
+
### Honest scope of the graph win (don't oversell it)
|
|
73
|
+
|
|
74
|
+
The reduction is a **navigation-phase win, not an end-to-end multiplier.**
|
|
75
|
+
The graph cuts the cost of *finding and orienting*; the *edit* phase still
|
|
76
|
+
reads the real files you change, and *verification* still runs the real
|
|
77
|
+
analyzers. The win is largest in big, unfamiliar codebases (orientation-by-
|
|
78
|
+
grep is expensive there) and near-zero in a small repo whose relevant files
|
|
79
|
+
already fit in context. Lead with the graph for discovery; then read the
|
|
80
|
+
actual code you're about to modify — `context` is a map, not a substitute
|
|
81
|
+
for the territory.
|
|
82
|
+
|
|
83
|
+
### Three hard rules for graph context (same as dxkit-action)
|
|
84
|
+
|
|
85
|
+
1. **It's a hint, never ground truth.** Confirm the symbol and call sites by
|
|
86
|
+
opening the file before you act on them — the graph stores declaration
|
|
87
|
+
lines, not end lines, and same-name symbols can conflate.
|
|
88
|
+
2. **A blank or `n/a` blast radius is NOT "safe to change".** Languages whose
|
|
89
|
+
call graph dxkit can't fully resolve (C# is the known case) report no
|
|
90
|
+
callers even for heavily-used files. Treat empty as *unknown* — fall back
|
|
91
|
+
to grep/read to find callers before a risky edit. Never read "no callers"
|
|
92
|
+
as "free to rewrite."
|
|
93
|
+
3. **Fall open — the graph is an accelerator, never a dependency.** If
|
|
94
|
+
graphify hasn't built a graph yet, `context` / `explore` print
|
|
95
|
+
`No graph.json … Run vyuh-dxkit health or pass --refresh` and exit
|
|
96
|
+
non-zero (they never crash or hang). Two responses, in order:
|
|
97
|
+
- Build it once: `npx vyuh-dxkit health` writes `graph.json` as a side
|
|
98
|
+
effect, or add `--refresh` to any explore/context call. Do this if the
|
|
99
|
+
repo is large enough that the orientation saving is worth one scan.
|
|
100
|
+
- Or just orient the normal way — grep + read — and carry on. You lose
|
|
101
|
+
the token saving, not the ability to build the feature.
|
|
102
|
+
|
|
103
|
+
### If graphify isn't installed at all
|
|
104
|
+
|
|
105
|
+
The graph is built by **graphify** (a registry tool). If it isn't installed,
|
|
106
|
+
`health` won't produce a `graph.json`, so step [2]'s graph queries are
|
|
107
|
+
unavailable — fall back to grep + read as above, or install it to unlock the
|
|
108
|
+
saving:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
npx vyuh-dxkit tools install # installs graphify + the other scanners
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Steps [5] and [6] do not need graphify.** The `vulnerabilities`,
|
|
115
|
+
`test-gaps`, `quality`, and `guardrail check` commands run fully without a
|
|
116
|
+
graph — only the `--graph-context` *enrichment* is suppressed (drop the flag
|
|
117
|
+
and the reports are still complete). So verification never depends on the
|
|
118
|
+
graph being present; only the orientation *speed-up* does.
|
|
119
|
+
|
|
120
|
+
## [3] Plan
|
|
121
|
+
|
|
122
|
+
Write an ordered list of edits. For each, name the file and the existing
|
|
123
|
+
pattern it mirrors (from step [2]). Prefer extending an existing module over
|
|
124
|
+
creating a new one unless the graph showed no natural home. Call out the
|
|
125
|
+
caller files in the blast radius that will need updating or re-testing.
|
|
126
|
+
|
|
127
|
+
## [4] Build
|
|
128
|
+
|
|
129
|
+
Read only the files the orientation step named — that's the point of doing
|
|
130
|
+
[2] first. Implement following the matched pattern. Keep the change tight:
|
|
131
|
+
comment density, naming, and idioms should match the surrounding code, not a
|
|
132
|
+
generic template.
|
|
133
|
+
|
|
134
|
+
## [5] Verify — never skip
|
|
135
|
+
|
|
136
|
+
A new feature can introduce exactly the things dxkit scans for: a SAST
|
|
137
|
+
finding, a vulnerable dependency you just added, an untested new surface, a
|
|
138
|
+
quality/slop regression. Run the analyzers on the changed area, with graph
|
|
139
|
+
context attached so you see each finding's blast radius:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
npx vyuh-dxkit vulnerabilities --detailed --graph-context # new code + new deps
|
|
143
|
+
npx vyuh-dxkit test-gaps --graph-context # is the new surface tested?
|
|
144
|
+
npx vyuh-dxkit quality --graph-context # slop / duplication / complexity
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Then gate the change the same way CI will:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
npx vyuh-dxkit guardrail check
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Exit 0 = the feature added no net-new regressions. Exit 1 = something new
|
|
154
|
+
appeared — **a finding you introduced.** Address it before pushing:
|
|
155
|
+
|
|
156
|
+
- A real finding in your new code → fix it now (hand off to `dxkit-action`
|
|
157
|
+
for the fix recipes — secret rotation, dep upgrade, writing the missing
|
|
158
|
+
test, etc.).
|
|
159
|
+
- A genuine false positive / intentional pattern → allowlist with a typed
|
|
160
|
+
category + reason (see `dxkit-action`'s allowlisting section). Fix first;
|
|
161
|
+
allowlist second.
|
|
162
|
+
|
|
163
|
+
The feature isn't done when it works — it's done when it works **and** the
|
|
164
|
+
guardrail is green.
|
|
165
|
+
|
|
166
|
+
## [6] Baseline decision
|
|
167
|
+
|
|
168
|
+
| Scenario | Action |
|
|
169
|
+
|---|---|
|
|
170
|
+
| Feature is clean; guardrail green | Just commit the code. Baseline + allowlist unchanged. |
|
|
171
|
+
| You fixed an introduced finding | Commit the code + fix together. Baseline unchanged. |
|
|
172
|
+
| Introduced finding is a true false positive / intentional | `vyuh-dxkit allowlist add` with `category=false-positive` or `test-fixture`; commit the annotation. |
|
|
173
|
+
| Feature deliberately accepts a known trade-off (documented) | `vyuh-dxkit allowlist add` with `category=accepted-risk` + `--expires`; never re-baseline silently. |
|
|
174
|
+
|
|
175
|
+
Prefer the allowlist over re-baselining for per-finding calls — it carries a
|
|
176
|
+
typed reason a future maintainer can read. Reserve "accept as baseline" for
|
|
177
|
+
the deliberate codebase-wide line-in-the-sand, not for hiding a finding your
|
|
178
|
+
own feature introduced.
|
|
179
|
+
|
|
180
|
+
## Hand-offs
|
|
181
|
+
|
|
182
|
+
- A finding the guardrail blocked needs fixing → `dxkit-action` (the fix-loop
|
|
183
|
+
recipes for secrets, dep-vulns, SAST, test gaps).
|
|
184
|
+
- Re-running reports between iterations → `dxkit-reports`.
|
|
185
|
+
- Ignore-file / config edits as part of the feature → `dxkit-config`.
|
|
186
|
+
- Hook problems on the verify push → `dxkit-hooks`.
|
|
187
|
+
- Deeper structural exploration than `context` gives (entry-points,
|
|
188
|
+
communities, hot-files) → run `npx vyuh-dxkit explore <subcommand>`
|
|
189
|
+
directly; see the `explore` command docs.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dxkit-ingest
|
|
3
|
+
description: Bring an external interprocedural-SAST engine's findings (Snyk Code, CodeQL, or any SARIF) into dxkit so they're fingerprinted, baselined, guardrailed, graph-linked, and fixable. Use when the user says "ingest Snyk", "pull our Snyk Code findings", "import a SARIF file", "run CodeQL and bring it in", or asks why dxkit's SAST finds less than Snyk/CodeQL.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# dxkit-ingest
|
|
7
|
+
|
|
8
|
+
dxkit's bundled SAST (community semgrep) is **intraprocedural** — it cannot follow tainted data across function boundaries. The findings that dominate a Snyk Code or CodeQL report (path traversal, information exposure, SSRF, injection) are **interprocedural** and live outside that engine. This skill brings those findings INTO dxkit so they become first-class: fingerprinted, deduped against native findings, written to the baseline, enforced by the guardrail, linked to the code graph, and fixable through `dxkit-action`.
|
|
9
|
+
|
|
10
|
+
dxkit is not re-detecting — it's orchestrating. The detection engine stays whatever the customer can run; dxkit owns the governance + agentic-fix loop on top of it.
|
|
11
|
+
|
|
12
|
+
## Pick the engine (license-aware)
|
|
13
|
+
|
|
14
|
+
Run the resolver's logic before ingesting:
|
|
15
|
+
|
|
16
|
+
| Situation | Engine | Why |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| Customer already runs **Snyk** (any tier, incl. free) | **Snyk Code via REST** | Reads stored findings — consumes **no** Snyk test quota. Their own license. |
|
|
19
|
+
| **Open-source** repo | **CodeQL on-demand** | CodeQL's CLI is licensed for open source. |
|
|
20
|
+
| **Private** repo with **GitHub Advanced Security** | **CodeQL on-demand** | GHAS covers private-repo CodeQL. Confirm consent first. |
|
|
21
|
+
| Private repo, no GHAS, no Snyk | stay on community semgrep | No licensed interprocedural engine available. Don't run CodeQL on private code without GHAS. |
|
|
22
|
+
|
|
23
|
+
**Never run CodeQL against a non-public repo without confirming the user has GitHub Advanced Security.** dxkit prompts for this; honor it.
|
|
24
|
+
|
|
25
|
+
## Path A — ingest Snyk Code
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Token: a Snyk API token from Snyk → Account settings → API token.
|
|
29
|
+
# dxkit reads it from the ENVIRONMENT — it does NOT auto-load a .env file.
|
|
30
|
+
export SNYK_TOKEN=... # in CI, add this once as a repo/org Actions secret
|
|
31
|
+
# org/project resolve from the flag, then .vyuh-dxkit.json, then the
|
|
32
|
+
# environment (SNYK_ORG_ID / SNYK_PROJECT_ID) — so an exported shell needs
|
|
33
|
+
# no flags. The project id is the project page URL in the Snyk UI.
|
|
34
|
+
npx vyuh-dxkit ingest --from-snyk --org <org-id> --project <project-id>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`--from-snyk` works on **every Snyk plan**, two ways:
|
|
38
|
+
|
|
39
|
+
- **REST API (quota-free)** — reads stored findings without consuming the
|
|
40
|
+
org's Snyk Code test quota. But REST API access is a **Snyk Enterprise**
|
|
41
|
+
entitlement; on Free/Team plans the read returns 403.
|
|
42
|
+
- **CLI fallback (free/team)** — on that 403 dxkit automatically falls back to
|
|
43
|
+
`snyk code test` (the Snyk Code *product* entitlement that free includes),
|
|
44
|
+
which writes SARIF dxkit ingests. This **does** cost one Snyk Code test from
|
|
45
|
+
the quota per run, and only needs the org (no project id). Pass `--snyk-cli`
|
|
46
|
+
to force this path and skip the REST attempt. dxkit installs the Snyk CLI on
|
|
47
|
+
demand if it's missing.
|
|
48
|
+
|
|
49
|
+
So on a free-tier customer, `--from-snyk` "just works" — it tries REST, hits
|
|
50
|
+
403, and runs the CLI test. Either way it writes `.dxkit/external/snyk-code.json`.
|
|
51
|
+
**Commit it** — every developer and CI run then reads the findings WITHOUT a
|
|
52
|
+
token; only whoever runs `ingest` (ideally one CI refresh job) needs it.
|
|
53
|
+
|
|
54
|
+
If `SNYK_TOKEN` is unset, dxkit says so explicitly — `export` it (or set the CI
|
|
55
|
+
secret); it will not read a `.env` file for you.
|
|
56
|
+
|
|
57
|
+
## Path B — ingest a SARIF file (any engine)
|
|
58
|
+
|
|
59
|
+
For CodeQL, a Snyk SARIF export, Semgrep Pro, Bearer, or anything that emits SARIF 2.1.0:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npx vyuh-dxkit ingest --sarif results.sarif # engine auto-detected from the SARIF
|
|
63
|
+
npx vyuh-dxkit ingest --sarif results.sarif --engine codeql # or force the label
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Producing the SARIF with CodeQL (OSS / GHAS only)
|
|
67
|
+
|
|
68
|
+
CodeQL is heavy (~database build + analysis; tens of minutes). Run it on demand / in CI, never on the pre-push hook.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
codeql database create db --language=javascript-typescript --source-root=.
|
|
72
|
+
codeql database analyze db \
|
|
73
|
+
codeql/javascript-queries:codeql-suites/javascript-security-extended.qls \
|
|
74
|
+
--format=sarifv2.1.0 --output=codeql.sarif
|
|
75
|
+
npx vyuh-dxkit ingest --sarif codeql.sarif
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Compiled languages (Java, C#, Kotlin, Go) need a working build for CodeQL extraction; JS/TS, Python, Ruby do not.
|
|
79
|
+
|
|
80
|
+
## After ingesting — the loop
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
[1] Ingest → .dxkit/external/<engine>.json (commit it)
|
|
84
|
+
[2] See them → npx vyuh-dxkit vulnerabilities --graph-context
|
|
85
|
+
[3] Fix them → hand off to dxkit-action (graph-linked: blast radius + callers)
|
|
86
|
+
[4] Lock the line → baseline picks them up; guardrail blocks net-new regressions
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Ingested findings flow through the same aggregate as native findings, so they appear in the vulnerability report (with the engine as the `tool`), get a stable fingerprint, dedupe against any overlapping semgrep finding, and — with `--graph-context` — carry the enclosing symbol + blast radius the agent needs to fix safely. That graph enrichment is the part the source engine's own autofix doesn't have.
|
|
90
|
+
|
|
91
|
+
## Keeping it fresh (CI)
|
|
92
|
+
|
|
93
|
+
Add a scheduled refresh (mirrors `dxkit-baseline-refresh`): a CI job with the `SNYK_TOKEN` secret runs `ingest --from-snyk` and commits the updated snapshot. The bundled `--with-deep-sast-refresh` workflow (`workflow_dispatch`) does exactly this; its `method` input picks `api` (Enterprise, quota-free) or `cli` (free/team, one test per run). The ingested findings are a point-in-time snapshot of the engine's last scan — re-ingest after the engine re-scans.
|
|
94
|
+
|
|
95
|
+
## Hand-offs
|
|
96
|
+
|
|
97
|
+
- To fix the ingested findings → `dxkit-action` (it reads them like any code finding).
|
|
98
|
+
- For token / secret setup questions → `dxkit-config`.
|
|
99
|
+
- For the broader read→act→verify loop → `dxkit-reports` then `dxkit-action`.
|
|
@@ -94,6 +94,16 @@ If any step fails, **stop**. Don't continue with downstream steps. Surface:
|
|
|
94
94
|
- Which step failed + its stderr
|
|
95
95
|
- Suggested recovery: "Run `npx vyuh-dxkit doctor` to see current state, or invoke the `dxkit-fix` skill to walk through repair."
|
|
96
96
|
|
|
97
|
+
**Peer-dep ERESOLVE on the binary install.** The most common failure on a
|
|
98
|
+
brownfield Node repo: `npm install @vyuhlabs/dxkit@<version>` aborts with
|
|
99
|
+
`npm error code ERESOLVE` from a conflict in the project's *own* existing
|
|
100
|
+
dependency tree (not dxkit's). It's a pre-existing conflict the upgrade
|
|
101
|
+
merely surfaces. Recovery: retry the same command with `--legacy-peer-deps`
|
|
102
|
+
(npm's own error message also suggests this), then persist the choice so
|
|
103
|
+
future installs don't re-hit it: `echo "legacy-peer-deps=true" >> .npmrc`.
|
|
104
|
+
After it succeeds, continue the loop. (`doctor` flags a missing `.npmrc`
|
|
105
|
+
persistence as its own operational check.)
|
|
106
|
+
|
|
97
107
|
### 6. Verify with doctor
|
|
98
108
|
|
|
99
109
|
If all steps succeeded, run `npx vyuh-dxkit doctor` and report. If doctor surfaces operational issues post-upgrade (e.g. `summary.fixable[]` not empty), **hand off to dxkit-fix** — say "Upgrade complete, but doctor surfaced N gaps. Walking through dxkit-fix to close them."
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
name: dxkit deep-SAST refresh
|
|
2
|
+
|
|
3
|
+
# Periodically re-ingest interprocedural SAST findings (Snyk Code) into
|
|
4
|
+
# `.dxkit/external/` and commit the snapshot. The committed snapshot is
|
|
5
|
+
# what the pre-push hook and the PR guardrail enforce against, so this
|
|
6
|
+
# job is the ONE place the external engine's token is needed — every
|
|
7
|
+
# developer and CI run reads the snapshot without it.
|
|
8
|
+
#
|
|
9
|
+
# Setup (one-time, by an admin):
|
|
10
|
+
# 1. Add a repository (or organization) secret `SNYK_TOKEN`
|
|
11
|
+
# (Settings → Secrets and variables → Actions). The token is never
|
|
12
|
+
# committed — it lives only here.
|
|
13
|
+
# 2. Set the org/project in `.vyuh-dxkit.json`:
|
|
14
|
+
# { "deepSast": { "snyk": { "orgId": "…", "projectId": "…" } } }
|
|
15
|
+
#
|
|
16
|
+
# Two read methods (pick via the `method` input when running on demand):
|
|
17
|
+
# - api (default): read stored findings over the Snyk REST API. Does NOT
|
|
18
|
+
# consume the org's Snyk Code test quota — but REST API access is an
|
|
19
|
+
# Enterprise-tier entitlement. On other plans the read 403s and dxkit
|
|
20
|
+
# auto-falls-back to the CLI method below.
|
|
21
|
+
# - cli: run `snyk code test` on the checkout (Snyk Code *product*
|
|
22
|
+
# entitlement, which free/team plans include). Costs one Snyk Code
|
|
23
|
+
# test from the quota per run. Needs only the org (no project id).
|
|
24
|
+
#
|
|
25
|
+
# The auto-commit carries `[skip ci]` so it doesn't re-trigger CI.
|
|
26
|
+
#
|
|
27
|
+
# This runs ON DEMAND only — trigger it from the Actions tab (Run
|
|
28
|
+
# workflow). To also refresh on a schedule, uncomment the `schedule:`
|
|
29
|
+
# block below; scheduled runs use the default method (`api`, which
|
|
30
|
+
# auto-falls-back to the CLI on non-Enterprise plans).
|
|
31
|
+
|
|
32
|
+
on:
|
|
33
|
+
workflow_dispatch:
|
|
34
|
+
inputs:
|
|
35
|
+
method:
|
|
36
|
+
description: 'Read method: api (quota-free, Enterprise) or cli (one test/run, free-tier)'
|
|
37
|
+
type: choice
|
|
38
|
+
default: api
|
|
39
|
+
options:
|
|
40
|
+
- api
|
|
41
|
+
- cli
|
|
42
|
+
# schedule:
|
|
43
|
+
# - cron: '0 6 * * 1' # weekly, Monday 06:00 UTC
|
|
44
|
+
|
|
45
|
+
permissions:
|
|
46
|
+
contents: write
|
|
47
|
+
|
|
48
|
+
jobs:
|
|
49
|
+
refresh:
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v6
|
|
53
|
+
with:
|
|
54
|
+
fetch-depth: 0
|
|
55
|
+
|
|
56
|
+
- uses: actions/setup-node@v6
|
|
57
|
+
with:
|
|
58
|
+
node-version: '22'
|
|
59
|
+
|
|
60
|
+
- name: Install dxkit
|
|
61
|
+
run: |
|
|
62
|
+
if [ -f package-lock.json ]; then
|
|
63
|
+
npm ci
|
|
64
|
+
elif [ -f package.json ]; then
|
|
65
|
+
npm install
|
|
66
|
+
else
|
|
67
|
+
npm install -g @vyuhlabs/dxkit
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
- name: Ingest Snyk Code findings
|
|
71
|
+
env:
|
|
72
|
+
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
|
73
|
+
METHOD: ${{ github.event.inputs.method || 'api' }}
|
|
74
|
+
run: |
|
|
75
|
+
if [ -z "${SNYK_TOKEN}" ]; then
|
|
76
|
+
echo "SNYK_TOKEN secret is not set — skipping deep-SAST refresh."
|
|
77
|
+
echo "Add it under Settings → Secrets and variables → Actions to enable."
|
|
78
|
+
exit 0
|
|
79
|
+
fi
|
|
80
|
+
if [ -x ./node_modules/.bin/vyuh-dxkit ]; then
|
|
81
|
+
DXKIT=./node_modules/.bin/vyuh-dxkit
|
|
82
|
+
else
|
|
83
|
+
DXKIT=vyuh-dxkit
|
|
84
|
+
fi
|
|
85
|
+
# org/project come from .vyuh-dxkit.json:deepSast.snyk. The api
|
|
86
|
+
# method auto-falls-back to the CLI on plans without REST access;
|
|
87
|
+
# the cli method forces `snyk code test` (one test from quota).
|
|
88
|
+
if [ "${METHOD}" = "cli" ]; then
|
|
89
|
+
"${DXKIT}" ingest --from-snyk --snyk-cli
|
|
90
|
+
else
|
|
91
|
+
"${DXKIT}" ingest --from-snyk
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
- name: Commit and push refreshed snapshot
|
|
95
|
+
run: |
|
|
96
|
+
git config user.name "github-actions[bot]"
|
|
97
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
98
|
+
if git diff --quiet -- .dxkit/external/; then
|
|
99
|
+
echo "Ingested snapshot unchanged — nothing to commit."
|
|
100
|
+
exit 0
|
|
101
|
+
fi
|
|
102
|
+
git add .dxkit/external/
|
|
103
|
+
git commit -m "chore(deep-sast): refresh ingested findings [skip ci]"
|
|
104
|
+
git push
|