auto-sync: 2026-06-04 11:20:01

This commit is contained in:
Stream
2026-06-04 11:20:05 +03:00
parent d17ae1b9dd
commit 6b7f04437d

View File

@@ -0,0 +1,85 @@
# Dev Report: orchestrator — 4 правки наблюдаемости + вторая дверь баг-8
Дата: 2026-06-04
Статус: DONE
## Задача
Одна ветка `fix/observability-and-merge-gate`, один PR. 4 правки:
1. КРИТ: merge-вебхук при `current_stage=="deploy"` НЕ ставит done (gated by deployer verdict).
2. КРИТ: токены — показывать полный вход (input + cache_read + cache_creation), хранить cache_creation.
3. deploy→done success → Plane в терминальный Done.
4. Все агенты прикладывают ссылку на свой артефакт в финиш-коммент.
## Результат — сдача
- **PR: #20** — https://git.mva154.duckdns.org/admin/orchestrator/pulls/20 (open, НЕ смержен)
- **Ветка:** `fix/observability-and-merge-gate` (от актуального main `2629dff`)
- **Commit:** `61e26a8`
- **pytest (вся сюита):** `244 passed, 9 failed`
- Baseline был 227 passed + 10 failed. Добавлено **17 новых тестов** (227→244).
- 9 failed = подмножество off-limits HMAC/401 группы. 10-й off-limits тест
(`test_plane_webhook_generates_sequential_ids`) падает только в изоляции,
а в полной сюите проходит из-за порядка/состояния DB — это pre-existing
флак внутри off-limits группы, не связан с правками. Ни один НЕ off-limits
тест не падает.
## Что изменилось в каждой правке
### Правка 1 — `src/webhooks/gitea.py` (merge-gate, баг-8 вторая дверь)
В ветке `action=="closed" and pr.get("merged")` добавлен ранний `return` при
`current_stage == "deploy"` (только лог, без update_task_stage / advance_stage —
чтобы не было гонки). Для всех остальных стадий поведение merge→done сохранено.
deployer мержит PR в начале работы → merge-вебхук больше не фейк-завершает задачу;
done на deploy решает только `check_deploy_status` через `advance_stage`.
### Правка 2 — `src/usage.py` + `src/db.py` (полный вход токенов)
- `db.py`: idempotent миграция `_ensure_column(agent_runs, "cache_creation_tokens", "INTEGER")`.
- `parse_usage_from_text`: добавлен `cache_creation_tokens` из
`cache_creation_input_tokens`.
- `record_usage`: пишет новую колонку.
- Новый `fmt_in()`: `in_total = input + cache_read + cache_creation`,
`cached = cache_read + cache_creation`. Формат `8.5M in (8.4M cached)`;
при cached==0 — просто `45.2k in` (обратно совместимо).
- `usage_comment`: использует `fmt_in()`.
- `task_usage_summary`: `total_in = SUM(input+cache_read+cache_creation)`,
отдельно `total_cached`, per_agent теперь 5-кортежи; COALESCE(...,0) для NULL.
- `task_summary_comment`: показывает `<total_in> вход (<cached> cached) / <out> выход · <cost>`.
- `cost_usd` НЕ тронут.
### Правка 3 — `src/stage_engine.py` + `src/plane_sync.py` (Plane→Done)
- `plane_sync.py`: новый `set_issue_done()``_set_issue_state_direct(PLANE_STATES["done"])`
(маппинг PLANE_STATES НЕ менялся).
- `stage_engine.advance_stage`: в Advance-блоке при `next_stage == "done"` и наличии
work_item_id вызывается `set_issue_done(work_item_id)` (в try/except). Теперь
успешный deploy→done гарантированно доводит Plane до терминального Done
(раньше застревал на In Progress, т.к. merge-вебхук обходил флоу).
### Правка 4 — `src/usage.py` + `src/agents/launcher.py` (ссылки на артефакты)
- `usage.py`: `usage_comment` принимает опц. `repo/branch/work_item_id/pr_number`;
новая `artifact_links()` строит markdown-ссылки через `gitea_public_url`
(fallback gitea_url): reviewer→12-review.md, tester→13-test-report.md,
deployer→14-deploy-log.md, architect→06-adr/, developer→PR+branch.
Отсутствующий контекст/артефакт → ссылка пропускается, не падает. analyst не тронут.
- `launcher._post_usage_comments`: прокидывает repo/branch/work_item_id; для developer
резолвит номер открытого PR (`_open_pr_number`).
## Изменённые файлы
- `src/webhooks/gitea.py` — merge-gate на deploy
- `src/db.py` — миграция cache_creation_tokens
- `src/usage.py` — парсинг/формат/summary/artifact_links
- `src/plane_sync.py` — set_issue_done
- `src/stage_engine.py` — терминальный Plane Done на deploy→done
- `src/agents/launcher.py` — контекст ссылок + _open_pr_number
- `tests/test_usage.py` — +12 тестов (cache_creation, формат cached/без, summary, ссылки)
- `tests/test_webhooks.py` — +2 теста (merge на deploy→не done; merge не-deploy→done)
- `tests/test_stage_engine.py` — +2 теста (deploy→done форсит Plane Done; не-терминал не форсит)
## Проблемы и решения
- pytest нельзя запустить из репо напрямую (pycache принадлежит root, нет venv).
Решение: запуск внутри контейнера `orchestrator` из смонтированного `/repos/orchestrator`
с `PYTHONDONTWRITEBYTECODE=1 -p no:cacheprovider`.
- `.env.bak-*` файлы в репо untracked — НЕ добавлял в коммит (staged только 9 целевых файлов).
- Существующий тест `test_usage_comment_format` остался зелёным: при cache=0
`in_total == input_tokens`, формат `45.2k in` без скобки — обратная совместимость сохранена.
## Не сделано (по ТЗ)
- PR НЕ смержен — оставлен на ревью Стрим (PR #20, open).
- PLANE_STATES маппинг, HMAC, gitea_public_url конфиг, conftest.py, status-only verdict-модель — не тронуты.