@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,530 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.detectDefaultBranch = detectDefaultBranch;
|
|
37
|
+
exports.installHooks = installHooks;
|
|
38
|
+
exports.installDevcontainer = installDevcontainer;
|
|
39
|
+
exports.installCiGuardrails = installCiGuardrails;
|
|
40
|
+
exports.installCiBaselineRefresh = installCiBaselineRefresh;
|
|
41
|
+
exports.installPrReview = installPrReview;
|
|
42
|
+
exports.installIgnoreFiles = installIgnoreFiles;
|
|
43
|
+
exports.installHooksPostinstall = installHooksPostinstall;
|
|
44
|
+
/**
|
|
45
|
+
* Phase Ship installers — additive copy of dxkit's guardrail templates
|
|
46
|
+
* into a consumer repo. Wired into `vyuh-dxkit init` via the
|
|
47
|
+
* `--with-hooks` / `--with-devcontainer` / `--with-ci` /
|
|
48
|
+
* `--with-baseline-refresh` flags (or `--full` which implies all).
|
|
49
|
+
*
|
|
50
|
+
* Each installer is additive by default: existing consumer files are
|
|
51
|
+
* never overwritten. When a conflict is detected, the installer
|
|
52
|
+
* writes a sidecar (`.dxkit`-suffixed) reference file and emits a
|
|
53
|
+
* note with merge instructions. `force: true` bypasses the sidecar
|
|
54
|
+
* fallback and overwrites in place.
|
|
55
|
+
*/
|
|
56
|
+
const fs = __importStar(require("fs"));
|
|
57
|
+
const path = __importStar(require("path"));
|
|
58
|
+
const child_process_1 = require("child_process");
|
|
59
|
+
const files_1 = require("./files");
|
|
60
|
+
const detect_1 = require("./detect");
|
|
61
|
+
const languages_1 = require("./languages");
|
|
62
|
+
/**
|
|
63
|
+
* Detect the consumer repo's default branch so workflow templates
|
|
64
|
+
* that fire on pushes to "the main branch" point at the right name.
|
|
65
|
+
* The resolution order is intentionally lenient — we'd rather
|
|
66
|
+
* substitute *some* sensible branch and let the consumer edit the
|
|
67
|
+
* workflow than refuse to install when git state is incomplete.
|
|
68
|
+
*
|
|
69
|
+
* 1. `git symbolic-ref refs/remotes/origin/HEAD` (set whenever the
|
|
70
|
+
* repo was cloned from a remote with a default-branch HEAD)
|
|
71
|
+
* 2. `git rev-parse --verify <name>` against `main` / `master` /
|
|
72
|
+
* `trunk` / `develop` — the four conventions that cover ~all
|
|
73
|
+
* real repos
|
|
74
|
+
* 3. The current branch (`git branch --show-current`) — the best
|
|
75
|
+
* guess in a freshly-`git init`'d repo that hasn't been pushed
|
|
76
|
+
* 4. Fallback to `'main'` — the GitHub default-branch default
|
|
77
|
+
*/
|
|
78
|
+
function detectDefaultBranch(cwd) {
|
|
79
|
+
try {
|
|
80
|
+
const ref = (0, child_process_1.execFileSync)('git', ['symbolic-ref', 'refs/remotes/origin/HEAD'], {
|
|
81
|
+
cwd,
|
|
82
|
+
encoding: 'utf8',
|
|
83
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
84
|
+
}).trim();
|
|
85
|
+
const match = ref.match(/^refs\/remotes\/origin\/(.+)$/);
|
|
86
|
+
if (match && match[1])
|
|
87
|
+
return match[1];
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
/* fall through */
|
|
91
|
+
}
|
|
92
|
+
for (const candidate of ['main', 'master', 'trunk', 'develop']) {
|
|
93
|
+
try {
|
|
94
|
+
(0, child_process_1.execFileSync)('git', ['rev-parse', '--verify', '--quiet', candidate], {
|
|
95
|
+
cwd,
|
|
96
|
+
stdio: 'ignore',
|
|
97
|
+
});
|
|
98
|
+
return candidate;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
/* try next */
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
const current = (0, child_process_1.execFileSync)('git', ['branch', '--show-current'], {
|
|
106
|
+
cwd,
|
|
107
|
+
encoding: 'utf8',
|
|
108
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
109
|
+
}).trim();
|
|
110
|
+
if (current)
|
|
111
|
+
return current;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
/* fall through */
|
|
115
|
+
}
|
|
116
|
+
return 'main';
|
|
117
|
+
}
|
|
118
|
+
function emptyResult() {
|
|
119
|
+
return { installed: [], skipped: [], sidecars: [], notes: [] };
|
|
120
|
+
}
|
|
121
|
+
function templatesDir() {
|
|
122
|
+
return path.join(__dirname, '..', 'templates');
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Copy a single source file to a destination, handling the
|
|
126
|
+
* additive-vs-force decision. Returns the (relative) path that was
|
|
127
|
+
* written + which bucket it lands in.
|
|
128
|
+
*/
|
|
129
|
+
function copyAdditive(srcAbs, destAbs, cwd, opts, result, options = {}) {
|
|
130
|
+
const relDest = path.relative(cwd, destAbs);
|
|
131
|
+
const exists = fs.existsSync(destAbs);
|
|
132
|
+
if (exists && !opts.force) {
|
|
133
|
+
const suffix = options.sidecarSuffix ?? '.dxkit';
|
|
134
|
+
const sidecarAbs = destAbs + suffix;
|
|
135
|
+
const relSidecar = path.relative(cwd, sidecarAbs);
|
|
136
|
+
fs.mkdirSync(path.dirname(sidecarAbs), { recursive: true });
|
|
137
|
+
fs.copyFileSync(srcAbs, sidecarAbs);
|
|
138
|
+
if (options.executable)
|
|
139
|
+
(0, files_1.makeExecutable)(sidecarAbs);
|
|
140
|
+
result.sidecars.push(relSidecar);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
fs.mkdirSync(path.dirname(destAbs), { recursive: true });
|
|
144
|
+
fs.copyFileSync(srcAbs, destAbs);
|
|
145
|
+
if (options.executable)
|
|
146
|
+
(0, files_1.makeExecutable)(destAbs);
|
|
147
|
+
if (exists) {
|
|
148
|
+
result.installed.push(relDest);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
result.installed.push(relDest);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Hooks installer. Writes `.githooks/pre-push` by default;
|
|
156
|
+
* additionally writes `.githooks/pre-commit` when
|
|
157
|
+
* `opts.withPrecommit === true`. When the consumer already has a
|
|
158
|
+
* matching hook (via .githooks/ or .husky/), emits a `.dxkit`
|
|
159
|
+
* sidecar instead and prints merge instructions.
|
|
160
|
+
*
|
|
161
|
+
* Customer still needs to run `git config core.hooksPath .githooks`
|
|
162
|
+
* to activate. We don't run it for them — that's a global git config
|
|
163
|
+
* mutation outside dxkit's purview.
|
|
164
|
+
*
|
|
165
|
+
* Why pre-commit is opt-in: see `InstallerOpts.withPrecommit`.
|
|
166
|
+
*/
|
|
167
|
+
function installHooks(cwd, opts = {}) {
|
|
168
|
+
const result = emptyResult();
|
|
169
|
+
const tmplDir = path.join(templatesDir(), '.githooks');
|
|
170
|
+
const destDir = path.join(cwd, '.githooks');
|
|
171
|
+
// Husky users have hooks at `.husky/<name>`. We treat either an
|
|
172
|
+
// existing `.githooks/<name>` *or* `.husky/<name>` as a conflict —
|
|
173
|
+
// both routes mean the consumer already has an active hook, even
|
|
174
|
+
// though only the .githooks/ path is the destination we write to.
|
|
175
|
+
//
|
|
176
|
+
// pre-commit is opt-in (slow on large repos until incremental
|
|
177
|
+
// scanning lands); pre-push always installs (acceptable cost).
|
|
178
|
+
const hookNames = opts.withPrecommit
|
|
179
|
+
? [{ name: 'pre-commit' }, { name: 'pre-push' }]
|
|
180
|
+
: [{ name: 'pre-push' }];
|
|
181
|
+
let anyConflict = false;
|
|
182
|
+
for (const { name } of hookNames) {
|
|
183
|
+
const destAbs = path.join(destDir, name);
|
|
184
|
+
const huskyAbs = path.join(cwd, '.husky', name);
|
|
185
|
+
const conflict = fs.existsSync(destAbs) || fs.existsSync(huskyAbs);
|
|
186
|
+
if (conflict)
|
|
187
|
+
anyConflict = true;
|
|
188
|
+
const srcAbs = path.join(tmplDir, name);
|
|
189
|
+
if (conflict && !opts.force) {
|
|
190
|
+
// Always land the dxkit hook at .githooks/<name>.dxkit when
|
|
191
|
+
// there's a conflict, even when the conflict is at a different
|
|
192
|
+
// path (husky). The sidecar is the same regardless of where the
|
|
193
|
+
// existing hook lives, and the merge note tells the consumer
|
|
194
|
+
// how to chain them.
|
|
195
|
+
const sidecarAbs = destAbs + '.dxkit';
|
|
196
|
+
fs.mkdirSync(path.dirname(sidecarAbs), { recursive: true });
|
|
197
|
+
fs.copyFileSync(srcAbs, sidecarAbs);
|
|
198
|
+
(0, files_1.makeExecutable)(sidecarAbs);
|
|
199
|
+
result.sidecars.push(path.relative(cwd, sidecarAbs));
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
fs.mkdirSync(path.dirname(destAbs), { recursive: true });
|
|
203
|
+
fs.copyFileSync(srcAbs, destAbs);
|
|
204
|
+
(0, files_1.makeExecutable)(destAbs);
|
|
205
|
+
result.installed.push(path.relative(cwd, destAbs));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (anyConflict) {
|
|
209
|
+
result.notes.push('Detected an existing pre-commit/pre-push hook. The dxkit hooks were ' +
|
|
210
|
+
'written as `.dxkit` sidecars next to your existing hooks; add a ' +
|
|
211
|
+
'`sh .githooks/<name>.dxkit` line to each existing hook to chain them.');
|
|
212
|
+
}
|
|
213
|
+
result.notes.push('Activate the hooks: `git config core.hooksPath .githooks` (one-time, per clone).');
|
|
214
|
+
if (!opts.withPrecommit) {
|
|
215
|
+
result.notes.push('pre-commit hook NOT installed (default). The full guardrail re-runs every analyzer ' +
|
|
216
|
+
'and is slow on large repos. Pre-push catches the same regressions before code leaves ' +
|
|
217
|
+
'the machine. Re-run init with `--with-precommit-hook` to enable commit-time gating.');
|
|
218
|
+
}
|
|
219
|
+
return result;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Render the per-stack features block as a properly-indented JSON
|
|
223
|
+
* fragment slotted into the template's `"features": __PLACEHOLDER__`
|
|
224
|
+
* line. The first line stays flush; continuation lines get the
|
|
225
|
+
* template's two-space outer indent so the resulting object reads
|
|
226
|
+
* naturally inside the surrounding JSONC.
|
|
227
|
+
*/
|
|
228
|
+
function renderFeaturesBlock(features) {
|
|
229
|
+
const raw = JSON.stringify(features, null, 2);
|
|
230
|
+
return raw
|
|
231
|
+
.split('\n')
|
|
232
|
+
.map((line, i) => (i === 0 ? line : ' ' + line))
|
|
233
|
+
.join('\n');
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Read the devcontainer.json template, substitute the
|
|
237
|
+
* `__DXKIT_DEVCONTAINER_FEATURES__` placeholder with the detected
|
|
238
|
+
* stack's features block, and return the rendered text. Pure-ish:
|
|
239
|
+
* one filesystem read, no writes.
|
|
240
|
+
*/
|
|
241
|
+
function renderDevcontainerJson(tmplDir, cwd) {
|
|
242
|
+
const srcAbs = path.join(tmplDir, 'devcontainer.json');
|
|
243
|
+
const template = fs.readFileSync(srcAbs, 'utf8');
|
|
244
|
+
const stack = (0, detect_1.detect)(cwd);
|
|
245
|
+
const features = (0, languages_1.buildDevcontainerFeatures)(stack.languages);
|
|
246
|
+
return template.replace('__DXKIT_DEVCONTAINER_FEATURES__', renderFeaturesBlock(features));
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Devcontainer installer. Writes the dxkit lightweight devcontainer
|
|
250
|
+
* (devcontainer.json + post-create.sh + install-agent-clis.sh) into
|
|
251
|
+
* `.devcontainer/`. If the consumer already has a devcontainer.json,
|
|
252
|
+
* writes the entire dxkit set into `.devcontainer/.dxkit-reference/`
|
|
253
|
+
* for manual merge.
|
|
254
|
+
*
|
|
255
|
+
* devcontainer.json is rendered per-detected-stack: only active
|
|
256
|
+
* packs' features land in the output. Always-on entries (Node +
|
|
257
|
+
* GitHub CLI) ship regardless so the post-create script can run on
|
|
258
|
+
* a non-Node project.
|
|
259
|
+
*/
|
|
260
|
+
function installDevcontainer(cwd, opts = {}) {
|
|
261
|
+
const result = emptyResult();
|
|
262
|
+
const tmplDir = path.join(templatesDir(), '.devcontainer');
|
|
263
|
+
const destDir = path.join(cwd, '.devcontainer');
|
|
264
|
+
const filesToCopyVerbatim = [
|
|
265
|
+
{ name: 'post-create.sh', executable: true },
|
|
266
|
+
{ name: 'install-agent-clis.sh', executable: true },
|
|
267
|
+
];
|
|
268
|
+
const hasExistingDevcontainer = fs.existsSync(path.join(destDir, 'devcontainer.json'));
|
|
269
|
+
if (hasExistingDevcontainer && !opts.force) {
|
|
270
|
+
// Stash the whole dxkit set under a reference dir so the
|
|
271
|
+
// consumer can read it without it interfering with their own.
|
|
272
|
+
// The reference devcontainer.json is rendered with the
|
|
273
|
+
// per-stack features so the customer sees the same shape as
|
|
274
|
+
// a fresh install — they can lift the features block directly.
|
|
275
|
+
const refDir = path.join(destDir, '.dxkit-reference');
|
|
276
|
+
fs.mkdirSync(refDir, { recursive: true });
|
|
277
|
+
const renderedJson = renderDevcontainerJson(tmplDir, cwd);
|
|
278
|
+
fs.writeFileSync(path.join(refDir, 'devcontainer.json'), renderedJson, 'utf8');
|
|
279
|
+
result.sidecars.push(path.relative(cwd, path.join(refDir, 'devcontainer.json')));
|
|
280
|
+
for (const f of filesToCopyVerbatim) {
|
|
281
|
+
const srcAbs = path.join(tmplDir, f.name);
|
|
282
|
+
const destAbs = path.join(refDir, f.name);
|
|
283
|
+
fs.copyFileSync(srcAbs, destAbs);
|
|
284
|
+
if (f.executable)
|
|
285
|
+
(0, files_1.makeExecutable)(destAbs);
|
|
286
|
+
result.sidecars.push(path.relative(cwd, destAbs));
|
|
287
|
+
}
|
|
288
|
+
result.notes.push('Existing devcontainer.json detected — dxkit pieces stashed in ' +
|
|
289
|
+
'`.devcontainer/.dxkit-reference/`. To enable dxkit guardrails in ' +
|
|
290
|
+
'your container: (1) merge the `features` block from the reference ' +
|
|
291
|
+
'devcontainer.json into yours, (2) add `bash .devcontainer/post-create.sh` ' +
|
|
292
|
+
'to your `postCreateCommand`, (3) copy `post-create.sh` and ' +
|
|
293
|
+
'`install-agent-clis.sh` into `.devcontainer/`.');
|
|
294
|
+
return result;
|
|
295
|
+
}
|
|
296
|
+
// devcontainer.json gets rendered (per-stack features substitution),
|
|
297
|
+
// the rest are flat copies.
|
|
298
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
299
|
+
const renderedJson = renderDevcontainerJson(tmplDir, cwd);
|
|
300
|
+
const destDevcontainerJson = path.join(destDir, 'devcontainer.json');
|
|
301
|
+
fs.writeFileSync(destDevcontainerJson, renderedJson, 'utf8');
|
|
302
|
+
result.installed.push(path.relative(cwd, destDevcontainerJson));
|
|
303
|
+
for (const f of filesToCopyVerbatim) {
|
|
304
|
+
copyAdditive(path.join(tmplDir, f.name), path.join(destDir, f.name), cwd, { force: true }, result, { executable: f.executable });
|
|
305
|
+
}
|
|
306
|
+
return result;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Generic workflow installer used by both --with-ci (PR-gate) and
|
|
310
|
+
* --with-baseline-refresh (post-merge auto-regen). Both targets are
|
|
311
|
+
* uniquely-named workflow files; conflict only happens on a re-run
|
|
312
|
+
* against an existing dxkit install, which we skip with a note.
|
|
313
|
+
*
|
|
314
|
+
* `substitutions` lets a workflow template carry placeholders the
|
|
315
|
+
* installer fills in at write time. The baseline-refresh workflow
|
|
316
|
+
* uses this for the consumer's default branch name; the PR-gate
|
|
317
|
+
* workflow ships verbatim.
|
|
318
|
+
*/
|
|
319
|
+
function installWorkflow(cwd, fileName, opts, substitutions = {}) {
|
|
320
|
+
const result = emptyResult();
|
|
321
|
+
const srcAbs = path.join(templatesDir(), '.github', 'workflows', fileName);
|
|
322
|
+
const destAbs = path.join(cwd, '.github', 'workflows', fileName);
|
|
323
|
+
if (fs.existsSync(destAbs) && !opts.force) {
|
|
324
|
+
result.skipped.push(path.relative(cwd, destAbs));
|
|
325
|
+
return result;
|
|
326
|
+
}
|
|
327
|
+
fs.mkdirSync(path.dirname(destAbs), { recursive: true });
|
|
328
|
+
if (Object.keys(substitutions).length === 0) {
|
|
329
|
+
fs.copyFileSync(srcAbs, destAbs);
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
let content = fs.readFileSync(srcAbs, 'utf8');
|
|
333
|
+
for (const [key, value] of Object.entries(substitutions)) {
|
|
334
|
+
content = content.split(key).join(value);
|
|
335
|
+
}
|
|
336
|
+
fs.writeFileSync(destAbs, content, 'utf8');
|
|
337
|
+
}
|
|
338
|
+
result.installed.push(path.relative(cwd, destAbs));
|
|
339
|
+
return result;
|
|
340
|
+
}
|
|
341
|
+
function installCiGuardrails(cwd, opts = {}) {
|
|
342
|
+
return installWorkflow(cwd, 'dxkit-guardrails.yml', opts);
|
|
343
|
+
}
|
|
344
|
+
function installCiBaselineRefresh(cwd, opts = {}) {
|
|
345
|
+
const defaultBranch = detectDefaultBranch(cwd);
|
|
346
|
+
const result = installWorkflow(cwd, 'dxkit-baseline-refresh.yml', opts, {
|
|
347
|
+
__DXKIT_DEFAULT_BRANCH__: defaultBranch,
|
|
348
|
+
});
|
|
349
|
+
if (result.installed.length > 0 && defaultBranch !== 'main') {
|
|
350
|
+
result.notes.push(`baseline-refresh workflow targets the '${defaultBranch}' branch (detected from your repo). ` +
|
|
351
|
+
`Edit the workflow's \`branches:\` trigger if you want a different one.`);
|
|
352
|
+
}
|
|
353
|
+
return result;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* AI PR-review workflow installer. Writes
|
|
357
|
+
* `.github/workflows/pr-review.yml` — a workflow that runs Claude
|
|
358
|
+
* Code over a PR's diff and posts a review comment.
|
|
359
|
+
*
|
|
360
|
+
* Opt-in (via `--with-pr-review`) because the workflow needs an
|
|
361
|
+
* `ANTHROPIC_API_KEY` repo secret AND a flipped `ENABLE_AI_REVIEW`
|
|
362
|
+
* repo variable to actually run anything; without both, the
|
|
363
|
+
* workflow file just sits inert in the repo and clutters the
|
|
364
|
+
* Actions tab. Customers who want this should opt in explicitly
|
|
365
|
+
* with the flag (and configure the repo secret + variable
|
|
366
|
+
* separately).
|
|
367
|
+
*/
|
|
368
|
+
function installPrReview(cwd, opts = {}) {
|
|
369
|
+
const result = installWorkflow(cwd, 'pr-review.yml', opts);
|
|
370
|
+
if (result.installed.length > 0) {
|
|
371
|
+
result.notes.push('pr-review.yml is dormant until you configure both: ' +
|
|
372
|
+
'(1) `ANTHROPIC_API_KEY` repo secret, and ' +
|
|
373
|
+
'(2) `ENABLE_AI_REVIEW=true` repo variable.');
|
|
374
|
+
}
|
|
375
|
+
return result;
|
|
376
|
+
}
|
|
377
|
+
const GITIGNORE_HEADER = '# dxkit — runtime outputs (analyzer reports + dashboard)';
|
|
378
|
+
const GITIGNORE_ENTRIES = [
|
|
379
|
+
'.dxkit/reports/',
|
|
380
|
+
'.dxkit/dashboard.html',
|
|
381
|
+
'.dxkit/cache/',
|
|
382
|
+
'graphify-out/',
|
|
383
|
+
];
|
|
384
|
+
/**
|
|
385
|
+
* Seed `.gitignore` with dxkit's runtime-output paths and write a
|
|
386
|
+
* starter `.dxkit-ignore` template explaining the optional dxkit-
|
|
387
|
+
* specific scan-exclusion file.
|
|
388
|
+
*
|
|
389
|
+
* Concerns the seeded files address:
|
|
390
|
+
* - `.gitignore`: stops customers from accidentally committing
|
|
391
|
+
* `.dxkit/reports/*.md` and `.dxkit/dashboard.html` (which
|
|
392
|
+
* churn on every analyzer run). Selectively keeps
|
|
393
|
+
* `.dxkit/baselines/` tracked — it IS the guardrail anchor.
|
|
394
|
+
* - `.dxkit-ignore`: dxkit's own scan-exclusion file. Loaded by
|
|
395
|
+
* `loadExclusions()` if present; never created by dxkit before
|
|
396
|
+
* this commit. Seeding a documented template makes the feature
|
|
397
|
+
* discoverable.
|
|
398
|
+
*
|
|
399
|
+
* Both are additive: existing `.gitignore` entries are preserved
|
|
400
|
+
* (dedup against current contents); existing `.dxkit-ignore` is
|
|
401
|
+
* never overwritten.
|
|
402
|
+
*/
|
|
403
|
+
function installIgnoreFiles(cwd, opts = {}) {
|
|
404
|
+
const result = emptyResult();
|
|
405
|
+
// .gitignore: append runtime-output entries
|
|
406
|
+
const gitignorePath = path.join(cwd, '.gitignore');
|
|
407
|
+
let existing = '';
|
|
408
|
+
if (fs.existsSync(gitignorePath)) {
|
|
409
|
+
existing = fs.readFileSync(gitignorePath, 'utf-8');
|
|
410
|
+
if (existing.includes(GITIGNORE_HEADER)) {
|
|
411
|
+
result.skipped.push('.gitignore');
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
const existingLines = new Set(existing.split('\n').map((l) => l.trim()));
|
|
415
|
+
const newEntries = GITIGNORE_ENTRIES.filter((e) => !existingLines.has(e));
|
|
416
|
+
if (newEntries.length > 0) {
|
|
417
|
+
const block = '\n' + GITIGNORE_HEADER + '\n' + newEntries.join('\n') + '\n';
|
|
418
|
+
fs.appendFileSync(gitignorePath, block, 'utf-8');
|
|
419
|
+
result.installed.push('.gitignore');
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
result.skipped.push('.gitignore');
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
const content = GITIGNORE_HEADER + '\n' + GITIGNORE_ENTRIES.join('\n') + '\n';
|
|
428
|
+
fs.writeFileSync(gitignorePath, content, 'utf-8');
|
|
429
|
+
result.installed.push('.gitignore');
|
|
430
|
+
}
|
|
431
|
+
// .dxkit-ignore: write starter template (never overwrite)
|
|
432
|
+
const dxkitIgnorePath = path.join(cwd, '.dxkit-ignore');
|
|
433
|
+
if (fs.existsSync(dxkitIgnorePath) && !opts.force) {
|
|
434
|
+
result.skipped.push('.dxkit-ignore');
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
fs.writeFileSync(dxkitIgnorePath, DXKIT_IGNORE_TEMPLATE, 'utf-8');
|
|
438
|
+
result.installed.push('.dxkit-ignore');
|
|
439
|
+
}
|
|
440
|
+
return result;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Wire `vyuh-dxkit hooks activate` into the consumer's `package.json`
|
|
444
|
+
* postinstall script so cloning + `npm install` auto-activates the
|
|
445
|
+
* dxkit hook directory. Closes the per-clone "run this one git config
|
|
446
|
+
* command" friction step that today's installHooks emits as a note.
|
|
447
|
+
*
|
|
448
|
+
* Conflict policy (mirrors the rest of the ship surface):
|
|
449
|
+
* - No package.json → skip cleanly (Python-only / Go-only / etc.
|
|
450
|
+
* repos use the existing manual-activation path).
|
|
451
|
+
* - scripts.postinstall absent → write ours.
|
|
452
|
+
* - scripts.postinstall already mentions `vyuh-dxkit hooks activate`
|
|
453
|
+
* → skip (idempotent re-runs).
|
|
454
|
+
* - scripts.postinstall is set to something else → leave it alone
|
|
455
|
+
* and emit a note asking the consumer to chain. Auto-chaining
|
|
456
|
+
* risks breaking their existing script's exit-code semantics.
|
|
457
|
+
*/
|
|
458
|
+
const POSTINSTALL_CMD = 'vyuh-dxkit hooks activate';
|
|
459
|
+
function installHooksPostinstall(cwd, _opts = {}) {
|
|
460
|
+
const result = emptyResult();
|
|
461
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
462
|
+
if (!fs.existsSync(pkgPath)) {
|
|
463
|
+
// Non-Node repos (Python-only, Go-only, .NET-only, etc.) — no
|
|
464
|
+
// postinstall surface to wire into. Fall back to the existing
|
|
465
|
+
// manual note emitted by `installHooks`.
|
|
466
|
+
return result;
|
|
467
|
+
}
|
|
468
|
+
let raw;
|
|
469
|
+
try {
|
|
470
|
+
raw = fs.readFileSync(pkgPath, 'utf-8');
|
|
471
|
+
}
|
|
472
|
+
catch {
|
|
473
|
+
return result;
|
|
474
|
+
}
|
|
475
|
+
let pkg;
|
|
476
|
+
try {
|
|
477
|
+
pkg = JSON.parse(raw);
|
|
478
|
+
}
|
|
479
|
+
catch {
|
|
480
|
+
// Malformed package.json — bail rather than risk corrupting it.
|
|
481
|
+
result.notes.push(`Skipped postinstall hooks-activation wire-up: ${path.relative(cwd, pkgPath)} is not valid JSON.`);
|
|
482
|
+
return result;
|
|
483
|
+
}
|
|
484
|
+
const existing = pkg.scripts?.postinstall;
|
|
485
|
+
if (existing && existing.includes(POSTINSTALL_CMD)) {
|
|
486
|
+
result.skipped.push('package.json (postinstall)');
|
|
487
|
+
return result;
|
|
488
|
+
}
|
|
489
|
+
if (existing && existing.trim().length > 0) {
|
|
490
|
+
// Don't auto-chain — too risky. Surface a clear note instead.
|
|
491
|
+
result.notes.push(`Existing package.json scripts.postinstall preserved. To auto-activate dxkit hooks on every clone, ` +
|
|
492
|
+
`chain by hand: \`"postinstall": "${existing} && ${POSTINSTALL_CMD}"\`.`);
|
|
493
|
+
return result;
|
|
494
|
+
}
|
|
495
|
+
pkg.scripts = { ...(pkg.scripts ?? {}), postinstall: POSTINSTALL_CMD };
|
|
496
|
+
// Preserve trailing newline if the original had one — many editors
|
|
497
|
+
// and linters expect it.
|
|
498
|
+
const trailingNewline = raw.endsWith('\n') ? '\n' : '';
|
|
499
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + trailingNewline, 'utf-8');
|
|
500
|
+
result.installed.push('package.json (postinstall)');
|
|
501
|
+
result.notes.push('Wired `vyuh-dxkit hooks activate` into package.json postinstall — every clone + `npm install` ' +
|
|
502
|
+
'will activate `core.hooksPath = .githooks` automatically. (Manual one-time activation no longer needed.)');
|
|
503
|
+
return result;
|
|
504
|
+
}
|
|
505
|
+
const DXKIT_IGNORE_TEMPLATE = `# .dxkit-ignore — extra paths dxkit's analyzers should skip.
|
|
506
|
+
#
|
|
507
|
+
# Format: same as .gitignore (directory/, file-glob, multi-segment).
|
|
508
|
+
# Union'd on top of:
|
|
509
|
+
# - dxkit's bundled defaults (node_modules/, dist/, .git/, build/, ...)
|
|
510
|
+
# - this repo's .gitignore
|
|
511
|
+
#
|
|
512
|
+
# Use this file for dxkit-specific exclusions that you don't want in
|
|
513
|
+
# .gitignore (e.g. vendored code you DO commit but DON'T want dxkit
|
|
514
|
+
# to analyze for quality / coverage / security findings).
|
|
515
|
+
#
|
|
516
|
+
# Common examples (uncomment + adjust to your project):
|
|
517
|
+
#
|
|
518
|
+
# vendor/ # vendored third-party code committed to git
|
|
519
|
+
# third_party/
|
|
520
|
+
# generated/ # generated code (protobuf, GraphQL types, ORM)
|
|
521
|
+
# *.generated.ts
|
|
522
|
+
# *.designer.cs
|
|
523
|
+
# legacy/ # pre-existing code you don't want to track findings against
|
|
524
|
+
# fixtures/large/ # test fixtures that inflate metrics
|
|
525
|
+
#
|
|
526
|
+
# After editing, the next \`vyuh-dxkit baseline create\` will pick up the
|
|
527
|
+
# changes. Note: changes to this file invalidate cached baselines
|
|
528
|
+
# (the file's content hash lands in the baseline envelope).
|
|
529
|
+
`;
|
|
530
|
+
//# sourceMappingURL=ship-installers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ship-installers.js","sourceRoot":"","sources":["../src/ship-installers.ts"],"names":[],"mappings":"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"}
|
package/dist/tools-cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools-cli.d.ts","sourceRoot":"","sources":["../src/tools-cli.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAWxC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,aAAa,CAAC,WAAW,CAAC,EACrC,OAAO,GAAE,mBAAwB,GAChC,MAAM,EAAE,CAQV;
|
|
1
|
+
{"version":3,"file":"tools-cli.d.ts","sourceRoot":"","sources":["../src/tools-cli.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAWxC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,aAAa,CAAC,WAAW,CAAC,EACrC,OAAO,GAAE,mBAAwB,GAChC,MAAM,EAAE,CAQV;AA8SD,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,IAAI,CAAC,CAYf"}
|
package/dist/tools-cli.js
CHANGED
|
@@ -98,20 +98,26 @@ function sortByLayer(statuses) {
|
|
|
98
98
|
});
|
|
99
99
|
}
|
|
100
100
|
function formatStatusLine(s) {
|
|
101
|
-
const icon = s.available ? '\x1b[32m✓\x1b[0m' : '\x1b[31m✗\x1b[0m';
|
|
102
101
|
const name = s.name.padEnd(16);
|
|
103
102
|
const layer = LAYER_LABEL[s.requirement.layer] || s.requirement.layer;
|
|
104
103
|
const forStack = s.requirement.for.padEnd(7);
|
|
105
104
|
if (s.available) {
|
|
106
105
|
const src = s.source === 'path' ? '' : ` (${s.source})`;
|
|
107
|
-
return `
|
|
106
|
+
return ` \x1b[32m✓\x1b[0m ${name} ${layer} ${forStack} ${logger.bold('found')}${src}`;
|
|
107
|
+
}
|
|
108
|
+
// N/A tools (applicability gate fired): show a distinct icon + the
|
|
109
|
+
// reason so users see "not for this stack" rather than "missing".
|
|
110
|
+
// These intentionally do NOT count toward the missing tally.
|
|
111
|
+
if (s.source === 'n/a') {
|
|
112
|
+
const reason = s.notApplicableReason ? ` \x1b[2m(${s.notApplicableReason})\x1b[0m` : '';
|
|
113
|
+
return ` \x1b[2m−\x1b[0m ${name} ${layer} ${forStack} \x1b[2mn/a${reason ? '' : ' for this stack'}\x1b[0m${reason}`;
|
|
108
114
|
}
|
|
109
115
|
// Project-local tools (F-UX-3): annotate so users don't confuse a
|
|
110
116
|
// missing dev-dep with a missing system tool.
|
|
111
117
|
const scopeNote = s.requirement.installScope === 'project-local'
|
|
112
118
|
? ' \x1b[2m(project-local — `npm ci`)\x1b[0m'
|
|
113
119
|
: '';
|
|
114
|
-
return `
|
|
120
|
+
return ` \x1b[31m✗\x1b[0m ${name} ${layer} ${forStack} \x1b[2mmissing\x1b[0m${scopeNote}`;
|
|
115
121
|
}
|
|
116
122
|
/** Show tool status for the repo's detected stack. */
|
|
117
123
|
function showStatus(targetPath) {
|
|
@@ -134,14 +140,27 @@ function showStatus(targetPath) {
|
|
|
134
140
|
logger.dim(` path: ${s.path}`);
|
|
135
141
|
}
|
|
136
142
|
}
|
|
137
|
-
|
|
143
|
+
// Split the unavailable set: truly missing (actionable) vs n/a
|
|
144
|
+
// (informational — the applicability gate excluded the tool from
|
|
145
|
+
// this stack). Missing-count math must not include n/a entries or
|
|
146
|
+
// customers see false "1/14 missing" alarms on repos that
|
|
147
|
+
// legitimately don't use the tool.
|
|
148
|
+
const missing = statuses.filter((s) => !s.available && s.source !== 'n/a');
|
|
149
|
+
const notApplicable = statuses.filter((s) => s.source === 'n/a');
|
|
138
150
|
const total = statuses.length;
|
|
151
|
+
const applicable = total - notApplicable.length;
|
|
139
152
|
console.log('');
|
|
140
153
|
if (missing.length === 0) {
|
|
141
|
-
|
|
154
|
+
if (notApplicable.length === 0) {
|
|
155
|
+
logger.success(`All ${total} required tools available.`);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
logger.success(`All ${applicable} applicable tools available (${notApplicable.length} n/a for this stack).`);
|
|
159
|
+
}
|
|
142
160
|
}
|
|
143
161
|
else {
|
|
144
|
-
|
|
162
|
+
const naSuffix = notApplicable.length > 0 ? `, ${notApplicable.length} n/a` : '';
|
|
163
|
+
logger.warn(`${missing.length}/${applicable} applicable tools missing${naSuffix}.`);
|
|
145
164
|
console.log('');
|
|
146
165
|
// F-UX-3: partition missing by install scope so the hint matches
|
|
147
166
|
// where each tool actually lives. Project-local tools (eslint,
|
|
@@ -212,13 +231,29 @@ async function runInstall(targetPath, autoYes, options = {}) {
|
|
|
212
231
|
statuses = showStatus(targetPath);
|
|
213
232
|
modeLabel = 'Install missing tools';
|
|
214
233
|
}
|
|
215
|
-
|
|
234
|
+
// Exclude n/a entries — applicability gate already determined the
|
|
235
|
+
// tool doesn't apply to this stack, so attempting an install would
|
|
236
|
+
// either no-op or pull in dead weight.
|
|
237
|
+
const missing = statuses.filter((s) => !s.available && s.source !== 'n/a');
|
|
238
|
+
const notApplicable = statuses.filter((s) => s.source === 'n/a');
|
|
239
|
+
// Targeted single-tool install hitting an n/a tool: surface the
|
|
240
|
+
// reason and exit cleanly rather than silently skipping. Users who
|
|
241
|
+
// explicitly typed the name deserve a direct answer.
|
|
242
|
+
if (options.toolName && notApplicable.length === 1 && missing.length === 0) {
|
|
243
|
+
const reason = notApplicable[0].notApplicableReason ?? 'not applicable to this stack';
|
|
244
|
+
logger.info(`${options.toolName} is not applicable here: ${reason}.`);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
216
247
|
if (missing.length === 0) {
|
|
217
248
|
if (options.toolName) {
|
|
218
249
|
logger.success(`${options.toolName} is already installed.`);
|
|
219
250
|
}
|
|
220
251
|
else if (options.all) {
|
|
221
|
-
|
|
252
|
+
const naSuffix = notApplicable.length > 0 ? ` (${notApplicable.length} n/a for this stack — skipped)` : '';
|
|
253
|
+
logger.success(`All ${statuses.length - notApplicable.length} applicable tools already installed.${naSuffix}`);
|
|
254
|
+
}
|
|
255
|
+
else if (notApplicable.length > 0) {
|
|
256
|
+
logger.success(`All applicable tools available (${notApplicable.length} n/a for this stack — skipped).`);
|
|
222
257
|
}
|
|
223
258
|
return;
|
|
224
259
|
}
|
|
@@ -290,7 +325,8 @@ async function runInstall(targetPath, autoYes, options = {}) {
|
|
|
290
325
|
const installed = results.filter((r) => r.status === 'installed').length;
|
|
291
326
|
const skipped = results.filter((r) => r.status === 'skipped').length;
|
|
292
327
|
const failed = results.filter((r) => r.status === 'failed').length;
|
|
293
|
-
|
|
328
|
+
const naSuffix = notApplicable.length > 0 ? `, ${notApplicable.length} n/a` : '';
|
|
329
|
+
logger.info(`${installed} installed, ${skipped} skipped, ${failed} failed${naSuffix}`);
|
|
294
330
|
if (failed > 0) {
|
|
295
331
|
console.log('');
|
|
296
332
|
logger.dim('Failed installs:');
|