feat: add dry-run workflow execution boundary

This commit is contained in:
john
2026-07-24 22:30:41 +08:00
parent 646178944d
commit c9ad841543
12 changed files with 553 additions and 17 deletions
+57
View File
@@ -468,6 +468,63 @@ test('shadow observer failure cannot fail a Native run and chat runs are not obs
assert.equal(JSON.parse(failure.dataJson).code, 'SHADOW_UNAVAILABLE');
});
test('canary dry-run records the candidate decision without changing Native run state', async () => {
const pool = createFakePool();
const gateway = createAgentRunGateway({
pool,
userAuth: {},
tkmindProxy: {},
autoDispatch: false,
observeWorkflowRun: async () => ({
observed: false,
mode: 'canary',
executionPlan: {
version: 'workflow-execution-decision-v1',
candidateEngine: 'langgraph',
effectiveEngine: 'native',
fallbackEngine: 'native',
reason: 'execution_gate_disabled',
candidateReason: 'percentage',
configVersion: 9,
bucket: 3,
dryRun: true,
handoffAllowed: false,
},
}),
});
const run = await gateway.createRun('user-canary', {
requestId: 'req-canary-dry-run',
sessionId: 'session-canary',
userMessage: { role: 'user', content: 'refactor this module' },
toolMode: 'code',
taskType: 'repo_refactor',
});
await waitFor(() => pool.events.some(
(event) => event.eventType === 'workflow_execution_planned',
));
assert.equal(run.status, 'queued');
assert.equal(
pool.events.some((event) => event.eventType === 'workflow_shadow_completed'),
false,
);
const event = pool.events.find((item) => item.eventType === 'workflow_execution_planned');
assert.deepEqual(JSON.parse(event.dataJson), {
version: 'workflow-execution-decision-v1',
mode: 'canary',
candidateEngine: 'langgraph',
effectiveEngine: 'native',
fallbackEngine: 'native',
reason: 'execution_gate_disabled',
candidateReason: 'percentage',
configVersion: 9,
bucket: 3,
dryRun: true,
handoffAllowed: false,
});
});
test('agent run starts a session and marks submitted reply as succeeded', async () => {
const pool = createFakePool();
const submitted = [];