@dewtech/dare-cli 3.2.0 → 3.3.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/README.md +2 -0
- package/dist/__tests__/dag-runner/ralph-loop.test.js +107 -45
- package/dist/__tests__/dag-runner/ralph-loop.test.js.map +1 -1
- package/dist/__tests__/dag-runner/state-store.test.d.ts +2 -0
- package/dist/__tests__/dag-runner/state-store.test.d.ts.map +1 -0
- package/dist/__tests__/dag-runner/state-store.test.js +74 -0
- package/dist/__tests__/dag-runner/state-store.test.js.map +1 -0
- package/dist/__tests__/ide-command-parity.test.js +1 -0
- package/dist/__tests__/ide-command-parity.test.js.map +1 -1
- package/dist/__tests__/project-generator.test.d.ts +2 -0
- package/dist/__tests__/project-generator.test.d.ts.map +1 -0
- package/dist/__tests__/project-generator.test.js +56 -0
- package/dist/__tests__/project-generator.test.js.map +1 -0
- package/dist/bin/dare.js +2 -0
- package/dist/bin/dare.js.map +1 -1
- package/dist/commands/__tests__/bench.spec.d.ts +2 -0
- package/dist/commands/__tests__/bench.spec.d.ts.map +1 -0
- package/dist/commands/__tests__/bench.spec.js +106 -0
- package/dist/commands/__tests__/bench.spec.js.map +1 -0
- package/dist/commands/__tests__/execute.best-of.spec.d.ts +2 -0
- package/dist/commands/__tests__/execute.best-of.spec.d.ts.map +1 -0
- package/dist/commands/__tests__/execute.best-of.spec.js +24 -0
- package/dist/commands/__tests__/execute.best-of.spec.js.map +1 -0
- package/dist/commands/__tests__/execute.telemetry.spec.d.ts +2 -0
- package/dist/commands/__tests__/execute.telemetry.spec.d.ts.map +1 -0
- package/dist/commands/__tests__/execute.telemetry.spec.js +93 -0
- package/dist/commands/__tests__/execute.telemetry.spec.js.map +1 -0
- package/dist/commands/__tests__/execute.verify.spec.d.ts +2 -0
- package/dist/commands/__tests__/execute.verify.spec.d.ts.map +1 -0
- package/dist/commands/__tests__/execute.verify.spec.js +150 -0
- package/dist/commands/__tests__/execute.verify.spec.js.map +1 -0
- package/dist/commands/bench.d.ts +10 -0
- package/dist/commands/bench.d.ts.map +1 -0
- package/dist/commands/bench.js +64 -0
- package/dist/commands/bench.js.map +1 -0
- package/dist/commands/execute-verification.d.ts +51 -0
- package/dist/commands/execute-verification.d.ts.map +1 -0
- package/dist/commands/execute-verification.js +201 -0
- package/dist/commands/execute-verification.js.map +1 -0
- package/dist/commands/execute.d.ts.map +1 -1
- package/dist/commands/execute.js +139 -2
- package/dist/commands/execute.js.map +1 -1
- package/dist/dag-runner/ralph-loop.d.ts +9 -9
- package/dist/dag-runner/ralph-loop.d.ts.map +1 -1
- package/dist/dag-runner/ralph-loop.js +89 -113
- package/dist/dag-runner/ralph-loop.js.map +1 -1
- package/dist/dag-runner/state-store.d.ts +14 -1
- package/dist/dag-runner/state-store.d.ts.map +1 -1
- package/dist/dag-runner/state-store.js +39 -8
- package/dist/dag-runner/state-store.js.map +1 -1
- package/dist/exec/npm-invoke.d.ts +8 -0
- package/dist/exec/npm-invoke.d.ts.map +1 -0
- package/dist/exec/npm-invoke.js +45 -0
- package/dist/exec/npm-invoke.js.map +1 -0
- package/dist/exec/safe-spawn.d.ts +21 -0
- package/dist/exec/safe-spawn.d.ts.map +1 -0
- package/dist/exec/safe-spawn.js +108 -0
- package/dist/exec/safe-spawn.js.map +1 -0
- package/dist/graphrag/types.d.ts +2 -2
- package/dist/graphrag/types.d.ts.map +1 -1
- package/dist/stacks/dna-emitter.d.ts.map +1 -1
- package/dist/stacks/dna-emitter.js +1 -10
- package/dist/stacks/dna-emitter.js.map +1 -1
- package/dist/utils/UpdateApplier.d.ts.map +1 -1
- package/dist/utils/UpdateApplier.js +8 -0
- package/dist/utils/UpdateApplier.js.map +1 -1
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +23 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/path-safety.d.ts +22 -0
- package/dist/utils/path-safety.d.ts.map +1 -0
- package/dist/utils/path-safety.js +83 -0
- package/dist/utils/path-safety.js.map +1 -0
- package/dist/utils/project-generator.d.ts.map +1 -1
- package/dist/utils/project-generator.js +2 -0
- package/dist/utils/project-generator.js.map +1 -1
- package/dist/utils/stack-bootstrap.js +2 -2
- package/dist/utils/stack-bootstrap.js.map +1 -1
- package/dist/verification/__tests__/anti-tamper.test.d.ts +2 -0
- package/dist/verification/__tests__/anti-tamper.test.d.ts.map +1 -0
- package/dist/verification/__tests__/anti-tamper.test.js +73 -0
- package/dist/verification/__tests__/anti-tamper.test.js.map +1 -0
- package/dist/verification/__tests__/bench-fixtures.test.d.ts +2 -0
- package/dist/verification/__tests__/bench-fixtures.test.d.ts.map +1 -0
- package/dist/verification/__tests__/bench-fixtures.test.js +35 -0
- package/dist/verification/__tests__/bench-fixtures.test.js.map +1 -0
- package/dist/verification/__tests__/bench-harness.test.d.ts +2 -0
- package/dist/verification/__tests__/bench-harness.test.d.ts.map +1 -0
- package/dist/verification/__tests__/bench-harness.test.js +75 -0
- package/dist/verification/__tests__/bench-harness.test.js.map +1 -0
- package/dist/verification/__tests__/bench-report.test.d.ts +2 -0
- package/dist/verification/__tests__/bench-report.test.d.ts.map +1 -0
- package/dist/verification/__tests__/bench-report.test.js +73 -0
- package/dist/verification/__tests__/bench-report.test.js.map +1 -0
- package/dist/verification/__tests__/best-of-n-runner.test.d.ts +2 -0
- package/dist/verification/__tests__/best-of-n-runner.test.d.ts.map +1 -0
- package/dist/verification/__tests__/best-of-n-runner.test.js +94 -0
- package/dist/verification/__tests__/best-of-n-runner.test.js.map +1 -0
- package/dist/verification/__tests__/config.test.d.ts +2 -0
- package/dist/verification/__tests__/config.test.d.ts.map +1 -0
- package/dist/verification/__tests__/config.test.js +50 -0
- package/dist/verification/__tests__/config.test.js.map +1 -0
- package/dist/verification/__tests__/decay-policy.test.d.ts +2 -0
- package/dist/verification/__tests__/decay-policy.test.d.ts.map +1 -0
- package/dist/verification/__tests__/decay-policy.test.js +130 -0
- package/dist/verification/__tests__/decay-policy.test.js.map +1 -0
- package/dist/verification/__tests__/fail-to-pass.test.d.ts +2 -0
- package/dist/verification/__tests__/fail-to-pass.test.d.ts.map +1 -0
- package/dist/verification/__tests__/fail-to-pass.test.js +107 -0
- package/dist/verification/__tests__/fail-to-pass.test.js.map +1 -0
- package/dist/verification/__tests__/failure-signature.test.d.ts +2 -0
- package/dist/verification/__tests__/failure-signature.test.d.ts.map +1 -0
- package/dist/verification/__tests__/failure-signature.test.js +40 -0
- package/dist/verification/__tests__/failure-signature.test.js.map +1 -0
- package/dist/verification/__tests__/logger.test.d.ts +2 -0
- package/dist/verification/__tests__/logger.test.d.ts.map +1 -0
- package/dist/verification/__tests__/logger.test.js +23 -0
- package/dist/verification/__tests__/logger.test.js.map +1 -0
- package/dist/verification/__tests__/mutation-cargo-mutants.test.d.ts +2 -0
- package/dist/verification/__tests__/mutation-cargo-mutants.test.d.ts.map +1 -0
- package/dist/verification/__tests__/mutation-cargo-mutants.test.js +96 -0
- package/dist/verification/__tests__/mutation-cargo-mutants.test.js.map +1 -0
- package/dist/verification/__tests__/mutation-infection.test.d.ts +2 -0
- package/dist/verification/__tests__/mutation-infection.test.d.ts.map +1 -0
- package/dist/verification/__tests__/mutation-infection.test.js +101 -0
- package/dist/verification/__tests__/mutation-infection.test.js.map +1 -0
- package/dist/verification/__tests__/mutation-mutmut.test.d.ts +2 -0
- package/dist/verification/__tests__/mutation-mutmut.test.d.ts.map +1 -0
- package/dist/verification/__tests__/mutation-mutmut.test.js +102 -0
- package/dist/verification/__tests__/mutation-mutmut.test.js.map +1 -0
- package/dist/verification/__tests__/mutation-registry.test.d.ts +2 -0
- package/dist/verification/__tests__/mutation-registry.test.d.ts.map +1 -0
- package/dist/verification/__tests__/mutation-registry.test.js +28 -0
- package/dist/verification/__tests__/mutation-registry.test.js.map +1 -0
- package/dist/verification/__tests__/mutation-stryker.test.d.ts +2 -0
- package/dist/verification/__tests__/mutation-stryker.test.d.ts.map +1 -0
- package/dist/verification/__tests__/mutation-stryker.test.js +88 -0
- package/dist/verification/__tests__/mutation-stryker.test.js.map +1 -0
- package/dist/verification/__tests__/no-shell-true.test.d.ts +2 -0
- package/dist/verification/__tests__/no-shell-true.test.d.ts.map +1 -0
- package/dist/verification/__tests__/no-shell-true.test.js +43 -0
- package/dist/verification/__tests__/no-shell-true.test.js.map +1 -0
- package/dist/verification/__tests__/path-safety.test.d.ts +2 -0
- package/dist/verification/__tests__/path-safety.test.d.ts.map +1 -0
- package/dist/verification/__tests__/path-safety.test.js +59 -0
- package/dist/verification/__tests__/path-safety.test.js.map +1 -0
- package/dist/verification/__tests__/prerank.test.d.ts +2 -0
- package/dist/verification/__tests__/prerank.test.d.ts.map +1 -0
- package/dist/verification/__tests__/prerank.test.js +44 -0
- package/dist/verification/__tests__/prerank.test.js.map +1 -0
- package/dist/verification/__tests__/runner.test.d.ts +2 -0
- package/dist/verification/__tests__/runner.test.d.ts.map +1 -0
- package/dist/verification/__tests__/runner.test.js +200 -0
- package/dist/verification/__tests__/runner.test.js.map +1 -0
- package/dist/verification/__tests__/safe-spawn.test.d.ts +2 -0
- package/dist/verification/__tests__/safe-spawn.test.d.ts.map +1 -0
- package/dist/verification/__tests__/safe-spawn.test.js +36 -0
- package/dist/verification/__tests__/safe-spawn.test.js.map +1 -0
- package/dist/verification/__tests__/security.test.d.ts +2 -0
- package/dist/verification/__tests__/security.test.d.ts.map +1 -0
- package/dist/verification/__tests__/security.test.js +79 -0
- package/dist/verification/__tests__/security.test.js.map +1 -0
- package/dist/verification/__tests__/selector-pareto.test.d.ts +2 -0
- package/dist/verification/__tests__/selector-pareto.test.d.ts.map +1 -0
- package/dist/verification/__tests__/selector-pareto.test.js +77 -0
- package/dist/verification/__tests__/selector-pareto.test.js.map +1 -0
- package/dist/verification/__tests__/telemetry.test.d.ts +2 -0
- package/dist/verification/__tests__/telemetry.test.d.ts.map +1 -0
- package/dist/verification/__tests__/telemetry.test.js +116 -0
- package/dist/verification/__tests__/telemetry.test.js.map +1 -0
- package/dist/verification/__tests__/type-check.test.d.ts +2 -0
- package/dist/verification/__tests__/type-check.test.d.ts.map +1 -0
- package/dist/verification/__tests__/type-check.test.js +52 -0
- package/dist/verification/__tests__/type-check.test.js.map +1 -0
- package/dist/verification/__tests__/worktree.test.d.ts +2 -0
- package/dist/verification/__tests__/worktree.test.d.ts.map +1 -0
- package/dist/verification/__tests__/worktree.test.js +41 -0
- package/dist/verification/__tests__/worktree.test.js.map +1 -0
- package/dist/verification/bench/fixtures.d.ts +11 -0
- package/dist/verification/bench/fixtures.d.ts.map +1 -0
- package/dist/verification/bench/fixtures.js +66 -0
- package/dist/verification/bench/fixtures.js.map +1 -0
- package/dist/verification/bench/harness.d.ts +19 -0
- package/dist/verification/bench/harness.d.ts.map +1 -0
- package/dist/verification/bench/harness.js +138 -0
- package/dist/verification/bench/harness.js.map +1 -0
- package/dist/verification/bench/report.d.ts +53 -0
- package/dist/verification/bench/report.d.ts.map +1 -0
- package/dist/verification/bench/report.js +47 -0
- package/dist/verification/bench/report.js.map +1 -0
- package/dist/verification/best-of-n/runner.d.ts +29 -0
- package/dist/verification/best-of-n/runner.d.ts.map +1 -0
- package/dist/verification/best-of-n/runner.js +76 -0
- package/dist/verification/best-of-n/runner.js.map +1 -0
- package/dist/verification/best-of-n/selector/pareto.d.ts +10 -0
- package/dist/verification/best-of-n/selector/pareto.d.ts.map +1 -0
- package/dist/verification/best-of-n/selector/pareto.js +65 -0
- package/dist/verification/best-of-n/selector/pareto.js.map +1 -0
- package/dist/verification/best-of-n/selector/prerank.d.ts +23 -0
- package/dist/verification/best-of-n/selector/prerank.d.ts.map +1 -0
- package/dist/verification/best-of-n/selector/prerank.js +32 -0
- package/dist/verification/best-of-n/selector/prerank.js.map +1 -0
- package/dist/verification/best-of-n/worktree.d.ts +9 -0
- package/dist/verification/best-of-n/worktree.d.ts.map +1 -0
- package/dist/verification/best-of-n/worktree.js +100 -0
- package/dist/verification/best-of-n/worktree.js.map +1 -0
- package/dist/verification/config.d.ts +24 -0
- package/dist/verification/config.d.ts.map +1 -0
- package/dist/verification/config.js +168 -0
- package/dist/verification/config.js.map +1 -0
- package/dist/verification/decay/policy.d.ts +16 -0
- package/dist/verification/decay/policy.d.ts.map +1 -0
- package/dist/verification/decay/policy.js +64 -0
- package/dist/verification/decay/policy.js.map +1 -0
- package/dist/verification/decay/signature.d.ts +6 -0
- package/dist/verification/decay/signature.d.ts.map +1 -0
- package/dist/verification/decay/signature.js +18 -0
- package/dist/verification/decay/signature.js.map +1 -0
- package/dist/verification/gates/anti-tamper.d.ts +16 -0
- package/dist/verification/gates/anti-tamper.d.ts.map +1 -0
- package/dist/verification/gates/anti-tamper.js +142 -0
- package/dist/verification/gates/anti-tamper.js.map +1 -0
- package/dist/verification/gates/fail-to-pass.d.ts +39 -0
- package/dist/verification/gates/fail-to-pass.d.ts.map +1 -0
- package/dist/verification/gates/fail-to-pass.js +173 -0
- package/dist/verification/gates/fail-to-pass.js.map +1 -0
- package/dist/verification/gates/mutation/adapter.d.ts +34 -0
- package/dist/verification/gates/mutation/adapter.d.ts.map +1 -0
- package/dist/verification/gates/mutation/adapter.js +22 -0
- package/dist/verification/gates/mutation/adapter.js.map +1 -0
- package/dist/verification/gates/mutation/cargo-mutants.d.ts +28 -0
- package/dist/verification/gates/mutation/cargo-mutants.d.ts.map +1 -0
- package/dist/verification/gates/mutation/cargo-mutants.js +170 -0
- package/dist/verification/gates/mutation/cargo-mutants.js.map +1 -0
- package/dist/verification/gates/mutation/infection.d.ts +28 -0
- package/dist/verification/gates/mutation/infection.d.ts.map +1 -0
- package/dist/verification/gates/mutation/infection.js +149 -0
- package/dist/verification/gates/mutation/infection.js.map +1 -0
- package/dist/verification/gates/mutation/mutmut.d.ts +23 -0
- package/dist/verification/gates/mutation/mutmut.d.ts.map +1 -0
- package/dist/verification/gates/mutation/mutmut.js +148 -0
- package/dist/verification/gates/mutation/mutmut.js.map +1 -0
- package/dist/verification/gates/mutation/stryker.d.ts +19 -0
- package/dist/verification/gates/mutation/stryker.d.ts.map +1 -0
- package/dist/verification/gates/mutation/stryker.js +103 -0
- package/dist/verification/gates/mutation/stryker.js.map +1 -0
- package/dist/verification/gates/type-check.d.ts +11 -0
- package/dist/verification/gates/type-check.d.ts.map +1 -0
- package/dist/verification/gates/type-check.js +84 -0
- package/dist/verification/gates/type-check.js.map +1 -0
- package/dist/verification/registry.d.ts +6 -0
- package/dist/verification/registry.d.ts.map +1 -0
- package/dist/verification/registry.js +49 -0
- package/dist/verification/registry.js.map +1 -0
- package/dist/verification/runner.d.ts +27 -0
- package/dist/verification/runner.d.ts.map +1 -0
- package/dist/verification/runner.js +173 -0
- package/dist/verification/runner.js.map +1 -0
- package/dist/verification/telemetry.d.ts +18 -0
- package/dist/verification/telemetry.d.ts.map +1 -0
- package/dist/verification/telemetry.js +71 -0
- package/dist/verification/telemetry.js.map +1 -0
- package/dist/verification/types.d.ts +89 -0
- package/dist/verification/types.d.ts.map +1 -0
- package/dist/verification/types.js +3 -0
- package/dist/verification/types.js.map +1 -0
- package/package.json +5 -3
- package/templates/UPDATE-MANIFEST.json +20 -0
- package/templates/ide/antigravity/.agents/skills/dare-bench/SKILL.md +21 -0
- package/templates/ide/claude/.claude/commands/dare-bench.md +18 -0
- package/templates/ide/cursor/.cursor/commands/dare-bench.md +18 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
const SKIP_PATTERNS = [
|
|
4
|
+
/\bit\.skip\s*\(/,
|
|
5
|
+
/\bit\.only\s*\(/,
|
|
6
|
+
/\bdescribe\.only\s*\(/,
|
|
7
|
+
/\bdescribe\.skip\s*\(/,
|
|
8
|
+
/\bxit\s*\(/,
|
|
9
|
+
/\bxdescribe\s*\(/,
|
|
10
|
+
/@pytest\.mark\.skip/,
|
|
11
|
+
];
|
|
12
|
+
function stripJsComments(content) {
|
|
13
|
+
return content
|
|
14
|
+
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
15
|
+
.replace(/\/\/.*$/gm, '');
|
|
16
|
+
}
|
|
17
|
+
function hasSkipMarker(content) {
|
|
18
|
+
return SKIP_PATTERNS.some((pattern) => pattern.test(content));
|
|
19
|
+
}
|
|
20
|
+
function countAssertions(content, ext) {
|
|
21
|
+
if (ext === '.py') {
|
|
22
|
+
const assertKw = (content.match(/\bassert\b/g) ?? []).length;
|
|
23
|
+
const selfAssert = (content.match(/\bself\.assert\w+/g) ?? []).length;
|
|
24
|
+
const pytestRaises = (content.match(/pytest\.raises\s*\(/g) ?? []).length;
|
|
25
|
+
return assertKw + selfAssert + pytestRaises;
|
|
26
|
+
}
|
|
27
|
+
if (ext === '.rs') {
|
|
28
|
+
return (content.match(/\bassert(?:_eq|_ne)?!\s*\(/g) ?? []).length;
|
|
29
|
+
}
|
|
30
|
+
if (ext === '.php') {
|
|
31
|
+
return (content.match(/\$this->assert\w+/g) ?? []).length;
|
|
32
|
+
}
|
|
33
|
+
const stripped = stripJsComments(content);
|
|
34
|
+
const expect = (stripped.match(/\bexpect\s*\(/g) ?? []).length;
|
|
35
|
+
const assertCalls = (stripped.match(/\bassert\s*\(/g) ?? []).length;
|
|
36
|
+
const matchers = (stripped.match(/\.to(?:Be|Equal|StrictEqual|Throw|Match|Contain)\s*\(/g) ??
|
|
37
|
+
[]).length;
|
|
38
|
+
return expect + assertCalls + matchers;
|
|
39
|
+
}
|
|
40
|
+
function fileExt(file) {
|
|
41
|
+
return path.extname(file).toLowerCase();
|
|
42
|
+
}
|
|
43
|
+
async function collectTestFiles(cwd, testGlob) {
|
|
44
|
+
const direct = path.join(cwd, testGlob);
|
|
45
|
+
if (await fs.pathExists(direct)) {
|
|
46
|
+
const stat = await fs.stat(direct);
|
|
47
|
+
if (stat.isFile())
|
|
48
|
+
return [testGlob.replace(/\\/g, '/')];
|
|
49
|
+
}
|
|
50
|
+
const found = [];
|
|
51
|
+
const suffixes = [
|
|
52
|
+
'.test.ts',
|
|
53
|
+
'.test.js',
|
|
54
|
+
'.spec.ts',
|
|
55
|
+
'.spec.js',
|
|
56
|
+
'_test.py',
|
|
57
|
+
'_test.rs',
|
|
58
|
+
];
|
|
59
|
+
async function walk(dir) {
|
|
60
|
+
let entries;
|
|
61
|
+
try {
|
|
62
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
for (const entry of entries) {
|
|
68
|
+
if (entry.name === 'node_modules' || entry.name === '.git')
|
|
69
|
+
continue;
|
|
70
|
+
const abs = path.join(dir, entry.name);
|
|
71
|
+
if (entry.isDirectory()) {
|
|
72
|
+
await walk(abs);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const rel = path.relative(cwd, abs).replace(/\\/g, '/');
|
|
76
|
+
if (suffixes.some((s) => rel.endsWith(s)))
|
|
77
|
+
found.push(rel);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
await walk(cwd);
|
|
81
|
+
return [...new Set(found)].sort();
|
|
82
|
+
}
|
|
83
|
+
export async function snapshotTests(args) {
|
|
84
|
+
const testFiles = await collectTestFiles(args.cwd, args.testGlob);
|
|
85
|
+
let assertionCount = 0;
|
|
86
|
+
for (const file of testFiles) {
|
|
87
|
+
const content = await fs.readFile(path.join(args.cwd, file), 'utf8');
|
|
88
|
+
assertionCount += countAssertions(content, fileExt(file));
|
|
89
|
+
}
|
|
90
|
+
return { assertionCount, testFiles };
|
|
91
|
+
}
|
|
92
|
+
export async function checkAntiTamper(args) {
|
|
93
|
+
const start = Date.now();
|
|
94
|
+
const current = await snapshotTests({
|
|
95
|
+
cwd: args.cwd,
|
|
96
|
+
testGlob: args.testGlob,
|
|
97
|
+
});
|
|
98
|
+
for (const file of args.baseline.testFiles) {
|
|
99
|
+
if (!current.testFiles.includes(file)) {
|
|
100
|
+
return {
|
|
101
|
+
aspect: 'anti-tamper',
|
|
102
|
+
verdict: 'FAIL',
|
|
103
|
+
reason: `test file removed: ${file}`,
|
|
104
|
+
durationMs: Date.now() - start,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const content = await fs.readFile(path.join(args.cwd, file), 'utf8');
|
|
108
|
+
if (hasSkipMarker(content)) {
|
|
109
|
+
return {
|
|
110
|
+
aspect: 'anti-tamper',
|
|
111
|
+
verdict: 'FAIL',
|
|
112
|
+
reason: `test weakened with skip/only in ${file}`,
|
|
113
|
+
durationMs: Date.now() - start,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (current.assertionCount < args.baseline.assertionCount) {
|
|
118
|
+
return {
|
|
119
|
+
aspect: 'anti-tamper',
|
|
120
|
+
verdict: 'FAIL',
|
|
121
|
+
reason: `assertion count dropped: ${args.baseline.assertionCount} → ${current.assertionCount}`,
|
|
122
|
+
durationMs: Date.now() - start,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (args.baseline.coveragePct !== undefined &&
|
|
126
|
+
current.coveragePct !== undefined &&
|
|
127
|
+
current.coveragePct < args.baseline.coveragePct - 1) {
|
|
128
|
+
return {
|
|
129
|
+
aspect: 'anti-tamper',
|
|
130
|
+
verdict: 'FAIL',
|
|
131
|
+
reason: `coverage dropped: ${args.baseline.coveragePct}% → ${current.coveragePct}%`,
|
|
132
|
+
durationMs: Date.now() - start,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
aspect: 'anti-tamper',
|
|
137
|
+
verdict: 'PASS',
|
|
138
|
+
reason: 'test suite not weakened',
|
|
139
|
+
durationMs: Date.now() - start,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=anti-tamper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anti-tamper.js","sourceRoot":"","sources":["../../../src/verification/gates/anti-tamper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AspectResult } from '../types.js';
|
|
2
|
+
import type { TamperSnapshot } from './anti-tamper.js';
|
|
3
|
+
export interface FailToPassBaseline {
|
|
4
|
+
readonly recordedAt: string;
|
|
5
|
+
readonly ranAgainst: string;
|
|
6
|
+
readonly failed: ReadonlyArray<string>;
|
|
7
|
+
readonly allFailed: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface VerificationArtifact {
|
|
10
|
+
readonly specGlob?: string;
|
|
11
|
+
readonly failToPassBaseline?: FailToPassBaseline;
|
|
12
|
+
readonly tamperSnapshot?: TamperSnapshot;
|
|
13
|
+
}
|
|
14
|
+
export declare class FailToPassMissingError extends Error {
|
|
15
|
+
readonly taskId: string;
|
|
16
|
+
constructor(taskId: string);
|
|
17
|
+
}
|
|
18
|
+
export declare function readVerificationArtifact(cwd: string, taskId: string): Promise<VerificationArtifact | undefined>;
|
|
19
|
+
/** Map stack → test runner argv for a spec glob/path. */
|
|
20
|
+
export declare function testCommandFor(stack: string, specGlob: string): {
|
|
21
|
+
command: string;
|
|
22
|
+
args: string[];
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Record baseline: spec must fail entirely against pre-implementation code.
|
|
26
|
+
*/
|
|
27
|
+
export declare function recordFailToPassBaseline(args: {
|
|
28
|
+
readonly taskId: string;
|
|
29
|
+
readonly cwd: string;
|
|
30
|
+
readonly specGlob: string;
|
|
31
|
+
}): Promise<FailToPassBaseline>;
|
|
32
|
+
/**
|
|
33
|
+
* Verify fail-to-pass gate at task completion.
|
|
34
|
+
*/
|
|
35
|
+
export declare function checkFailToPass(args: {
|
|
36
|
+
readonly taskId: string;
|
|
37
|
+
readonly cwd: string;
|
|
38
|
+
}): Promise<AspectResult>;
|
|
39
|
+
//# sourceMappingURL=fail-to-pass.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fail-to-pass.d.ts","sourceRoot":"","sources":["../../../src/verification/gates/fail-to-pass.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACjD,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;CAC1C;AAED,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,MAAM;CAK3B;AAQD,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAI3C;AA8BD,yDAAyD;AACzD,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAyBrC;AA+DD;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,IAAI,EAAE;IACnD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA4B9B;AAoBD;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,YAAY,CAAC,CAiCxB"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import { safeSpawn } from '../../exec/safe-spawn.js';
|
|
4
|
+
import { npmInvoke } from '../../exec/npm-invoke.js';
|
|
5
|
+
import { resolveStackFromConfig } from '../../dag-runner/ralph-loop.js';
|
|
6
|
+
export class FailToPassMissingError extends Error {
|
|
7
|
+
constructor(taskId) {
|
|
8
|
+
super(`fail-to-pass baseline missing for task ${taskId}`);
|
|
9
|
+
this.name = 'FailToPassMissingError';
|
|
10
|
+
this.taskId = taskId;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const BASELINE_DIR = '.dare/verification';
|
|
14
|
+
function artifactPath(cwd, taskId) {
|
|
15
|
+
return path.join(cwd, BASELINE_DIR, `${taskId}.json`);
|
|
16
|
+
}
|
|
17
|
+
export async function readVerificationArtifact(cwd, taskId) {
|
|
18
|
+
const file = artifactPath(cwd, taskId);
|
|
19
|
+
if (!(await fs.pathExists(file)))
|
|
20
|
+
return undefined;
|
|
21
|
+
return (await fs.readJson(file));
|
|
22
|
+
}
|
|
23
|
+
async function readArtifact(cwd, taskId) {
|
|
24
|
+
return readVerificationArtifact(cwd, taskId);
|
|
25
|
+
}
|
|
26
|
+
async function writeArtifact(cwd, taskId, patch) {
|
|
27
|
+
const file = artifactPath(cwd, taskId);
|
|
28
|
+
await fs.ensureDir(path.dirname(file));
|
|
29
|
+
const prev = (await readArtifact(cwd, taskId)) ?? {};
|
|
30
|
+
await fs.writeJson(file, { ...prev, ...patch }, { spaces: 2 });
|
|
31
|
+
}
|
|
32
|
+
async function gitHead(cwd) {
|
|
33
|
+
const result = await safeSpawn('git', ['rev-parse', 'HEAD'], {
|
|
34
|
+
cwd,
|
|
35
|
+
timeoutSeconds: 30,
|
|
36
|
+
maxChars: 200,
|
|
37
|
+
});
|
|
38
|
+
if (result.code === 0)
|
|
39
|
+
return result.stdout.trim();
|
|
40
|
+
return 'unknown';
|
|
41
|
+
}
|
|
42
|
+
/** Map stack → test runner argv for a spec glob/path. */
|
|
43
|
+
export function testCommandFor(stack, specGlob) {
|
|
44
|
+
switch (stack) {
|
|
45
|
+
case 'node-nestjs':
|
|
46
|
+
case 'react':
|
|
47
|
+
case 'vue':
|
|
48
|
+
case 'mcp-server-node-ts':
|
|
49
|
+
return npmInvoke(['exec', 'vitest', 'run', specGlob, '--reporter=json']);
|
|
50
|
+
case 'python-fastapi':
|
|
51
|
+
case 'mcp-server-python':
|
|
52
|
+
return {
|
|
53
|
+
command: 'pytest',
|
|
54
|
+
args: [specGlob, '-q', '--tb=short'],
|
|
55
|
+
};
|
|
56
|
+
case 'rust-axum':
|
|
57
|
+
case 'rust-leptos':
|
|
58
|
+
case 'rust-leptos-csr':
|
|
59
|
+
return { command: 'cargo', args: ['test', '--quiet', specGlob] };
|
|
60
|
+
case 'php-laravel':
|
|
61
|
+
return { command: 'php', args: ['artisan', 'test', specGlob] };
|
|
62
|
+
case 'go-gin':
|
|
63
|
+
case 'go-stdlib':
|
|
64
|
+
return { command: 'go', args: ['test', specGlob] };
|
|
65
|
+
default:
|
|
66
|
+
throw new Error(`No fail-to-pass test runner for stack: ${stack}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function testId(file, name) {
|
|
70
|
+
return `${file}::${name}`;
|
|
71
|
+
}
|
|
72
|
+
function parseVitestJson(stdout) {
|
|
73
|
+
const passed = [];
|
|
74
|
+
const failed = [];
|
|
75
|
+
try {
|
|
76
|
+
const report = JSON.parse(stdout);
|
|
77
|
+
for (const fileResult of report.testResults ?? []) {
|
|
78
|
+
const file = fileResult.name ?? 'unknown';
|
|
79
|
+
for (const assertion of fileResult.assertionResults ?? []) {
|
|
80
|
+
const id = testId(file, assertion.fullName ?? 'unknown');
|
|
81
|
+
if (assertion.status === 'passed')
|
|
82
|
+
passed.push(id);
|
|
83
|
+
else if (assertion.status === 'failed')
|
|
84
|
+
failed.push(id);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// fallback: no structured results
|
|
90
|
+
}
|
|
91
|
+
return { passed, failed };
|
|
92
|
+
}
|
|
93
|
+
async function runSpecSuite(cwd, stack, specGlob) {
|
|
94
|
+
const { command, args } = testCommandFor(stack, specGlob);
|
|
95
|
+
const result = await safeSpawn(command, args, {
|
|
96
|
+
cwd,
|
|
97
|
+
timeoutSeconds: 300,
|
|
98
|
+
maxChars: 200000,
|
|
99
|
+
});
|
|
100
|
+
const { passed, failed } = parseVitestJson(result.stdout);
|
|
101
|
+
return {
|
|
102
|
+
exitCode: result.code,
|
|
103
|
+
passed,
|
|
104
|
+
failed,
|
|
105
|
+
stderr: result.stderr,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Record baseline: spec must fail entirely against pre-implementation code.
|
|
110
|
+
*/
|
|
111
|
+
export async function recordFailToPassBaseline(args) {
|
|
112
|
+
const stack = await resolveStackFromConfig(args.cwd);
|
|
113
|
+
const run = await runSpecSuite(args.cwd, stack, args.specGlob);
|
|
114
|
+
if (run.passed.length > 0) {
|
|
115
|
+
throw new Error(`fail-to-pass baseline requires all tests to fail; passed: ${run.passed.join(', ')}`);
|
|
116
|
+
}
|
|
117
|
+
if (run.failed.length === 0 && run.exitCode === 0) {
|
|
118
|
+
throw new Error('fail-to-pass baseline requires a failing spec (all tests must fail before implementation)');
|
|
119
|
+
}
|
|
120
|
+
const baseline = {
|
|
121
|
+
recordedAt: new Date().toISOString(),
|
|
122
|
+
ranAgainst: await gitHead(args.cwd),
|
|
123
|
+
failed: run.failed.length > 0 ? run.failed : [`${args.specGlob}::(suite)`],
|
|
124
|
+
allFailed: true,
|
|
125
|
+
};
|
|
126
|
+
await writeArtifact(args.cwd, args.taskId, {
|
|
127
|
+
specGlob: args.specGlob,
|
|
128
|
+
failToPassBaseline: baseline,
|
|
129
|
+
});
|
|
130
|
+
return baseline;
|
|
131
|
+
}
|
|
132
|
+
function failAspect(reason, durationMs = 0) {
|
|
133
|
+
return {
|
|
134
|
+
aspect: 'fail-to-pass',
|
|
135
|
+
verdict: 'FAIL',
|
|
136
|
+
reason,
|
|
137
|
+
durationMs,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function passAspect(reason, durationMs) {
|
|
141
|
+
return {
|
|
142
|
+
aspect: 'fail-to-pass',
|
|
143
|
+
verdict: 'PASS',
|
|
144
|
+
reason,
|
|
145
|
+
durationMs,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Verify fail-to-pass gate at task completion.
|
|
150
|
+
*/
|
|
151
|
+
export async function checkFailToPass(args) {
|
|
152
|
+
const start = Date.now();
|
|
153
|
+
const artifact = await readArtifact(args.cwd, args.taskId);
|
|
154
|
+
const baseline = artifact?.failToPassBaseline;
|
|
155
|
+
const specGlob = artifact?.specGlob;
|
|
156
|
+
if (!baseline || !specGlob) {
|
|
157
|
+
return failAspect('no baseline recorded');
|
|
158
|
+
}
|
|
159
|
+
const stack = await resolveStackFromConfig(args.cwd);
|
|
160
|
+
const run = await runSpecSuite(args.cwd, stack, specGlob);
|
|
161
|
+
const durationMs = Date.now() - start;
|
|
162
|
+
if (run.failed.length > 0) {
|
|
163
|
+
return failAspect(`tests still failing: ${run.failed.join(', ')}`, durationMs);
|
|
164
|
+
}
|
|
165
|
+
if (run.exitCode !== 0) {
|
|
166
|
+
return failAspect(`spec suite did not pass (exit ${run.exitCode})`, durationMs);
|
|
167
|
+
}
|
|
168
|
+
if (!baseline.allFailed) {
|
|
169
|
+
return failAspect('baseline was not allFailed', durationMs);
|
|
170
|
+
}
|
|
171
|
+
return passAspect('all baseline tests now pass', durationMs);
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=fail-to-pass.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fail-to-pass.js","sourceRoot":"","sources":["../../../src/verification/gates/fail-to-pass.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { MutationTool } from '../../types.js';
|
|
2
|
+
export interface MutationRunInput {
|
|
3
|
+
readonly cwd: string;
|
|
4
|
+
readonly changedFiles: ReadonlyArray<string>;
|
|
5
|
+
readonly incremental: boolean;
|
|
6
|
+
readonly maxMutants: number;
|
|
7
|
+
readonly timeoutSeconds: number;
|
|
8
|
+
}
|
|
9
|
+
export interface MutationRunOutput {
|
|
10
|
+
/** killed/(killed+survived). NaN when no mutants — caller treats as SKIP. */
|
|
11
|
+
readonly score: number;
|
|
12
|
+
readonly killed: number;
|
|
13
|
+
readonly survived: number;
|
|
14
|
+
readonly noCoverage: number;
|
|
15
|
+
readonly timedOut: boolean;
|
|
16
|
+
readonly tool: MutationTool;
|
|
17
|
+
}
|
|
18
|
+
export interface MutationAdapter {
|
|
19
|
+
readonly tool: MutationTool;
|
|
20
|
+
readonly stacks: ReadonlyArray<string>;
|
|
21
|
+
isAvailable(cwd: string): Promise<boolean>;
|
|
22
|
+
run(input: MutationRunInput): Promise<MutationRunOutput>;
|
|
23
|
+
}
|
|
24
|
+
export declare class MutationToolNotFoundError extends Error {
|
|
25
|
+
readonly tool: MutationTool;
|
|
26
|
+
constructor(tool: MutationTool);
|
|
27
|
+
}
|
|
28
|
+
export declare class UnknownMutationStackError extends Error {
|
|
29
|
+
readonly stack: string;
|
|
30
|
+
constructor(stack: string);
|
|
31
|
+
}
|
|
32
|
+
/** Normalized mutation score for reporting gates. */
|
|
33
|
+
export declare function mutationScore(output: MutationRunOutput): number;
|
|
34
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/verification/gates/mutation/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,GAAG,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC1D;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;gBAEhB,IAAI,EAAE,YAAY;CAK/B;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,KAAK,EAAE,MAAM;CAK1B;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAI/D"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export class MutationToolNotFoundError extends Error {
|
|
2
|
+
constructor(tool) {
|
|
3
|
+
super(`Mutation tool not available: ${tool}`);
|
|
4
|
+
this.name = 'MutationToolNotFoundError';
|
|
5
|
+
this.tool = tool;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export class UnknownMutationStackError extends Error {
|
|
9
|
+
constructor(stack) {
|
|
10
|
+
super(`No mutation adapter registered for stack: ${stack}`);
|
|
11
|
+
this.name = 'UnknownMutationStackError';
|
|
12
|
+
this.stack = stack;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** Normalized mutation score for reporting gates. */
|
|
16
|
+
export function mutationScore(output) {
|
|
17
|
+
const denom = output.killed + output.survived;
|
|
18
|
+
if (denom === 0)
|
|
19
|
+
return Number.NaN;
|
|
20
|
+
return output.killed / denom;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../../src/verification/gates/mutation/adapter.ts"],"names":[],"mappings":"AA2BA,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAGlD,YAAY,IAAkB;QAC5B,KAAK,CAAC,gCAAgC,IAAI,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAGlD,YAAY,KAAa;QACvB,KAAK,CAAC,6CAA6C,KAAK,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;QACxC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAED,qDAAqD;AACrD,MAAM,UAAU,aAAa,CAAC,MAAyB;IACrD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC9C,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC;IACnC,OAAO,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { MutationAdapter, MutationRunInput, MutationRunOutput } from './adapter.js';
|
|
2
|
+
export declare const OUTCOMES_REL: string;
|
|
3
|
+
interface CargoMutantsSummary {
|
|
4
|
+
readonly caught?: number;
|
|
5
|
+
readonly missed?: number;
|
|
6
|
+
readonly unviable?: number;
|
|
7
|
+
readonly timeout?: number;
|
|
8
|
+
}
|
|
9
|
+
interface CargoMutantsOutcomeEntry {
|
|
10
|
+
readonly outcome?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface CargoMutantsOutcomesFile {
|
|
13
|
+
readonly summary?: CargoMutantsSummary;
|
|
14
|
+
readonly outcomes?: ReadonlyArray<CargoMutantsOutcomeEntry>;
|
|
15
|
+
readonly caught?: number;
|
|
16
|
+
readonly missed?: number;
|
|
17
|
+
readonly unviable?: number;
|
|
18
|
+
readonly timeout?: number;
|
|
19
|
+
}
|
|
20
|
+
/** Parse `mutants.out/outcomes.json` into normalized output. */
|
|
21
|
+
export declare function parseCargoMutantsReport(report: CargoMutantsOutcomesFile, timedOut?: boolean): MutationRunOutput;
|
|
22
|
+
/** Build `cargo mutants` argv (exported for tests). */
|
|
23
|
+
export declare function buildCargoMutantsArgv(input: MutationRunInput, inDiffPath?: string): string[];
|
|
24
|
+
export declare const cargoMutantsAdapter: MutationAdapter;
|
|
25
|
+
/** Registry export (task-030). */
|
|
26
|
+
export declare const adapter: MutationAdapter;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=cargo-mutants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cargo-mutants.d.ts","sourceRoot":"","sources":["../../../../src/verification/gates/mutation/cargo-mutants.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,cAAc,CAAC;AAMtB,eAAO,MAAM,YAAY,QAA4C,CAAC;AAMtE,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,UAAU,wBAAwB;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,wBAAwB,CAAC,CAAC;IAC5D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AA2BD,gEAAgE;AAChE,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,wBAAwB,EAChC,QAAQ,UAAQ,GACf,iBAAiB,CAwCnB;AAED,uDAAuD;AACvD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,gBAAgB,EACvB,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,EAAE,CAaV;AAwDD,eAAO,MAAM,mBAAmB,EAAE,eA8CjC,CAAC;AAEF,kCAAkC;AAClC,eAAO,MAAM,OAAO,iBAAsB,CAAC"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import { safeSpawn } from '../../../exec/safe-spawn.js';
|
|
4
|
+
import { MutationToolNotFoundError, mutationScore, } from './adapter.js';
|
|
5
|
+
export const OUTCOMES_REL = path.join('mutants.out', 'outcomes.json');
|
|
6
|
+
const IN_DIFF_REL = path.join('.dare', 'mutation-in-diff.patch');
|
|
7
|
+
const MIN_CARGO_MUTANTS_VERSION = [25, 0, 0];
|
|
8
|
+
const RS_EXT = /\.rs$/i;
|
|
9
|
+
function parseVersionTuple(text) {
|
|
10
|
+
const match = text.match(/(\d+)\.(\d+)\.(\d+)/);
|
|
11
|
+
if (!match)
|
|
12
|
+
return null;
|
|
13
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
14
|
+
}
|
|
15
|
+
function versionGte(version, minimum) {
|
|
16
|
+
for (let i = 0; i < 3; i += 1) {
|
|
17
|
+
if (version[i] > minimum[i])
|
|
18
|
+
return true;
|
|
19
|
+
if (version[i] < minimum[i])
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
function classifyOutcome(raw) {
|
|
25
|
+
const status = raw.toLowerCase();
|
|
26
|
+
if (status === 'caught' || status === 'timeout')
|
|
27
|
+
return 'killed';
|
|
28
|
+
if (status === 'missed')
|
|
29
|
+
return 'survived';
|
|
30
|
+
if (status === 'unviable')
|
|
31
|
+
return 'noCoverage';
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
/** Parse `mutants.out/outcomes.json` into normalized output. */
|
|
35
|
+
export function parseCargoMutantsReport(report, timedOut = false) {
|
|
36
|
+
let killed = 0;
|
|
37
|
+
let survived = 0;
|
|
38
|
+
let noCoverage = 0;
|
|
39
|
+
if (report.summary) {
|
|
40
|
+
killed =
|
|
41
|
+
(report.summary.caught ?? 0) + (report.summary.timeout ?? 0);
|
|
42
|
+
survived = report.summary.missed ?? 0;
|
|
43
|
+
noCoverage = report.summary.unviable ?? 0;
|
|
44
|
+
}
|
|
45
|
+
else if (report.outcomes?.length) {
|
|
46
|
+
for (const entry of report.outcomes) {
|
|
47
|
+
const kind = classifyOutcome(entry.outcome ?? '');
|
|
48
|
+
if (kind === 'killed')
|
|
49
|
+
killed += 1;
|
|
50
|
+
else if (kind === 'survived')
|
|
51
|
+
survived += 1;
|
|
52
|
+
else if (kind === 'noCoverage')
|
|
53
|
+
noCoverage += 1;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
killed = (report.caught ?? 0) + (report.timeout ?? 0);
|
|
58
|
+
survived = report.missed ?? 0;
|
|
59
|
+
noCoverage = report.unviable ?? 0;
|
|
60
|
+
}
|
|
61
|
+
const output = {
|
|
62
|
+
killed,
|
|
63
|
+
survived,
|
|
64
|
+
noCoverage,
|
|
65
|
+
timedOut,
|
|
66
|
+
tool: 'cargo-mutants',
|
|
67
|
+
score: mutationScore({
|
|
68
|
+
killed,
|
|
69
|
+
survived,
|
|
70
|
+
noCoverage,
|
|
71
|
+
timedOut,
|
|
72
|
+
tool: 'cargo-mutants',
|
|
73
|
+
score: 0,
|
|
74
|
+
}),
|
|
75
|
+
};
|
|
76
|
+
return output;
|
|
77
|
+
}
|
|
78
|
+
/** Build `cargo mutants` argv (exported for tests). */
|
|
79
|
+
export function buildCargoMutantsArgv(input, inDiffPath) {
|
|
80
|
+
const argv = [
|
|
81
|
+
'mutants',
|
|
82
|
+
'--json',
|
|
83
|
+
'--timeout',
|
|
84
|
+
String(input.timeoutSeconds),
|
|
85
|
+
];
|
|
86
|
+
if (input.incremental && inDiffPath) {
|
|
87
|
+
argv.push('--in-diff', inDiffPath);
|
|
88
|
+
}
|
|
89
|
+
return argv;
|
|
90
|
+
}
|
|
91
|
+
function diffPaths(changedFiles) {
|
|
92
|
+
const rustFiles = [
|
|
93
|
+
...new Set(changedFiles.filter((f) => RS_EXT.test(f))),
|
|
94
|
+
];
|
|
95
|
+
return rustFiles.length > 0 ? rustFiles : [...new Set(changedFiles)];
|
|
96
|
+
}
|
|
97
|
+
async function collectGitDiff(cwd, changedFiles) {
|
|
98
|
+
const paths = diffPaths(changedFiles);
|
|
99
|
+
if (paths.length === 0)
|
|
100
|
+
return null;
|
|
101
|
+
const result = await safeSpawn('git', ['diff', '--', ...paths], {
|
|
102
|
+
cwd,
|
|
103
|
+
timeoutSeconds: 60,
|
|
104
|
+
maxChars: 500000,
|
|
105
|
+
});
|
|
106
|
+
if (result.code !== 0 || !result.stdout.trim())
|
|
107
|
+
return null;
|
|
108
|
+
return result.stdout;
|
|
109
|
+
}
|
|
110
|
+
async function writeInDiffFile(cwd, diff) {
|
|
111
|
+
const abs = path.join(cwd, IN_DIFF_REL);
|
|
112
|
+
await fs.ensureDir(path.dirname(abs));
|
|
113
|
+
await fs.writeFile(abs, diff, 'utf8');
|
|
114
|
+
return IN_DIFF_REL;
|
|
115
|
+
}
|
|
116
|
+
async function probeCargoMutants(cwd) {
|
|
117
|
+
const result = await safeSpawn('cargo', ['mutants', '--version'], {
|
|
118
|
+
cwd,
|
|
119
|
+
timeoutSeconds: 30,
|
|
120
|
+
maxChars: 2000,
|
|
121
|
+
});
|
|
122
|
+
if (result.code !== 0)
|
|
123
|
+
return false;
|
|
124
|
+
const version = parseVersionTuple(`${result.stdout}\n${result.stderr}`);
|
|
125
|
+
if (!version)
|
|
126
|
+
return true;
|
|
127
|
+
return versionGte(version, MIN_CARGO_MUTANTS_VERSION);
|
|
128
|
+
}
|
|
129
|
+
async function readOutcomesReport(cwd) {
|
|
130
|
+
const reportPath = path.join(cwd, OUTCOMES_REL);
|
|
131
|
+
if (!(await fs.pathExists(reportPath))) {
|
|
132
|
+
return {};
|
|
133
|
+
}
|
|
134
|
+
return (await fs.readJson(reportPath));
|
|
135
|
+
}
|
|
136
|
+
export const cargoMutantsAdapter = {
|
|
137
|
+
tool: 'cargo-mutants',
|
|
138
|
+
stacks: ['rust-axum', 'rust-leptos', 'rust-leptos-csr'],
|
|
139
|
+
async isAvailable(cwd) {
|
|
140
|
+
return probeCargoMutants(cwd);
|
|
141
|
+
},
|
|
142
|
+
async run(input) {
|
|
143
|
+
if (!(await probeCargoMutants(input.cwd))) {
|
|
144
|
+
throw new MutationToolNotFoundError('cargo-mutants');
|
|
145
|
+
}
|
|
146
|
+
let inDiffPath;
|
|
147
|
+
if (input.incremental && input.changedFiles.length > 0) {
|
|
148
|
+
const diff = await collectGitDiff(input.cwd, input.changedFiles);
|
|
149
|
+
if (diff) {
|
|
150
|
+
inDiffPath = await writeInDiffFile(input.cwd, diff);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const spawnResult = await safeSpawn('cargo', buildCargoMutantsArgv(input, inDiffPath), {
|
|
154
|
+
cwd: input.cwd,
|
|
155
|
+
timeoutSeconds: input.timeoutSeconds,
|
|
156
|
+
maxChars: 8000,
|
|
157
|
+
});
|
|
158
|
+
const report = await readOutcomesReport(input.cwd);
|
|
159
|
+
const output = parseCargoMutantsReport(report, spawnResult.timedOut);
|
|
160
|
+
if (spawnResult.code !== 0 &&
|
|
161
|
+
!spawnResult.timedOut &&
|
|
162
|
+
output.killed + output.survived === 0) {
|
|
163
|
+
throw new Error(`cargo mutants exited with code ${spawnResult.code}: ${spawnResult.stderr.trim()}`);
|
|
164
|
+
}
|
|
165
|
+
return output;
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
/** Registry export (task-030). */
|
|
169
|
+
export const adapter = cargoMutantsAdapter;
|
|
170
|
+
//# sourceMappingURL=cargo-mutants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cargo-mutants.js","sourceRoot":"","sources":["../../../../src/verification/gates/mutation/cargo-mutants.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAMxD,OAAO,EACL,yBAAyB,EACzB,aAAa,GACd,MAAM,cAAc,CAAC;AAEtB,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;AACtE,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,wBAAwB,CAAC,CAAC;AAEjE,MAAM,yBAAyB,GAAsC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAChF,MAAM,MAAM,GAAG,QAAQ,CAAC;AAsBxB,SAAS,iBAAiB,CAAC,IAAY;IACrC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAChD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,UAAU,CACjB,OAAiC,EACjC,OAA0C;IAE1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACzC,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IAC5C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,eAAe,CAAC,GAAW;IAClC,MAAM,MAAM,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACjE,IAAI,MAAM,KAAK,QAAQ;QAAE,OAAO,UAAU,CAAC;IAC3C,IAAI,MAAM,KAAK,UAAU;QAAE,OAAO,YAAY,CAAC;IAC/C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,uBAAuB,CACrC,MAAgC,EAChC,QAAQ,GAAG,KAAK;IAEhB,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,MAAM;YACJ,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;QAC/D,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QACtC,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;IAC5C,CAAC;SAAM,IAAI,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;YAClD,IAAI,IAAI,KAAK,QAAQ;gBAAE,MAAM,IAAI,CAAC,CAAC;iBAC9B,IAAI,IAAI,KAAK,UAAU;gBAAE,QAAQ,IAAI,CAAC,CAAC;iBACvC,IAAI,IAAI,KAAK,YAAY;gBAAE,UAAU,IAAI,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;QACtD,QAAQ,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;QAC9B,UAAU,GAAG,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,MAAM,MAAM,GAAsB;QAChC,MAAM;QACN,QAAQ;QACR,UAAU;QACV,QAAQ;QACR,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,aAAa,CAAC;YACnB,MAAM;YACN,QAAQ;YACR,UAAU;YACV,QAAQ;YACR,IAAI,EAAE,eAAe;YACrB,KAAK,EAAE,CAAC;SACT,CAAC;KACH,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,qBAAqB,CACnC,KAAuB,EACvB,UAAmB;IAEnB,MAAM,IAAI,GAAG;QACX,SAAS;QACT,QAAQ;QACR,WAAW;QACX,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC;KAC7B,CAAC;IAEF,IAAI,KAAK,CAAC,WAAW,IAAI,UAAU,EAAE,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,SAAS,CAAC,YAAmC;IACpD,MAAM,SAAS,GAAG;QAChB,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;KACvD,CAAC;IACF,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,GAAW,EACX,YAAmC;IAEnC,MAAM,KAAK,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,EAAE;QAC9D,GAAG;QACH,cAAc,EAAE,EAAE;QAClB,QAAQ,EAAE,MAAO;KAClB,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,OAAO,IAAI,CAAC;IAC5D,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,GAAW,EAAE,IAAY;IACtD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACxC,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACtC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACtC,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,GAAW;IAC1C,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE;QAChE,GAAG;QACH,cAAc,EAAE,EAAE;QAClB,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC;IACH,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEpC,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACxE,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,UAAU,CAAC,OAAO,EAAE,yBAAyB,CAAC,CAAC;AACxD,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,GAAW;IAEX,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAChD,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAA6B,CAAC;AACrE,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAoB;IAClD,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,CAAC,WAAW,EAAE,aAAa,EAAE,iBAAiB,CAAC;IAEvD,KAAK,CAAC,WAAW,CAAC,GAAW;QAC3B,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAuB;QAC/B,IAAI,CAAC,CAAC,MAAM,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,yBAAyB,CAAC,eAAe,CAAC,CAAC;QACvD,CAAC;QAED,IAAI,UAA8B,CAAC;QACnC,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvD,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;YACjE,IAAI,IAAI,EAAE,CAAC;gBACT,UAAU,GAAG,MAAM,eAAe,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QAED,MAAM,WAAW,GAAG,MAAM,SAAS,CACjC,OAAO,EACP,qBAAqB,CAAC,KAAK,EAAE,UAAU,CAAC,EACxC;YACE,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,QAAQ,EAAE,IAAI;SACf,CACF,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,uBAAuB,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;QAErE,IACE,WAAW,CAAC,IAAI,KAAK,CAAC;YACtB,CAAC,WAAW,CAAC,QAAQ;YACrB,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ,KAAK,CAAC,EACrC,CAAC;YACD,MAAM,IAAI,KAAK,CACb,kCAAkC,WAAW,CAAC,IAAI,KAAK,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CACnF,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC;AAEF,kCAAkC;AAClC,MAAM,CAAC,MAAM,OAAO,GAAG,mBAAmB,CAAC"}
|