workflow-ai 1.2.1 → 1.3.1

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.
package/README.md CHANGED
@@ -1,475 +1,64 @@
1
- # workflow-ai
2
-
3
- Координатор воркфлоу для AI-агентов конвейер на основе канбан-доски для AI-агентов, пишущих код.
4
-
5
- Система координации AI-агентов через файловую канбан-доску. Автоматически оркестрирует выполнение задач: берёт тикеты из очереди, запускает нужного агента, проверяет результат и генерирует отчёты.
6
-
7
- ## Установка
8
-
9
- ```bash
10
- npm install -g workflow-ai
11
- ```
12
-
13
- ## Быстрый старт
14
-
15
- ```bash
16
- # 1. Инициализировать воркфлоу в вашем проекте
17
- workflow init
18
- ```
19
-
20
- ```text
21
- # 2. Открыть проект в AI-агенте (Claude Code, Kilo, и т.д.) и попросить создать план через скил:
22
- Создай план <описание задачи> используя скил .workflow/src/skills/create-plan/SKILL.md
23
- ```
24
-
25
- ```bash
26
- # 3. Запустить конвейер — он декомпозирует план на тикеты и начнёт исполнение
27
- workflow run
28
- ```
29
-
30
- ## Команды
31
-
32
- | Команда | Описание |
33
- |---------|----------|
34
- | `workflow init [path] [--force]` | Инициализировать директорию `.workflow/` со структурой канбан-доски |
35
- | `workflow run [options]` | Запустить AI-конвейер |
36
- | `workflow update [path]` | Обновить глобальную директорию и пересоздать junctions |
37
- | `workflow eject <skill> [path]` | Извлечь скил (скопировать из глобальной директории в проект) |
38
- | `workflow eject-scripts [path]` | Извлечь скрипты (скопировать из глобальной директории в проект) |
39
- | `workflow eject-configs [path]` | Извлечь конфиги (скопировать из глобальной директории в проект) |
40
- | `workflow list [path]` | Вывести список скилов со статусом (shared/ejected/project-only) |
41
- | `workflow help` | Показать справку |
42
- | `workflow version` | Показать версию |
43
-
44
- ### Опции команды `run`
45
-
46
- | Опция | Описание |
47
- |-------|----------|
48
- | `--plan <plan>` | ID плана для выполнения |
49
- | `--config <path>` | Путь к конфиг-файлу |
50
- | `--project <path>` | Корень проекта (по умолчанию: автоопределение) |
51
-
52
- ## Инициализация
53
-
54
- Команда `workflow init` создаёт структуру директории `.workflow/`:
55
-
56
- ```
57
- .workflow/
58
- ├── config/ # → junction на ~/.workflow/configs/ (eject для кастомизации)
59
- ├── plans/
60
- │ ├── current/ # Текущие планы разработки
61
- │ ├── templates/ # Шаблоны планов с триггерами (повторяющиеся планы)
62
- │ └── archive/ # Архивные планы
63
- ├── tickets/
64
- │ ├── backlog/ # Ожидают условий
65
- │ ├── ready/ # Готовы к выполнению
66
- │ ├── in-progress/ # В работе
67
- │ ├── blocked/ # Заблокированы зависимостями
68
- │ ├── review/ # Ожидают ревью
69
- │ └── done/ # Завершены
70
- ├── reports/ # Сгенерированные отчёты
71
- ├── logs/ # Логи выполнения конвейера
72
- ├── metrics/ # Метрики производительности
73
- ├── templates/ # Шаблоны тикетов/планов/отчётов
74
- └── src/
75
- ├── skills/ # Инструкции скилов (junctions на глобальные, по каждому скилу)
76
- └── scripts/ # Скрипты автоматизации (junction на глобальные)
77
- ```
78
-
79
- ## Конвейер
80
-
81
- Команда `workflow run` исполняет многоэтапный конвейер:
82
-
83
- 1. **pick-first-task** — выбрать тикет из очереди ready
84
- 2. **check-plan-templates** — проверить триггеры шаблонов планов, создать планы при срабатывании
85
- 3. **check-plan-decomposition** — проверить состояние декомпозиции/активации планов
86
- 4. **allocate-ticket-ids** — выделить стартовые ID для префиксов до декомпозиции
87
- 5. **decompose-plan** — разбить план на тикеты (при необходимости)
88
- 6. **check-atomicity-limit / verify-atomicity / increment-atomicity-counter** — проверить атомарность тикетов плана
89
- 7. **check-conditions** — проверить условия готовности тикета
90
- 8. **move-to-ready** — переместить тикеты из backlog в ready
91
- 9. **pick-next-task** — выбрать следующий тикет для выполнения
92
- 10. **move-to-in-progress** — начать выполнение
93
- 11. **check-relevance** — проверить, что тикет всё ещё актуален (на скриптах, без LLM)
94
- 12. **check-mcp** — проверить доступность MCP-зависимостей тикета
95
- 13. **execute-task** — выполнить работу через AI-агента
96
- 14. **move-to-review** — отправить на ревью
97
- 15. **verify-artifacts** — детерминированная проверка артефактов тикета
98
- 16. **review-result** — проверить результаты по Definition of Done
99
- 17. **increment-task-attempts** — учесть попытки повторов
100
- 18. **move-ticket** — переместить в done/blocked по результатам ревью
101
- 19. **create-report** — сгенерировать отчёт о выполнении
102
- 20. **analyze-report / decompose-gaps** — проанализировать результаты и итерировать
103
- 21. **complete-plan / increment-plan-iterations** — закрыть план или запустить следующую итерацию
104
-
105
- ### Типы стадий
106
-
107
- #### `update-counter`
108
- Встроенная стадия, инкрементирует счётчик и возвращает статус для перехода. Требует `counter` и опционально `max`. Возвращает `default` или `max_reached`.
109
-
110
- #### `manual-gate`
111
- Встроенная стадия для ручного одобрения. Создаёт файл `.workflow/approvals/{step_id}.json` со статусом `pending` и ждёт решения через polling (интервал по умолчанию 2000мс).
112
-
113
- **Параметры:**
114
- - `poll_interval_ms` — интервал опроса (опц., default 2000)
115
- - `timeout_seconds` — таймаут в секундах (опц., default без таймаута)
116
-
117
- **Требуемые goto:**
118
- - `approved` — обязательный, переход при одобрении
119
- - `rejected` — обязательный, переход при отклонении
120
-
121
- **Опциональные goto:**
122
- - `timeout` — при истечении таймаута
123
- - `aborted` — при остановке runner'а (SIGTERM)
124
-
125
- **Формат step_id:** `{ticket_id}_{stageId}_{attempt}` (например, `QA-12_manual-approve_0`)
126
-
127
- **Approval-файл содержит:**
128
- ```json
129
- {
130
- "step_id": "QA-12_manual-approve_0",
131
- "ticket_id": "QA-12",
132
- "stage_id": "manual-approve",
133
- "attempt": 0,
134
- "status": "pending",
135
- "created_at": "2026-04-28T12:34:56.789Z",
136
- "updated_at": "2026-04-28T12:34:56.789Z",
137
- "decided_by": null,
138
- "comment": null,
139
- "context_snapshot": { ... }
140
- }
141
- ```
142
-
143
- **Два способа одобрения:**
144
- 1. **Через MCP-клиент** (например `workflow-mcp`): tool `approve_step({step_id, decision, comment})` пишет в файл approval
145
- 2. **Прямая правка файла:** открыть `.workflow/approvals/{step_id}.json`, изменить `"status": "pending"` на `"approved"` или `"rejected"`, сохранить
146
-
147
- **Важное:** `manual-gate` — **opt-in**. Если ваш pipeline не использует стадии `manual-gate`, поведение полностью идентично предыдущим версиям! Никаких breaking changes.
148
-
149
- **Пример:**
150
- ```yaml
151
- stages:
152
- manual-approve-deploy:
153
- type: manual-gate
154
- poll_interval_ms: 2000
155
- timeout_seconds: 86400
156
- goto:
157
- approved: continue-deploy
158
- rejected: rollback
159
- timeout: notify-stuck
160
- aborted: end
161
- ```
162
-
163
- Агенты настраиваются в `configs/pipeline.yaml`.
164
-
165
- ## Скилы
166
-
167
- Встроенные скилы для разных типов задач:
168
-
169
- | Скил | Описание |
170
- |------|----------|
171
- | `analyze-report` | Анализ отчёта |
172
- | `coach` | Управление и улучшение скилов |
173
- | `create-plan` | Создание плана |
174
- | `create-report` | Генерация отчёта |
175
- | `decompose-gaps` | Декомпозиция пробелов |
176
- | `decompose-plan` | Декомпозиция плана на тикеты |
177
- | `deep-research` | Глубокий ресерч |
178
- | `execute-task` | Выполнение задачи |
179
- | `manual-testing` | UI-observability: ручное тестирование сценариев |
180
- | `review-result` | Ревью результата по DoD |
181
-
182
- Скилы хранятся глобально в `~/.workflow/skills/` и подключаются в проекты через junctions.
183
-
184
- Используйте `workflow eject <skill>` для копирования скила в проект для кастомизации.
185
-
186
- ### Как работать с коучем
187
-
188
- Коуч — мета-скил для создания и улучшения остальных скилов. Правки в `.workflow/src/skills/` делаются **только** через него.
189
-
190
- ```text
191
- # Запрос к AI-агенту:
192
- Загрузи коуча из .workflow/src/skills/coach/SKILL.md и <действие>
193
- ```
194
-
195
- Варианты `<действия>`:
196
-
197
- | Тип задачи | Пример запроса |
198
- |------------|----------------|
199
- | Создать новый скил | `создай скил <имя> для <назначение>` |
200
- | Аудит существующего | `сделай аудит скила <имя>` |
201
- | Анализ эффективности | `проанализируй результаты скила <имя> по завершённым тикетам` |
202
- | Точечное улучшение | `улучши скил <имя>: <что именно>` |
203
- | Ресерч практик | `найди лучшие практики для <тема> и обогати скил <имя>` |
204
- | Ревью скила | `сделай ревью скила <имя>` |
205
-
206
- Коуч сам определит тип задачи, загрузит нужный воркфлоу, внесёт правку, прогонит тест скила и запишет результат в `.workflow/coach-backlog.yaml`. Коммит делает пользователь.
207
-
208
- ## Регрессионные тесты скилов
209
-
210
- Трёхуровневая система тестирования скилов для проверки качества AI-агентов.
211
-
212
- ### Три слоя тестирования
213
-
214
- | Уровень | Название | Описание |
215
- |---------|----------|----------|
216
- | L0 | Static | Базовая проверка синтаксиса и структуры: YAML-валидация, проверка обязательных полей, линтер |
217
- | L1 | Deterministic | Детерминированные тесты: эталонные входные данные → ожидаемый результат (strict match) |
218
- | L2 | Rubric | Гибкая оценка по критериям: scorer выставляет баллы на основе качества результата |
219
-
220
- ### Структура директорий
221
-
222
- ```
223
- src/skills/<name>/tests/
224
- ├── index.yaml # Метаданные тестов, список test cases
225
- ├── cases/ # Входные данные для тестов
226
- │ └── <case-id>/
227
- │ └── input.yaml
228
- ├── fixtures/ # Ожидаемые выходные данные (для L1)
229
- │ └── <case-id>/
230
- │ └── expected.yaml
231
- └── rubrics/ # Критерии оценки (для L2)
232
- └── <case-id>/
233
- └── rubric.yaml
234
- ```
235
-
236
- ### Запуск тестов
237
-
238
- ```bash
239
- npm run test:skills
240
- ```
241
-
242
- ### CLI-флаги
243
-
244
- | Флаг | Описание |
245
- |------|----------|
246
- | `--skill <name>` | Запустить тесты только для указанного скила |
247
- | `--relevant` | Запустить только тесты, соответствующие изменённым файлам |
248
- | `--establish-baseline` | Запустить тесты и сохранить результаты как baseline |
249
- | `--baseline-ref <ref>` | Использовать конкретный baseline (коммит, тег) |
250
- | `--yes` | Автоматически подтверждать все действия |
251
-
252
- ### Режимы вердикта
253
-
254
- | Режим | Описание |
255
- |-------|----------|
256
- | `no-baseline` | Первый запуск — результаты сохраняются как baseline без сравнения |
257
- | `no-regression` | Сравнение с baseline — тест считается пройденным, если результат не хуже baseline |
258
-
259
- ### Принцип git write
260
-
261
- Runner и коуч **не выполняют git write-операций**. Все изменения в кодовой базе делает исключительно пользователь. Runner только анализирует и рекомендует, но не коммитит.
262
-
263
- ### Первый запуск на новом проекте
264
-
265
- 1. Запустить тесты с флагом `--establish-baseline`
266
- 2. Проверить результаты: красные тесты — ожидаемы для нового проекта
267
- 3. Зафиксировать baseline: `git commit current/` как baseline-коммит
268
-
269
- ## Скрипты
270
-
271
- Скрипты хранятся глобально в `~/.workflow/scripts/` и подключаются одним junction в `.workflow/src/scripts/`.
272
-
273
- Используйте `workflow eject-scripts` для копирования скриптов в проект для кастомизации.
274
-
275
- ## Конфиги
276
-
277
- Конфиги хранятся глобально в `~/.workflow/configs/` и подключаются одним junction в `.workflow/config/`.
278
-
279
- Используйте `workflow eject-configs` для копирования конфигов в проект для кастомизации.
280
-
281
- ## Шаблоны планов
282
-
283
- Шаблоны планов позволяют автоматически создавать повторяющиеся планы. Шаблоны лежат в `.workflow/plans/templates/` и содержат условия триггеров во frontmatter.
284
-
285
- ### Формат шаблона
286
-
287
- ```yaml
288
- id: "TMPL-001"
289
- title: "Daily manual testing"
290
- type: template
291
- trigger:
292
- type: daily # daily | weekly | date_after | interval_days
293
- params: {} # параметры, зависящие от типа
294
- last_triggered: "" # обновляется автоматически при срабатывании
295
- enabled: true
296
- ```
297
-
298
- ### Типы триггеров
299
-
300
- | Тип | Параметры | Описание |
301
- |-----|-----------|----------|
302
- | `daily` | — | Раз в день |
303
- | `weekly` | `days_of_week: [1,3,5]` (0=вс) | В указанные дни недели |
304
- | `date_after` | `date: "2026-04-01"` | Один раз после указанной даты |
305
- | `interval_days` | `days: 3` | Каждые N дней |
306
-
307
- При срабатывании триггера конвейер создаёт план в `plans/current/` со статусом `approved`, далее идёт обычный поток декомпозиции.
308
-
309
- ## Типы задач
310
-
311
- | Тип | Префикс | Описание |
312
- |-----|---------|----------|
313
- | `arch` | ARCH | Архитектура и планирование |
314
- | `impl` | IMPL | Реализация кода |
315
- | `fix` | FIX | Исправления ошибок |
316
- | `review` | REVIEW | Ревью кода/документации |
317
- | `docs` | DOCS | Документация |
318
- | `admin` | ADMIN | Административные задачи |
319
-
320
- ## Fallback агентов и правила здоровья
321
-
322
- Система включает механизм in-stage fallback и health-мониторинг агентов.
323
-
324
- ### Механика fallback
325
-
326
- Когда агент падает во время выполнения задачи, система использует **artifact-snapshot** для принятия решения:
327
- - Если snapshot пустой (нет записанных файлов) → выполняется fallback на следующего агента
328
- - Если snapshot непустой (есть изменения) → задача переходит в состояние `goto.error`
329
-
330
- **Пример сценария:** Qwen превысил quota и упал без записи файлов → Kilo вызван в той же попытке, task_attempts не инкрементирован.
331
-
332
- Конфигурация snapshot:
333
- ```yaml
334
- execution:
335
- artifact_snapshot_enabled: false # по умолчанию выключено
336
- snapshot_paths: ["src/", "configs/"] # что мониторить
337
- snapshot_max_file_size: 524288 # файлы >512KB — только mtime+size
338
- ```
339
-
340
- **Baseline производительности:** `p50=169ms p95=299ms files=598` (из QA-20 benchmark).
341
-
342
- ### Классификатор ошибок и health-реестр
343
-
344
- Ошибки классифицируются по классам:
345
- - `unavailable` — агент временно недоступен (quota, rate limit)
346
- - `transient` — временная ошибка сети (timeout, 5xx)
347
- - `misconfigured` — ошибка конфигурации (401, 403, отсутствует API key)
348
- - `unmatched` — ошибка не распознана
349
-
350
- **Семантика TTL:**
351
- - `5m` — 5 минут
352
- - `1h` — 1 час
353
- - `until_utc_midnight` — до полуночи UTC (минимум 30 минут)
354
- - `infinite` — навсегда
355
-
356
- Файл конфигурации: `configs/agent-health-rules.yaml`. Файл состояния: `.workflow/state/agent-health.json`.
357
-
358
- ### Команда сброса
359
-
360
- ```bash
361
- # показать текущее состояние
362
- node .workflow/src/scripts/reset-agent-health.js
363
-
364
- # сбросить конкретного агента
365
- node .workflow/src/scripts/reset-agent-health.js --agent qwen-code
366
-
367
- # сбросить всех агентов
368
- node .workflow/src/scripts/reset-agent-health.js --all
369
- ```
370
-
371
- ### Пример добавления правила
372
-
373
- ```yaml
374
- # В configs/agent-health-rules.yaml:
375
- agents:
376
- my-new-agent:
377
- rules:
378
- - id: "my-agent-quota"
379
- class: "unavailable"
380
- ttl: "until_utc_midnight"
381
- pattern: "quota exceeded|daily limit reached"
382
- exit_codes: "any"
383
- ```
384
-
385
- ## Конфигурация
386
-
387
- ### `configs/config.yaml`
388
-
389
- Основная конфигурация воркфлоу: информация о проекте, типы задач, приоритеты, статусы, типы условий, пути, настройки отчётности.
390
-
391
- ### `configs/pipeline.yaml`
392
-
393
- Определение конвейера: агенты, стадии, управление потоком, goto-логика, стратегии повторов.
394
-
395
- #### `manual-gate` stage
396
-
397
- `type: manual-gate` — встроенный тип стадии для ручного одобрения. Создаёт файл `.workflow/approvals/{step_id}.json` со статусом `pending` и ждёт решения через polling.
398
-
399
- **Поля:**
400
- - `type: manual-gate` — обязательное, идентификатор типа стадии
401
- - `poll_interval_ms` — опциональное, интервал опроса в мс (default: 2000, минимум: 100)
402
- - `timeout_seconds` — опциональное, таймаут в секундах (default: null — без таймаута)
403
- - `goto.approved` — обязательное, следующая стадия при одобрении
404
- - `goto.rejected` — обязательное, следующая стадия при отклонении
405
- - `goto.timeout` — опциональное, следующая стадия при истечении таймаута
406
- - `goto.aborted` — опциональное, следующая стадия при остановке runner'а (SIGTERM)
407
-
408
- **Пример:**
409
- ```yaml
410
- stages:
411
- manual-approve-deploy:
412
- type: manual-gate
413
- poll_interval_ms: 2000
414
- timeout_seconds: 86400
415
- goto:
416
- approved: continue-deploy
417
- rejected: rollback
418
- timeout: notify-stuck
419
- aborted: end
420
- ```
421
-
422
- **Два способа одобрения:**
423
- 1. **Через MCP-клиент** (например `workflow-mcp`): tool `approve_step({step_id, decision, comment})` пишет в файл approval. Опционально — пользователю не обязал подключать MCP.
424
- 2. **Прямая правка файла:** открыть `.workflow/approvals/{step_id}.json`, изменить `"status": "pending"` на `"approved"` или `"rejected"`, сохранить. **Базовый способ, работающий без какой-либо внешней инфраструктуры** — достаточно текстового редактора.
425
-
426
- **Важное:** `manual-gate` — **opt-in**. Если ваш pipeline не использует стадии `manual-gate`, поведение полностью идентично предыдущим версиям! Никаких breaking changes.
427
-
428
- **Формат approval-файла:**
429
- ```json
430
- {
431
- "step_id": "QA-12_manual-approve_0",
432
- "ticket_id": "QA-12",
433
- "stage_id": "manual-approve",
434
- "attempt": 0,
435
- "status": "pending",
436
- "created_at": "2026-04-28T12:34:56.789Z",
437
- "updated_at": "2026-04-28T12:34:56.789Z",
438
- "decided_by": null,
439
- "comment": null,
440
- "context_snapshot": { ... }
441
- }
442
- ```
443
-
444
- ### `configs/ticket-movement-rules.yaml`
445
-
446
- Правила автоматического перемещения тикетов на основе статуса ревью.
447
-
448
- ## Структура проекта
449
-
450
- ```
451
- workflow-ai/
452
- ├── bin/ # Точка входа CLI
453
- ├── src/
454
- │ ├── cli.mjs # Парсинг команд
455
- │ ├── runner.mjs # Оркестратор конвейера
456
- │ ├── init.mjs # Инициализация проекта
457
- │ ├── global-dir.mjs # Управление глобальной ~/.workflow/
458
- │ ├── junction-manager.mjs # Управление junction/symlink
459
- │ ├── wf-loader.mjs # Загрузчик конфигов
460
- │ ├── lib/ # Библиотеки утилит
461
- │ └── tests/ # Набор тестов
462
- ├── configs/ # Файлы конфигурации (источник)
463
- ├── templates/ # Шаблоны воркфлоу (источник)
464
- ├── agent-templates/ # Шаблоны инструкций для AI-агентов
465
- └── package.json
466
- ```
467
-
468
- ## Требования
469
-
470
- - Node.js >= 18.0.0
471
- - npm
472
-
473
- ## Лицензия
474
-
475
- MIT
1
+
2
+ - Добавлено упоминание `human-gate` в разделе про runner-стадии (пример конфига в pipeline.yaml: human-review-step типа manual-gate).
3
+ - Добавлено упоминание `mark-blocked` как механизм нотификации autoblocked-тикетов (поля auto_blocked_reason/attempts/at).
4
+
5
+ ## Синглтон семантика Pipeline
6
+
7
+ Система workflow реализует паттерн синглтона для выполнения пайплайна: одновременно разрешена только одна активная инстанция пайплайна для каждого проекта.
8
+
9
+ ### Семантика Синглтона
10
+ При попытке запустить второй пайплайн, когда первый уже работает, система вернёт ошибку `PIPELINE_ALREADY_RUNNING`.
11
+
12
+ ### Структура `.workflow/logs/.pipeline.lock`
13
+ Файл блокировки содержит следующие поля:
14
+ - `pid`: ID процесса работающего пайплайна
15
+ - `started_at`: Временная метка запуска пайплайна
16
+ - `started_by`: Инициатор запуска пайплайна (cli | mcp | extension)
17
+ - `run_id`: Уникальный идентификатор этого запуска
18
+ - `pipeline_log`: Путь к файлу логов пайплайна
19
+ - `project_root`: Корневая директория проекта
20
+ - `pipeline_version`: Версия выполняемого пайплайна
21
+
22
+ ### Команды
23
+ - `workflow run --project <path> [--started-by cli|mcp|extension] [--force]` - Запустить пайплайн для указанного проекта
24
+ - `workflow stop --project <path> [--grace-sec N]` - Мягко остановить пайплайн (SIGTERM → SIGKILL после N секунд)
25
+ - `--force` флаг - Обход блокировки (только для отладки, когда процесс зависает)
26
+
27
+ ### Восстановление
28
+ Если файл блокировки устарел (процесс упал, но блокировка не удалена):
29
+ 1. Проверь, что процесс мёртв: `workflow stop --project <path>` (автоматически детектит устаревшие блокировки)
30
+ 2. Если стандартная остановка не решает проблему: `workflow run --force --project <path>`
31
+
32
+ ## Runner-стадии
33
+
34
+ В системе поддерживаются различные типы стадий для управления процессами разработки:
35
+
36
+ ### Human Gate
37
+
38
+ `human-gate` стадия ручного контроля, которая требует вмешательства человека для продолжения выполнения пайплайна. Используется для критических точек, где необходима ручная проверка или утверждение.
39
+
40
+ **Условия срабатывания:**
41
+ - Стадия `manual-gate-human` блокирует пайплайн до ручного снятия gate
42
+ - Gate снимается через команду `move-ticket.js <id> unblock`
43
+ - Поддерживает настройку таймаутов и условий повторных попыток
44
+
45
+ **Пример конфигурации pipeline.yaml:**
46
+ ```yaml
47
+ stages:
48
+ - name: manual-gate-human
49
+ type: manual-gate-human
50
+ config:
51
+ timeout: 3600 # 1 hour
52
+ max_attempts: 3
53
+ message: "Requires human approval before deployment"
54
+ ```
55
+
56
+ Пример полного файла `pipeline.yaml` доступен в `docs/samples/pipeline-with-human-gate.yaml`.
57
+
58
+ ### Autoblock notifications
59
+
60
+ Для автоматического блокировки тикетов при возникновении проблем используется механизм `mark-blocked`. Блокированные тикеты получают дополнительные поля в frontmatter для отслеживания причин и попыток:
61
+
62
+ - `auto_blocked_reason` причина автоматической блокировки
63
+ - `auto_blocked_attempts` — количество попыток разблокировки
64
+ - `auto_blocked_at` время автоматической блокировки
@@ -185,6 +185,18 @@ pipeline:
185
185
  workdir: "."
