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.
Files changed (113) hide show
  1. package/README.md +261 -0
  2. package/package.json +95 -0
  3. package/src/agents/README.md +139 -0
  4. package/src/agents/adapters/anthropic.adapter.ts +166 -0
  5. package/src/agents/adapters/dalle.adapter.ts +145 -0
  6. package/src/agents/adapters/gemini.adapter.ts +134 -0
  7. package/src/agents/adapters/imagen.adapter.ts +106 -0
  8. package/src/agents/adapters/nano-banana.adapter.ts +129 -0
  9. package/src/agents/adapters/openai.adapter.ts +165 -0
  10. package/src/agents/adapters/veo.adapter.ts +130 -0
  11. package/src/agents/agent.schema.property.test.ts +379 -0
  12. package/src/agents/agent.schema.test.ts +148 -0
  13. package/src/agents/agent.schema.ts +263 -0
  14. package/src/agents/index.ts +60 -0
  15. package/src/agents/registered-agent.schema.ts +356 -0
  16. package/src/agents/registry.ts +97 -0
  17. package/src/agents/tournament-configs.property.test.ts +266 -0
  18. package/src/cli/README.md +145 -0
  19. package/src/cli/commands/define.ts +79 -0
  20. package/src/cli/commands/list.ts +46 -0
  21. package/src/cli/commands/logs.ts +83 -0
  22. package/src/cli/commands/run.ts +416 -0
  23. package/src/cli/commands/verify.ts +110 -0
  24. package/src/cli/index.ts +81 -0
  25. package/src/config/README.md +128 -0
  26. package/src/config/env.ts +262 -0
  27. package/src/config/index.ts +19 -0
  28. package/src/eval/README.md +318 -0
  29. package/src/eval/ai-judge.test.ts +435 -0
  30. package/src/eval/ai-judge.ts +368 -0
  31. package/src/eval/code-validators.ts +414 -0
  32. package/src/eval/evaluateOutcome.property.test.ts +1174 -0
  33. package/src/eval/evaluateOutcome.ts +591 -0
  34. package/src/eval/immigration-validators.ts +122 -0
  35. package/src/eval/index.ts +90 -0
  36. package/src/eval/judge-cache.ts +402 -0
  37. package/src/eval/tournament-validators.property.test.ts +439 -0
  38. package/src/eval/validators.property.test.ts +1118 -0
  39. package/src/eval/validators.ts +1199 -0
  40. package/src/eval/weighted-scorer.ts +285 -0
  41. package/src/index.ts +17 -0
  42. package/src/league/README.md +188 -0
  43. package/src/league/health-check.ts +353 -0
  44. package/src/league/index.ts +93 -0
  45. package/src/league/killAgent.ts +151 -0
  46. package/src/league/league.test.ts +1151 -0
  47. package/src/league/runLeague.ts +843 -0
  48. package/src/league/scoreAgent.ts +175 -0
  49. package/src/modules/omnibridge/__tests__/.gitkeep +1 -0
  50. package/src/modules/omnibridge/__tests__/auth-tunnel.property.test.ts +524 -0
  51. package/src/modules/omnibridge/__tests__/deterministic-logger.property.test.ts +965 -0
  52. package/src/modules/omnibridge/__tests__/ghost-api.property.test.ts +461 -0
  53. package/src/modules/omnibridge/__tests__/omnibridge-integration.test.ts +542 -0
  54. package/src/modules/omnibridge/__tests__/parallel-executor.property.test.ts +671 -0
  55. package/src/modules/omnibridge/__tests__/semantic-normalizer.property.test.ts +521 -0
  56. package/src/modules/omnibridge/__tests__/semantic-normalizer.test.ts +254 -0
  57. package/src/modules/omnibridge/__tests__/session-vault.property.test.ts +367 -0
  58. package/src/modules/omnibridge/__tests__/shadow-session.property.test.ts +523 -0
  59. package/src/modules/omnibridge/__tests__/triangulation-engine.property.test.ts +292 -0
  60. package/src/modules/omnibridge/__tests__/verification-engine.property.test.ts +769 -0
  61. package/src/modules/omnibridge/api/.gitkeep +1 -0
  62. package/src/modules/omnibridge/api/ghost-api.ts +1087 -0
  63. package/src/modules/omnibridge/auth/.gitkeep +1 -0
  64. package/src/modules/omnibridge/auth/auth-tunnel.ts +843 -0
  65. package/src/modules/omnibridge/auth/session-vault.ts +577 -0
  66. package/src/modules/omnibridge/core/.gitkeep +1 -0
  67. package/src/modules/omnibridge/core/semantic-normalizer.ts +702 -0
  68. package/src/modules/omnibridge/core/triangulation-engine.ts +530 -0
  69. package/src/modules/omnibridge/core/types.ts +610 -0
  70. package/src/modules/omnibridge/execution/.gitkeep +1 -0
  71. package/src/modules/omnibridge/execution/deterministic-logger.ts +629 -0
  72. package/src/modules/omnibridge/execution/parallel-executor.ts +542 -0
  73. package/src/modules/omnibridge/execution/shadow-session.ts +794 -0
  74. package/src/modules/omnibridge/index.ts +212 -0
  75. package/src/modules/omnibridge/omnibridge.ts +510 -0
  76. package/src/modules/omnibridge/verification/.gitkeep +1 -0
  77. package/src/modules/omnibridge/verification/verification-engine.ts +783 -0
  78. package/src/outcomes/README.md +75 -0
  79. package/src/outcomes/acquire-pilot-customer.ts +297 -0
  80. package/src/outcomes/code-delivery-outcomes.ts +89 -0
  81. package/src/outcomes/code-outcomes.ts +256 -0
  82. package/src/outcomes/code_review_battle.test.ts +135 -0
  83. package/src/outcomes/code_review_battle.ts +135 -0
  84. package/src/outcomes/cold_email_battle.ts +97 -0
  85. package/src/outcomes/content_creation_battle.ts +160 -0
  86. package/src/outcomes/f1_stem_opt_compliance.ts +61 -0
  87. package/src/outcomes/index.ts +107 -0
  88. package/src/outcomes/lead_gen_battle.test.ts +113 -0
  89. package/src/outcomes/lead_gen_battle.ts +99 -0
  90. package/src/outcomes/outcome.schema.property.test.ts +229 -0
  91. package/src/outcomes/outcome.schema.ts +187 -0
  92. package/src/outcomes/qualified_sales_interest.ts +118 -0
  93. package/src/outcomes/swarm_planner.property.test.ts +370 -0
  94. package/src/outcomes/swarm_planner.ts +96 -0
  95. package/src/outcomes/web_extraction.ts +234 -0
  96. package/src/runtime/README.md +220 -0
  97. package/src/runtime/agentRunner.test.ts +341 -0
  98. package/src/runtime/agentRunner.ts +746 -0
  99. package/src/runtime/claudeAdapter.ts +232 -0
  100. package/src/runtime/costTracker.ts +123 -0
  101. package/src/runtime/index.ts +34 -0
  102. package/src/runtime/modelAdapter.property.test.ts +305 -0
  103. package/src/runtime/modelAdapter.ts +144 -0
  104. package/src/runtime/openaiAdapter.ts +235 -0
  105. package/src/utils/README.md +122 -0
  106. package/src/utils/command-runner.ts +134 -0
  107. package/src/utils/cost-guard.ts +379 -0
  108. package/src/utils/errors.test.ts +290 -0
  109. package/src/utils/errors.ts +442 -0
  110. package/src/utils/index.ts +37 -0
  111. package/src/utils/logger.test.ts +361 -0
  112. package/src/utils/logger.ts +419 -0
  113. package/src/utils/output-parsers.ts +216 -0
