diff --git a/memory/2026-06-03.md b/memory/2026-06-03.md index 83fded4..18af101 100644 --- a/memory/2026-06-03.md +++ b/memory/2026-06-03.md @@ -90,3 +90,44 @@ Dev **запаниковал** на старте orch1b: «параллельн - Деплой: `docker compose up -d --build && sleep 6 && curl -s :8500/health && curl -s :8500/queue` - Тесты в контейнере: `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` - ⚠️ root-файлы на хосте — через `docker exec orchestrator rm -rf` (не sudo, пароль не тот) + + +--- + +## Аудит 02.06 ПОЛНОСТЬЮ ЗАКРЫТ (финал дня 03.06) + +### L-1 / L-2 / L-3 — ЗАМЕРЖЕНО (PR #7 `be27f506`) +- Один компактный PR, 3 коммита: `48b7707` docs(stages) L-1, `0653c24` feat(launcher) L-2, `8f11971` refactor(plane_sync) L-3. +- **L-1:** шапка `src/stages.py:8` врала «when entering the NEXT stage» (этот нейминг породил баг ORCH-4) → исправлена на «advancing FROM this stage (NOT the next stage's agent)». Только комментарий. +- **L-2:** `prune_run_logs(runs_dir, keep_days=30, keep_max=500, active_paths=None)` в `launcher.py` — чистит `*.log` старше keep_days ИЛИ сверх keep_max свежих; не трогает не-.log, поддиректории, активный лог. Вызов best-effort в `lifespan` (try/except + warning, не роняет app). Параметры: env `ORCH_LOG_KEEP_DAYS`/`ORCH_LOG_KEEP_MAX`, дефолты в config.py. +6 тестов `tests/test_log_rotation.py`. +- **L-3:** эмодзи-литералы → `EMOJI_STAGE`/`EMOJI_QG_FAIL`/`EMOJI_DONE` в `plane_sync.py`. Вывод байт-в-байт прежний. (стр.242 стала f-строкой ради подстановки — текст тот же.) +- Тесты: 145 → **151 passed** (+6), 9 = baseline 401. +- **L-4 СНЯТ:** мусорной папки `{src` уже нет. **L-5 СНЯТ:** `tests/test_launcher.py` (18 тестов) уже существует — долг закрыт по ходу ORCH-1b/2/4. Аудит 02.06 отстал от кода. + +### M-6 — ЗАМЕРЖЕНО (PR #8 `12e2691a`), Слава отметил как ВАЖНУЮ +- `feat(webhook): derive work_item_id from Plane sequence_id` `1d978ca` + `fix(plane_sync): drop hardcoded ET- prefix` `c431a3d`. +- **Суть:** `work_item_id` теперь = Plane `sequence_id` (источник правды), а не `max(tasks)+1`. Helper `fetch_issue_sequence_id(issue_id, project_id)` в `plane_sync.py` — GET `…/projects/{pid}/issues/{uuid}/` (⚠️ **trailing slash обязателен**, без него 301), `sequence_id` = top-level int, timeout=10, try/except → None (не кидает). +- **Fallback автономности:** Plane down / seq=None → старый `get_next_work_item_id` + warning. Task создаётся при любом исходе, конвейер не встаёт. `get_next_work_item_id` ОСТАВЛЕН как fallback. +- **Бонус-фикс:** `find_issue_id` хардкодил `f"ET-{seq:03d}"` → сломан для ORCH-префикса (ORCH-6). Убрано, матч по числу из `rsplit("-",1)`, обобщено на любой префикс. +- Живая иллюстрация рассинхрона: `ET-010` (`f9009756…`) в Plane = **404** — старый счётчик такие дыры игнорировал. +- Тесты: 151 → **158 passed** (+7 `tests/test_m6_sequence.py`), 9 = baseline. +- Отчёт: `tasks/orchestrator/reports/dev-2026-06-03-orch-m6-plane-sequence.md`. + +### ⚠️ ГОНКА ВЕТОК — урок (важно для будущих параллельных задач) +- L1L2L3 и M-6 — оба правят orchestrator-репо из ОДНОЙ рабочей копии `/home/slin/repos/orchestrator`. Запуск двух Dev одновременно = реальная драка за git-состояние (НЕ ложная паника). +- **Правило:** при работе двух задач в одном репо — сначала смержить+освободить ветку первой, ТОЛЬКО потом запускать вторую из чистого main. Так и сделала: PR #7 мерж → потом запуск M-6. + +### 🔍 Три одинаковых сообщения (🔄 ET-100) — РАЗГАДКА +- **НЕ оркестратор, НЕ дубль конвейера (НЕ класс ET-009).** Орк за сутки слал в Telegram **0 сообщений** (проверено по логам), в конвейере 1 задача, breaker closed. +- Причина: **дубли completion-событий субагента** (Dev) — повадка доставки OpenClaw, событие «субагент завершил» приходит по нескольку раз, родитель просыпается на каждой доставке → отклик протекает наружу. +- Лечение: глушу через NO_REPLY, но 1-2 иногда проскакивают. Риска для данных/конвейера НОЛЬ. Если будет бесить Славу — копнуть жёсткий дедуп на уровне обработчика. + +### Токен Gitea — РАЗРЕШЕНО +- Подтверждено: мерж M-6 прошёл рабочим токеном (брала из env контейнера по заметке Dev). `.env` на сервере содержит устаревший `ORCH_GITEA_TOKEN` (28 симв, 401), рабочий (40 симв) — `docker exec orchestrator printenv | grep -i gitea`. **Славе на заметку:** синхронизировать `.env`. + +### ИТОГ +- **Весь бэклог orchestrator + весь аудит 02.06 закрыты.** В main: ORCH-1/1b/2/4/5/6/7 + L1L2L3 + M-6. ORCH-8 отменена, L-4/L-5 сняты как уже сделанные. +- Прод после M-6: main HEAD `12e2691`, health ok, breaker closed. +- Merge-commits финала: PR #7 `be27f506` (L1L2L3), PR #8 `12e2691a` (M-6). +- ТЗ-файлы: `DEV_TASK_ORCH_CLEANUP_L1L2L3.md`, `DEV_TASK_ORCH_M6_PLANE_SEQUENCE.md`. +- ⏳ Открыто (НЕ срочно): прод-применение хука enduro-trails (swap `.new`→живой) — ждёт ОК Славы; бэкап `enduro-deploy-hook.sh.bak-1780468526`. diff --git a/tasks/orchestrator/reports/dev-2026-06-03-orch-m6-plane-sequence.md b/tasks/orchestrator/reports/dev-2026-06-03-orch-m6-plane-sequence.md new file mode 100644 index 0000000..b66ce93 --- /dev/null +++ b/tasks/orchestrator/reports/dev-2026-06-03-orch-m6-plane-sequence.md @@ -0,0 +1,55 @@ +# Dev Report: M-6 — work_item_id из Plane sequence_id +Дата: 2026-06-03 +Статус: DONE (запушено, PR #8 открыт; НЕ мержено — мерж за Стримом после живой проверки) + +## Задача +Источник правды для номера work_item_id — Plane `sequence_id`, маппить в `-NNN`. +Fallback на `get_next_work_item_id` (DB-инкремент) если Plane недоступен (автономность > точность). +Бонус: убрать хардкод `ET-` в `find_issue_id`. + +## Разведка (живой GET к Plane) — КЛЮЧЕВОЕ +- Endpoint одиночного issue: `{PLANE_BASE}/workspaces/{ws}/projects/{pid}/issues/{uuid}/` + — **trailing slash ОБЯЗАТЕЛЕН**: без него 301 redirect (не JSON). +- Успешный GET (issue `64e98247-...`, seq=5) → **200**, `sequence_id` — **top-level int** (`5`), + поле называется именно `sequence_id`. Формат helper-шаблона из ТЗ совпал 1:1. +- GET по `f9009756-...` (ET-010) → **404** с `{"error": ...}` JSON → `.get("sequence_id")` = None + → helper вернёт None. Этот issue реально отсутствует в Plane — живая иллюстрация рассинхрона, + ради которого делается M-6. +- Списочный endpoint `/issues/` → 200, `results[]` с `sequence_id` (int) на каждом issue. +- Вывод: шаблон helper-а из ТЗ корректен, использован как есть (trailing slash уже был). + +## Сделано +- [x] Разведка живым GET — формат подтверждён +- [x] `plane_sync.py`: `fetch_issue_sequence_id(issue_id, project_id) -> int|None` (timeout=10, try/except, не кидает) +- [x] `webhooks/plane.py` `handle_work_item_created`: seq→`f"{prefix}-{seq:03d}"`, None→fallback DB + logger.warning +- [x] `plane_sync.py` `find_issue_id`: убран хардкод `ET-`, матч по sequence_id из суффикса work_item_id (rsplit("-",1)), обобщён на любой префикс +- [x] `tests/test_m6_sequence.py` — 7 тестов +- [x] 2 коммита (Conventional Commits), push, проверка remote, PR #8 + +## Изменённые файлы +- `src/plane_sync.py` — +helper `fetch_issue_sequence_id`; find_issue_id без ET-хардкода (матч по числу из суффикса) +- `src/webhooks/plane.py` — work_item_id из Plane seq + fallback на get_next_work_item_id +- `tests/test_m6_sequence.py` — новый, 7 тестов + +## Результат +- Новые тесты: **7 passed** (helper int/None×2/missing-field; created→ORCH-007 по seq=7; created→fallback ORCH-099 при seq=None; find_issue_id ORCH-005 по seq=5; ET-002 по seq=2). +- Полный прогон в контейнере (IMG=orchestrator-orchestrator): + **158 passed, 9 failed** — 9 = pre-existing 401/signature в test_webhooks.py (baseline 151 + 7 новых = 158). M-6 не трогает HMAC; 9 не починены и не сломаны (как требует ТЗ). +- Fallback-путь: при seq=None task всё равно создаётся (тест `test_created_falls_back_to_db_when_plane_down` это assert-ит) → автономность сохранена. + +## Git +- Ветка `feature/ORCH-M6-plane-sequence` из свежего main (be27f50). +- Коммиты: + - `1d978ca feat(webhook): derive work_item_id from Plane sequence_id (M-6)` + - `c431a3d fix(plane_sync): drop hardcoded ET- prefix in find_issue_id (M-6)` +- `git log origin/main..origin/feature/ORCH-M6-plane-sequence` → оба коммита присутствуют на remote (грабля ORCH-7 проверена). +- PR #8: https://git.mva154.duckdns.org/admin/orchestrator/pulls/8 (head→base = feature→main). +- Токен: рабочий из env контейнера (`ORCH_GITEA_TOKEN=c81227...`), совпал с embedded в origin URL. + +## Проблемы и решения +- Remote-only репо (нет локального доступа) → редактировал через Python-скрипты по SSH; heredoc с Python мангал shell → решил через `cat > file` (base64-free, через stdin). +- Коммит-сплит: оба изменения в plane_sync.py → разнёс `git add -p` (printf "y\nn\n") — feature-хелпер в коммит 1, find_issue_id-фикс в коммит 2. + +## Ограничения соблюдены +Не трогал: nginx/openclaw.json/.env/deploy-хук/is_active/ORCH-1..7/stage_engine/STAGE_TRANSITIONS/HMAC/очередь. +`get_next_work_item_id` оставлен как fallback. НЕ деплоил, НЕ мержил.