flow-projection-generator-stress.test.mjs
121 lines 3.9 KB
Raw
sha256:8915fe406161f95c1681f9469375e7bae5b28c884f00bedbdef65e4b0cd0738d docs(flow): commit FLOW-V0-SPEC.md hygiene for 7A-INT merge Human 15 hours ago
1 /**
2 * Tier 4 — STRESS: large-flow projection bounds and ordering.
3 *
4 * @see docs/FLOW-PROJECTION-GENERATOR-CONTRACT-7A-11.md §9
5 */
6 import { describe, it, beforeEach, afterEach } from 'node:test';
7 import assert from 'node:assert/strict';
8 import fs from 'node:fs';
9 import path from 'node:path';
10 import { fileURLToPath } from 'node:url';
11 import {
12 projectFlow,
13 MAX_RENDERED_BYTES,
14 } from '../lib/flow/projection-generator.mjs';
15 import {
16 saveFlowStore,
17 buildFlowStepId,
18 MAX_STEPS_PER_FLOW,
19 } from '../lib/flow/flow-store.mjs';
20
21 const __dirname = path.dirname(fileURLToPath(import.meta.url));
22 const tmpRoot = path.join(__dirname, 'fixtures', 'tmp-flow-projection-stress');
23
24 describe('Flow projection — stress', () => {
25 const dataDir = path.join(tmpRoot, 'data');
26 const vaultId = 'default';
27 const flowId = 'flow_stress_projection';
28
29 beforeEach(() => {
30 fs.rmSync(tmpRoot, { recursive: true, force: true });
31 fs.mkdirSync(dataDir, { recursive: true });
32 const steps = [];
33 const stepIds = [];
34 for (let i = 1; i <= MAX_STEPS_PER_FLOW; i += 1) {
35 const stepId = buildFlowStepId(flowId, i);
36 stepIds.push(stepId);
37 steps.push({
38 schema: 'knowtation.flow_step/v0',
39 step_id: stepId,
40 flow_id: flowId,
41 ordinal: i,
42 owned_job: `Job ${i} with padding ${'x'.repeat(200)}`,
43 instruction: `Instruction ${i}`,
44 trigger: `Trigger ${i}`,
45 when_not_to_run: `Skip ${i}`,
46 requires: [{ kind: 'tool', id: `handle_${i}` }],
47 boundaries: [`boundary ${i}`],
48 skill_refs: [{ kind: 'cli', id: `skill_${i}` }],
49 inputs: [{ name: 'in', from: 'prev' }],
50 outputs: [{ name: 'out', type: 'text' }],
51 output_shape: `shape ${i}`,
52 verification: {
53 kind: 'human_review',
54 evidence_required: true,
55 description: `verify ${i}`,
56 },
57 automatable: 'manual',
58 });
59 }
60 saveFlowStore(dataDir, {
61 vaults: {
62 [vaultId]: {
63 flows: [
64 {
65 schema: 'knowtation.flow/v0',
66 flow_id: flowId,
67 title: 'Stress projection',
68 version: '1.0.0',
69 scope: 'personal',
70 summary: 'stress',
71 tags: ['stress'],
72 steps: stepIds,
73 updated: '2026-06-20T00:00:00Z',
74 truncated: false,
75 },
76 ],
77 steps,
78 runs: [],
79 candidates: [],
80 projections: [],
81 },
82 },
83 });
84 });
85
86 afterEach(() => {
87 fs.rmSync(tmpRoot, { recursive: true, force: true });
88 });
89
90 it('MAX_STEPS_PER_FLOW flow stays within MAX_RENDERED_BYTES with step-boundary truncation', () => {
91 const store = JSON.parse(
92 fs.readFileSync(path.join(dataDir, 'hub_flow_store.json'), 'utf8'),
93 );
94 const flow = store.vaults[vaultId].flows[0];
95 const steps = store.vaults[vaultId].steps;
96 const t0 = performance.now();
97 const projection = projectFlow(flow, steps, { harness: 'cli_runbook' });
98 const elapsed = performance.now() - t0;
99 assert.ok(Buffer.byteLength(projection.rendered, 'utf8') <= MAX_RENDERED_BYTES);
100 const ordinals = [...projection.rendered.matchAll(/## Step (\d+)/g)].map((m) => Number(m[1]));
101 for (let i = 1; i < ordinals.length; i += 1) {
102 assert.ok(ordinals[i] > ordinals[i - 1]);
103 }
104 assert.ok(elapsed < 5000, `render took ${elapsed}ms`);
105 if (projection.fidelity.notes) {
106 assert.match(projection.fidelity.notes, /truncat/i);
107 }
108 });
109
110 it('many back-to-back projections remain bounded', () => {
111 const store = JSON.parse(
112 fs.readFileSync(path.join(dataDir, 'hub_flow_store.json'), 'utf8'),
113 );
114 const flow = store.vaults[vaultId].flows[0];
115 const steps = store.vaults[vaultId].steps;
116 for (let i = 0; i < 20; i += 1) {
117 const p = projectFlow(flow, steps, { harness: 'cursor_rule' });
118 assert.ok(Buffer.byteLength(p.rendered, 'utf8') <= MAX_RENDERED_BYTES);
119 }
120 });
121 });
File History 1 commit
sha256:8915fe406161f95c1681f9469375e7bae5b28c884f00bedbdef65e4b0cd0738d docs(flow): commit FLOW-V0-SPEC.md hygiene for 7A-INT merge Human 15 hours ago