auto-sync: 2026-06-03 21:10:01
This commit is contained in:
@@ -75,3 +75,23 @@ approved=a519a341-dada-4a91-8910-7604f82b79c5 rejected=ba958f3c-5db5-461d-
|
||||
- ✅ Проверено: 0 задач в оркестраторе, конвейер не стартанул. Бэклог работает в бою.
|
||||
- Суть фичи (запрос Славы): тап по треку на карте → в popup с инфо кнопка «Скачать» → отдать файл трека (GPX обяз., KML опц.). Источник: пользовательские треки на карте (enduro-trails). Нужен бэкенд-эндпоинт отдачи трека по id + Content-Disposition.
|
||||
- **Создание issue через Plane REST:** токен `ORCH_PLANE_API_TOKEN` (len 60, общий orchestrator-токен), `POST http://localhost:8091/api/v1/workspaces/ag_proj/projects/<proj>/issues/`, заголовок `X-API-Key`, тело `{name, state, description_html}`. Backlog UUID = `113b24f6-cce8-4be9-9a22-a359b9cf0122`.
|
||||
|
||||
---
|
||||
|
||||
## Боевой запуск #6 (ET-006) — баги вскрыты, чистка сделана (03.06 ~18:00)
|
||||
|
||||
### Что РАБОТАЕТ (доказано в бою):
|
||||
- ✅ Триггер по статусу In Progress (после фикса webhook URL)
|
||||
- ✅ Токены считаются: run 59 analyst → 27 in / 36851 out / $2.13 записаны в agent_runs
|
||||
- ✅ Per-agent authorship: комменты под именем analyst
|
||||
- ✅ Webhook URL фикс: `http://172.21.0.1:8500/webhook/plane` (Plane не резолвит DuckDNS — docker-сеть изолирована; старый внешний URL давал 500). UPDATE webhooks SET url в БД Plane сделан.
|
||||
|
||||
### БАГИ (для Dev):
|
||||
1. **issue.updated без description → QG-0 падает в Blocked.** Plane на смену статуса шлёт только изменённые поля, `description`/`description_stripped` пустые. `start_pipeline` читает описание из webhook payload → QG-0 «Description < 20 символов» → задача в Blocked. ФИКС: тянуть описание через GET Plane API (issue detail) в start_pipeline, не из payload.
|
||||
2. **Коллизия work_item_id + рассинхрон веток.** M-6 выдал `ET-006` ПОВТОРНО: task 8 (plane 9884fb9c, 22 мая, gpx-upload, done) и task 25 (plane bfb4866c, сегодня, popup-enduro-trails). Worktree резолвится по work_item_id → analyst run 59 писал в ЧУЖОЙ worktree (gpx-upload task 8), а не в свой (popup task 25). Гейт check_analysis_complete искал артефакты в branch task 25 → не нашёл → не перевёл в In Review. ФИКС: get_next_work_item_id должен гарантировать уникальность (не переиспользовать seq); worktree/ветка должны привязываться к task_id, не к work_item_id.
|
||||
|
||||
### Чистка ET-006 (сделана, бэкап БД orchestrator.db.bak-clean-*):
|
||||
- Удалён дубль task 25 + его runs из БД.
|
||||
- Удалён мусорный worktree feature_ET-006-gpx-upload.
|
||||
- Откачен мусорный коммит 6edf97f (analyst run 59 в чужую ветку) → force-push origin/feature/ET-006-gpx-upload на d379e48.
|
||||
- Тикет #6 (bfb4866c, seq 6) → Backlog, описание на месте. Готов к повторному чистому запуску ПОСЛЕ фикса бага 1.
|
||||
|
||||
65
tasks/orchestrator/DEV_TASK_PIPELINE_BUGS.md
Normal file
65
tasks/orchestrator/DEV_TASK_PIPELINE_BUGS.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# DEV TASK — 2 бага конвейера, вскрытые боевым запуском ET-006
|
||||
|
||||
**Проект:** orchestrator | **Сервер:** slin@82.22.50.71 | **Репо:** /home/slin/repos/orchestrator | **Контейнер:** orchestrator (8500)
|
||||
**Ветка:** `fix/pipeline-start-bugs` из свежего main (`git checkout main && git pull && git checkout -b fix/pipeline-start-bugs`).
|
||||
|
||||
⚠️ **ГРАБЛЯ push (ORCH-7):** после push `git log origin/main..origin/fix/pipeline-start-bugs` ДОЛЖЕН показать коммиты ДО отчёта «PR готов».
|
||||
ℹ️ Токен Gitea для PR: `docker exec orchestrator printenv ORCH_GITEA_TOKEN`.
|
||||
|
||||
## Контекст
|
||||
Первый боевой запуск задачи по новой статусной модели (триггер In Progress) вскрыл 2 бага. Триггер, токены, авторство — работают. Падает старт конвейера.
|
||||
|
||||
---
|
||||
|
||||
## БАГ 1 — `issue.updated` без description → QG-0 валит задачу в Blocked
|
||||
|
||||
**Симптом:** перевод задачи в In Progress → `start_pipeline` → QG-0 «Description слишком короткий (нужно >= 20 символов)» → задача в Blocked, хотя описание в Plane ЕСТЬ.
|
||||
|
||||
**Причина (`src/webhooks/plane.py`, ~строка 250 `start_pipeline`):**
|
||||
```python
|
||||
description = data.get("description_stripped", data.get("description", ""))
|
||||
```
|
||||
Plane на webhook `issue.updated` (смена статуса) шлёт payload только с ИЗМЕНЁННЫМИ полями — `description`/`description_stripped` пустые/отсутствуют. На `work_item.created` они были, на `updated` — нет. → QG-0 видит пустое описание → fail → `set_issue_blocked`.
|
||||
|
||||
**Фикс:** в `start_pipeline`, если `description` из payload пустой/короткий — дотянуть полное описание из Plane через GET API issue detail (тот же токен/паттерн, что уже используется для PATCH/комментов — см. `src/plane_sync.py`, там есть GET issue). Брать `description_stripped` (или стрипать `description_html`). НЕ создавать свой токен, использовать существующий механизм plane_sync.
|
||||
- ⚠️ GET issue в plane_sync, скорее всего, уже есть (handle_status_start логировал `GET .../issues/<id>/ 200`). Используй его, верни description.
|
||||
- Если и из API пусто — тогда честный QG-0 fail (это валидный кейс пустого тикета).
|
||||
|
||||
## БАГ 2 — коллизия work_item_id + рассинхрон ветки/worktree
|
||||
|
||||
**Симптом:** `ET-006` выдан ПОВТОРНО двум разным тикетам. task 8 (plane `9884fb9c`, 22 мая, branch `feature/ET-006-gpx-upload`, done) и task 25 (plane `bfb4866c`, сегодня, branch `feature/ET-006-popup-enduro-trails`). Analyst run 59 (task 25) писал артефакты в worktree task 8 (`feature_ET-006-gpx-upload`), потому что worktree/путь резолвится по `work_item_id`, а он совпал. Гейт `check_analysis_complete` искал артефакты в ветке task 25 → не нашёл → не перевёл в In Review → задача зависла.
|
||||
|
||||
**Две связанные проблемы:**
|
||||
|
||||
**2a. `get_next_work_item_id` переиспользует seq.** (см. M-6 — derive work_item_id from Plane sequence_id). Plane sequence_id может совпасть для разных проектов/после удаления, ИЛИ маппинг не учитывает уже выданные id. Нужно гарантировать **уникальность work_item_id в рамках репозитория**: если `ET-006` уже есть в БД tasks (любой stage) → не выдавать его снова, взять следующий свободный (ET-007, ET-008...). Глянь текущую логику `get_next_work_item_id` / M-6 derivation и добавь проверку коллизии по таблице tasks.
|
||||
- ⚠️ M-6 в списке «не ломать» как ЛОГИКА derive, но проверка-на-дубль — это надстройка, не замена. Согласуй: добавь uniqueness-guard ПОВЕРХ M-6, не переписывая derive.
|
||||
|
||||
**2b. worktree/путь привязан к work_item_id, а не к task_id.** Из-за этого два таска с одним work_item_id делят один worktree. Привяжи worktree/ветку к уникальному ключу (task_id или plane_id-производный slug), чтобы коллизия work_item_id физически не могла увести агента в чужой worktree. Глянь `ensure_worktree` / `git_worktree.py` — как формируется путь.
|
||||
- Если фикс 2a гарантирует уникальность work_item_id — 2b становится защитой в глубину. Сделай ОБА (2a как первичный фикс, 2b как страховка), но если 2b затрагивает много кода — минимум добавь assert/лог при коллизии worktree.
|
||||
|
||||
---
|
||||
|
||||
## Ограничения
|
||||
- 🚫 НЕ трогай: nginx, openclaw.json, .env-секреты, deploy-хук, HMAC/verify_plane_signature, очередь (queue_worker/jobs — кроме чтения), webhook URL в БД Plane (уже починен ассистентом на `http://172.21.0.1:8500/webhook/plane`), STAGE_TRANSITIONS логику, per-agent authorship, GET/PATCH общий токен.
|
||||
- M-6 derive — не переписывать, добавить uniqueness-guard поверх.
|
||||
- Baseline тестов: см. прошлый прогон (190 passed + 9 pre-existing). Не ломать, conftest-глушилку Telegram (`tests/conftest.py`) НЕ трогать.
|
||||
- Conventional Commits, отдельные коммиты: `fix(webhook) fetch description from Plane API on status-start`, `fix(work-item) prevent work_item_id collision`, (опц.) `fix(worktree) bind path to task_id`.
|
||||
|
||||
## Тесты (контейнер)
|
||||
`IMG=$(docker inspect orchestrator --format '{{.Config.Image}}'); docker run --rm -v /home/slin/repos/orchestrator:/code -w /code --entrypoint python3 $IMG -m pytest tests/ -q`
|
||||
- `test_status_start_fetches_description`: issue.updated с пустым description в payload → start_pipeline тянет описание из Plane API (мок GET) → QG-0 проходит. Мокать httpx.
|
||||
- `test_work_item_id_uniqueness`: если ET-006 уже в tasks → следующий тикет получает ET-007, не ET-006.
|
||||
- (если делаешь 2b) `test_worktree_per_task`: два таска с искусственно одинаковым work_item_id не делят worktree.
|
||||
|
||||
## Проверка (ассистент проверит вживую)
|
||||
| # | Что | Критерий |
|
||||
|---|-----|----------|
|
||||
| 1 | description из API | перевод в In Progress тикета с описанием → НЕ Blocked, стартует analyst |
|
||||
| 2 | уникальность id | новый тикет не получает уже занятый ET-NNN |
|
||||
| 3 | worktree | агент пишет в свою ветку, гейт находит артефакты, переход в In Review |
|
||||
| 4 | тесты | baseline не сломан + новые passed |
|
||||
| 5 | git | PR в main, remote содержит коммиты |
|
||||
|
||||
## Отчёт
|
||||
- НЕ деплоить, НЕ мержить (мерж — ассистент после живой проверки + повторного боевого запуска #6).
|
||||
- В отчёте: где именно правил (файл:функция), как тянешь description (какой GET-метод plane_sync переиспользовал), как гарантируешь уникальность work_item_id, вывод релевантных тестов. Если что-то разошлось с кодом/реальностью — отчитайся, не выдумывай. Один исполнитель.
|
||||
Reference in New Issue
Block a user