@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.
Files changed (93) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/dist/analyzers/correctness/run.d.ts +79 -0
  3. package/dist/analyzers/correctness/run.d.ts.map +1 -0
  4. package/dist/analyzers/correctness/run.js +173 -0
  5. package/dist/analyzers/correctness/run.js.map +1 -0
  6. package/dist/analyzers/correctness/surface-run.d.ts +73 -0
  7. package/dist/analyzers/correctness/surface-run.d.ts.map +1 -0
  8. package/dist/analyzers/correctness/surface-run.js +142 -0
  9. package/dist/analyzers/correctness/surface-run.js.map +1 -0
  10. package/dist/analyzers/correctness/surface.d.ts +69 -0
  11. package/dist/analyzers/correctness/surface.d.ts.map +1 -0
  12. package/dist/analyzers/correctness/surface.js +281 -0
  13. package/dist/analyzers/correctness/surface.js.map +1 -0
  14. package/dist/cli.d.ts.map +1 -1
  15. package/dist/cli.js +144 -4
  16. package/dist/cli.js.map +1 -1
  17. package/dist/generator.d.ts.map +1 -1
  18. package/dist/generator.js +5 -0
  19. package/dist/generator.js.map +1 -1
  20. package/dist/issue-cli.d.ts +2 -1
  21. package/dist/issue-cli.d.ts.map +1 -1
  22. package/dist/issue-cli.js +4 -0
  23. package/dist/issue-cli.js.map +1 -1
  24. package/dist/languages/capabilities/correctness.d.ts +54 -0
  25. package/dist/languages/capabilities/correctness.d.ts.map +1 -0
  26. package/dist/languages/capabilities/correctness.js +20 -0
  27. package/dist/languages/capabilities/correctness.js.map +1 -0
  28. package/dist/languages/csharp.d.ts.map +1 -1
  29. package/dist/languages/csharp.js +84 -0
  30. package/dist/languages/csharp.js.map +1 -1
  31. package/dist/languages/go.d.ts.map +1 -1
  32. package/dist/languages/go.js +51 -0
  33. package/dist/languages/go.js.map +1 -1
  34. package/dist/languages/index.d.ts +11 -0
  35. package/dist/languages/index.d.ts.map +1 -1
  36. package/dist/languages/index.js +12 -0
  37. package/dist/languages/index.js.map +1 -1
  38. package/dist/languages/java.d.ts.map +1 -1
  39. package/dist/languages/java.js +12 -0
  40. package/dist/languages/java.js.map +1 -1
  41. package/dist/languages/jvm-build.d.ts +54 -0
  42. package/dist/languages/jvm-build.d.ts.map +1 -0
  43. package/dist/languages/jvm-build.js +245 -0
  44. package/dist/languages/jvm-build.js.map +1 -0
  45. package/dist/languages/kotlin.d.ts.map +1 -1
  46. package/dist/languages/kotlin.js +13 -0
  47. package/dist/languages/kotlin.js.map +1 -1
  48. package/dist/languages/python.d.ts.map +1 -1
  49. package/dist/languages/python.js +78 -0
  50. package/dist/languages/python.js.map +1 -1
  51. package/dist/languages/ruby.d.ts.map +1 -1
  52. package/dist/languages/ruby.js +64 -0
  53. package/dist/languages/ruby.js.map +1 -1
  54. package/dist/languages/rust.d.ts.map +1 -1
  55. package/dist/languages/rust.js +110 -0
  56. package/dist/languages/rust.js.map +1 -1
  57. package/dist/languages/types.d.ts +20 -0
  58. package/dist/languages/types.d.ts.map +1 -1
  59. package/dist/languages/typescript.d.ts.map +1 -1
  60. package/dist/languages/typescript.js +109 -0
  61. package/dist/languages/typescript.js.map +1 -1
  62. package/dist/loop/floor-gate.d.ts +54 -0
  63. package/dist/loop/floor-gate.d.ts.map +1 -0
  64. package/dist/loop/floor-gate.js +157 -0
  65. package/dist/loop/floor-gate.js.map +1 -0
  66. package/dist/loop/floor-state.d.ts +66 -0
  67. package/dist/loop/floor-state.d.ts.map +1 -0
  68. package/dist/loop/floor-state.js +138 -0
  69. package/dist/loop/floor-state.js.map +1 -0
  70. package/dist/loop/scaffold.d.ts +4 -0
  71. package/dist/loop/scaffold.d.ts.map +1 -1
  72. package/dist/loop/scaffold.js +7 -7
  73. package/dist/loop/scaffold.js.map +1 -1
  74. package/dist/loop/stop-gate.d.ts +2 -1
  75. package/dist/loop/stop-gate.d.ts.map +1 -1
  76. package/dist/loop/stop-gate.js +44 -6
  77. package/dist/loop/stop-gate.js.map +1 -1
  78. package/dist/ship-installers.d.ts +20 -0
  79. package/dist/ship-installers.d.ts.map +1 -1
  80. package/dist/ship-installers.js +17 -16
  81. package/dist/ship-installers.js.map +1 -1
  82. package/dist/uninstall/index.d.ts +47 -0
  83. package/dist/uninstall/index.d.ts.map +1 -0
  84. package/dist/uninstall/index.js +418 -0
  85. package/dist/uninstall/index.js.map +1 -0
  86. package/dist/uninstall/reversals.d.ts +70 -0
  87. package/dist/uninstall/reversals.d.ts.map +1 -0
  88. package/dist/uninstall/reversals.js +202 -0
  89. package/dist/uninstall/reversals.js.map +1 -0
  90. package/package.json +1 -1
  91. package/templates/.claude/skills/dxkit-uninstall/SKILL.md +55 -0
  92. package/templates/.githooks/pre-push +10 -0
  93. 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":"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"}
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,CAo/DvD"}
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
- if (!values.json)
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 (!values.json)
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 (!values.json)
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], vyuh-dxkit loop doctor`);
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
  }