auto-sync: 2026-06-04 11:20:01
This commit is contained in:
@@ -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-модель — не тронуты.
|
||||
Reference in New Issue
Block a user