ai-maestro 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/CHANGELOG.md +11 -0
- package/LICENSE +15 -0
- package/README.md +727 -0
- package/bin/maestro.mjs +246 -0
- package/package.json +29 -0
- package/src/checkpoint.mjs +102 -0
- package/src/codex-diagnostics.mjs +682 -0
- package/src/codex-home-inspect.mjs +252 -0
- package/src/codex-home.mjs +258 -0
- package/src/commands.mjs +809 -0
- package/src/config.mjs +11 -0
- package/src/debug.mjs +164 -0
- package/src/encoding-guard.mjs +125 -0
- package/src/engines/ai-router-engine.mjs +37 -0
- package/src/engines/codex-engine.mjs +21 -0
- package/src/engines/engine.mjs +21 -0
- package/src/engines/registry.mjs +29 -0
- package/src/files.mjs +65 -0
- package/src/format.mjs +132 -0
- package/src/lock.mjs +439 -0
- package/src/memory-log.mjs +18 -0
- package/src/memory.mjs +1 -0
- package/src/orchestration/attempt-chain-runtime.mjs +627 -0
- package/src/orchestration/budget-manager.mjs +121 -0
- package/src/orchestration/capability-registry.mjs +108 -0
- package/src/orchestration/consolidator.mjs +772 -0
- package/src/orchestration/delegation-executor.mjs +262 -0
- package/src/orchestration/delegation-manager.mjs +116 -0
- package/src/orchestration/deployment-intent.mjs +36 -0
- package/src/orchestration/engine-history.mjs +110 -0
- package/src/orchestration/engine-policy.mjs +73 -0
- package/src/orchestration/engine-selector.mjs +187 -0
- package/src/orchestration/execution-context.mjs +45 -0
- package/src/orchestration/failure-classifier.mjs +136 -0
- package/src/orchestration/failure-evidence.mjs +237 -0
- package/src/orchestration/fallback-chain-lock.mjs +217 -0
- package/src/orchestration/fallback-chain-trail.mjs +218 -0
- package/src/orchestration/fallback-executor.mjs +146 -0
- package/src/orchestration/fallback-graph.mjs +106 -0
- package/src/orchestration/fallback-recommendation.mjs +73 -0
- package/src/orchestration/file-conflict-detector.mjs +126 -0
- package/src/orchestration/host-validation.mjs +241 -0
- package/src/orchestration/orchestration-loop.mjs +1971 -0
- package/src/orchestration/orchestration-runtime.mjs +1019 -0
- package/src/orchestration/orchestration-scheduler.mjs +135 -0
- package/src/orchestration/orchestration-trail.mjs +192 -0
- package/src/orchestration/preflight.mjs +212 -0
- package/src/orchestration/provider-health.mjs +566 -0
- package/src/orchestration/provider-router.mjs +352 -0
- package/src/orchestration/rc-check-adapters.mjs +817 -0
- package/src/orchestration/rc-check.mjs +544 -0
- package/src/orchestration/rc-policy.mjs +200 -0
- package/src/orchestration/runtime-gate.mjs +146 -0
- package/src/orchestration/sector-managers.mjs +215 -0
- package/src/orchestration/self-hosting-canary.mjs +231 -0
- package/src/orchestration/self-hosting-readiness.mjs +244 -0
- package/src/orchestration/spec-planner.mjs +877 -0
- package/src/orchestration/subtask-planner.mjs +176 -0
- package/src/orchestration/task-classifier.mjs +241 -0
- package/src/orchestration/verifier.mjs +1608 -0
- package/src/orchestration-commands.mjs +279 -0
- package/src/planner.mjs +38 -0
- package/src/project.mjs +1 -0
- package/src/run-diagnostics.mjs +641 -0
- package/src/runner.mjs +243 -0
- package/src/safety.mjs +116 -0
- package/src/schema.mjs +371 -0
- package/src/session-commands.mjs +521 -0
- package/src/shell.mjs +93 -0
- package/src/smart-planner.mjs +249 -0
- package/src/task-commands.mjs +1182 -0
- package/src/tasks.mjs +134 -0
- package/src/ui/commands.mjs +76 -0
- package/src/ui/events.mjs +45 -0
- package/src/ui/public/app.js +600 -0
- package/src/ui/public/index.html +88 -0
- package/src/ui/public/style.css +460 -0
- package/src/ui/server.mjs +112 -0
- package/src/ui/state.mjs +504 -0
- package/src/usage.mjs +178 -0
- package/src/workspace-diff.mjs +228 -0
package/src/schema.mjs
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
export const SCHEMA_VERSION = 1;
|
|
2
|
+
|
|
3
|
+
export function stampSchemaVersion(obj) {
|
|
4
|
+
return { ...obj, schemaVersion: SCHEMA_VERSION };
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const TASK_STATUSES = new Set(['pending', 'in_progress', 'completed', 'completed_with_warnings', 'failed', 'blocked', 'needs_human', 'archived']);
|
|
8
|
+
|
|
9
|
+
export function validateTask(task) {
|
|
10
|
+
const errors = [];
|
|
11
|
+
if (!task || typeof task !== 'object') {
|
|
12
|
+
return { ok: false, errors: ['task is not an object'] };
|
|
13
|
+
}
|
|
14
|
+
if (task.id === undefined || task.id === null) {
|
|
15
|
+
errors.push('missing id');
|
|
16
|
+
}
|
|
17
|
+
if (typeof task.description !== 'string' || !task.description) {
|
|
18
|
+
errors.push('missing description');
|
|
19
|
+
}
|
|
20
|
+
if (typeof task.status !== 'string' || !TASK_STATUSES.has(task.status)) {
|
|
21
|
+
errors.push('invalid status: ' + task.status);
|
|
22
|
+
}
|
|
23
|
+
if (task.createdAt !== undefined && typeof task.createdAt !== 'string') {
|
|
24
|
+
errors.push('createdAt must be a string');
|
|
25
|
+
}
|
|
26
|
+
return { ok: errors.length === 0, errors };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const RUN_STATUSES = new Set(['completed', 'completed_with_warnings', 'failed', 'blocked', 'needs_human']);
|
|
30
|
+
|
|
31
|
+
export function validateRunEntry(entry) {
|
|
32
|
+
const errors = [];
|
|
33
|
+
if (!entry || typeof entry !== 'object') {
|
|
34
|
+
return { ok: false, errors: ['run entry is not an object'] };
|
|
35
|
+
}
|
|
36
|
+
if (entry.taskId === undefined || entry.taskId === null) {
|
|
37
|
+
errors.push('missing taskId');
|
|
38
|
+
}
|
|
39
|
+
if (typeof entry.status !== 'string' || !RUN_STATUSES.has(entry.status)) {
|
|
40
|
+
errors.push('invalid status: ' + entry.status);
|
|
41
|
+
}
|
|
42
|
+
if (typeof entry.startTime !== 'string') {
|
|
43
|
+
errors.push('missing startTime');
|
|
44
|
+
}
|
|
45
|
+
return { ok: errors.length === 0, errors };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const ORCHESTRATION_EVENT_TYPES = new Set(['orchestration_started', 'orchestration_blocked', 'orchestration_finished']);
|
|
49
|
+
|
|
50
|
+
export function validateOrchestrationEvent(event) {
|
|
51
|
+
const errors = [];
|
|
52
|
+
if (!event || typeof event !== 'object' || Array.isArray(event)) {
|
|
53
|
+
return { ok: false, errors: ['orchestration event is not an object'] };
|
|
54
|
+
}
|
|
55
|
+
if (event.schemaVersion !== SCHEMA_VERSION) {
|
|
56
|
+
errors.push('invalid schemaVersion: ' + event.schemaVersion);
|
|
57
|
+
}
|
|
58
|
+
if (typeof event.orchestrationId !== 'string' || event.orchestrationId.trim().length === 0) {
|
|
59
|
+
errors.push('missing orchestrationId');
|
|
60
|
+
}
|
|
61
|
+
if (event.parentTaskId === undefined || event.parentTaskId === null || String(event.parentTaskId).trim().length === 0) {
|
|
62
|
+
errors.push('missing parentTaskId');
|
|
63
|
+
}
|
|
64
|
+
if (typeof event.attempt !== 'number' || !Number.isInteger(event.attempt) || event.attempt < 1) {
|
|
65
|
+
errors.push('invalid attempt: ' + event.attempt);
|
|
66
|
+
}
|
|
67
|
+
if (event.mode !== 'real') {
|
|
68
|
+
errors.push('invalid mode: ' + event.mode);
|
|
69
|
+
}
|
|
70
|
+
if (typeof event.eventType !== 'string' || !ORCHESTRATION_EVENT_TYPES.has(event.eventType)) {
|
|
71
|
+
errors.push('invalid eventType: ' + event.eventType);
|
|
72
|
+
}
|
|
73
|
+
if (typeof event.startTime !== 'string') {
|
|
74
|
+
errors.push('missing startTime');
|
|
75
|
+
}
|
|
76
|
+
if (typeof event.timestamp !== 'string') {
|
|
77
|
+
errors.push('missing timestamp');
|
|
78
|
+
}
|
|
79
|
+
if (event.eventType === 'orchestration_blocked') {
|
|
80
|
+
if (!['blocked', 'needs_human'].includes(event.status)) {
|
|
81
|
+
errors.push('invalid blocked status: ' + event.status);
|
|
82
|
+
}
|
|
83
|
+
if (typeof event.reason !== 'string') {
|
|
84
|
+
errors.push('missing blocked reason');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (event.eventType === 'orchestration_finished') {
|
|
88
|
+
if (typeof event.endTime !== 'string') {
|
|
89
|
+
errors.push('missing endTime');
|
|
90
|
+
}
|
|
91
|
+
if (typeof event.status !== 'string' || !TASK_STATUSES.has(event.status)) {
|
|
92
|
+
errors.push('invalid status: ' + event.status);
|
|
93
|
+
}
|
|
94
|
+
if (!Array.isArray(event.children)) {
|
|
95
|
+
errors.push('children must be an array');
|
|
96
|
+
}
|
|
97
|
+
if (event.consolidation !== null && event.consolidation !== undefined && typeof event.consolidation !== 'object') {
|
|
98
|
+
errors.push('consolidation must be an object or null');
|
|
99
|
+
}
|
|
100
|
+
if (event.verification !== null && event.verification !== undefined && typeof event.verification !== 'object') {
|
|
101
|
+
errors.push('verification must be an object or null');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return { ok: errors.length === 0, errors };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function validateUsageSummary(summary) {
|
|
108
|
+
const errors = [];
|
|
109
|
+
if (!summary || typeof summary !== 'object') {
|
|
110
|
+
return { ok: false, errors: ['usage summary is not an object'] };
|
|
111
|
+
}
|
|
112
|
+
for (const field of ['totalRuns', 'completed', 'failed', 'blocked']) {
|
|
113
|
+
if (typeof summary[field] !== 'number') {
|
|
114
|
+
errors.push('missing numeric field: ' + field);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
for (const field of ['preferFree', 'allowPaid', 'allowClaudeReview', 'allowDirectOpenAI']) {
|
|
118
|
+
if (typeof summary[field] !== 'boolean') {
|
|
119
|
+
errors.push('missing boolean field: ' + field);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return { ok: errors.length === 0, errors };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const COST_CLASSES = new Set(['free', 'free-tier', 'paid', 'local', 'unknown']);
|
|
126
|
+
const CONFIDENCE_LEVELS = new Set(['confirmed', 'probable', 'unknown']);
|
|
127
|
+
|
|
128
|
+
// Accepts a number in [0,5], the literal string 'unknown', or null/undefined
|
|
129
|
+
// (all three mean "not scored"). Rejects fabricated out-of-range numbers,
|
|
130
|
+
// but never requires a number to be present.
|
|
131
|
+
function isScoreOrUnknown(value) {
|
|
132
|
+
if (value === null || value === undefined || value === 'unknown') return true;
|
|
133
|
+
return typeof value === 'number' && value >= 0 && value <= 5;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function validateEngineFiche(engine) {
|
|
137
|
+
const errors = [];
|
|
138
|
+
if (!engine || typeof engine !== 'object') {
|
|
139
|
+
return { ok: false, errors: ['engine fiche is not an object'] };
|
|
140
|
+
}
|
|
141
|
+
if (typeof engine.id !== 'string' || !engine.id) {
|
|
142
|
+
errors.push('missing id');
|
|
143
|
+
}
|
|
144
|
+
if (typeof engine.provider !== 'string' || !engine.provider) {
|
|
145
|
+
errors.push('missing provider');
|
|
146
|
+
}
|
|
147
|
+
if (typeof engine.enabled !== 'boolean') {
|
|
148
|
+
errors.push('enabled must be boolean');
|
|
149
|
+
}
|
|
150
|
+
if (typeof engine.validated !== 'boolean') {
|
|
151
|
+
errors.push('validated must be boolean');
|
|
152
|
+
}
|
|
153
|
+
const cost = engine.cost || {};
|
|
154
|
+
if (!COST_CLASSES.has(cost.class)) {
|
|
155
|
+
errors.push('cost.class must be one of ' + [...COST_CLASSES].join('|'));
|
|
156
|
+
}
|
|
157
|
+
const caps = engine.capabilities || {};
|
|
158
|
+
for (const field of ['reasoning', 'planning', 'coding', 'debugging', 'review', 'writing', 'documentation', 'longContext']) {
|
|
159
|
+
if (!isScoreOrUnknown(caps[field])) {
|
|
160
|
+
errors.push('capabilities.' + field + ' must be a number 0-5 or null');
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const confidence = engine.confidence || {};
|
|
164
|
+
for (const field of ['capabilities', 'cost', 'tools']) {
|
|
165
|
+
if (confidence[field] !== undefined && !CONFIDENCE_LEVELS.has(confidence[field])) {
|
|
166
|
+
errors.push('confidence.' + field + ' must be one of ' + [...CONFIDENCE_LEVELS].join('|'));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return { ok: errors.length === 0, errors };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function validateEnginesFile(value) {
|
|
173
|
+
const engines = Array.isArray(value) ? value : (value && Array.isArray(value.engines) ? value.engines : null);
|
|
174
|
+
if (!engines) {
|
|
175
|
+
return { ok: false, errors: ['engines.json must be an array of engine fiches, or an object with an "engines" array'] };
|
|
176
|
+
}
|
|
177
|
+
const errors = [];
|
|
178
|
+
const seenIds = new Set();
|
|
179
|
+
for (const engine of engines) {
|
|
180
|
+
const result = validateEngineFiche(engine);
|
|
181
|
+
if (!result.ok) {
|
|
182
|
+
errors.push('engine "' + (engine && engine.id) + '": ' + result.errors.join(', '));
|
|
183
|
+
}
|
|
184
|
+
if (engine && engine.id) {
|
|
185
|
+
if (seenIds.has(engine.id)) {
|
|
186
|
+
errors.push('duplicate engine id: ' + engine.id);
|
|
187
|
+
}
|
|
188
|
+
seenIds.add(engine.id);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return { ok: errors.length === 0, errors };
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export function validateBudget(budget) {
|
|
195
|
+
const errors = [];
|
|
196
|
+
if (!budget || typeof budget !== 'object') {
|
|
197
|
+
return { ok: false, errors: ['budget is not an object'] };
|
|
198
|
+
}
|
|
199
|
+
for (const field of ['currencyBudget', 'estimatedTokenBudget', 'maxRunsPerTask', 'maxSubagentsPerTask', 'maxDepth']) {
|
|
200
|
+
if (typeof budget[field] !== 'number') {
|
|
201
|
+
errors.push('missing numeric field: ' + field);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
for (const field of ['preferFree', 'allowPaid', 'allowClaudeReview', 'allowDirectOpenAI']) {
|
|
205
|
+
if (typeof budget[field] !== 'boolean') {
|
|
206
|
+
errors.push('missing boolean field: ' + field);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (budget.allowHostValidationFallback !== undefined && typeof budget.allowHostValidationFallback !== 'boolean') {
|
|
210
|
+
errors.push('allowHostValidationFallback must be boolean');
|
|
211
|
+
}
|
|
212
|
+
if (budget.hostValidationCommands !== undefined) {
|
|
213
|
+
if (!Array.isArray(budget.hostValidationCommands)) {
|
|
214
|
+
errors.push('hostValidationCommands must be an array');
|
|
215
|
+
} else {
|
|
216
|
+
const allowed = new Set(['npm-test', 'npm-run-check', 'node-check']);
|
|
217
|
+
for (const commandId of budget.hostValidationCommands) {
|
|
218
|
+
if (!allowed.has(commandId)) errors.push('unknown hostValidationCommand: ' + commandId);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return { ok: errors.length === 0, errors };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const FAILURE_CATEGORIES = new Set([
|
|
226
|
+
'quota_exceeded', 'rate_limit', 'provider_unavailable', 'network_error',
|
|
227
|
+
'authentication_error', 'missing_tool', 'insufficient_capability',
|
|
228
|
+
'context_too_small', 'invalid_output', 'syntax_failure', 'test_failure',
|
|
229
|
+
'policy_violation', 'budget_exceeded', 'safety_blocked', 'needs_human',
|
|
230
|
+
'windows_shell_mismatch', 'unsupported_tool_call', 'suspected_false_positive',
|
|
231
|
+
'windows_sandbox_acl_failure',
|
|
232
|
+
'nested_sandbox_process_failure',
|
|
233
|
+
'engine_resolution_cmd_only',
|
|
234
|
+
'process_terminated_unexpectedly',
|
|
235
|
+
'unknown_failure'
|
|
236
|
+
]);
|
|
237
|
+
|
|
238
|
+
const FALLBACK_ACTION_TYPES = new Set(['retry', 'switch_engine', 'ask_human', 'block', 'verify', 'fix', 'none']);
|
|
239
|
+
|
|
240
|
+
export function validateFailureClassification(classification) {
|
|
241
|
+
const errors = [];
|
|
242
|
+
if (!classification || typeof classification !== 'object') {
|
|
243
|
+
return { ok: false, errors: ['failure classification is not an object'] };
|
|
244
|
+
}
|
|
245
|
+
if (!FAILURE_CATEGORIES.has(classification.category)) {
|
|
246
|
+
errors.push('unknown failure category: ' + classification.category);
|
|
247
|
+
}
|
|
248
|
+
if (!['low', 'medium', 'high', 'critical'].includes(classification.severity)) {
|
|
249
|
+
errors.push('invalid severity: ' + classification.severity);
|
|
250
|
+
}
|
|
251
|
+
if (typeof classification.retryable !== 'boolean') {
|
|
252
|
+
errors.push('retryable must be a boolean');
|
|
253
|
+
}
|
|
254
|
+
if (typeof classification.shouldFallback !== 'boolean') {
|
|
255
|
+
errors.push('shouldFallback must be a boolean');
|
|
256
|
+
}
|
|
257
|
+
if (typeof classification.shouldAskHuman !== 'boolean') {
|
|
258
|
+
errors.push('shouldAskHuman must be a boolean');
|
|
259
|
+
}
|
|
260
|
+
if (!Array.isArray(classification.reason)) {
|
|
261
|
+
errors.push('reason must be an array');
|
|
262
|
+
}
|
|
263
|
+
if (!Array.isArray(classification.evidence)) {
|
|
264
|
+
errors.push('evidence must be an array');
|
|
265
|
+
}
|
|
266
|
+
return { ok: errors.length === 0, errors };
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export function validateFallbackPlan(plan) {
|
|
270
|
+
const errors = [];
|
|
271
|
+
if (!plan || typeof plan !== 'object') {
|
|
272
|
+
return { ok: false, errors: ['fallback plan is not an object'] };
|
|
273
|
+
}
|
|
274
|
+
if (!FALLBACK_ACTION_TYPES.has(plan.action)) {
|
|
275
|
+
errors.push('unknown fallback action: ' + plan.action);
|
|
276
|
+
}
|
|
277
|
+
if (plan.successorEngine !== null && typeof plan.successorEngine !== 'string') {
|
|
278
|
+
errors.push('successorEngine must be a string or null');
|
|
279
|
+
}
|
|
280
|
+
if (plan.successorRole !== null && typeof plan.successorRole !== 'string') {
|
|
281
|
+
errors.push('successorRole must be a string or null');
|
|
282
|
+
}
|
|
283
|
+
if (!Array.isArray(plan.reason)) {
|
|
284
|
+
errors.push('reason must be an array');
|
|
285
|
+
}
|
|
286
|
+
if (typeof plan.allowed !== 'boolean') {
|
|
287
|
+
errors.push('allowed must be a boolean');
|
|
288
|
+
}
|
|
289
|
+
if (typeof plan.requiresHuman !== 'boolean') {
|
|
290
|
+
errors.push('requiresHuman must be a boolean');
|
|
291
|
+
}
|
|
292
|
+
return { ok: errors.length === 0, errors };
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export function validateExecutionContextSummary(summary) {
|
|
296
|
+
const errors = [];
|
|
297
|
+
if (!summary || typeof summary !== 'object') {
|
|
298
|
+
return { ok: false, errors: ['execution context summary is not an object'] };
|
|
299
|
+
}
|
|
300
|
+
if (typeof summary.projectRoot !== 'string') {
|
|
301
|
+
errors.push('missing projectRoot');
|
|
302
|
+
}
|
|
303
|
+
if (typeof summary.taskId !== 'string') {
|
|
304
|
+
errors.push('missing taskId');
|
|
305
|
+
}
|
|
306
|
+
if (typeof summary.runKind !== 'string') {
|
|
307
|
+
errors.push('missing runKind');
|
|
308
|
+
}
|
|
309
|
+
if (typeof summary.attemptNumber !== 'number') {
|
|
310
|
+
errors.push('missing attemptNumber');
|
|
311
|
+
}
|
|
312
|
+
if (typeof summary.orchestrationDepth !== 'number') {
|
|
313
|
+
errors.push('missing orchestrationDepth');
|
|
314
|
+
}
|
|
315
|
+
return { ok: errors.length === 0, errors };
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
export function validateFallbackGraph(graph) {
|
|
320
|
+
const errors = [];
|
|
321
|
+
if (!graph || typeof graph !== 'object') {
|
|
322
|
+
return { ok: false, errors: ['fallback graph is not an object'] };
|
|
323
|
+
}
|
|
324
|
+
const rules = graph.rules || {};
|
|
325
|
+
for (const category of Object.keys(rules)) {
|
|
326
|
+
if (!FAILURE_CATEGORIES.has(category)) {
|
|
327
|
+
errors.push('unknown failure category: ' + category);
|
|
328
|
+
}
|
|
329
|
+
if (typeof rules[category].action !== 'string' || !FALLBACK_ACTION_TYPES.has(rules[category].action)) {
|
|
330
|
+
errors.push('rule for ' + category + ' is missing a valid action or has an unknown action');
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return { ok: errors.length === 0, errors };
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Phase 14: what KIND of run produced a usage/RUNS.jsonl row. Older rows
|
|
337
|
+
// predate this field entirely and must be treated as 'unknown', never
|
|
338
|
+
// silently assumed to be 'task' — see .maestro/V0_5_CURRENT_ARCHITECTURE_AUDIT.md
|
|
339
|
+
// section 8 for why retrofitting old rows is explicitly out of scope.
|
|
340
|
+
const RUN_KINDS = new Set([
|
|
341
|
+
'task', 'diagnostic', 'doctor', 'codex-test', 'ui-command',
|
|
342
|
+
'release-check', 'preflight', 'verification', 'subagent'
|
|
343
|
+
]);
|
|
344
|
+
|
|
345
|
+
export function inferRunKind(command) {
|
|
346
|
+
switch (command) {
|
|
347
|
+
case 'run-task':
|
|
348
|
+
case 'run-all':
|
|
349
|
+
case 'run-one':
|
|
350
|
+
case 'retry':
|
|
351
|
+
return 'task';
|
|
352
|
+
case 'codex-test':
|
|
353
|
+
return 'codex-test';
|
|
354
|
+
case 'codex-compare':
|
|
355
|
+
case 'codex-home':
|
|
356
|
+
case 'codex-home-diff':
|
|
357
|
+
case 'codex-home-inventory':
|
|
358
|
+
case 'codex-home-probe':
|
|
359
|
+
case 'codex-home-repair':
|
|
360
|
+
case 'codex-debug':
|
|
361
|
+
return 'diagnostic';
|
|
362
|
+
case 'doctor':
|
|
363
|
+
return 'doctor';
|
|
364
|
+
case 'release-check':
|
|
365
|
+
return 'release-check';
|
|
366
|
+
default:
|
|
367
|
+
return 'unknown';
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export { FAILURE_CATEGORIES, COST_CLASSES, CONFIDENCE_LEVELS, RUN_KINDS, FALLBACK_ACTION_TYPES, ORCHESTRATION_EVENT_TYPES };
|