Files
orchestrator/docs/work-items/ORCH-026/02-trz.md

135 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 02-ТЗ — Управление зависимостями задач (B ждёт A) в очереди
**Work Item:** ORCH-026 · **Repo:** orchestrator · **Стадия:** analysis
> ТЗ фиксирует ТРЕБОВАНИЯ к изменениям (модули, контракты, артефакты). Конкретный механизм
> сериализации и место хранения связей — решение архитектора (ADR в `06-adr/`); ниже отмечены
> как «КАНДИДАТ / решает архитектор». Аналитик не предлагает архитектуру.
---
## 1. Задействованные модули `src/`
| Модуль | Роль в задаче | Уровень |
|--------|---------------|---------|
| `src/queue_worker.py` | Планировщик: `_drain_once` / `claim_next_job` — точка учёта зависимостей и сериализации при выборе job. | A + B |
| `src/db.py` | Очередь `jobs` / `tasks`; `claim_next_job`, `enqueue_job`, `count_running_jobs`. Кандидат на хранение связей и блокировки claim. | A + B |
| `src/merge_gate.py` | merge-lease (ORCH-065), `branch_is_behind_main` / `auto_rebase_onto_main` (ORCH-043) — опора для proactive pre-merge rebase и расширения окна сериализации. | A |
| `src/qg/checks.py` | `check_branch_mergeable` (под-гейт ребра `deploy-staging → deploy`) — точка форсированного pre-merge rebase. | A |
| `src/stage_engine.py` | `advance_stage` — врезки гейтов; точка интеграции сериализации/верификации. | A |
| `src/webhooks/plane.py` | `handle_work_item_created` / `start_pipeline` — приём задачи; точка чтения relations (если источник — Plane). | B |
| `src/plane_sync.py` | `set_issue_blocked`, `get_project_states` (`blocked`/`needs_input`), relations API. | B |
| `src/notifications.py` | live-карточка: индикация `Blocked` / «ждёт ORCH-NNN». | B |
| `src/config.py` | Новые kill-switch + scope-настройки (паттерн `*_enabled` / `*_repos`). | A + B |
| `src/reconciler.py` / `src/job_reaper.py` | Не ломать: skip заблокированных задач (как уже делается для Blocked/Needs-Input, ORCH-060/068); реклейм ресурсов сериализации. | A + B |
---
## 2. Требования к изменениям — Уровень A (сериализация merge/деплоя)
### 2.1 Proactive pre-merge rebase (A-2)
- На ребре `deploy-staging → deploy`, ДО фактического merge (в составе `check_branch_mergeable`
или соседнего под-гейта), ветка задачи **всегда** догоняется на свежий `origin/main`
**не только при `branch_is_behind_main`/конфликте**.
- Переиспользовать `merge_gate.auto_rebase_onto_main` (rebase + `push --force-with-lease`
ТОЛЬКО ветки задачи). Текстовый конфликт → существующий контракт: `rebase --abort` → откат на
`development` (как ORCH-043).
- **Инвариант:** никаких push/force-push в `main`.
### 2.2 Расширение окна merge-lease (A-1, A-3, A-4)
- **КАНДИДАТ (решает архитектор):** держать per-repo merge-lease (ORCH-065) не только «на
момент merge», а на окно **«merge → main-updated»** (для self — до подтверждения
`merged_to_main: true` / `done`), чтобы B не дошла до своего merge, пока A не в `main`.
- Acquire — **неблокирующий** (как сейчас): занято → **defer** задачи B через
`enqueue_job(available_at_delay_s=...)`, bounded бюджет (анти-livelock; ср.
`merge_defer_max_attempts`). Откат на `development` НЕ применять для defer.
- Release — holder-aware (как `release_merge_lease`), на merged-вебхуке / `deploy→done` /
откате / по проактивному реклейму (ORCH-065 `reclaim_stale_lease`).
- Сериализация **строго per-repo** (`.merge-lease-<repo>.json`) — кросс-репо параллелизм не
затрагивается (A-3).
### 2.3 Условность и безопасность (A-5)
- Реально только для применимых репо: kill-switch + CSV-scope (паттерн `merge_gate_repos` /
`merge_verify_repos`; пусто → только self-hosting `orchestrator`).
- `STAGE_TRANSITIONS`, `Confirm Deploy` (ORCH-059), exit-коды deploy-хука, БАГ-8,
terminal-sync — **без изменений**.
- Контракт **never-raise** для всех новых функций (как соседи в `merge_gate.py`).
---
## 3. Требования к изменениям — Уровень B (декларативные зависимости)
### 3.1 Декларация связи (B-1)
- **КАНДИДАТ хранения (решает архитектор, см. BRD §4.1):**
- вариант Plane relations: читать `blocked-by` через Plane API в `handle_work_item_created`;
- вариант БД: новая таблица `job_deps(task_id, depends_on_task_id)` или поле в `tasks`
(idempotent `_ensure_column` миграция, как ORCH-065 `jobs.pid`);
- гибрид: Plane — декларация, БД — кэш для планировщика (offline-устойчивость).
- Миграция БД (если выбран вариант с таблицей/колонкой) — **только аддитивная**
(`CREATE TABLE IF NOT EXISTS` / `_ensure_column`), безопасная на живой прод-БД с общими
данными enduro-trails.
### 3.2 Гейт планировщика (B-2)
- При выборе job (`claim_next_job` / `_drain_once`) задача с незавершёнными depends-on
**не клеймится** (аналог `available_at`-gate): пропускается до тех пор, пока все depends-on
не `done`. Не должна занимать слот `max_concurrency`.
- Реализация — **leaf-функция** с чистой логикой «готова ли задача к запуску» (тестируемо
юнитами, never-raise), по образцу `staging_verdict.py` / `post_deploy.py`.
### 3.3 Защита от дедлоков (B-3)
- Детектор циклов в графе depends-on (DFS/обнаружение цикла) — чистая функция, юнит-тестируемая.
- Цикл → задача(и) НЕ запускается молча: `set_issue_blocked` + alert (Telegram/Plane) с
указанием цикла. Не блокировать поток других задач.
### 3.4 Видимость (B-4)
- Заблокированная задача: Plane-статус `Blocked` (`set_issue_blocked`) и/или строка ожидания в
Telegram-карточке («⏳ ждёт ORCH-NNN»). Использовать существующий механизм карточки
(`notifications.update_task_tracker`), контракт never-raise / silent.
- `reconciler` F-1 уже пропускает Blocked/Needs-Input (ORCH-060/068) — убедиться, что новые
заблокированные-по-зависимости задачи тоже пропускаются (не «разблокируются» ошибочно).
---
## 4. Изменения API (endpoints)
- **Новые HTTP endpoints не требуются.**
- **Наблюдаемость:** расширить снимок `GET /queue` блоком о зависимостях/сериализации
(по образцу блоков `reconcile` / `reaper` / `post_deploy` / `merge_verify`): кол-во
заблокированных задач, держатель merge-lease, defer-счётчики, обнаруженные циклы. Read-only,
никогда не источник истины для решений.
## 5. Изменения схемы БД
- **КАНДИДАТ (если выбран БД/гибрид для Уровня B):** аддитивная таблица `job_deps` или колонка
в `tasks` (см. §3.1). Только `CREATE TABLE IF NOT EXISTS` / `_ensure_column`. Без изменения
существующих колонок `jobs`/`tasks`. Restart-safe, безопасно на общей прод-БД.
- Уровень A (сериализация) — **без изменения схемы БД** (merge-lease файловый, как ORCH-065).
## 6. Требования к новым QG checks
- **Новый зарегистрированный QG-чек НЕ вводится** (паттерн ORCH-071/058: под-гейт — врезка в
`advance_stage` или расширение `check_branch_mergeable`, а не новая запись в `QG_CHECKS`).
- Реестр `QG_CHECKS` — без изменений.
## 7. Конфигурация (`src/config.py`)
Новые настройки по паттерну `*_enabled` (kill-switch) + `*_repos` (CSV scope, пусто →
self-hosting). КАНДИДАТ-имена (финализирует архитектор):
- Уровень A: `merge_serialize_enabled` / `merge_serialize_repos` (или расширение
`merge_gate_*`); опционально `premerge_rebase_always` (вкл proactive rebase).
- Уровень B: `task_deps_enabled` / `task_deps_source` (`plane|db|hybrid`).
Дефолты — обратная совместимость (для не-self репо — прежнее поведение).
## 8. Артефакты pipeline (создать/обновить В ТОМ ЖЕ PR)
- `06-adr/ADR-001-*.md` — решение по сериализации (A) и хранению зависимостей (B).
- Обновить `docs/architecture/README.md` (раздел про очередь/merge-gate/сериализацию).
- Обновить `CLAUDE.md` (паспорт: конвейер/инварианты, если меняется поведение очереди).
- Обновить `CHANGELOG.md` (`## [Unreleased]`).
- Если вводится таблица БД — отразить в `08-data-requirements.md` (создаёт архитектор).
- `07-infra-requirements.md` — если требуется новый Plane-статус/настройка relations.
## 9. Инварианты (НЕ нарушать)
1. `STAGE_TRANSITIONS`, реестр `QG_CHECKS`, `check_deploy_status`/`check_staging_status`,
`Confirm Deploy` (ORCH-059), БАГ-8, terminal-sync — без изменений.
2. Никаких push/force-push в `main`; force только `--force-with-lease` на ветку задачи.
3. Сериализация — строго per-repo; кросс-репо параллелизм сохранён.
4. never-raise во всех новых функциях; restart-safe состояние.
5. ORCH-026 дополняет рубежи ORCH-073, не заменяет.
6. Прод-контейнер orchestrator не рестартится вне штатного `Confirm Deploy`.