outcome-cli 1.0.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 +261 -0
- package/package.json +95 -0
- package/src/agents/README.md +139 -0
- package/src/agents/adapters/anthropic.adapter.ts +166 -0
- package/src/agents/adapters/dalle.adapter.ts +145 -0
- package/src/agents/adapters/gemini.adapter.ts +134 -0
- package/src/agents/adapters/imagen.adapter.ts +106 -0
- package/src/agents/adapters/nano-banana.adapter.ts +129 -0
- package/src/agents/adapters/openai.adapter.ts +165 -0
- package/src/agents/adapters/veo.adapter.ts +130 -0
- package/src/agents/agent.schema.property.test.ts +379 -0
- package/src/agents/agent.schema.test.ts +148 -0
- package/src/agents/agent.schema.ts +263 -0
- package/src/agents/index.ts +60 -0
- package/src/agents/registered-agent.schema.ts +356 -0
- package/src/agents/registry.ts +97 -0
- package/src/agents/tournament-configs.property.test.ts +266 -0
- package/src/cli/README.md +145 -0
- package/src/cli/commands/define.ts +79 -0
- package/src/cli/commands/list.ts +46 -0
- package/src/cli/commands/logs.ts +83 -0
- package/src/cli/commands/run.ts +416 -0
- package/src/cli/commands/verify.ts +110 -0
- package/src/cli/index.ts +81 -0
- package/src/config/README.md +128 -0
- package/src/config/env.ts +262 -0
- package/src/config/index.ts +19 -0
- package/src/eval/README.md +318 -0
- package/src/eval/ai-judge.test.ts +435 -0
- package/src/eval/ai-judge.ts +368 -0
- package/src/eval/code-validators.ts +414 -0
- package/src/eval/evaluateOutcome.property.test.ts +1174 -0
- package/src/eval/evaluateOutcome.ts +591 -0
- package/src/eval/immigration-validators.ts +122 -0
- package/src/eval/index.ts +90 -0
- package/src/eval/judge-cache.ts +402 -0
- package/src/eval/tournament-validators.property.test.ts +439 -0
- package/src/eval/validators.property.test.ts +1118 -0
- package/src/eval/validators.ts +1199 -0
- package/src/eval/weighted-scorer.ts +285 -0
- package/src/index.ts +17 -0
- package/src/league/README.md +188 -0
- package/src/league/health-check.ts +353 -0
- package/src/league/index.ts +93 -0
- package/src/league/killAgent.ts +151 -0
- package/src/league/league.test.ts +1151 -0
- package/src/league/runLeague.ts +843 -0
- package/src/league/scoreAgent.ts +175 -0
- package/src/modules/omnibridge/__tests__/.gitkeep +1 -0
- package/src/modules/omnibridge/__tests__/auth-tunnel.property.test.ts +524 -0
- package/src/modules/omnibridge/__tests__/deterministic-logger.property.test.ts +965 -0
- package/src/modules/omnibridge/__tests__/ghost-api.property.test.ts +461 -0
- package/src/modules/omnibridge/__tests__/omnibridge-integration.test.ts +542 -0
- package/src/modules/omnibridge/__tests__/parallel-executor.property.test.ts +671 -0
- package/src/modules/omnibridge/__tests__/semantic-normalizer.property.test.ts +521 -0
- package/src/modules/omnibridge/__tests__/semantic-normalizer.test.ts +254 -0
- package/src/modules/omnibridge/__tests__/session-vault.property.test.ts +367 -0
- package/src/modules/omnibridge/__tests__/shadow-session.property.test.ts +523 -0
- package/src/modules/omnibridge/__tests__/triangulation-engine.property.test.ts +292 -0
- package/src/modules/omnibridge/__tests__/verification-engine.property.test.ts +769 -0
- package/src/modules/omnibridge/api/.gitkeep +1 -0
- package/src/modules/omnibridge/api/ghost-api.ts +1087 -0
- package/src/modules/omnibridge/auth/.gitkeep +1 -0
- package/src/modules/omnibridge/auth/auth-tunnel.ts +843 -0
- package/src/modules/omnibridge/auth/session-vault.ts +577 -0
- package/src/modules/omnibridge/core/.gitkeep +1 -0
- package/src/modules/omnibridge/core/semantic-normalizer.ts +702 -0
- package/src/modules/omnibridge/core/triangulation-engine.ts +530 -0
- package/src/modules/omnibridge/core/types.ts +610 -0
- package/src/modules/omnibridge/execution/.gitkeep +1 -0
- package/src/modules/omnibridge/execution/deterministic-logger.ts +629 -0
- package/src/modules/omnibridge/execution/parallel-executor.ts +542 -0
- package/src/modules/omnibridge/execution/shadow-session.ts +794 -0
- package/src/modules/omnibridge/index.ts +212 -0
- package/src/modules/omnibridge/omnibridge.ts +510 -0
- package/src/modules/omnibridge/verification/.gitkeep +1 -0
- package/src/modules/omnibridge/verification/verification-engine.ts +783 -0
- package/src/outcomes/README.md +75 -0
- package/src/outcomes/acquire-pilot-customer.ts +297 -0
- package/src/outcomes/code-delivery-outcomes.ts +89 -0
- package/src/outcomes/code-outcomes.ts +256 -0
- package/src/outcomes/code_review_battle.test.ts +135 -0
- package/src/outcomes/code_review_battle.ts +135 -0
- package/src/outcomes/cold_email_battle.ts +97 -0
- package/src/outcomes/content_creation_battle.ts +160 -0
- package/src/outcomes/f1_stem_opt_compliance.ts +61 -0
- package/src/outcomes/index.ts +107 -0
- package/src/outcomes/lead_gen_battle.test.ts +113 -0
- package/src/outcomes/lead_gen_battle.ts +99 -0
- package/src/outcomes/outcome.schema.property.test.ts +229 -0
- package/src/outcomes/outcome.schema.ts +187 -0
- package/src/outcomes/qualified_sales_interest.ts +118 -0
- package/src/outcomes/swarm_planner.property.test.ts +370 -0
- package/src/outcomes/swarm_planner.ts +96 -0
- package/src/outcomes/web_extraction.ts +234 -0
- package/src/runtime/README.md +220 -0
- package/src/runtime/agentRunner.test.ts +341 -0
- package/src/runtime/agentRunner.ts +746 -0
- package/src/runtime/claudeAdapter.ts +232 -0
- package/src/runtime/costTracker.ts +123 -0
- package/src/runtime/index.ts +34 -0
- package/src/runtime/modelAdapter.property.test.ts +305 -0
- package/src/runtime/modelAdapter.ts +144 -0
- package/src/runtime/openaiAdapter.ts +235 -0
- package/src/utils/README.md +122 -0
- package/src/utils/command-runner.ts +134 -0
- package/src/utils/cost-guard.ts +379 -0
- package/src/utils/errors.test.ts +290 -0
- package/src/utils/errors.ts +442 -0
- package/src/utils/index.ts +37 -0
- package/src/utils/logger.test.ts +361 -0
- package/src/utils/logger.ts +419 -0
- package/src/utils/output-parsers.ts +216 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Property-based tests for Tournament Seed Bounty Validators
|
|
3
|
+
*
|
|
4
|
+
* Tests the validators used in code review battles and lead generation battles.
|
|
5
|
+
* Each property test validates universal correctness properties across many inputs.
|
|
6
|
+
*
|
|
7
|
+
* @module eval/tournament-validators.property.test
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, test, expect } from 'vitest';
|
|
11
|
+
import * as fc from 'fast-check';
|
|
12
|
+
import {
|
|
13
|
+
validateSecurityIssue,
|
|
14
|
+
validatePerformanceIssue,
|
|
15
|
+
validateNoiseFreeness,
|
|
16
|
+
validateComplexityReduction,
|
|
17
|
+
validateLinkedIn,
|
|
18
|
+
validateLeadGenPrecision,
|
|
19
|
+
validateExpertReview,
|
|
20
|
+
type ValidationResult,
|
|
21
|
+
} from './validators.js';
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// Code Review Battle Property Tests
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Property-based tests for Security Issue Detection
|
|
29
|
+
*
|
|
30
|
+
* **Feature: tournament-seed-bounties, Property 1: Security Issue Detection**
|
|
31
|
+
* **Validates: Requirements 1.4, 3.3**
|
|
32
|
+
*
|
|
33
|
+
* Property 1: Security Issue Detection
|
|
34
|
+
* *For any* code review artifact, the security validator SHALL return valid: true
|
|
35
|
+
* if and only if the artifact contains at least one issue with type "security"
|
|
36
|
+
* and severity "CRITICAL".
|
|
37
|
+
*/
|
|
38
|
+
describe('Security Issue Detection - Property Tests', () => {
|
|
39
|
+
// **Feature: tournament-seed-bounties, Property 1: Security Issue Detection**
|
|
40
|
+
test('artifacts with CRITICAL security issues are valid', () => {
|
|
41
|
+
fc.assert(
|
|
42
|
+
fc.property(
|
|
43
|
+
fc.array(fc.record({
|
|
44
|
+
type: fc.constantFrom('security', 'performance', 'style', 'logic'),
|
|
45
|
+
severity: fc.constantFrom('CRITICAL', 'HIGH', 'MEDIUM', 'LOW'),
|
|
46
|
+
description: fc.string(),
|
|
47
|
+
lineNumber: fc.integer({ min: 1, max: 100 })
|
|
48
|
+
})),
|
|
49
|
+
(issues) => {
|
|
50
|
+
// Ensure at least one CRITICAL security issue exists
|
|
51
|
+
const artifactWithSecurity = {
|
|
52
|
+
issues: [
|
|
53
|
+
...issues,
|
|
54
|
+
{
|
|
55
|
+
type: 'security',
|
|
56
|
+
severity: 'CRITICAL',
|
|
57
|
+
description: 'SQL injection vulnerability',
|
|
58
|
+
lineNumber: 1
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const result = validateSecurityIssue(artifactWithSecurity, 'CRITICAL');
|
|
64
|
+
expect(result.valid).toBe(true);
|
|
65
|
+
expect(result.errors).toHaveLength(0);
|
|
66
|
+
}
|
|
67
|
+
),
|
|
68
|
+
{ numRuns: 100 }
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// **Feature: tournament-seed-bounties, Property 1: Security Issue Detection**
|
|
73
|
+
test('artifacts without CRITICAL security issues are invalid', () => {
|
|
74
|
+
fc.assert(
|
|
75
|
+
fc.property(
|
|
76
|
+
fc.array(fc.record({
|
|
77
|
+
type: fc.constantFrom('performance', 'style', 'logic'), // No security
|
|
78
|
+
severity: fc.constantFrom('CRITICAL', 'HIGH', 'MEDIUM', 'LOW'),
|
|
79
|
+
description: fc.string(),
|
|
80
|
+
lineNumber: fc.integer({ min: 1, max: 100 })
|
|
81
|
+
})),
|
|
82
|
+
(issues) => {
|
|
83
|
+
const artifact = { issues };
|
|
84
|
+
const result = validateSecurityIssue(artifact, 'CRITICAL');
|
|
85
|
+
expect(result.valid).toBe(false);
|
|
86
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
87
|
+
}
|
|
88
|
+
),
|
|
89
|
+
{ numRuns: 100 }
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// **Feature: tournament-seed-bounties, Property 1: Security Issue Detection**
|
|
94
|
+
test('validation is deterministic', () => {
|
|
95
|
+
fc.assert(
|
|
96
|
+
fc.property(
|
|
97
|
+
fc.array(fc.record({
|
|
98
|
+
type: fc.constantFrom('security', 'performance', 'style', 'logic'),
|
|
99
|
+
severity: fc.constantFrom('CRITICAL', 'HIGH', 'MEDIUM', 'LOW'),
|
|
100
|
+
description: fc.string()
|
|
101
|
+
})),
|
|
102
|
+
(issues) => {
|
|
103
|
+
const artifact = { issues };
|
|
104
|
+
const result1 = validateSecurityIssue(artifact, 'CRITICAL');
|
|
105
|
+
const result2 = validateSecurityIssue(artifact, 'CRITICAL');
|
|
106
|
+
expect(result1.valid).toBe(result2.valid);
|
|
107
|
+
expect(result1.errors).toEqual(result2.errors);
|
|
108
|
+
}
|
|
109
|
+
),
|
|
110
|
+
{ numRuns: 100 }
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Property-based tests for Performance Issue Detection
|
|
117
|
+
*
|
|
118
|
+
* **Feature: tournament-seed-bounties, Property 2: Performance Issue Detection**
|
|
119
|
+
* **Validates: Requirements 1.5, 3.4**
|
|
120
|
+
*
|
|
121
|
+
* Property 2: Performance Issue Detection
|
|
122
|
+
* *For any* code review artifact, the performance validator SHALL return valid: true
|
|
123
|
+
* if and only if the artifact contains at least one issue with type "performance".
|
|
124
|
+
*/
|
|
125
|
+
describe('Performance Issue Detection - Property Tests', () => {
|
|
126
|
+
// **Feature: tournament-seed-bounties, Property 2: Performance Issue Detection**
|
|
127
|
+
test('artifacts with performance issues are valid', () => {
|
|
128
|
+
fc.assert(
|
|
129
|
+
fc.property(
|
|
130
|
+
fc.array(fc.record({
|
|
131
|
+
type: fc.constantFrom('security', 'performance', 'style', 'logic'),
|
|
132
|
+
severity: fc.constantFrom('CRITICAL', 'HIGH', 'MEDIUM', 'LOW'),
|
|
133
|
+
description: fc.string()
|
|
134
|
+
})),
|
|
135
|
+
(issues) => {
|
|
136
|
+
// Ensure at least one performance issue exists
|
|
137
|
+
const artifactWithPerformance = {
|
|
138
|
+
issues: [
|
|
139
|
+
...issues,
|
|
140
|
+
{
|
|
141
|
+
type: 'performance',
|
|
142
|
+
severity: 'HIGH',
|
|
143
|
+
description: 'N+1 query detected'
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const result = validatePerformanceIssue(artifactWithPerformance);
|
|
149
|
+
expect(result.valid).toBe(true);
|
|
150
|
+
expect(result.errors).toHaveLength(0);
|
|
151
|
+
}
|
|
152
|
+
),
|
|
153
|
+
{ numRuns: 100 }
|
|
154
|
+
);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// **Feature: tournament-seed-bounties, Property 2: Performance Issue Detection**
|
|
158
|
+
test('artifacts without performance issues are invalid', () => {
|
|
159
|
+
fc.assert(
|
|
160
|
+
fc.property(
|
|
161
|
+
fc.array(fc.record({
|
|
162
|
+
type: fc.constantFrom('security', 'style', 'logic'), // No performance
|
|
163
|
+
severity: fc.constantFrom('CRITICAL', 'HIGH', 'MEDIUM', 'LOW'),
|
|
164
|
+
description: fc.string()
|
|
165
|
+
})),
|
|
166
|
+
(issues) => {
|
|
167
|
+
const artifact = { issues };
|
|
168
|
+
const result = validatePerformanceIssue(artifact);
|
|
169
|
+
expect(result.valid).toBe(false);
|
|
170
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
171
|
+
}
|
|
172
|
+
),
|
|
173
|
+
{ numRuns: 100 }
|
|
174
|
+
);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Property-based tests for Noise-Free Comment Validation
|
|
180
|
+
*
|
|
181
|
+
* **Feature: tournament-seed-bounties, Property 3: Noise-Free Comment Validation**
|
|
182
|
+
* **Validates: Requirements 1.6, 3.5**
|
|
183
|
+
*
|
|
184
|
+
* Property 3: Noise-Free Comment Validation
|
|
185
|
+
* *For any* code review artifact and source diff, the noise-freeness validator
|
|
186
|
+
* SHALL return valid: true if and only if every comment's lineContent is present
|
|
187
|
+
* in the source diff string.
|
|
188
|
+
*/
|
|
189
|
+
describe('Noise-Free Comment Validation - Property Tests', () => {
|
|
190
|
+
// **Feature: tournament-seed-bounties, Property 3: Noise-Free Comment Validation**
|
|
191
|
+
test('comments within source diff are valid', () => {
|
|
192
|
+
fc.assert(
|
|
193
|
+
fc.property(
|
|
194
|
+
fc.array(fc.string({ minLength: 1, maxLength: 100 })),
|
|
195
|
+
fc.array(fc.string({ minLength: 1, maxLength: 50 })),
|
|
196
|
+
(sourceLines, additionalLines) => {
|
|
197
|
+
const sourceDiff = [...sourceLines, ...additionalLines].join('\n');
|
|
198
|
+
|
|
199
|
+
// Create comments that reference lines in the source diff
|
|
200
|
+
const comments = sourceLines.map((line, index) => ({
|
|
201
|
+
lineContent: line,
|
|
202
|
+
comment: `Comment about line ${index}`,
|
|
203
|
+
lineNumber: index + 1
|
|
204
|
+
}));
|
|
205
|
+
|
|
206
|
+
const artifact = { comments };
|
|
207
|
+
const result = validateNoiseFreeness(artifact, sourceDiff);
|
|
208
|
+
expect(result.valid).toBe(true);
|
|
209
|
+
expect(result.errors).toHaveLength(0);
|
|
210
|
+
}
|
|
211
|
+
),
|
|
212
|
+
{ numRuns: 100 }
|
|
213
|
+
);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// **Feature: tournament-seed-bounties, Property 3: Noise-Free Comment Validation**
|
|
217
|
+
test('comments outside source diff are invalid', () => {
|
|
218
|
+
fc.assert(
|
|
219
|
+
fc.property(
|
|
220
|
+
fc.string({ minLength: 1, maxLength: 100 }),
|
|
221
|
+
fc.string({ minLength: 1, maxLength: 100 }).filter(s => s !== ''),
|
|
222
|
+
(sourceDiff, outsideLine) => {
|
|
223
|
+
// Ensure outsideLine is not in sourceDiff
|
|
224
|
+
fc.pre(!sourceDiff.includes(outsideLine));
|
|
225
|
+
|
|
226
|
+
const comments = [{
|
|
227
|
+
lineContent: outsideLine,
|
|
228
|
+
comment: 'This comment is outside the diff',
|
|
229
|
+
lineNumber: 1
|
|
230
|
+
}];
|
|
231
|
+
|
|
232
|
+
const artifact = { comments };
|
|
233
|
+
const result = validateNoiseFreeness(artifact, sourceDiff);
|
|
234
|
+
expect(result.valid).toBe(false);
|
|
235
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
236
|
+
}
|
|
237
|
+
),
|
|
238
|
+
{ numRuns: 100 }
|
|
239
|
+
);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Property-based tests for Complexity Reduction Validation
|
|
245
|
+
*
|
|
246
|
+
* **Feature: tournament-seed-bounties, Property 4: Complexity Reduction Validation**
|
|
247
|
+
* **Validates: Requirements 1.7, 3.7**
|
|
248
|
+
*
|
|
249
|
+
* Property 4: Complexity Reduction Validation
|
|
250
|
+
* *For any* code review artifact with a refactor suggestion, the complexity validator
|
|
251
|
+
* SHALL return valid: true if and only if (originalComplexity - suggestedComplexity)
|
|
252
|
+
* >= minReduction.
|
|
253
|
+
*/
|
|
254
|
+
describe('Complexity Reduction Validation - Property Tests', () => {
|
|
255
|
+
// **Feature: tournament-seed-bounties, Property 4: Complexity Reduction Validation**
|
|
256
|
+
test('sufficient complexity reduction is valid', () => {
|
|
257
|
+
fc.assert(
|
|
258
|
+
fc.property(
|
|
259
|
+
fc.integer({ min: 5, max: 20 }), // originalComplexity
|
|
260
|
+
fc.integer({ min: 2, max: 10 }), // minReduction
|
|
261
|
+
(originalComplexity, minReduction) => {
|
|
262
|
+
const suggestedComplexity = originalComplexity - minReduction;
|
|
263
|
+
|
|
264
|
+
const artifact = {
|
|
265
|
+
refactorSuggestion: {
|
|
266
|
+
originalComplexity,
|
|
267
|
+
suggestedComplexity,
|
|
268
|
+
description: 'Refactor to reduce complexity'
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const result = validateComplexityReduction(artifact, minReduction);
|
|
273
|
+
expect(result.valid).toBe(true);
|
|
274
|
+
expect(result.errors).toHaveLength(0);
|
|
275
|
+
}
|
|
276
|
+
),
|
|
277
|
+
{ numRuns: 100 }
|
|
278
|
+
);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// **Feature: tournament-seed-bounties, Property 4: Complexity Reduction Validation**
|
|
282
|
+
test('insufficient complexity reduction is invalid', () => {
|
|
283
|
+
fc.assert(
|
|
284
|
+
fc.property(
|
|
285
|
+
fc.integer({ min: 5, max: 20 }), // originalComplexity
|
|
286
|
+
fc.integer({ min: 3, max: 10 }), // minReduction
|
|
287
|
+
(originalComplexity, minReduction) => {
|
|
288
|
+
// Create insufficient reduction (less than minReduction)
|
|
289
|
+
const reduction = Math.max(0, minReduction - 1);
|
|
290
|
+
const suggestedComplexity = originalComplexity - reduction;
|
|
291
|
+
|
|
292
|
+
const artifact = {
|
|
293
|
+
refactorSuggestion: {
|
|
294
|
+
originalComplexity,
|
|
295
|
+
suggestedComplexity,
|
|
296
|
+
description: 'Insufficient refactor'
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const result = validateComplexityReduction(artifact, minReduction);
|
|
301
|
+
expect(result.valid).toBe(false);
|
|
302
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
303
|
+
}
|
|
304
|
+
),
|
|
305
|
+
{ numRuns: 100 }
|
|
306
|
+
);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// **Feature: tournament-seed-bounties, Property 4: Complexity Reduction Validation**
|
|
310
|
+
test('missing refactor suggestion is invalid', () => {
|
|
311
|
+
const artifact = {}; // No refactorSuggestion
|
|
312
|
+
const result = validateComplexityReduction(artifact, 2);
|
|
313
|
+
expect(result.valid).toBe(false);
|
|
314
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
315
|
+
expect(result.errors[0]).toContain('No refactor suggestion provided');
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// ============================================================================
|
|
320
|
+
// Lead Generation Battle Property Tests
|
|
321
|
+
// ============================================================================
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Property-based tests for ValidationResult Structure Consistency
|
|
325
|
+
*
|
|
326
|
+
* **Feature: tournament-seed-bounties, Property 7: ValidationResult Structure Consistency**
|
|
327
|
+
* **Validates: Requirements 3.2, 4.2, 1.8, 2.8**
|
|
328
|
+
*
|
|
329
|
+
* Property 7: ValidationResult Structure Consistency
|
|
330
|
+
* *For any* validator function call, the result SHALL have a valid boolean and an
|
|
331
|
+
* errors array where: if valid is true, errors is empty; if valid is false,
|
|
332
|
+
* errors contains at least one descriptive message.
|
|
333
|
+
*/
|
|
334
|
+
describe('ValidationResult Structure Consistency - Property Tests', () => {
|
|
335
|
+
// **Feature: tournament-seed-bounties, Property 7: ValidationResult Structure Consistency**
|
|
336
|
+
test('all validators return consistent ValidationResult structure', () => {
|
|
337
|
+
fc.assert(
|
|
338
|
+
fc.property(
|
|
339
|
+
fc.string(),
|
|
340
|
+
(linkedIn) => {
|
|
341
|
+
const result = validateLinkedIn(linkedIn);
|
|
342
|
+
|
|
343
|
+
// Must have valid boolean and errors array
|
|
344
|
+
expect(typeof result.valid).toBe('boolean');
|
|
345
|
+
expect(Array.isArray(result.errors)).toBe(true);
|
|
346
|
+
|
|
347
|
+
// If valid, errors should be empty; if invalid, errors should have content
|
|
348
|
+
if (result.valid) {
|
|
349
|
+
expect(result.errors).toHaveLength(0);
|
|
350
|
+
} else {
|
|
351
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
352
|
+
expect(result.errors.every(error => typeof error === 'string')).toBe(true);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
),
|
|
356
|
+
{ numRuns: 100 }
|
|
357
|
+
);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
// **Feature: tournament-seed-bounties, Property 7: ValidationResult Structure Consistency**
|
|
361
|
+
test('composite validators maintain structure consistency', () => {
|
|
362
|
+
fc.assert(
|
|
363
|
+
fc.property(
|
|
364
|
+
fc.record({
|
|
365
|
+
email: fc.string(),
|
|
366
|
+
companySize: fc.integer({ min: 0, max: 10000 }),
|
|
367
|
+
role: fc.string(),
|
|
368
|
+
linkedIn: fc.string()
|
|
369
|
+
}),
|
|
370
|
+
(artifact) => {
|
|
371
|
+
const result = validateLeadGenPrecision(artifact);
|
|
372
|
+
|
|
373
|
+
// Must have valid boolean and errors array
|
|
374
|
+
expect(typeof result.valid).toBe('boolean');
|
|
375
|
+
expect(Array.isArray(result.errors)).toBe(true);
|
|
376
|
+
|
|
377
|
+
// If valid, errors should be empty; if invalid, errors should have content
|
|
378
|
+
if (result.valid) {
|
|
379
|
+
expect(result.errors).toHaveLength(0);
|
|
380
|
+
} else {
|
|
381
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
382
|
+
expect(result.errors.every(error => typeof error === 'string')).toBe(true);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
),
|
|
386
|
+
{ numRuns: 100 }
|
|
387
|
+
);
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// ============================================================================
|
|
392
|
+
// Integration Property Tests
|
|
393
|
+
// ============================================================================
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Property-based tests for Expert Review Composite Validation
|
|
397
|
+
*
|
|
398
|
+
* Tests the validateExpertReview function which combines all code review validations.
|
|
399
|
+
*/
|
|
400
|
+
describe('Expert Review Composite Validation - Property Tests', () => {
|
|
401
|
+
test('expert review combines all validation errors', () => {
|
|
402
|
+
fc.assert(
|
|
403
|
+
fc.property(
|
|
404
|
+
fc.array(fc.record({
|
|
405
|
+
type: fc.constantFrom('style', 'logic'), // No security or performance
|
|
406
|
+
severity: fc.constantFrom('HIGH', 'MEDIUM', 'LOW'), // No CRITICAL
|
|
407
|
+
description: fc.string()
|
|
408
|
+
})),
|
|
409
|
+
fc.array(fc.record({
|
|
410
|
+
lineContent: fc.string(),
|
|
411
|
+
comment: fc.string(),
|
|
412
|
+
lineNumber: fc.integer({ min: 1, max: 100 })
|
|
413
|
+
})),
|
|
414
|
+
fc.string(),
|
|
415
|
+
(issues, comments, sourceDiff) => {
|
|
416
|
+
// Create artifact that will fail multiple validations
|
|
417
|
+
const artifact = {
|
|
418
|
+
issues,
|
|
419
|
+
comments,
|
|
420
|
+
// No refactorSuggestion
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const result = validateExpertReview(artifact, sourceDiff);
|
|
424
|
+
|
|
425
|
+
// Should be invalid and have multiple errors
|
|
426
|
+
expect(result.valid).toBe(false);
|
|
427
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
428
|
+
|
|
429
|
+
// Should contain specific error messages
|
|
430
|
+
const errorText = result.errors.join(' ');
|
|
431
|
+
expect(errorText).toContain('security');
|
|
432
|
+
expect(errorText).toContain('performance');
|
|
433
|
+
expect(errorText).toContain('refactor');
|
|
434
|
+
}
|
|
435
|
+
),
|
|
436
|
+
{ numRuns: 100 }
|
|
437
|
+
);
|
|
438
|
+
});
|
|
439
|
+
});
|