186
186
  description: "Проверка доступности MCP-серверов"
187
187
 
188
+ script-mark-blocked:
189
+ command: "node"
190
+ args: [".workflow/src/scripts/mark-blocked.js"]
191
+ workdir: "."
192
+ description: "Обновление frontmatter и запись в alerts.jsonl при автоблокировке"
193
+
194
+ script-mark-human-rejected:
195
+ command: "node"
196
+ args: [".workflow/src/scripts/mark-blocked.js"]
197
+ workdir: "."
198
+ description: "Обновление frontmatter при отклонении human-тикета"
199
+
188
200
  script-verify-artifacts:
189
201
  command: "node"
190
202
  args: [".workflow/src/skills/review-result/scripts/verify-artifacts.js"]
@@ -274,6 +286,10 @@ pipeline:
274
286
  task_type: "$result.type"
275
287
  required_capabilities: "$result.required_capabilities"
276
288
  target: in-progress
289
+ human_ready:
290
+ stage: manual-gate-human
291
+ params:
292
+ ticket_id: "$result.ticket_id"
277
293
  in_review:
278
294
  stage: verify-artifacts
279
295
  params:
@@ -487,6 +503,10 @@ pipeline:
487
503
  task_type: "$result.type"
488
504
  required_capabilities: "$result.required_capabilities"
