feat: add dry-run workflow execution boundary
This commit is contained in:
@@ -35,6 +35,56 @@ test('shadow observer skips without creating a remote client when mode does not
|
||||
observed: false,
|
||||
reason: 'mode_off',
|
||||
mode: 'off',
|
||||
executionPlan: null,
|
||||
});
|
||||
assert.equal(fetchCalls, 0);
|
||||
});
|
||||
|
||||
test('shadow boundary returns an auditable dry-run plan without calling LangGraph', async () => {
|
||||
let fetchCalls = 0;
|
||||
const observer = createWorkflowShadowObserver({
|
||||
configService: {
|
||||
async selectEngine() {
|
||||
return {
|
||||
engine: 'native',
|
||||
candidateEngine: 'langgraph',
|
||||
shadowEngine: null,
|
||||
fallbackEngine: 'native',
|
||||
reason: 'execution_gate_disabled',
|
||||
candidateReason: 'user_allowlist',
|
||||
mode: 'canary',
|
||||
configVersion: 8,
|
||||
bucket: 42,
|
||||
dryRun: true,
|
||||
};
|
||||
},
|
||||
async getRuntimeState() {
|
||||
throw new Error('must not load runtime config');
|
||||
},
|
||||
},
|
||||
fetchImpl: async () => {
|
||||
fetchCalls += 1;
|
||||
return jsonResponse({});
|
||||
},
|
||||
});
|
||||
|
||||
const result = await observer({
|
||||
runId: 'run-dry-1',
|
||||
requestId: 'request-dry-1',
|
||||
userId: 'user-1',
|
||||
});
|
||||
assert.equal(result.observed, false);
|
||||
assert.deepEqual(result.executionPlan, {
|
||||
version: 'workflow-execution-decision-v1',
|
||||
candidateEngine: 'langgraph',
|
||||
effectiveEngine: 'native',
|
||||
fallbackEngine: 'native',
|
||||
reason: 'execution_gate_disabled',
|
||||
candidateReason: 'user_allowlist',
|
||||
configVersion: 8,
|
||||
bucket: 42,
|
||||
dryRun: true,
|
||||
handoffAllowed: false,
|
||||
});
|
||||
assert.equal(fetchCalls, 0);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user