flow-execution-parity-integration.test.mjs
109 lines 3.6 KB
Raw
sha256:8915fe406161f95c1681f9469375e7bae5b28c884f00bedbdef65e4b0cd0738d docs(flow): commit FLOW-V0-SPEC.md hygiene for 7A-INT merge Human 22 hours ago
1 /**
2 * Tier 2 — INTEGRATION: triple-surface parity + disabled gates.
3 */
4 import { describe, it, beforeEach, afterEach } from 'node:test';
5 import assert from 'node:assert/strict';
6 import fs from 'node:fs';
7 import path from 'node:path';
8 import { fileURLToPath } from 'node:url';
9
10 import {
11 handleFlowRunStartRequest,
12 handleFlowRunMcpRequest,
13 } from '../lib/flow/flow-execution.mjs';
14 import { createProposal } from '../hub/proposals-store.mjs';
15 import { writeExecutionPolicy, seedAutomatableFlow } from './fixtures/flow/execution-helpers.mjs';
16
17 const __dirname = path.dirname(fileURLToPath(import.meta.url));
18 const tmpRoot = path.join(__dirname, 'fixtures', 'tmp-flow-execution-parity');
19
20 describe('Flow execution — triple-surface parity', () => {
21 function freshDataDir(name) {
22 const d = path.join(tmpRoot, name);
23 fs.rmSync(d, { recursive: true, force: true });
24 fs.mkdirSync(d, { recursive: true });
25 return d;
26 }
27
28 beforeEach(() => {
29 fs.rmSync(tmpRoot, { recursive: true, force: true });
30 fs.mkdirSync(tmpRoot, { recursive: true });
31 process.env.FLOW_RUN_WRITES_ENABLED = '1';
32 });
33
34 afterEach(() => {
35 fs.rmSync(tmpRoot, { recursive: true, force: true });
36 delete process.env.FLOW_RUN_WRITES_ENABLED;
37 delete process.env.FLOW_AUTOMATABLE_EXECUTION_ENABLED;
38 });
39
40 it('Hub handler and MCP start produce deep-equal run records', () => {
41 const hubDir = freshDataDir('hub');
42 const mcpDir = freshDataDir('mcp');
43 const bundle = seedAutomatableFlow(hubDir, 'default');
44 seedAutomatableFlow(mcpDir, 'default');
45
46 const hub = handleFlowRunStartRequest({
47 dataDir: hubDir,
48 vaultId: 'default',
49 role: 'admin',
50 flowId: bundle.flow.flow_id,
51 flowVersion: bundle.flow.version,
52 harness: 'hub',
53 });
54 const mcp = handleFlowRunMcpRequest({
55 dataDir: mcpDir,
56 vaultId: 'default',
57 cliScopes: ['personal', 'project', 'org'],
58 action: 'start',
59 flow_id: bundle.flow.flow_id,
60 flow_version: bundle.flow.version,
61 harness: 'mcp',
62 });
63
64 assert.equal(hub.ok, true);
65 assert.equal(mcp.ok, true);
66 const hubRun = hub.payload.run;
67 const mcpRun = mcp.payload.run;
68 assert.equal(hubRun.flow_id, mcpRun.flow_id);
69 assert.equal(hubRun.flow_version, mcpRun.flow_version);
70 assert.equal(hubRun.scope, mcpRun.scope);
71 assert.equal(hubRun.step_states.length, mcpRun.step_states.length);
72 });
73
74 it('FLOW_RUN_WRITES_ENABLED=off ⇒ identical disabled code', () => {
75 delete process.env.FLOW_RUN_WRITES_ENABLED;
76 const dir = freshDataDir('off');
77 seedAutomatableFlow(dir, 'default');
78 const hub = handleFlowRunStartRequest({
79 dataDir: dir,
80 vaultId: 'default',
81 role: 'admin',
82 flowId: 'flow_automatable_test',
83 flowVersion: '1.0.0',
84 });
85 const mcp = handleFlowRunMcpRequest({
86 dataDir: dir,
87 vaultId: 'default',
88 cliScopes: ['personal', 'project', 'org'],
89 action: 'start',
90 flow_id: 'flow_automatable_test',
91 flow_version: '1.0.0',
92 createProposal,
93 });
94 assert.equal(hub.ok, false);
95 assert.equal(mcp.ok, false);
96 assert.equal(hub.code, 'FLOW_RUN_WRITES_DISABLED');
97 assert.equal(mcp.code, 'FLOW_RUN_WRITES_DISABLED');
98 });
99 });
100
101 describe('Flow execution — Hub route wiring contract', () => {
102 it('registers run routes gated by FLOW_RUN_WRITE_ROLES', async () => {
103 const { getRepoRoot } = await import('../lib/repo-root.mjs');
104 const src = fs.readFileSync(path.join(getRepoRoot(), 'hub/server.mjs'), 'utf8');
105 assert.match(src, /FLOW_RUN_WRITE_ROLES/);
106 assert.match(src, /execute-automatable/);
107 assert.match(src, /handleFlowRunStartRequest/);
108 });
109 });
File History 1 commit
sha256:8915fe406161f95c1681f9469375e7bae5b28c884f00bedbdef65e4b0cd0738d docs(flow): commit FLOW-V0-SPEC.md hygiene for 7A-INT merge Human 22 hours ago