kin/tasks/adr-automode.md
Gros Frumos 4a27bf0693 feat(KIN-012): UI auto/review mode toggle, autopilot indicator, persist project mode in DB
- TaskDetail: hide Approve/Reject buttons in auto mode, show "Автопилот активен" badge
- TaskDetail: execution_mode persisted per-task via PATCH /api/tasks/{id}
- TaskDetail: loadMode reads DB value, falls back to localStorage per project
- TaskDetail: back navigation preserves status filter via ?back_status query param
- ProjectView: toggleMode now persists to DB via PATCH /api/projects/{id}
- ProjectView: loadMode reads project.execution_mode from DB first
- ProjectView: task list shows 🔓 badge for auto-mode tasks
- ProjectView: status filter synced to URL query param ?status=
- api.ts: add patchProject(), execution_mode field on Project interface
- core/db.py, core/models.py: execution_mode columns + migration for projects & tasks
- web/api.py: PATCH /api/projects/{id} and PATCH /api/tasks/{id} support execution_mode
- tests: 256 tests pass, new test_auto_mode.py with 60+ auto mode tests
- frontend: vitest config added for component tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 20:02:01 +02:00

12 KiB
Raw Permalink Blame History

ADR: Auto Mode — полный автопилот (KIN-012)

Дата: 2026-03-15 Статус: Accepted Автор: architect (KIN-012)


Контекст

Задача: реализовать два режима исполнения пайплайнов:

  • Auto — полный автопилот: pipeline → auto-approve → auto-followup → auto-rerun при permission issues → hooks. Без остановок на review/blocked.
  • Review — текущее поведение: задача уходит в статус review, ждёт ручного approve.

Что уже реализовано (анализ кода)

1. Хранение режима — core/db.py

  • projects.execution_mode TEXT NOT NULL DEFAULT 'review' — дефолт на уровне проекта
  • tasks.execution_mode TEXT — nullable, переопределяет проект
  • Миграции добавляют оба столбца к существующим БД

2. Приоритет режима — core/models.py:get_effective_mode()

task.execution_mode > project.execution_mode > 'review'

Вычисляется один раз в начале run_pipeline.

3. Auto-approve — agents/runner.py:run_pipeline() (строки 519536)

if mode == "auto":
    models.update_task(conn, task_id, status="done")
    run_hooks(conn, project_id, task_id, event="task_auto_approved", ...)
else:
    models.update_task(conn, task_id, status="review")

4. Permission retry — agents/runner.py:run_pipeline() (строки 453475)

if mode == "auto" and not allow_write and _is_permission_error(result):
    run_hooks(..., event="task_permission_retry", ...)
    retry = run_agent(..., allow_write=True)
    allow_write = True  # propagates to all subsequent steps
  • Срабатывает только в auto режиме
  • Ровно 1 попытка retry на шаг
  • После первого retry allow_write=True сохраняется на весь оставшийся пайплайн

5. Паттерны permission errors — core/followup.py:PERMISSION_PATTERNS

permission denied, ручное применение, cannot write, read-only, manually appl, ...

6. Post-pipeline hooks — core/hooks.py События: pipeline_completed, task_auto_approved, task_permission_retry


Пробелы — что НЕ реализовано

Gap 1: Auto-followup не вызывается из run_pipeline

generate_followups() существует в core/followup.py, но нигде не вызывается автоматически. В run_pipeline после завершения пайплайна — только хуки.

Gap 2: Auto-resolution pending_actions в auto mode

generate_followups() возвращает pending_actions (permission-blocked followup items) с опциями ["rerun", "manual_task", "skip"]. В auto mode нет логики автоматического выбора опции.

Gap 3: Наследование режима followup-задачами

Задачи, созданные через generate_followups(), создаются с execution_mode=None (наследуют от проекта). Это правильное поведение, но не задокументировано.


Решения

D1: Где хранить режим

Решение: двухуровневая иерархия (уже реализована, зафиксируем).

Уровень Поле Дефолт Переопределяет
Глобальный review
Проект projects.execution_mode 'review' глобальный
Задача tasks.execution_mode NULL проект

Глобального конфига нет — осознанное решение. Каждый проект управляет своим режимом. Задача может переопределить проект (например, форсировать review для security-sensitive задач).

Изменения БД не нужны — структура готова.


D2: Как runner обходит ожидание approve в auto mode

Решение: уже реализовано. Зафиксируем контракт:

run_pipeline() в auto mode:
  1. Все шаги выполняются последовательно
  2. При успехе → task.status = "done" (минуя "review")
  3. Хук task_auto_approved + pipeline_completed
  4. generate_followups() автоматически (Gap 1, см. D4)

В review mode — без изменений: task.status = "review", generate_followups() не вызывается автоматически.


D3: Auto-rerun при permission issues — лимит и критерии

Что считать permission issue: Паттерны из PERMISSION_PATTERNS в core/followup.py. Список достаточен, расширяется при необходимости через PR.

