Files
wiki/tasks/orchestrator/reports/dev-2026-06-04-observability-fixes.md
2026-06-04 11:20:05 +03:00

6.4 KiB
Raw Blame History

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: #20admin/orchestrator#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-модель — не тронуты.