@vyuhlabs/dxkit 2.22.0 → 2.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +97 -0
- package/dist/analyzers/correctness/run.d.ts +79 -0
- package/dist/analyzers/correctness/run.d.ts.map +1 -0
- package/dist/analyzers/correctness/run.js +173 -0
- package/dist/analyzers/correctness/run.js.map +1 -0
- package/dist/analyzers/correctness/surface-run.d.ts +73 -0
- package/dist/analyzers/correctness/surface-run.d.ts.map +1 -0
- package/dist/analyzers/correctness/surface-run.js +142 -0
- package/dist/analyzers/correctness/surface-run.js.map +1 -0
- package/dist/analyzers/correctness/surface.d.ts +69 -0
- package/dist/analyzers/correctness/surface.d.ts.map +1 -0
- package/dist/analyzers/correctness/surface.js +281 -0
- package/dist/analyzers/correctness/surface.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +144 -4
- package/dist/cli.js.map +1 -1
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +5 -0
- package/dist/generator.js.map +1 -1
- package/dist/issue-cli.d.ts +2 -1
- package/dist/issue-cli.d.ts.map +1 -1
- package/dist/issue-cli.js +4 -0
- package/dist/issue-cli.js.map +1 -1
- package/dist/languages/capabilities/correctness.d.ts +54 -0
- package/dist/languages/capabilities/correctness.d.ts.map +1 -0
- package/dist/languages/capabilities/correctness.js +20 -0
- package/dist/languages/capabilities/correctness.js.map +1 -0
- package/dist/languages/csharp.d.ts.map +1 -1
- package/dist/languages/csharp.js +84 -0
- package/dist/languages/csharp.js.map +1 -1
- package/dist/languages/go.d.ts.map +1 -1
- package/dist/languages/go.js +51 -0
- package/dist/languages/go.js.map +1 -1
- package/dist/languages/index.d.ts +11 -0
- package/dist/languages/index.d.ts.map +1 -1
- package/dist/languages/index.js +12 -0
- package/dist/languages/index.js.map +1 -1
- package/dist/languages/java.d.ts.map +1 -1
- package/dist/languages/java.js +12 -0
- package/dist/languages/java.js.map +1 -1
- package/dist/languages/jvm-build.d.ts +54 -0
- package/dist/languages/jvm-build.d.ts.map +1 -0
- package/dist/languages/jvm-build.js +245 -0
- package/dist/languages/jvm-build.js.map +1 -0
- package/dist/languages/kotlin.d.ts.map +1 -1
- package/dist/languages/kotlin.js +13 -0
- package/dist/languages/kotlin.js.map +1 -1
- package/dist/languages/python.d.ts.map +1 -1
- package/dist/languages/python.js +78 -0
- package/dist/languages/python.js.map +1 -1
- package/dist/languages/ruby.d.ts.map +1 -1
- package/dist/languages/ruby.js +64 -0
- package/dist/languages/ruby.js.map +1 -1
- package/dist/languages/rust.d.ts.map +1 -1
- package/dist/languages/rust.js +110 -0
- package/dist/languages/rust.js.map +1 -1
- package/dist/languages/types.d.ts +20 -0
- package/dist/languages/types.d.ts.map +1 -1
- package/dist/languages/typescript.d.ts.map +1 -1
- package/dist/languages/typescript.js +109 -0
- package/dist/languages/typescript.js.map +1 -1
- package/dist/loop/floor-gate.d.ts +54 -0
- package/dist/loop/floor-gate.d.ts.map +1 -0
- package/dist/loop/floor-gate.js +157 -0
- package/dist/loop/floor-gate.js.map +1 -0
- package/dist/loop/floor-state.d.ts +66 -0
- package/dist/loop/floor-state.d.ts.map +1 -0
- package/dist/loop/floor-state.js +138 -0
- package/dist/loop/floor-state.js.map +1 -0
- package/dist/loop/scaffold.d.ts +4 -0
- package/dist/loop/scaffold.d.ts.map +1 -1
- package/dist/loop/scaffold.js +7 -7
- package/dist/loop/scaffold.js.map +1 -1
- package/dist/loop/stop-gate.d.ts +2 -1
- package/dist/loop/stop-gate.d.ts.map +1 -1
- package/dist/loop/stop-gate.js +44 -6
- package/dist/loop/stop-gate.js.map +1 -1
- package/dist/ship-installers.d.ts +20 -0
- package/dist/ship-installers.d.ts.map +1 -1
- package/dist/ship-installers.js +17 -16
- package/dist/ship-installers.js.map +1 -1
- package/dist/uninstall/index.d.ts +47 -0
- package/dist/uninstall/index.d.ts.map +1 -0
- package/dist/uninstall/index.js +418 -0
- package/dist/uninstall/index.js.map +1 -0
- package/dist/uninstall/reversals.d.ts +70 -0
- package/dist/uninstall/reversals.d.ts.map +1 -0
- package/dist/uninstall/reversals.js +202 -0
- package/dist/uninstall/reversals.js.map +1 -0
- package/package.json +1 -1
- package/templates/.claude/skills/dxkit-uninstall/SKILL.md +55 -0
- package/templates/.githooks/pre-push +10 -0
- package/templates/.github/workflows/dxkit-guardrails.yml +17 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The correctness-floor SURFACE resolver — decides, per surface, whether the
|
|
3
|
+
* floor runs by default. This is the canonical resolver for the correctness
|
|
4
|
+
* capability (mirror of `resolveBaselineMode` for baseline modes, Rule 11): one
|
|
5
|
+
* function, one precedence order, so no two call sites drift on the default.
|
|
6
|
+
*
|
|
7
|
+
* Three surfaces run the floor, with different postures:
|
|
8
|
+
* - `loop-stop` — an autonomous loop's Stop-gate. ALWAYS default-on: an agent
|
|
9
|
+
* must never declare "done" on code that does not compile or whose tests
|
|
10
|
+
* fail. (An explicit flag/policy can still turn it off, but the default is
|
|
11
|
+
* on regardless of what CI the repo has.)
|
|
12
|
+
* - `pre-push` / `ci` — ADAPTIVE. If the repo already runs its tests in its own
|
|
13
|
+
* CI, dxkit's floor is redundant there, so it defaults to OPT-IN. If no
|
|
14
|
+
* test-running CI is detected, the floor defaults ON so pushes/PRs are still
|
|
15
|
+
* checked. When we cannot tell (a CI exists but its test step is opaque), we
|
|
16
|
+
* FAIL TOWARD ON — a redundant floor run is cheap; a missed regression is not.
|
|
17
|
+
*
|
|
18
|
+
* Precedence (highest first), mirroring the loop-preset + baseline-mode
|
|
19
|
+
* resolvers:
|
|
20
|
+
* 1. explicit `flag` argument (a `--correctness` / `--no-correctness` CLI flag)
|
|
21
|
+
* 2. `DXKIT_FLOOR_<SURFACE>` env var (benchmark / CI override)
|
|
22
|
+
* 3. `.dxkit/policy.json` → `correctness.surfaces.<surface>`
|
|
23
|
+
* 4. the surface's default (always-on for loop-stop; adaptive for pre-push/ci)
|
|
24
|
+
*/
|
|
25
|
+
export type CorrectnessSurface = 'loop-stop' | 'pre-push' | 'ci';
|
|
26
|
+
export type SurfaceDecisionSource = 'always-on' | 'flag' | 'env' | 'policy' | 'adaptive-no-test-ci' | 'adaptive-test-ci-detected' | 'adaptive-uncertain';
|
|
27
|
+
export interface SurfaceResolution {
|
|
28
|
+
readonly surface: CorrectnessSurface;
|
|
29
|
+
readonly enabled: boolean;
|
|
30
|
+
readonly source: SurfaceDecisionSource;
|
|
31
|
+
/** One-line human-readable rationale, for `doctor` / CLI output. */
|
|
32
|
+
readonly reason: string;
|
|
33
|
+
}
|
|
34
|
+
export type TestCiStatus = 'has-test-ci' | 'no-test-ci' | 'uncertain';
|
|
35
|
+
export interface TestCiDetection {
|
|
36
|
+
readonly status: TestCiStatus;
|
|
37
|
+
/** When `has-test-ci`, the file + command that proved it (for the reason). */
|
|
38
|
+
readonly evidence?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Detect whether the repo runs its tests in its OWN CI. Reads GitHub Actions
|
|
42
|
+
* workflows (excluding dxkit-authored ones) plus the common flat CI configs,
|
|
43
|
+
* scanning for a test invocation:
|
|
44
|
+
* - a matching test command in any file → `has-test-ci`;
|
|
45
|
+
* - no CI config found at all → `no-test-ci` (dxkit's floor should default on);
|
|
46
|
+
* - CI config exists but no test command matched (opaque `make ci`, a called
|
|
47
|
+
* reusable workflow, etc.) → `uncertain` (fail toward on).
|
|
48
|
+
* Best-effort and never throws — an unreadable file is skipped.
|
|
49
|
+
*/
|
|
50
|
+
export declare function detectTestCi(cwd: string): TestCiDetection;
|
|
51
|
+
/** Read `correctness.surfaces.<surface>` from `.dxkit/policy.json`. Best-effort:
|
|
52
|
+
* a missing / malformed file or absent block yields an empty map. */
|
|
53
|
+
export declare function readSurfacePolicy(cwd: string): Partial<Record<CorrectnessSurface, boolean>>;
|
|
54
|
+
export interface ResolveSurfaceOptions {
|
|
55
|
+
readonly surface: CorrectnessSurface;
|
|
56
|
+
readonly cwd: string;
|
|
57
|
+
/** Explicit `--correctness` / `--no-correctness` CLI flag (highest precedence). */
|
|
58
|
+
readonly flag?: boolean;
|
|
59
|
+
/** Injected for tests; defaults to reading `.dxkit/policy.json`. */
|
|
60
|
+
readonly policySurfaces?: Partial<Record<CorrectnessSurface, boolean>>;
|
|
61
|
+
/** Injected for tests; defaults to the real `detectTestCi`. */
|
|
62
|
+
readonly detect?: (cwd: string) => TestCiDetection;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Resolve whether the correctness floor is enabled on a surface. Pure aside from
|
|
66
|
+
* the default policy/env reads (both injectable); never throws.
|
|
67
|
+
*/
|
|
68
|
+
export declare function resolveCorrectnessSurface(opts: ResolveSurfaceOptions): SurfaceResolution;
|
|
69
|
+
//# sourceMappingURL=surface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../../src/analyzers/correctness/surface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAOH,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,UAAU,GAAG,IAAI,CAAC;AAEjE,MAAM,MAAM,qBAAqB,GAC7B,WAAW,GACX,MAAM,GACN,KAAK,GACL,QAAQ,GACR,qBAAqB,GACrB,2BAA2B,GAC3B,oBAAoB,CAAC;AAEzB,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,oEAAoE;IACpE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,YAAY,GAAG,WAAW,CAAC;AAEtE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AA2DD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CA4CzD;AAID;sEACsE;AACtE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC,CAgB3F;AAoBD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,oEAAoE;IACpE,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC,CAAC;IACvE,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,eAAe,CAAC;CACpD;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,qBAAqB,GAAG,iBAAiB,CAwExF"}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The correctness-floor SURFACE resolver — decides, per surface, whether the
|
|
4
|
+
* floor runs by default. This is the canonical resolver for the correctness
|
|
5
|
+
* capability (mirror of `resolveBaselineMode` for baseline modes, Rule 11): one
|
|
6
|
+
* function, one precedence order, so no two call sites drift on the default.
|
|
7
|
+
*
|
|
8
|
+
* Three surfaces run the floor, with different postures:
|
|
9
|
+
* - `loop-stop` — an autonomous loop's Stop-gate. ALWAYS default-on: an agent
|
|
10
|
+
* must never declare "done" on code that does not compile or whose tests
|
|
11
|
+
* fail. (An explicit flag/policy can still turn it off, but the default is
|
|
12
|
+
* on regardless of what CI the repo has.)
|
|
13
|
+
* - `pre-push` / `ci` — ADAPTIVE. If the repo already runs its tests in its own
|
|
14
|
+
* CI, dxkit's floor is redundant there, so it defaults to OPT-IN. If no
|
|
15
|
+
* test-running CI is detected, the floor defaults ON so pushes/PRs are still
|
|
16
|
+
* checked. When we cannot tell (a CI exists but its test step is opaque), we
|
|
17
|
+
* FAIL TOWARD ON — a redundant floor run is cheap; a missed regression is not.
|
|
18
|
+
*
|
|
19
|
+
* Precedence (highest first), mirroring the loop-preset + baseline-mode
|
|
20
|
+
* resolvers:
|
|
21
|
+
* 1. explicit `flag` argument (a `--correctness` / `--no-correctness` CLI flag)
|
|
22
|
+
* 2. `DXKIT_FLOOR_<SURFACE>` env var (benchmark / CI override)
|
|
23
|
+
* 3. `.dxkit/policy.json` → `correctness.surfaces.<surface>`
|
|
24
|
+
* 4. the surface's default (always-on for loop-stop; adaptive for pre-push/ci)
|
|
25
|
+
*/
|
|
26
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
27
|
+
if (k2 === undefined) k2 = k;
|
|
28
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
29
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
30
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
31
|
+
}
|
|
32
|
+
Object.defineProperty(o, k2, desc);
|
|
33
|
+
}) : (function(o, m, k, k2) {
|
|
34
|
+
if (k2 === undefined) k2 = k;
|
|
35
|
+
o[k2] = m[k];
|
|
36
|
+
}));
|
|
37
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
38
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
39
|
+
}) : function(o, v) {
|
|
40
|
+
o["default"] = v;
|
|
41
|
+
});
|
|
42
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
43
|
+
var ownKeys = function(o) {
|
|
44
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
45
|
+
var ar = [];
|
|
46
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
47
|
+
return ar;
|
|
48
|
+
};
|
|
49
|
+
return ownKeys(o);
|
|
50
|
+
};
|
|
51
|
+
return function (mod) {
|
|
52
|
+
if (mod && mod.__esModule) return mod;
|
|
53
|
+
var result = {};
|
|
54
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
55
|
+
__setModuleDefault(result, mod);
|
|
56
|
+
return result;
|
|
57
|
+
};
|
|
58
|
+
})();
|
|
59
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
60
|
+
exports.detectTestCi = detectTestCi;
|
|
61
|
+
exports.readSurfacePolicy = readSurfacePolicy;
|
|
62
|
+
exports.resolveCorrectnessSurface = resolveCorrectnessSurface;
|
|
63
|
+
const fs = __importStar(require("fs"));
|
|
64
|
+
const path = __importStar(require("path"));
|
|
65
|
+
const policy_1 = require("../../baseline/policy");
|
|
66
|
+
// ─── Test-CI detection ──────────────────────────────────────────────────────
|
|
67
|
+
/** CI config files we can read as text and scan for a test invocation. Ordered
|
|
68
|
+
* by ubiquity; GitHub Actions workflows are handled separately (a directory). */
|
|
69
|
+
const FLAT_CI_FILES = [
|
|
70
|
+
'.gitlab-ci.yml',
|
|
71
|
+
'.gitlab-ci.yaml',
|
|
72
|
+
'Jenkinsfile',
|
|
73
|
+
'.circleci/config.yml',
|
|
74
|
+
'azure-pipelines.yml',
|
|
75
|
+
'azure-pipelines.yaml',
|
|
76
|
+
'.travis.yml',
|
|
77
|
+
'bitbucket-pipelines.yml',
|
|
78
|
+
];
|
|
79
|
+
/** Substrings that mark a real test invocation, unioned across ecosystems. Kept
|
|
80
|
+
* deliberately specific (a bare "test" would match too much) so a match is a
|
|
81
|
+
* confident "this CI runs tests" signal. */
|
|
82
|
+
const TEST_COMMAND_PATTERNS = [
|
|
83
|
+
/\bnpm (run )?test\b/,
|
|
84
|
+
/\byarn (run )?test\b/,
|
|
85
|
+
/\bpnpm (run )?test\b/,
|
|
86
|
+
/\bnpx (vitest|jest|mocha|ava|playwright)\b/,
|
|
87
|
+
/\b(vitest|jest|mocha|ava)\b/,
|
|
88
|
+
/\bpytest\b/,
|
|
89
|
+
/\bpython -m (pytest|unittest)\b/,
|
|
90
|
+
/\b(tox|nox)\b/,
|
|
91
|
+
/\bgo test\b/,
|
|
92
|
+
/\bcargo (test|nextest)\b/,
|
|
93
|
+
/\bmvn (.*\s)?(test|verify)\b/,
|
|
94
|
+
/\b(\.\/)?gradlew? (.*\s)?(test|check)\b/,
|
|
95
|
+
/\bdotnet test\b/,
|
|
96
|
+
/\b(bundle exec )?rspec\b/,
|
|
97
|
+
/\brake (.*\s)?test\b/,
|
|
98
|
+
/\bmake (.*\s)?test\b/,
|
|
99
|
+
/\bjust (.*\s)?test\b/,
|
|
100
|
+
];
|
|
101
|
+
/** Is a workflow file one dxkit itself installed? Its own guardrail/floor CI is
|
|
102
|
+
* the surface being resolved, not a pre-existing test-CI, so it must not count
|
|
103
|
+
* as the repo "already testing in CI". */
|
|
104
|
+
function isDxkitAuthoredWorkflow(name) {
|
|
105
|
+
return name.startsWith('dxkit-');
|
|
106
|
+
}
|
|
107
|
+
function textRunsTests(text) {
|
|
108
|
+
return TEST_COMMAND_PATTERNS.some((re) => re.test(text));
|
|
109
|
+
}
|
|
110
|
+
function matchedTestCommand(text) {
|
|
111
|
+
for (const re of TEST_COMMAND_PATTERNS) {
|
|
112
|
+
const m = re.exec(text);
|
|
113
|
+
if (m)
|
|
114
|
+
return m[0];
|
|
115
|
+
}
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Detect whether the repo runs its tests in its OWN CI. Reads GitHub Actions
|
|
120
|
+
* workflows (excluding dxkit-authored ones) plus the common flat CI configs,
|
|
121
|
+
* scanning for a test invocation:
|
|
122
|
+
* - a matching test command in any file → `has-test-ci`;
|
|
123
|
+
* - no CI config found at all → `no-test-ci` (dxkit's floor should default on);
|
|
124
|
+
* - CI config exists but no test command matched (opaque `make ci`, a called
|
|
125
|
+
* reusable workflow, etc.) → `uncertain` (fail toward on).
|
|
126
|
+
* Best-effort and never throws — an unreadable file is skipped.
|
|
127
|
+
*/
|
|
128
|
+
function detectTestCi(cwd) {
|
|
129
|
+
let sawAnyCi = false;
|
|
130
|
+
// GitHub Actions workflows (a directory of yml/yaml files).
|
|
131
|
+
const wfDir = path.join(cwd, '.github', 'workflows');
|
|
132
|
+
let wfNames = [];
|
|
133
|
+
try {
|
|
134
|
+
wfNames = fs
|
|
135
|
+
.readdirSync(wfDir)
|
|
136
|
+
.filter((n) => (n.endsWith('.yml') || n.endsWith('.yaml')) && !isDxkitAuthoredWorkflow(n));
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
/* no workflows dir */
|
|
140
|
+
}
|
|
141
|
+
for (const name of wfNames) {
|
|
142
|
+
sawAnyCi = true;
|
|
143
|
+
let text;
|
|
144
|
+
try {
|
|
145
|
+
text = fs.readFileSync(path.join(wfDir, name), 'utf8');
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (textRunsTests(text)) {
|
|
151
|
+
return {
|
|
152
|
+
status: 'has-test-ci',
|
|
153
|
+
evidence: `.github/workflows/${name}: ${matchedTestCommand(text)}`,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Flat CI config files.
|
|
158
|
+
for (const rel of FLAT_CI_FILES) {
|
|
159
|
+
let text;
|
|
160
|
+
try {
|
|
161
|
+
text = fs.readFileSync(path.join(cwd, rel), 'utf8');
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
sawAnyCi = true;
|
|
167
|
+
if (textRunsTests(text)) {
|
|
168
|
+
return { status: 'has-test-ci', evidence: `${rel}: ${matchedTestCommand(text)}` };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return sawAnyCi ? { status: 'uncertain' } : { status: 'no-test-ci' };
|
|
172
|
+
}
|
|
173
|
+
// ─── Policy + env reads ─────────────────────────────────────────────────────
|
|
174
|
+
/** Read `correctness.surfaces.<surface>` from `.dxkit/policy.json`. Best-effort:
|
|
175
|
+
* a missing / malformed file or absent block yields an empty map. */
|
|
176
|
+
function readSurfacePolicy(cwd) {
|
|
177
|
+
try {
|
|
178
|
+
const raw = fs.readFileSync(path.join(cwd, policy_1.DEFAULT_POLICY_FILENAME), 'utf8');
|
|
179
|
+
const parsed = JSON.parse(raw);
|
|
180
|
+
const surfaces = parsed.correctness?.surfaces;
|
|
181
|
+
if (!surfaces || typeof surfaces !== 'object')
|
|
182
|
+
return {};
|
|
183
|
+
const out = {};
|
|
184
|
+
for (const s of ['loop-stop', 'pre-push', 'ci']) {
|
|
185
|
+
if (typeof surfaces[s] === 'boolean')
|
|
186
|
+
out[s] = surfaces[s];
|
|
187
|
+
}
|
|
188
|
+
return out;
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
return {};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const ENV_VAR = {
|
|
195
|
+
'loop-stop': 'DXKIT_FLOOR_LOOP',
|
|
196
|
+
'pre-push': 'DXKIT_FLOOR_PREPUSH',
|
|
197
|
+
ci: 'DXKIT_FLOOR_CI',
|
|
198
|
+
};
|
|
199
|
+
/** Parse a truthy/falsy env override, or undefined when unset/unrecognized. */
|
|
200
|
+
function envOverride(surface) {
|
|
201
|
+
const raw = process.env[ENV_VAR[surface]];
|
|
202
|
+
if (raw === undefined)
|
|
203
|
+
return undefined;
|
|
204
|
+
const v = raw.trim().toLowerCase();
|
|
205
|
+
if (['1', 'true', 'on', 'yes'].includes(v))
|
|
206
|
+
return true;
|
|
207
|
+
if (['0', 'false', 'off', 'no'].includes(v))
|
|
208
|
+
return false;
|
|
209
|
+
return undefined;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Resolve whether the correctness floor is enabled on a surface. Pure aside from
|
|
213
|
+
* the default policy/env reads (both injectable); never throws.
|
|
214
|
+
*/
|
|
215
|
+
function resolveCorrectnessSurface(opts) {
|
|
216
|
+
const { surface } = opts;
|
|
217
|
+
// 1. explicit CLI flag
|
|
218
|
+
if (opts.flag !== undefined) {
|
|
219
|
+
return {
|
|
220
|
+
surface,
|
|
221
|
+
enabled: opts.flag,
|
|
222
|
+
source: 'flag',
|
|
223
|
+
reason: `explicitly ${opts.flag ? 'enabled' : 'disabled'} via flag`,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
// 2. env override
|
|
227
|
+
const env = envOverride(surface);
|
|
228
|
+
if (env !== undefined) {
|
|
229
|
+
return {
|
|
230
|
+
surface,
|
|
231
|
+
enabled: env,
|
|
232
|
+
source: 'env',
|
|
233
|
+
reason: `${env ? 'enabled' : 'disabled'} via ${ENV_VAR[surface]}`,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
// 3. policy file
|
|
237
|
+
const policy = opts.policySurfaces ?? readSurfacePolicy(opts.cwd);
|
|
238
|
+
const pol = policy[surface];
|
|
239
|
+
if (pol !== undefined) {
|
|
240
|
+
return {
|
|
241
|
+
surface,
|
|
242
|
+
enabled: pol,
|
|
243
|
+
source: 'policy',
|
|
244
|
+
reason: `${pol ? 'enabled' : 'disabled'} via .dxkit/policy.json correctness.surfaces.${surface}`,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
// 4. surface default
|
|
248
|
+
if (surface === 'loop-stop') {
|
|
249
|
+
return {
|
|
250
|
+
surface,
|
|
251
|
+
enabled: true,
|
|
252
|
+
source: 'always-on',
|
|
253
|
+
reason: 'loop Stop-gate runs the floor by default — an agent must not stop on broken code',
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
// pre-push / ci: adaptive on the repo's own test-CI
|
|
257
|
+
const det = (opts.detect ?? detectTestCi)(opts.cwd);
|
|
258
|
+
if (det.status === 'has-test-ci') {
|
|
259
|
+
return {
|
|
260
|
+
surface,
|
|
261
|
+
enabled: false,
|
|
262
|
+
source: 'adaptive-test-ci-detected',
|
|
263
|
+
reason: `opt-in — the repo already runs tests in CI (${det.evidence}); enable explicitly to also run dxkit's floor here`,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
if (det.status === 'no-test-ci') {
|
|
267
|
+
return {
|
|
268
|
+
surface,
|
|
269
|
+
enabled: true,
|
|
270
|
+
source: 'adaptive-no-test-ci',
|
|
271
|
+
reason: 'no test-running CI detected — the floor runs by default so changes are still checked',
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
surface,
|
|
276
|
+
enabled: true,
|
|
277
|
+
source: 'adaptive-uncertain',
|
|
278
|
+
reason: 'a CI exists but its test step is opaque — running the floor to be safe (fail toward on)',
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=surface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface.js","sourceRoot":"","sources":["../../../src/analyzers/correctness/surface.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqGH,oCA4CC;AAMD,8CAgBC;AAmCD,8DAwEC;AAhRD,uCAAyB;AACzB,2CAA6B;AAE7B,kDAAgE;AA6BhE,+EAA+E;AAE/E;kFACkF;AAClF,MAAM,aAAa,GAAG;IACpB,gBAAgB;IAChB,iBAAiB;IACjB,aAAa;IACb,sBAAsB;IACtB,qBAAqB;IACrB,sBAAsB;IACtB,aAAa;IACb,yBAAyB;CAC1B,CAAC;AAEF;;6CAE6C;AAC7C,MAAM,qBAAqB,GAAsB;IAC/C,qBAAqB;IACrB,sBAAsB;IACtB,sBAAsB;IACtB,4CAA4C;IAC5C,6BAA6B;IAC7B,YAAY;IACZ,iCAAiC;IACjC,eAAe;IACf,aAAa;IACb,0BAA0B;IAC1B,8BAA8B;IAC9B,yCAAyC;IACzC,iBAAiB;IACjB,0BAA0B;IAC1B,sBAAsB;IACtB,sBAAsB;IACtB,sBAAsB;CACvB,CAAC;AAEF;;2CAE2C;AAC3C,SAAS,uBAAuB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAY;IACtC,KAAK,MAAM,EAAE,IAAI,qBAAqB,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,YAAY,CAAC,GAAW;IACtC,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,4DAA4D;IAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IACrD,IAAI,OAAO,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,GAAG,EAAE;aACT,WAAW,CAAC,KAAK,CAAC;aAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,CAAC;IAAC,MAAM,CAAC;QACP,sBAAsB;IACxB,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,OAAO;gBACL,MAAM,EAAE,aAAa;gBACrB,QAAQ,EAAE,qBAAqB,IAAI,KAAK,kBAAkB,CAAC,IAAI,CAAC,EAAE;aACnE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,wBAAwB;IACxB,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAChC,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,GAAG,KAAK,kBAAkB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACpF,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;AACvE,CAAC;AAED,+EAA+E;AAE/E;sEACsE;AACtE,SAAgB,iBAAiB,CAAC,GAAW;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,gCAAuB,CAAC,EAAE,MAAM,CAAC,CAAC;QAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAE5B,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC;QAC9C,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QACzD,MAAM,GAAG,GAAiD,EAAE,CAAC;QAC7D,KAAK,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,IAAI,CAAU,EAAE,CAAC;YACzD,IAAI,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,SAAS;gBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC7D,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAuC;IAClD,WAAW,EAAE,kBAAkB;IAC/B,UAAU,EAAE,qBAAqB;IACjC,EAAE,EAAE,gBAAgB;CACrB,CAAC;AAEF,+EAA+E;AAC/E,SAAS,WAAW,CAAC,OAA2B;IAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1C,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACnC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACxD,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1D,OAAO,SAAS,CAAC;AACnB,CAAC;AAeD;;;GAGG;AACH,SAAgB,yBAAyB,CAAC,IAA2B;IACnE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAEzB,uBAAuB;IACvB,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO;YACL,OAAO;YACP,OAAO,EAAE,IAAI,CAAC,IAAI;YAClB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,cAAc,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,WAAW;SACpE,CAAC;IACJ,CAAC;IAED,kBAAkB;IAClB,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO;YACL,OAAO;YACP,OAAO,EAAE,GAAG;YACZ,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,QAAQ,OAAO,CAAC,OAAO,CAAC,EAAE;SAClE,CAAC;IACJ,CAAC;IAED,iBAAiB;IACjB,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClE,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO;YACL,OAAO;YACP,OAAO,EAAE,GAAG;YACZ,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,gDAAgD,OAAO,EAAE;SACjG,CAAC;IACJ,CAAC;IAED,qBAAqB;IACrB,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;QAC5B,OAAO;YACL,OAAO;YACP,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,WAAW;YACnB,MAAM,EAAE,kFAAkF;SAC3F,CAAC;IACJ,CAAC;IAED,oDAAoD;IACpD,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpD,IAAI,GAAG,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;QACjC,OAAO;YACL,OAAO;YACP,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,2BAA2B;YACnC,MAAM,EAAE,+CAA+C,GAAG,CAAC,QAAQ,qDAAqD;SACzH,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QAChC,OAAO;YACL,OAAO;YACP,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,qBAAqB;YAC7B,MAAM,EACJ,sFAAsF;SACzF,CAAC;IACJ,CAAC;IACD,OAAO;QACL,OAAO;QACP,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,oBAAoB;QAC5B,MAAM,EACJ,yFAAyF;KAC5F,CAAC;AACJ,CAAC"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AA4SA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AA4SA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkpEvD"}
|
package/dist/cli.js
CHANGED
|
@@ -376,6 +376,12 @@ async function run(argv) {
|
|
|
376
376
|
'added-by': { type: 'string' },
|
|
377
377
|
mode: { type: 'string' },
|
|
378
378
|
ref: { type: 'string' },
|
|
379
|
+
surface: { type: 'string' },
|
|
380
|
+
correctness: { type: 'boolean' },
|
|
381
|
+
'no-correctness': { type: 'boolean' },
|
|
382
|
+
'keep-baselines': { type: 'boolean', default: false },
|
|
383
|
+
'remove-devdep': { type: 'boolean', default: false },
|
|
384
|
+
'no-feedback': { type: 'boolean', default: false },
|
|
379
385
|
'soon-days': { type: 'string' },
|
|
380
386
|
'against-baseline': { type: 'boolean', default: false },
|
|
381
387
|
'baseline-name': { type: 'string' },
|
|
@@ -1801,9 +1807,13 @@ async function run(argv) {
|
|
|
1801
1807
|
`Expected one of: committed-full, committed-sanitized, ref-based.`);
|
|
1802
1808
|
process.exit(1);
|
|
1803
1809
|
}
|
|
1804
|
-
|
|
1810
|
+
// Suppress the console header/info in --json AND --markdown: both are
|
|
1811
|
+
// machine-captured (piped to a file / a PR comment), so the ANSI-styled
|
|
1812
|
+
// console chrome would leak into the report.
|
|
1813
|
+
const quiet = !!values.json || !!values.markdown;
|
|
1814
|
+
if (!quiet)
|
|
1805
1815
|
logger.header('vyuh-dxkit guardrail check');
|
|
1806
|
-
if (!
|
|
1816
|
+
if (!quiet)
|
|
1807
1817
|
logger.info(`Checking ${targetPath} against baseline...`);
|
|
1808
1818
|
const startTime = Date.now();
|
|
1809
1819
|
try {
|
|
@@ -1819,7 +1829,7 @@ async function run(argv) {
|
|
|
1819
1829
|
cliMode: cliMode ?? undefined,
|
|
1820
1830
|
cliRef: values.ref,
|
|
1821
1831
|
});
|
|
1822
|
-
if (!
|
|
1832
|
+
if (!quiet)
|
|
1823
1833
|
logger.info(`Baseline ${result.mode.explanation}`);
|
|
1824
1834
|
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
1825
1835
|
if (values.json) {
|
|
@@ -1840,6 +1850,118 @@ async function run(argv) {
|
|
|
1840
1850
|
}
|
|
1841
1851
|
break;
|
|
1842
1852
|
}
|
|
1853
|
+
case 'uninstall': {
|
|
1854
|
+
const targetPath = resolveRepoPath(positionals[1]);
|
|
1855
|
+
const { planUninstall, executeUninstall } = await Promise.resolve().then(() => __importStar(require('./uninstall')));
|
|
1856
|
+
const opts = {
|
|
1857
|
+
keepBaselines: !!values['keep-baselines'],
|
|
1858
|
+
removeDevDependency: !!values['remove-devdep'],
|
|
1859
|
+
force: !!values.force,
|
|
1860
|
+
};
|
|
1861
|
+
const plan = planUninstall(targetPath, opts);
|
|
1862
|
+
if (values.json) {
|
|
1863
|
+
await emitJson({ empty: plan.empty, warnings: plan.warnings, actions: plan.actions });
|
|
1864
|
+
process.exit(0);
|
|
1865
|
+
}
|
|
1866
|
+
logger.header('vyuh-dxkit uninstall');
|
|
1867
|
+
if (plan.empty) {
|
|
1868
|
+
logger.info('No dxkit footprint found in this repo — nothing to remove.');
|
|
1869
|
+
process.exit(0);
|
|
1870
|
+
}
|
|
1871
|
+
const active = plan.actions.filter((a) => a.status === 'pending');
|
|
1872
|
+
logger.info(`Will restore the pre-dxkit state by ${active.length} change(s):`);
|
|
1873
|
+
for (const a of active) {
|
|
1874
|
+
const verb = a.kind.startsWith('revert')
|
|
1875
|
+
? 'revert'
|
|
1876
|
+
: a.kind === 'git-config-unset'
|
|
1877
|
+
? 'unset'
|
|
1878
|
+
: 'remove';
|
|
1879
|
+
process.stdout.write(` ${verb.padEnd(6)} ${a.target} (${a.detail})\n`);
|
|
1880
|
+
}
|
|
1881
|
+
for (const w of plan.warnings)
|
|
1882
|
+
logger.warn(w);
|
|
1883
|
+
if (!opts.removeDevDependency) {
|
|
1884
|
+
logger.dim(' (package.json @vyuhlabs/dxkit devDependency kept — pass --remove-devdep to remove it)');
|
|
1885
|
+
}
|
|
1886
|
+
if (!values.yes) {
|
|
1887
|
+
logger.info('');
|
|
1888
|
+
logger.info(`Dry run — nothing changed. Re-run with ${(0, self_invocation_1.dxkitCli)('uninstall --yes')} to apply.`);
|
|
1889
|
+
process.exit(0);
|
|
1890
|
+
}
|
|
1891
|
+
const result = executeUninstall(targetPath, plan, opts);
|
|
1892
|
+
logger.success(`Removed ${result.removed.length}, reverted ${result.reverted.length}` +
|
|
1893
|
+
(result.skipped.length
|
|
1894
|
+
? `, skipped ${result.skipped.length} (edited — use --force)`
|
|
1895
|
+
: '') +
|
|
1896
|
+
'. dxkit has been uninstalled.');
|
|
1897
|
+
// Optional, skippable feedback — a prefilled GitHub issue the user opens
|
|
1898
|
+
// themselves (no telemetry, no auto-submit).
|
|
1899
|
+
if (!values['no-feedback']) {
|
|
1900
|
+
const { buildIssueUrl, readDxkitVersion } = await Promise.resolve().then(() => __importStar(require('./issue-cli')));
|
|
1901
|
+
const url = buildIssueUrl({
|
|
1902
|
+
type: 'uninstall',
|
|
1903
|
+
about: '',
|
|
1904
|
+
dxkitVersion: readDxkitVersion(),
|
|
1905
|
+
nodeVersion: process.version,
|
|
1906
|
+
platform: process.platform,
|
|
1907
|
+
arch: process.arch,
|
|
1908
|
+
});
|
|
1909
|
+
logger.info('');
|
|
1910
|
+
logger.info('Mind sharing why? It genuinely helps. Open a prefilled issue (nothing is sent automatically):');
|
|
1911
|
+
logger.dim(` ${url}`);
|
|
1912
|
+
logger.dim(' (skip with --no-feedback)');
|
|
1913
|
+
}
|
|
1914
|
+
process.exit(0);
|
|
1915
|
+
break;
|
|
1916
|
+
}
|
|
1917
|
+
case 'floor': {
|
|
1918
|
+
const subCommand = positionals[1];
|
|
1919
|
+
if (subCommand !== 'check') {
|
|
1920
|
+
logger.fail(`Unknown floor subcommand: ${subCommand ?? '(missing)'}. ` +
|
|
1921
|
+
`Available: vyuh-dxkit floor check [path] [--surface pre-push|ci] [--base <ref>] ` +
|
|
1922
|
+
`[--correctness | --no-correctness] [--json]`);
|
|
1923
|
+
process.exit(1);
|
|
1924
|
+
}
|
|
1925
|
+
const targetPath = resolveRepoPath(positionals[2]);
|
|
1926
|
+
const surfaceRaw = values.surface ?? 'pre-push';
|
|
1927
|
+
if (surfaceRaw !== 'pre-push' && surfaceRaw !== 'ci') {
|
|
1928
|
+
logger.fail(`Unknown --surface value: ${surfaceRaw}. Expected one of: pre-push, ci.`);
|
|
1929
|
+
process.exit(1);
|
|
1930
|
+
}
|
|
1931
|
+
// --correctness / --no-correctness → the explicit enable/disable override.
|
|
1932
|
+
const flag = values.correctness ? true : values['no-correctness'] ? false : undefined;
|
|
1933
|
+
const { runFloorForSurface } = await Promise.resolve().then(() => __importStar(require('./analyzers/correctness/surface-run')));
|
|
1934
|
+
const outcome = runFloorForSurface({
|
|
1935
|
+
surface: surfaceRaw,
|
|
1936
|
+
cwd: targetPath,
|
|
1937
|
+
base: values.base,
|
|
1938
|
+
flag,
|
|
1939
|
+
});
|
|
1940
|
+
if (values.json) {
|
|
1941
|
+
await emitJson({
|
|
1942
|
+
surface: outcome.surface,
|
|
1943
|
+
enabled: outcome.enabled,
|
|
1944
|
+
ran: outcome.ran,
|
|
1945
|
+
blocks: outcome.blocks,
|
|
1946
|
+
reason: outcome.reason,
|
|
1947
|
+
checks: outcome.result?.checks ?? [],
|
|
1948
|
+
});
|
|
1949
|
+
}
|
|
1950
|
+
else {
|
|
1951
|
+
if (outcome.blocks) {
|
|
1952
|
+
logger.fail(outcome.summary);
|
|
1953
|
+
for (const c of outcome.result?.checks.filter((c) => c.status === 'fail') ?? []) {
|
|
1954
|
+
if (c.output)
|
|
1955
|
+
process.stdout.write(`\n[${c.pack} ${c.label}]\n${c.output}\n`);
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
else {
|
|
1959
|
+
logger.success(outcome.summary);
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
process.exit(outcome.blocks ? 1 : 0);
|
|
1963
|
+
break;
|
|
1964
|
+
}
|
|
1843
1965
|
case 'setup-branch-protection': {
|
|
1844
1966
|
const { runSetupBranchProtection } = await Promise.resolve().then(() => __importStar(require('./setup-branch-protection')));
|
|
1845
1967
|
const requireReviewsRaw = values['require-reviews'];
|
|
@@ -2000,8 +2122,26 @@ async function run(argv) {
|
|
|
2000
2122
|
await runLoopDoctor(cwd, { json: !!values.json });
|
|
2001
2123
|
break;
|
|
2002
2124
|
}
|
|
2125
|
+
if (sub === 'snapshot') {
|
|
2126
|
+
// Capture the correctness-floor entry snapshot — the already-broken set
|
|
2127
|
+
// on the current (pristine) tree — so later Stops block only on
|
|
2128
|
+
// NET-NEW failures. Run at loop activation, before the agent changes
|
|
2129
|
+
// anything, or the recorded set won't be genuinely pre-existing.
|
|
2130
|
+
const { captureFloorSnapshot } = await Promise.resolve().then(() => __importStar(require('./loop/floor-gate')));
|
|
2131
|
+
const { describeCorrectnessFloor } = await Promise.resolve().then(() => __importStar(require('./analyzers/correctness/run')));
|
|
2132
|
+
const result = captureFloorSnapshot(cwd);
|
|
2133
|
+
if (result === null) {
|
|
2134
|
+
logger.info('No active language pack provides a correctness floor — nothing to snapshot.');
|
|
2135
|
+
break;
|
|
2136
|
+
}
|
|
2137
|
+
const failing = result.checks.filter((c) => c.status === 'fail').length;
|
|
2138
|
+
logger.success(`Captured correctness-floor entry snapshot (${result.checks.length} check(s), ` +
|
|
2139
|
+
`${failing} already failing). ${describeCorrectnessFloor(result)}`);
|
|
2140
|
+
break;
|
|
2141
|
+
}
|
|
2003
2142
|
logger.fail(`Unknown loop subcommand: ${sub ?? '(missing)'}. ` +
|
|
2004
|
-
`Available: vyuh-dxkit loop ledger [show | summarize | clear],
|
|
2143
|
+
`Available: vyuh-dxkit loop ledger [show | summarize | clear], ` +
|
|
2144
|
+
`vyuh-dxkit loop doctor, vyuh-dxkit loop snapshot`);
|
|
2005
2145
|
process.exit(1);
|
|
2006
2146
|
break;
|
|
2007
2147
|
}
|