auto-sync: 2026-06-04 13:20:01
This commit is contained in:
92
tasks/orchestrator/DEV_TASK_TRACKER_EDIT_FIX.md
Normal file
92
tasks/orchestrator/DEV_TASK_TRACKER_EDIT_FIX.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# 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):
|
||||
```python
|
||||
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, краткое описание фикса.
|
||||
Reference in New Issue
Block a user