Files
wiki/tasks/orchestrator/DEV_TASK_ORCH-046.md
2026-06-06 07:10:02 +03:00

8.8 KiB
Raw Permalink Blame History

ТЗ / черновик ADR — ORCH-46: «Испорченный телефон» при заворотах агентам

Статус: ЧЕРНОВИК на согласование Славе. Перед запуском конвейером Слава выбирает вариант дизайна (см. §3) и подтверждает scope. ORCH-46 лезет в ядро (stage_engine.py), поэтому ADR обязателен.

1. Проблема (факты из кода, проверено 06.06)

Когда задачу возвращают на доработку, орк формирует деву task_desc (→ .task-dev.md), и в нём — только ссылка на файл, без сути замечаний. Дословно из src/stage_engine.py:

  • Reviewer REQUEST_CHANGES (стр. ~419): "...Note: REQUEST_CHANGES from reviewer (attempt N/3). Fix findings in docs/work-items/<WI>/12-review.md"
  • Tester FAIL (стр. ~455): "...Note: Tests FAILED. Fix failures described in docs/work-items/<WI>/13-test-report.md"

Три корневые беды (ровно они убивали автономность ORCH-17):

  1. Испорченный телефон. Деву дают ссылку «иди читай файл», а не текст претензий. Ключевую мысль (напр. governance: «не трогай shared-гейт») легко проскочить.
  2. Противоречивые сигналы. Tester шлёт «Tests FAILED, чини тесты» (толкает лезть в тест-код → в т.ч. в shared-гейт), reviewer шлёт «не трогай gate». Два противоположных приказа в разных кругах, дев видит только последний.
  3. Нет памяти между кругами. Каждый developer-запуск — чистый агент (agent_runs лишь считает количество). Дев не знает, на чём уже погорел в прошлых кругах → повторяет ошибку.

2. Что есть для решения (разведано)

  • 12-review.md содержит структурированный блок ## Findings с уровнями ### P0 — Blocker / P1 — Must fix / P2 — Should fix / P3 — Nice-to-have + frontmatter verdict:. → findings машиночитаемы, можно извлечь P0/P1/P2.
  • 13-test-report.md содержит frontmatter result:/verdict:/status: + тело с описанием падений. → можно извлечь причину FAIL.
  • agent_runs (БД) — по task_id+agent считаются круги; туда же можно писать краткий «след» каждого заворота (что требовалось, к какому агенту относилось).
  • Передача в агента: enqueue_job(agent, repo, task_desc, task_id) → launcher пишет task_desc в .task-dev.md. Менять формат task_desc достаточно, чтобы донести больше.

3. ВАРИАНТЫ ДИЗАЙНА (выбрать один — решение Славы)

Вариант A — «Вклеить findings» (минимальный, низкий риск) рекомендую как старт

  • В task_desc при заворотах встраивать ТЕКСТ замечаний, а не только ссылку.
    • Reviewer: распарсить ## Findings из 12-review.md, вынуть P0/P1 (must-fix) дословно в task_desc. Ссылку на файл оставить как «полный контекст».
    • Tester: вынуть причину FAIL (reason + ключевые строки тела 13-test-report.md).
  • Плюсы: бьёт прямо в беду №1 (испорченный телефон), правка локальная (формирование строки + парсер-хелпер), легко тестируется. Минусы: не решает №2/№3 полностью.

Вариант B — A + «память кругов» (средний)

  • Всё из A, плюс: в agent_runs (или отдельную мини-таблицу dev_round_notes) писать краткий след каждого заворота: круг N, агент-источник (reviewer/tester), суть требования. При новом запуске дева вклеивать в task_desc блок «История прошлых кругов: на чём уже погорел / чего НЕ делать». Бьёт по беде №3.
  • Плюсы: дев перестаёт повторять ошибки. Минусы: миграция БД/новая таблица, чуть сложнее.

Вариант C — A + B + «склейка противоречий» (полный, выше риск)

  • Всё из A+B, плюс: если в истории есть конфликт сигналов (reviewer «не трогай X» vs tester «почини тесты, связанные с X»), орк склеивает их в одно непротиворечивое ТЗ с явным приоритетом (governance reviewer > tester по умолчанию; правило вынести в конфиг/ADR).
  • Плюсы: убивает все три беды. Минусы: эвристика склейки сложна, риск ложной логики, больше тестов, заметнее правка ядра.

Моя рекомендация: делать A сейчас (быстрая большая отдача, низкий риск ядра), B и C — отдельными инкрементами после обкатки A на реальных заворотах. Но финальное слово — за Славой.

4. Scope (для выбранного варианта — заполнить после решения)

  • Файлы: src/stage_engine.py (формирование task_desc в 2-3 ветках), новый хелпер-парсер (напр. src/review_parse.py: extract_review_findings(path) -> str, extract_test_failures(path) -> str), тесты, ADR, CHANGELOG.
  • (Вариант B/C доп.: миграция БД / src/db.py.)
  • НЕ трогать: сами гейты check_* (ORCH-45/47 уже в проде), QG-реестр, сигнатуры публичных функций, webhook-пути (заворот идёт launcher-путём, finished_agent задан).

5. Acceptance Criteria (вариант A)

  • AC-1: при reviewer REQUEST_CHANGES .task-dev.md содержит ДОСЛОВНЫЙ текст P0/P1 findings из 12-review.md (не только ссылку).
  • AC-2: при tester FAIL .task-dev.md содержит причину падения (reason + релевантный фрагмент 13-test-report.md).
  • AC-3: ссылка на полный файл сохранена как доп. контекст.
  • AC-4: парсер устойчив к отсутствию/битому файлу (graceful: fallback на старую ссылку-строку, никогда не падает — по образцу _parse_tests_verdict, который «never raise»).
  • AC-5: существующие тесты stage_engine/test_qg зелёные; добавлены юнит-тесты парсера (findings есть / пусто / битый YAML / только P3).
  • AC-6: retry-счётчик и rollback-логика НЕ изменены по поведению.

6. Команды проверки

  • В контейнере: python -m pytest tests/test_qg.py tests/test_stage_engine*.py -q.
  • Ручной снапшот task_desc: смоделировать заворот и проверить содержимое .task-dev.md.

7. Грабли (из опыта 05.06 — обязательно учесть)

  • Запуск через конвейер: заголовок задачи ≤80 символов (QG-0), иначе Blocked.
  • Деплой после мержа: /app запечён в образ → нужен docker compose build orchestrator + рестарт + проверка claude-auth (HOME=/home/slin claude.exe --print, timeout 90с).
  • Gitea API: заголовок Authorization: token <ORCH_GITEA_TOKEN>; heredoc через ssh+docker глотает вывод → скрипт+base64+docker cp.
  • Это правка ЯДРА (stage_engine) — на staging обязателен честный прогон; помнить про B6/ORCH-48 (staging-реестр пока видит прод-проекты — не блокер, но при E2E учитывать).