diff --git a/CHANGELOG.md b/CHANGELOG.md index 09445c6..235e5f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ## [Unreleased] ### Added +- **Единый status-коммент агентов в Plane** (ORCH-016): `usage.build_status_comment(...)` — один хелпер для ВСЕХ ролей (analyst..deployer). HTML-формат: header `{icon} {Role} — {описание}`, опциональная строка `Verdict/Status: …` из YAML-frontmatter артефакта, **строка `Длительность: 4m 12s`** (явный `duration_s` от launcher, fallback из `agent_runs` для аналитика), `Документы:
`, тех-хвост `tokens · cost`. Утилитки: `usage.fmt_duration`, `usage.get_agent_duration`, новый модуль `src/frontmatter.py` (defensive YAML reader). ADR `docs/work-items/ORCH-016/06-adr/ADR-001-unified-status-comment.md`. - **Документация по канону** (ORCH-9): `CLAUDE.md` (паспорт проекта), структура `docs/` (`architecture/` + `adr/`, `operations/`, `work-items/`, `history/`), `docs/operations/INFRA.md` (RUNBOOK с инфра-изоляцией и self-hosting рисками). - **ADR**: adr-0001 (multi-repo registry), adr-0002 (job queue), adr-0003 (условный staging-гейт). - **Стадия `deploy-staging`** (ORCH-35): промежуточный гейт между `testing` и `deploy`. QG `check_staging_status` (условный, только для self-hosting repo). PR #31. @@ -14,6 +15,7 @@ - **Реестр проектов** (ORCH-6): `src/projects.py`, фильтрация вебхуков по проекту. ### Changed +- **Status-коммент агентов теперь HTML и единообразен** (ORCH-016): `src/usage.usage_comment(...)` помечен deprecated и стал тонкой обёрткой над `build_status_comment`; `src/usage.artifact_links(...)` теперь возвращает `...
`. +- Развилка фиксируется в `12-review.md` reviewer'ом по факту проверки. + +**Детекция.** Ручной чек-лист в staging-логе (`15-staging-log.md`) с приложенным скриншотом коммента. + +## R-3 (P2) — SQLite contention при DB-фоллбэке длительности + +**Описание.** `get_agent_duration(task_id, agent)` делает SELECT по `agent_runs` в момент сборки коммента. SQLite-БД одновременно используется очередью (`jobs`), воркером, вебхуками и Telegram-трекером; пиковая нагрузка → коротко блокирующиеся читатели. + +**Митигация.** +- Запрос идёт по индексу `(task_id, agent)` (если его нет — добавление индекса не входит в scope ORCH-016, но запрос всё равно быстрый: типичный `agent_runs` ≤ 50 строк на задачу). +- `try/except Exception` оборачивает SELECT → `logger.debug(...)` → `None`. При залоченной БД строка «Длительность:» просто опускается (AC-14). +- Запрос делаем ТОЛЬКО когда `duration_s` не передан явно (т.е. только для аналитика). + +**Детекция.** TC-25 — integration-тест на исключение в чтении `agent_runs`. + +## R-4 (P3) — Расхождение значений длительности (param vs DB) + +**Описание.** `_duration_s` в `src/agents/launcher.py:391` считается как `int(time.time() - _start_ts)`. DB-фоллбэк считает `(julianday(finished_at) - julianday(started_at)) * 86400`. Возможно расхождение в 1 секунду (округление) или больше (если `finished_at` пишется не сразу). + +**Митигация.** AC-13 допускает погрешность ±1с. Для аналитика, где используем только DB-фоллбэк, отклонений между двумя источниками не наблюдается (источник один). + +**Не митигируется специально** — последствия нулевые (декоративная строка). + +## R-5 (P2) — Скрытые callers `usage_comment` / `artifact_links` + +**Описание.** ADR-001 предписывает удалить `usage_comment` и переписать `artifact_links` на HTML. В рамках только grep по `src/` я нашёл единственного клиента — `_post_usage_comments` в `src/agents/launcher.py`. Однако функция могла использоваться скриптами (`scripts/`), тестами (`tests/`), миграционными утилитами или внешними интеграциями. + +**Митигация.** Developer на стадии development обязан выполнить полный grep: +```bash +grep -rn "usage_comment\|artifact_links" . --include="*.py" +``` +И переписать все вызовы. Если найдётся внешний потребитель — оставить `usage_comment` как deprecated-обёртку и зафиксировать в `12-review.md`. + +**Детекция.** TC-10 (полный pytest зелёный), TC-17 (дедуп-регрессия), reviewer-чек. + +## R-6 (P2) — Регрессия status-only verdict model аналитика (PR #12/#13) + +**Описание.** Аналитик переходит в `In Review` И не должен auto-advance'иться — статус ждёт Approved/Rejected от стейкхолдера. Если переписывание `_build_analyst_ready_comment` на обёртку случайно вернёт `auto_advance=True` или поменяет content так, что человек не поймёт инструкцию — порвётся существующий контракт. + +**Митигация.** +- TC-11 + TC-16: регрессионные тесты на формат коммента и status-only поведение. +- ADR-001 §1 явно фиксирует: контракт аналитика сохраняется; обёртка строит ИДЕНТИЧНЫЙ существующему текст + добавляет только строку длительности. + +## R-7 (P3) — Локализация и кодировка emoji в HTML + +**Описание.** В `src/usage.py` emoji-ы записаны `\Uxxxxxxxx`-escape'ами. При сборке HTML это безопасно (Python декодирует до utf-8), но при возможном последующем base64/quoted-printable транспорте могла бы возникнуть проблема. Plane API принимает utf-8 → риск минимален. + +**Митигация.** Не требуется. Существующий путь (PR #13, аналитик) уже посылает emoji через тот же `add_comment` без проблем. + +## R-8 (P3) — Дублирование YAML-парсинга frontmatter + +**Описание.** ADR-001 §5 принимает дублирование (~10 строк) в `src/frontmatter.py` и оставляет `src/qg/checks.py` со своим парсером. При расхождении правил (например, мы научим `read_frontmatter_value` поддерживать `---\nkey: value\n---` без trailing newline, а `qg/checks.py` останется строгим) теоретически возможны несогласованные интерпретации. + +**Митигация.** Принято в scope discipline; следующая задача-рефактор объединит. До тех пор — `read_frontmatter_value` обязан быть строго совместимым (по тестам) с поведением `qg/checks.py` на канонических случаях (BR-frontmatter с trailing newline после `---`). + +## R-9 (P0) — НЕ перезапускать прод-контейнер `orchestrator` + +**Описание.** Self-hosting: прод-контейнер (8500) обслуживает ВСЕ проекты (orchestrator + enduro-trails) из общей БД. Внеплановый рестарт ради «быстро посмотреть формат коммента» = простой конвейера всех проектов. + +**Митигация.** +- Все эксперименты — на staging (8501) через `docker compose --profile staging up -d orchestrator-staging`. +- Прод-деплой только через стандартный путь `deploy-staging → deploy` (под надзором `check_staging_status`). +- ЗАПРЕЩЕНО при ручном тестировании коммента дёргать `docker compose restart orchestrator`. + +--- + +## Открытые вопросы (Q&A — все закрыты ADR-001) + +| Q | Вопрос | Решение | Где зафиксировано | +|---|--------|---------|-------------------| +| Q-1 | Куда девать usage-метрику (tokens/cost)? | Сохранить как `…` хвостом в том же комменте. | ADR-001 §3 | +| Q-2 | «Длительность:» или «Duration:»? | «Длительность:» (русский, соответствует остальным меткам). | ADR-001 §4 | +| Q-3 | Один общий хелпер или раздельные для analyst/прочих? | Один: `build_status_comment(...)`; analyst — ветка внутри. | ADR-001 §1 | +| Q-4 | Парсер frontmatter — переиспользовать `qg/checks.py` или новый? | Новый `src/frontmatter.py`; `qg/checks.py` НЕ трогаем в этом PR. | ADR-001 §5 | +| Q-5 | Контракт DB-фоллбэка длительности. | `get_agent_duration(task_id, agent) -> int | None`, см. SQL в ADR-001 §6. | ADR-001 §6 | +| Q-6 | HTML vs Markdown. | HTML (как у эталона); `artifact_links` переписывается на ``. | ADR-001 §7 | +| Q-7 | Судьба старого `usage_comment(...)`. | Удалить, перевести единственного клиента (`_post_usage_comments`) на `build_status_comment`. | ADR-001 §1 | + +Если developer на стадии development обнаружит, что R-5 материализуется (есть скрытый клиент `usage_comment`) — допустимо оставить `usage_comment` как 1-строчную deprecated-обёртку (`return build_status_comment(...)`) и зафиксировать факт в `12-review.md` без возврата в architecture. + +--- + +*Risk register для ORCH-016. Обновляется reviewer'ом, если в ходе ревью всплывут новые риски — текущий список фиксирует видимое на момент завершения стадии architecture.* diff --git a/docs/work-items/ORCH-016/12-review.md b/docs/work-items/ORCH-016/12-review.md new file mode 100644 index 0000000..2c1f70a --- /dev/null +++ b/docs/work-items/ORCH-016/12-review.md @@ -0,0 +1,120 @@ +--- +type: review +work_item_id: ORCH-016 +verdict: APPROVED +version: 1 +--- + +# Review ORCH-016 — Единый status-коммент агентов в Plane + +## Summary + +PR реализует ТЗ ORCH-016 и ADR-001 полностью: вводится единый хелпер +`src/usage.build_status_comment(...)` для всех ролей (analyst…deployer), +строка `Длительность: …` с явным `duration_s` от launcher и DB-фоллбэком для +аналитика, defensive YAML-парсер `src/frontmatter.read_frontmatter_value`, +HTML-формат с эмодзи / Verdict / Документы / `` тех-хвостом. Аналитик +переведён на ту же ветку без регрессии (`tests/test_analyst_comment.py` + +`tests/test_analyst_status_only_regression.py` зелёные). `usage_comment` стал +deprecated-обёрткой, `artifact_links` теперь возвращает HTML-фрагменты +(breaking-change только для внутреннего вызова из удаляемого пути). +Документация обновлена: CHANGELOG.md (`Added` + `Changed`), +`docs/architecture/README.md` (новый подраздел «Plane Sync: единый +status-коммент агентов»), ADR-001 заведён в +`docs/work-items/ORCH-016/06-adr/`. + +Прохождение тестов: +- 60 новых ORCH-016 тестов: PASS (TC-01…TC-23 покрывают AC-1…AC-14). +- TC-20 (`test_qg_registry_snapshot.py`) подтверждает: `QG_CHECKS` и + `STAGE_TRANSITIONS` бит-идентичны (AC-11). +- Полный прогон: 392 PASS, 4 FAIL (`tests/test_m6_sequence.py::*`, + `tests/test_plane_webhook.py::test_orchestrator_project_routes_to_orchestrator_repo`, + `tests/test_plane_webhook.py::test_prefixes_independent_per_project`). + Эти 4 фейла **предсуществуют на `main`** (проверено: `git checkout main -- + src/ tests/` → те же 4 фейла; ORCH-016 их не индуцировал). AC-10 «no + regression» соблюдено. + +Соответствие ТЗ (`02-trz.md`): +- §1 модули: тронуты строго заявленные (`usage.py`, `stage_engine.py`, + `agents/launcher.py`, новый `frontmatter.py`); `qg/checks.py` сознательно + не трогается (ADR-001 §5, alt-6). +- §2.1–§2.5 формат, описания, verdict, ссылки, duration — реализовано. +- §3 API не меняется; §4 БД не меняется; §5 новых QG нет — подтверждено + TC-20. +- §6 docstrings, graceful frontmatter / duration, `fmt_duration` — чистая, + AC-13 happy + edge кейсы зелёные. +- §7 артефакты: ADR заведён. +- §8 документация: README архитектуры и CHANGELOG обновлены, `CLAUDE.md` + не трогается (правила не меняются). +- §9 запреты: `QG_CHECKS` / `STAGE_TRANSITIONS` / `add_comment` / + `_headers_for` / `PLANE_BOT_TOKENS` не тронуты; `--no-verify` не + использован. + +Соответствие ADR-001: +- §1 единственный публичный `build_status_comment(...)` с указанной + сигнатурой ✓ +- §2 описания per-agent ✓ +- §3 `` тех-хвост ✓ +- §4 русская метка `Длительность:` ✓ +- §5 `src/frontmatter.py` ✓ +- §6 `get_agent_duration` с указанным SQL ✓ +- §7 HTML-якоря, `