@vyuhlabs/dxkit 2.21.2 → 2.23.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 +94 -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/analyzers/flow/config.d.ts +10 -0
- package/dist/analyzers/flow/config.d.ts.map +1 -1
- package/dist/analyzers/flow/config.js +29 -0
- package/dist/analyzers/flow/config.js.map +1 -1
- package/dist/analyzers/flow/contract.d.ts +12 -0
- package/dist/analyzers/flow/contract.d.ts.map +1 -1
- package/dist/analyzers/flow/contract.js +20 -0
- package/dist/analyzers/flow/contract.js.map +1 -1
- package/dist/analyzers/flow/diagnose.d.ts +62 -0
- package/dist/analyzers/flow/diagnose.d.ts.map +1 -0
- package/dist/analyzers/flow/diagnose.js +120 -0
- package/dist/analyzers/flow/diagnose.js.map +1 -0
- package/dist/analyzers/flow/publish.d.ts +47 -0
- package/dist/analyzers/flow/publish.d.ts.map +1 -0
- package/dist/analyzers/flow/publish.js +146 -0
- package/dist/analyzers/flow/publish.js.map +1 -0
- package/dist/analyzers/flow/setup.d.ts +71 -0
- package/dist/analyzers/flow/setup.d.ts.map +1 -0
- package/dist/analyzers/flow/setup.js +136 -0
- package/dist/analyzers/flow/setup.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +129 -6
- package/dist/cli.js.map +1 -1
- package/dist/doctor.d.ts +7 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +38 -1
- package/dist/doctor.js.map +1 -1
- package/dist/flow-cli.d.ts +10 -0
- package/dist/flow-cli.d.ts.map +1 -1
- package/dist/flow-cli.js +46 -0
- package/dist/flow-cli.js.map +1 -1
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +6 -0
- package/dist/generator.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/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/prompts.d.ts +15 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +66 -0
- package/dist/prompts.js.map +1 -1
- package/dist/workspace.d.ts +52 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +130 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +1 -1
- package/templates/.claude/skills/dxkit-config/SKILL.md +14 -0
- package/templates/.claude/skills/dxkit-fix/SKILL.md +2 -0
- package/templates/.claude/skills/dxkit-flow/SKILL.md +83 -0
- package/templates/.claude/skills/dxkit-hooks/SKILL.md +1 -1
- package/templates/.claude/skills/dxkit-init/SKILL.md +5 -0
- package/templates/.claude/skills/dxkit-onboard/SKILL.md +2 -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":"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"}
|
|
@@ -34,4 +34,14 @@ export interface FlowConfig {
|
|
|
34
34
|
* config behaves as "monorepo, block on exact net-new breaks".
|
|
35
35
|
*/
|
|
36
36
|
export declare function readFlowConfig(cwd: string): FlowConfig;
|
|
37
|
+
/**
|
|
38
|
+
* Write into `.dxkit/policy.json:flow`, merging the patch over the existing
|
|
39
|
+
* `flow` block and PRESERVING every other policy section (loop, baseline, …) —
|
|
40
|
+
* the same discipline `ensureLoopPreset` uses for `loop.preset`. This is the
|
|
41
|
+
* single writer of the flow policy section (Rule 2), paired with the reader
|
|
42
|
+
* above. Returns `true` if the file changed, `false` if it was already at the
|
|
43
|
+
* target (idempotent) or could not be parsed (malformed policy is left
|
|
44
|
+
* untouched — the caller reports it rather than clobbering hand-edits).
|
|
45
|
+
*/
|
|
46
|
+
export declare function writeFlowPolicy(cwd: string, patch: Partial<Pick<FlowConfig, 'mode' | 'stripUrlPrefixes' | 'specs'>>): boolean;
|
|
37
47
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/analyzers/flow/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH;;;;;;8CAM8C;AAC9C,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;AAEpD,MAAM,WAAW,UAAU;IACzB;+CAC2C;IAC3C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B;iEAC6D;IAC7D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAwBD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAiBtD"}
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/analyzers/flow/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH;;;;;;8CAM8C;AAC9C,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;AAEpD,MAAM,WAAW,UAAU;IACzB;+CAC2C;IAC3C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B;iEAC6D;IAC7D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAwBD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAiBtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,GAAG,OAAO,CAAC,CAAC,GACtE,OAAO,CAgBT"}
|
|
@@ -44,6 +44,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
44
44
|
})();
|
|
45
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
46
|
exports.readFlowConfig = readFlowConfig;
|
|
47
|
+
exports.writeFlowPolicy = writeFlowPolicy;
|
|
47
48
|
const fs = __importStar(require("fs"));
|
|
48
49
|
const path = __importStar(require("path"));
|
|
49
50
|
const DEFAULTS = {
|
|
@@ -81,4 +82,32 @@ function readFlowConfig(cwd) {
|
|
|
81
82
|
: DEFAULTS.blockThreshold,
|
|
82
83
|
};
|
|
83
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Write into `.dxkit/policy.json:flow`, merging the patch over the existing
|
|
87
|
+
* `flow` block and PRESERVING every other policy section (loop, baseline, …) —
|
|
88
|
+
* the same discipline `ensureLoopPreset` uses for `loop.preset`. This is the
|
|
89
|
+
* single writer of the flow policy section (Rule 2), paired with the reader
|
|
90
|
+
* above. Returns `true` if the file changed, `false` if it was already at the
|
|
91
|
+
* target (idempotent) or could not be parsed (malformed policy is left
|
|
92
|
+
* untouched — the caller reports it rather than clobbering hand-edits).
|
|
93
|
+
*/
|
|
94
|
+
function writeFlowPolicy(cwd, patch) {
|
|
95
|
+
const abs = path.join(cwd, '.dxkit', 'policy.json');
|
|
96
|
+
let policy = {};
|
|
97
|
+
if (fs.existsSync(abs)) {
|
|
98
|
+
try {
|
|
99
|
+
policy = JSON.parse(fs.readFileSync(abs, 'utf8'));
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return false; // malformed — leave it; caller surfaces the note
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const nextFlow = { ...(policy.flow ?? {}), ...patch };
|
|
106
|
+
if (JSON.stringify(policy.flow ?? {}) === JSON.stringify(nextFlow))
|
|
107
|
+
return false;
|
|
108
|
+
policy.flow = nextFlow;
|
|
109
|
+
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
|
110
|
+
fs.writeFileSync(abs, JSON.stringify(policy, null, 2) + '\n', 'utf8');
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
84
113
|
//# sourceMappingURL=config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/analyzers/flow/config.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDH,wCAiBC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/analyzers/flow/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -47,6 +47,10 @@ interface SnapshotMeta {
|
|
|
47
47
|
readonly generatedAt: string;
|
|
48
48
|
/** Commit the snapshot was produced against, when known. */
|
|
49
49
|
readonly commitSha?: string;
|
|
50
|
+
/** Change-detection digest of the contract's contents — lets a consumer see
|
|
51
|
+
* that a published contract drifted (routes changed) even when the commit or
|
|
52
|
+
* timestamp did not carry the signal. Set by `flow publish`. */
|
|
53
|
+
readonly contentHash?: string;
|
|
50
54
|
}
|
|
51
55
|
export interface ServedContract extends SnapshotMeta {
|
|
52
56
|
readonly side: 'served';
|
|
@@ -58,6 +62,14 @@ export interface ConsumedContract extends SnapshotMeta {
|
|
|
58
62
|
}
|
|
59
63
|
/** The `${method} ${path}` join key both sides meet on. */
|
|
60
64
|
export declare function contractKey(method: string, routePath: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* A short, stable content digest of a served route set. Lets a consumer detect
|
|
67
|
+
* that a published contract drifted (routes added/removed) even when the commit
|
|
68
|
+
* SHA or timestamp did not carry the signal. Non-cryptographic (FNV-1a): this
|
|
69
|
+
* is a change-detection digest, NOT a finding identity, so it deliberately does
|
|
70
|
+
* not route through the fingerprint helpers (Rule 9 governs identity, not this).
|
|
71
|
+
*/
|
|
72
|
+
export declare function servedContentHash(routes: readonly ServedRoute[]): string;
|
|
61
73
|
/**
|
|
62
74
|
* The served inventory: every distinct `(method, path)` this repo serves,
|
|
63
75
|
* deduped via the shared helper (spec wins). Sorted for byte-stable snapshots
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/analyzers/flow/contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAA6C,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpF,4EAA4E;AAC5E,eAAO,MAAM,QAAQ,QAA8B,CAAC;AACpD,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAC7C,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAEjD,wDAAwD;AACxD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,aAAa,GAAG,MAAM,CAAC;CACpD;AAED;;;;wEAIwE;AACxE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,UAAU,YAAY;IACpB,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;IAC1B;wDACoD;IACpD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/analyzers/flow/contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAA6C,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpF,4EAA4E;AAC5E,eAAO,MAAM,QAAQ,QAA8B,CAAC;AACpD,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAC7C,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAEjD,wDAAwD;AACxD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,aAAa,GAAG,MAAM,CAAC;CACpD;AAED;;;;wEAIwE;AACxE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,UAAU,YAAY;IACpB,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;IAC1B;wDACoD;IACpD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;qEAEiE;IACjE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,cAAe,SAAQ,YAAY;IAClD,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,eAAe,EAAE,CAAC;CACtC;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,CAWxE;AAID;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,GAAG,cAAc,CAKxF;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,GAAG,gBAAgB,CAsB5F;AAWD,oEAAoE;AACpE,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,MAAM,CAEjF;AAED,sEAAsE;AACtE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAErF;AAgBD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAG7F;AAED,mEAAmE;AACnE,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAGjG;AAED;oEACoE;AACpE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC,CAElE"}
|
|
@@ -53,6 +53,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
53
53
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
54
|
exports.CONSUMED_SNAPSHOT = exports.SERVED_SNAPSHOT = exports.FLOW_DIR = void 0;
|
|
55
55
|
exports.contractKey = contractKey;
|
|
56
|
+
exports.servedContentHash = servedContentHash;
|
|
56
57
|
exports.buildServedContract = buildServedContract;
|
|
57
58
|
exports.buildConsumedContract = buildConsumedContract;
|
|
58
59
|
exports.writeServedContract = writeServedContract;
|
|
@@ -71,6 +72,25 @@ exports.CONSUMED_SNAPSHOT = 'consumed.json';
|
|
|
71
72
|
function contractKey(method, routePath) {
|
|
72
73
|
return `${method} ${routePath}`;
|
|
73
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* A short, stable content digest of a served route set. Lets a consumer detect
|
|
77
|
+
* that a published contract drifted (routes added/removed) even when the commit
|
|
78
|
+
* SHA or timestamp did not carry the signal. Non-cryptographic (FNV-1a): this
|
|
79
|
+
* is a change-detection digest, NOT a finding identity, so it deliberately does
|
|
80
|
+
* not route through the fingerprint helpers (Rule 9 governs identity, not this).
|
|
81
|
+
*/
|
|
82
|
+
function servedContentHash(routes) {
|
|
83
|
+
const canon = routes
|
|
84
|
+
.map((r) => contractKey(r.method, r.path))
|
|
85
|
+
.sort()
|
|
86
|
+
.join('\n');
|
|
87
|
+
let h = 0x811c9dc5;
|
|
88
|
+
for (let i = 0; i < canon.length; i++) {
|
|
89
|
+
h ^= canon.charCodeAt(i);
|
|
90
|
+
h = Math.imul(h, 0x01000193);
|
|
91
|
+
}
|
|
92
|
+
return (h >>> 0).toString(16).padStart(8, '0');
|
|
93
|
+
}
|
|
74
94
|
// ─── Build (from a flow model) ────────────────────────────────────────────────
|
|
75
95
|
/**
|
|
76
96
|
* The served inventory: every distinct `(method, path)` this repo serves,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../../src/analyzers/flow/contract.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../../src/analyzers/flow/contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flow diagnosis — the "diagnose" surface, folded into `doctor` (there is no
|
|
3
|
+
* standalone `flow doctor`). Where the gate answers "did this PR break an
|
|
4
|
+
* integration?", diagnose answers "what is the current state of the contract?":
|
|
5
|
+
* which client calls do NOT resolve to a served route and why, which served
|
|
6
|
+
* routes nobody consumes, and how the served side is being resolved (the
|
|
7
|
+
* connection-resolution ladder).
|
|
8
|
+
*
|
|
9
|
+
* The output is deliberately agent-legible — `doctor --json` carries the whole
|
|
10
|
+
* `FlowDiagnosis`, so the `dxkit-flow` skill reads it as a thin consumer rather
|
|
11
|
+
* than scraping console prose. Reuses the shared extractor (Rule 2); fail-open
|
|
12
|
+
* (any error → `null`, and doctor simply omits the flow section).
|
|
13
|
+
*/
|
|
14
|
+
import type { FlowTopology } from './setup';
|
|
15
|
+
/** Why a client call did not cleanly bind to a served route. */
|
|
16
|
+
export type UnresolvedReason = 'no-route' | 'external' | 'placeholder-only';
|
|
17
|
+
/** The recommended next step for an unresolved call. `scaffold-resolver`
|
|
18
|
+
* (extend extraction to an unsupported framework) is intentionally NOT emitted
|
|
19
|
+
* here — an un-extracted call is absent, not unresolved; that path needs the
|
|
20
|
+
* extension SDK. */
|
|
21
|
+
export type FlowFixHint = 'add-route' | 'configure-participant' | 'adopt-spec' | 'annotate';
|
|
22
|
+
/** One client call that does not resolve, plus the reason and the suggested fix. */
|
|
23
|
+
export interface UnresolvedCall {
|
|
24
|
+
readonly method: string;
|
|
25
|
+
readonly rawUrl: string;
|
|
26
|
+
readonly path: string | null;
|
|
27
|
+
readonly file: string;
|
|
28
|
+
readonly line: number;
|
|
29
|
+
readonly reason: UnresolvedReason;
|
|
30
|
+
readonly suggestion: FlowFixHint;
|
|
31
|
+
}
|
|
32
|
+
/** A served route no client call binds to — a dead route, or a route consumed
|
|
33
|
+
* only by a repo dxkit cannot see (a cross-repo consumer). */
|
|
34
|
+
export interface UnconsumedRoute {
|
|
35
|
+
readonly method: string;
|
|
36
|
+
readonly path: string;
|
|
37
|
+
readonly file: string;
|
|
38
|
+
readonly line: number;
|
|
39
|
+
}
|
|
40
|
+
/** Which rung of the connection-resolution ladder produced the served set. */
|
|
41
|
+
export type ConnectionRung = 'monorepo' | 'committed-counterpart' | 'configured-participants' | 'unresolved';
|
|
42
|
+
export interface FlowDiagnosis {
|
|
43
|
+
readonly topology: FlowTopology;
|
|
44
|
+
readonly calls: number;
|
|
45
|
+
readonly routes: number;
|
|
46
|
+
readonly resolved: number;
|
|
47
|
+
/** Client calls that do not cleanly bind, each with a reason + suggestion. */
|
|
48
|
+
readonly unresolved: readonly UnresolvedCall[];
|
|
49
|
+
/** Served routes with no consuming call (dead-route / cross-repo candidates). */
|
|
50
|
+
readonly servedUnconsumed: readonly UnconsumedRoute[];
|
|
51
|
+
readonly connection: {
|
|
52
|
+
readonly rung: ConnectionRung;
|
|
53
|
+
readonly note: string;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Diagnose the repo's flow contract. Returns `null` (and doctor omits the flow
|
|
58
|
+
* section) when no flow-capable pack is active, when extraction finds nothing,
|
|
59
|
+
* or on any error.
|
|
60
|
+
*/
|
|
61
|
+
export declare function diagnoseFlow(cwd: string): Promise<FlowDiagnosis | null>;
|
|
62
|
+
//# sourceMappingURL=diagnose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnose.d.ts","sourceRoot":"","sources":["../../../src/analyzers/flow/diagnose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,gEAAgE;AAChE,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,UAAU,GAAG,kBAAkB,CAAC;AAE5E;;;qBAGqB;AACrB,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,uBAAuB,GAAG,YAAY,GAAG,UAAU,CAAC;AAE5F,oFAAoF;AACpF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;CAClC;AAED;+DAC+D;AAC/D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,8EAA8E;AAC9E,MAAM,MAAM,cAAc,GACtB,UAAU,GACV,uBAAuB,GACvB,yBAAyB,GACzB,YAAY,CAAC;AAEjB,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;IAC/C,iFAAiF;IACjF,QAAQ,CAAC,gBAAgB,EAAE,SAAS,eAAe,EAAE,CAAC;IACtD,QAAQ,CAAC,UAAU,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/E;AA2DD;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA2C7E"}
|