489
505
  target: in-progress
506
+ human_ready:
507
+ stage: manual-gate-human
508
+ params:
509
+ ticket_id: "$result.ticket_id"
490
510
  in_review:
491
511
  stage: verify-artifacts
492
512
  params:
@@ -649,6 +669,73 @@ pipeline:
649
669
  ticket_id: "$context.ticket_id"
650
670
  attempt: "$counter.task_attempts"
651
671
 
672
+ # -------------------------------------------------------------------------
673
+ # 2d. manual-gate-human
674
+ # Используется для созревших human-тикетов (pick-first-task возвращает human_ready).
675
+ # Ждёт решения по approval-файлу (approved/rejected/timeout).
676
+ # -------------------------------------------------------------------------
677
+ manual-gate-human:
678
+ description: "Ожидание ручного выполнения созревшего human-тикета"
679
+ type: manual-gate
680
+ poll_interval_ms: 2000
681
+ timeout_seconds: 86400
682
+ goto:
683
+ approved: pick-first-task
684
+ rejected:
685
+ stage: mark-human-rejected
686
+ params:
687
+ ticket_id: "$context.ticket_id"
688
+ timeout:
689
+ stage: mark-human-rejected
690
+ params:
691
+ ticket_id: "$context.ticket_id"
692
+ reason: "human_gate_timeout"
693
+ aborted: end
694
+
695
+ # -------------------------------------------------------------------------
696
+ # 3b. mark-blocked
697
+ # Записывает причину автоблокировки в frontmatter тикета и эмитит alert
698
+ # в alerts.jsonl. Вставлен между increment-task-attempts.max_reached и
699
+ # move-ticket(blocked).
700
+ # -------------------------------------------------------------------------
701
+ mark-blocked:
702
+ description: "Записать причину автоблокировки в frontmatter и эмитить alert"
703
+ agent: script-mark-blocked
704
+ timeout: 30
705
+ goto:
706
+ default:
707
+ stage: move-ticket
708
+ params:
709
+ ticket_id: "$context.ticket_id"
710
+ target: blocked
711
+ error:
712
+ stage: move-ticket
713
+ params:
714
+ ticket_id: "$context.ticket_id"
715
+ target: blocked
716
+
717
+ # -------------------------------------------------------------------------
718
+ # 3b'. mark-human-rejected
719
+ # Записывает причину отклонения human-тикета (reject/timeout) и переходит
720
+ # в move-ticket(blocked). Используется ветками rejected и timeout стейджа
721
+ # manual-gate-human.
722
+ # -------------------------------------------------------------------------
723
+ mark-human-rejected:
724
+ description: "Записать причину отклонения human-тикета и переместить в blocked"
725
+ agent: script-mark-human-rejected
726
+ timeout: 30
727
+ goto:
728
+ default:
729
+ stage: move-ticket
730
+ params:
731
+ ticket_id: "$context.ticket_id"
732
+ target: blocked
733
+ error:
734
+ stage: move-ticket
735
+ params:
736
+ ticket_id: "$context.ticket_id"
737
+ target: blocked
738
+
652
739
  # -------------------------------------------------------------------------
653
740
  # 3c. verify-artifacts
654
741
  # Механическая предпроверка артефактов тикета перед AI-ревью.
@@ -729,10 +816,11 @@ pipeline:
729
816
  ticket_id: "$context.ticket_id"
730
817
  target: ready
731
818
  max_reached:
732
- stage: move-ticket
819
+ stage: mark-blocked
733
820
  params:
734
821
  ticket_id: "$context.ticket_id"
735
- target: blocked
822
+ attempts: "$counter.task_attempts"
823
+ reason: "max_review_attempts"
736
824
 
737
825
  # -------------------------------------------------------------------------
738
826
  # 5. move-ticket