@shrkcrft/quality-gates 0.1.0-alpha.18 → 0.1.0-alpha.20
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/dist/gates/arch-gate.d.ts +15 -4
- package/dist/gates/arch-gate.d.ts.map +1 -1
- package/dist/gates/arch-gate.js +61 -11
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/runner/run-gates.d.ts +3 -0
- package/dist/runner/run-gates.d.ts.map +1 -1
- package/dist/runner/run-gates.js +1 -1
- package/dist/schema/arch-gate-options.d.ts +16 -0
- package/dist/schema/arch-gate-options.d.ts.map +1 -0
- package/dist/schema/arch-gate-options.js +1 -0
- package/package.json +10 -10
|
@@ -1,8 +1,19 @@
|
|
|
1
|
+
import type { IArchGateOptions } from '../schema/arch-gate-options.js';
|
|
1
2
|
import type { IGateResult } from '../schema/quality-gate.js';
|
|
2
3
|
/**
|
|
3
|
-
* Architecture-guard gate.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Architecture-guard gate.
|
|
5
|
+
*
|
|
6
|
+
* When a frozen baseline exists and `baselineRelative` is not disabled (the
|
|
7
|
+
* DEFAULT), the gate fails only on NEW architecture errors — violations absent
|
|
8
|
+
* from the baseline — and surfaces the total pre-existing debt as informational.
|
|
9
|
+
* This stops the gate from being a perpetual red on baseline debt the current
|
|
10
|
+
* diff never introduced (an agent learns to ignore a gate that's always red).
|
|
11
|
+
*
|
|
12
|
+
* When no baseline is frozen (or `baselineRelative: false`), it preserves the
|
|
13
|
+
* legacy behavior — fail on ANY error — so nothing regresses for projects that
|
|
14
|
+
* never opted in, and a clean-tree CI demand stays expressible.
|
|
15
|
+
*
|
|
16
|
+
* Warnings never fail the gate; they are reported as `warn`.
|
|
6
17
|
*/
|
|
7
|
-
export declare function archGate(projectRoot: string): IGateResult;
|
|
18
|
+
export declare function archGate(projectRoot: string, options?: IArchGateOptions): IGateResult;
|
|
8
19
|
//# sourceMappingURL=arch-gate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arch-gate.d.ts","sourceRoot":"","sources":["../../src/gates/arch-gate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"arch-gate.d.ts","sourceRoot":"","sources":["../../src/gates/arch-gate.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,WAAW,CA6FzF"}
|
package/dist/gates/arch-gate.js
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
import { runArchCheck } from '@shrkcrft/architecture-guard';
|
|
1
|
+
import { ArchReportStore, diffSnapshots, runArchCheck, snapshotFromReport, violationId, } from '@shrkcrft/architecture-guard';
|
|
2
2
|
/**
|
|
3
|
-
* Architecture-guard gate.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Architecture-guard gate.
|
|
4
|
+
*
|
|
5
|
+
* When a frozen baseline exists and `baselineRelative` is not disabled (the
|
|
6
|
+
* DEFAULT), the gate fails only on NEW architecture errors — violations absent
|
|
7
|
+
* from the baseline — and surfaces the total pre-existing debt as informational.
|
|
8
|
+
* This stops the gate from being a perpetual red on baseline debt the current
|
|
9
|
+
* diff never introduced (an agent learns to ignore a gate that's always red).
|
|
10
|
+
*
|
|
11
|
+
* When no baseline is frozen (or `baselineRelative: false`), it preserves the
|
|
12
|
+
* legacy behavior — fail on ANY error — so nothing regresses for projects that
|
|
13
|
+
* never opted in, and a clean-tree CI demand stays expressible.
|
|
14
|
+
*
|
|
15
|
+
* Warnings never fail the gate; they are reported as `warn`.
|
|
6
16
|
*/
|
|
7
|
-
export function archGate(projectRoot) {
|
|
17
|
+
export function archGate(projectRoot, options = {}) {
|
|
8
18
|
const start = Date.now();
|
|
9
19
|
const report = runArchCheck({ projectRoot });
|
|
10
20
|
if (report.diagnostics.some((d) => d.includes('code-graph store missing'))) {
|
|
@@ -19,18 +29,58 @@ export function archGate(projectRoot) {
|
|
|
19
29
|
}
|
|
20
30
|
const errors = report.countsBySeverity.error;
|
|
21
31
|
const warnings = report.countsBySeverity.warning;
|
|
32
|
+
const baseline = options.baselineRelative === false ? undefined : new ArchReportStore(projectRoot).readBaseline();
|
|
33
|
+
if (baseline) {
|
|
34
|
+
const current = snapshotFromReport(report);
|
|
35
|
+
const delta = diffSnapshots(baseline, current);
|
|
36
|
+
const newIds = new Set(delta.newViolationIds);
|
|
37
|
+
const newViolations = report.violations.filter((v) => newIds.has(violationId(v)));
|
|
38
|
+
const newErrors = newViolations.filter((v) => v.severity === 'error').length;
|
|
39
|
+
const newWarnings = newViolations.filter((v) => v.severity === 'warning').length;
|
|
40
|
+
const baselineErrors = baseline.countsBySeverity.error;
|
|
41
|
+
if (newErrors > 0) {
|
|
42
|
+
return {
|
|
43
|
+
id: 'arch',
|
|
44
|
+
label: 'Architecture',
|
|
45
|
+
status: 'fail',
|
|
46
|
+
message: `${newErrors} NEW architecture error(s) since baseline (baseline debt: ${baselineErrors}, informational).`,
|
|
47
|
+
details: { newErrors, newWarnings, baselineErrors, totalErrors: errors, newViolationIds: delta.newViolationIds },
|
|
48
|
+
nextCommands: ['shrk arch check', 'shrk arch baseline show'],
|
|
49
|
+
durationMs: Date.now() - start,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (newWarnings > 0) {
|
|
53
|
+
return {
|
|
54
|
+
id: 'arch',
|
|
55
|
+
label: 'Architecture',
|
|
56
|
+
status: 'warn',
|
|
57
|
+
message: `${newWarnings} new architecture warning(s) since baseline (baseline debt: ${baselineErrors} error(s), informational).`,
|
|
58
|
+
details: { newWarnings, baselineErrors, totalErrors: errors, totalWarnings: warnings },
|
|
59
|
+
nextCommands: ['shrk arch check'],
|
|
60
|
+
durationMs: Date.now() - start,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
id: 'arch',
|
|
65
|
+
label: 'Architecture',
|
|
66
|
+
status: 'pass',
|
|
67
|
+
message: errors > 0
|
|
68
|
+
? `No NEW architecture violations (baseline debt: ${baselineErrors} error(s), informational).`
|
|
69
|
+
: 'No architecture violations.',
|
|
70
|
+
details: { baselineErrors, totalErrors: errors },
|
|
71
|
+
durationMs: Date.now() - start,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
// No baseline (or baseline-relative disabled): fail on any error (legacy), but
|
|
75
|
+
// hint how to opt into NEW-only gating.
|
|
22
76
|
if (errors > 0) {
|
|
23
77
|
return {
|
|
24
78
|
id: 'arch',
|
|
25
79
|
label: 'Architecture',
|
|
26
80
|
status: 'fail',
|
|
27
81
|
message: `${errors} architecture error(s).`,
|
|
28
|
-
details: {
|
|
29
|
-
|
|
30
|
-
warnings,
|
|
31
|
-
kinds: report.countsByKind,
|
|
32
|
-
},
|
|
33
|
-
nextCommands: ['shrk arch check'],
|
|
82
|
+
details: { errors, warnings, kinds: report.countsByKind },
|
|
83
|
+
nextCommands: ['shrk arch check', 'shrk arch baseline write'],
|
|
34
84
|
durationMs: Date.now() - start,
|
|
35
85
|
};
|
|
36
86
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,qCAAqC,CAAC;AACpD,cAAc,mCAAmC,CAAC;AAClD,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,qCAAqC,CAAC;AACpD,cAAc,mCAAmC,CAAC;AAClD,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type IApiDiffGateOptions } from '../gates/api-diff-gate.js';
|
|
2
|
+
import type { IArchGateOptions } from '../schema/arch-gate-options.js';
|
|
2
3
|
import { type IGraphCyclesGateOptions } from '../gates/graph-cycles-gate.js';
|
|
3
4
|
import { type IGraphUnresolvedGateOptions } from '../gates/graph-unresolved-gate.js';
|
|
4
5
|
import { type IImpactGateOptions } from '../gates/impact-gate.js';
|
|
@@ -8,6 +9,8 @@ import { type IStructuralPatternsGateOptions } from '../gates/structural-pattern
|
|
|
8
9
|
import { type IQualityGateReport } from '../schema/quality-gate.js';
|
|
9
10
|
export interface IRunGatesOptions {
|
|
10
11
|
projectRoot: string;
|
|
12
|
+
/** Optional architecture-gate config (baseline-relative toggle). */
|
|
13
|
+
arch?: IArchGateOptions;
|
|
11
14
|
/** Optional impact-gate config (sinceRef, failOn). */
|
|
12
15
|
impact?: IImpactGateOptions;
|
|
13
16
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-gates.d.ts","sourceRoot":"","sources":["../../src/runner/run-gates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAElF,OAAO,EAAmB,KAAK,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAE9F,OAAO,EAEL,KAAK,2BAA2B,EACjC,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAc,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAEL,KAAK,8BAA8B,EACpC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,yCAAyC;IACzC,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC,6CAA6C;IAC7C,eAAe,CAAC,EAAE,2BAA2B,CAAC;IAC9C,4CAA4C;IAC5C,cAAc,CAAC,EAAE,0BAA0B,CAAC;IAC5C,gDAAgD;IAChD,kBAAkB,CAAC,EAAE,8BAA8B,CAAC;IACpD,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,4BAA4B,CAAC;IAChD,oCAAoC;IACpC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,kBAAkB,CAkD7E"}
|
|
1
|
+
{"version":3,"file":"run-gates.d.ts","sourceRoot":"","sources":["../../src/runner/run-gates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAElF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAmB,KAAK,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAE9F,OAAO,EAEL,KAAK,2BAA2B,EACjC,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAc,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAEL,KAAK,8BAA8B,EACpC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,sDAAsD;IACtD,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,yCAAyC;IACzC,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC,6CAA6C;IAC7C,eAAe,CAAC,EAAE,2BAA2B,CAAC;IAC9C,4CAA4C;IAC5C,cAAc,CAAC,EAAE,0BAA0B,CAAC;IAC5C,gDAAgD;IAChD,kBAAkB,CAAC,EAAE,8BAA8B,CAAC;IACpD,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,4BAA4B,CAAC;IAChD,oCAAoC;IACpC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,kBAAkB,CAkD7E"}
|
package/dist/runner/run-gates.js
CHANGED
|
@@ -40,7 +40,7 @@ export function runQualityGates(options) {
|
|
|
40
40
|
gates.push(graphFreshGate(options.projectRoot));
|
|
41
41
|
}
|
|
42
42
|
if (!disabled.has('arch')) {
|
|
43
|
-
gates.push(archGate(options.projectRoot));
|
|
43
|
+
gates.push(archGate(options.projectRoot, options.arch ?? {}));
|
|
44
44
|
}
|
|
45
45
|
if (!disabled.has('impact')) {
|
|
46
46
|
gates.push(impactGate(options.projectRoot, options.impact ?? {}));
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for the architecture-guard gate.
|
|
3
|
+
*/
|
|
4
|
+
export interface IArchGateOptions {
|
|
5
|
+
/**
|
|
6
|
+
* When true (the DEFAULT) and a frozen baseline exists, the gate fails only on
|
|
7
|
+
* NEW architecture errors (violations absent from the baseline) and surfaces
|
|
8
|
+
* the total pre-existing debt as informational — so the gate isn't a perpetual
|
|
9
|
+
* red on baseline debt the current diff never introduced.
|
|
10
|
+
*
|
|
11
|
+
* Set to false to fail on ANY error regardless of the baseline (the legacy
|
|
12
|
+
* behavior; useful for a clean-tree CI demand).
|
|
13
|
+
*/
|
|
14
|
+
baselineRelative?: boolean;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=arch-gate-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arch-gate-options.d.ts","sourceRoot":"","sources":["../../src/schema/arch-gate-options.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shrkcrft/quality-gates",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.20",
|
|
4
4
|
"description": "SharkCraft quality gates: single aggregator that runs the code-intelligence checks (graph index, boundaries, architecture, impact summary) and emits one pass/fail report. The pre-merge gate for AI-agent-authored changes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "SharkCraft contributors",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "./dist/index.js",
|
|
9
|
-
"types": "./dist/index.d.
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
@@ -43,14 +43,14 @@
|
|
|
43
43
|
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@shrkcrft/core": "^0.1.0-alpha.
|
|
47
|
-
"@shrkcrft/graph": "^0.1.0-alpha.
|
|
48
|
-
"@shrkcrft/architecture-guard": "^0.1.0-alpha.
|
|
49
|
-
"@shrkcrft/impact-engine": "^0.1.0-alpha.
|
|
50
|
-
"@shrkcrft/api-surface-diff": "^0.1.0-alpha.
|
|
51
|
-
"@shrkcrft/boundaries": "^0.1.0-alpha.
|
|
52
|
-
"@shrkcrft/structural-search": "^0.1.0-alpha.
|
|
53
|
-
"@shrkcrft/context-planner": "^0.1.0-alpha.
|
|
46
|
+
"@shrkcrft/core": "^0.1.0-alpha.20",
|
|
47
|
+
"@shrkcrft/graph": "^0.1.0-alpha.20",
|
|
48
|
+
"@shrkcrft/architecture-guard": "^0.1.0-alpha.20",
|
|
49
|
+
"@shrkcrft/impact-engine": "^0.1.0-alpha.20",
|
|
50
|
+
"@shrkcrft/api-surface-diff": "^0.1.0-alpha.20",
|
|
51
|
+
"@shrkcrft/boundaries": "^0.1.0-alpha.20",
|
|
52
|
+
"@shrkcrft/structural-search": "^0.1.0-alpha.20",
|
|
53
|
+
"@shrkcrft/context-planner": "^0.1.0-alpha.20"
|
|
54
54
|
},
|
|
55
55
|
"publishConfig": {
|
|
56
56
|
"access": "public"
|