@studio-foundation/engine 0.3.0-beta.1 → 0.3.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/dist/__tests__/engine.conditions-group.test.d.ts +2 -0
  2. package/dist/__tests__/engine.conditions-group.test.d.ts.map +1 -0
  3. package/dist/__tests__/engine.conditions-group.test.js +222 -0
  4. package/dist/__tests__/engine.conditions-group.test.js.map +1 -0
  5. package/dist/__tests__/engine.conditions.test.d.ts +2 -0
  6. package/dist/__tests__/engine.conditions.test.d.ts.map +1 -0
  7. package/dist/__tests__/engine.conditions.test.js +164 -0
  8. package/dist/__tests__/engine.conditions.test.js.map +1 -0
  9. package/dist/__tests__/engine.resume.test.d.ts +2 -0
  10. package/dist/__tests__/engine.resume.test.d.ts.map +1 -0
  11. package/dist/__tests__/engine.resume.test.js +93 -0
  12. package/dist/__tests__/engine.resume.test.js.map +1 -0
  13. package/dist/__tests__/engine.script-stage.test.d.ts +2 -0
  14. package/dist/__tests__/engine.script-stage.test.d.ts.map +1 -0
  15. package/dist/__tests__/engine.script-stage.test.js +108 -0
  16. package/dist/__tests__/engine.script-stage.test.js.map +1 -0
  17. package/dist/db/client.d.ts +3 -0
  18. package/dist/db/client.d.ts.map +1 -0
  19. package/{src/db/client.ts → dist/db/client.js} +1 -2
  20. package/dist/db/client.js.map +1 -0
  21. package/dist/engine.context-event.test.d.ts +2 -0
  22. package/dist/engine.context-event.test.d.ts.map +1 -0
  23. package/dist/engine.context-event.test.js +111 -0
  24. package/dist/engine.context-event.test.js.map +1 -0
  25. package/dist/engine.d.ts +52 -0
  26. package/dist/engine.d.ts.map +1 -0
  27. package/dist/engine.js +364 -0
  28. package/dist/engine.js.map +1 -0
  29. package/dist/events.d.ts +163 -0
  30. package/dist/events.d.ts.map +1 -0
  31. package/dist/events.js +12 -0
  32. package/dist/events.js.map +1 -0
  33. package/{src/index.ts → dist/index.d.ts} +3 -45
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +24 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/pipeline/agent-loader.d.ts +4 -0
  38. package/dist/pipeline/agent-loader.d.ts.map +1 -0
  39. package/dist/pipeline/agent-loader.js +28 -0
  40. package/dist/pipeline/agent-loader.js.map +1 -0
  41. package/dist/pipeline/agent-loader.test.d.ts +2 -0
  42. package/dist/pipeline/agent-loader.test.d.ts.map +1 -0
  43. package/dist/pipeline/agent-loader.test.js +134 -0
  44. package/dist/pipeline/agent-loader.test.js.map +1 -0
  45. package/dist/pipeline/condition-evaluator.d.ts +6 -0
  46. package/dist/pipeline/condition-evaluator.d.ts.map +1 -0
  47. package/dist/pipeline/condition-evaluator.js +105 -0
  48. package/dist/pipeline/condition-evaluator.js.map +1 -0
  49. package/dist/pipeline/condition-evaluator.test.d.ts +2 -0
  50. package/dist/pipeline/condition-evaluator.test.d.ts.map +1 -0
  51. package/dist/pipeline/condition-evaluator.test.js +103 -0
  52. package/dist/pipeline/condition-evaluator.test.js.map +1 -0
  53. package/dist/pipeline/context-pack-loader.d.ts +3 -0
  54. package/dist/pipeline/context-pack-loader.d.ts.map +1 -0
  55. package/dist/pipeline/context-pack-loader.js +51 -0
  56. package/dist/pipeline/context-pack-loader.js.map +1 -0
  57. package/dist/pipeline/context-propagation.d.ts +28 -0
  58. package/dist/pipeline/context-propagation.d.ts.map +1 -0
  59. package/dist/pipeline/context-propagation.js +161 -0
  60. package/dist/pipeline/context-propagation.js.map +1 -0
  61. package/dist/pipeline/context-propagation.test.d.ts +2 -0
  62. package/dist/pipeline/context-propagation.test.d.ts.map +1 -0
  63. package/dist/pipeline/context-propagation.test.js +194 -0
  64. package/dist/pipeline/context-propagation.test.js.map +1 -0
  65. package/dist/pipeline/contract-loader.d.ts +4 -0
  66. package/dist/pipeline/contract-loader.d.ts.map +1 -0
  67. package/dist/pipeline/contract-loader.js +30 -0
  68. package/dist/pipeline/contract-loader.js.map +1 -0
  69. package/dist/pipeline/group-orchestrator.d.ts +19 -0
  70. package/dist/pipeline/group-orchestrator.d.ts.map +1 -0
  71. package/dist/pipeline/group-orchestrator.js +376 -0
  72. package/dist/pipeline/group-orchestrator.js.map +1 -0
  73. package/dist/pipeline/hook-executor.d.ts +28 -0
  74. package/dist/pipeline/hook-executor.d.ts.map +1 -0
  75. package/dist/pipeline/hook-executor.js +63 -0
  76. package/dist/pipeline/hook-executor.js.map +1 -0
  77. package/dist/pipeline/hook-executor.test.d.ts +2 -0
  78. package/dist/pipeline/hook-executor.test.d.ts.map +1 -0
  79. package/dist/pipeline/hook-executor.test.js +71 -0
  80. package/dist/pipeline/hook-executor.test.js.map +1 -0
  81. package/dist/pipeline/invariants-loader.d.ts +6 -0
  82. package/dist/pipeline/invariants-loader.d.ts.map +1 -0
  83. package/dist/pipeline/invariants-loader.js +15 -0
  84. package/dist/pipeline/invariants-loader.js.map +1 -0
  85. package/dist/pipeline/invariants-loader.test.d.ts +2 -0
  86. package/dist/pipeline/invariants-loader.test.d.ts.map +1 -0
  87. package/dist/pipeline/invariants-loader.test.js +39 -0
  88. package/dist/pipeline/invariants-loader.test.js.map +1 -0
  89. package/dist/pipeline/loader.d.ts +5 -0
  90. package/dist/pipeline/loader.d.ts.map +1 -0
  91. package/dist/pipeline/loader.js +132 -0
  92. package/dist/pipeline/loader.js.map +1 -0
  93. package/dist/pipeline/loader.test.d.ts +2 -0
  94. package/dist/pipeline/loader.test.d.ts.map +1 -0
  95. package/dist/pipeline/loader.test.js +120 -0
  96. package/dist/pipeline/loader.test.js.map +1 -0
  97. package/dist/pipeline/output-validator.d.ts +10 -0
  98. package/dist/pipeline/output-validator.d.ts.map +1 -0
  99. package/dist/pipeline/output-validator.js +20 -0
  100. package/dist/pipeline/output-validator.js.map +1 -0
  101. package/dist/pipeline/output-validator.test.d.ts +2 -0
  102. package/dist/pipeline/output-validator.test.d.ts.map +1 -0
  103. package/dist/pipeline/output-validator.test.js +77 -0
  104. package/dist/pipeline/output-validator.test.js.map +1 -0
  105. package/dist/pipeline/post-validator.d.ts +8 -0
  106. package/dist/pipeline/post-validator.d.ts.map +1 -0
  107. package/dist/pipeline/post-validator.js +103 -0
  108. package/dist/pipeline/post-validator.js.map +1 -0
  109. package/dist/pipeline/skill-loader.d.ts +10 -0
  110. package/dist/pipeline/skill-loader.d.ts.map +1 -0
  111. package/dist/pipeline/skill-loader.js +26 -0
  112. package/dist/pipeline/skill-loader.js.map +1 -0
  113. package/dist/pipeline/skill-loader.test.d.ts +2 -0
  114. package/dist/pipeline/skill-loader.test.d.ts.map +1 -0
  115. package/dist/pipeline/skill-loader.test.js +38 -0
  116. package/dist/pipeline/skill-loader.test.js.map +1 -0
  117. package/dist/pipeline/stage-executor.d.ts +26 -0
  118. package/dist/pipeline/stage-executor.d.ts.map +1 -0
  119. package/dist/pipeline/stage-executor.js +540 -0
  120. package/dist/pipeline/stage-executor.js.map +1 -0
  121. package/dist/pipeline/stage-resolver.d.ts +3 -0
  122. package/dist/pipeline/stage-resolver.d.ts.map +1 -0
  123. package/dist/pipeline/stage-resolver.js +6 -0
  124. package/dist/pipeline/stage-resolver.js.map +1 -0
  125. package/dist/pipeline/startup-executor.d.ts +3 -0
  126. package/dist/pipeline/startup-executor.d.ts.map +1 -0
  127. package/dist/pipeline/startup-executor.js +23 -0
  128. package/dist/pipeline/startup-executor.js.map +1 -0
  129. package/dist/pipeline/startup-executor.test.d.ts +2 -0
  130. package/dist/pipeline/startup-executor.test.d.ts.map +1 -0
  131. package/dist/pipeline/startup-executor.test.js +34 -0
  132. package/dist/pipeline/startup-executor.test.js.map +1 -0
  133. package/dist/pipeline/types.d.ts +28 -0
  134. package/dist/pipeline/types.d.ts.map +1 -0
  135. package/dist/pipeline/types.js +12 -0
  136. package/dist/pipeline/types.js.map +1 -0
  137. package/dist/repo-resolver.d.ts +10 -0
  138. package/dist/repo-resolver.d.ts.map +1 -0
  139. package/dist/repo-resolver.js +39 -0
  140. package/dist/repo-resolver.js.map +1 -0
  141. package/dist/spawners/direct-engine-spawner.d.ts +8 -0
  142. package/dist/spawners/direct-engine-spawner.d.ts.map +1 -0
  143. package/dist/spawners/direct-engine-spawner.js +24 -0
  144. package/dist/spawners/direct-engine-spawner.js.map +1 -0
  145. package/dist/state/run-store.d.ts +74 -0
  146. package/dist/state/run-store.d.ts.map +1 -0
  147. package/dist/state/run-store.js +269 -0
  148. package/dist/state/run-store.js.map +1 -0
  149. package/dist/state/run-store.test.d.ts +2 -0
  150. package/dist/state/run-store.test.d.ts.map +1 -0
  151. package/dist/state/run-store.test.js +130 -0
  152. package/dist/state/run-store.test.js.map +1 -0
  153. package/dist/state/state-machine.d.ts +6 -0
  154. package/dist/state/state-machine.d.ts.map +1 -0
  155. package/dist/state/state-machine.js +27 -0
  156. package/dist/state/state-machine.js.map +1 -0
  157. package/dist/state/status-derivation.d.ts +12 -0
  158. package/dist/state/status-derivation.d.ts.map +1 -0
  159. package/dist/state/status-derivation.js +30 -0
  160. package/dist/state/status-derivation.js.map +1 -0
  161. package/package.json +7 -4
  162. package/ARCHITECTURE.md +0 -57
  163. package/src/__tests__/__fixtures__/script-stage/contracts/book-context.contract.yaml +0 -4
  164. package/src/__tests__/engine.conditions-group.test.ts +0 -244
  165. package/src/__tests__/engine.conditions.test.ts +0 -186
  166. package/src/__tests__/engine.resume.test.ts +0 -108
  167. package/src/__tests__/engine.script-stage.test.ts +0 -125
  168. package/src/engine.context-event.test.ts +0 -175
  169. package/src/engine.ts +0 -491
  170. package/src/events.ts +0 -167
  171. package/src/pipeline/agent-loader.test.ts +0 -151
  172. package/src/pipeline/agent-loader.ts +0 -39
  173. package/src/pipeline/condition-evaluator.test.ts +0 -129
  174. package/src/pipeline/condition-evaluator.ts +0 -121
  175. package/src/pipeline/context-pack-loader.ts +0 -63
  176. package/src/pipeline/context-propagation.test.ts +0 -237
  177. package/src/pipeline/context-propagation.ts +0 -235
  178. package/src/pipeline/contract-loader.ts +0 -41
  179. package/src/pipeline/group-orchestrator.ts +0 -483
  180. package/src/pipeline/hook-executor.test.ts +0 -121
  181. package/src/pipeline/hook-executor.ts +0 -87
  182. package/src/pipeline/invariants-loader.test.ts +0 -51
  183. package/src/pipeline/invariants-loader.ts +0 -14
  184. package/src/pipeline/loader.test.ts +0 -128
  185. package/src/pipeline/loader.ts +0 -149
  186. package/src/pipeline/output-validator.test.ts +0 -100
  187. package/src/pipeline/output-validator.ts +0 -40
  188. package/src/pipeline/post-validator.ts +0 -124
  189. package/src/pipeline/skill-loader.test.ts +0 -44
  190. package/src/pipeline/skill-loader.ts +0 -32
  191. package/src/pipeline/stage-executor.ts +0 -654
  192. package/src/pipeline/stage-resolver.ts +0 -8
  193. package/src/pipeline/startup-executor.test.ts +0 -37
  194. package/src/pipeline/startup-executor.ts +0 -32
  195. package/src/pipeline/types.ts +0 -42
  196. package/src/repo-resolver.ts +0 -61
  197. package/src/spawners/direct-engine-spawner.ts +0 -26
  198. package/src/state/run-store.test.ts +0 -157
  199. package/src/state/run-store.ts +0 -362
  200. package/src/state/state-machine.ts +0 -35
  201. package/src/state/status-derivation.ts +0 -36
  202. package/tests/context-pack-loader.test.ts +0 -113
  203. package/tests/context-propagation.test.ts +0 -267
  204. package/tests/direct-engine-spawner.test.ts +0 -102
  205. package/tests/e2e/feature-v5.test.ts +0 -57
  206. package/tests/events.test.ts +0 -56
  207. package/tests/fixtures/agents/test-agent.agent.yaml +0 -5
  208. package/tests/fixtures/contracts/code-gen.contract.yaml +0 -6
  209. package/tests/fixtures/contracts/qa-gate.contract.yaml +0 -15
  210. package/tests/fixtures/contracts/test-contract.contract.yaml +0 -6
  211. package/tests/fixtures/pipelines/group-test.pipeline.yaml +0 -40
  212. package/tests/fixtures/pipelines/simple.pipeline.yaml +0 -15
  213. package/tests/fixtures/pipelines/two-stage.pipeline.yaml +0 -24
  214. package/tests/fixtures/software/pipelines/feature-builder.pipeline.yaml +0 -75
  215. package/tests/fixtures/test-project/agents/test-agent.agent.yaml +0 -5
  216. package/tests/fixtures/test-project/contracts/basic-result.contract.yaml +0 -6
  217. package/tests/fixtures/test-project/contracts/code-gen.contract.yaml +0 -6
  218. package/tests/fixtures/test-project/contracts/maximum-only.contract.yaml +0 -8
  219. package/tests/fixtures/test-project/contracts/qa-gate.contract.yaml +0 -15
  220. package/tests/fixtures/test-project/contracts/strict-result.contract.yaml +0 -7
  221. package/tests/fixtures/test-project/contracts/test-contract.contract.yaml +0 -6
  222. package/tests/fixtures/test-project/pipelines/group-simple.pipeline.yaml +0 -26
  223. package/tests/fixtures/test-project/pipelines/group-test.pipeline.yaml +0 -40
  224. package/tests/fixtures/test-project/pipelines/hook-output-template.pipeline.yaml +0 -19
  225. package/tests/fixtures/test-project/pipelines/hook-reject-on-failure.pipeline.yaml +0 -19
  226. package/tests/fixtures/test-project/pipelines/maximum-only.pipeline.yaml +0 -15
  227. package/tests/fixtures/test-project/pipelines/parallel-collect-all-test.pipeline.yaml +0 -39
  228. package/tests/fixtures/test-project/pipelines/parallel-context-isolation-test.pipeline.yaml +0 -38
  229. package/tests/fixtures/test-project/pipelines/parallel-fail-test.pipeline.yaml +0 -39
  230. package/tests/fixtures/test-project/pipelines/parallel-test.pipeline.yaml +0 -39
  231. package/tests/fixtures/test-project/pipelines/parallel-then-sequential-test.pipeline.yaml +0 -38
  232. package/tests/fixtures/test-project/pipelines/simple.pipeline.yaml +0 -15
  233. package/tests/fixtures/test-project/pipelines/two-stage.pipeline.yaml +0 -24
  234. package/tests/fixtures/test-project/pipelines/with-startup.pipeline.yaml +0 -19
  235. package/tests/loader.test.ts +0 -385
  236. package/tests/post-validator.test.ts +0 -297
  237. package/tests/repo-resolver.test.ts +0 -102
  238. package/tests/run-store.test.ts +0 -143
  239. package/tests/state-machine.test.ts +0 -110
  240. package/tests/unit/context-propagation.test.ts +0 -45
  241. package/tests/unit/engine.test.ts +0 -770
  242. package/tests/unit/group-loop.test.ts +0 -389
  243. package/tests/unit/group-parallel.test.ts +0 -423
  244. package/tests/unit/state/status-derivation.test.ts +0 -88
  245. package/tsconfig.json +0 -24
  246. package/vitest.config.ts +0 -14
