# 03-Acceptance Criteria — ORCH-017 Work Item: **ORCH-017** · Repo: `orchestrator` Каждый критерий формулирует условие PASS/FAIL. Источник — 01-brd.md / 02-trz.md. ## AC-1 — Ссылка на BRD присутствует в уведомлении - **PASS:** Текст, сформированный `notify_approve_requested`, содержит кликабельную ссылку на `docs/work-items//01-brd.md` вида `{gitea_public_url|gitea_url}/{owner}/{repo}/src/branch/{branch}/docs/work-items/{WI}/01-brd.md`. - **FAIL:** Ссылки на BRD нет, либо она ведёт не на `01-brd.md`/не на нужный WI. ## AC-2 — Ссылка на Plane-issue присутствует в уведомлении - **PASS:** Тот же текст содержит кликабельную ссылку на issue в Plane, построенную на внешнем web-URL Plane + workspace + project + `plane_issue_id` (или согласованный браузер-формат). - **FAIL:** Ссылки на issue нет, либо она указывает на внутренний `localhost`/неверную issue. ## AC-3 — Базовый URL берётся из внешних настроек - **PASS:** BRD-ссылка использует `gitea_public_url`, при его пустоте — `gitea_url`; Plane-ссылка использует `plane_web_url` (env `ORCH_PLANE_WEB_URL`), при пустоте — `plane_api_url`. - **FAIL:** Захардкожен хост, либо ссылка нерабочая снаружи деплой-хоста. ## AC-4 — Существующий призыв сохранён - **PASS:** Текст по-прежнему содержит призыв перевести задачу в статус Approved (смысл строки «Переведите задачу в статус Approved … для продолжения» сохранён). - **FAIL:** Призыв удалён/искажён. ## AC-5 — Одно отдельное пингующее сообщение, без дублей - **PASS:** `notify_approve_requested` отправляет ровно одно сообщение через `send_telegram` (пингующее, не silent). Живой трекер (`update_task_tracker`) обновляется как раньше и не дублируется новым сообщением. - **FAIL:** Появляется второе/дубль-сообщение, либо трекер шлётся повторно как новое сообщение. ## AC-6 — Graceful degradation (никогда не ронять оркестратор) - **PASS:** При отсутствии `branch` / `plane_issue_id` / незаданном Plane web-URL функция НЕ бросает исключение: уведомление уходит с доступными ссылками (или без отсутствующей), орк жив. - **FAIL:** Отсутствие данных приводит к исключению/падению потока уведомлений. ## AC-7 — HTML-безопасность - **PASS:** Сохранён `parse_mode="HTML"`; динамические подписи экранируются (`html.escape`), URL валиден и не ломает разметку сообщения. - **FAIL:** Сообщение приходит с битой HTML-разметкой или с неэкранированным пользовательским текстом. ## AC-8 — Логика апрува не затронута - **PASS:** `:approved:`-handler, `check_analysis_approved`, переходы стадий и реестр `QG_CHECKS` без изменений; правка касается только текста/формата уведомления. - **FAIL:** Изменена логика гейта/перехода стадий. ## AC-9 — Документация обновлена в том же PR - **PASS:** Обновлены `CHANGELOG.md` и `.env.example` (новая `ORCH_PLANE_WEB_URL`); если добавлена настройка — отражено в env-карте (`CLAUDE.md`/`docs/operations/INFRA.md`); заведён ADR на выбранный формат. (Reviewer проверяет доку → нет обновления = REQUEST_CHANGES.) - **FAIL:** Код изменён, документация — нет. ## AC-10 — Тесты зелёные - **PASS:** Новые/затронутые тесты (`tests/test_notify_approve_links.py` и существующие `tests/test_telegram_tracker.py`, `tests/test_notify_done_regression.py`) проходят; `pytest tests/ -q` зелёный. - **FAIL:** Любой связанный тест падает. --- ### Зависит от решений Owner (open questions 01-brd §8) - Если выбран вариант **inline-кнопок** — AC-1/AC-2 считаются выполненными при наличии кнопок «📄 Открыть BRD» / «✅ К задаче в Plane» с теми же URL; дополнительно AC: обратная совместимость `send_telegram` (старые вызовы без `reply_markup` работают). - Если охват расширен до **всех точек решения** — AC-1/AC-2 проверяются для каждой такой точки.