@tagma/sdk 0.7.3 → 0.7.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 (230) hide show
  1. package/README.md +85 -57
  2. package/dist/approval.d.ts +2 -12
  3. package/dist/approval.d.ts.map +1 -1
  4. package/dist/approval.js +1 -90
  5. package/dist/approval.js.map +1 -1
  6. package/dist/bootstrap.d.ts +1 -1
  7. package/dist/bootstrap.d.ts.map +1 -1
  8. package/dist/completions/file-exists.js +1 -1
  9. package/dist/completions/file-exists.js.map +1 -1
  10. package/dist/completions/output-check.d.ts.map +1 -1
  11. package/dist/completions/output-check.js +17 -4
  12. package/dist/completions/output-check.js.map +1 -1
  13. package/dist/config.d.ts +4 -4
  14. package/dist/config.d.ts.map +1 -1
  15. package/dist/config.js +2 -2
  16. package/dist/config.js.map +1 -1
  17. package/dist/dataflow.d.ts +3 -0
  18. package/dist/dataflow.d.ts.map +1 -0
  19. package/dist/dataflow.js +2 -0
  20. package/dist/dataflow.js.map +1 -0
  21. package/dist/drivers/opencode.d.ts.map +1 -1
  22. package/dist/drivers/opencode.js +23 -71
  23. package/dist/drivers/opencode.js.map +1 -1
  24. package/dist/engine.d.ts +5 -56
  25. package/dist/engine.d.ts.map +1 -1
  26. package/dist/engine.js +7 -297
  27. package/dist/engine.js.map +1 -1
  28. package/dist/index.d.ts +4 -6
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +2 -4
  31. package/dist/index.js.map +1 -1
  32. package/dist/logger.d.ts +2 -60
  33. package/dist/logger.d.ts.map +1 -1
  34. package/dist/logger.js +1 -153
  35. package/dist/logger.js.map +1 -1
  36. package/dist/middlewares/static-context.d.ts.map +1 -1
  37. package/dist/middlewares/static-context.js +1 -2
  38. package/dist/middlewares/static-context.js.map +1 -1
  39. package/dist/pipeline-runner.d.ts.map +1 -1
  40. package/dist/pipeline-runner.js +2 -2
  41. package/dist/pipeline-runner.js.map +1 -1
  42. package/dist/plugins.d.ts +2 -2
  43. package/dist/plugins.d.ts.map +1 -1
  44. package/dist/plugins.js +1 -1
  45. package/dist/plugins.js.map +1 -1
  46. package/dist/runner.d.ts +1 -35
  47. package/dist/runner.d.ts.map +1 -1
  48. package/dist/runner.js +1 -610
  49. package/dist/runner.js.map +1 -1
  50. package/dist/runtime/adapters/stdin-approval.d.ts +2 -0
  51. package/dist/runtime/adapters/stdin-approval.d.ts.map +1 -0
  52. package/dist/runtime/adapters/stdin-approval.js +2 -0
  53. package/dist/runtime/adapters/stdin-approval.js.map +1 -0
  54. package/dist/runtime/adapters/websocket-approval.d.ts +2 -0
  55. package/dist/runtime/adapters/websocket-approval.d.ts.map +1 -0
  56. package/dist/runtime/adapters/websocket-approval.js +2 -0
  57. package/dist/runtime/adapters/websocket-approval.js.map +1 -0
  58. package/dist/runtime/bun-process-runner.d.ts +2 -0
  59. package/dist/runtime/bun-process-runner.d.ts.map +1 -0
  60. package/dist/runtime/bun-process-runner.js +2 -0
  61. package/dist/runtime/bun-process-runner.js.map +1 -0
  62. package/dist/runtime.d.ts +2 -8
  63. package/dist/runtime.d.ts.map +1 -1
  64. package/dist/runtime.js +1 -7
  65. package/dist/runtime.js.map +1 -1
  66. package/dist/schema.d.ts.map +1 -1
  67. package/dist/schema.js +3 -4
  68. package/dist/schema.js.map +1 -1
  69. package/dist/tagma.d.ts +3 -4
  70. package/dist/tagma.d.ts.map +1 -1
  71. package/dist/tagma.js +2 -3
  72. package/dist/tagma.js.map +1 -1
  73. package/dist/triggers/file.d.ts.map +1 -1
  74. package/dist/triggers/file.js +74 -108
  75. package/dist/triggers/file.js.map +1 -1
  76. package/dist/triggers/manual.d.ts.map +1 -1
  77. package/dist/triggers/manual.js +1 -2
  78. package/dist/triggers/manual.js.map +1 -1
  79. package/dist/types.d.ts +1 -2
  80. package/dist/types.d.ts.map +1 -1
  81. package/dist/types.js +1 -12
  82. package/dist/types.js.map +1 -1
  83. package/dist/utils-api.d.ts +1 -1
  84. package/dist/utils-api.d.ts.map +1 -1
  85. package/dist/utils-api.js +1 -1
  86. package/dist/utils-api.js.map +1 -1
  87. package/dist/validate-raw.d.ts.map +1 -1
  88. package/dist/validate-raw.js +5 -12
  89. package/dist/validate-raw.js.map +1 -1
  90. package/package.json +20 -22
  91. package/dist/adapters/stdin-approval.d.ts +0 -6
  92. package/dist/adapters/stdin-approval.d.ts.map +0 -1
  93. package/dist/adapters/stdin-approval.js +0 -90
  94. package/dist/adapters/stdin-approval.js.map +0 -1
  95. package/dist/adapters/websocket-approval.d.ts +0 -28
  96. package/dist/adapters/websocket-approval.d.ts.map +0 -1
  97. package/dist/adapters/websocket-approval.js +0 -147
  98. package/dist/adapters/websocket-approval.js.map +0 -1
  99. package/dist/core/dataflow.d.ts +0 -23
  100. package/dist/core/dataflow.d.ts.map +0 -1
  101. package/dist/core/dataflow.js +0 -99
  102. package/dist/core/dataflow.js.map +0 -1
  103. package/dist/core/log-prune.d.ts +0 -16
  104. package/dist/core/log-prune.d.ts.map +0 -1
  105. package/dist/core/log-prune.js +0 -34
  106. package/dist/core/log-prune.js.map +0 -1
  107. package/dist/core/preflight.d.ts +0 -13
  108. package/dist/core/preflight.d.ts.map +0 -1
  109. package/dist/core/preflight.js +0 -61
  110. package/dist/core/preflight.js.map +0 -1
  111. package/dist/core/run-context.d.ts +0 -55
  112. package/dist/core/run-context.d.ts.map +0 -1
  113. package/dist/core/run-context.js +0 -158
  114. package/dist/core/run-context.js.map +0 -1
  115. package/dist/core/run-state.d.ts +0 -25
  116. package/dist/core/run-state.d.ts.map +0 -1
  117. package/dist/core/run-state.js +0 -93
  118. package/dist/core/run-state.js.map +0 -1
  119. package/dist/core/scheduler.d.ts +0 -13
  120. package/dist/core/scheduler.d.ts.map +0 -1
  121. package/dist/core/scheduler.js +0 -35
  122. package/dist/core/scheduler.js.map +0 -1
  123. package/dist/core/task-executor.d.ts +0 -13
  124. package/dist/core/task-executor.d.ts.map +0 -1
  125. package/dist/core/task-executor.js +0 -601
  126. package/dist/core/task-executor.js.map +0 -1
  127. package/dist/core/trigger-errors.d.ts +0 -9
  128. package/dist/core/trigger-errors.d.ts.map +0 -1
  129. package/dist/core/trigger-errors.js +0 -15
  130. package/dist/core/trigger-errors.js.map +0 -1
  131. package/dist/dag.d.ts +0 -45
  132. package/dist/dag.d.ts.map +0 -1
  133. package/dist/dag.js +0 -177
  134. package/dist/dag.js.map +0 -1
  135. package/dist/hooks.d.ts +0 -73
  136. package/dist/hooks.d.ts.map +0 -1
  137. package/dist/hooks.js +0 -106
  138. package/dist/hooks.js.map +0 -1
  139. package/dist/pipeline-definition.d.ts +0 -3
  140. package/dist/pipeline-definition.d.ts.map +0 -1
  141. package/dist/pipeline-definition.js +0 -4
  142. package/dist/pipeline-definition.js.map +0 -1
  143. package/dist/ports.d.ts +0 -196
  144. package/dist/ports.d.ts.map +0 -1
  145. package/dist/ports.js +0 -688
  146. package/dist/ports.js.map +0 -1
  147. package/dist/prompt-doc.d.ts +0 -70
  148. package/dist/prompt-doc.d.ts.map +0 -1
  149. package/dist/prompt-doc.js +0 -154
  150. package/dist/prompt-doc.js.map +0 -1
  151. package/dist/registry.d.ts +0 -67
  152. package/dist/registry.d.ts.map +0 -1
  153. package/dist/registry.js +0 -293
  154. package/dist/registry.js.map +0 -1
  155. package/dist/task-ref.d.ts +0 -55
  156. package/dist/task-ref.d.ts.map +0 -1
  157. package/dist/task-ref.js +0 -103
  158. package/dist/task-ref.js.map +0 -1
  159. package/dist/utils.d.ts +0 -13
  160. package/dist/utils.d.ts.map +0 -1
  161. package/dist/utils.js +0 -177
  162. package/dist/utils.js.map +0 -1
  163. package/src/adapters/stdin-approval.ts +0 -106
  164. package/src/adapters/websocket-approval.ts +0 -224
  165. package/src/approval.ts +0 -131
  166. package/src/bootstrap.ts +0 -55
  167. package/src/completions/exit-code.ts +0 -34
  168. package/src/completions/file-exists.ts +0 -66
  169. package/src/completions/output-check.test.ts +0 -50
  170. package/src/completions/output-check.ts +0 -92
  171. package/src/config-ops.test.ts +0 -70
  172. package/src/config-ops.ts +0 -328
  173. package/src/config.ts +0 -26
  174. package/src/core/dataflow.test.ts +0 -166
  175. package/src/core/dataflow.ts +0 -161
  176. package/src/core/log-prune.test.ts +0 -58
  177. package/src/core/log-prune.ts +0 -43
  178. package/src/core/preflight.test.ts +0 -49
  179. package/src/core/preflight.ts +0 -89
  180. package/src/core/run-context.test.ts +0 -256
  181. package/src/core/run-context.ts +0 -211
  182. package/src/core/run-state.test.ts +0 -98
  183. package/src/core/run-state.ts +0 -122
  184. package/src/core/scheduler.test.ts +0 -83
  185. package/src/core/scheduler.ts +0 -42
  186. package/src/core/task-executor.ts +0 -743
  187. package/src/core/trigger-errors.ts +0 -15
  188. package/src/dag.test.ts +0 -56
  189. package/src/dag.ts +0 -245
  190. package/src/drivers/opencode.ts +0 -410
  191. package/src/engine-ports-mixed.test.ts +0 -156
  192. package/src/engine-ports.test.ts +0 -166
  193. package/src/engine-task-type.test.ts +0 -56
  194. package/src/engine.ts +0 -458
  195. package/src/hooks.ts +0 -193
  196. package/src/index.ts +0 -33
  197. package/src/logger.ts +0 -182
  198. package/src/middlewares/static-context.ts +0 -49
  199. package/src/pipeline-definition.ts +0 -5
  200. package/src/pipeline-runner.test.ts +0 -91
  201. package/src/pipeline-runner.ts +0 -194
  202. package/src/plugin-registry.test.ts +0 -382
  203. package/src/plugins.ts +0 -21
  204. package/src/ports.test.ts +0 -678
  205. package/src/ports.ts +0 -925
  206. package/src/prompt-doc.test.ts +0 -174
  207. package/src/prompt-doc.ts +0 -169
  208. package/src/registry.ts +0 -353
  209. package/src/runner.test.ts +0 -142
  210. package/src/runner.ts +0 -666
  211. package/src/runtime.ts +0 -20
  212. package/src/schema-ports.test.ts +0 -172
  213. package/src/schema.test.ts +0 -213
  214. package/src/schema.ts +0 -379
  215. package/src/tagma.test.ts +0 -155
  216. package/src/tagma.ts +0 -62
  217. package/src/task-ref.test.ts +0 -401
  218. package/src/task-ref.ts +0 -121
  219. package/src/triggers/file.ts +0 -164
  220. package/src/triggers/manual.ts +0 -86
  221. package/src/types.ts +0 -18
  222. package/src/utils-api.ts +0 -8
  223. package/src/utils.test.ts +0 -28
  224. package/src/utils.ts +0 -203
  225. package/src/validate-raw-plugin-types.test.ts +0 -60
  226. package/src/validate-raw-ports.test.ts +0 -136
  227. package/src/validate-raw.ts +0 -852
  228. package/src/yaml-compiler.test.ts +0 -108
  229. package/src/yaml-compiler.ts +0 -110
  230. package/src/yaml.ts +0 -11