@@ -0,0 +1,3 @@
1
+ export { SQLiteRunStore, InMemoryRunStore, PgRunStore } from '../state/run-store.js';
2
+ export type { RunStore, AsyncRunStore, AnyRunStore } from '../state/run-store.js';
3
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACrF,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC"}
@@ -1,5 +1,4 @@
1
1
  // Database client — re-exports from run-store
2
2
  // Kept for backward compatibility with the barrel structure
3
-
4
3
  export { SQLiteRunStore, InMemoryRunStore, PgRunStore } from '../state/run-store.js';
5
- export type { RunStore, AsyncRunStore, AnyRunStore } from '../state/run-store.js';
4
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,4DAA4D;AAE5D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=engine.context-event.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.context-event.test.d.ts","sourceRoot":"","sources":["../src/engine.context-event.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,111 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { mkdtemp, mkdir, writeFile } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ import { PipelineEngine } from './engine.js';
6
+ import { createDefaultRegistry, ToolRegistry, MockProvider } from '@studio-foundation/runner';
7
+ async function makeTestDirs() {
8
+ const base = await mkdtemp(join(tmpdir(), 'studio-ctx-test-'));
9
+ const configsDir = join(base, '.studio');
10
+ await mkdir(join(configsDir, 'pipelines'), { recursive: true });
11
+ await mkdir(join(configsDir, 'agents'), { recursive: true });
12
+ await mkdir(join(configsDir, 'contracts'), { recursive: true });
13
+ await writeFile(join(configsDir, 'pipelines', 'test-pipe.pipeline.yaml'), `
14
+ name: test-pipe
15
+ description: test
16
+ version: 1
17
+ stages:
18
+ - name: my-stage
19
+ kind: analysis
20
+ agent: analyst
21
+ contract: stage-contract
22
+ context:
23
+ include: [input]
24
+ `);
25
+ await writeFile(join(configsDir, 'agents', 'analyst.agent.yaml'), `
26
+ name: analyst
27
+ provider: mock
28
+ model: mock
29
+ system_prompt: "You are an analyst."
30
+ `);
31
+ await writeFile(join(configsDir, 'contracts', 'stage-contract.contract.yaml'), `
32
+ name: stage-contract
33
+ version: 1
34
+ schema:
35
+ required_fields:
36
+ - summary
37
+ `);
38
+ return { configsDir };
39
+ }
40
+ // MockProvider keys on contract_name (= stage_contract). Use this in all tests.
41
+ const MOCK_STAGE_KEY = 'stage-contract';
42
+ describe('PipelineEngine — onStageContext event', () => {
43
+ it('emits onStageContext once per stage', async () => {
44
+ const { configsDir } = await makeTestDirs();
45
+ const mockStages = new Map([
46
+ [MOCK_STAGE_KEY, { output: { summary: 'done' }, tool_calls: [] }],
47
+ ]);
48
+ const mockProvider = new MockProvider(mockStages);
49
+ const providerRegistry = createDefaultRegistry({});
50
+ providerRegistry.register(mockProvider);
51
+ const toolRegistry = new ToolRegistry();
52
+ const received = [];
53
+ const engine = new PipelineEngine({ configsDir, providerRegistry, toolRegistry }, { onStageContext: (e) => received.push(e) });
54
+ await engine.run({ pipeline: 'test-pipe', input: 'test input' });
55
+ expect(received).toHaveLength(1);
56
+ expect(received[0].stage).toBe('my-stage');
57
+ expect(received[0].run_id).toMatch(/^[0-9a-f-]{36}$/); // uuid
58
+ expect(received[0].context_keys.input).toBe('test input'.length);
59
+ });
60
+ it('includes no context_content by default (DEBUG unset)', async () => {
61
+ const { configsDir } = await makeTestDirs();
62
+ delete process.env.DEBUG;
63
+ const mockProvider = new MockProvider(new Map([[MOCK_STAGE_KEY, { output: { summary: 'done' }, tool_calls: [] }]]));
64
+ const providerRegistry = createDefaultRegistry({});
65
+ providerRegistry.register(mockProvider);
66
+ const received = [];
67
+ const engine = new PipelineEngine({ configsDir, providerRegistry, toolRegistry: new ToolRegistry() }, { onStageContext: (e) => received.push(e) });
68
+ await engine.run({ pipeline: 'test-pipe', input: 'hello' });
69
+ expect(received[0].context_content).toBeUndefined();
70
+ expect(received[0].system_prompt).toBeUndefined();
71
+ });
72
+ it('includes context_content when DEBUG=studio:context', async () => {
73
+ const { configsDir } = await makeTestDirs();
74
+ process.env.DEBUG = 'studio:context';
75
+ const mockProvider = new MockProvider(new Map([[MOCK_STAGE_KEY, { output: { summary: 'done' }, tool_calls: [] }]]));
76
+ const providerRegistry = createDefaultRegistry({});
77
+ providerRegistry.register(mockProvider);
78
+ const received = [];
79
+ const engine = new PipelineEngine({ configsDir, providerRegistry, toolRegistry: new ToolRegistry() }, { onStageContext: (e) => received.push(e) });
80
+ await engine.run({ pipeline: 'test-pipe', input: 'hello' });
81
+ expect(received[0].context_content).toBeDefined();
82
+ expect(received[0].context_content?.input).toBe('hello');
83
+ expect(received[0].system_prompt).toBeUndefined();
84
+ delete process.env.DEBUG;
85
+ });
86
+ it('includes system_prompt when DEBUG=studio:context:verbose', async () => {
87
+ const { configsDir } = await makeTestDirs();
88
+ process.env.DEBUG = 'studio:context:verbose';
89
+ const mockProvider = new MockProvider(new Map([[MOCK_STAGE_KEY, { output: { summary: 'done' }, tool_calls: [] }]]));
90
+ const providerRegistry = createDefaultRegistry({});
91
+ providerRegistry.register(mockProvider);
92
+ const received = [];
93
+ const engine = new PipelineEngine({ configsDir, providerRegistry, toolRegistry: new ToolRegistry() }, { onStageContext: (e) => received.push(e) });
94
+ await engine.run({ pipeline: 'test-pipe', input: 'hello' });
95
+ expect(received[0].context_content).toBeDefined(); // verbose implies context
96
+ expect(received[0].system_prompt).toBe('You are an analyst.');
97
+ delete process.env.DEBUG;
98
+ });
99
+ it('does not call handler at all when onStageContext is not registered', async () => {
100
+ const { configsDir } = await makeTestDirs();
101
+ const mockProvider = new MockProvider(new Map([[MOCK_STAGE_KEY, { output: { summary: 'done' }, tool_calls: [] }]]));
102
+ const providerRegistry = createDefaultRegistry({});
103
+ providerRegistry.register(mockProvider);
104
+ // No onStageContext handler
105
+ const engine = new PipelineEngine({ configsDir, providerRegistry, toolRegistry: new ToolRegistry() }, { onStageComplete: vi.fn() } // some other handler but not onStageContext
106
+ );
107
+ // Should not throw
108
+ await engine.run({ pipeline: 'test-pipe', input: 'hello' });
109
+ });
110
+ });
111
+ //# sourceMappingURL=engine.context-event.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.context-event.test.js","sourceRoot":"","sources":["../src/engine.context-event.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { PipelineRun, PipelineDefinition, RunSpawner, ToolCall } from '@studio-foundation/contracts';
2
+ import { type ToolRegistry, type ProviderRegistry } from '@studio-foundation/runner';
3
+ import type { AnyRunStore } from './state/run-store.js';
4
+ import type { EngineEvents } from './events.js';
5
+ export interface EngineConfig {
6
+ configsDir: string;
7
+ repoPath?: string;
8
+ providerRegistry: ProviderRegistry;
9
+ toolRegistry?: ToolRegistry;
10
+ db?: AnyRunStore;
11
+ providerOverride?: string;
12
+ /**
13
+ * Skills content from active plugins, keyed by plugin name.
14
+ * Each entry is an array of formatted markdown strings to inject
15
+ * into the system prompt of agents that declare the plugin.
16
+ */
17
+ pluginSkills?: Record<string, string[]>;
18
+ spawner?: RunSpawner;
19
+ maxDepth?: number;
20
+ defaultProvider?: string;
21
+ defaultModel?: string;
22
+ }
23
+ export interface RunInput {
24
+ id?: string;
25
+ pipeline?: string;
26
+ pipelineDef?: PipelineDefinition;
27
+ input?: string | Record<string, unknown>;
28
+ userInput?: string | Record<string, unknown>;
29
+ meta?: Record<string, unknown>;
30
+ anonymize?: boolean;
31
+ signal?: AbortSignal;
32
+ depth?: number;
33
+ parentRunId?: string;
34
+ resumeFromStage?: string;
35
+ priorStageOutputs?: Map<string, unknown>;
36
+ priorStageToolResults?: Map<string, ToolCall[]>;
37
+ originalRunId?: string;
38
+ }
39
+ export declare class PipelineEngine {
40
+ private config;
41
+ private events?;
42
+ private emitter;
43
+ private pipelineTotals;
44
+ private stageExecutor;
45
+ private groupOrchestrator;
46
+ constructor(config: EngineConfig, events?: EngineEvents | undefined);
47
+ run(input: RunInput): Promise<PipelineRun>;
48
+ /** For external listeners via the generic event bus */
49
+ onEvent(listener: (event: import('./events.js').PipelineEvent) => void): void;
50
+ private persistKeymap;
51
+ }
52
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,WAAW,EACX,kBAAkB,EAClB,UAAU,EAEV,QAAQ,EACT,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,gBAAgB,EAItB,MAAM,2BAA2B,CAAC;AAUnC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAMhD,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,qBAAqB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA2DD,qBAAa,cAAc;IAOvB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM,CAAC;IAPjB,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,iBAAiB,CAAoB;gBAGnC,MAAM,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,YAAY,YAAA;IAqBzB,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC;IAsThD,uDAAuD;IACvD,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,aAAa,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI;YAM/D,aAAa;CAc5B"}
package/dist/engine.js ADDED
@@ -0,0 +1,364 @@
1
+ // Main pipeline engine — the orchestrator
2
+ // Connects ralph (retry loop) + runner (agent execution) + contracts (validation)
3
+ import { randomUUID } from 'node:crypto';
4
+ import { isStageGroup } from '@studio-foundation/contracts';
5
+ import { AnonymizationMiddleware, createStudioRunTool, STUDIO_RUN_PROMPT_SNIPPET, } from '@studio-foundation/runner';
6
+ import { loadPipelineByName } from './pipeline/loader.js';
7
+ import { executeStartupCommands } from './pipeline/startup-executor.js';
8
+ import { loadInvariantsFile } from './pipeline/invariants-loader.js';
9
+ import { createInitialContext, addStageOutput, addStageToolResults, clearGroupFeedback, } from './pipeline/context-propagation.js';
10
+ import { PipelineEventEmitter } from './events.js';
11
+ import { resolveProjectPaths } from './pipeline/types.js';
12
+ import { StageExecutor } from './pipeline/stage-executor.js';
13
+ import { GroupOrchestrator } from './pipeline/group-orchestrator.js';
14
+ /**
15
+ * Collect all leaf stage names in pipeline order (group containers are transparent).
16
+ */
17
+ function collectLeafStageNames(entries) {
18
+ const names = [];
19
+ for (const entry of entries) {
20
+ if (isStageGroup(entry)) {
21
+ for (const stage of entry.stages)
22
+ names.push(stage.name);
23
+ }
24
+ else {
25
+ names.push(entry.name);
26
+ }
27
+ }
28
+ return names;
29
+ }
30
+ /**
31
+ * Returns the set of stage names that should be skipped (all leaf stages before resumeFromStage).
32
+ * Throws if resumeFromStage is not found in the pipeline.
33
+ */
34
+ function buildSkipSet(entries, resumeFromStage) {
35
+ const leafNames = collectLeafStageNames(entries);
36
+ const targetIndex = leafNames.indexOf(resumeFromStage);
37
+ if (targetIndex < 0) {
38
+ throw new Error(`Stage "${resumeFromStage}" not found in pipeline`);
39
+ }
40
+ return new Set(leafNames.slice(0, targetIndex));
41
+ }
42
+ function countTotalStages(entries) {
43
+ let count = 0;
44
+ for (const entry of entries) {
45
+ if (isStageGroup(entry)) {
46
+ count += entry.stages.length;
47
+ }
48
+ else {
49
+ count++;
50
+ }
51
+ }
52
+ return count;
53
+ }
54
+ /**
55
+ * Create a StageRun for a skipped stage (used during resume operations).
56
+ * Uses randomUUID() to ensure unique IDs across multiple resume runs.
57
+ */
58
+ function makeSkippedStageRun(stageName, reason) {
59
+ const now = new Date().toISOString();
60
+ return {
61
+ id: randomUUID(),
62
+ stage_name: stageName,
63
+ status: 'skipped',
64
+ started_at: now,
65
+ completed_at: now,
66
+ tasks: [],
67
+ skipped_reason: reason,
68
+ };
69
+ }
70
+ export class PipelineEngine {
71
+ config;
72
+ events;
73
+ emitter;
74
+ pipelineTotals = { tokens: 0, toolCalls: 0 };
75
+ stageExecutor;
76
+ groupOrchestrator;
77
+ constructor(config, events) {
78
+ this.config = config;
79
+ this.events = events;
80
+ this.emitter = new PipelineEventEmitter();
81
+ this.stageExecutor = new StageExecutor({
82
+ events,
83
+ emitter: this.emitter,
84
+ providerRegistry: config.providerRegistry,
85
+ repoPath: config.repoPath,
86
+ configsDir: config.configsDir,
87
+ pluginSkills: config.pluginSkills,
88
+ providerOverride: config.providerOverride,
89
+ defaultProvider: config.defaultProvider,
90
+ defaultModel: config.defaultModel,
91
+ });
92
+ this.groupOrchestrator = new GroupOrchestrator({
93
+ events,
94
+ emitter: this.emitter,
95
+ stageExecutor: this.stageExecutor,
96
+ });
97
+ }
98
+ async run(input) {
99
+ const signal = input.signal;
100
+ // Resolve the effective user input (support both 'input' and 'userInput' aliases)
101
+ const userInputValue = input.userInput ?? input.input ?? '';
102
+ if (!input.pipeline && !input.pipelineDef) {
103
+ throw new Error('RunInput must provide either "pipeline" (pipeline name) or "pipelineDef" (inline definition)');
104
+ }
105
+ // 1. Resolve paths — configsDir is now the project root directly
106
+ const projectPaths = resolveProjectPaths(this.config.configsDir);
107
+ // 2. Load the pipeline — either from an inline definition or a YAML file
108
+ const pipeline = input.pipelineDef
109
+ ? input.pipelineDef
110
+ : await loadPipelineByName(input.pipeline, projectPaths.pipelinesDir);
111
+ // 2. Create the PipelineRun
112
+ const pipelineRun = {
113
+ id: input.id ?? randomUUID(),
114
+ pipeline_name: pipeline.name,
115
+ status: 'running',
116
+ started_at: new Date().toISOString(),
117
+ stages: [],
118
+ ...(typeof userInputValue === 'object' && userInputValue !== null
119
+ ? { input: userInputValue }
120
+ : {}),
121
+ ...(input.parentRunId ? { parent_run_id: input.parentRunId } : {}),
122
+ };
123
+ // Reset totals for this run
124
+ this.pipelineTotals = { tokens: 0, toolCalls: 0 };
125
+ const pipelineStartTime = Date.now();
126
+ // Create anonymization middleware for this run if requested via RunInput flag
127
+ const runAnonymize = input.anonymize === true;
128
+ const runMiddleware = runAnonymize ? new AnonymizationMiddleware() : null;
129
+ // Persist the run immediately so log_path can be written before terminal states
130
+ await this.config.db?.savePipelineRun(pipelineRun);
131
+ // Build per-run tool registry: clone the shared registry and inject studio-run
132
+ // with run-specific context (run ID, depth) if a spawner is configured.
133
+ // For script-only pipelines, toolRegistry may be undefined.
134
+ const runToolRegistry = this.config.spawner && this.config.toolRegistry
135
+ ? (() => {
136
+ const registry = this.config.toolRegistry.clone();
137
+ registry.registerPlugin('studio_run', createStudioRunTool({
138
+ spawner: this.config.spawner,
139
+ currentRunId: pipelineRun.id,
140
+ currentDepth: input.depth ?? 0,
141
+ maxDepth: this.config.maxDepth ?? 3,
142
+ }), STUDIO_RUN_PROMPT_SNIPPET);
143
+ return registry;
144
+ })()
145
+ : this.config.toolRegistry;
146
+ this.events?.onPipelineStart?.({
147
+ pipeline_name: pipeline.name,
148
+ run_id: pipelineRun.id,
149
+ });
150
+ this.emitter.emit({ type: 'pipeline_start', pipelineId: pipelineRun.id });
151
+ // 3. Initialize context
152
+ const pipelineContext = createInitialContext(userInputValue, this.config.repoPath);
153
+ // Run on_pipeline_start commands to bootstrap dynamic context
154
+ if (pipeline.on_pipeline_start?.length) {
155
+ const cwd = this.config.repoPath ?? this.config.configsDir;
156
+ pipelineContext.startupContext = await executeStartupCommands(pipeline.on_pipeline_start, cwd);
157
+ }
158
+ // Load .studio/invariants.md if present — injected into every agent's system_prompt
159
+ pipelineContext.invariantsContent = await loadInvariantsFile(projectPaths.projectDir);
160
+ // Pre-populate context from prior run if resuming
161
+ const skipSet = input.resumeFromStage
162
+ ? buildSkipSet(pipeline.stages, input.resumeFromStage)
163
+ : new Set();
164
+ if (input.resumeFromStage) {
165
+ for (const [stageName, output] of input.priorStageOutputs ?? []) {
166
+ addStageOutput(pipelineContext, stageName, output);
167
+ }
168
+ for (const [stageName, toolCalls] of input.priorStageToolResults ?? []) {
169
+ addStageToolResults(pipelineContext, stageName, toolCalls);
170
+ }
171
+ }
172
+ // 4. Execute stages sequentially (handling groups)
173
+ const totalStages = countTotalStages(pipeline.stages);
174
+ let stageCounter = 0;
175
+ let previousStageName;
176
+ for (const entry of pipeline.stages) {
177
+ // Check for cancellation before each pipeline entry
178
+ if (signal?.aborted) {
179
+ pipelineRun.status = 'cancelled';
180
+ pipelineRun.completed_at = new Date().toISOString();
181
+ const lastStage = pipelineRun.stages[pipelineRun.stages.length - 1];
182
+ this.events?.onPipelineCancelled?.({
183
+ run_id: pipelineRun.id,
184
+ cancelled_at_stage: lastStage?.stage_name ?? 'before_first_stage',
185
+ duration_ms: Date.now() - pipelineStartTime,
186
+ });
187
+ await this.config.db?.savePipelineRun(pipelineRun);
188
+ this.events?.onPipelineComplete?.({
189
+ pipeline_name: pipeline.name,
190
+ run_id: pipelineRun.id,
191
+ status: 'cancelled',
192
+ duration_ms: Date.now() - pipelineStartTime,
193
+ total_tokens: this.pipelineTotals.tokens,
194
+ total_tool_calls: this.pipelineTotals.toolCalls,
195
+ });
196
+ this.emitter.emit({ type: 'pipeline_complete', pipelineId: pipelineRun.id });
197
+ return pipelineRun;
198
+ }
199
+ if (isStageGroup(entry)) {
200
+ // ========== GROUP ==========
201
+ // Check if all group stages should be skipped
202
+ const allGroupStagesSkipped = entry.stages.every(s => skipSet.has(s.name));
203
+ if (allGroupStagesSkipped) {
204
+ const groupSkipReason = input.originalRunId
205
+ ? `resumed from run ${input.originalRunId}`
206
+ : 'resumed from prior run';
207
+ for (const stage of entry.stages) {
208
+ stageCounter++;
209
+ const skippedRun = makeSkippedStageRun(stage.name, groupSkipReason);
210
+ this.events?.onStageComplete?.({
211
+ stage_name: stage.name,
212
+ stage_index: stageCounter - 1,
213
+ total_stages: totalStages,
214
+ status: 'skipped',
215
+ attempts: 0,
216
+ duration_ms: 0,
217
+ skipped_reason: groupSkipReason,
218
+ });
219
+ pipelineRun.stages.push(skippedRun);
220
+ previousStageName = stage.name;
221
+ }
222
+ clearGroupFeedback(pipelineContext);
223
+ continue;
224
+ }
225
+ const groupResult = await this.groupOrchestrator.run(entry, pipelineContext, stageCounter, totalStages, userInputValue, projectPaths, runToolRegistry, runMiddleware, pipelineRun.id, signal, skipSet, input.originalRunId);
226
+ this.pipelineTotals.tokens += groupResult.totalTokensDelta;
227
+ this.pipelineTotals.toolCalls += groupResult.totalToolCallsDelta;
228
+ pipelineRun.stages.push(...groupResult.stageRuns);
229
+ stageCounter += groupResult.stagesExecuted;
230
+ // Update previousStageName to the last stage in the group
231
+ if (entry.stages.length > 0) {
232
+ previousStageName = entry.stages[entry.stages.length - 1].name;
233
+ }
234
+ // Clear group feedback after group completes
235
+ clearGroupFeedback(pipelineContext);
236
+ if (groupResult.status === 'rejected' || groupResult.status === 'failed' || groupResult.status === 'cancelled') {
237
+ pipelineRun.status = groupResult.status;
238
+ pipelineRun.completed_at = new Date().toISOString();
239
+ if (groupResult.status === 'cancelled') {
240
+ const lastStage = pipelineRun.stages[pipelineRun.stages.length - 1];
241
+ this.events?.onPipelineCancelled?.({
242
+ run_id: pipelineRun.id,
243
+ cancelled_at_stage: lastStage?.stage_name ?? 'unknown',
244
+ duration_ms: Date.now() - pipelineStartTime,
245
+ });
246
+ }
247
+ await this.config.db?.savePipelineRun(pipelineRun);
248
+ if (runMiddleware) {
249
+ await this.persistKeymap(pipelineRun.id, runMiddleware.getKeymap());
250
+ }
251
+ this.events?.onPipelineComplete?.({
252
+ pipeline_name: pipeline.name,
253
+ run_id: pipelineRun.id,
254
+ status: pipelineRun.status,
255
+ duration_ms: Date.now() - pipelineStartTime,
256
+ total_tokens: this.pipelineTotals.tokens,
257
+ total_tool_calls: this.pipelineTotals.toolCalls,
258
+ });
259
+ this.emitter.emit({ type: 'pipeline_complete', pipelineId: pipelineRun.id });
260
+ return pipelineRun;
261
+ }
262
+ }
263
+ else {
264
+ // ========== SIMPLE STAGE ==========
265
+ stageCounter++;
266
+ // Skip stage if resuming from a later stage
267
+ if (skipSet.has(entry.name)) {
268
+ const skippedReason = input.originalRunId
269
+ ? `resumed from run ${input.originalRunId}`
270
+ : 'resumed from prior run';
271
+ const skippedRun = makeSkippedStageRun(entry.name, skippedReason);
272
+ this.events?.onStageComplete?.({
273
+ stage_name: entry.name,
274
+ stage_index: stageCounter - 1,
275
+ total_stages: totalStages,
276
+ status: 'skipped',
277
+ attempts: 0,
278
+ duration_ms: 0,
279
+ skipped_reason: skippedReason,
280
+ });
281
+ pipelineRun.stages.push(skippedRun);
282
+ previousStageName = entry.name;
283
+ continue;
284
+ }
285
+ const result = await this.stageExecutor.execute(entry, pipelineContext, previousStageName, userInputValue, stageCounter - 1, totalStages, projectPaths, runToolRegistry, runMiddleware, pipelineRun.id, signal);
286
+ this.pipelineTotals.tokens += result.tokensDelta ?? 0;
287
+ this.pipelineTotals.toolCalls += result.toolCallsDelta ?? 0;
288
+ pipelineRun.stages.push(result.stageRun);
289
+ if (result.status === 'failed' || result.status === 'rejected' || result.status === 'cancelled') {
290
+ pipelineRun.status = result.stageRun.status;
291
+ pipelineRun.completed_at = new Date().toISOString();
292
+ if (result.status === 'cancelled') {
293
+ this.events?.onPipelineCancelled?.({
294
+ run_id: pipelineRun.id,
295
+ cancelled_at_stage: result.stageRun.stage_name,
296
+ duration_ms: Date.now() - pipelineStartTime,
297
+ });
298
+ }
299
+ await this.config.db?.savePipelineRun(pipelineRun);
300
+ if (runMiddleware) {
301
+ await this.persistKeymap(pipelineRun.id, runMiddleware.getKeymap());
302
+ }
303
+ this.events?.onPipelineComplete?.({
304
+ pipeline_name: pipeline.name,
305
+ run_id: pipelineRun.id,
306
+ status: pipelineRun.status,
307
+ duration_ms: Date.now() - pipelineStartTime,
308
+ total_tokens: this.pipelineTotals.tokens,
309
+ total_tool_calls: this.pipelineTotals.toolCalls,
310
+ });
311
+ this.emitter.emit({ type: 'pipeline_complete', pipelineId: pipelineRun.id });
312
+ return pipelineRun;
313
+ }
314
+ if (result.lastAgentOutput !== undefined) {
315
+ addStageOutput(pipelineContext, entry.name, result.lastAgentOutput);
316
+ }
317
+ if (result.toolCalls && result.toolCalls.length > 0) {
318
+ addStageToolResults(pipelineContext, entry.name, result.toolCalls);
319
+ }
320
+ previousStageName = entry.name;
321
+ }
322
+ }
323
+ // 5. All stages succeeded
324
+ pipelineRun.status = 'success';
325
+ pipelineRun.completed_at = new Date().toISOString();
326
+ // 6. Persist then emit (DB must be updated before SSE fires, so spawnAndWait GET sees final status)
327
+ await this.config.db?.savePipelineRun(pipelineRun);
328
+ if (runMiddleware) {
329
+ await this.persistKeymap(pipelineRun.id, runMiddleware.getKeymap());
330
+ }
331
+ this.events?.onPipelineComplete?.({
332
+ pipeline_name: pipeline.name,
333
+ run_id: pipelineRun.id,
334
+ status: pipelineRun.status,
335
+ duration_ms: Date.now() - pipelineStartTime,
336
+ total_tokens: this.pipelineTotals.tokens,
337
+ total_tool_calls: this.pipelineTotals.toolCalls,
338
+ });
339
+ this.emitter.emit({ type: 'pipeline_complete', pipelineId: pipelineRun.id });
340
+ return pipelineRun;
341
+ }
342
+ /** For external listeners via the generic event bus */
343
+ onEvent(listener) {
344
+ this.emitter.on(listener);
345
+ }
346
+ // -- Private --
347
+ async persistKeymap(runId, keymap) {
348
+ if (Object.keys(keymap).length === 0)
349
+ return;
350
+ try {
351
+ const { mkdir, writeFile } = await import('node:fs/promises');
352
+ const { join } = await import('node:path');
353
+ // configsDir is .studio/ directly — keymap goes in .studio/runs/anonymization/
354
+ const anonDir = join(this.config.configsDir, 'runs', 'anonymization');
355
+ await mkdir(anonDir, { recursive: true });
356
+ const keymapPath = join(anonDir, `${runId}.keymap.json`);
357
+ await writeFile(keymapPath, JSON.stringify(keymap, null, 2), 'utf-8');
358
+ }
359
+ catch {
360
+ // Non-fatal — keymap persistence is best-effort
361
+ }
362
+ }
363
+ }
364
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}