@vyuhlabs/dxkit 2.4.8 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +312 -0
- package/README.md +360 -439
- package/dist/analyzers/security/aggregator.d.ts.map +1 -1
- package/dist/analyzers/security/aggregator.js +4 -46
- package/dist/analyzers/security/aggregator.js.map +1 -1
- package/dist/analyzers/tools/fingerprint.d.ts +91 -26
- package/dist/analyzers/tools/fingerprint.d.ts.map +1 -1
- package/dist/analyzers/tools/fingerprint.js +111 -22
- package/dist/analyzers/tools/fingerprint.js.map +1 -1
- package/dist/analyzers/tools/generic.d.ts.map +1 -1
- package/dist/analyzers/tools/generic.js +6 -1
- package/dist/analyzers/tools/generic.js.map +1 -1
- package/dist/analyzers/tools/gitleaks.d.ts +24 -1
- package/dist/analyzers/tools/gitleaks.d.ts.map +1 -1
- package/dist/analyzers/tools/gitleaks.js +20 -11
- package/dist/analyzers/tools/gitleaks.js.map +1 -1
- package/dist/analyzers/tools/graphify.d.ts.map +1 -1
- package/dist/analyzers/tools/graphify.js +9 -5
- package/dist/analyzers/tools/graphify.js.map +1 -1
- package/dist/analyzers/tools/tool-registry.d.ts +19 -1
- package/dist/analyzers/tools/tool-registry.d.ts.map +1 -1
- package/dist/analyzers/tools/tool-registry.js +25 -0
- package/dist/analyzers/tools/tool-registry.js.map +1 -1
- package/dist/analyzers/types.d.ts +6 -4
- package/dist/analyzers/types.d.ts.map +1 -1
- package/dist/baseline/baseline-file.d.ts +104 -0
- package/dist/baseline/baseline-file.d.ts.map +1 -0
- package/dist/baseline/baseline-file.js +110 -0
- package/dist/baseline/baseline-file.js.map +1 -0
- package/dist/baseline/check-renderers.d.ts +108 -0
- package/dist/baseline/check-renderers.d.ts.map +1 -0
- package/dist/baseline/check-renderers.js +379 -0
- package/dist/baseline/check-renderers.js.map +1 -0
- package/dist/baseline/check.d.ts +127 -0
- package/dist/baseline/check.d.ts.map +1 -0
- package/dist/baseline/check.js +462 -0
- package/dist/baseline/check.js.map +1 -0
- package/dist/baseline/content-hash.d.ts +83 -0
- package/dist/baseline/content-hash.d.ts.map +1 -0
- package/dist/baseline/content-hash.js +131 -0
- package/dist/baseline/content-hash.js.map +1 -0
- package/dist/baseline/create.d.ts +96 -0
- package/dist/baseline/create.d.ts.map +1 -0
- package/dist/baseline/create.js +339 -0
- package/dist/baseline/create.js.map +1 -0
- package/dist/baseline/entry-to-located.d.ts +35 -0
- package/dist/baseline/entry-to-located.d.ts.map +1 -0
- package/dist/baseline/entry-to-located.js +72 -0
- package/dist/baseline/entry-to-located.js.map +1 -0
- package/dist/baseline/finding-identity.d.ts +47 -0
- package/dist/baseline/finding-identity.d.ts.map +1 -0
- package/dist/baseline/finding-identity.js +292 -0
- package/dist/baseline/finding-identity.js.map +1 -0
- package/dist/baseline/git-aware-match.d.ts +146 -0
- package/dist/baseline/git-aware-match.d.ts.map +1 -0
- package/dist/baseline/git-aware-match.js +439 -0
- package/dist/baseline/git-aware-match.js.map +1 -0
- package/dist/baseline/policy.d.ts +171 -0
- package/dist/baseline/policy.d.ts.map +1 -0
- package/dist/baseline/policy.js +206 -0
- package/dist/baseline/policy.js.map +1 -0
- package/dist/baseline/producers/health.d.ts +30 -0
- package/dist/baseline/producers/health.d.ts.map +1 -0
- package/dist/baseline/producers/health.js +42 -0
- package/dist/baseline/producers/health.js.map +1 -0
- package/dist/baseline/producers/index.d.ts +164 -0
- package/dist/baseline/producers/index.d.ts.map +1 -0
- package/dist/baseline/producers/index.js +200 -0
- package/dist/baseline/producers/index.js.map +1 -0
- package/dist/baseline/producers/licenses.d.ts +23 -0
- package/dist/baseline/producers/licenses.d.ts.map +1 -0
- package/dist/baseline/producers/licenses.js +46 -0
- package/dist/baseline/producers/licenses.js.map +1 -0
- package/dist/baseline/producers/quality.d.ts +39 -0
- package/dist/baseline/producers/quality.d.ts.map +1 -0
- package/dist/baseline/producers/quality.js +84 -0
- package/dist/baseline/producers/quality.js.map +1 -0
- package/dist/baseline/producers/secret-hmac.d.ts +45 -0
- package/dist/baseline/producers/secret-hmac.d.ts.map +1 -0
- package/dist/baseline/producers/secret-hmac.js +70 -0
- package/dist/baseline/producers/secret-hmac.js.map +1 -0
- package/dist/baseline/producers/security.d.ts +59 -0
- package/dist/baseline/producers/security.d.ts.map +1 -0
- package/dist/baseline/producers/security.js +135 -0
- package/dist/baseline/producers/security.js.map +1 -0
- package/dist/baseline/producers/tests.d.ts +36 -0
- package/dist/baseline/producers/tests.d.ts.map +1 -0
- package/dist/baseline/producers/tests.js +69 -0
- package/dist/baseline/producers/tests.js.map +1 -0
- package/dist/baseline/salt.d.ts +45 -0
- package/dist/baseline/salt.d.ts.map +1 -0
- package/dist/baseline/salt.js +113 -0
- package/dist/baseline/salt.js.map +1 -0
- package/dist/baseline/show.d.ts +79 -0
- package/dist/baseline/show.d.ts.map +1 -0
- package/dist/baseline/show.js +233 -0
- package/dist/baseline/show.js.map +1 -0
- package/dist/baseline/types.d.ts +482 -0
- package/dist/baseline/types.d.ts.map +1 -0
- package/dist/baseline/types.js +53 -0
- package/dist/baseline/types.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +398 -82
- package/dist/cli.js.map +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +0 -4
- package/dist/constants.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +39 -35
- package/dist/doctor.js.map +1 -1
- package/dist/fail-on.d.ts +84 -0
- package/dist/fail-on.d.ts.map +1 -0
- package/dist/fail-on.js +128 -0
- package/dist/fail-on.js.map +1 -0
- package/dist/generator.d.ts +1 -1
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +81 -274
- package/dist/generator.js.map +1 -1
- package/dist/hooks-cli.d.ts +20 -0
- package/dist/hooks-cli.d.ts.map +1 -0
- package/dist/hooks-cli.js +145 -0
- package/dist/hooks-cli.js.map +1 -0
- package/dist/languages/csharp.d.ts.map +1 -1
- package/dist/languages/csharp.js +4 -9
- package/dist/languages/csharp.js.map +1 -1
- package/dist/languages/go.d.ts.map +1 -1
- package/dist/languages/go.js +3 -14
- package/dist/languages/go.js.map +1 -1
- package/dist/languages/index.d.ts +19 -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 +4 -6
- package/dist/languages/java.js.map +1 -1
- package/dist/languages/kotlin.d.ts.map +1 -1
- package/dist/languages/kotlin.js +9 -11
- package/dist/languages/kotlin.js.map +1 -1
- package/dist/languages/python.d.ts.map +1 -1
- package/dist/languages/python.js +4 -15
- package/dist/languages/python.js.map +1 -1
- package/dist/languages/ruby.d.ts.map +1 -1
- package/dist/languages/ruby.js +4 -6
- package/dist/languages/ruby.js.map +1 -1
- package/dist/languages/rust.d.ts.map +1 -1
- package/dist/languages/rust.js +4 -4
- package/dist/languages/rust.js.map +1 -1
- package/dist/languages/types.d.ts +29 -28
- package/dist/languages/types.d.ts.map +1 -1
- package/dist/languages/typescript.d.ts.map +1 -1
- package/dist/languages/typescript.js +31 -4
- package/dist/languages/typescript.js.map +1 -1
- package/dist/lib.d.ts +2 -3
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +3 -6
- package/dist/lib.js.map +1 -1
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +0 -10
- package/dist/prompts.js.map +1 -1
- package/dist/report-schema.d.ts +42 -0
- package/dist/report-schema.d.ts.map +1 -0
- package/dist/report-schema.js +54 -0
- package/dist/report-schema.js.map +1 -0
- package/dist/ship-installers.d.ts +112 -0
- package/dist/ship-installers.d.ts.map +1 -0
- package/dist/ship-installers.js +530 -0
- package/dist/ship-installers.js.map +1 -0
- package/dist/tools-cli.d.ts.map +1 -1
- package/dist/tools-cli.js +45 -9
- package/dist/tools-cli.js.map +1 -1
- package/dist/types.d.ts +0 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +0 -4
- package/dist/update.js.map +1 -1
- package/package.json +17 -11
- package/templates/.claude/skills/dxkit-action/SKILL.md +150 -0
- package/templates/.claude/skills/dxkit-config/SKILL.md +124 -0
- package/templates/.claude/skills/dxkit-hooks/SKILL.md +109 -0
- package/templates/.claude/skills/dxkit-init/SKILL.md +93 -0
- package/templates/.claude/skills/dxkit-learn/SKILL.md +84 -0
- package/templates/.claude/skills/dxkit-reports/SKILL.md +111 -0
- package/templates/.devcontainer/devcontainer.json +55 -0
- package/templates/.devcontainer/install-agent-clis.sh +42 -0
- package/templates/.devcontainer/post-create.sh +81 -0
- package/templates/.githooks/pre-commit +55 -0
- package/templates/.githooks/pre-push +63 -0
- package/templates/.github/workflows/dxkit-baseline-refresh.yml +78 -0
- package/templates/.github/workflows/dxkit-guardrails.yml +98 -0
- package/templates/AGENTS.md.template +137 -0
- package/templates/CLAUDE.md.template +16 -245
- package/dist/codebase-scanner.d.ts +0 -36
- package/dist/codebase-scanner.d.ts.map +0 -1
- package/dist/codebase-scanner.js +0 -688
- package/dist/codebase-scanner.js.map +0 -1
- package/dist/project-yaml.d.ts +0 -13
- package/dist/project-yaml.d.ts.map +0 -1
- package/dist/project-yaml.js +0 -188
- package/dist/project-yaml.js.map +0 -1
- package/templates/.ai/README.md +0 -117
- package/templates/.ai/prompts/execution-prompt.md +0 -9
- package/templates/.ai/prompts/planning-prompt.md +0 -18
- package/templates/.ai/prompts/session-end-template.md +0 -182
- package/templates/.ai/prompts/session-end.md +0 -132
- package/templates/.ai/prompts/session-start.md +0 -109
- package/templates/.ai/prompts/step-by-step.md +0 -113
- package/templates/.ai/sessions/.gitkeep +0 -0
- package/templates/.claude/agents/doc-writer.md +0 -107
- package/templates/.claude/agents/knowledge-bot.md +0 -64
- package/templates/.claude/agents/onboarding.md +0 -61
- package/templates/.claude/agents/quality-reviewer.md +0 -85
- package/templates/.claude/agents-available/code-reviewer.md +0 -29
- package/templates/.claude/agents-available/codebase-explorer.md +0 -100
- package/templates/.claude/agents-available/dashboard-builder.md +0 -433
- package/templates/.claude/agents-available/debugger.md +0 -29
- package/templates/.claude/agents-available/dependency-mapper.md +0 -80
- package/templates/.claude/agents-available/dev-report.md +0 -108
- package/templates/.claude/agents-available/doc-writer.md +0 -107
- package/templates/.claude/agents-available/feature-builder.md +0 -163
- package/templates/.claude/agents-available/feature-planner.md +0 -185
- package/templates/.claude/agents-available/health-auditor.md +0 -95
- package/templates/.claude/agents-available/hooks-configurator.md +0 -211
- package/templates/.claude/agents-available/knowledge-bot.md +0 -62
- package/templates/.claude/agents-available/plan-executor.md +0 -133
- package/templates/.claude/agents-available/strategic-planner.md +0 -141
- package/templates/.claude/agents-available/test-gap-finder.md +0 -67
- package/templates/.claude/agents-available/test-writer.md +0 -34
- package/templates/.claude/agents-available/vulnerability-scanner.md +0 -173
- package/templates/.claude/commands/ask.md +0 -7
- package/templates/.claude/commands/build-feature.md +0 -26
- package/templates/.claude/commands/build.md.template +0 -30
- package/templates/.claude/commands/check.md.template +0 -43
- package/templates/.claude/commands/dashboard.md +0 -28
- package/templates/.claude/commands/deps.md +0 -15
- package/templates/.claude/commands/dev-report.md +0 -50
- package/templates/.claude/commands/docs.md +0 -21
- package/templates/.claude/commands/doctor.md +0 -21
- package/templates/.claude/commands/enable-agent.md +0 -12
- package/templates/.claude/commands/execute-plan.md +0 -25
- package/templates/.claude/commands/explore-codebase.md +0 -12
- package/templates/.claude/commands/export-pdf.md +0 -30
- package/templates/.claude/commands/feature.md +0 -25
- package/templates/.claude/commands/fix-issue.md +0 -12
- package/templates/.claude/commands/fix.md.template +0 -32
- package/templates/.claude/commands/health.md +0 -58
- package/templates/.claude/commands/help.md +0 -36
- package/templates/.claude/commands/learn.md +0 -48
- package/templates/.claude/commands/onboarding.md +0 -21
- package/templates/.claude/commands/plan.md +0 -20
- package/templates/.claude/commands/quality.md.template +0 -65
- package/templates/.claude/commands/session-end.md +0 -40
- package/templates/.claude/commands/session-start.md +0 -30
- package/templates/.claude/commands/setup-hooks.md +0 -18
- package/templates/.claude/commands/setup-pr-review.md +0 -72
- package/templates/.claude/commands/stealth-mode.md +0 -17
- package/templates/.claude/commands/test-gaps.md +0 -49
- package/templates/.claude/commands/test.md.template +0 -40
- package/templates/.claude/commands/vulnerabilities.md +0 -49
- package/templates/.claude/skills/build/SKILL.md.template +0 -98
- package/templates/.claude/skills/deploy/SKILL.md.template +0 -131
- package/templates/.claude/skills/deploy/references/gotchas.md +0 -5
- package/templates/.claude/skills/doctor/SKILL.md +0 -54
- package/templates/.claude/skills/gcloud/SKILL.md +0 -66
- package/templates/.claude/skills/gcloud/references/gotchas.md +0 -5
- package/templates/.claude/skills/learned/SKILL.md +0 -55
- package/templates/.claude/skills/learned/references/conventions.md +0 -11
- package/templates/.claude/skills/learned/references/deny-recommendations.md +0 -18
- package/templates/.claude/skills/learned/references/gotchas.md +0 -11
- package/templates/.claude/skills/pulumi/SKILL.md +0 -73
- package/templates/.claude/skills/quality/SKILL.md.template +0 -108
- package/templates/.claude/skills/quality/references/gotchas.md +0 -5
- package/templates/.claude/skills/review/SKILL.md.template +0 -73
- package/templates/.claude/skills/scaffold/SKILL.md.template +0 -123
- package/templates/.claude/skills/secrets/SKILL.md +0 -52
- package/templates/.claude/skills/session/SKILL.md +0 -43
- package/templates/.claude/skills/test/SKILL.md.template +0 -122
- package/templates/.claude/skills/test/references/gotchas.md +0 -5
- package/templates/.devcontainer/Dockerfile.dev.template +0 -89
- package/templates/.devcontainer/devcontainer.json.template +0 -184
- package/templates/.devcontainer/docker-compose.yml.template +0 -105
- package/templates/.devcontainer/init-scripts/01-init.sql.template +0 -12
- package/templates/.devcontainer/post-create.sh.template +0 -298
- package/templates/.github/workflows/ci.yml.template +0 -399
- package/templates/.github/workflows/quality.yml.template +0 -376
- package/templates/.pre-commit-config.yaml.template +0 -106
- package/templates/.project/config/edit_config.py +0 -275
- package/templates/.project/config/project_config.py +0 -894
- package/templates/.project/scripts/codegen/generate-all.sh +0 -20
- package/templates/.project/scripts/codegen/validate-all.sh +0 -17
- package/templates/.project/scripts/docs/generate-all.sh +0 -30
- package/templates/.project/scripts/docs/serve.sh +0 -20
- package/templates/.project/scripts/quality/fix-all.sh +0 -138
- package/templates/.project/scripts/quality/lint-go.sh +0 -34
- package/templates/.project/scripts/quality/lint-python.sh +0 -54
- package/templates/.project/scripts/quality/run-all.sh +0 -497
- package/templates/.project/scripts/session/commit.sh +0 -70
- package/templates/.project/scripts/session/create-pr.sh +0 -165
- package/templates/.project/scripts/session/end.sh +0 -207
- package/templates/.project/scripts/session/start.sh +0 -233
- package/templates/.project/scripts/setup/doctor.sh +0 -404
- package/templates/.project/scripts/setup/interactive-setup.sh +0 -585
- package/templates/.project/scripts/sync/sync-template.sh +0 -328
- package/templates/.project/scripts/test/run-all.sh +0 -179
- package/templates/.project/scripts/test/run-quick.sh +0 -25
- package/templates/Makefile +0 -514
- package/templates/config/versions.yaml +0 -57
- package/templates/configs/go/.golangci.yml.template +0 -172
- package/templates/configs/go/go.mod.template +0 -15
- package/templates/configs/java/README.md +0 -6
- package/templates/configs/kotlin/README.md +0 -6
- package/templates/configs/node/package.json.template +0 -67
- package/templates/configs/node/tsconfig.json.template +0 -53
- package/templates/configs/python/pyproject.toml.template +0 -92
- package/templates/configs/python/pytest.ini.template +0 -64
- package/templates/configs/python/ruff.toml.template +0 -79
- package/templates/configs/ruby/README.md +0 -6
- package/templates/configs/rust/Cargo.toml.template +0 -51
- package/templates/configs/shared/.editorconfig +0 -67
- package/templates/scripts/validate-templates.sh +0 -449
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dxkit-learn
|
|
3
|
+
description: Answer questions about dxkit — what each scanner does, what a baseline is, what the 6 health dimensions score, how guardrails work. Use when the user asks "what does dxkit X do?", "what's a baseline?", "what's the slop score?", "how do hooks fit in?", or anything else about dxkit concepts.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# dxkit-learn
|
|
7
|
+
|
|
8
|
+
This skill explains how dxkit works. Reach for it when the user asks about dxkit concepts before they take an action.
|
|
9
|
+
|
|
10
|
+
## Mental model
|
|
11
|
+
|
|
12
|
+
dxkit measures a codebase along **6 dimensions** (Security, Code Quality, Tests, Documentation, Maintainability, Developer Experience) using deterministic scanners (gitleaks, semgrep, cloc, jscpd, graphify, ruff, eslint, …). Findings are anchored to a **baseline** (`.dxkit/baselines/main.json`) so today's pre-existing issues don't block tomorrow's PR. A **guardrail check** diffs current state against the baseline and blocks net-new regressions. Hooks + CI wire the guardrail into the developer's workflow.
|
|
13
|
+
|
|
14
|
+
The three contracts to remember:
|
|
15
|
+
|
|
16
|
+
1. **Baseline = the brownfield anchor**. Pre-existing findings are recorded once; future scans only block on *additions*.
|
|
17
|
+
2. **Hooks fire fast (pre-push); CI fires thorough**. Both use the same guardrail logic.
|
|
18
|
+
3. **Reports are deterministic** — same code + same baseline = same findings. The salt mode (`deterministic` vs `random`) controls per-finding identity stability across runs.
|
|
19
|
+
|
|
20
|
+
## The 6 dimensions
|
|
21
|
+
|
|
22
|
+
Each dimension is a 0-100 score with letter grade (A≥80, B≥60, C≥40, D≥20, E<20):
|
|
23
|
+
|
|
24
|
+
| Dimension | What scores it down |
|
|
25
|
+
|---|---|
|
|
26
|
+
| **Security** | Secret leaks (gitleaks), SAST findings (semgrep), dependency vulns (osv-scanner / npm-audit / pip-audit / etc.), TLS-bypass patterns |
|
|
27
|
+
| **Code Quality** | Lint findings (eslint / ruff / golangci-lint / clippy / detekt / rubocop / dotnet-format), high duplication (jscpd), code-pattern slop |
|
|
28
|
+
| **Tests** | Missing test coverage on primary-architecture files; missing test runner config; below-threshold line coverage |
|
|
29
|
+
| **Documentation** | Missing/empty README; missing doc-comments on public APIs (XML-doc/JSDoc/TSDoc/godoc/etc.); below-threshold comment ratio |
|
|
30
|
+
| **Maintainability** | Function/file size outliers, deep cyclomatic complexity, god-objects, high orphan-module count, dead imports |
|
|
31
|
+
| **Developer Experience** | Missing `.gitignore` / `.editorconfig` / `package.json` engines pin / devcontainer / hooks / CI workflow |
|
|
32
|
+
|
|
33
|
+
Run `vyuh-dxkit health` to see all six at once. Each dimension report has a "top actions" list — the changes that would lift the score the most.
|
|
34
|
+
|
|
35
|
+
## The scanner toolchain
|
|
36
|
+
|
|
37
|
+
dxkit doesn't write parsers — it orchestrates established tools and computes scores. The full list is in `TOOL_DEFS` (or run `vyuh-dxkit tools list`). Key ones:
|
|
38
|
+
|
|
39
|
+
- **gitleaks** — secret scanning (API keys, AWS credentials, GitHub tokens)
|
|
40
|
+
- **semgrep** — multi-language SAST (auto config picks rulesets per active language pack)
|
|
41
|
+
- **cloc** — language-aware line counting (excludes comments + blanks)
|
|
42
|
+
- **jscpd** — copy-paste detection
|
|
43
|
+
- **graphify** — AST-based metrics (functions, classes, cohesion, god-nodes, dead imports)
|
|
44
|
+
- **osv-scanner** — dependency vulnerabilities (npm/pip/cargo/go/gem/maven via OSV.dev)
|
|
45
|
+
- Per-language linters: eslint (TS), ruff (Python), golangci-lint (Go), clippy (Rust), dotnet-format (C#), detekt (Kotlin), pmd (Java), rubocop (Ruby)
|
|
46
|
+
|
|
47
|
+
If a tool isn't installed, dxkit degrades gracefully (the affected dimension reports a partial score with a "missing tool" note instead of crashing).
|
|
48
|
+
|
|
49
|
+
## Baselines explained
|
|
50
|
+
|
|
51
|
+
A baseline is the per-finding identity snapshot of a scan. Every finding has a **fingerprint** (SHA-1[0:16] of file+rule+line-window+content). The baseline stores those fingerprints. The guardrail diffs today's scan against the baseline:
|
|
52
|
+
|
|
53
|
+
- Fingerprint in scan + in baseline → **existing** (ignored)
|
|
54
|
+
- Fingerprint in scan + NOT in baseline → **added** (blocks)
|
|
55
|
+
- Fingerprint in baseline + NOT in scan → **removed** (silently good)
|
|
56
|
+
|
|
57
|
+
That's why "fix a critical, leave the medium" works — the medium's fingerprint stays in the baseline; only net-new findings count.
|
|
58
|
+
|
|
59
|
+
Commands:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
vyuh-dxkit baseline create # Capture current state into .dxkit/baselines/main.json
|
|
63
|
+
vyuh-dxkit baseline show # Summarize what's recorded
|
|
64
|
+
vyuh-dxkit baseline show --kind secret # Drill into a specific finding kind
|
|
65
|
+
vyuh-dxkit guardrail check # Diff current scan vs baseline; exit 1 on net-new
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Hooks
|
|
69
|
+
|
|
70
|
+
Two hooks ship under `.githooks/`:
|
|
71
|
+
|
|
72
|
+
- **pre-push** (always-on under `--full`): runs the guardrail check before code leaves the developer's machine. Fast on warm scanner caches (~10-30s).
|
|
73
|
+
- **pre-commit** (opt-in via `--with-precommit-hook`): same logic, fires on every commit. Slower on large repos until incremental scanning lands.
|
|
74
|
+
|
|
75
|
+
Activation is wired via `npm postinstall` so `npm install` after `git clone` sets `core.hooksPath = .githooks` automatically.
|
|
76
|
+
|
|
77
|
+
## How to learn more
|
|
78
|
+
|
|
79
|
+
- `vyuh-dxkit <subcommand> --help` — flag reference
|
|
80
|
+
- `vyuh-dxkit baseline show` — what your repo already has recorded
|
|
81
|
+
- `.dxkit/reports/` — every analyzer's markdown + JSON output from the last run
|
|
82
|
+
- `vyuh-dxkit dashboard` — single HTML view of every report
|
|
83
|
+
|
|
84
|
+
When the user asks specifically about a scanner or a finding type, point them at the relevant report or run the relevant analyzer command directly.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dxkit-reports
|
|
3
|
+
description: Run dxkit reports and explain their output. Use when the user asks "run health", "check security", "show me the dashboard", "what does this score mean", or anything about generating / reading dxkit analyzer output. Hands off to dxkit-action for fixing findings.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# dxkit-reports
|
|
7
|
+
|
|
8
|
+
This skill runs dxkit analyzers and reads their output back to the user. It's the "tell me how my codebase is doing" surface.
|
|
9
|
+
|
|
10
|
+
## Command map
|
|
11
|
+
|
|
12
|
+
| User asks | Command | Output |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| "Overall health" / "give me the score" | `vyuh-dxkit health` | 6-dimension score table + top actions per dimension |
|
|
15
|
+
| "Check security" / "find vulns" | `vyuh-dxkit vulnerabilities` | Code-level SAST + dep-vuln + secret findings, grouped by severity |
|
|
16
|
+
| "Test coverage gaps" | `vyuh-dxkit test-gaps` | Source files without matching tests, prioritized by architectural role |
|
|
17
|
+
| "Code quality" | `vyuh-dxkit quality` | Lint findings + duplication + slop score |
|
|
18
|
+
| "Who's been working on what" | `vyuh-dxkit dev-report` | Per-author activity, hot files, churn |
|
|
19
|
+
| "License inventory" | `vyuh-dxkit licenses` | Every dependency's declared license |
|
|
20
|
+
| "Bill of materials" | `vyuh-dxkit bom` | Licenses + dep vulnerabilities joined (15-col XLSX-ready output) |
|
|
21
|
+
| "Run everything" | `vyuh-dxkit report` | Every analyzer in one shot, ~3-5 min |
|
|
22
|
+
| "Show me the dashboard" | `vyuh-dxkit dashboard` | Single HTML view of all reports — opens at `.dxkit/reports/dashboard.html` |
|
|
23
|
+
|
|
24
|
+
## Where output lands
|
|
25
|
+
|
|
26
|
+
Every analyzer writes to `.dxkit/reports/` with a date-stamped filename:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
.dxkit/reports/
|
|
30
|
+
health-2026-05-19.md
|
|
31
|
+
health-2026-05-19.json
|
|
32
|
+
vulnerability-scan-2026-05-19.md
|
|
33
|
+
vulnerability-scan-2026-05-19-detailed.json
|
|
34
|
+
...
|
|
35
|
+
dashboard.html
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The `.md` files are human-readable; the `.json` files are machine-readable (for CI consumption or custom tooling). Reports are gitignored by default — they regenerate on every run.
|
|
39
|
+
|
|
40
|
+
## Reading the health report
|
|
41
|
+
|
|
42
|
+
The 6 dimensions each get an A-E grade. Below each grade the "top actions" list shows what would lift the score the most (sorted by potential uplift). Example:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
Security: B (72)
|
|
46
|
+
Top actions:
|
|
47
|
+
1. Pin @types/node to ≥18.19.0 (closes 2 dep-vuln entries)
|
|
48
|
+
2. Add gitleaks pre-commit hook (closes 1 secret-scan finding)
|
|
49
|
+
3. Replace `Math.random()` in src/auth/token.ts (closes 1 SAST finding)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Score → rating: A ≥ 80, B ≥ 60, C ≥ 40, D ≥ 20, E < 20. **Cap tiers** can pin a score below its arithmetic value when trust is broken (e.g., uncommitted state caps at 79). The report explains the cap if one fires.
|
|
53
|
+
|
|
54
|
+
## Common patterns
|
|
55
|
+
|
|
56
|
+
### Quick health check (warm cache)
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
vyuh-dxkit health
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Re-uses cached scanner outputs where possible. ~5-15s on warm cache, ~30-60s cold.
|
|
63
|
+
|
|
64
|
+
### Pre-merge audit (thorough)
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
vyuh-dxkit health --with-coverage # Runs tests + materializes coverage before scoring
|
|
68
|
+
vyuh-dxkit vulnerabilities # Always re-runs the deep security scan
|
|
69
|
+
vyuh-dxkit dashboard # Renders the latest reports into one HTML view
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`--with-coverage` is slow (runs your test suite) but switches the Tests dimension from heuristic ("files match a test pattern") to real ("line coverage from your reporter"). Worth it for pre-merge audits.
|
|
73
|
+
|
|
74
|
+
### Per-PR scope
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
vyuh-dxkit guardrail check
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Diffs the current scan vs the baseline. Exit 1 on net-new findings (the same logic the pre-push hook uses).
|
|
81
|
+
|
|
82
|
+
### Failing CI on a threshold
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
vyuh-dxkit health --fail-on-score=70 # Exit 1 if overall score < 70
|
|
86
|
+
vyuh-dxkit vulnerabilities --fail-on-severity=high # Exit 1 if any high-severity finding
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Use these in CI for hard floors.
|
|
90
|
+
|
|
91
|
+
## Reading dependency findings
|
|
92
|
+
|
|
93
|
+
`vulnerabilities` (and `bom`) carry severity + CVSS where available. The severity column is computed via OSV.dev's enrichment — when OSV reports no severity, dxkit assigns one via CVSS v4.0 base-score math (see `src/analyzers/tools/cvss-v4.ts`).
|
|
94
|
+
|
|
95
|
+
When the user asks "is this CVE worth fixing today" the answer depends on:
|
|
96
|
+
1. **Reachability** — does the codebase actually call the vulnerable function? (Today: heuristic via graphify call-graph; reachability tiers are a roadmap item.)
|
|
97
|
+
2. **Exploitability** — public PoC? Authentication required? Network exposure?
|
|
98
|
+
3. **Patch availability** — is there a fixed version?
|
|
99
|
+
|
|
100
|
+
Surface those three when summarizing a dep-vuln finding. The detailed JSON has the OSV/GHSA reference URL — link to it.
|
|
101
|
+
|
|
102
|
+
## When the user wants to ACT on findings
|
|
103
|
+
|
|
104
|
+
Hand off to the `dxkit-action` skill — that's the workflow for prioritizing + fixing + re-baselining. This skill stops at "here's what's wrong."
|
|
105
|
+
|
|
106
|
+
## Troubleshooting
|
|
107
|
+
|
|
108
|
+
- **"Scanner X unavailable"** → run `vyuh-dxkit tools list` to see status; `vyuh-dxkit tools install` to install missing ones.
|
|
109
|
+
- **"N/A for this stack"** → applicability-guard fired (e.g., vitest-coverage on a mocha repo). Not a problem; the scanner doesn't apply here.
|
|
110
|
+
- **Report looks stale** → `.dxkit/reports/` is keyed by date. Re-run the analyzer to get a fresh date-stamped file.
|
|
111
|
+
- **Numbers don't match between two reports** → check whether `--with-coverage` was used. Without it, Tests dimension uses heuristic; with it, real coverage. They legitimately differ.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dxkit dev environment",
|
|
3
|
+
|
|
4
|
+
// Universal base + per-stack composable features. The features
|
|
5
|
+
// block below is generated by `vyuh-dxkit init` from the detected
|
|
6
|
+
// stack — only toolchains your project actually uses get installed.
|
|
7
|
+
// Always-on: Node (dxkit's own runtime) + GitHub CLI. Add or
|
|
8
|
+
// remove entries by hand if you want to over- or under-ride the
|
|
9
|
+
// auto-detected set.
|
|
10
|
+
"image": "mcr.microsoft.com/devcontainers/base:ubuntu-22.04",
|
|
11
|
+
|
|
12
|
+
"features": __DXKIT_DEVCONTAINER_FEATURES__,
|
|
13
|
+
|
|
14
|
+
// Reproducibility note: language toolchains are pinned in the
|
|
15
|
+
// features block above. Scanner tools (gitleaks, semgrep, cloc,
|
|
16
|
+
// jscpd, ruff, osv-scanner, ...) are pinned in dxkit's TOOL_DEFS
|
|
17
|
+
// registry and installed by `vyuh-dxkit tools install --yes` in
|
|
18
|
+
// post-create.sh. Bumping a scanner version is a dxkit upgrade,
|
|
19
|
+
// not a Dockerfile edit.
|
|
20
|
+
"postCreateCommand": "bash .devcontainer/post-create.sh",
|
|
21
|
+
|
|
22
|
+
// Run on every container start (incl. Codespaces resume). Keeps
|
|
23
|
+
// `dxkit tools list` accurate if a tool was uninstalled or the
|
|
24
|
+
// registry pinned-versions advanced since last use.
|
|
25
|
+
"postStartCommand": "command -v vyuh-dxkit >/dev/null 2>&1 && vyuh-dxkit tools list || true",
|
|
26
|
+
|
|
27
|
+
"customizations": {
|
|
28
|
+
"vscode": {
|
|
29
|
+
"extensions": [
|
|
30
|
+
"anthropic.claude-code",
|
|
31
|
+
"dbaeumer.vscode-eslint",
|
|
32
|
+
"esbenp.prettier-vscode",
|
|
33
|
+
"ms-python.python",
|
|
34
|
+
"ms-python.vscode-pylance",
|
|
35
|
+
"golang.go",
|
|
36
|
+
"rust-lang.rust-analyzer",
|
|
37
|
+
"ms-dotnettools.csharp",
|
|
38
|
+
"redhat.java",
|
|
39
|
+
"fwcd.kotlin",
|
|
40
|
+
"rebornix.ruby",
|
|
41
|
+
"github.vscode-github-actions",
|
|
42
|
+
"github.vscode-pull-request-github"
|
|
43
|
+
],
|
|
44
|
+
"settings": {
|
|
45
|
+
"editor.formatOnSave": true,
|
|
46
|
+
"files.eol": "\n"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
"remoteUser": "vscode",
|
|
52
|
+
|
|
53
|
+
// Forward dxkit's HTTP analyzer dashboard if you run it locally.
|
|
54
|
+
"forwardPorts": []
|
|
55
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Install the AI coding-agent CLIs that pair with dxkit's commit-time
|
|
4
|
+
# guardrails. Pinned versions so devcontainer rebuilds produce a
|
|
5
|
+
# deterministic environment; bump these intentionally.
|
|
6
|
+
#
|
|
7
|
+
# Both CLIs are published to npm and install globally into the
|
|
8
|
+
# devcontainer image's Node toolchain (provided by the features
|
|
9
|
+
# block in devcontainer.json).
|
|
10
|
+
|
|
11
|
+
set -euo pipefail
|
|
12
|
+
|
|
13
|
+
# Pinned at devcontainer template publish time. Loosen to `@latest`
|
|
14
|
+
# if you want each container start to pull the newest CLI — at the
|
|
15
|
+
# cost of non-deterministic builds. Set to `skip` to skip the install
|
|
16
|
+
# entirely (useful if you only use one of the two agents).
|
|
17
|
+
CLAUDE_CODE_VERSION="${CLAUDE_CODE_VERSION:-latest}"
|
|
18
|
+
CODEX_VERSION="${CODEX_VERSION:-latest}"
|
|
19
|
+
|
|
20
|
+
if [ "${CLAUDE_CODE_VERSION}" = "skip" ]; then
|
|
21
|
+
echo "==> Claude Code CLI install skipped (CLAUDE_CODE_VERSION=skip)."
|
|
22
|
+
else
|
|
23
|
+
echo "==> Installing Claude Code CLI..."
|
|
24
|
+
if command -v claude >/dev/null 2>&1; then
|
|
25
|
+
echo " Already installed: $(claude --version 2>&1 | head -n1)"
|
|
26
|
+
else
|
|
27
|
+
npm install -g "@anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}" \
|
|
28
|
+
|| echo "WARN: Claude Code install failed — try manually with 'npm install -g @anthropic-ai/claude-code'." >&2
|
|
29
|
+
fi
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
if [ "${CODEX_VERSION}" = "skip" ]; then
|
|
33
|
+
echo "==> OpenAI Codex CLI install skipped (CODEX_VERSION=skip)."
|
|
34
|
+
else
|
|
35
|
+
echo "==> Installing OpenAI Codex CLI..."
|
|
36
|
+
if command -v codex >/dev/null 2>&1; then
|
|
37
|
+
echo " Already installed: $(codex --version 2>&1 | head -n1)"
|
|
38
|
+
else
|
|
39
|
+
npm install -g "@openai/codex@${CODEX_VERSION}" \
|
|
40
|
+
|| echo "WARN: Codex CLI install failed — try manually with 'npm install -g @openai/codex'." >&2
|
|
41
|
+
fi
|
|
42
|
+
fi
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Devcontainer post-create. Runs once after the container is built
|
|
4
|
+
# (and again on Codespaces prebuild). Idempotent — safe to re-run.
|
|
5
|
+
#
|
|
6
|
+
# Responsibilities:
|
|
7
|
+
# 1. Install project dependencies if this is a Node project.
|
|
8
|
+
# 2. Ensure dxkit is on PATH (project-local first, global fallback).
|
|
9
|
+
# 3. Install dxkit's scanner toolchain (gitleaks, semgrep, cloc, etc.)
|
|
10
|
+
# via the TOOL_DEFS registry — pinned versions, language-aware.
|
|
11
|
+
# 4. Install the AI coding-agent CLIs for the AI-native dev loop.
|
|
12
|
+
#
|
|
13
|
+
# Run from the repo root — the devcontainer's workspaceFolder is set
|
|
14
|
+
# by `devcontainer.json` so the post-create command starts there.
|
|
15
|
+
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
|
|
18
|
+
echo "==> dxkit post-create starting in $(pwd)"
|
|
19
|
+
|
|
20
|
+
# Install project dependencies if this is a Node project. Soft-fail
|
|
21
|
+
# the whole step: a lockfile that won't resolve (tarball moved,
|
|
22
|
+
# private-registry auth not configured yet, peer-dep churn) is
|
|
23
|
+
# annoying but shouldn't take down the rest of the post-create. The
|
|
24
|
+
# user can re-run `npm install` after authenticating or fixing the
|
|
25
|
+
# lockfile.
|
|
26
|
+
#
|
|
27
|
+
# The fallback chain layers three install strategies before giving up:
|
|
28
|
+
#
|
|
29
|
+
# 1. `npm ci` (lockfile path only) — strict, fast, uses the lockfile
|
|
30
|
+
# verbatim. Happy path on a healthy tree.
|
|
31
|
+
# 2. `npm install` — looser; rebuilds lockfile entries if the
|
|
32
|
+
# lockfile drifted (lockfile vs package.json mismatch after a
|
|
33
|
+
# merge, for example).
|
|
34
|
+
# 3. `npm install --legacy-peer-deps` — last resort. npm v7+ defaults
|
|
35
|
+
# to strict peer-dep resolution; brownfield monorepos almost
|
|
36
|
+
# always carry unresolved peers (eslint 8↔10, react cross-pkg
|
|
37
|
+
# peer mismatches, etc.) which fail both prior steps with
|
|
38
|
+
# multi-line ERESOLVE dumps. Legacy mode skips the peer-dep
|
|
39
|
+
# check and gets a working node_modules/.
|
|
40
|
+
if [ -f package.json ]; then
|
|
41
|
+
echo "==> Installing project dependencies..."
|
|
42
|
+
if [ -f package-lock.json ]; then
|
|
43
|
+
npm ci || npm install || npm install --legacy-peer-deps || {
|
|
44
|
+
echo "WARN: project dependency install failed even with --legacy-peer-deps — re-run 'npm install --legacy-peer-deps' manually after fixing the cause." >&2
|
|
45
|
+
}
|
|
46
|
+
else
|
|
47
|
+
npm install || npm install --legacy-peer-deps || {
|
|
48
|
+
echo "WARN: project dependency install failed even with --legacy-peer-deps — re-run 'npm install --legacy-peer-deps' manually after fixing the cause." >&2
|
|
49
|
+
}
|
|
50
|
+
fi
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# Resolve dxkit. Prefer the project-local install if a `package.json`
|
|
54
|
+
# pinned dxkit in devDependencies; otherwise install globally so the
|
|
55
|
+
# binary is on PATH for the rest of the script and any subshell.
|
|
56
|
+
if [ -x ./node_modules/.bin/vyuh-dxkit ]; then
|
|
57
|
+
DXKIT="./node_modules/.bin/vyuh-dxkit"
|
|
58
|
+
elif command -v vyuh-dxkit >/dev/null 2>&1; then
|
|
59
|
+
DXKIT="vyuh-dxkit"
|
|
60
|
+
else
|
|
61
|
+
echo "==> Installing @vyuhlabs/dxkit globally..."
|
|
62
|
+
npm install -g @vyuhlabs/dxkit
|
|
63
|
+
DXKIT="vyuh-dxkit"
|
|
64
|
+
fi
|
|
65
|
+
echo "==> Using dxkit binary: ${DXKIT}"
|
|
66
|
+
|
|
67
|
+
echo "==> Installing scanner toolchain via dxkit registry..."
|
|
68
|
+
# `tools install --yes` reads the detector's required-tools list and
|
|
69
|
+
# runs the pinned install command for each one. Tools already present
|
|
70
|
+
# are no-ops, so this is fast on warm containers. Soft-fail so a
|
|
71
|
+
# single tool's install hiccup doesn't break the whole container.
|
|
72
|
+
"${DXKIT}" tools install --yes || {
|
|
73
|
+
echo "WARN: some scanner tools failed to install — run 'vyuh-dxkit tools list' to see status." >&2
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
echo "==> Installing AI coding-agent CLIs..."
|
|
77
|
+
bash "$(dirname "$0")/install-agent-clis.sh" || {
|
|
78
|
+
echo "WARN: agent CLI install had issues — install manually if needed." >&2
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
echo "==> dxkit post-create done. Run 'vyuh-dxkit health' to verify."
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
#
|
|
3
|
+
# dxkit pre-commit hook — fast guardrail check against the baseline.
|
|
4
|
+
#
|
|
5
|
+
# Runs `vyuh-dxkit guardrail check --changed-only` so only findings
|
|
6
|
+
# overlapping lines you just changed can block the commit. The full
|
|
7
|
+
# guardrail (without --changed-only) runs in the pre-push hook and
|
|
8
|
+
# in the CI PR-gate workflow; this one prioritises feedback speed.
|
|
9
|
+
#
|
|
10
|
+
# Install:
|
|
11
|
+
# git config core.hooksPath .githooks
|
|
12
|
+
#
|
|
13
|
+
# Escape hatches:
|
|
14
|
+
# DXKIT_SKIP_HOOKS=1 git commit ... # one-off bypass
|
|
15
|
+
# git commit --no-verify ... # standard git bypass
|
|
16
|
+
#
|
|
17
|
+
# First-time setup: this hook does NOT block when no baseline exists
|
|
18
|
+
# yet. Run `vyuh-dxkit baseline create` once to capture today's state,
|
|
19
|
+
# then commits start being gated against it.
|
|
20
|
+
|
|
21
|
+
set -e
|
|
22
|
+
|
|
23
|
+
if [ "${DXKIT_SKIP_HOOKS:-0}" = "1" ]; then
|
|
24
|
+
echo "[dxkit pre-commit] DXKIT_SKIP_HOOKS=1 set — skipping guardrail check."
|
|
25
|
+
exit 0
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
# Resolve the dxkit binary: prefer the project-local install, fall
|
|
29
|
+
# back to a global one. We deliberately do NOT shell out to `npx`
|
|
30
|
+
# here — npx may try to fetch from the registry, which makes the
|
|
31
|
+
# hook fail offline and slow down every commit.
|
|
32
|
+
if [ -x "./node_modules/.bin/vyuh-dxkit" ]; then
|
|
33
|
+
DXKIT="./node_modules/.bin/vyuh-dxkit"
|
|
34
|
+
elif command -v vyuh-dxkit >/dev/null 2>&1; then
|
|
35
|
+
DXKIT="vyuh-dxkit"
|
|
36
|
+
else
|
|
37
|
+
echo "[dxkit pre-commit] vyuh-dxkit not found on PATH or in ./node_modules/.bin." >&2
|
|
38
|
+
echo " Install it with: npm install --save-dev @vyuhlabs/dxkit" >&2
|
|
39
|
+
echo " Or skip this hook for this commit: DXKIT_SKIP_HOOKS=1 git commit ..." >&2
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
BASELINE_NAME="${DXKIT_BASELINE_NAME:-main}"
|
|
44
|
+
BASELINE_FILE=".dxkit/baselines/${BASELINE_NAME}.json"
|
|
45
|
+
|
|
46
|
+
if [ ! -f "${BASELINE_FILE}" ]; then
|
|
47
|
+
echo "[dxkit pre-commit] No baseline at ${BASELINE_FILE} — not blocking."
|
|
48
|
+
echo " Run \`${DXKIT} baseline create\` once to start gating commits."
|
|
49
|
+
exit 0
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# `--changed-only` restricts blocking to findings whose anchor line
|
|
53
|
+
# overlaps the diff between the baseline's anchor commit and HEAD.
|
|
54
|
+
# Pre-commit is fast-mode by design; the pre-push hook runs full.
|
|
55
|
+
"${DXKIT}" guardrail check --changed-only --name "${BASELINE_NAME}"
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
#
|
|
3
|
+
# dxkit pre-push hook — full guardrail check against the baseline.
|
|
4
|
+
#
|
|
5
|
+
# Runs the full `vyuh-dxkit guardrail check` (no --changed-only),
|
|
6
|
+
# so every regression introduced since the baseline blocks the push.
|
|
7
|
+
# Slower than pre-commit, but the push boundary is the last point
|
|
8
|
+
# we can stop bad code from leaving the developer's machine.
|
|
9
|
+
#
|
|
10
|
+
# Install:
|
|
11
|
+
# git config core.hooksPath .githooks
|
|
12
|
+
#
|
|
13
|
+
# Escape hatches:
|
|
14
|
+
# DXKIT_SKIP_HOOKS=1 git push ... # one-off bypass
|
|
15
|
+
# git push --no-verify ... # standard git bypass
|
|
16
|
+
|
|
17
|
+
set -e
|
|
18
|
+
|
|
19
|
+
if [ "${DXKIT_SKIP_HOOKS:-0}" = "1" ]; then
|
|
20
|
+
echo "[dxkit pre-push] DXKIT_SKIP_HOOKS=1 set — skipping guardrail check."
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Delete-only pushes (e.g. `git push origin --delete <branch>`) carry
|
|
25
|
+
# no commits to gate. Git invokes pre-push with stdin lines of the
|
|
26
|
+
# form: <local-ref> <local-sha> <remote-ref> <remote-sha>. A delete
|
|
27
|
+
# has local-sha = 40 zeros. Skip rather than failing the gate on an
|
|
28
|
+
# empty diff.
|
|
29
|
+
all_zero=true
|
|
30
|
+
while read -r _local_ref local_sha _remote_ref _remote_sha; do
|
|
31
|
+
if [ "${local_sha}" != "0000000000000000000000000000000000000000" ]; then
|
|
32
|
+
all_zero=false
|
|
33
|
+
break
|
|
34
|
+
fi
|
|
35
|
+
done
|
|
36
|
+
if [ "${all_zero}" = "true" ]; then
|
|
37
|
+
echo "[dxkit pre-push] Delete-only push detected — skipping guardrail check."
|
|
38
|
+
exit 0
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Resolve the dxkit binary: prefer the project-local install, fall
|
|
42
|
+
# back to a global one. Match the pre-commit hook's resolution order.
|
|
43
|
+
if [ -x "./node_modules/.bin/vyuh-dxkit" ]; then
|
|
44
|
+
DXKIT="./node_modules/.bin/vyuh-dxkit"
|
|
45
|
+
elif command -v vyuh-dxkit >/dev/null 2>&1; then
|
|
46
|
+
DXKIT="vyuh-dxkit"
|
|
47
|
+
else
|
|
48
|
+
echo "[dxkit pre-push] vyuh-dxkit not found on PATH or in ./node_modules/.bin." >&2
|
|
49
|
+
echo " Install it with: npm install --save-dev @vyuhlabs/dxkit" >&2
|
|
50
|
+
echo " Or skip this hook for this push: DXKIT_SKIP_HOOKS=1 git push ..." >&2
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
BASELINE_NAME="${DXKIT_BASELINE_NAME:-main}"
|
|
55
|
+
BASELINE_FILE=".dxkit/baselines/${BASELINE_NAME}.json"
|
|
56
|
+
|
|
57
|
+
if [ ! -f "${BASELINE_FILE}" ]; then
|
|
58
|
+
echo "[dxkit pre-push] No baseline at ${BASELINE_FILE} — not blocking."
|
|
59
|
+
echo " Run \`${DXKIT} baseline create\` once to start gating pushes."
|
|
60
|
+
exit 0
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
"${DXKIT}" guardrail check --name "${BASELINE_NAME}"
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
name: dxkit baseline refresh
|
|
2
|
+
|
|
3
|
+
# After every merge to main, regenerate `.dxkit/baselines/main.json`
|
|
4
|
+
# to capture the new "approved" state of the repo. The next PR's
|
|
5
|
+
# guardrail check is gated against this refreshed anchor, so a
|
|
6
|
+
# regression introduced in PR N+1 stands out from the noise of
|
|
7
|
+
# whatever was merged in PR N.
|
|
8
|
+
#
|
|
9
|
+
# The auto-commit carries `[skip ci]` so it doesn't re-trigger this
|
|
10
|
+
# workflow or the guardrails PR-gate.
|
|
11
|
+
|
|
12
|
+
on:
|
|
13
|
+
push:
|
|
14
|
+
branches: [__DXKIT_DEFAULT_BRANCH__]
|
|
15
|
+
# Ignore pushes that only changed the baseline file — those are
|
|
16
|
+
# this workflow's own commits, and re-running would be a no-op
|
|
17
|
+
# anyway. Belt-and-braces with [skip ci] below.
|
|
18
|
+
paths-ignore:
|
|
19
|
+
- '.dxkit/baselines/**'
|
|
20
|
+
|
|
21
|
+
permissions:
|
|
22
|
+
contents: write
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
refresh:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
# Don't re-run on our own auto-commit (defensive — paths-ignore
|
|
28
|
+
# above already filters the common case).
|
|
29
|
+
if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }}
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@v6
|
|
32
|
+
with:
|
|
33
|
+
fetch-depth: 0
|
|
34
|
+
# `persist-credentials: true` (the default) leaves the
|
|
35
|
+
# token in .git/config so the final `git push` reuses it.
|
|
36
|
+
|
|
37
|
+
- uses: actions/setup-node@v6
|
|
38
|
+
with:
|
|
39
|
+
node-version: '22'
|
|
40
|
+
|
|
41
|
+
- name: Install dxkit
|
|
42
|
+
run: |
|
|
43
|
+
if [ -f package-lock.json ]; then
|
|
44
|
+
npm ci
|
|
45
|
+
elif [ -f package.json ]; then
|
|
46
|
+
npm install
|
|
47
|
+
else
|
|
48
|
+
npm install -g @vyuhlabs/dxkit
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
- name: Install scanner tools
|
|
52
|
+
run: |
|
|
53
|
+
if [ -x ./node_modules/.bin/vyuh-dxkit ]; then
|
|
54
|
+
./node_modules/.bin/vyuh-dxkit tools install --yes
|
|
55
|
+
else
|
|
56
|
+
vyuh-dxkit tools install --yes
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
- name: Recompute baseline
|
|
60
|
+
run: |
|
|
61
|
+
if [ -x ./node_modules/.bin/vyuh-dxkit ]; then
|
|
62
|
+
DXKIT=./node_modules/.bin/vyuh-dxkit
|
|
63
|
+
else
|
|
64
|
+
DXKIT=vyuh-dxkit
|
|
65
|
+
fi
|
|
66
|
+
"${DXKIT}" baseline create --force
|
|
67
|
+
|
|
68
|
+
- name: Commit and push refreshed baseline
|
|
69
|
+
run: |
|
|
70
|
+
git config user.name "github-actions[bot]"
|
|
71
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
72
|
+
if git diff --quiet -- .dxkit/baselines/; then
|
|
73
|
+
echo "Baseline unchanged — nothing to commit."
|
|
74
|
+
exit 0
|
|
75
|
+
fi
|
|
76
|
+
git add .dxkit/baselines/
|
|
77
|
+
git commit -m "chore(baseline): refresh main anchor [skip ci]"
|
|
78
|
+
git push
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
name: dxkit guardrails
|
|
2
|
+
|
|
3
|
+
# Runs the dxkit guardrail check on every pull request. New regressions
|
|
4
|
+
# vs. the committed `.dxkit/baselines/main.json` block the PR. Existing
|
|
5
|
+
# findings (your "brownfield debt") are allowed — they were already
|
|
6
|
+
# captured when you ran `vyuh-dxkit baseline create`.
|
|
7
|
+
#
|
|
8
|
+
# Customise by editing your project's `.dxkit/policy.json` (created by
|
|
9
|
+
# `vyuh-dxkit init --with-ci`). The matcher's classifications
|
|
10
|
+
# (added / relocated / tooling_drift / config_drift / persisted /
|
|
11
|
+
# removed / fixed) map to block/warn buckets there.
|
|
12
|
+
|
|
13
|
+
on:
|
|
14
|
+
pull_request:
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
pull-requests: write
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
guardrail:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v6
|
|
25
|
+
with:
|
|
26
|
+
# Full history so the git-aware matcher can resolve the
|
|
27
|
+
# baseline's anchor commit + diff against HEAD.
|
|
28
|
+
fetch-depth: 0
|
|
29
|
+
|
|
30
|
+
- uses: actions/setup-node@v6
|
|
31
|
+
with:
|
|
32
|
+
node-version: '22'
|
|
33
|
+
|
|
34
|
+
# Install dxkit. Prefers a project-local install (devDependencies)
|
|
35
|
+
# so the version is pinned alongside the project. Falls back to a
|
|
36
|
+
# global install for non-JS projects.
|
|
37
|
+
- name: Install dxkit
|
|
38
|
+
run: |
|
|
39
|
+
if [ -f package-lock.json ]; then
|
|
40
|
+
npm ci
|
|
41
|
+
elif [ -f package.json ]; then
|
|
42
|
+
npm install
|
|
43
|
+
else
|
|
44
|
+
npm install -g @vyuhlabs/dxkit
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# Install the scanner toolchain dxkit needs for this stack
|
|
48
|
+
# (gitleaks, semgrep, cloc, jscpd, ruff, osv-scanner, etc.).
|
|
49
|
+
# `--yes` makes the install non-interactive; the registry
|
|
50
|
+
# decides what to install based on detected languages.
|
|
51
|
+
- name: Install scanner tools
|
|
52
|
+
run: |
|
|
53
|
+
if [ -x ./node_modules/.bin/vyuh-dxkit ]; then
|
|
54
|
+
./node_modules/.bin/vyuh-dxkit tools install --yes
|
|
55
|
+
else
|
|
56
|
+
vyuh-dxkit tools install --yes
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
# Capture the markdown report regardless of exit code so we can
|
|
60
|
+
# post it as a PR comment even when the guardrail blocks.
|
|
61
|
+
- name: Run guardrail check
|
|
62
|
+
id: guardrail
|
|
63
|
+
run: |
|
|
64
|
+
if [ -x ./node_modules/.bin/vyuh-dxkit ]; then
|
|
65
|
+
DXKIT=./node_modules/.bin/vyuh-dxkit
|
|
66
|
+
else
|
|
67
|
+
DXKIT=vyuh-dxkit
|
|
68
|
+
fi
|
|
69
|
+
set +e
|
|
70
|
+
"${DXKIT}" guardrail check --markdown > guardrail-report.md
|
|
71
|
+
echo "exit_code=$?" >> "$GITHUB_OUTPUT"
|
|
72
|
+
|
|
73
|
+
- name: Post PR comment
|
|
74
|
+
if: always()
|
|
75
|
+
env:
|
|
76
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
77
|
+
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
78
|
+
run: |
|
|
79
|
+
# Find a previous dxkit-guardrails comment by marker so we
|
|
80
|
+
# update in place rather than appending a new one per push.
|
|
81
|
+
MARKER='<!-- dxkit-guardrails -->'
|
|
82
|
+
{
|
|
83
|
+
printf '%s\n' "$MARKER"
|
|
84
|
+
cat guardrail-report.md
|
|
85
|
+
} > comment.md
|
|
86
|
+
existing=$(gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \
|
|
87
|
+
--jq ".[] | select(.body | startswith(\"${MARKER}\")) | .id" \
|
|
88
|
+
| head -n1)
|
|
89
|
+
if [ -n "${existing}" ]; then
|
|
90
|
+
gh api -X PATCH \
|
|
91
|
+
"repos/${{ github.repository }}/issues/comments/${existing}" \
|
|
92
|
+
-F body=@comment.md
|
|
93
|
+
else
|
|
94
|
+
gh pr comment "${PR_NUMBER}" --body-file comment.md
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
- name: Fail if guardrail blocked
|
|
98
|
+
run: exit ${{ steps.guardrail.outputs.exit_code }}
|