Files
orchestrator/docs/work-items/ORCH-016/10-tech-risks.md

12 KiB
Raw Blame History

Технические риски — ORCH-016

Work Item: ORCH-016 Стадия: architecture Автор: architect Дата: 2026-06-05

Риски ранжированы по приоритету (P0 = блокер, P1 = серьёзный, P2 = умеренный, P3 = информационный). Каждый риск содержит митигацию и/или способ детекции на тестах.


R-1 (P1) — Self-hosting: сломанный коммент => слепая зона по ORCH-задаче

Описание. Изменение касается генерации комментов; орк дорабатывает сам себя. Если новый build_status_comment падает / отдаёт пустую строку / отдаёт битый HTML, стейкхолдер (Слава) потеряет видимость прогресса именно по той задаче, которая сломала комменты — и не сможет диагностировать без docker logs.

Митигация.

  • Внешний try/except Exception вокруг сборки HTML: при любом исключении возвращаем простой fallback-текст вида f"{icon} {role} готов" + logger.exception(...). Лучше «уродливый» коммент, чем тишина.
  • Юнит-тесты tests/test_status_comment_format.py (TC-01..TC-12, TC-23) фиксируют золотой HTML — регрессия ловится на CI до прод-деплоя.
  • Обязательный staging-гейт (check_staging_status для orchestrator) — финальный предохранитель: задача с ORCH-меткой не дойдёт до прод-контейнера, пока staging-инстанс (8501) не подтвердит, что комменты собираются.

R-2 (P1) — Plane HTML sanitization: <sub> / <br> / <ul> могут не рендериться

Описание. Plane (self-hosted) санитизирует входящий HTML. Эталон аналитика подтверждает рендер <ul> / <li> / <a> / <b>; рендер <sub> и <br> НЕ подтверждён на текущей версии Plane.

Митигация.

  • На staging (8501) опубликовать тестовый коммент build_status_comment(...) руками (через python -m скрипт или curl на dev-задачу) и визуально проверить рендер тех-хвоста и переводов строк ПЕРЕД мержем PR.
  • Если <sub> не рендерится — fallback: оставить usage-метрику обычной строкой с · разделителем (без <sub>).
  • Если <br> не рендерится — переходим на \n (Plane сам интерпретирует) либо упаковываем строки в <p>...</p>.
  • Развилка фиксируется в 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-фоллбэк, отклонений между двумя источниками не наблюдается (источник один).

Не митигируется специально — последствия нулевые (декоративная строка).

Описание. ADR-001 предписывает удалить usage_comment и переписать artifact_links на HTML. В рамках только grep по src/ я нашёл единственного клиента — _post_usage_comments в src/agents/launcher.py. Однако функция могла использоваться скриптами (scripts/), тестами (tests/), миграционными утилитами или внешними интеграциями.

Митигация. Developer на стадии development обязан выполнить полный grep:

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)? Сохранить как <sub>…</sub> хвостом в том же комменте. 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.
Q-6 HTML vs Markdown. HTML (как у эталона); artifact_links переписывается на <a>. 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.