@@ -1,172 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import yaml from 'js-yaml';
3
- import type { PipelineConfig, RawPipelineConfig } from './types';
4
- import { deresolvePipeline, parseYaml, resolveConfig, serializePipeline } from './schema';
5
-
6
- const WORK_DIR = process.platform === 'win32' ? 'D:\\fake-work' : '/fake-work';
7
-
8
- describe('schema — unified bindings passthrough', () => {
9
- test('typed inputs and outputs survive onto the resolved task', () => {
10
- const raw: RawPipelineConfig = {
11
- name: 'p',
12
- tracks: [
13
- {
14
- id: 't',
15
- name: 'T',
16
- tasks: [
17
- {
18
- id: 'a',
19
- command: 'echo "{{inputs.city}}"',
20
- inputs: { city: { from: 't.plan.outputs.city', type: 'string', required: true } },
21
- outputs: { report: { from: 'json.reportPath', type: 'string' } },
22
- },
23
- ],
24
- },
25
- ],
26
- };
27
- const task = resolveConfig(raw, WORK_DIR).tracks[0]!.tasks[0]!;
28
- expect(task.inputs).toEqual(raw.tracks[0]!.tasks[0]!.inputs!);
29
- expect(task.outputs).toEqual(raw.tracks[0]!.tasks[0]!.outputs!);
30
- });
31
-
32
- test('typed inputs and outputs round-trip through deresolve', () => {
33
- const raw: RawPipelineConfig = {
34
- name: 'p',
35
- tracks: [
36
- {
37
- id: 't',
38
- name: 'T',
39
- tasks: [
40
- {
41
- id: 'a',
42
- command: 'echo "{{inputs.city}}"',
43
- inputs: {
44
- city: {
45
- from: 't.plan.outputs.city',
46
- type: 'enum',
47
- enum: ['Shanghai', 'Paris'],
48
- required: true,
49
- },
50
- },
51
- outputs: { raw: { from: 'stdout' } },
52
- },
53
- ],
54
- },
55
- ],
56
- };
57
- const back = deresolvePipeline(resolveConfig(raw, WORK_DIR), WORK_DIR);
58
- expect(back.tracks[0]!.tasks[0]!.inputs).toEqual(raw.tracks[0]!.tasks[0]!.inputs!);
59
- expect(back.tracks[0]!.tasks[0]!.outputs).toEqual(raw.tracks[0]!.tasks[0]!.outputs!);
60
- });
61
-
62
- test('empty binding maps are dropped on deresolve', () => {
63
- const resolved: PipelineConfig = {
64
- name: 'p',
65
- tracks: [
66
- {
67
- id: 't',
68
- name: 'T',
69
- tasks: [
70
- {
71
- id: 'a',
72
- name: 'a',
73
- prompt: 'hi',
74
- inputs: {},
75
- outputs: {},
76
- },
77
- ],
78
- },
79
- ],
80
- };
81
- const back = deresolvePipeline(resolved, WORK_DIR);
82
- expect(back.tracks[0]!.tasks[0]!.inputs).toBeUndefined();
83
- expect(back.tracks[0]!.tasks[0]!.outputs).toBeUndefined();
84
- });
85
-
86
- test('legacy ports are not carried through resolve or deresolve', () => {
87
- const raw: RawPipelineConfig = {
88
- name: 'p',
89
- tracks: [
90
- {
91
- id: 't',
92
- name: 'T',
93
- tasks: [
94
- {
95
- id: 'a',
96
- command: 'echo ok',
97
- ports: { outputs: [{ name: 'old', type: 'string' }] },
98
- },
99
- ],
100
- },
101
- ],
102
- };
103
- const resolved = resolveConfig(raw, WORK_DIR);
104
- expect(resolved.tracks[0]!.tasks[0]!.ports).toBeUndefined();
105
- const back = deresolvePipeline(resolved, WORK_DIR);
106
- expect(back.tracks[0]!.tasks[0]!.ports).toBeUndefined();
107
- });
108
-
109
- test('YAML round-trip preserves typed unified binding shape', () => {
110
- const raw: RawPipelineConfig = {
111
- name: 'p',
112
- tracks: [
113
- {
114
- id: 't',
115
- name: 'T',
116
- tasks: [
117
- {
118
- id: 'classify',
119
- prompt: 'pick a bucket',
120
- inputs: { doc: { type: 'string', required: true, description: 'Full text' } },
121
- outputs: {
122
- bucket: {
123
- type: 'enum',
124
- enum: ['spam', 'ham'],
125
- description: 'Classification',
126
- },
127
- },
128
- },
129
- ],
130
- },
131
- ],
132
- };
133
- const yamlText = serializePipeline(raw);
134
- const parsed = (yaml.load(yamlText) as { pipeline: RawPipelineConfig }).pipeline;
135
- expect(parsed.tracks[0]!.tasks[0]!.inputs).toEqual(raw.tracks[0]!.tasks[0]!.inputs!);
136
- expect(parsed.tracks[0]!.tasks[0]!.outputs).toEqual(raw.tracks[0]!.tasks[0]!.outputs!);
137
- });
138
-
139
- test('real-world YAML with typed bindings parses cleanly', () => {
140
- const text = `pipeline:
141
- name: demo
142
- tracks:
143
- - id: t
144
- name: Main
145
- tasks:
146
- - id: build
147
- command: bun run build
148
- outputs:
149
- bundlePath:
150
- from: json.bundlePath
151
- type: string
152
- - id: test
153
- depends_on: [build]
154
- command: 'bun test "{{inputs.bundlePath}}"'
155
- inputs:
156
- bundlePath:
157
- from: t.build.outputs.bundlePath
158
- type: string
159
- required: true
160
- `;
161
- const config = parseYaml(text);
162
- expect(config.tracks[0]!.tasks[0]!.outputs!.bundlePath).toEqual({
163
- from: 'json.bundlePath',
164
- type: 'string',
165
- });
166
- expect(config.tracks[0]!.tasks[1]!.inputs!.bundlePath).toEqual({
167
- from: 't.build.outputs.bundlePath',
168
- type: 'string',
169
- required: true,
170
- });
171
- });
172
- });
@@ -1,213 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import yaml from 'js-yaml';
3
- import type { PipelineConfig, RawPipelineConfig } from './types';
4
- import { deresolvePipeline, parseYaml, resolveConfig, serializePipeline } from './schema';
5
-
6
- function parsePipelineYaml(content: string): RawPipelineConfig {
7
- const doc = yaml.load(content) as { pipeline: RawPipelineConfig };
8
- return doc.pipeline;
9
- }
10
-
11
- describe('completion default serialization', () => {
12
- test('serializePipeline omits default exit_code completions from raw configs', () => {
13
- const raw: RawPipelineConfig = {
14
- name: 'Serialize Defaults',
15
- tracks: [
16
- {
17
- id: 'track_a',
18
- name: 'Track A',
19
- tasks: [
20
- { id: 'task_1', prompt: 'hello', completion: { type: 'exit_code' } },
21
- { id: 'task_2', prompt: 'world', completion: { type: 'exit_code', expect: 0 } },
22
- { id: 'task_3', prompt: 'keep me', completion: { type: 'exit_code', expect: 2 } },
23
- ],
24
- },
25
- ],
26
- };
27
-
28
- const parsed = parsePipelineYaml(serializePipeline(raw));
29
- expect(parsed.tracks[0].tasks[0].completion).toBeUndefined();
30
- expect(parsed.tracks[0].tasks[1].completion).toBeUndefined();
31
- expect(parsed.tracks[0].tasks[2].completion).toEqual({ type: 'exit_code', expect: 2 });
32
- });
33
-
34
- test('serializePipeline preserves non-default completion plugins', () => {
35
- const raw: RawPipelineConfig = {
36
- name: 'Serialize Explicit',
37
- tracks: [
38
- {
39
- id: 'track_a',
40
- name: 'Track A',
41
- tasks: [
42
- {
43
- id: 'task_1',
44
- prompt: 'check file',
45
- completion: { type: 'file_exists', path: './out.txt' },
46
- },
47
- ],
48
- },
49
- ],
50
- };
51
-
52
- const parsed = parsePipelineYaml(serializePipeline(raw));
53
- expect(parsed.tracks[0].tasks[0].completion).toEqual({
54
- type: 'file_exists',
55
- path: './out.txt',
56
- });
57
- });
58
-
59
- test('serializePipeline drops continue_from from command tasks (prompt-only field)', () => {
60
- const raw: RawPipelineConfig = {
61
- name: 'Strip Continue From',
62
- tracks: [
63
- {
64
- id: 'track_a',
65
- name: 'Track A',
66
- tasks: [
67
- { id: 'upstream', prompt: 'generate something' },
68
- // Simulates a task the user authored as `prompt` with a
69
- // continue_from, then toggled to `command` in the editor panel.
70
- // The field should not survive serialization.
71
- {
72
- id: 'downstream',
73
- command: 'bun run build',
74
- continue_from: 'upstream',
75
- depends_on: ['upstream'],
76
- },
77
- // A prompt task keeps its continue_from as-is.
78
- { id: 'threaded', prompt: 'refine', continue_from: 'upstream' },
79
- ],
80
- },
81
- ],
82
- };
83
-
84
- const parsed = parsePipelineYaml(serializePipeline(raw));
85
- expect(parsed.tracks[0].tasks[1].continue_from).toBeUndefined();
86
- expect(parsed.tracks[0].tasks[1].depends_on).toEqual(['upstream']);
87
- expect(parsed.tracks[0].tasks[2].continue_from).toBe('upstream');
88
- });
89
-
90
- test('deresolvePipeline also omits the default exit_code completion', () => {
91
- const resolved: PipelineConfig = {
92
- name: 'Deresolve Defaults',
93
- tracks: [
94
- {
95
- id: 'track_a',
96
- name: 'Track A',
97
- driver: 'opencode',
98
- permissions: { read: true, write: false, execute: false },
99
- on_failure: 'skip_downstream',
100
- cwd: 'D:/workspace',
101
- tasks: [
102
- {
103
- id: 'task_1',
104
- name: 'Task 1',
105
- prompt: 'hello',
106
- driver: 'opencode',
107
- permissions: { read: true, write: false, execute: false },
108
- cwd: 'D:/workspace',
109
- completion: { type: 'exit_code', expect: 0 },
110
- },
111
- {
112
- id: 'task_2',
113
- name: 'Task 2',
114
- prompt: 'custom',
115
- driver: 'opencode',
116
- permissions: { read: true, write: false, execute: false },
117
- cwd: 'D:/workspace',
118
- completion: { type: 'output_check', check: 'test -f ./done.txt' },
119
- },
120
- ],
121
- },
122
- ],
123
- };
124
-
125
- const raw = deresolvePipeline(resolved, 'D:/workspace');
126
- expect(raw.tracks[0].tasks[0].completion).toBeUndefined();
127
- expect(raw.tracks[0].tasks[1].completion).toEqual({
128
- type: 'output_check',
129
- check: 'test -f ./done.txt',
130
- });
131
- });
132
- });
133
-
134
- describe('parseYaml structural validation', () => {
135
- test('rejects non-array pipeline.tracks with a clear error', () => {
136
- expect(() =>
137
- parseYaml(`
138
- pipeline:
139
- name: Bad
140
- tracks:
141
- id: not-an-array
142
- `),
143
- ).toThrow(/pipeline\.tracks must be an array/);
144
- });
145
-
146
- test('rejects non-array track.tasks with a clear error', () => {
147
- expect(() =>
148
- parseYaml(`
149
- pipeline:
150
- name: Bad
151
- tracks:
152
- - id: t
153
- name: T
154
- tasks:
155
- id: not-an-array
156
- `),
157
- ).toThrow(/track "t": tasks must be an array/);
158
- });
159
- });
160
-
161
- describe('permissions inheritance', () => {
162
- test('resolveConfig applies pipeline-level permissions to tracks and tasks', () => {
163
- const raw: RawPipelineConfig = {
164
- name: 'Pipeline Permissions',
165
- permissions: { read: true, write: true, execute: false },
166
- tracks: [
167
- {
168
- id: 'track_a',
169
- name: 'Track A',
170
- tasks: [{ id: 'task_1', prompt: 'hello' }],
171
- },
172
- ],
173
- };
174
-
175
- const resolved = resolveConfig(raw, 'D:/workspace');
176
- expect(resolved.tracks[0].permissions).toEqual({ read: true, write: true, execute: false });
177
- expect(resolved.tracks[0].tasks[0].permissions).toEqual({
178
- read: true,
179
- write: true,
180
- execute: false,
181
- });
182
- });
183
-
184
- test('deresolvePipeline preserves pipeline-level permissions without repeating inherited values', () => {
185
- const resolved: PipelineConfig = {
186
- name: 'Deresolve Permissions',
187
- permissions: { read: true, write: true, execute: false },
188
- tracks: [
189
- {
190
- id: 'track_a',
191
- name: 'Track A',
192
- permissions: { read: true, write: true, execute: false },
193
- cwd: 'D:/workspace',
194
- tasks: [
195
- {
196
- id: 'task_1',
197
- name: 'Task 1',
198
- prompt: 'hello',
199
- permissions: { read: true, write: true, execute: false },
200
- cwd: 'D:/workspace',
201
- },
202
- ],
203
- },
204
- ],
205
- };
206
-
207
- const raw = deresolvePipeline(resolved, 'D:/workspace');
208
-
209
- expect(raw.permissions).toEqual({ read: true, write: true, execute: false });
210
- expect(raw.tracks[0].permissions).toBeUndefined();
211
- expect(raw.tracks[0].tasks[0].permissions).toBeUndefined();
212
- });
213
- });