flow-execution-unit.test.mjs
95 lines 3.4 KB
Raw
sha256:8915fe406161f95c1681f9469375e7bae5b28c884f00bedbdef65e4b0cd0738d docs(flow): commit FLOW-V0-SPEC.md hygiene for 7A-INT merge Human 19 hours ago
1 /**
2 * Tier 1 — UNIT: execution gate helpers, consent schema, sub-gate defaults.
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 getFlowRunWritesEnabled,
12 getFlowAutomatableExecutionEnabled,
13 consentForClient,
14 FLOW_EXECUTION_CONSENT_SCHEMA,
15 validateImportAutomatableSteps,
16 runModelOrchestrationStub,
17 frontierOrdinal,
18 } from '../lib/flow/flow-execution.mjs';
19 import { writeExecutionPolicy } from './fixtures/flow/execution-helpers.mjs';
20
21 const __dirname = path.dirname(fileURLToPath(import.meta.url));
22 const tmpRoot = path.join(__dirname, 'fixtures', 'tmp-flow-execution-unit');
23
24 describe('Flow execution — unit', () => {
25 beforeEach(() => {
26 fs.rmSync(tmpRoot, { recursive: true, force: true });
27 fs.mkdirSync(tmpRoot, { recursive: true });
28 delete process.env.FLOW_RUN_WRITES_ENABLED;
29 delete process.env.FLOW_AUTOMATABLE_EXECUTION_ENABLED;
30 });
31
32 afterEach(() => {
33 fs.rmSync(tmpRoot, { recursive: true, force: true });
34 delete process.env.FLOW_RUN_WRITES_ENABLED;
35 delete process.env.FLOW_AUTOMATABLE_EXECUTION_ENABLED;
36 });
37
38 it('sub-gates default off; policy file can enable', () => {
39 const dataDir = path.join(tmpRoot, 'off');
40 fs.mkdirSync(dataDir);
41 assert.equal(getFlowRunWritesEnabled(dataDir), false);
42 assert.equal(getFlowAutomatableExecutionEnabled(dataDir), false);
43 writeExecutionPolicy(dataDir, { runWrites: true, automatable: true });
44 assert.equal(getFlowRunWritesEnabled(dataDir), true);
45 assert.equal(getFlowAutomatableExecutionEnabled(dataDir), true);
46 });
47
48 it('consentForClient validates schema fields without secrets', () => {
49 const stored = {
50 schema: FLOW_EXECUTION_CONSENT_SCHEMA,
51 consent_id: 'fcons_test',
52 vault_id: 'default',
53 scope: 'personal',
54 run_id: 'run_abc',
55 flow_id: 'flow_test',
56 flow_version: '1.0.0',
57 allowed_lanes: ['local_default'],
58 cost_cap_units: 50,
59 cost_consumed_units: 0,
60 actor_hash: 'abc123',
61 expires_at: '2026-06-20T13:00:00Z',
62 revoked_at: null,
63 };
64 const client = consentForClient(stored);
65 assert.equal(client.schema, FLOW_EXECUTION_CONSENT_SCHEMA);
66 assert.equal(JSON.stringify(client).includes('api_key'), false);
67 });
68
69 it('validateImportAutomatableSteps rejects when policy forbids', () => {
70 const dataDir = path.join(tmpRoot, 'policy');
71 fs.mkdirSync(dataDir);
72 writeExecutionPolicy(dataDir, { automatableForbidden: true });
73 const steps = [{ step_id: 'flow_x#1', automatable: 'automatable' }];
74 const result = validateImportAutomatableSteps(steps, dataDir);
75 assert.equal(result.ok, false);
76 });
77
78 it('runModelOrchestrationStub dry_run produces no evidence', () => {
79 const out = runModelOrchestrationStub({ lane: 'local_default', dryRun: true });
80 assert.equal(out.evidence_ref, null);
81 assert.equal(out.cost_units, 0);
82 });
83
84 it('frontierOrdinal returns next pending ordinal', () => {
85 const steps = [
86 { step_id: 'flow_x#1', ordinal: 1 },
87 { step_id: 'flow_x#2', ordinal: 2 },
88 ];
89 const states = [
90 { step_id: 'flow_x#1', status: 'done', verified: true },
91 { step_id: 'flow_x#2', status: 'pending', verified: false },
92 ];
93 assert.equal(frontierOrdinal(states, steps), 2);
94 });
95 });
File History 1 commit
sha256:8915fe406161f95c1681f9469375e7bae5b28c884f00bedbdef65e4b0cd0738d docs(flow): commit FLOW-V0-SPEC.md hygiene for 7A-INT merge Human 19 hours ago