workflow-ai 1.0.10 → 1.0.11

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.
@@ -1,440 +1,480 @@
1
- # =============================================================================
2
- # Pipeline Configuration — формат конфигурации пайплайна
3
- # =============================================================================
4
- # Описывает цепочку этапов (stages), доступных агентов, goto-логику переходов,
5
- # retry-стратегии и настройки выполнения.
6
- #
7
- # Runner читает этот файл и автономно оркестрирует работу:
8
- # node .workflow/src/runner.mjs --config .workflow/config/pipeline.yaml
9
- #
10
- # Переменные в goto.params:
11
- # $result.* — поля из результата текущего stage
12
- # $context.* — переменные из секции context (обновляются через params)
13
- # $counter.* — значения счётчиков (обновляются стейджами type: update-counter)
14
- # =============================================================================
15
-
16
- pipeline:
17
- name: "default"
18
- version: "1.0"
19
-
20
- # ===========================================================================
21
- # Агенты (agents)
22
- # ===========================================================================
23
- # Каждый агент — это CLI-инструмент, который runner вызывает через child_process.
24
- # Формат:
25
- # <agent-id>:
26
- # command: <string> — исполняемый файл (должен быть в PATH)
27
- # args: <string[]> — аргументы командной строки
28
- # workdir: <string> — рабочая директория (по умолчанию ".")
29
- # description: <string> — описание агента (опционально)
30
- #
31
- # Runner добавляет промпт последним аргументом автоматически.
32
- # ===========================================================================
33
- agents:
34
- claude-sonnet:
35
- command: "claude"
36
- args: ["--model", "claude-sonnet-4-6", "--permission-mode", "acceptEdits", "-p"]
37
- workdir: "."
38
- description: "Claude Sonnet — быстрая модель для простых задач"
39
-
40
- claude-opus:
41
- command: "claude"
42
- args: ["--model", "claude-opus-4-6", "--permission-mode", "acceptEdits", "-p"]
43
- workdir: "."
44
- description: "Claude Opus — мощная модель для сложных задач"
45
-
46
- qwen-code:
47
- command: "qwen"
48
- args: ["-y", "-p"]
49
- workdir: "."
50
- description: "Qwen Code — альтернативный агент для независимой проверки"
51
-
52
- kilo-code:
53
- command: "kilo"
54
- args: ["-m", "kilo/minimax/minimax-m2.5:free", "--agent", "orchestrator", "run"]
55
- workdir: "."
56
- description: "Агент с мульти-режимами (architect, code, debug)"
57
-
58
- kilo-glm:
59
- command: "kilo"
60
- args: ["-m", "zai-coding-plan/glm-4.7", "--agent", "orchestrator", "run"]
61
- workdir: "."
62
- description: "Kilo GLM"
63
-
64
- kilo-deepseek:
65
- command: "kilo"
66
- args: ["-m", "deepseek/deepseek-reasoner", "--agent", "code", "run"]
67
- workdir: "."
68
- description: "Kilo deepseek"
69
-
70
- script-move:
71
- command: "node"
72
- args: [".workflow/src/scripts/move-ticket.js"]
73
- workdir: "."
74
- description: "Скрипт для перемещения тикетов между директориями"
75
-
76
- script-pick:
77
- command: "node"
78
- args: [".workflow/src/scripts/pick-next-task.js"]
79
- workdir: "."
80
- description: "Скрипт для выбора следующего тикета из ready/"
81
-
82
- script-move-ready:
83
- command: "node"
84
- args: [".workflow/src/scripts/move-to-ready.js"]
85
- workdir: "."
86
- description: "Скрипт для перемещения тикетов из backlog/ в ready/"
87
-
88
- script-check-conditions:
89
- command: "node"
90
- args: [".workflow/src/scripts/check-conditions.js"]
91
- workdir: "."
92
- description: "Скрипт для проверки условий тикетов в backlog/"
93
-
94
- script-move-to-review:
95
- command: "node"
96
- args: [".workflow/src/scripts/move-to-review.js"]
97
- workdir: "."
98
- description: "Скрипт для перемещения завершённых тикетов из in-progress/ в review/"
99
-
100
-
101
- default_agent: qwen-code
102
-
103
- # ===========================================================================
104
- # Этапы (stages)
105
- # ===========================================================================
106
- # Каждый stage описывает один шаг пайплайна.
107
- # Формат:
108
- # <stage-id>:
109
- # description: <string> — что делает этот этап
110
- # agent: <agent-id> — какой агент выполняет (ссылка на agents.*)
111
- # skill: <skill-id> какой skill использовать (файл .workflow/src/skills/<skill>/SKILL.md)
112
- # goto: логика переходов по результату
113
- # <status>: ключ = статус результата агента
114
- # stage: <stage-id> следующий stage
115
- # params: <map> параметры, передаваемые в context следующего stage
116
- # default: fallback если статус не совпал ни с одним ключом
117
- #
118
- # Специальные значения stage:
119
- # "end" завершение пайплайна
120
- #
121
- # Встроенный тип стейджа (type: update-counter):
122
- # Инкрементирует счётчик без вызова агента.
123
- # type: update-counter встроенный обработчик runner'а
124
- # counter: <string> — имя счётчика
125
- # max: <int> при достижении max возвращает статус "max_reached"
126
- # goto:
127
- # default: <stage> — следующий стейдж (счётчик < max)
128
- # max_reached: <stage> стейдж при достижении max
129
- # ===========================================================================
130
- stages:
131
-
132
- # -------------------------------------------------------------------------
133
- # 0. pick-first-task
134
- # Выбирает следующую задачу из ready/ по приоритету и зависимостям
135
- # Если ready/ пуст — проверяет review/
136
- # -------------------------------------------------------------------------
137
- pick-first-task:
138
- description: "Выбрать задачу задачу из ready по приоритету"
139
- agent: script-pick
140
- goto:
141
- found:
142
- stage: move-to-in-progress
143
- params:
144
- ticket_id: "$result.ticket_id"
145
- target: in-progress
146
- in_review:
147
- stage: review-result
148
- params:
149
- ticket_id: "$result.ticket_id"
150
- attempt: "1"
151
- completed_in_progress:
152
- stage: move-to-review
153
- params:
154
- ticket_id: "$result.ticket_id"
155
- empty: check-conditions
156
- error: create-report
157
-
158
- # -------------------------------------------------------------------------
159
- # 1. check-conditions
160
- # Проверяет условия тикетов в backlog/, выводит список готовых
161
- # -------------------------------------------------------------------------
162
- check-conditions:
163
- description: "Проверить условия тикетов в backlog, вывести готовые"
164
- agent: script-check-conditions
165
- goto:
166
- has_ready:
167
- stage: move-to-ready
168
- params:
169
- ready_tickets: "$result.ready_tickets"
170
- default: pick-next-task
171
- empty: create-report
172
- error: create-report
173
-
174
- # -------------------------------------------------------------------------
175
- # 1b. move-to-ready
176
- # Перемещает тикеты из backlog/ в ready/ (по списку из check-conditions)
177
- # -------------------------------------------------------------------------
178
- move-to-ready:
179
- description: "Переместить готовые тикеты из backlog в ready"
180
- agent: script-move-ready
181
- timeout: 120
182
- goto:
183
- default: pick-next-task
184
-
185
- # -------------------------------------------------------------------------
186
- # 2. pick-next-task
187
- # Выбирает следующую задачу из ready/ по приоритету и зависимостям
188
- # Если ready/ пуст проверяет review/
189
- # -------------------------------------------------------------------------
190
- pick-next-task:
191
- description: "Выбрать следующую задачу из ready по приоритету"
192
- agent: script-pick
193
- goto:
194
- found:
195
- stage: move-to-in-progress
196
- params:
197
- ticket_id: "$result.ticket_id"
198
- target: in-progress
199
- in_review:
200
- stage: review-result
201
- params:
202
- ticket_id: "$result.ticket_id"
203
- attempt: "1"
204
- completed_in_progress:
205
- stage: move-to-review
206
- params:
207
- ticket_id: "$result.ticket_id"
208
- empty: check-conditions
209
- error: create-report
210
-
211
- # -------------------------------------------------------------------------
212
- # 2b. move-to-in-progress
213
- # Перемещает тикет из ready/ в in-progress/ перед выполнением
214
- # -------------------------------------------------------------------------
215
- move-to-in-progress:
216
- description: "Переместить тикет из ready в in-progress"
217
- agent: script-move
218
- timeout: 120
219
- goto:
220
- default:
221
- stage: execute-task
222
- params:
223
- ticket_id: "$context.ticket_id"
224
- error:
225
- stage: execute-task
226
- params:
227
- ticket_id: "$context.ticket_id"
228
-
229
-
230
- # -------------------------------------------------------------------------
231
- # 3. execute-task
232
- # Выполняет выбранную задачу (код, документация, план и т.д.)
233
- # -------------------------------------------------------------------------
234
- execute-task:
235
- description: "Выполнить выбранную задачу"
236
- agent: qwen-code
237
- fallback_agent: kilo-deepseek
238
- skill: execute-task
239
- counter: task_attempts
240
- agent_by_attempt:
241
- 1: qwen-code
242
- 2: claude-sonnet
243
- 3: claude-opus
244
- 4: kilo-deepseek
245
- goto:
246
- default:
247
- stage: move-to-review
248
- params:
249
- ticket_id: "$context.ticket_id"
250
- attempt: "$counter.task_attempts"
251
- target: review
252
- error:
253
- stage: move-to-review
254
- params:
255
- ticket_id: "$context.ticket_id"
256
- attempt: "$counter.task_attempts"
257
- target: review
258
-
259
- # -------------------------------------------------------------------------
260
- # 3b. move-to-review
261
- # Перемещает тикет в review/ после выполнения задачи
262
- # -------------------------------------------------------------------------
263
- move-to-review:
264
- description: "Переместить тикет в review после выполнения"
265
- agent: script-move-to-review
266
- timeout: 120
267
- goto:
268
- skipped:
269
- stage: pick-next-task
270
- default:
271
- stage: review-result
272
- params:
273
- ticket_id: "$context.ticket_id"
274
- attempt: "$counter.task_attempts"
275
-
276
- # -------------------------------------------------------------------------
277
- # 4. review-result
278
- # Проверяет результат выполнения на соответствие DoD тикета.
279
- # Использует независимый агент (qwen-code) для объективной оценки.
280
- # При failed — переходит на increment-task-attempts для учёта попытки.
281
- # -------------------------------------------------------------------------
282
- review-result:
283
- description: "Проверить результат выполнения на соответствие DoD тикета"
284
- agent: claude-sonnet
285
- fallback_agent: qwen-code
286
- skill: review-result
287
- counter: task_attempts
288
- goto:
289
- passed:
290
- stage: move-ticket
291
- params:
292
- ticket_id: "$context.ticket_id"
293
- target: done
294
- failed:
295
- stage: increment-task-attempts
296
- params:
297
- ticket_id: "$context.ticket_id"
298
- default:
299
- stage: move-ticket
300
- params:
301
- ticket_id: "$context.ticket_id"
302
- target: blocked
303
-
304
- # -------------------------------------------------------------------------
305
- # 4b. increment-task-attempts
306
- # Отдельный стейдж обновления счётчика попыток выполнения тикета.
307
- # При достижении max — блокирует тикет. Иначе — возвращает в очередь.
308
- # -------------------------------------------------------------------------
309
- increment-task-attempts:
310
- description: "Обновить счётчик попыток выполнения тикета"
311
- type: update-counter
312
- counter: task_attempts
313
- max: 6
314
- goto:
315
- default:
316
- stage: move-ticket
317
- params:
318
- ticket_id: "$context.ticket_id"
319
- target: ready
320
- max_reached:
321
- stage: move-ticket
322
- params:
323
- ticket_id: "$context.ticket_id"
324
- target: blocked
325
-
326
- # -------------------------------------------------------------------------
327
- # 5. move-ticket
328
- # Перемещает тикет в целевую директорию (done/ или blocked/)
329
- # -------------------------------------------------------------------------
330
- move-ticket:
331
- description: "Переместить тикет (done / blocked)"
332
- agent: script-move
333
- timeout: 120
334
- goto:
335
- default: pick-next-task
336
-
337
- # -------------------------------------------------------------------------
338
- # 6. create-report
339
- # Создаёт итоговый отчёт по выполненным задачам текущего цикла
340
- # -------------------------------------------------------------------------
341
- create-report:
342
- description: "Создать итоговый отчёт по выполненным задачам"
343
- agent: claude-sonnet
344
- fallback_agent: qwen-code
345
- skill: create-report
346
- goto:
347
- default:
348
- stage: analyze-report
349
- params:
350
- report_id: "$result.report_id"
351
-
352
- # -------------------------------------------------------------------------
353
- # 7. analyze-report
354
- # Анализирует отчёт: план выполнен полностью или есть пробелы?
355
- # При has_gaps — переходит на increment-plan-iterations для учёта итерации.
356
- # -------------------------------------------------------------------------
357
- analyze-report:
358
- description: "Проанализировать отчёт: план выполнен полностью?"
359
- agent: claude-opus
360
- fallback_agent: qwen-code
361
- skill: analyze-report
362
- goto:
363
- completed: end
364
- has_gaps:
365
- stage: increment-plan-iterations
366
- params:
367
- gaps: "$result.gaps"
368
- report_id: "$context.report_id"
369
-
370
- # -------------------------------------------------------------------------
371
- # 7b. increment-plan-iterations
372
- # Отдельный стейдж обновления счётчика итераций анализа плана.
373
- # При достижении max — завершает пайплайн. Иначе — декомпозирует пробелы.
374
- # -------------------------------------------------------------------------
375
- increment-plan-iterations:
376
- description: "Обновить счётчик итераций анализа плана"
377
- type: update-counter
378
- counter: plan_iterations
379
- max: 2
380
- goto:
381
- default:
382
- stage: decompose-gaps
383
- max_reached: end
384
-
385
- # -------------------------------------------------------------------------
386
- # 8. decompose-gaps
387
- # Декомпозирует недочёты из анализа отчёта в новые тикеты (backlog/)
388
- # -------------------------------------------------------------------------
389
- decompose-gaps:
390
- description: "Декомпозировать недочёты из отчёта в новые тикеты"
391
- agent: claude-sonnet
392
- fallback_agent: qwen-code
393
- skill: decompose-gaps
394
- goto:
395
- default: check-conditions
396
-
397
- # ===========================================================================
398
- # Точка входа (entry)
399
- # ===========================================================================
400
- # Stage, с которого начинается выполнение пайплайна.
401
- # ===========================================================================
402
- entry: pick-first-task
403
-
404
- # ===========================================================================
405
- # Контекст (context)
406
- # ===========================================================================
407
- # Переменные, доступные всем stages через $context.*.
408
- # Runner автоматически обновляет context через params в goto-переходах.
409
- # Начальные значения задаются здесь или через CLI:
410
- # node runner.mjs --plan PLAN-003
411
- # ===========================================================================
412
- context:
413
- plan_id: "" # ID плана (задаётся при запуске)
414
-
415
- # ===========================================================================
416
- # Защита файлов (protected_files)
417
- # ===========================================================================
418
- # Glob-паттерны файлов, в которые агентам запрещена запись.
419
- # Runner проверяет эти паттерны и блокирует изменения.
420
- # Пути указываются относительно корня проекта (без префикса .workflow/)
421
- # ===========================================================================
422
- protected_files:
423
- - ".workflow/plans/**" # Планы — только для чтения
424
- - ".workflow/config/**" # Конфигурация
425
-
426
- # ===========================================================================
427
- # Настройки выполнения (execution)
428
- # ===========================================================================
429
- # Параметры, управляющие поведением runner'а.
430
- #
431
- # max_steps: абсолютный лимит шагов за один запуск (защита от зацикливания)
432
- # delay_between_stages: пауза между этапами в секундах
433
- # timeout_per_stage: таймаут на один этап в секундах (по истечении — ошибка)
434
- # log_file: — путь к файлу логов (относительно корня проекта)
435
- # ===========================================================================
436
- execution:
437
- max_steps: 100
438
- delay_between_stages: 5
439
- timeout_per_stage: 1800
440
- log_file: ".workflow/logs/pipeline.log"
1
+ # =============================================================================
2
+ # Pipeline Configuration — формат конфигурации пайплайна
3
+ # =============================================================================
4
+ # Описывает цепочку этапов (stages), доступных агентов, goto-логику переходов,
5
+ # retry-стратегии и настройки выполнения.
6
+ #
7
+ # Runner читает этот файл и автономно оркестрирует работу:
8
+ # node .workflow/src/runner.mjs --config .workflow/config/pipeline.yaml
9
+ #
10
+ # Переменные в goto.params:
11
+ # $result.* — поля из результата текущего stage
12
+ # $context.* — переменные из секции context (обновляются через params)
13
+ # $counter.* — значения счётчиков (обновляются стейджами type: update-counter)
14
+ # =============================================================================
15
+
16
+ pipeline:
17
+ name: "default"
18
+ version: "1.0"
19
+
20
+ # ===========================================================================
21
+ # Агенты (agents)
22
+ # ===========================================================================
23
+ # Каждый агент — это CLI-инструмент, который runner вызывает через child_process.
24
+ # Формат:
25
+ # <agent-id>:
26
+ # command: <string> — исполняемый файл (должен быть в PATH)
27
+ # args: <string[]> — аргументы командной строки
28
+ # workdir: <string> — рабочая директория (по умолчанию ".")
29
+ # description: <string> — описание агента (опционально)
30
+ #
31
+ # Runner добавляет промпт последним аргументом автоматически.
32
+ # ===========================================================================
33
+ agents:
34
+ claude-sonnet:
35
+ command: "claude"
36
+ args: ["--model", "claude-sonnet-4-6", "--permission-mode", "acceptEdits", "-p"]
37
+ workdir: "."
38
+ description: "Claude Sonnet — быстрая модель для простых задач"
39
+
40
+ claude-opus:
41
+ command: "claude"
42
+ args: ["--model", "claude-opus-4-6", "--permission-mode", "acceptEdits", "-p"]
43
+ workdir: "."
44
+ description: "Claude Opus — мощная модель для сложных задач"
45
+
46
+ qwen-code:
47
+ command: "qwen"
48
+ args: ["-y", "-p"]
49
+ workdir: "."
50
+ description: "Qwen Code — альтернативный агент для независимой проверки"
51
+
52
+ kilo-code:
53
+ command: "kilo"
54
+ args: ["-m", "kilo/minimax/minimax-m2.5:free", "--agent", "orchestrator", "run"]
55
+ workdir: "."
56
+ description: "Агент с мульти-режимами (architect, code, debug)"
57
+
58
+ kilo-glm:
59
+ command: "kilo"
60
+ args: ["-m", "zai-coding-plan/glm-4.7", "--agent", "orchestrator", "run"]
61
+ workdir: "."
62
+ description: "Kilo GLM"
63
+
64
+ kilo-deepseek:
65
+ command: "kilo"
66
+ args: ["-m", "deepseek/deepseek-reasoner", "--agent", "code", "run"]
67
+ workdir: "."
68
+ description: "Kilo deepseek"
69
+
70
+ script-move:
71
+ command: "node"
72
+ args: [".workflow/src/scripts/move-ticket.js"]
73
+ workdir: "."
74
+ description: "Скрипт для перемещения тикетов между директориями"
75
+
76
+ script-pick:
77
+ command: "node"
78
+ args: [".workflow/src/scripts/pick-next-task.js"]
79
+ workdir: "."
80
+ description: "Скрипт для выбора следующего тикета из ready/"
81
+
82
+ script-move-ready:
83
+ command: "node"
84
+ args: [".workflow/src/scripts/move-to-ready.js"]
85
+ workdir: "."
86
+ description: "Скрипт для перемещения тикетов из backlog/ в ready/"
87
+
88
+ script-check-conditions:
89
+ command: "node"
90
+ args: [".workflow/src/scripts/check-conditions.js"]
91
+ workdir: "."
92
+ description: "Скрипт для проверки условий тикетов в backlog/"
93
+
94
+ script-move-to-review:
95
+ command: "node"
96
+ args: [".workflow/src/scripts/move-to-review.js"]
97
+ workdir: "."
98
+ description: "Скрипт для перемещения завершённых тикетов из in-progress/ в review/"
99
+
100
+
101
+ default_agent: qwen-code
102
+
103
+ # ===========================================================================
104
+ # Этапы (stages)
105
+ # ===========================================================================
106
+ # Каждый stage описывает один шаг пайплайна.
107
+ # Формат:
108
+ # <stage-id>:
109
+ # description: <string> — что делает этот этап
110
+ # agent: <agent-id> — какой агент выполняет (ссылка на agents.*)
111
+ # fallback_agent: <agent-id> запасной агент, если основной недоступен
112
+ # skill: <skill-id> какой skill использовать (.workflow/src/skills/<skill>/SKILL.md)
113
+ # instructions: <string> доп. инструкции, передаваемые агенту в промпте
114
+ # counter: <string> имя счётчика попыток для этого stage
115
+ # agent_by_type: маршрутизация агента по типу задачи (task_type)
116
+ # <type>: <agent-id> например: impl: claude-sonnet, arch: claude-opus
117
+ # agent_by_attempt: — ротация агента по номеру попытки
118
+ # <N>: <agent-id> — например: 1: qwen-code, 2: claude-sonnet
119
+ # goto: логика переходов по результату
120
+ # <status>: — ключ = статус результата агента
121
+ # stage: <stage-id> — следующий stage
122
+ # params: <map> — параметры, передаваемые в context следующего stage
123
+ # default: fallback если статус не совпал ни с одним ключом
124
+ #
125
+ # Приоритет выбора агента: agent_by_attempt > agent_by_type > agent > default_agent
126
+ #
127
+ # Специальные значения stage:
128
+ # "end"завершение пайплайна
129
+ #
130
+ # Встроенный тип стейджа (type: update-counter):
131
+ # Инкрементирует счётчик без вызова агента.
132
+ # type: update-counter — встроенный обработчик runner'а
133
+ # counter: <string> — имя счётчика
134
+ # max: <int> — при достижении max возвращает статус "max_reached"
135
+ # goto:
136
+ # default: <stage> — следующий стейдж (счётчик < max)
137
+ # max_reached: <stage> — стейдж при достижении max
138
+ # ===========================================================================
139
+ stages:
140
+
141
+ # -------------------------------------------------------------------------
142
+ # 0. pick-first-task
143
+ # Выбирает следующую задачу из ready/ по приоритету и зависимостям
144
+ # Если ready/ пуст — проверяет review/
145
+ # -------------------------------------------------------------------------
146
+ pick-first-task:
147
+ description: "Выбрать задачу задачу из ready по приоритету"
148
+ agent: script-pick
149
+ goto:
150
+ found:
151
+ stage: move-to-in-progress
152
+ params:
153
+ ticket_id: "$result.ticket_id"
154
+ target: in-progress
155
+ in_review:
156
+ stage: review-result
157
+ params:
158
+ ticket_id: "$result.ticket_id"
159
+ attempt: "1"
160
+ completed_in_progress:
161
+ stage: move-to-review
162
+ params:
163
+ ticket_id: "$result.ticket_id"
164
+ empty: check-conditions
165
+ error: create-report
166
+
167
+ # -------------------------------------------------------------------------
168
+ # 1. check-conditions
169
+ # Проверяет условия тикетов в backlog/, выводит список готовых
170
+ # -------------------------------------------------------------------------
171
+ check-conditions:
172
+ description: "Проверить условия тикетов в backlog, вывести готовые"
173
+ agent: script-check-conditions
174
+ goto:
175
+ has_ready:
176
+ stage: move-to-ready
177
+ params:
178
+ ready_tickets: "$result.ready_tickets"
179
+ default: pick-next-task
180
+ empty: create-report
181
+ error: create-report
182
+
183
+ # -------------------------------------------------------------------------
184
+ # 1b. move-to-ready
185
+ # Перемещает тикеты из backlog/ в ready/ (по списку из check-conditions)
186
+ # -------------------------------------------------------------------------
187
+ move-to-ready:
188
+ description: "Переместить готовые тикеты из backlog в ready"
189
+ agent: script-move-ready
190
+ timeout: 120
191
+ goto:
192
+ default: pick-next-task
193
+
194
+ # -------------------------------------------------------------------------
195
+ # 2. pick-next-task
196
+ # Выбирает следующую задачу из ready/ по приоритету и зависимостям
197
+ # Если ready/ пуст — проверяет review/
198
+ # -------------------------------------------------------------------------
199
+ pick-next-task:
200
+ description: "Выбрать следующую задачу из ready по приоритету"
201
+ agent: script-pick
202
+ goto:
203
+ found:
204
+ stage: move-to-in-progress
205
+ params:
206
+ ticket_id: "$result.ticket_id"
207
+ target: in-progress
208
+ in_review:
209
+ stage: review-result
210
+ params:
211
+ ticket_id: "$result.ticket_id"
212
+ attempt: "1"
213
+ completed_in_progress:
214
+ stage: move-to-review
215
+ params:
216
+ ticket_id: "$result.ticket_id"
217
+ empty: check-conditions
218
+ error: create-report
219
+
220
+ # -------------------------------------------------------------------------
221
+ # 2b. move-to-in-progress
222
+ # Перемещает тикет из ready/ в in-progress/ перед выполнением
223
+ # -------------------------------------------------------------------------
224
+ move-to-in-progress:
225
+ description: "Переместить тикет из ready в in-progress"
226
+ agent: script-move
227
+ timeout: 120
228
+ goto:
229
+ default:
230
+ stage: check-relevance
231
+ params:
232
+ ticket_id: "$context.ticket_id"
233
+ error:
234
+ stage: check-relevance
235
+ params:
236
+ ticket_id: "$context.ticket_id"
237
+
238
+ # -------------------------------------------------------------------------
239
+ # 2c. check-relevance
240
+ # Проверяет актуальность тикета перед выполнением (план активен, DoD не выполнен)
241
+ # Fail-safe: default fallback → execute-task (лучше выполнить лишний, чем пропустить)
242
+ # -------------------------------------------------------------------------
243
+ check-relevance:
244
+ description: "Проверить актуальность тикета перед выполнением"
245
+ agent: qwen-code
246
+ fallback_agent: claude-sonnet
247
+ skill: check-relevance
248
+ goto:
249
+ relevant:
250
+ stage: execute-task
251
+ params:
252
+ ticket_id: "$context.ticket_id"
253
+ irrelevant:
254
+ stage: move-ticket
255
+ params:
256
+ ticket_id: "$context.ticket_id"
257
+ target: done
258
+ default:
259
+ stage: execute-task
260
+ params:
261
+ ticket_id: "$context.ticket_id"
262
+
263
+ # -------------------------------------------------------------------------
264
+ # 3. execute-task
265
+ # Выполняет выбранную задачу (код, документация, план и т.д.)
266
+ # -------------------------------------------------------------------------
267
+ execute-task:
268
+ description: "Выполнить выбранную задачу"
269
+ agent: qwen-code
270
+ fallback_agent: kilo-deepseek
271
+ skill: execute-task
272
+ counter: task_attempts
273
+ agent_by_type:
274
+ impl: claude-sonnet
275
+ fix: claude-sonnet
276
+ arch: claude-opus
277
+ review: qwen-code
278
+ docs: qwen-code
279
+ plan: claude-opus
280
+ agent_by_attempt:
281
+ 1: qwen-code
282
+ 2: claude-sonnet
283
+ 3: claude-opus
284
+ 4: kilo-deepseek
285
+ goto:
286
+ default:
287
+ stage: move-to-review
288
+ params:
289
+ ticket_id: "$context.ticket_id"
290
+ attempt: "$counter.task_attempts"
291
+ target: review
292
+ error:
293
+ stage: move-to-review
294
+ params:
295
+ ticket_id: "$context.ticket_id"
296
+ attempt: "$counter.task_attempts"
297
+ target: review
298
+
299
+ # -------------------------------------------------------------------------
300
+ # 3b. move-to-review
301
+ # Перемещает тикет в review/ после выполнения задачи
302
+ # -------------------------------------------------------------------------
303
+ move-to-review:
304
+ description: "Переместить тикет в review после выполнения"
305
+ agent: script-move-to-review
306
+ timeout: 120
307
+ goto:
308
+ skipped:
309
+ stage: pick-next-task
310
+ default:
311
+ stage: review-result
312
+ params:
313
+ ticket_id: "$context.ticket_id"
314
+ attempt: "$counter.task_attempts"
315
+
316
+ # -------------------------------------------------------------------------
317
+ # 4. review-result
318
+ # Проверяет результат выполнения на соответствие DoD тикета.
319
+ # Использует независимый агент (qwen-code) для объективной оценки.
320
+ # При failed — переходит на increment-task-attempts для учёта попытки.
321
+ # -------------------------------------------------------------------------
322
+ review-result:
323
+ description: "Проверить результат выполнения на соответствие DoD тикета"
324
+ agent: claude-sonnet
325
+ fallback_agent: qwen-code
326
+ skill: review-result
327
+ counter: task_attempts
328
+ goto:
329
+ passed:
330
+ stage: move-ticket
331
+ params:
332
+ ticket_id: "$context.ticket_id"
333
+ target: done
334
+ failed:
335
+ stage: increment-task-attempts
336
+ params:
337
+ ticket_id: "$context.ticket_id"
338
+ default:
339
+ stage: move-ticket
340
+ params:
341
+ ticket_id: "$context.ticket_id"
342
+ target: blocked
343
+
344
+ # -------------------------------------------------------------------------
345
+ # 4b. increment-task-attempts
346
+ # Отдельный стейдж обновления счётчика попыток выполнения тикета.
347
+ # При достижении max — блокирует тикет. Иначе — возвращает в очередь.
348
+ # -------------------------------------------------------------------------
349
+ increment-task-attempts:
350
+ description: "Обновить счётчик попыток выполнения тикета"
351
+ type: update-counter
352
+ counter: task_attempts
353
+ max: 6
354
+ goto:
355
+ default:
356
+ stage: move-ticket
357
+ params:
358
+ ticket_id: "$context.ticket_id"
359
+ target: ready
360
+ max_reached:
361
+ stage: move-ticket
362
+ params:
363
+ ticket_id: "$context.ticket_id"
364
+ target: blocked
365
+
366
+ # -------------------------------------------------------------------------
367
+ # 5. move-ticket
368
+ # Перемещает тикет в целевую директорию (done/ или blocked/)
369
+ # -------------------------------------------------------------------------
370
+ move-ticket:
371
+ description: "Переместить тикет (done / blocked)"
372
+ agent: script-move
373
+ timeout: 120
374
+ goto:
375
+ default: pick-next-task
376
+
377
+ # -------------------------------------------------------------------------
378
+ # 6. create-report
379
+ # Создаёт итоговый отчёт по выполненным задачам текущего цикла
380
+ # -------------------------------------------------------------------------
381
+ create-report:
382
+ description: "Создать итоговый отчёт по выполненным задачам"
383
+ agent: claude-sonnet
384
+ fallback_agent: qwen-code
385
+ skill: create-report
386
+ goto:
387
+ default:
388
+ stage: analyze-report
389
+ params:
390
+ report_id: "$result.report_id"
391
+
392
+ # -------------------------------------------------------------------------
393
+ # 7. analyze-report
394
+ # Анализирует отчёт: план выполнен полностью или есть пробелы?
395
+ # При has_gaps — переходит на increment-plan-iterations для учёта итерации.
396
+ # -------------------------------------------------------------------------
397
+ analyze-report:
398
+ description: "Проанализировать отчёт: план выполнен полностью?"
399
+ agent: claude-opus
400
+ fallback_agent: qwen-code
401
+ skill: analyze-report
402
+ goto:
403
+ completed: end
404
+ has_gaps:
405
+ stage: increment-plan-iterations
406
+ params:
407
+ gaps: "$result.gaps"
408
+ report_id: "$context.report_id"
409
+
410
+ # -------------------------------------------------------------------------
411
+ # 7b. increment-plan-iterations
412
+ # Отдельный стейдж обновления счётчика итераций анализа плана.
413
+ # При достижении max завершает пайплайн. Иначе — декомпозирует пробелы.
414
+ # -------------------------------------------------------------------------
415
+ increment-plan-iterations:
416
+ description: "Обновить счётчик итераций анализа плана"
417
+ type: update-counter
418
+ counter: plan_iterations
419
+ max: 2
420
+ goto:
421
+ default:
422
+ stage: decompose-gaps
423
+ max_reached: end
424
+
425
+ # -------------------------------------------------------------------------
426
+ # 8. decompose-gaps
427
+ # Декомпозирует недочёты из анализа отчёта в новые тикеты (backlog/)
428
+ # -------------------------------------------------------------------------
429
+ decompose-gaps:
430
+ description: "Декомпозировать недочёты из отчёта в новые тикеты"
431
+ agent: claude-sonnet
432
+ fallback_agent: qwen-code
433
+ skill: decompose-gaps
434
+ goto:
435
+ default: check-conditions
436
+
437
+ # ===========================================================================
438
+ # Точка входа (entry)
439
+ # ===========================================================================
440
+ # Stage, с которого начинается выполнение пайплайна.
441
+ # ===========================================================================
442
+ entry: pick-first-task
443
+
444
+ # ===========================================================================
445
+ # Контекст (context)
446
+ # ===========================================================================
447
+ # Переменные, доступные всем stages через $context.*.
448
+ # Runner автоматически обновляет context через params в goto-переходах.
449
+ # Начальные значения задаются здесь или через CLI:
450
+ # node runner.mjs --plan PLAN-003
451
+ # ===========================================================================
452
+ context:
453
+ plan_id: "" # ID плана (задаётся при запуске)
454
+
455
+ # ===========================================================================
456
+ # Защита файлов (protected_files)
457
+ # ===========================================================================
458
+ # Glob-паттерны файлов, в которые агентам запрещена запись.
459
+ # Runner проверяет эти паттерны и блокирует изменения.
460
+ # Пути указываются относительно корня проекта (без префикса .workflow/)
461
+ # ===========================================================================
462
+ protected_files:
463
+ - ".workflow/plans/**" # Планы — только для чтения
464
+ - ".workflow/config/**" # Конфигурация
465
+
466
+ # ===========================================================================
467
+ # Настройки выполнения (execution)
468
+ # ===========================================================================
469
+ # Параметры, управляющие поведением runner'а.
470
+ #
471
+ # max_steps: — абсолютный лимит шагов за один запуск (защита от зацикливания)
472
+ # delay_between_stages: — пауза между этапами в секундах
473
+ # timeout_per_stage: — таймаут на один этап в секундах (по истечении — ошибка)
474
+ # log_file: — путь к файлу логов (относительно корня проекта)
475
+ # ===========================================================================
476
+ execution:
477
+ max_steps: 100
478
+ delay_between_stages: 5
479
+ timeout_per_stage: 1800
480
+ log_file: ".workflow/logs/pipeline.log"