# ТЗ / черновик 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//12-review.md"` - **Tester FAIL** (стр. ~455): `"...Note: Tests FAILED. Fix failures described in docs/work-items//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 `; heredoc через ssh+docker глотает вывод → скрипт+base64+docker cp. - Это правка ЯДРА (stage_engine) — на staging обязателен честный прогон; помнить про B6/ORCH-48 (staging-реестр пока видит прод-проекты — не блокер, но при E2E учитывать).