oxe-cc 1.5.1 → 1.7.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/AGENTS.md +1 -1
- package/CHANGELOG.md +45 -0
- package/README.md +19 -15
- package/bin/lib/oxe-agent-install.cjs +125 -24
- package/bin/lib/oxe-dashboard.cjs +21 -5
- package/bin/lib/oxe-project-health.cjs +120 -42
- package/bin/lib/oxe-release.cjs +77 -4
- package/bin/oxe-cc.js +155 -78
- package/commands/oxe/debug.md +6 -1
- package/commands/oxe/discuss.md +7 -2
- package/commands/oxe/execute.md +7 -2
- package/commands/oxe/plan-agent.md +7 -2
- package/commands/oxe/plan.md +7 -2
- package/commands/oxe/scan.md +6 -1
- package/commands/oxe/spec.md +6 -1
- package/commands/oxe/verify.md +6 -1
- package/docs/CONTENT-MIGRATION-AUDIT.md +49 -0
- package/docs/RELEASE-READINESS.md +8 -0
- package/docs/RUNTIME-SMOKE-MATRIX.md +9 -2
- package/lib/runtime/compiler/graph-compiler.js +32 -0
- package/lib/runtime/context/context-pack-builder.d.ts +15 -0
- package/lib/runtime/context/context-pack-builder.js +78 -0
- package/lib/runtime/events/catalog.d.ts +1 -1
- package/lib/runtime/events/catalog.js +5 -0
- package/lib/runtime/executor/action-tool-map.d.ts +3 -0
- package/lib/runtime/executor/action-tool-map.js +41 -0
- package/lib/runtime/executor/built-in-tools.d.ts +8 -0
- package/lib/runtime/executor/built-in-tools.js +267 -0
- package/lib/runtime/executor/index.d.ts +6 -0
- package/lib/runtime/executor/index.js +12 -0
- package/lib/runtime/executor/llm-task-executor.d.ts +29 -0
- package/lib/runtime/executor/llm-task-executor.js +138 -0
- package/lib/runtime/executor/node-prompt-builder.d.ts +3 -0
- package/lib/runtime/executor/node-prompt-builder.js +36 -0
- package/lib/runtime/executor/stream-completion.d.ts +38 -0
- package/lib/runtime/executor/stream-completion.js +105 -0
- package/lib/runtime/index.d.ts +1 -0
- package/lib/runtime/index.js +2 -0
- package/lib/runtime/models/failure.d.ts +5 -0
- package/lib/runtime/models/failure.js +2 -0
- package/lib/runtime/plugins/capability-adapter.d.ts +9 -0
- package/lib/runtime/plugins/capability-adapter.js +111 -8
- package/lib/runtime/plugins/plugin-abi.d.ts +8 -0
- package/lib/runtime/plugins/plugin-registry.d.ts +2 -1
- package/lib/runtime/plugins/plugin-registry.js +6 -1
- package/lib/runtime/reducers/run-state-reducer.js +39 -2
- package/lib/runtime/scheduler/scheduler.d.ts +14 -2
- package/lib/runtime/scheduler/scheduler.js +131 -11
- package/lib/runtime/verification/verification-manifest.d.ts +5 -2
- package/lib/sdk/index.cjs +10 -5
- package/lib/sdk/index.d.ts +21 -10
- package/oxe/agents/oxe-assumptions-analyzer.md +136 -0
- package/oxe/agents/oxe-codebase-mapper.md +142 -0
- package/oxe/agents/oxe-debugger.md +145 -0
- package/oxe/agents/oxe-executor.md +139 -0
- package/oxe/agents/oxe-integration-checker.md +142 -0
- package/oxe/agents/oxe-plan-checker.md +143 -0
- package/oxe/agents/oxe-planner.md +151 -0
- package/oxe/agents/oxe-research-synthesizer.md +146 -0
- package/oxe/agents/oxe-researcher.md +163 -0
- package/oxe/agents/oxe-ui-auditor.md +151 -0
- package/oxe/agents/oxe-ui-checker.md +157 -0
- package/oxe/agents/oxe-ui-researcher.md +179 -0
- package/oxe/agents/oxe-validation-auditor.md +154 -0
- package/oxe/agents/oxe-verifier.md +132 -0
- package/oxe/personas/README.md +91 -39
- package/oxe/personas/architect.md +149 -37
- package/oxe/personas/db-specialist.md +149 -36
- package/oxe/personas/debugger.md +155 -38
- package/oxe/personas/executor.md +164 -38
- package/oxe/personas/planner.md +165 -36
- package/oxe/personas/researcher.md +148 -35
- package/oxe/personas/ui-specialist.md +164 -36
- package/oxe/personas/verifier.md +174 -39
- package/oxe/templates/CONFIG.md +3 -3
- package/oxe/templates/EXECUTION-RUNTIME.template.md +1 -1
- package/oxe/templates/FIXTURE-PACK.template.json +29 -22
- package/oxe/templates/FIXTURE-PACK.template.md +20 -11
- package/oxe/templates/IMPLEMENTATION-PACK.template.json +55 -39
- package/oxe/templates/IMPLEMENTATION-PACK.template.md +28 -16
- package/oxe/templates/INVESTIGATION.template.md +38 -38
- package/oxe/templates/PLAN.template.md +63 -32
- package/oxe/templates/REFERENCE-ANCHORS.template.md +18 -14
- package/oxe/templates/RESEARCH.template.md +11 -11
- package/oxe/templates/SPEC.template.md +6 -6
- package/oxe/templates/SUMMARY.template.md +33 -3
- package/oxe/templates/config.template.json +1 -1
- package/oxe/workflows/debug.md +9 -7
- package/oxe/workflows/execute.md +31 -28
- package/oxe/workflows/forensics.md +5 -3
- package/oxe/workflows/milestone.md +12 -12
- package/oxe/workflows/next.md +1 -1
- package/oxe/workflows/plan.md +409 -132
- package/oxe/workflows/references/adaptive-discovery.md +27 -27
- package/oxe/workflows/references/flow-robustness-contract.md +80 -80
- package/oxe/workflows/references/session-path-resolution.md +71 -71
- package/oxe/workflows/references/workflow-runtime-contracts.json +127 -127
- package/oxe/workflows/scan.md +355 -69
- package/oxe/workflows/spec.md +302 -9
- package/oxe/workflows/ui-review.md +5 -4
- package/oxe/workflows/ui-spec.md +4 -3
- package/oxe/workflows/verify.md +12 -9
- package/oxe/workflows/workstream.md +16 -16
- package/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/runtime/src/compiler/graph-compiler.ts +40 -0
- package/packages/runtime/src/context/context-pack-builder.ts +80 -0
- package/packages/runtime/src/events/catalog.ts +5 -0
- package/packages/runtime/src/executor/action-tool-map.ts +46 -0
- package/packages/runtime/src/executor/built-in-tools.ts +276 -0
- package/packages/runtime/src/executor/index.ts +6 -0
- package/packages/runtime/src/executor/llm-task-executor.ts +194 -0
- package/packages/runtime/src/executor/node-prompt-builder.ts +45 -0
- package/packages/runtime/src/executor/stream-completion.ts +145 -0
- package/packages/runtime/src/index.ts +3 -0
- package/packages/runtime/src/models/failure.ts +11 -0
- package/packages/runtime/src/plugins/capability-adapter.ts +117 -10
- package/packages/runtime/src/plugins/plugin-abi.ts +9 -0
- package/packages/runtime/src/plugins/plugin-registry.ts +10 -1
- package/packages/runtime/src/reducers/run-state-reducer.ts +59 -2
- package/packages/runtime/src/scheduler/scheduler.ts +152 -14
- package/packages/runtime/src/verification/verification-manifest.ts +12 -8
- package/vscode-extension/oxe-agents-1.6.0.vsix +0 -0
- package/vscode-extension/oxe-agents-1.7.0.vsix +0 -0
- package/vscode-extension/package.json +1 -1
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
1
3
|
import { appendEvent } from '../events/bus';
|
|
2
4
|
import type { OxeEvent } from '../events/envelope';
|
|
3
5
|
import type { EventInput } from '../events/bus';
|
|
@@ -18,10 +20,14 @@ import {
|
|
|
18
20
|
createJournal,
|
|
19
21
|
} from './run-journal';
|
|
20
22
|
import type { RunJournal } from './run-journal';
|
|
23
|
+
import type { FailureClass } from '../models/failure';
|
|
24
|
+
import { listMemos } from '../decision/decision-memo';
|
|
25
|
+
import type { RollbackPlan } from '../decision/decision-memo';
|
|
26
|
+
import { runCapabilityAsync } from '../plugins/capability-adapter';
|
|
21
27
|
|
|
22
28
|
export interface TaskResult {
|
|
23
29
|
success: boolean;
|
|
24
|
-
failure_class:
|
|
30
|
+
failure_class: FailureClass;
|
|
25
31
|
evidence: string[];
|
|
26
32
|
output: string;
|
|
27
33
|
}
|
|
@@ -35,6 +41,11 @@ export interface TaskExecutor {
|
|
|
35
41
|
): Promise<TaskResult>;
|
|
36
42
|
}
|
|
37
43
|
|
|
44
|
+
export interface SchedulerOptions {
|
|
45
|
+
maxRunDurationMs?: number; // default: 30 min
|
|
46
|
+
staleProgressMs?: number; // default: 5 min without any task completing
|
|
47
|
+
}
|
|
48
|
+
|
|
38
49
|
export interface SchedulerContext {
|
|
39
50
|
projectRoot: string;
|
|
40
51
|
sessionId: string | null;
|
|
@@ -48,15 +59,17 @@ export interface SchedulerContext {
|
|
|
48
59
|
quota?: RunQuota;
|
|
49
60
|
policyActor?: string;
|
|
50
61
|
onEvent?: (event: OxeEvent) => void;
|
|
62
|
+
options?: SchedulerOptions;
|
|
51
63
|
}
|
|
52
64
|
|
|
53
65
|
export interface RunResult {
|
|
54
66
|
run_id: string;
|
|
55
|
-
status: 'completed' | 'failed' | 'blocked' | 'cancelled' | 'paused';
|
|
67
|
+
status: 'completed' | 'failed' | 'blocked' | 'cancelled' | 'paused' | 'aborted';
|
|
56
68
|
completed: string[];
|
|
57
69
|
failed: string[];
|
|
58
70
|
blocked: string[];
|
|
59
71
|
pending_gates?: string[];
|
|
72
|
+
reason?: string;
|
|
60
73
|
}
|
|
61
74
|
|
|
62
75
|
type NodeStatus = 'pending' | 'ready' | 'running' | 'completed' | 'failed' | 'blocked';
|
|
@@ -66,11 +79,43 @@ export class Scheduler {
|
|
|
66
79
|
private paused = false;
|
|
67
80
|
private journal: RunJournal | null = null;
|
|
68
81
|
private ctx: SchedulerContext | null = null;
|
|
82
|
+
private runStartMs = 0;
|
|
83
|
+
private lastProgressMs = 0;
|
|
84
|
+
|
|
85
|
+
private recordProgress(): void {
|
|
86
|
+
this.lastProgressMs = Date.now();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private async executeRollback(plan: RollbackPlan, ctx: SchedulerContext): Promise<void> {
|
|
90
|
+
try {
|
|
91
|
+
switch (plan.strategy) {
|
|
92
|
+
case 'revert_commit':
|
|
93
|
+
await runCapabilityAsync('git', ['revert', 'HEAD', '--no-edit'], {}, ctx.projectRoot, 30_000);
|
|
94
|
+
break;
|
|
95
|
+
case 'restore_workspace':
|
|
96
|
+
await runCapabilityAsync('git', ['checkout', '.'], {}, ctx.projectRoot, 30_000);
|
|
97
|
+
break;
|
|
98
|
+
case 'undo_patch':
|
|
99
|
+
for (const p of plan.steps) {
|
|
100
|
+
await runCapabilityAsync('git', ['checkout', 'HEAD', '--', p], {}, ctx.projectRoot, 10_000);
|
|
101
|
+
}
|
|
102
|
+
break;
|
|
103
|
+
case 'no_rollback':
|
|
104
|
+
default:
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
this.emit(ctx, { type: 'RollbackExecuted', payload: { strategy: plan.strategy } });
|
|
108
|
+
} catch (err) {
|
|
109
|
+
this.emit(ctx, { type: 'RollbackFailed', payload: { strategy: plan.strategy, error: String(err) } });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
69
112
|
|
|
70
113
|
async run(graph: ExecutionGraph, ctx: SchedulerContext): Promise<RunResult> {
|
|
71
114
|
this.cancelled = false;
|
|
72
115
|
this.paused = false;
|
|
73
116
|
this.ctx = ctx;
|
|
117
|
+
this.runStartMs = Date.now();
|
|
118
|
+
this.lastProgressMs = Date.now();
|
|
74
119
|
|
|
75
120
|
const status = new Map<string, NodeStatus>();
|
|
76
121
|
for (const id of graph.nodes.keys()) status.set(id, 'pending');
|
|
@@ -79,6 +124,30 @@ export class Scheduler {
|
|
|
79
124
|
const failed: string[] = [];
|
|
80
125
|
const blocked: string[] = [];
|
|
81
126
|
|
|
127
|
+
// Plan hash drift detection: abort if the graph was recompiled since ACTIVE-RUN was saved
|
|
128
|
+
const activeRunPath = ctx.sessionId
|
|
129
|
+
? path.join(ctx.projectRoot, '.oxe', ctx.sessionId, 'execution', 'ACTIVE-RUN.json')
|
|
130
|
+
: path.join(ctx.projectRoot, '.oxe', 'ACTIVE-RUN.json');
|
|
131
|
+
if (fs.existsSync(activeRunPath)) {
|
|
132
|
+
try {
|
|
133
|
+
const activeRun = JSON.parse(fs.readFileSync(activeRunPath, 'utf8')) as Record<string, unknown>;
|
|
134
|
+
const savedHash = activeRun.plan_hash as string | undefined;
|
|
135
|
+
const currentHash = graph.metadata.plan_hash;
|
|
136
|
+
if (savedHash && savedHash !== currentHash) {
|
|
137
|
+
return {
|
|
138
|
+
run_id: ctx.runId,
|
|
139
|
+
status: 'aborted',
|
|
140
|
+
completed: [],
|
|
141
|
+
failed: [],
|
|
142
|
+
blocked: [],
|
|
143
|
+
reason: `plan_drift: graph recompiled (${savedHash} → ${currentHash}). Run /oxe-plan --replan to realign.`,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
} catch {
|
|
147
|
+
// ACTIVE-RUN not parseable — continue without drift check
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
82
151
|
this.journal = createJournal(ctx.runId);
|
|
83
152
|
saveJournal(ctx.projectRoot, ctx.runId, this.journal);
|
|
84
153
|
|
|
@@ -88,9 +157,24 @@ export class Scheduler {
|
|
|
88
157
|
detail: { session_id: ctx.sessionId ?? null },
|
|
89
158
|
});
|
|
90
159
|
|
|
160
|
+
const maxRunMs = ctx.options?.maxRunDurationMs ?? 30 * 60_000;
|
|
161
|
+
const staleMs = ctx.options?.staleProgressMs ?? 5 * 60_000;
|
|
162
|
+
|
|
91
163
|
for (const wave of graph.waves) {
|
|
92
164
|
if (this.cancelled) break;
|
|
93
165
|
|
|
166
|
+
// Global run timeout
|
|
167
|
+
if (Date.now() - this.runStartMs > maxRunMs) {
|
|
168
|
+
this.emit(ctx, { type: 'RunAborted', payload: { reason: 'global_timeout' } });
|
|
169
|
+
return { run_id: ctx.runId, status: 'aborted', completed: [], failed: [], blocked: [], reason: 'global_timeout' };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Stale progress timeout (no task completed in staleMs)
|
|
173
|
+
if (Date.now() - this.lastProgressMs > staleMs) {
|
|
174
|
+
this.emit(ctx, { type: 'RunAborted', payload: { reason: 'no_progress_timeout' } });
|
|
175
|
+
return { run_id: ctx.runId, status: 'aborted', completed: [], failed: [], blocked: [], reason: 'no_progress_timeout' };
|
|
176
|
+
}
|
|
177
|
+
|
|
94
178
|
// Respect pause: persist journal and return paused result
|
|
95
179
|
if (this.paused) {
|
|
96
180
|
this.journal.scheduler_state = 'paused';
|
|
@@ -123,7 +207,17 @@ export class Scheduler {
|
|
|
123
207
|
this.journal.blocked_work_items = blocked.slice();
|
|
124
208
|
saveJournal(ctx.projectRoot, ctx.runId, this.journal);
|
|
125
209
|
|
|
126
|
-
if (waveFailed)
|
|
210
|
+
if (waveFailed) {
|
|
211
|
+
// Execute rollback plan if one was created for this run
|
|
212
|
+
const memos = listMemos(ctx.projectRoot, ctx.runId);
|
|
213
|
+
for (const memo of memos) {
|
|
214
|
+
if (memo.rollback_plan.strategy !== 'no_rollback') {
|
|
215
|
+
await this.executeRollback(memo.rollback_plan, ctx);
|
|
216
|
+
break; // apply at most one rollback plan per wave failure
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
127
221
|
}
|
|
128
222
|
|
|
129
223
|
// Any remaining pending nodes become blocked
|
|
@@ -305,6 +399,15 @@ export class Scheduler {
|
|
|
305
399
|
};
|
|
306
400
|
}
|
|
307
401
|
|
|
402
|
+
private isConcurrentSafe(nodeId: string, graph: ExecutionGraph, ctx: SchedulerContext): boolean {
|
|
403
|
+
const node = graph.nodes.get(nodeId)!;
|
|
404
|
+
if (node.mutation_scope.length > 0) return false;
|
|
405
|
+
const primaryAction = pickPrimaryAction(node, ctx.pluginRegistry);
|
|
406
|
+
if (!primaryAction) return true;
|
|
407
|
+
const provider = ctx.pluginRegistry?.toolProviderFor(primaryAction.type);
|
|
408
|
+
return provider?.idempotent ?? true;
|
|
409
|
+
}
|
|
410
|
+
|
|
308
411
|
private async runWave(
|
|
309
412
|
nodeIds: string[],
|
|
310
413
|
graph: ExecutionGraph,
|
|
@@ -338,10 +441,7 @@ export class Scheduler {
|
|
|
338
441
|
});
|
|
339
442
|
}
|
|
340
443
|
|
|
341
|
-
const readOnly = eligible.filter((id) =>
|
|
342
|
-
const node = graph.nodes.get(id)!;
|
|
343
|
-
return node.mutation_scope.length === 0;
|
|
344
|
-
});
|
|
444
|
+
const readOnly = eligible.filter((id) => this.isConcurrentSafe(id, graph, ctx));
|
|
345
445
|
const mutations = eligible.filter((id) => !readOnly.includes(id));
|
|
346
446
|
|
|
347
447
|
if (readOnly.length > 0) {
|
|
@@ -453,6 +553,7 @@ export class Scheduler {
|
|
|
453
553
|
});
|
|
454
554
|
status.set(nodeId, 'completed');
|
|
455
555
|
completed.push(nodeId);
|
|
556
|
+
this.recordProgress();
|
|
456
557
|
return;
|
|
457
558
|
}
|
|
458
559
|
|
|
@@ -464,29 +565,47 @@ export class Scheduler {
|
|
|
464
565
|
this.blockNode(nodeId, ctx, status, blocked, 'quota_exceeded', retryBlocked);
|
|
465
566
|
return;
|
|
466
567
|
}
|
|
568
|
+
// Exponential backoff with jitter: 1s * 2^(attempt-1) + [0, 500ms], capped at 30s
|
|
569
|
+
const backoffMs = Math.min(
|
|
570
|
+
1_000 * Math.pow(2, attempt - 1) + Math.random() * 500,
|
|
571
|
+
30_000
|
|
572
|
+
);
|
|
573
|
+
await new Promise<void>(resolve => setTimeout(resolve, backoffMs));
|
|
467
574
|
this.emit(ctx, {
|
|
468
575
|
type: 'RetryScheduled',
|
|
469
576
|
work_item_id: nodeId,
|
|
470
|
-
payload: { next_attempt: attempt + 1, reason: lastResult.failure_class },
|
|
577
|
+
payload: { next_attempt: attempt + 1, reason: lastResult.failure_class, backoff_ms: backoffMs },
|
|
471
578
|
});
|
|
472
579
|
}
|
|
473
|
-
} catch (err) {
|
|
580
|
+
} catch (err: unknown) {
|
|
581
|
+
// Error boundary: isolate task failure, emit structured event, do not crash scheduler
|
|
582
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
583
|
+
const stack = err instanceof Error ? err.stack : undefined;
|
|
584
|
+
this.emit(ctx, {
|
|
585
|
+
type: 'TaskErrorBoundaryTripped',
|
|
586
|
+
work_item_id: nodeId,
|
|
587
|
+
payload: { message, stack, attempt },
|
|
588
|
+
});
|
|
474
589
|
lastResult = {
|
|
475
590
|
success: false,
|
|
476
591
|
failure_class: 'env',
|
|
477
592
|
evidence: [],
|
|
478
|
-
output:
|
|
593
|
+
output: `[error_boundary] ${message}`,
|
|
479
594
|
};
|
|
480
595
|
if (attempt < maxAttempts) {
|
|
596
|
+
const backoffMs = Math.min(1_000 * Math.pow(2, attempt - 1) + Math.random() * 500, 30_000);
|
|
597
|
+
await new Promise<void>(resolve => setTimeout(resolve, backoffMs));
|
|
481
598
|
this.emit(ctx, {
|
|
482
599
|
type: 'RetryScheduled',
|
|
483
600
|
work_item_id: nodeId,
|
|
484
|
-
payload: { next_attempt: attempt + 1, reason: 'env' },
|
|
601
|
+
payload: { next_attempt: attempt + 1, reason: 'env', backoff_ms: backoffMs },
|
|
485
602
|
});
|
|
486
603
|
}
|
|
487
604
|
} finally {
|
|
488
605
|
if (lease) {
|
|
489
|
-
await ctx.workspaceManager.dispose(lease.workspace_id).catch(() =>
|
|
606
|
+
await ctx.workspaceManager.dispose(lease.workspace_id).catch((e: unknown) =>
|
|
607
|
+
this.emit(ctx!, { type: 'WorkspaceDisposeFailed', payload: { workspace_id: lease?.workspace_id, error: String(e) } })
|
|
608
|
+
);
|
|
490
609
|
lease = null;
|
|
491
610
|
}
|
|
492
611
|
}
|
|
@@ -562,7 +681,7 @@ export class Scheduler {
|
|
|
562
681
|
payload: { provider: provider.name, action_type: primaryAction.type },
|
|
563
682
|
});
|
|
564
683
|
|
|
565
|
-
const
|
|
684
|
+
const invocationInput = {
|
|
566
685
|
action_type: primaryAction.type,
|
|
567
686
|
work_item_id: node.id,
|
|
568
687
|
run_id: ctx.runId,
|
|
@@ -572,7 +691,26 @@ export class Scheduler {
|
|
|
572
691
|
targets: primaryAction.targets ?? [],
|
|
573
692
|
},
|
|
574
693
|
workspace_root: lease.root_path,
|
|
575
|
-
}
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
if (provider.preInvoke) {
|
|
697
|
+
const preCheck = await provider.preInvoke(invocationInput);
|
|
698
|
+
if (!preCheck.allowed) {
|
|
699
|
+
this.emit(ctx, {
|
|
700
|
+
type: 'ToolFailed',
|
|
701
|
+
work_item_id: node.id,
|
|
702
|
+
attempt_id: attemptId,
|
|
703
|
+
payload: { provider: provider.name, action_type: primaryAction.type, error: preCheck.reason ?? 'pre_invoke blocked', evidence_paths: [], side_effects_applied: [] },
|
|
704
|
+
});
|
|
705
|
+
return { success: false, failure_class: 'policy', evidence: [], output: preCheck.reason ?? 'pre_invoke blocked' };
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
const result = await provider.invoke(invocationInput);
|
|
710
|
+
|
|
711
|
+
if (provider.postInvoke) {
|
|
712
|
+
await provider.postInvoke(invocationInput, result).catch(() => {});
|
|
713
|
+
}
|
|
576
714
|
|
|
577
715
|
this.emit(ctx, {
|
|
578
716
|
type: result.success ? 'ToolCompleted' : 'ToolFailed',
|
|
@@ -6,13 +6,17 @@ import type { CheckResult } from './verification-compiler';
|
|
|
6
6
|
|
|
7
7
|
export type VerificationProfile = 'quick' | 'standard' | 'critical';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
| '
|
|
12
|
-
| '
|
|
13
|
-
| '
|
|
14
|
-
| '
|
|
15
|
-
| '
|
|
9
|
+
/** Verification-specific failure classification (why a check failed, not why a task failed). */
|
|
10
|
+
export type VerificationFailureClass =
|
|
11
|
+
| 'deterministic' // check always fails regardless of retry
|
|
12
|
+
| 'flaky' // check outcome is non-deterministic
|
|
13
|
+
| 'timeout' // check exceeded time budget
|
|
14
|
+
| 'env_setup' // environment/infrastructure prevented check from running
|
|
15
|
+
| 'policy_failure' // policy blocked the check
|
|
16
|
+
| 'evidence_missing'; // required evidence was never collected
|
|
17
|
+
|
|
18
|
+
/** @deprecated Use VerificationFailureClass. Kept for backwards compat. */
|
|
19
|
+
export type FailureClass = VerificationFailureClass;
|
|
16
20
|
|
|
17
21
|
export type VerificationGranularity = 'work_item' | 'wave' | 'run';
|
|
18
22
|
|
|
@@ -20,7 +24,7 @@ export interface ManifestCheck {
|
|
|
20
24
|
check_id: string;
|
|
21
25
|
acceptance_ref: string | null;
|
|
22
26
|
status: VerificationStatus;
|
|
23
|
-
failure_class:
|
|
27
|
+
failure_class: VerificationFailureClass | null;
|
|
24
28
|
evidence_refs: string[];
|
|
25
29
|
duration_ms: number;
|
|
26
30
|
}
|
|
Binary file
|
|
Binary file
|