diff --git a/memory/2026-06-05.md b/memory/2026-06-05.md index ecdf3ad..874f5bf 100644 --- a/memory/2026-06-05.md +++ b/memory/2026-06-05.md @@ -418,7 +418,8 @@ Dev (session orch9_docs_canon) отработал, я проверила не с - **БЛОКЕР 2 = ORCH-10 (в работе):** plane_sync.py хардкодит PLANE_STATES = UUID СТАТУСОВ ТОЛЬКО ENDURO. ORCH-проект имел 5 базовых статусов, нет стадийных. Слава: «сделать в ORCH такую же статусную модель как в ET, недостающие добавить». - **СДЕЛАЛА:** создала 9 недостающих статусов в ORCH-проекте через Plane API (Architecture/Development/Review/Testing/Approved/Rejected/Needs Input/In Review/Blocked) — теперь 14 шт, идентично ET по составу. UUID НОВЫЕ (свои у ORCH). - **Dev запущен** (orch10_states, session 305f824d): ТЗ `DEV_TASK_ORCH10_PER_PROJECT_STATES.md` — динамический резолвинг статусов по project_id (get_project_states + кэш + fallback _DEFAULT_STATES). КРИТИЧНО: webhook-сравнение in_progress резолвить по проекту (иначе ORCH-задача не стартует). Ветка feature/ORCH-10-per-project-states. - - Полные карты UUID обоих проектов — в ТЗ (сняты с прода). ORCH-16 ОСТАЛАСЬ в Backlog (мой PATCH state упал 400 — и хорошо, конвейер НЕ запущен). В описание ORCH-16 дописаны ответы на 2 вопроса (текст+ссылка+1-строка вердикт; один коммент на агента). + - **ORCH-10 ГОТОВ → ПРОВЕРЕНО МНОЙ лично (PR #33):** diff только plane_sync.py+webhooks/plane.py+tests, 342 passed (+23), резолвинг живой (ET→b873d9eb/3020bbb7, ORCH→e331bfb3/795cc32f, UUID разные), enduro не сломан. get_project_states(project_id)+кэш+fallback _DEFAULT_STATES. ЖДЁТ МЕРЖА PR #33. После мержа → ребилд прода → проверка в контейнере → ORCH-16 старт. + - Полные карты UUID обоих проектов — в ТЗ (сняты с прода). ORCH-37 заведена (гигиена статусов Plane, Backlog, id 9ccc5490). ORCH-16 ОСТАЛАСЬ в Backlog (мой PATCH state упал 400 — и хорошо, конвейер НЕ запущен). В описание ORCH-16 дописаны ответы на 2 вопроса (текст+ссылка+1-строка вердикт; один коммент на агента). - **ПОРЯДОК:** ORCH-10 (Dev) → ребилд прода → проверка резолвинга лично → ТОГДА ORCH-16 Backlog→In Progress (старт конвейера). - ORCH-16 = «Единообразные коммент-артефакты в Plane» id `2b80c58c-2a83-4ab0-aa69-b7f5d2f8c345`, мелкая, наполнена. Первая самодоработка-прогрев. diff --git a/tasks/orchestrator/reports/dev-2026-06-05-orch10-states.md b/tasks/orchestrator/reports/dev-2026-06-05-orch10-states.md new file mode 100644 index 0000000..1172529 --- /dev/null +++ b/tasks/orchestrator/reports/dev-2026-06-05-orch10-states.md @@ -0,0 +1,108 @@ +# Dev Report: ORCH-10 — per-project Plane state resolution +Дата: 2026-06-05 +Статус: DONE + +## Задача +Устранить блокер запуска ORCH-задач: `src/plane_sync.py` хардкодил глобальный `PLANE_STATES` с UUID статусов только enduro-проекта. Webhook-сравнение `new_state == PLANE_STATES["in_progress"]` совпадало только с ET UUID `b873d9eb`, ORCH UUID `e331bfb3` игнорировался — pipeline никогда не стартовал для ORCH-задач. + +## Сделано + +- [x] Создана ветка `feature/ORCH-10-per-project-states` из `origin/main` +- [x] Прочитан и изучен существующий код `src/plane_sync.py`, `src/webhooks/plane.py`, `src/projects.py` +- [x] Реализован `get_project_states(project_id)` — динамический резолвинг UUID по проекту через Plane API +- [x] Добавлен `_DEFAULT_STATES` (= прежний `PLANE_STATES`), `PLANE_STATES` оставлен как alias +- [x] Добавлен кэш `_STATES_CACHE` per project_id и функция `reload_project_states()` +- [x] Добавлен `stage_to_state(stage, project_id)` через `get_project_states` +- [x] `update_issue_state()` переключён на `stage_to_state()` вместо `STAGE_TO_STATE` dict +- [x] Все `set_issue_*()` функции резолвят UUID через `get_project_states(project_id)` +- [x] `webhooks/plane.py::handle_issue_updated()` — сравнение через `get_project_states(project_id)` вместо глобального `PLANE_STATES` +- [x] `webhooks/plane.py::start_pipeline()` QG-0 blocked path — `get_project_states(plane_project_id)["blocked"]` +- [x] Написаны 23 новых теста в `tests/test_orch10_states.py` +- [x] `pytest tests/ -q` — 342 passed (было 319, +23) +- [x] Коммит: `fix(plane): resolve issue states per-project instead of hardcoded enduro UUIDs (ORCH-10)` +- [x] Push ветки и создание PR #33 + +## Изменённые файлы + +| Файл | Что изменено | +|------|-------------| +| `src/plane_sync.py` | `_DEFAULT_STATES` + `PLANE_STATES` alias; `_STATES_CACHE`; `get_project_states()`; `reload_project_states()`; `_PLANE_NAME_TO_KEY`; `_STAGE_TO_STATE_KEY`; `stage_to_state()`; `update_issue_state()` → `stage_to_state()`; все `set_issue_*()` через `get_project_states()` | +| `src/webhooks/plane.py` | `handle_issue_updated()`: `proj_states = get_project_states(project_id)`, сравнение per-project; `start_pipeline()` QG-0: `get_project_states(plane_project_id)["blocked"]` | +| `tests/test_orch10_states.py` | 23 новых теста (NEW FILE) | + +## Результат + +### pytest +``` +342 passed, 4 warnings in 9.66s +``` +Было 319, стало 342 (+23 ORCH-10 теста). Ни один существующий тест не сломан. + +### git diff --name-status origin/main..feature/ORCH-10-per-project-states +``` +M src/plane_sync.py +M src/webhooks/plane.py +A tests/test_orch10_states.py +``` +Только разрешённые файлы. `qg/checks.py`, launcher, queue — не тронуты. + +### PR +**#33** — https://git.mva154.duckdns.org/admin/orchestrator/pulls/33 +Ветка: `feature/ORCH-10-per-project-states` → `main`. Мержить НЕ нужно (Стрим смержит вручную после ревью). + +## Проверка всех критериев ТЗ + +1. **pytest tests/ -q** — ✅ 342 passed (было 319) + +2. **get_project_states(ET) → ET-UUID; get_project_states(ORCH) → ORCH-UUID** — ✅ + - `test_get_project_states_enduro`: все 14 ET UUID совпадают + - `test_get_project_states_orchestrator`: все 14 ORCH UUID совпадают + - `test_get_project_states_et_in_progress_uuid`: ET `in_progress` = `b873d9eb-993c-48cd-97ac-99a9b1623967` + - `test_get_project_states_orch_in_progress_uuid`: ORCH `in_progress` = `e331bfb3-e17e-4699-ba48-4abb89c21b7b` + +3. **webhook in_progress распознаётся для обоих проектов** — ✅ + - `test_webhook_in_progress_et_starts_pipeline`: ET `b873d9eb` → `handle_status_start` called + - `test_webhook_in_progress_orch_starts_pipeline`: ORCH `e331bfb3` → `handle_status_start` called + - `test_webhook_et_in_progress_not_confused_with_orch`: ET UUID в ORCH-проекте НЕ триггерит + +4. **Fallback при недоступном API → _DEFAULT_STATES** — ✅ + - `test_get_project_states_api_error_fallback`: Exception → `_DEFAULT_STATES` + - `test_get_project_states_non_200_fallback`: HTTP 500 → `_DEFAULT_STATES` + - `test_get_project_states_empty_response_fallback`: пустой results → `_DEFAULT_STATES` + - `test_get_project_states_none_project_id_fallback`: None → `_DEFAULT_STATES` без API-вызова + +5. **git diff --name-status** — ✅ только `plane_sync.py`, `webhooks/plane.py`, `tests/` + +## Архитектура резолвинга/кэша + +``` +get_project_states(project_id: str) -> dict[str, str] +│ +├── if project_id in _STATES_CACHE -> return cached +│ +├── GET /api/v1/workspaces/{WORKSPACE}/projects/{project_id}/states/ +│ ├── success → map by _PLANE_NAME_TO_KEY, fill missing from _DEFAULT_STATES +│ │ → _STATES_CACHE[project_id] = resolved; return resolved +│ └── failure → log warning; return _DEFAULT_STATES (ET values, safe fallback) +│ +└── None project_id → _DEFAULT_STATES immediately + +stage_to_state(stage, project_id) -> str | None +└── _STAGE_TO_STATE_KEY[stage] -> logical key + └── get_project_states(project_id)[key] -> UUID +``` + +**Кэш**: `_STATES_CACHE: dict[str, dict[str,str]]` — per project_id, не протухает (процесс перезапускает). `reload_project_states(project_id=None)` — для тестов и ручного сброса. + +**Backward compat**: `PLANE_STATES` = `_DEFAULT_STATES` (alias). `STAGE_TO_STATE` оставлен как статический dict на ET-значениях (для тестов). `update_issue_state()` теперь вызывает `stage_to_state()` вместо него. + +## Проблемы и решения + +**Проблема**: `$()` в bash-heredoc-е SSH интерпретировался шеллом → bash command substitution error. +**Решение**: файлы передавались через `base64 | ssh 'base64 -d > file'` — без heredoc. + +**Проблема**: `git commit -m` с Python-кодом в строке вызывал bash syntax error. +**Решение**: многострочный `-m` отдельной строкой через SSH; bash-парсер затронул только переменные типа `$()` — commit прошёл корректно. + +## Следующий шаг +Отправить на ревью → Стрим мержит PR #33 → ребилд docker-образа → ручная проверка на проде.