@@ -0,0 +1,442 @@
1
+ /**
2
+ * Custom Error Types - Structured error handling for the Earnd Bounty Engine
3
+ *
4
+ * Provides typed error classes for different failure scenarios:
5
+ * - ValidationError: Invalid outcome/agent schemas, malformed data
6
+ * - ExecutionError: Model API failures, timeouts, network issues
7
+ * - LimitError: Cost ceiling, attempt limit, time limit exceeded
8
+ * - SystemError: Infrastructure failures, Durable Object issues
9
+ *
10
+ * @module utils/errors
11
+ * @see Requirements 5.4, 10.4
12
+ */
13
+
14
+ /**
15
+ * Error codes for structured error handling.
16
+ */
17
+ export enum ErrorCode {
18
+ // Validation errors (1xxx)
19
+ VALIDATION_SCHEMA_INVALID = 'VALIDATION_SCHEMA_INVALID',
20
+ VALIDATION_FIELD_MISSING = 'VALIDATION_FIELD_MISSING',
21
+ VALIDATION_FIELD_INVALID = 'VALIDATION_FIELD_INVALID',
22
+ VALIDATION_DATA_MALFORMED = 'VALIDATION_DATA_MALFORMED',
23
+
24
+ // Execution errors (2xxx)
25
+ EXECUTION_MODEL_FAILURE = 'EXECUTION_MODEL_FAILURE',
26
+ EXECUTION_TIMEOUT = 'EXECUTION_TIMEOUT',
27
+ EXECUTION_NETWORK_ERROR = 'EXECUTION_NETWORK_ERROR',
28
+ EXECUTION_RETRY_EXHAUSTED = 'EXECUTION_RETRY_EXHAUSTED',
29
+
30
+ // Limit errors (3xxx)
31
+ LIMIT_COST_EXCEEDED = 'LIMIT_COST_EXCEEDED',
32
+ LIMIT_ATTEMPTS_EXCEEDED = 'LIMIT_ATTEMPTS_EXCEEDED',
33
+ LIMIT_TIME_EXCEEDED = 'LIMIT_TIME_EXCEEDED',
34
+ LIMIT_GLOBAL_SPEND_EXCEEDED = 'LIMIT_GLOBAL_SPEND_EXCEEDED',
35
+
36
+ // System errors (4xxx)
37
+ SYSTEM_INFRASTRUCTURE_FAILURE = 'SYSTEM_INFRASTRUCTURE_FAILURE',
38
+ SYSTEM_STATE_CORRUPTION = 'SYSTEM_STATE_CORRUPTION',
39
+ SYSTEM_UNKNOWN_ERROR = 'SYSTEM_UNKNOWN_ERROR',
40
+ }
41
+
42
+ /**
43
+ * Structured error response format.
44
+ * Used for consistent error reporting across the system.
45
+ *
46
+ * @see design.md - Error Response Format
47
+ */
48
+ export interface ErrorResponse {
49
+ /** Error code for programmatic handling */
50
+ code: ErrorCode | string;
51
+ /** Human-readable error message */
52
+ message: string;
53
+ /** Additional context about the error */
54
+ details?: Record<string, unknown>;
55
+ /** Whether the error is potentially recoverable */
56
+ recoverable: boolean;
57
+ }
58
+
59
+ /**
60
+ * Base class for all Earnd Bounty Engine errors.
61
+ * Extends Error with structured response format.
62
+ */
63
+ export abstract class EarndError extends Error {
64
+ /** Error code for programmatic handling */
65
+ abstract readonly code: ErrorCode;
66
+ /** Whether the error is potentially recoverable */
67
+ abstract readonly recoverable: boolean;
68
+ /** Additional context about the error */
69
+ readonly details?: Record<string, unknown>;
70
+
71
+ constructor(message: string, details?: Record<string, unknown>) {
72
+ super(message);
73
+ this.name = this.constructor.name;
74
+ this.details = details;
75
+
76
+ // Maintains proper stack trace for where error was thrown
77
+ if (Error.captureStackTrace) {
78
+ Error.captureStackTrace(this, this.constructor);
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Converts the error to a structured ErrorResponse.
84
+ */
85
+ toResponse(): ErrorResponse {
86
+ return {
87
+ code: this.code,
88
+ message: this.message,
89
+ details: this.details,
90
+ recoverable: this.recoverable,
91
+ };
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Validation Error - Invalid schemas, malformed data
97
+ *
98
+ * Thrown when:
99
+ * - Outcome/agent schemas are invalid
100
+ * - Required fields are missing
101
+ * - Data fails validation rules
102
+ *
103
+ * @see Requirements 5.4 - Fail closed on unverifiable data
104
+ */
105
+ export class ValidationError extends EarndError {
106
+ readonly code: ErrorCode;
107
+ readonly recoverable = false; // Validation errors require fixing the input
108
+
109
+ constructor(
110
+ message: string,
111
+ code: ErrorCode = ErrorCode.VALIDATION_SCHEMA_INVALID,
112
+ details?: Record<string, unknown>
113
+ ) {
114
+ super(message, details);
115
+ this.code = code;
116
+ }
117
+
118
+ /**
119
+ * Creates a ValidationError for a missing field.
120
+ */
121
+ static missingField(fieldName: string, context?: string): ValidationError {
122
+ return new ValidationError(
123
+ `Missing required field: ${fieldName}${context ? ` in ${context}` : ''}`,
124
+ ErrorCode.VALIDATION_FIELD_MISSING,
125
+ { field: fieldName, context }
126
+ );
127
+ }
128
+
129
+ /**
130
+ * Creates a ValidationError for an invalid field value.
131
+ */
132
+ static invalidField(
133
+ fieldName: string,
134
+ reason: string,
135
+ value?: unknown
136
+ ): ValidationError {
137
+ return new ValidationError(
138
+ `Invalid field "${fieldName}": ${reason}`,
139
+ ErrorCode.VALIDATION_FIELD_INVALID,
140
+ { field: fieldName, reason, value }
141
+ );
142
+ }
143
+
144
+ /**
145
+ * Creates a ValidationError for malformed data.
146
+ */
147
+ static malformedData(message: string, details?: Record<string, unknown>): ValidationError {
148
+ return new ValidationError(message, ErrorCode.VALIDATION_DATA_MALFORMED, details);
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Execution Error - Model API failures, timeouts, network issues
154
+ *
155
+ * Thrown when:
156
+ * - Model API calls fail
157
+ * - Network requests timeout
158
+ * - Retries are exhausted
159
+ *
160
+ * These errors may be recoverable with retry logic.
161
+ */
162
+ export class ExecutionError extends EarndError {
163
+ readonly code: ErrorCode;
164
+ readonly recoverable: boolean;
165
+
166
+ constructor(
167
+ message: string,
168
+ code: ErrorCode = ErrorCode.EXECUTION_MODEL_FAILURE,
169
+ recoverable = true,
170
+ details?: Record<string, unknown>
171
+ ) {
172
+ super(message, details);
173
+ this.code = code;
174
+ this.recoverable = recoverable;
175
+ }
176
+
177
+ /**
178
+ * Creates an ExecutionError for a model API failure.
179
+ */
180
+ static modelFailure(
181
+ provider: string,
182
+ reason: string,
183
+ details?: Record<string, unknown>
184
+ ): ExecutionError {
185
+ return new ExecutionError(
186
+ `Model API failure (${provider}): ${reason}`,
187
+ ErrorCode.EXECUTION_MODEL_FAILURE,
188
+ true,
189
+ { provider, reason, ...details }
190
+ );
191
+ }
192
+
193
+ /**
194
+ * Creates an ExecutionError for a timeout.
195
+ */
196
+ static timeout(operation: string, durationMs: number): ExecutionError {
197
+ return new ExecutionError(
198
+ `Operation timed out: ${operation} after ${durationMs}ms`,
199
+ ErrorCode.EXECUTION_TIMEOUT,
200
+ true,
201
+ { operation, durationMs }
202
+ );
203
+ }
204
+
205
+ /**
206
+ * Creates an ExecutionError for a network error.
207
+ */
208
+ static networkError(message: string, details?: Record<string, unknown>): ExecutionError {
209
+ return new ExecutionError(
210
+ `Network error: ${message}`,
211
+ ErrorCode.EXECUTION_NETWORK_ERROR,
212
+ true,
213
+ details
214
+ );
215
+ }
216
+
217
+ /**
218
+ * Creates an ExecutionError when retries are exhausted.
219
+ */
220
+ static retryExhausted(
221
+ operation: string,
222
+ attempts: number,
223
+ lastError?: string
224
+ ): ExecutionError {
225
+ return new ExecutionError(
226
+ `Retries exhausted for ${operation} after ${attempts} attempts${lastError ? `: ${lastError}` : ''}`,
227
+ ErrorCode.EXECUTION_RETRY_EXHAUSTED,
228
+ false, // No more retries possible
229
+ { operation, attempts, lastError }
230
+ );
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Limit Error - Cost ceiling, attempt limit, time limit exceeded
236
+ *
237
+ * Thrown when:
238
+ * - Agent exceeds cost ceiling
239
+ * - Agent exceeds attempt limit
240
+ * - Agent exceeds time limit
241
+ * - Global spend ceiling is exceeded
242
+ *
243
+ * @see Requirements 10.4 - Fail closed with no payout on limit exceeded
244
+ */
245
+ export class LimitError extends EarndError {
246
+ readonly code: ErrorCode;
247
+ readonly recoverable = false; // Limit errors mean termination
248
+
249
+ constructor(
250
+ message: string,
251
+ code: ErrorCode = ErrorCode.LIMIT_COST_EXCEEDED,
252
+ details?: Record<string, unknown>
253
+ ) {
254
+ super(message, details);
255
+ this.code = code;
256
+ }
257
+
258
+ /**
259
+ * Creates a LimitError for cost ceiling exceeded.
260
+ */
261
+ static costExceeded(
262
+ agentId: string,
263
+ spent: number,
264
+ ceiling: number
265
+ ): LimitError {
266
+ return new LimitError(
267
+ `Agent ${agentId} exceeded cost ceiling: ${spent} > ${ceiling} tokens`,
268
+ ErrorCode.LIMIT_COST_EXCEEDED,
269
+ { agentId, spent, ceiling }
270
+ );
271
+ }
272
+
273
+ /**
274
+ * Creates a LimitError for attempts exceeded.
275
+ */
276
+ static attemptsExceeded(
277
+ agentId: string,
278
+ attempts: number,
279
+ maxAttempts: number
280
+ ): LimitError {
281
+ return new LimitError(
282
+ `Agent ${agentId} exceeded attempt limit: ${attempts} >= ${maxAttempts}`,
283
+ ErrorCode.LIMIT_ATTEMPTS_EXCEEDED,
284
+ { agentId, attempts, maxAttempts }
285
+ );
286
+ }
287
+
288
+ /**
289
+ * Creates a LimitError for time limit exceeded.
290
+ */
291
+ static timeExceeded(
292
+ agentId: string,
293
+ elapsedMs: number,
294
+ limitMs: number
295
+ ): LimitError {
296
+ return new LimitError(
297
+ `Agent ${agentId} exceeded time limit: ${elapsedMs}ms >= ${limitMs}ms`,
298
+ ErrorCode.LIMIT_TIME_EXCEEDED,
299
+ { agentId, elapsedMs, limitMs }
300
+ );
301
+ }
302
+
303
+ /**
304
+ * Creates a LimitError for global spend ceiling exceeded.
305
+ */
306
+ static globalSpendExceeded(
307
+ totalSpent: number,
308
+ ceiling: number
309
+ ): LimitError {
310
+ return new LimitError(
311
+ `Global spend ceiling exceeded: ${totalSpent} > ${ceiling}`,
312
+ ErrorCode.LIMIT_GLOBAL_SPEND_EXCEEDED,
313
+ { totalSpent, ceiling }
314
+ );
315
+ }
316
+ }
317
+
318
+ /**
319
+ * System Error - Infrastructure failures, state corruption
320
+ *
321
+ * Thrown when:
322
+ * - Cloudflare Worker/Durable Object failures
323
+ * - State corruption detected
324
+ * - Unknown system errors occur
325
+ *
326
+ * These errors typically require operator intervention.
327
+ */
328
+ export class SystemError extends EarndError {
329
+ readonly code: ErrorCode;
330
+ readonly recoverable = false; // System errors require intervention
331
+
332
+ constructor(
333
+ message: string,
334
+ code: ErrorCode = ErrorCode.SYSTEM_UNKNOWN_ERROR,
335
+ details?: Record<string, unknown>
336
+ ) {
337
+ super(message, details);
338
+ this.code = code;
339
+ }
340
+
341
+ /**
342
+ * Creates a SystemError for infrastructure failure.
343
+ */
344
+ static infrastructureFailure(
345
+ component: string,
346
+ reason: string,
347
+ details?: Record<string, unknown>
348
+ ): SystemError {
349
+ return new SystemError(
350
+ `Infrastructure failure in ${component}: ${reason}`,
351
+ ErrorCode.SYSTEM_INFRASTRUCTURE_FAILURE,
352
+ { component, reason, ...details }
353
+ );
354
+ }
355
+
356
+ /**
357
+ * Creates a SystemError for state corruption.
358
+ */
359
+ static stateCorruption(
360
+ context: string,
361
+ details?: Record<string, unknown>
362
+ ): SystemError {
363
+ return new SystemError(
364
+ `State corruption detected: ${context}`,
365
+ ErrorCode.SYSTEM_STATE_CORRUPTION,
366
+ { context, ...details }
367
+ );
368
+ }
369
+
370
+ /**
371
+ * Creates a SystemError from an unknown error.
372
+ */
373
+ static fromUnknown(error: unknown): SystemError {
374
+ const message = error instanceof Error ? error.message : String(error);
375
+ const stack = error instanceof Error ? error.stack : undefined;
376
+ return new SystemError(
377
+ `Unknown system error: ${message}`,
378
+ ErrorCode.SYSTEM_UNKNOWN_ERROR,
379
+ { originalMessage: message, stack }
380
+ );
381
+ }
382
+ }
383
+
384
+ /**
385
+ * Type guard to check if an error is an EarndError.
386
+ */
387
+ export function isEarndError(error: unknown): error is EarndError {
388
+ return error instanceof EarndError;
389
+ }
390
+
391
+ /**
392
+ * Type guard to check if an error is a ValidationError.
393
+ */
394
+ export function isValidationError(error: unknown): error is ValidationError {
395
+ return error instanceof ValidationError;
396
+ }
397
+
398
+ /**
399
+ * Type guard to check if an error is an ExecutionError.
400
+ */
401
+ export function isExecutionError(error: unknown): error is ExecutionError {
402
+ return error instanceof ExecutionError;
403
+ }
404
+
405
+ /**
406
+ * Type guard to check if an error is a LimitError.
407
+ */
408
+ export function isLimitError(error: unknown): error is LimitError {
409
+ return error instanceof LimitError;
410
+ }
411
+
412
+ /**
413
+ * Type guard to check if an error is a SystemError.
414
+ */
415
+ export function isSystemError(error: unknown): error is SystemError {
416
+ return error instanceof SystemError;
417
+ }
418
+
419
+ /**
420
+ * Converts any error to an ErrorResponse.
421
+ * Useful for consistent error handling at API boundaries.
422
+ */
423
+ export function toErrorResponse(error: unknown): ErrorResponse {
424
+ if (isEarndError(error)) {
425
+ return error.toResponse();
426
+ }
427
+
428
+ if (error instanceof Error) {
429
+ return {
430
+ code: ErrorCode.SYSTEM_UNKNOWN_ERROR,
431
+ message: error.message,
432
+ details: { name: error.name, stack: error.stack },
433
+ recoverable: false,
434
+ };
435
+ }
436
+
437
+ return {
438
+ code: ErrorCode.SYSTEM_UNKNOWN_ERROR,
439
+ message: String(error),
440
+ recoverable: false,
441
+ };
442
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Utils Module - Shared utilities for the Earnd Bounty Engine
3
+ *
4
+ * @module utils
5
+ */
6
+
7
+ export {
8
+ type LogResult,
9
+ type LogEntry,
10
+ type LogEntryInput,
11
+ log,
12
+ getLogs,
13
+ getAgentLogs,
14
+ clearLogs,
15
+ clearAllLogs,
16
+ getTotalLogCount,
17
+ formatLogsForCli,
18
+ logSuccess,
19
+ logFailure,
20
+ logPending,
21
+ } from './logger.js';
22
+
23
+ export {
24
+ ErrorCode,
25
+ type ErrorResponse,
26
+ EarndError,
27
+ ValidationError,
28
+ ExecutionError,
29
+ LimitError,
30
+ SystemError,
31
+ isEarndError,
32
+ isValidationError,
33
+ isExecutionError,
34
+ isLimitError,
35
+ isSystemError,
36
+ toErrorResponse,
37
+ } from './errors.js';