diff --git a/docs/work-items/ORCH-016/06-adr/ADR-001-unified-status-comment.md b/docs/work-items/ORCH-016/06-adr/ADR-001-unified-status-comment.md
new file mode 100644
index 0000000..7e2154f
--- /dev/null
+++ b/docs/work-items/ORCH-016/06-adr/ADR-001-unified-status-comment.md
@@ -0,0 +1,203 @@
+# ADR-001: Единый формат status-коммента агентов в Plane
+
+- **Work Item:** ORCH-016
+- **Стадия:** architecture
+- **Статус:** Accepted
+- **Дата:** 2026-06-05
+- **Автор:** architect
+
+## Контекст
+
+ТЗ ORCH-016 требует привести коммент-формат всех агентов (architect/developer/reviewer/tester/deployer + сохранение совместимости с analyst) к единому виду по эталону `src/stage_engine.py::_build_analyst_ready_comment` и дополнительно встроить **строку длительности работы агента**.
+
+ТЗ оставил архитектору пять открытых вопросов (см. §2.2, §2.5, §2.7, §6):
+1. Где живёт общий хелпер построения коммента (один файл vs. два).
+2. Как ведём себя с usage-метрикой (tokens / $cost) в новом формате (Q-1 из ТЗ §2.7).
+3. Локализация метки длительности — «Длительность:» vs «Duration:».
+4. Парсинг frontmatter артефакта (verdict / deploy_status / staging_status) — переиспользовать `src/qg/checks.py` или дублировать.
+5. Контракт хелпера БД-фоллбэка длительности и его форма.
+
+Дополнительно: текущий `usage_comment(...)` — публичная (внутри проекта) функция, вызывается из `src/agents/launcher.py::_post_usage_comments`. Менять формат «на месте» без явного решения о судьбе старой сигнатуры рискованно.
+
+## Решение
+
+### 1. Архитектура хелперов
+
+Вводим **ровно один публичный хелпер** в `src/usage.py`:
+
+```python
+def build_status_comment(
+ agent: str, # "analyst" | "architect" | ... | "deployer"
+ *,
+ repo: str | None = None,
+ branch: str | None = None,
+ work_item_id: str | None = None,
+ pr_number: int | None = None,
+ stage: str | None = None, # "deploy" vs "deploy-staging" (для deployer)
+ usage: dict | None = None, # tokens/cost (опционально)
+ duration_s: int | None = None, # если известно — иначе fallback по БД
+ task_id: int | None = None, # требуется ТОЛЬКО для DB-фоллбэка длительности
+ worktree_root: str | None = None, # для чтения артефактов; None → опускаем verdict
+) -> str:
+```
+
+Что делает:
+- Собирает заголовок `{ICON} {RoleName} — {описание}` (описание per-agent — см. §2 ниже).
+- Опционально дописывает строку `Verdict: …` / `Status: …` (только для reviewer/tester/deployer и только если frontmatter артефакта присутствует и распознан).
+- Всегда (если известна) дописывает строку `Длительность: …` через `fmt_duration(...)`.
+- Дописывает блок `Документы:
`.
+- Опционально дописывает технический хвост `{tokens}/{cost}` — см. §3.
+
+`_build_analyst_ready_comment(...)` в `src/stage_engine.py` переписывается как **тонкая обёртка** над `build_status_comment(agent="analyst", ...)`. Аналитик-специфичный текст (инструкция «переведите в Approved/Rejected» + полный список 01-brd / 02-trz / 03-acceptance-criteria / 04-test-plan) добавляется ВНУТРИ `build_status_comment` через ветку `agent == "analyst"` — это единственное место, где per-agent текст шире одной строки. Альтернатива (передавать кастомный текст параметром) добавляет API-площадь без пользы.
+
+**Старый `usage_comment(...)` удаляется**; единственный его внешний вызов — `src/agents/launcher.py::_post_usage_comments` — переписывается на `build_status_comment(...)`. Это упрощает дальнейшее сопровождение (один формат → одна функция); риск минимален, потому что `usage_comment` — внутренний API.
+
+### 2. Per-agent описания (финализация ТЗ §2.2)
+
+| Агент | Описание (HTML, без точки в конце) |
+|-------|------------------------------------|
+| analyst | «Подготовил BRD / ТЗ / Acceptance Criteria. Для продвижения переведите задачу в статус Approved» (плюс существующая инструкция про Approved/Rejected уходит как продолжение) |
+| architect | «Завершил архитектурную проработку. См. ADR ниже» |
+| developer | «Завершил разработку. См. PR / branch ниже» |
+| reviewer | «Завершил ревью изменений» |
+| tester | «Завершил прогон тестов» |
+| deployer (deploy) | «Завершил прод-деплой» |
+| deployer (deploy-staging) | «Завершил staging-деплой» |
+
+### 3. Решение по Q-1 (usage-метрика)
+
+**Сохраняем** usage-метрику как **техническую ``-строку в конце** коммента, объединённую с длительностью НЕ нужно — длительность остаётся ОТДЕЛЬНОЙ строкой нормального веса (требование ТЗ §2.5).
+
+Конкретно:
+```html
+8.5M in (8.4M cached) / 45.8k out · $7.29
+```
+
+Почему НЕ удаляем:
+- Тех-метрика полезна для оценки стоимости задачи на пост-мортеме (особенно для ORCH-задач, где orchestrator расходует свой же бюджет).
+- `task_summary_comment` (Deployer end-of-task) суммирует по задаче, но не покрывает per-agent breakdown в момент завершения каждой стадии — для трассировки «кто сколько потратил» полезно видеть сразу.
+
+Почему ``, а не обычная строка:
+- Стейкхолдер (Слава) явно просил «без раздувания»; визуально приглушённый хвост не конкурирует за внимание с описанием/вердиктом/длительностью/ссылками.
+- Plane корректно рендерит `` (проверено ранее на PR #13).
+
+При `usage = None` или нулевых значениях — хвост опускается полностью.
+
+### 4. Решение по Q-2 (локализация метки длительности)
+
+Используем русский: **`Длительность: 4m 12s`**.
+Обоснование: все человеческие тексты комментов уже на русском (заголовок «Документы:», описания стадий). Метка `4m 12s` сама по себе универсальна и понятна без перевода (стандарт CLI-инструментов: `time`, `gh`, `kubectl`).
+
+### 5. Решение по Q-4 (парсинг frontmatter)
+
+Создаём НОВЫЙ маленький утилитный модуль **`src/frontmatter.py`** с единственной функцией:
+
+```python
+def read_frontmatter_value(path: str, key: str) -> str | None:
+ """Read a single key from leading YAML frontmatter. Never raises.
+
+ Returns None if file missing, frontmatter absent/malformed, or key not set.
+ """
+```
+
+Реализация — yaml.safe_load на блоке между двумя `---` строками; всё ловится одним `try/except` → `logger.debug` → `None`.
+
+Этот модуль используют:
+- `src/usage.py::build_status_comment` — для извлечения `verdict:` / `deploy_status:` / `staging_status:`.
+- `src/qg/checks.py` — НЕ обязательно мигрировать в этом PR (out-of-scope ORCH-016); миграция может пройти отдельной задачей-рефакторингом. **В этом PR `qg/checks.py` НЕ трогаем** — снижает blast radius и риск регрессии гейтов.
+
+Дублирование (~10 строк YAML-парсера в `qg/checks.py` остаётся) сознательно принято: scope discipline > DRY на одном переиспользовании.
+
+### 6. Решение по Q-5 (DB-фоллбэк длительности)
+
+Хелпер в `src/usage.py`:
+
+```python
+def get_agent_duration(task_id: int, agent: str) -> int | None:
+ """Return last finished agent_runs duration (seconds) for (task, agent).
+ Never raises. None on missing row / NULL finished_at / negative / error.
+ """
+```
+
+SQL — ровно как в ТЗ §2.5 (фоллбэк):
+```sql
+SELECT CAST((julianday(finished_at) - julianday(started_at)) * 86400 AS INTEGER)
+FROM agent_runs
+WHERE task_id=? AND agent=?
+ AND finished_at IS NOT NULL
+ORDER BY id DESC LIMIT 1
+```
+
+Чтение через `get_db()` (стандартный путь модуля), обёрнутое в `try/except Exception` → `logger.debug(...)` → `None`. Соединение всегда закрывается в `finally`.
+
+`build_status_comment` вызывает `get_agent_duration(...)` ТОЛЬКО когда:
+- `duration_s is None`, И
+- `task_id is not None` (вызывающая сторона согласилась оплатить лишний SELECT).
+
+Если оба источника пусты → строка «Длительность:» опускается (AC-14).
+
+### 7. Решение по HTML vs Markdown (ТЗ §6)
+
+Целевой рендер — **HTML**, как у эталона аналитика. Конкретно:
+- Заголовок и описание — plain text + emoji.
+- Verdict / Длительность — отдельные строки, разделяются `
` (или `\n` если Plane корректно интерпретирует переводы строк; экспериментально подтвердить на staging — см. R-2 в `10-tech-risks.md`).
+- Блок документов — `Документы:`.
+- Технический хвост — `…` отдельной строкой через `
`.
+
+`artifact_links(...)` (сейчас возвращает markdown-строки `[label](url)`) — **переписывается на HTML-якоря** `label`. Эмодзи-префиксы (📂/🔗/📐/📄) сохраняются. Возвращаемый тип меняется: `list[str]` остаётся, но содержимое — HTML-фрагменты (документировано в docstring).
+
+Это breaking-change для внутреннего API `artifact_links`, но единственный внешний вызов был из `usage_comment`, который тоже удаляется. Других вызовов в `tests/`/`scripts/` нет (developer проверит grep'ом в development-стадии).
+
+### 8. Контракт `fmt_duration` (полностью по AC-13)
+
+```python
+def fmt_duration(seconds: int | None) -> str:
+ """0..59 → '{s}s'; 60..3599 → '{m}m {ss:02d}s'; >=3600 → '{h}h {mm:02d}m'.
+ None / negative → '' (caller should drop the line)."""
+```
+
+Чистая функция, без I/O, easily unit-testable. Размещение: `src/usage.py` (рядом с `fmt_tokens` / `fmt_cost`).
+
+## Альтернативы
+
+1. **Два отдельных хелпера** (`build_analyst_status_comment` + `build_agent_status_comment`).
+ Отклонено: ТЗ явно просит «единый эталонный формат»; дублирование шаблона расходится со временем.
+
+2. **Оставить `usage_comment` как deprecated-обёртку.**
+ Отклонено: один внутренний вызов, deprecation добавляет когнитивный шум без выигрыша.
+
+3. **Перенести usage-метрику в `task_summary_comment` (вариант B из ТЗ §2.7).**
+ Отклонено: теряем per-stage видимость затрат; финальный summary не отвечает на вопрос «сколько съел конкретно reviewer».
+
+4. **Markdown вместо HTML.**
+ Отклонено: эталон аналитика (PR #13) уже HTML; смена ломает визуальный паритет.
+
+5. **Английская метка «Duration:».**
+ Отклонено: ассиметрия с остальными русскими подписями в комменте.
+
+6. **Рефакторить `qg/checks.py` на `src/frontmatter.py` в этом же PR.**
+ Отклонено: расширяет blast radius на гейты; делаем отдельной задачей.
+
+## Последствия
+
+### Положительные
+- Единая точка изменения формата комментов на будущее — `build_status_comment`.
+- Удаление дубликата `usage_comment` уменьшает API-площадь модуля.
+- `src/frontmatter.py` подготавливает почву для будущего рефактора `qg/checks.py` (DRY-победа в один заход следующей задачей).
+- HTML-рендеринг даёт стейкхолдеру кликабельные ссылки и приглушённый тех-хвост.
+
+### Отрицательные / ограничения
+- Дублирование YAML-парсинга на ~10 строк (qg/checks.py остаётся со своим).
+- Дополнительный SELECT к `agent_runs` на каждый коммент аналитика (1 запрос, по индексу `task_id`, ничтожно).
+- HTML-разметка ломается визуально, если Plane изменит политику санитизации `` или `` (риск R-2).
+
+### Self-hosting
+- Хелперы — чистый код, без рестарта прод-контейнера. Изменения дойдут до прода через стандартный staging-гейт (`deploy-staging` → `deploy`).
+- Если коммент сломается, ленту Plane задачи ORCH-016 первой и заметим — feedback loop коротко.
+
+## Связи
+- ТЗ §1, §2, §6 (`docs/work-items/ORCH-016/02-trz.md`)
+- AC-1..AC-14 (`docs/work-items/ORCH-016/03-acceptance-criteria.md`)
+- PR #13 (эталон аналитика — `_build_analyst_ready_comment`)
+- PR #14 (`gitea_public_url` для кликабельных ссылок)
+- `src/usage.py`, `src/stage_engine.py`, `src/agents/launcher.py`, `src/db.py`, `src/qg/checks.py`
diff --git a/docs/work-items/ORCH-016/10-tech-risks.md b/docs/work-items/ORCH-016/10-tech-risks.md
new file mode 100644
index 0000000..e3bef0a
--- /dev/null
+++ b/docs/work-items/ORCH-016/10-tech-risks.md
@@ -0,0 +1,112 @@
+# Технические риски — 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: `` / `
` / `` могут не рендериться
+
+**Описание.** Plane (self-hosted) санитизирует входящий HTML. Эталон аналитика подтверждает рендер `` / `- ` / `` / ``; **рендер `` и `
` НЕ подтверждён** на текущей версии Plane.
+
+**Митигация.**
+- На staging (8501) опубликовать тестовый коммент `build_status_comment(...)` руками (через `python -m` скрипт или curl на dev-задачу) и визуально проверить рендер тех-хвоста и переводов строк ПЕРЕД мержем PR.
+- Если `` не рендерится — fallback: оставить usage-метрику обычной строкой с `· ` разделителем (без ``).
+- Если `
` не рендерится — переходим на `\n` (Plane сам интерпретирует) либо упаковываем строки в `...
`.
+- Развилка фиксируется в `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.*