olympus-ai 4.4.13 → 4.4.15
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/.claude-plugin/plugin.json +1 -1
- package/dist/features/workflow-engine/checkpoint.d.ts.map +1 -1
- package/dist/features/workflow-engine/checkpoint.js +33 -6
- package/dist/features/workflow-engine/checkpoint.js.map +1 -1
- package/dist/features/workflow-engine/construction/executor.d.ts +38 -3
- package/dist/features/workflow-engine/construction/executor.d.ts.map +1 -1
- package/dist/features/workflow-engine/construction/executor.js +245 -3
- package/dist/features/workflow-engine/construction/executor.js.map +1 -1
- package/dist/features/workflow-engine/construction/regression-baseline.d.ts +76 -0
- package/dist/features/workflow-engine/construction/regression-baseline.d.ts.map +1 -0
- package/dist/features/workflow-engine/construction/regression-baseline.js +274 -0
- package/dist/features/workflow-engine/construction/regression-baseline.js.map +1 -0
- package/dist/features/workflow-engine/construction/regression-categorizer.d.ts +44 -0
- package/dist/features/workflow-engine/construction/regression-categorizer.d.ts.map +1 -0
- package/dist/features/workflow-engine/construction/regression-categorizer.js +54 -0
- package/dist/features/workflow-engine/construction/regression-categorizer.js.map +1 -0
- package/dist/features/workflow-engine/construction/validators/index.d.ts +6 -0
- package/dist/features/workflow-engine/construction/validators/index.d.ts.map +1 -0
- package/dist/features/workflow-engine/construction/validators/index.js +4 -0
- package/dist/features/workflow-engine/construction/validators/index.js.map +1 -0
- package/dist/features/workflow-engine/construction/validators/pipeline.d.ts +10 -0
- package/dist/features/workflow-engine/construction/validators/pipeline.d.ts.map +1 -0
- package/dist/features/workflow-engine/construction/validators/pipeline.js +84 -0
- package/dist/features/workflow-engine/construction/validators/pipeline.js.map +1 -0
- package/dist/features/workflow-engine/construction/validators/quality-patterns.d.ts +18 -0
- package/dist/features/workflow-engine/construction/validators/quality-patterns.d.ts.map +1 -0
- package/dist/features/workflow-engine/construction/validators/quality-patterns.js +245 -0
- package/dist/features/workflow-engine/construction/validators/quality-patterns.js.map +1 -0
- package/dist/features/workflow-engine/construction/validators/quality-validator.d.ts +3 -0
- package/dist/features/workflow-engine/construction/validators/quality-validator.d.ts.map +1 -0
- package/dist/features/workflow-engine/construction/validators/quality-validator.js +132 -0
- package/dist/features/workflow-engine/construction/validators/quality-validator.js.map +1 -0
- package/dist/features/workflow-engine/construction/validators/types.d.ts +26 -0
- package/dist/features/workflow-engine/construction/validators/types.d.ts.map +1 -0
- package/dist/features/workflow-engine/construction/validators/types.js +2 -0
- package/dist/features/workflow-engine/construction/validators/types.js.map +1 -0
- package/dist/features/workflow-engine/index.d.ts +3 -1
- package/dist/features/workflow-engine/index.d.ts.map +1 -1
- package/dist/features/workflow-engine/index.js +1 -0
- package/dist/features/workflow-engine/index.js.map +1 -1
- package/dist/features/workflow-engine/phase-types.d.ts +73 -1
- package/dist/features/workflow-engine/phase-types.d.ts.map +1 -1
- package/dist/hooks/olympus-hooks.cjs +334 -280
- package/dist/hooks/registry.d.ts +18 -0
- package/dist/hooks/registry.d.ts.map +1 -1
- package/dist/hooks/registry.js +18 -0
- package/dist/hooks/registry.js.map +1 -1
- package/dist/installer/index.d.ts +1 -1
- package/dist/installer/index.js +1 -1
- package/package.json +1 -1
- package/resources/agents/frontend-engineer-high.md +12 -0
- package/resources/agents/olympian-high.md +77 -1
- package/resources/agents/olympian.md +31 -7
- package/resources/claude-md.md +44 -0
- package/resources/config/risk-keywords.json +5 -0
- package/resources/rules/common/pathway-behaviors.md +100 -0
- package/resources/rules/common/terminal-formatting.md +161 -0
- package/resources/rules/construction/build-and-test.md +58 -0
- package/resources/rules/construction/code-generation.md +26 -5
- package/resources/rules/construction/test-generation.md +82 -0
- package/resources/skills/continue/SKILL.md +4 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression Baseline Module
|
|
3
|
+
*
|
|
4
|
+
* Owns all I/O-touching regression logic: capturing a pre-unit baseline by running
|
|
5
|
+
* the project's test suite, comparing results against a prior baseline, and writing
|
|
6
|
+
* structured regression reports to disk.
|
|
7
|
+
*
|
|
8
|
+
* Pure in-memory functions (compareAgainstBaseline) deliberately contain no I/O so
|
|
9
|
+
* they remain fast and testable without mocking.
|
|
10
|
+
*/
|
|
11
|
+
import type { RegressionBaseline, RegressionReport, RegressionCategory } from '../phase-types.js';
|
|
12
|
+
export type { RegressionCategory };
|
|
13
|
+
/**
|
|
14
|
+
* Structured diff produced by compareAgainstBaseline.
|
|
15
|
+
* Contains newly introduced failures, newly fixed tests, and significant timing changes.
|
|
16
|
+
*/
|
|
17
|
+
export interface RegressionBaselineDiff {
|
|
18
|
+
new_failures: Array<{
|
|
19
|
+
name: string;
|
|
20
|
+
filePath: string;
|
|
21
|
+
}>;
|
|
22
|
+
new_passes: Array<{
|
|
23
|
+
name: string;
|
|
24
|
+
filePath: string;
|
|
25
|
+
}>;
|
|
26
|
+
timing_changes: Array<{
|
|
27
|
+
name: string;
|
|
28
|
+
before_ms: number;
|
|
29
|
+
after_ms: number;
|
|
30
|
+
delta_ms: number;
|
|
31
|
+
}>;
|
|
32
|
+
computed_at: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Run the project test suite and capture a baseline snapshot of all test results.
|
|
36
|
+
*
|
|
37
|
+
* Writes the result to `aidlc-docs/{workflowId}/construction/regression-baseline.json`.
|
|
38
|
+
* A non-zero exit code from the test runner is treated as expected — the output is still
|
|
39
|
+
* parsed and captured.
|
|
40
|
+
*
|
|
41
|
+
* @param projectPath - Absolute path to the project root.
|
|
42
|
+
* @param workflowId - AIDLC workflow identifier (used to build output path).
|
|
43
|
+
* @param testCommand - Shell command to invoke the test suite (e.g. `npm test`).
|
|
44
|
+
*/
|
|
45
|
+
export declare function captureBaseline(projectPath: string, workflowId: string, testCommand: string): Promise<RegressionBaseline>;
|
|
46
|
+
/**
|
|
47
|
+
* Compare a prior baseline against a new set of test results to produce a structured diff.
|
|
48
|
+
*
|
|
49
|
+
* Pure in-memory — no I/O. Completes in <5 s for 1 000 tests via O(1) Map lookups.
|
|
50
|
+
*
|
|
51
|
+
* Classification rules:
|
|
52
|
+
* - new_failures: baseline was `passed` or `skipped`, current is `failed`
|
|
53
|
+
* - new_passes: baseline was `failed`, current is `passed`
|
|
54
|
+
* - timing_changes: both runs have the test and |delta| > 100 ms
|
|
55
|
+
*
|
|
56
|
+
* @param baseline - Previously captured RegressionBaseline.
|
|
57
|
+
* @param currentResults - Test results from the current run.
|
|
58
|
+
*/
|
|
59
|
+
export declare function compareAgainstBaseline(baseline: RegressionBaseline, currentResults: Array<{
|
|
60
|
+
name: string;
|
|
61
|
+
filePath: string;
|
|
62
|
+
status: 'passed' | 'failed' | 'skipped';
|
|
63
|
+
duration_ms: number;
|
|
64
|
+
}>): RegressionBaselineDiff;
|
|
65
|
+
/**
|
|
66
|
+
* Write a human-readable regression report markdown file.
|
|
67
|
+
*
|
|
68
|
+
* Output path: `aidlc-docs/{workflowId}/construction/{unitId}/testing/regression-report.md`
|
|
69
|
+
*
|
|
70
|
+
* @param projectPath - Absolute path to the project root.
|
|
71
|
+
* @param workflowId - AIDLC workflow identifier.
|
|
72
|
+
* @param unitId - Unit identifier (e.g. `u-001-core-types`).
|
|
73
|
+
* @param report - The RegressionReport object to render.
|
|
74
|
+
*/
|
|
75
|
+
export declare function writeRegressionReport(projectPath: string, workflowId: string, unitId: string, report: RegressionReport): Promise<void>;
|
|
76
|
+
//# sourceMappingURL=regression-baseline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regression-baseline.d.ts","sourceRoot":"","sources":["../../../../src/features/workflow-engine/construction/regression-baseline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAElG,YAAY,EAAE,kBAAkB,EAAE,CAAC;AASnC;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,cAAc,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/F,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CAkD7B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,kBAAkB,EAC5B,cAAc,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,GACtH,sBAAsB,CAiDxB;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,IAAI,CAAC,CAuCf"}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression Baseline Module
|
|
3
|
+
*
|
|
4
|
+
* Owns all I/O-touching regression logic: capturing a pre-unit baseline by running
|
|
5
|
+
* the project's test suite, comparing results against a prior baseline, and writing
|
|
6
|
+
* structured regression reports to disk.
|
|
7
|
+
*
|
|
8
|
+
* Pure in-memory functions (compareAgainstBaseline) deliberately contain no I/O so
|
|
9
|
+
* they remain fast and testable without mocking.
|
|
10
|
+
*/
|
|
11
|
+
import fs from 'fs-extra';
|
|
12
|
+
import path from 'path';
|
|
13
|
+
import { execSync } from 'child_process';
|
|
14
|
+
/**
|
|
15
|
+
* Run the project test suite and capture a baseline snapshot of all test results.
|
|
16
|
+
*
|
|
17
|
+
* Writes the result to `aidlc-docs/{workflowId}/construction/regression-baseline.json`.
|
|
18
|
+
* A non-zero exit code from the test runner is treated as expected — the output is still
|
|
19
|
+
* parsed and captured.
|
|
20
|
+
*
|
|
21
|
+
* @param projectPath - Absolute path to the project root.
|
|
22
|
+
* @param workflowId - AIDLC workflow identifier (used to build output path).
|
|
23
|
+
* @param testCommand - Shell command to invoke the test suite (e.g. `npm test`).
|
|
24
|
+
*/
|
|
25
|
+
export async function captureBaseline(projectPath, workflowId, testCommand) {
|
|
26
|
+
const constructionDir = path.join(projectPath, 'aidlc-docs', workflowId, 'construction');
|
|
27
|
+
await fs.ensureDir(constructionDir);
|
|
28
|
+
const framework = detectFramework(testCommand);
|
|
29
|
+
let stdout = '';
|
|
30
|
+
let stderr = '';
|
|
31
|
+
try {
|
|
32
|
+
const result = execSync(testCommand, {
|
|
33
|
+
cwd: projectPath,
|
|
34
|
+
encoding: 'utf-8',
|
|
35
|
+
stdio: 'pipe',
|
|
36
|
+
});
|
|
37
|
+
stdout = result;
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
// execSync throws when exit code != 0; extract captured output from the error object
|
|
41
|
+
const execError = err;
|
|
42
|
+
stdout = execError.stdout ?? '';
|
|
43
|
+
stderr = execError.stderr ?? '';
|
|
44
|
+
}
|
|
45
|
+
const rawOutput = stdout || stderr;
|
|
46
|
+
const tests = parseTestOutput(rawOutput, framework);
|
|
47
|
+
const passed = tests.filter(t => t.status === 'passed').length;
|
|
48
|
+
const failed = tests.filter(t => t.status === 'failed').length;
|
|
49
|
+
const skipped = tests.filter(t => t.status === 'skipped').length;
|
|
50
|
+
const baseline = {
|
|
51
|
+
tests: tests.map(t => ({
|
|
52
|
+
name: t.name,
|
|
53
|
+
filePath: t.filePath,
|
|
54
|
+
status: t.status,
|
|
55
|
+
duration_ms: t.duration_ms,
|
|
56
|
+
})),
|
|
57
|
+
captured_at: new Date().toISOString(),
|
|
58
|
+
test_command: testCommand,
|
|
59
|
+
framework,
|
|
60
|
+
total: tests.length,
|
|
61
|
+
passed,
|
|
62
|
+
failed,
|
|
63
|
+
skipped,
|
|
64
|
+
};
|
|
65
|
+
const baselinePath = path.join(constructionDir, 'regression-baseline.json');
|
|
66
|
+
await fs.writeJson(baselinePath, baseline, { spaces: 2 });
|
|
67
|
+
return baseline;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Compare a prior baseline against a new set of test results to produce a structured diff.
|
|
71
|
+
*
|
|
72
|
+
* Pure in-memory — no I/O. Completes in <5 s for 1 000 tests via O(1) Map lookups.
|
|
73
|
+
*
|
|
74
|
+
* Classification rules:
|
|
75
|
+
* - new_failures: baseline was `passed` or `skipped`, current is `failed`
|
|
76
|
+
* - new_passes: baseline was `failed`, current is `passed`
|
|
77
|
+
* - timing_changes: both runs have the test and |delta| > 100 ms
|
|
78
|
+
*
|
|
79
|
+
* @param baseline - Previously captured RegressionBaseline.
|
|
80
|
+
* @param currentResults - Test results from the current run.
|
|
81
|
+
*/
|
|
82
|
+
export function compareAgainstBaseline(baseline, currentResults) {
|
|
83
|
+
// Build O(1) lookup map from baseline
|
|
84
|
+
const baselineMap = new Map();
|
|
85
|
+
for (const t of baseline.tests) {
|
|
86
|
+
baselineMap.set(t.name, t);
|
|
87
|
+
}
|
|
88
|
+
const new_failures = [];
|
|
89
|
+
const new_passes = [];
|
|
90
|
+
const timing_changes = [];
|
|
91
|
+
for (const current of currentResults) {
|
|
92
|
+
const baselineEntry = baselineMap.get(current.name);
|
|
93
|
+
if (!baselineEntry) {
|
|
94
|
+
if (current.status === 'failed') {
|
|
95
|
+
new_failures.push({ name: current.name, filePath: current.filePath });
|
|
96
|
+
}
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if ((baselineEntry.status === 'passed' || baselineEntry.status === 'skipped') &&
|
|
100
|
+
current.status === 'failed') {
|
|
101
|
+
new_failures.push({ name: current.name, filePath: current.filePath });
|
|
102
|
+
}
|
|
103
|
+
if (baselineEntry.status === 'failed' && current.status === 'passed') {
|
|
104
|
+
new_passes.push({ name: current.name, filePath: current.filePath });
|
|
105
|
+
}
|
|
106
|
+
const delta = Math.abs(current.duration_ms - baselineEntry.duration_ms);
|
|
107
|
+
if (delta > 100) {
|
|
108
|
+
timing_changes.push({
|
|
109
|
+
name: current.name,
|
|
110
|
+
before_ms: baselineEntry.duration_ms,
|
|
111
|
+
after_ms: current.duration_ms,
|
|
112
|
+
delta_ms: delta,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
new_failures,
|
|
118
|
+
new_passes,
|
|
119
|
+
timing_changes,
|
|
120
|
+
computed_at: new Date().toISOString(),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Write a human-readable regression report markdown file.
|
|
125
|
+
*
|
|
126
|
+
* Output path: `aidlc-docs/{workflowId}/construction/{unitId}/testing/regression-report.md`
|
|
127
|
+
*
|
|
128
|
+
* @param projectPath - Absolute path to the project root.
|
|
129
|
+
* @param workflowId - AIDLC workflow identifier.
|
|
130
|
+
* @param unitId - Unit identifier (e.g. `u-001-core-types`).
|
|
131
|
+
* @param report - The RegressionReport object to render.
|
|
132
|
+
*/
|
|
133
|
+
export async function writeRegressionReport(projectPath, workflowId, unitId, report) {
|
|
134
|
+
const testingDir = path.join(projectPath, 'aidlc-docs', workflowId, 'construction', unitId, 'testing');
|
|
135
|
+
await fs.ensureDir(testingDir);
|
|
136
|
+
const reportPath = path.join(testingDir, 'regression-report.md');
|
|
137
|
+
const failureRows = report.failures
|
|
138
|
+
.map(f => `| ${f.test_name} | ${f.file_path} | ${f.category} | ${f.rationale} |`)
|
|
139
|
+
.join('\n');
|
|
140
|
+
const content = `# Regression Report
|
|
141
|
+
|
|
142
|
+
**Workflow ID**: ${report.workflow_id}
|
|
143
|
+
**Unit ID**: ${report.unit_id}
|
|
144
|
+
**Baseline Captured At**: ${report.baseline_captured_at}
|
|
145
|
+
**Compared At**: ${report.compared_at}
|
|
146
|
+
|
|
147
|
+
## Summary
|
|
148
|
+
|
|
149
|
+
| Metric | Count |
|
|
150
|
+
|---|---|
|
|
151
|
+
| Total Regressions | ${report.total_regressions} |
|
|
152
|
+
| Legitimate Regressions | ${report.legitimate_regressions} |
|
|
153
|
+
|
|
154
|
+
## Failures
|
|
155
|
+
|
|
156
|
+
| Test Name | File Path | Category | Rationale |
|
|
157
|
+
|---|---|---|---|
|
|
158
|
+
${failureRows || '| _No failures_ | | | |'}
|
|
159
|
+
`;
|
|
160
|
+
await fs.writeFile(reportPath, content, 'utf-8');
|
|
161
|
+
}
|
|
162
|
+
function detectFramework(testCommand) {
|
|
163
|
+
if (testCommand.includes('vitest'))
|
|
164
|
+
return 'vitest';
|
|
165
|
+
if (testCommand.includes('jest'))
|
|
166
|
+
return 'jest';
|
|
167
|
+
return 'unknown';
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Parse raw test runner output into TestResult objects.
|
|
171
|
+
*
|
|
172
|
+
* Two strategies:
|
|
173
|
+
* 1. JSON reporter path (vitest/jest `--json`): triggered when output contains `"numPassedTests"`.
|
|
174
|
+
* Parses `testResults[*].assertionResults`.
|
|
175
|
+
* 2. Plain-text fallback: line-by-line scan for TAP-style and Unicode pass/fail markers.
|
|
176
|
+
*/
|
|
177
|
+
function parseTestOutput(output, _framework) {
|
|
178
|
+
// Strategy 1: JSON reporter format — numPassedTests is the canonical sentinel field
|
|
179
|
+
if (output.includes('"numPassedTests"')) {
|
|
180
|
+
try {
|
|
181
|
+
// JSON may be prefixed with non-JSON noise; start from first `{`
|
|
182
|
+
const jsonStart = output.indexOf('{');
|
|
183
|
+
if (jsonStart !== -1) {
|
|
184
|
+
const parsed = JSON.parse(output.slice(jsonStart));
|
|
185
|
+
const results = [];
|
|
186
|
+
if (Array.isArray(parsed.testResults)) {
|
|
187
|
+
for (const suite of parsed.testResults) {
|
|
188
|
+
const filePath = suite.testFilePath ?? suite.name ?? 'unknown';
|
|
189
|
+
for (const assertion of (suite.assertionResults ?? [])) {
|
|
190
|
+
results.push({
|
|
191
|
+
name: assertion.fullName ?? assertion.title ?? 'unnamed',
|
|
192
|
+
filePath,
|
|
193
|
+
status: mapJsonStatus(assertion.status),
|
|
194
|
+
duration_ms: assertion.duration ?? 0,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (results.length > 0)
|
|
200
|
+
return results;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// JSON parse failed — fall through to plain-text parser
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Strategy 2: plain-text line scanner
|
|
208
|
+
return parsePlainTextOutput(output);
|
|
209
|
+
}
|
|
210
|
+
function mapJsonStatus(status) {
|
|
211
|
+
if (status === 'passed')
|
|
212
|
+
return 'passed';
|
|
213
|
+
if (status === 'failed')
|
|
214
|
+
return 'failed';
|
|
215
|
+
return 'skipped';
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Plain-text fallback parser for TAP-like or human-readable test output.
|
|
219
|
+
*
|
|
220
|
+
* Pass markers: ✓ √ ok N -
|
|
221
|
+
* Fail markers: ✗ × not ok N -
|
|
222
|
+
* Duration: (NNNms) or NNNms suffix
|
|
223
|
+
* File context: nearest preceding `FAIL src/...` or `PASS src/...` line
|
|
224
|
+
*/
|
|
225
|
+
function parsePlainTextOutput(output) {
|
|
226
|
+
const lines = output.split('\n');
|
|
227
|
+
const results = [];
|
|
228
|
+
let currentFilePath = 'unknown';
|
|
229
|
+
for (const line of lines) {
|
|
230
|
+
const trimmed = line.trim();
|
|
231
|
+
// Update file context from suite headers like `FAIL src/foo.test.ts`
|
|
232
|
+
const fileHeaderMatch = trimmed.match(/^(?:FAIL|PASS)\s+(src\S+)/);
|
|
233
|
+
if (fileHeaderMatch) {
|
|
234
|
+
currentFilePath = fileHeaderMatch[1];
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
// Pass patterns: ✓ name (Nms) | ok N - name
|
|
238
|
+
const passPatterns = [
|
|
239
|
+
/^[✓√]\s+(.+?)(?:\s+\((\d+)ms\)|\s+(\d+)ms)?$/,
|
|
240
|
+
/^ok\s+\d+\s+-\s+(.+?)(?:\s+#.*)?(?:\s+(\d+)ms)?$/,
|
|
241
|
+
];
|
|
242
|
+
// Fail patterns: ✗ name (Nms) | not ok N - name
|
|
243
|
+
const failPatterns = [
|
|
244
|
+
/^[✗×]\s+(.+?)(?:\s+\((\d+)ms\)|\s+(\d+)ms)?$/,
|
|
245
|
+
/^not ok\s+\d+\s+-\s+(.+?)(?:\s+#.*)?(?:\s+(\d+)ms)?$/,
|
|
246
|
+
];
|
|
247
|
+
let matched = false;
|
|
248
|
+
for (const pattern of passPatterns) {
|
|
249
|
+
const m = trimmed.match(pattern);
|
|
250
|
+
if (m) {
|
|
251
|
+
results.push({ name: m[1].trim(), filePath: currentFilePath, status: 'passed', duration_ms: parseMs(m[2] ?? m[3]) });
|
|
252
|
+
matched = true;
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (!matched) {
|
|
257
|
+
for (const pattern of failPatterns) {
|
|
258
|
+
const m = trimmed.match(pattern);
|
|
259
|
+
if (m) {
|
|
260
|
+
results.push({ name: m[1].trim(), filePath: currentFilePath, status: 'failed', duration_ms: parseMs(m[2] ?? m[3]) });
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return results;
|
|
267
|
+
}
|
|
268
|
+
function parseMs(value) {
|
|
269
|
+
if (!value)
|
|
270
|
+
return 0;
|
|
271
|
+
const n = parseInt(value, 10);
|
|
272
|
+
return isNaN(n) ? 0 : n;
|
|
273
|
+
}
|
|
274
|
+
//# sourceMappingURL=regression-baseline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regression-baseline.js","sourceRoot":"","sources":["../../../../src/features/workflow-engine/construction/regression-baseline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression Categorizer
|
|
3
|
+
*
|
|
4
|
+
* Pure logic module (no I/O) for classifying test failures into one of four
|
|
5
|
+
* RegressionCategory values and computing summary counts for ConstructionUnitProgress.
|
|
6
|
+
*/
|
|
7
|
+
import type { RegressionCategory } from '../phase-types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Classify a single failing test into one of four regression categories.
|
|
10
|
+
*
|
|
11
|
+
* Decision tree (evaluated in this exact order):
|
|
12
|
+
* 1. pre_existing_failure — baseline had the test already failing
|
|
13
|
+
* 2. flaky — at least one re-run passed without code changes
|
|
14
|
+
* 3. intentional_change — test did not exist in the baseline (new test)
|
|
15
|
+
* 4. legitimate_regression — baseline was passing/skipped, all re-runs also failed
|
|
16
|
+
*
|
|
17
|
+
* @param testName - The failing test name (used for traceability only).
|
|
18
|
+
* @param baselineEntry - Baseline snapshot entry, or null if the test is new.
|
|
19
|
+
* @param rerunResults - Results from up to 2 re-runs without code changes.
|
|
20
|
+
*/
|
|
21
|
+
export declare function categorizeFailure(_testName: string, baselineEntry: {
|
|
22
|
+
status: 'passed' | 'failed' | 'skipped';
|
|
23
|
+
} | null, rerunResults: Array<{
|
|
24
|
+
status: 'passed' | 'failed' | 'skipped';
|
|
25
|
+
}>): RegressionCategory;
|
|
26
|
+
export declare function checkFlakyThreshold(categorizedFailures: RegressionCategory[], warnThresholdPct?: number): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Compute the regressions_count and flaky_count values for ConstructionUnitProgress.
|
|
29
|
+
*
|
|
30
|
+
* Only `legitimate_regression` contributes to regressions_count.
|
|
31
|
+
* Only `flaky` contributes to flaky_count.
|
|
32
|
+
* `pre_existing_failure` and `intentional_change` are excluded from both.
|
|
33
|
+
*
|
|
34
|
+
* @param failures - Newly failing tests (parallel to categories).
|
|
35
|
+
* @param categories - RegressionCategory for each failure entry.
|
|
36
|
+
*/
|
|
37
|
+
export declare function buildRegressionSummary(_failures: Array<{
|
|
38
|
+
test_name: string;
|
|
39
|
+
file_path: string;
|
|
40
|
+
}>, categories: RegressionCategory[]): {
|
|
41
|
+
regressions_count: number;
|
|
42
|
+
flaky_count: number;
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=regression-categorizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regression-categorizer.d.ts","sourceRoot":"","sources":["../../../../src/features/workflow-engine/construction/regression-categorizer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE;IAAE,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAA;CAAE,GAAG,IAAI,EACjE,YAAY,EAAE,KAAK,CAAC;IAAE,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAA;CAAE,CAAC,GAC/D,kBAAkB,CAcpB;AAED,wBAAgB,mBAAmB,CACjC,mBAAmB,EAAE,kBAAkB,EAAE,EACzC,gBAAgB,SAAM,GACrB,OAAO,CAKT;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,EAC1D,UAAU,EAAE,kBAAkB,EAAE,GAC/B;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAIpD"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression Categorizer
|
|
3
|
+
*
|
|
4
|
+
* Pure logic module (no I/O) for classifying test failures into one of four
|
|
5
|
+
* RegressionCategory values and computing summary counts for ConstructionUnitProgress.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Classify a single failing test into one of four regression categories.
|
|
9
|
+
*
|
|
10
|
+
* Decision tree (evaluated in this exact order):
|
|
11
|
+
* 1. pre_existing_failure — baseline had the test already failing
|
|
12
|
+
* 2. flaky — at least one re-run passed without code changes
|
|
13
|
+
* 3. intentional_change — test did not exist in the baseline (new test)
|
|
14
|
+
* 4. legitimate_regression — baseline was passing/skipped, all re-runs also failed
|
|
15
|
+
*
|
|
16
|
+
* @param testName - The failing test name (used for traceability only).
|
|
17
|
+
* @param baselineEntry - Baseline snapshot entry, or null if the test is new.
|
|
18
|
+
* @param rerunResults - Results from up to 2 re-runs without code changes.
|
|
19
|
+
*/
|
|
20
|
+
export function categorizeFailure(_testName, baselineEntry, rerunResults) {
|
|
21
|
+
if (baselineEntry !== null && baselineEntry.status === 'failed') {
|
|
22
|
+
return 'pre_existing_failure';
|
|
23
|
+
}
|
|
24
|
+
if (rerunResults.some(r => r.status === 'passed')) {
|
|
25
|
+
return 'flaky';
|
|
26
|
+
}
|
|
27
|
+
if (baselineEntry === null) {
|
|
28
|
+
return 'intentional_change';
|
|
29
|
+
}
|
|
30
|
+
return 'legitimate_regression';
|
|
31
|
+
}
|
|
32
|
+
export function checkFlakyThreshold(categorizedFailures, warnThresholdPct = 0.2) {
|
|
33
|
+
const total = categorizedFailures.length;
|
|
34
|
+
if (total === 0)
|
|
35
|
+
return false;
|
|
36
|
+
const flakyCount = categorizedFailures.filter(c => c === 'flaky').length;
|
|
37
|
+
return flakyCount / total > warnThresholdPct;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Compute the regressions_count and flaky_count values for ConstructionUnitProgress.
|
|
41
|
+
*
|
|
42
|
+
* Only `legitimate_regression` contributes to regressions_count.
|
|
43
|
+
* Only `flaky` contributes to flaky_count.
|
|
44
|
+
* `pre_existing_failure` and `intentional_change` are excluded from both.
|
|
45
|
+
*
|
|
46
|
+
* @param failures - Newly failing tests (parallel to categories).
|
|
47
|
+
* @param categories - RegressionCategory for each failure entry.
|
|
48
|
+
*/
|
|
49
|
+
export function buildRegressionSummary(_failures, categories) {
|
|
50
|
+
const regressions_count = categories.filter(c => c === 'legitimate_regression').length;
|
|
51
|
+
const flaky_count = categories.filter(c => c === 'flaky').length;
|
|
52
|
+
return { regressions_count, flaky_count };
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=regression-categorizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regression-categorizer.js","sourceRoot":"","sources":["../../../../src/features/workflow-engine/construction/regression-categorizer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAC/B,SAAiB,EACjB,aAAiE,EACjE,YAAgE;IAEhE,IAAI,aAAa,KAAK,IAAI,IAAI,aAAa,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAChE,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,EAAE,CAAC;QAClD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,OAAO,uBAAuB,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,mBAAyC,EACzC,gBAAgB,GAAG,GAAG;IAEtB,MAAM,KAAK,GAAG,mBAAmB,CAAC,MAAM,CAAC;IACzC,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9B,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC;IACzE,OAAO,UAAU,GAAG,KAAK,GAAG,gBAAgB,CAAC;AAC/C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,sBAAsB,CACpC,SAA0D,EAC1D,UAAgC;IAEhC,MAAM,iBAAiB,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,uBAAuB,CAAC,CAAC,MAAM,CAAC;IACvF,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC;IACjE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { ValidatorName, ValidatorConfig, ValidatorRiskTier, RiskKeywordConfig, PipelineResult, ValidatorFn, } from './types.js';
|
|
2
|
+
export { runValidationPipeline, shouldSkipValidator, applyAllowFailures, updateCheckpointForValidator, } from './pipeline.js';
|
|
3
|
+
export { createQualityValidator } from './quality-validator.js';
|
|
4
|
+
export { detectAntiPatterns, calculateNegativeCaseRatio, } from './quality-patterns.js';
|
|
5
|
+
export type { AntiPatternCategory, AntiPatternRule, NegativeCaseResult, } from './quality-patterns.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/workflow-engine/construction/validators/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,EAClB,4BAA4B,GAC7B,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,OAAO,EACL,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,kBAAkB,GACnB,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { runValidationPipeline, shouldSkipValidator, applyAllowFailures, updateCheckpointForValidator, } from './pipeline.js';
|
|
2
|
+
export { createQualityValidator } from './quality-validator.js';
|
|
3
|
+
export { detectAntiPatterns, calculateNegativeCaseRatio, } from './quality-patterns.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/features/workflow-engine/construction/validators/index.ts"],"names":[],"mappings":"AASA,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,EAClB,4BAA4B,GAC7B,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,OAAO,EACL,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ValidatorResult, ValidatorStatus } from '../../phase-types.js';
|
|
2
|
+
import type { ValidatorName, ValidatorFn, ValidatorConfig, PipelineResult } from './types.js';
|
|
3
|
+
export declare function runValidationPipeline(validators: Map<ValidatorName, ValidatorFn>, config: ValidatorConfig): Promise<PipelineResult>;
|
|
4
|
+
export declare function shouldSkipValidator(name: ValidatorName, config: ValidatorConfig): {
|
|
5
|
+
skip: boolean;
|
|
6
|
+
reason?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function applyAllowFailures(result: ValidatorResult): ValidatorResult;
|
|
9
|
+
export declare function updateCheckpointForValidator(projectPath: string, workflowId: string, unitId: string, validatorName: ValidatorName, status: ValidatorStatus, coveragePercentage?: number): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../../../../src/features/workflow-engine/construction/validators/pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAqC,MAAM,sBAAsB,CAAC;AAChH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAa9F,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,GAAG,CAAC,aAAa,EAAE,WAAW,CAAC,EAC3C,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,cAAc,CAAC,CAuCzB;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,eAAe,GACtB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAqBpC;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe,GAAG,eAAe,CAM3E;AAED,wBAAsB,4BAA4B,CAChD,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,eAAe,EACvB,kBAAkB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,IAAI,CAAC,CAmBf"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { loadCheckpoint, saveCheckpoint } from '../../checkpoint.js';
|
|
2
|
+
const PIPELINE_ORDER = ['quality', 'mutation', 'traceability', 'contract', 'coverage'];
|
|
3
|
+
const VALIDATOR_FIELD_MAP = {
|
|
4
|
+
quality: 'quality_validation_status',
|
|
5
|
+
mutation: 'mutation_validation_status',
|
|
6
|
+
traceability: 'traceability_status',
|
|
7
|
+
contract: 'contract_validation_status',
|
|
8
|
+
coverage: 'coverage_status',
|
|
9
|
+
};
|
|
10
|
+
export async function runValidationPipeline(validators, config) {
|
|
11
|
+
const results = [];
|
|
12
|
+
for (const name of PIPELINE_ORDER) {
|
|
13
|
+
const fn = validators.get(name);
|
|
14
|
+
if (!fn) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
let result;
|
|
18
|
+
try {
|
|
19
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), config.timeoutBudgetMs));
|
|
20
|
+
result = await Promise.race([fn(config), timeoutPromise]);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
const isTimeout = err instanceof Error && err.message === 'timeout';
|
|
24
|
+
const errorFinding = {
|
|
25
|
+
id: `${name}-error`,
|
|
26
|
+
severity: 'error',
|
|
27
|
+
category: isTimeout ? 'timeout' : 'runtime-error',
|
|
28
|
+
message: isTimeout
|
|
29
|
+
? `Validator '${name}' exceeded timeout of ${config.timeoutBudgetMs}ms`
|
|
30
|
+
: `Validator '${name}' threw an error: ${err instanceof Error ? err.message : String(err)}`,
|
|
31
|
+
};
|
|
32
|
+
console.error(`[ValidatorPipeline] ${name} validator failed:`, err);
|
|
33
|
+
result = {
|
|
34
|
+
status: isTimeout ? 'timeout' : 'failed',
|
|
35
|
+
findings: [errorFinding],
|
|
36
|
+
artifactPath: '',
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
results.push({ validator: name, result });
|
|
40
|
+
}
|
|
41
|
+
return { results };
|
|
42
|
+
}
|
|
43
|
+
export function shouldSkipValidator(name, config) {
|
|
44
|
+
if (name === 'mutation') {
|
|
45
|
+
const criticalKeywords = [
|
|
46
|
+
'auth', 'payment', 'security', 'encrypt', 'token',
|
|
47
|
+
'credential', 'password', 'session', 'permission',
|
|
48
|
+
];
|
|
49
|
+
const hasCritical = config.unitFiles.some(f => criticalKeywords.some(k => f.toLowerCase().includes(k)));
|
|
50
|
+
if (!hasCritical) {
|
|
51
|
+
return { skip: true, reason: 'No critical-path keywords found in unit files' };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (name === 'contract') {
|
|
55
|
+
if (config.apiSurfaceFiles.length === 0) {
|
|
56
|
+
return { skip: true, reason: 'No API surface files in unit' };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return { skip: false };
|
|
60
|
+
}
|
|
61
|
+
export function applyAllowFailures(result) {
|
|
62
|
+
return {
|
|
63
|
+
...result,
|
|
64
|
+
status: 'passed',
|
|
65
|
+
findings: result.findings.map(f => ({ ...f, severity: 'info' })),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export async function updateCheckpointForValidator(projectPath, workflowId, unitId, validatorName, status, coveragePercentage) {
|
|
69
|
+
const checkpoint = await loadCheckpoint(projectPath, workflowId);
|
|
70
|
+
if (!checkpoint || !checkpoint.construction_units) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const unit = checkpoint.construction_units[unitId];
|
|
74
|
+
if (!unit) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const field = VALIDATOR_FIELD_MAP[validatorName];
|
|
78
|
+
unit[field] = status;
|
|
79
|
+
if (validatorName === 'coverage' && coveragePercentage !== undefined) {
|
|
80
|
+
unit.coverage_percentage = coveragePercentage;
|
|
81
|
+
}
|
|
82
|
+
await saveCheckpoint(projectPath, checkpoint);
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../../../../src/features/workflow-engine/construction/validators/pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Finding, ValidatorFindingSeverity } from '../../phase-types.js';
|
|
2
|
+
export type AntiPatternCategory = 'tautological' | 'empty-body' | 'trivially-true' | 'surface-assertion' | 'excessive-mocking' | 'snapshot-overuse';
|
|
3
|
+
export interface AntiPatternRule {
|
|
4
|
+
category: AntiPatternCategory;
|
|
5
|
+
severity: ValidatorFindingSeverity;
|
|
6
|
+
pattern: RegExp;
|
|
7
|
+
description: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const REJECTION_PATTERNS: AntiPatternRule[];
|
|
10
|
+
export declare const WARNING_PATTERNS: AntiPatternRule[];
|
|
11
|
+
export declare function detectAntiPatterns(testContent: string, testName: string, filePath: string): Finding[];
|
|
12
|
+
export interface NegativeCaseResult {
|
|
13
|
+
ratio: number;
|
|
14
|
+
totalTests: number;
|
|
15
|
+
negativeTests: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function calculateNegativeCaseRatio(testContent: string): NegativeCaseResult;
|
|
18
|
+
//# sourceMappingURL=quality-patterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-patterns.d.ts","sourceRoot":"","sources":["../../../../../src/features/workflow-engine/construction/validators/quality-patterns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAE9E,MAAM,MAAM,mBAAmB,GAC3B,cAAc,GACd,YAAY,GACZ,gBAAgB,GAChB,mBAAmB,GACnB,mBAAmB,GACnB,kBAAkB,CAAC;AAEvB,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,QAAQ,EAAE,wBAAwB,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,kBAAkB,EAAE,eAAe,EA2C/C,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,eAAe,EAmB7C,CAAC;AAkHF,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,EAAE,CAkEX;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,CAiBlF"}
|