Files
wiki/tasks/orchestrator/DEV_TASK_TRACKER_EDIT_FIX.md
2026-06-04 13:20:10 +03:00

7.6 KiB
Raw Permalink Blame History

DEV TASK: orchestrator — фикс трекера (дубли сообщений + отставание)

Репо: slin@82.22.50.71:/home/slin/repos/orchestrator (пароль motoZ@yaz2010). Push в main запрещён (pre-receive hook) → только PR в Gitea. Gitea токен: docker exec orchestrator printenv ORCH_GITEA_TOKEN. Одна ветка fix/tracker-edit-not-modified от актуального main, один PR. Baseline pytest на этом проде: 259 passed + 9 failed (9 = off-limits HMAC/401, НЕ чинить).


КОНТЕКСТ / БАГ (подтверждён на живой задаче ET-013)

Живой Telegram-трекер (PR #21, src/notifications.py) на боевом прогоне ET-013 повёл себя так:

  • За прогон: 21 editMessageText, но 7 sendMessage — трекер 7 раз прислал НОВОЕ сообщение вместо редактирования одного. Слава жалуется: «сообщение не одно, а при изменении приходит новое».
  • Часть editMessageText падает с HTTP 400 Bad Request. Это НЕ сбой Telegram — это ответ "message is not modified" (текст трекера не изменился между переходами, напр. повторный цикл review→development→review рисует ту же строку).

Корень (точно)

edit_telegram (notifications.py ~76-97):

data = resp.json()
return bool(data.get("ok"))   # 400 "not modified" -> ok:false -> возвращает False

Возвращает False на ЛЮБОМ 400. А update_task_tracker (~374-392) трактует False как «edit не удался» → вызывает send_telegram(...) (новое сообщение) и перезаписывает tracker_message_id. Итог: дубли + старый трекер «осиротевает» и больше не обновляется (отстаёт от реальности — застрял на снимке Review, хотя был ещё цикл dev→review).


ЧТО СДЕЛАТЬ (3 правки)

Правка 1 — edit_telegram: "not modified" = успех, НЕ дубль

В edit_telegram разобрать тело ответа Telegram. Если ok:false, но description содержит "message is not modified" (или "exactly the same") — вернуть True (редактировать нечего, всё в порядке, дубль НЕ нужен). Логировать на DEBUG, не на WARNING.

Правка 2 — fallback на новое сообщение ТОЛЬКО при реально пропавшем сообщении

Сейчас update_task_tracker: if edit_telegram(...) == False -> send_telegram (новое). Изменить логику так, чтобы новое сообщение слалось только когда исходное реально нельзя редактировать:

  • "message to edit not found" / "message can't be edited" / "MESSAGE_ID_INVALID" → сообщение пропало/удалено → fallback на новое (как сейчас), обновить tracker_message_id.
  • Любой другой провал edit (сеть, таймаут, временный 5xx, неизвестный 400) → НЕ слать новое, просто залогировать и выйти (трекер дорисуется на следующем переходе). Плодить дубли на временных ошибках нельзя.

Реализация: пусть edit_telegram возвращает не голый bool, а различимый результат — например enum/строку ("ok" | "not_modified" | "gone" | "failed"), либо tuple (ok: bool, gone: bool). update_task_tracker шлёт новое сообщение только при gone. "ok" и "not_modified" → ничего не делать. "failed" → лог + выход без нового сообщения. Никогда не падать (текущий стиль fire-and-forget сохранить).

Правка 3 — повторные циклы стадии видимы (чтобы текст реально менялся)

Чтобы трекер не «застывал» на повторных проходах одной стадии (review↔development), у АКТИВНОЙ стадии в render_task_tracker показывать признак повторного захода/попытки, например: 🔄 Review · попытка 2 … идёт (номер попытки = число записей agent_runs этого агента по задаче, или attempts из jobs если доступно). Завершённые стадии () НЕ трогать — формат финальной строки прежний. Это и делает текст уникальным между циклами (меньше not-modified), и честно показывает Славе, что идёт переработка.

  • Если данных о попытке нет — рисовать как раньше (🔄 Review … идёт), без «попытка N».
  • Считать попытку аккуратно: повторный запуск ТОЙ ЖЕ стадии (например 2-й review), а не суммарно все агенты. Бери число прогонов агента этой стадии для текущей задачи.

НЕ ТРОГАТЬ

  • Формат завершённых строк (✅ Stage Nм · in↓/out↑ · $ · model), блок Итого, «Ревью БРД», short_model_name, миграции, usage_comment/Plane-комменты, PLANE_STATES, HMAC, queue, launcher deployer-guard, отдельные алерты (approve/deploy-fail/agent-fail/error).
  • disable_notification трекера (всегда silent).

ТЕСТЫ (обязательно, мокать httpx)

  • edit_telegram: ответ 400 "message is not modified" → трактуется как успех (не gone, не дубль).
  • edit_telegram: 400 "message to edit not found" → gone.
  • edit_telegram: 200 ok → ok.
  • edit_telegram: таймаут/5xx → failed (не gone).
  • update_task_tracker: edit not_modified → НЕ зовёт send_telegram (нет дубля).
  • update_task_tracker: edit gone → зовёт send_telegram + обновляет tracker_message_id.
  • update_task_tracker: edit failed (временная) → НЕ зовёт send_telegram.
  • render_task_tracker: повторный заход стадии (2 review-рана) → попытка 2 в активной строке; один заход → без «попытка N»; завершённые строки без изменений.
  • Полный pytest зелёный кроме тех же 9 off-limits.

СДАЧА

  • Ветка fix/tracker-edit-not-modified, один PR в Gitea. НЕ мержить сам — на ревью Стрим.
  • Отчёт: tasks/orchestrator/reports/dev-2026-06-04-tracker-edit-fix.md — commit-хеш, PR-номер, вывод pytest, что изменилось в каждой из 3 правок, до/после по логике (когда теперь шлётся новое сообщение, а когда нет).
  • Сообщить: PR-номер, результат pytest, краткое описание фикса.