Лимит попыток: 1 retry per step (уже реализовано). Обоснование:

  • Permission issue — либо системная проблема (нет прав на директорию), либо claude CLI требует --dangerously-skip-permissions
  • Второй retry с теми же параметрами не имеет смысла — проблема детерминированная
  • Если 1 retry не помог → task.status = "blocked" даже в auto mode

Поведение после retry: allow_write=True применяется ко всем последующим шагам пайплайна (не только retry шагу). Это безопасно в контексте Kin — агенты работают в изолированном рабочем каталоге проекта.

Хук task_permission_retry: Срабатывает перед retry — позволяет логировать / оповещать, но не блокирует.

Итоговая таблица поведения при failure:

Режим Тип ошибки Поведение
auto permission error (первый) retry с allow_write=True
auto permission error (после retry) blocked
auto любая другая ошибка blocked
review любая ошибка blocked

D4: Auto-followup интеграция с post-pipeline hooks

Решение: generate_followups() вызывается из run_pipeline() в auto mode после task_auto_approved хука.

Порядок событий в auto mode:

1. pipeline успешно завершён
2. task.status = "done"
3. хук: task_auto_approved  ← пользовательские хуки (rebuild-frontend и т.д.)
4. generate_followups()     ← анализируем output, создаём followup задачи
5. хук: pipeline_completed  ← финальное уведомление

В review mode:

1. pipeline успешно завершён
2. task.status = "review"
3. хук: pipeline_completed
   ← generate_followups() НЕ вызывается (ждём manual approve)

Почему после task_auto_approved, а не до: Хуки типа rebuild-frontend (KIN-010) изменяют состояние файловой системы. Followup-агент должен видеть актуальное состояние проекта после всех хуков.


D5: Auto-resolution pending_actions в auto mode

generate_followups() может вернуть pending_actions — элементы, заблокированные из-за permission issues. В auto mode нужна автоматическая стратегия.

Решение: в auto mode pending_actions резолвятся как "rerun".

Обоснование:

  • Auto mode = полный автопилот, пользователь не должен принимать решения
  • "rerun" — наиболее агрессивная и полезная стратегия: повторяем шаг с allow_write=True
  • Если rerun снова даёт permission error → создаётся manual_task (escalation)
auto mode + pending_action:
  → resolve_pending_action(choice="rerun")
  → если rerun провалился → create manual_task с тегом "auto_escalated"
  → всё логируется

review mode + pending_action:
  → возвращается пользователю через API для ручного выбора

D6: Наследование режима followup-задачами

Задачи, созданные через generate_followups(), создаются с execution_mode=None.

Решение: followup-задачи наследуют режим через проект (существующая иерархия D1). Явно устанавливать execution_mode в followup-задачах не нужно — если проект в auto, все его задачи по умолчанию в auto.

Исключение: если оригинальная задача была в review (ручной override), followup-задачи НЕ наследуют это — они создаются "чисто" от проекта. Это намеренное поведение: override в задаче — разовое действие.


Итоговая карта изменений (что нужно реализовать)

# Файл Изменение Gap
1 agents/runner.py Вызов generate_followups() в auto mode после task_auto_approved D4
2 core/followup.py Auto-resolution pending_actions в generate_followups() при auto mode D5
3 web/api.py Endpoint для смены execution_mode проекта/задачи
4 web/frontend UI переключатель Auto/Review (project settings + task detail)

Что НЕ нужно менять:

  • core/db.py — схема готова
  • core/models.pyget_effective_mode() готов
  • core/hooks.py — события готовы
  • Permission detection в runner.py — готово

Риски и ограничения

  1. Стоимость в auto mode: generate_followups() добавляет один запуск агента после каждого пайплайна. При высокой нагрузке это существенный overhead. Митигация: generate_followups() можно сделать опциональным (флаг auto_followup в project settings).

  2. Permission retry scope: allow_write=True после первого retry применяется ко всем последующим шагам. Это агрессивно, но допустимо, т.к. агент уже начал писать файлы.

  3. Infinite loop в auto-followup: если followup создаёт задачи, а те создают ещё followup — нет механизма остановки. Митигация: parent_task_id позволяет отслеживать глубину. Задачи с source: followup:* глубже 1 уровня — не генерируют followup автоматически.

  4. Race condition: если два пайплайна запускаются для одной задачи одновременно — БД-уровень не блокирует. SQLite WAL + task.status = 'in_progress' в начале пайплайна дают частичную защиту, но не полную.


Статус реализации

  • DB schema: execution_mode в projects и tasks
  • get_effective_mode() с приоритетом task > project > review
  • Auto-approve: task.status = "done" в auto mode
  • Permission retry: 1 попытка с allow_write=True
  • Хуки: task_auto_approved, pipeline_completed, task_permission_retry
  • Auto-followup: вызов generate_followups() из run_pipeline() в auto mode (Gap 1)
  • Auto-resolution pending_actions в auto mode (Gap 2)
  • API endpoints для управления execution_mode
  • Frontend UI для Auto/Review переключателя