copilot-liku-cli 0.0.1
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/ARCHITECTURE.md +411 -0
- package/CONFIGURATION.md +302 -0
- package/CONTRIBUTING.md +225 -0
- package/ELECTRON_README.md +121 -0
- package/INSTALLATION.md +350 -0
- package/LICENSE.md +1 -0
- package/PROJECT_STATUS.md +229 -0
- package/QUICKSTART.md +255 -0
- package/README.md +167 -0
- package/TESTING.md +274 -0
- package/package.json +61 -0
- package/scripts/start.js +30 -0
- package/src/assets/tray-icon.png +0 -0
- package/src/cli/commands/agent.js +327 -0
- package/src/cli/commands/click.js +108 -0
- package/src/cli/commands/drag.js +85 -0
- package/src/cli/commands/find.js +109 -0
- package/src/cli/commands/keys.js +132 -0
- package/src/cli/commands/mouse.js +79 -0
- package/src/cli/commands/repl.js +290 -0
- package/src/cli/commands/screenshot.js +72 -0
- package/src/cli/commands/scroll.js +74 -0
- package/src/cli/commands/start.js +67 -0
- package/src/cli/commands/type.js +57 -0
- package/src/cli/commands/wait.js +84 -0
- package/src/cli/commands/window.js +104 -0
- package/src/cli/liku.js +249 -0
- package/src/cli/util/output.js +174 -0
- package/src/main/agents/base-agent.js +410 -0
- package/src/main/agents/builder.js +484 -0
- package/src/main/agents/index.js +62 -0
- package/src/main/agents/orchestrator.js +362 -0
- package/src/main/agents/researcher.js +511 -0
- package/src/main/agents/state-manager.js +344 -0
- package/src/main/agents/supervisor.js +365 -0
- package/src/main/agents/verifier.js +452 -0
- package/src/main/ai-service.js +1633 -0
- package/src/main/index.js +2208 -0
- package/src/main/inspect-service.js +467 -0
- package/src/main/system-automation.js +1186 -0
- package/src/main/ui-automation/config.js +76 -0
- package/src/main/ui-automation/core/helpers.js +41 -0
- package/src/main/ui-automation/core/index.js +15 -0
- package/src/main/ui-automation/core/powershell.js +82 -0
- package/src/main/ui-automation/elements/finder.js +274 -0
- package/src/main/ui-automation/elements/index.js +14 -0
- package/src/main/ui-automation/elements/wait.js +66 -0
- package/src/main/ui-automation/index.js +164 -0
- package/src/main/ui-automation/interactions/element-click.js +211 -0
- package/src/main/ui-automation/interactions/high-level.js +230 -0
- package/src/main/ui-automation/interactions/index.js +47 -0
- package/src/main/ui-automation/keyboard/index.js +15 -0
- package/src/main/ui-automation/keyboard/input.js +179 -0
- package/src/main/ui-automation/mouse/click.js +186 -0
- package/src/main/ui-automation/mouse/drag.js +88 -0
- package/src/main/ui-automation/mouse/index.js +30 -0
- package/src/main/ui-automation/mouse/movement.js +51 -0
- package/src/main/ui-automation/mouse/scroll.js +116 -0
- package/src/main/ui-automation/screenshot.js +183 -0
- package/src/main/ui-automation/window/index.js +23 -0
- package/src/main/ui-automation/window/manager.js +305 -0
- package/src/main/utils/time.js +62 -0
- package/src/main/visual-awareness.js +597 -0
- package/src/renderer/chat/chat.js +671 -0
- package/src/renderer/chat/index.html +725 -0
- package/src/renderer/chat/preload.js +112 -0
- package/src/renderer/overlay/index.html +648 -0
- package/src/renderer/overlay/overlay.js +782 -0
- package/src/renderer/overlay/preload.js +90 -0
- package/src/shared/grid-math.js +82 -0
- package/src/shared/inspect-types.js +230 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verifier Agent
|
|
3
|
+
*
|
|
4
|
+
* Runs phased verification on Builder changes and returns proofs plus pass/fail verdict.
|
|
5
|
+
* READ-ONLY: Does not edit files.
|
|
6
|
+
*
|
|
7
|
+
* Operating Rules:
|
|
8
|
+
* - Verify based on provided diffs/outputs; do not speculate
|
|
9
|
+
* - Prefer smallest, most relevant checks first, then broaden
|
|
10
|
+
* - Phased verification: Lint → Build → Unit → Integration → E2E
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const { BaseAgent, AgentRole, AgentCapabilities } = require('./base-agent');
|
|
14
|
+
|
|
15
|
+
class VerifierAgent extends BaseAgent {
|
|
16
|
+
constructor(options = {}) {
|
|
17
|
+
super({
|
|
18
|
+
...options,
|
|
19
|
+
role: AgentRole.VERIFIER,
|
|
20
|
+
name: options.name || 'verifier',
|
|
21
|
+
description: 'Validates changes with phased verification pipeline',
|
|
22
|
+
capabilities: [
|
|
23
|
+
AgentCapabilities.SEARCH,
|
|
24
|
+
AgentCapabilities.READ,
|
|
25
|
+
AgentCapabilities.EXECUTE,
|
|
26
|
+
AgentCapabilities.TODO,
|
|
27
|
+
AgentCapabilities.HANDOFF
|
|
28
|
+
]
|
|
29
|
+
// NOTE: No EDIT capability - Verifier is read-only
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Verifier-specific state
|
|
33
|
+
this.verificationResults = [];
|
|
34
|
+
this.currentPhase = null;
|
|
35
|
+
this.verdict = null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getSystemPrompt() {
|
|
39
|
+
return `You are the VERIFIER agent in a multi-agent coding system.
|
|
40
|
+
|
|
41
|
+
# OPERATING CONTRACT (NON-NEGOTIABLE)
|
|
42
|
+
- **No guessing**: Verify based on provided changes only.
|
|
43
|
+
- **Preserve functionalities**: Read-only; no edits.
|
|
44
|
+
- **Modularity & robustness**: Phase-based verification.
|
|
45
|
+
- **Least privilege**: Read-only access only.
|
|
46
|
+
- **Recursion limits**: Depth ≤3; avoid >10 sub-calls without progress.
|
|
47
|
+
- **Security**: Check invariants/regressions; fail on issues.
|
|
48
|
+
- **Background hygiene**: PID-track long-running tests.
|
|
49
|
+
|
|
50
|
+
# YOUR RESPONSIBILITIES
|
|
51
|
+
1. Receive changes from Builder/Supervisor
|
|
52
|
+
2. Run verification pipeline sequentially
|
|
53
|
+
3. Provide proofs/logs for each phase
|
|
54
|
+
4. Issue verdict: Pass/fail + suggestions
|
|
55
|
+
5. Hand off back to Supervisor
|
|
56
|
+
|
|
57
|
+
# VERIFICATION PIPELINE
|
|
58
|
+
Phase 1: LINT - ESLint/Prettier/code style
|
|
59
|
+
Phase 2: BUILD - Compilation/bundling
|
|
60
|
+
Phase 3: UNIT TESTS - Framework-specific unit tests
|
|
61
|
+
Phase 4: INTEGRATION - API tests, service integration
|
|
62
|
+
Phase 5: E2E - Playwright/Cypress end-to-end (optional)
|
|
63
|
+
|
|
64
|
+
# OUTPUT FORMAT
|
|
65
|
+
Always structure your response as:
|
|
66
|
+
1. Phase: [current phase]
|
|
67
|
+
2. Command: [what was run]
|
|
68
|
+
3. Result: [pass/fail]
|
|
69
|
+
4. Output: [relevant logs]
|
|
70
|
+
5. Issues: [any problems found]
|
|
71
|
+
6. Verdict: [overall pass/fail]
|
|
72
|
+
7. Suggestions: [if failed, what to fix]`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async process(task, context = {}) {
|
|
76
|
+
this.log('info', 'Verifier processing task', { task: task.description || task });
|
|
77
|
+
|
|
78
|
+
// Check recursion limits
|
|
79
|
+
const limits = this.checkRecursionLimits();
|
|
80
|
+
if (!limits.allowed) {
|
|
81
|
+
return {
|
|
82
|
+
success: false,
|
|
83
|
+
error: limits.reason,
|
|
84
|
+
phase: 'pre-check'
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
this.enterRecursion();
|
|
90
|
+
|
|
91
|
+
// Extract changes to verify
|
|
92
|
+
const changes = context.diffs || context.changes || [];
|
|
93
|
+
const changedFiles = changes.map(c => c.file).filter(Boolean);
|
|
94
|
+
|
|
95
|
+
// Run verification pipeline
|
|
96
|
+
const results = await this.runVerificationPipeline(changedFiles, context);
|
|
97
|
+
|
|
98
|
+
// Compile verdict
|
|
99
|
+
const verdict = this.compileVerdict(results);
|
|
100
|
+
this.verdict = verdict;
|
|
101
|
+
|
|
102
|
+
this.exitRecursion();
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
success: verdict.passed,
|
|
106
|
+
verdict,
|
|
107
|
+
results: this.verificationResults,
|
|
108
|
+
suggestedNext: verdict.passed ? 'complete' : 'supervisor',
|
|
109
|
+
suggestions: verdict.suggestions
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
} catch (error) {
|
|
113
|
+
this.exitRecursion();
|
|
114
|
+
return {
|
|
115
|
+
success: false,
|
|
116
|
+
error: error.message,
|
|
117
|
+
phase: this.currentPhase,
|
|
118
|
+
partialResults: this.verificationResults
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async runVerificationPipeline(changedFiles, context) {
|
|
124
|
+
const phases = [
|
|
125
|
+
{ name: 'lint', fn: () => this.runLint(changedFiles) },
|
|
126
|
+
{ name: 'build', fn: () => this.runBuild() },
|
|
127
|
+
{ name: 'unit', fn: () => this.runUnitTests(changedFiles) },
|
|
128
|
+
{ name: 'integration', fn: () => this.runIntegrationTests(context) },
|
|
129
|
+
// E2E is optional and expensive - only run if explicitly requested
|
|
130
|
+
...(context.includeE2E ? [{ name: 'e2e', fn: () => this.runE2ETests(context) }] : [])
|
|
131
|
+
];
|
|
132
|
+
|
|
133
|
+
const results = [];
|
|
134
|
+
|
|
135
|
+
for (const phase of phases) {
|
|
136
|
+
this.currentPhase = phase.name;
|
|
137
|
+
this.log('info', `Starting verification phase: ${phase.name}`);
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
const result = await phase.fn();
|
|
141
|
+
results.push({
|
|
142
|
+
phase: phase.name,
|
|
143
|
+
...result,
|
|
144
|
+
timestamp: new Date().toISOString()
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
this.verificationResults.push(result);
|
|
148
|
+
|
|
149
|
+
// Stop on first failure unless told to continue
|
|
150
|
+
if (!result.passed && !context.continueOnFailure) {
|
|
151
|
+
this.log('warn', `Phase ${phase.name} failed, stopping pipeline`);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
} catch (error) {
|
|
156
|
+
results.push({
|
|
157
|
+
phase: phase.name,
|
|
158
|
+
passed: false,
|
|
159
|
+
error: error.message,
|
|
160
|
+
timestamp: new Date().toISOString()
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
if (!context.continueOnFailure) {
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return results;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async runLint(changedFiles) {
|
|
173
|
+
this.log('info', 'Running lint verification');
|
|
174
|
+
|
|
175
|
+
const commands = [
|
|
176
|
+
'npm run lint --if-present 2>&1',
|
|
177
|
+
'npx eslint --ext .js,.ts,.jsx,.tsx . 2>&1 || true',
|
|
178
|
+
'npx prettier --check . 2>&1 || true'
|
|
179
|
+
];
|
|
180
|
+
|
|
181
|
+
const outputs = [];
|
|
182
|
+
let passed = true;
|
|
183
|
+
const issues = [];
|
|
184
|
+
|
|
185
|
+
for (const cmd of commands) {
|
|
186
|
+
try {
|
|
187
|
+
const result = await this.execute(cmd, { timeout: 60000 });
|
|
188
|
+
outputs.push({
|
|
189
|
+
command: cmd,
|
|
190
|
+
output: result.stdout,
|
|
191
|
+
error: result.stderr
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
if (result.stderr?.includes('error') || result.stdout?.includes('error')) {
|
|
195
|
+
passed = false;
|
|
196
|
+
issues.push(this.extractLintIssues(result.stdout || result.stderr));
|
|
197
|
+
}
|
|
198
|
+
} catch (error) {
|
|
199
|
+
// Lint commands may exit non-zero, that's okay
|
|
200
|
+
outputs.push({ command: cmd, error: error.message });
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this.addProof('lint', JSON.stringify(outputs).slice(0, 1000));
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
phase: 'lint',
|
|
208
|
+
passed,
|
|
209
|
+
outputs,
|
|
210
|
+
issues: issues.flat()
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
extractLintIssues(output) {
|
|
215
|
+
const issues = [];
|
|
216
|
+
const lines = output.split('\n');
|
|
217
|
+
|
|
218
|
+
for (const line of lines) {
|
|
219
|
+
if (/error|warning/i.test(line) && line.includes(':')) {
|
|
220
|
+
issues.push(line.trim());
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return issues.slice(0, 20); // Limit to first 20 issues
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async runBuild() {
|
|
228
|
+
this.log('info', 'Running build verification');
|
|
229
|
+
|
|
230
|
+
const buildCommands = [
|
|
231
|
+
'npm run build --if-present 2>&1',
|
|
232
|
+
'npx tsc --noEmit 2>&1 || true'
|
|
233
|
+
];
|
|
234
|
+
|
|
235
|
+
let passed = true;
|
|
236
|
+
const outputs = [];
|
|
237
|
+
const errors = [];
|
|
238
|
+
|
|
239
|
+
for (const cmd of buildCommands) {
|
|
240
|
+
try {
|
|
241
|
+
const result = await this.execute(cmd, { timeout: 120000 });
|
|
242
|
+
outputs.push({
|
|
243
|
+
command: cmd,
|
|
244
|
+
output: result.stdout?.slice(0, 2000),
|
|
245
|
+
exitCode: result.success ? 0 : 1
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
if (!result.success || result.stderr?.includes('error')) {
|
|
249
|
+
passed = false;
|
|
250
|
+
errors.push(result.stderr || result.stdout);
|
|
251
|
+
}
|
|
252
|
+
} catch (error) {
|
|
253
|
+
outputs.push({ command: cmd, error: error.message });
|
|
254
|
+
passed = false;
|
|
255
|
+
errors.push(error.message);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
this.addProof('build', passed ? 'Build passed' : errors.join('\n').slice(0, 500));
|
|
260
|
+
|
|
261
|
+
return {
|
|
262
|
+
phase: 'build',
|
|
263
|
+
passed,
|
|
264
|
+
outputs,
|
|
265
|
+
errors
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async runUnitTests(changedFiles) {
|
|
270
|
+
this.log('info', 'Running unit test verification');
|
|
271
|
+
|
|
272
|
+
// Determine test framework
|
|
273
|
+
let testCommand = 'npm test 2>&1';
|
|
274
|
+
|
|
275
|
+
// If specific files changed, try to run only related tests
|
|
276
|
+
if (changedFiles.length > 0 && changedFiles.length < 10) {
|
|
277
|
+
const testPatterns = changedFiles
|
|
278
|
+
.map(f => f.replace(/\.(js|ts|jsx|tsx)$/, ''))
|
|
279
|
+
.join('|');
|
|
280
|
+
testCommand = `npm test -- --testPathPattern="${testPatterns}" 2>&1 || npm test 2>&1`;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
try {
|
|
284
|
+
const result = await this.execute(testCommand, { timeout: 180000 });
|
|
285
|
+
|
|
286
|
+
const passed = result.success &&
|
|
287
|
+
(result.stdout?.includes('passed') || !result.stdout?.includes('failed'));
|
|
288
|
+
|
|
289
|
+
const testCounts = this.parseTestOutput(result.stdout || '');
|
|
290
|
+
|
|
291
|
+
this.addProof('unit-tests',
|
|
292
|
+
`${testCounts.passed} passed, ${testCounts.failed} failed`
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
return {
|
|
296
|
+
phase: 'unit',
|
|
297
|
+
passed,
|
|
298
|
+
output: result.stdout?.slice(0, 3000),
|
|
299
|
+
testCounts,
|
|
300
|
+
errors: result.stderr
|
|
301
|
+
};
|
|
302
|
+
} catch (error) {
|
|
303
|
+
return {
|
|
304
|
+
phase: 'unit',
|
|
305
|
+
passed: false,
|
|
306
|
+
error: error.message,
|
|
307
|
+
testCounts: { passed: 0, failed: 0, skipped: 0 }
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
parseTestOutput(output) {
|
|
313
|
+
const counts = { passed: 0, failed: 0, skipped: 0 };
|
|
314
|
+
|
|
315
|
+
// Jest format
|
|
316
|
+
const jestMatch = output.match(/(\d+) passed.*?(\d+) failed/);
|
|
317
|
+
if (jestMatch) {
|
|
318
|
+
counts.passed = parseInt(jestMatch[1]) || 0;
|
|
319
|
+
counts.failed = parseInt(jestMatch[2]) || 0;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Mocha format
|
|
323
|
+
const mochaMatch = output.match(/(\d+) passing.*?(\d+) failing/);
|
|
324
|
+
if (mochaMatch) {
|
|
325
|
+
counts.passed = parseInt(mochaMatch[1]) || 0;
|
|
326
|
+
counts.failed = parseInt(mochaMatch[2]) || 0;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return counts;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async runIntegrationTests(context) {
|
|
333
|
+
this.log('info', 'Running integration test verification');
|
|
334
|
+
|
|
335
|
+
// Check if integration tests exist
|
|
336
|
+
const integrationCommands = [
|
|
337
|
+
'npm run test:integration --if-present 2>&1',
|
|
338
|
+
'npm run test:api --if-present 2>&1'
|
|
339
|
+
];
|
|
340
|
+
|
|
341
|
+
let ranAny = false;
|
|
342
|
+
let passed = true;
|
|
343
|
+
const outputs = [];
|
|
344
|
+
|
|
345
|
+
for (const cmd of integrationCommands) {
|
|
346
|
+
try {
|
|
347
|
+
const result = await this.execute(cmd, { timeout: 300000 });
|
|
348
|
+
|
|
349
|
+
if (!result.stdout?.includes('No integration tests')) {
|
|
350
|
+
ranAny = true;
|
|
351
|
+
outputs.push({
|
|
352
|
+
command: cmd,
|
|
353
|
+
output: result.stdout?.slice(0, 2000),
|
|
354
|
+
passed: result.success
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
if (!result.success) {
|
|
358
|
+
passed = false;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
} catch (error) {
|
|
362
|
+
// Integration tests may not exist
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return {
|
|
367
|
+
phase: 'integration',
|
|
368
|
+
passed: ranAny ? passed : true,
|
|
369
|
+
skipped: !ranAny,
|
|
370
|
+
outputs
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
async runE2ETests(context) {
|
|
375
|
+
this.log('info', 'Running E2E test verification');
|
|
376
|
+
|
|
377
|
+
// Playwright E2E
|
|
378
|
+
try {
|
|
379
|
+
// Start with critical path only
|
|
380
|
+
const result = await this.execute(
|
|
381
|
+
'npx playwright test --grep "critical-path" 2>&1 || npx playwright test 2>&1',
|
|
382
|
+
{ timeout: 600000 }
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
const passed = result.success && !result.stdout?.includes('failed');
|
|
386
|
+
|
|
387
|
+
this.addProof('e2e', passed ? 'E2E passed' : 'E2E failed');
|
|
388
|
+
|
|
389
|
+
return {
|
|
390
|
+
phase: 'e2e',
|
|
391
|
+
passed,
|
|
392
|
+
output: result.stdout?.slice(0, 3000),
|
|
393
|
+
traceAvailable: result.stdout?.includes('trace')
|
|
394
|
+
};
|
|
395
|
+
} catch (error) {
|
|
396
|
+
return {
|
|
397
|
+
phase: 'e2e',
|
|
398
|
+
passed: false,
|
|
399
|
+
error: error.message
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
compileVerdict(results) {
|
|
405
|
+
const allPassed = results.every(r => r.passed || r.skipped);
|
|
406
|
+
const failedPhases = results.filter(r => !r.passed && !r.skipped);
|
|
407
|
+
|
|
408
|
+
const suggestions = [];
|
|
409
|
+
|
|
410
|
+
for (const failed of failedPhases) {
|
|
411
|
+
switch (failed.phase) {
|
|
412
|
+
case 'lint':
|
|
413
|
+
suggestions.push('Fix linting errors before proceeding');
|
|
414
|
+
break;
|
|
415
|
+
case 'build':
|
|
416
|
+
suggestions.push('Resolve build/compilation errors');
|
|
417
|
+
break;
|
|
418
|
+
case 'unit':
|
|
419
|
+
suggestions.push('Fix failing unit tests');
|
|
420
|
+
break;
|
|
421
|
+
case 'integration':
|
|
422
|
+
suggestions.push('Address integration test failures');
|
|
423
|
+
break;
|
|
424
|
+
case 'e2e':
|
|
425
|
+
suggestions.push('Review E2E test failures, check traces');
|
|
426
|
+
break;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
return {
|
|
431
|
+
passed: allPassed,
|
|
432
|
+
summary: {
|
|
433
|
+
total: results.length,
|
|
434
|
+
passed: results.filter(r => r.passed).length,
|
|
435
|
+
failed: failedPhases.length,
|
|
436
|
+
skipped: results.filter(r => r.skipped).length
|
|
437
|
+
},
|
|
438
|
+
failedPhases: failedPhases.map(f => f.phase),
|
|
439
|
+
suggestions,
|
|
440
|
+
timestamp: new Date().toISOString()
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
reset() {
|
|
445
|
+
super.reset();
|
|
446
|
+
this.verificationResults = [];
|
|
447
|
+
this.currentPhase = null;
|
|
448
|
+
this.verdict = null;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
module.exports = { VerifierAgent };
|