analyst(ET): auto-commit from analyst run_id=346
This commit is contained in:
52
docs/work-items/ORCH-068/01-brd.md
Normal file
52
docs/work-items/ORCH-068/01-brd.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# BRD — ORCH-068: BUG reconciler livelock (спам unblock done-задачи)
|
||||
|
||||
## 1. Контекст и предыстория
|
||||
Reconciler (`src/reconciler.py`, ORCH-053) — фоновый поток, который доигрывает пропущенные webhook-переходы. Ветвь **F-2 (plane-side)** опрашивает Plane per-project и реплеит In Progress / Approved / Rejected через штатные `handle_status_start` / `handle_verdict`. При фактической разблокировке вызывается `_note_unblock` → лог + Telegram.
|
||||
|
||||
ORCH-066 (мердж `feature/ORCH-066-plane`, прод 2026-06-07 ~22:16 UTC) ввела новую статусную модель Plane (маппинг стадия↔статус, новые имена `Done`, `Monitoring after Deploy` и т.п.). Это спровоцировало регрессию в F-2.
|
||||
|
||||
## 2. Проблема (бизнес-симптом)
|
||||
С 22:17 UTC (рестарт прод-контейнера после деплоя ORCH-066) reconciler каждые ~120с шлёт в Telegram:
|
||||
```
|
||||
reconciler: ET-002 done разблокирована (потерян webhook)
|
||||
```
|
||||
для задачи **ET-002** (enduro-trails), которая в Done с 2026-05-21. На момент анализа — 191+ сообщений подряд, поток не прекращается (ночной спам, найден Славой 2026-06-08 01:22 UTC).
|
||||
|
||||
**Ключевой факт:** ET-002 полностью синхронизирована — БД `stage=done`, Plane `state=Done`. Reconciler обязан молчать (инвариант «silence when in sync», AC-9/AC-10 из ORCH-053), но шлёт уведомления вхолостую.
|
||||
|
||||
## 3. Диагностика (проведена, root cause найден)
|
||||
1. **Деньги/токены НЕ тратятся:** `jobs` / `agent_runs` за 4ч пусты; `advance_stage` для done = no-op; `handle_verdict` для done-задачи ничего не меняет. Это «дешёвый», но шумный и подрывающий доверие баг (livelock + ложный alert-fatigue).
|
||||
2. **Механизм:**
|
||||
- `_reconcile_plane_project` (`src/reconciler.py` ~241) тянет `list_issues_by_state(pid, [in_progress, approved, rejected])`.
|
||||
- На enduro-trails статусы «схлопнуты»: после ORCH-066 терминальный `Done` алиасится под UUID `approved` (см. ниже п.4) → ET-002 (Plane=Done) **попадает** в actionable-выборку.
|
||||
- В `_reconcile_plane_issue` (~295) срабатывает ветка `new_state == approved and task is not None` → `handle_verdict(approved)` (no-op, задача уже done) **+ безусловный `_note_unblock`**.
|
||||
- `_note_unblock` (~317) вызывается **сразу после `_dispatch`, не проверяя фактическое изменение состояния** — хотя его docstring обещает «fires only on an actual state change, never per idle tick». Инвариант нарушен.
|
||||
3. **Два независимых дефекта складываются:**
|
||||
- **D1 (выборка):** терминальные статусы (`Done`/`Cancelled`) не исключены из actionable-набора F-2; на «схлопывающих» проектах Done не отличается от approved по голому UUID.
|
||||
- **D2 (нотификация):** `_note_unblock` срабатывает безусловно после no-op dispatch, а не только при подтверждённом state change.
|
||||
4. **Почему `get_project_states` схлопывает:** функция строит маппинг по *именам* статусов из Plane API, затем недостающие ключи добивает из `_DEFAULT_STATES` (enduro-значения). После ORCH-066 набор статусов enduro изменился — голый UUID перестал однозначно различать `Done` (completed-группа) и `approved` (review). Группа состояния (`state.group`) при этом различает их корректно, но в коде не используется.
|
||||
|
||||
## 4. Связанный баг (BUG КЭША СТАТУСОВ, найден 2026-06-07 при деплое ORCH-066)
|
||||
`_STATES_CACHE` (`src/plane_sync.py` ~134) кэширует статусы Plane на **весь lifetime процесса**. После создания нового Plane-статуса (напр. `Confirm Deploy`) боевой процесс держит устаревший набор → webhook на новый статус даёт «no pipeline action» (Phase B не триггерится). Лечилось только рестартом орка. Примитив сброса уже есть — `reload_project_states()` — но он нигде не вызывается автоматически.
|
||||
|
||||
Оба бага — следствие хрупкости статусной модели после ORCH-066. **Решение:** вести их в одном work item (см. scope ниже), окончательное разделение — на усмотрение архитектора.
|
||||
|
||||
## 5. Цели (Goals)
|
||||
- G1. Reconciler НЕ шлёт «разблокирована» для синхронизированной done/cancelled задачи (восстановить инвариант silence-when-in-sync).
|
||||
- G2. `_note_unblock` срабатывает **только** при реальном state change (соблюдён AC-9/AC-10).
|
||||
- G3. Дедуп: нет повторного спама по той же задаче без изменения её состояния.
|
||||
- G4. Корректное различение терминальных (`Done`/`Cancelled`) и review-статусов (`approved`/`rejected`) даже на проектах, «схлопывающих» их по UUID — на всех проектах (enduro И orchestrator).
|
||||
- G5 (secondary). Устаревший `_STATES_CACHE` обновляется без рестарта процесса (TTL / flush-on-unknown / endpoint).
|
||||
|
||||
## 6. Не-цели (Out of scope)
|
||||
- N1. Менять source-of-truth: ориентир F-2 на Plane **остаётся** корректным по дизайну (таблица `tasks` без status-колонки; статусы двигает человек в Plane). Идею F-2 НЕ переписываем — баг в маппинге/нотификации, не в концепции.
|
||||
- N2. Менять реестры `STAGE_TRANSITIONS` / `QG_CHECKS`, схему БД, контракты гейтов.
|
||||
- N3. Менять поведение F-1 (gate-side) и F-3.
|
||||
- N4. Полный авто-approve деплоя (ORCH-54).
|
||||
|
||||
## 7. Затронутые стороны
|
||||
- **Все проекты на одном инстансе** (enduro-trails + orchestrator, общая БД/очередь) — баг проявился на ET-002, но фикс выборки терминалов обязан быть проектно-независимым.
|
||||
- **Self-hosting:** правка идёт в работающий прод-инструмент → обязательна страховка staging (8501), запрет на рестарт прод-контейнера в рамках задачи.
|
||||
|
||||
## 8. Критерий успеха (бизнес)
|
||||
Тик reconciler для синхронизированной done/cancelled задачи = **0 уведомлений, 0 jobs, 0 токенов**. Telegram-спам прекращён. Легитимная разблокировка (реально потерянный approved/in_progress webhook) по-прежнему работает (нет регресса F-2).
|
||||
68
docs/work-items/ORCH-068/02-trz.md
Normal file
68
docs/work-items/ORCH-068/02-trz.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# ТЗ — ORCH-068: устранить livelock reconciler F-2 + спам unblock done-задачи
|
||||
|
||||
> Документ описывает ТРЕБОВАНИЯ к изменению поведения (что и где), а не выбор реализации. Конкретный механизм (state.group vs явный allowlist терминалов; TTL vs flush-on-unknown) — решение архитектора в ADR.
|
||||
|
||||
## 1. Затронутые модули `src/`
|
||||
| Модуль | Роль в баге | Требуемое изменение |
|
||||
|--------|-------------|---------------------|
|
||||
| `src/reconciler.py` | F-2 `_reconcile_plane_project` / `_reconcile_plane_issue` / `_note_unblock` | Исключить терминальные статусы из actionable-выборки; `_note_unblock` только при подтверждённом state change; дедуп. |
|
||||
| `src/plane_sync.py` | `get_project_states`, `list_issues_by_state`, `_STATES_CACHE` | Дать способ различать терминальные/review статусы (группа состояния); устранить вечно-устаревший кэш (TTL/flush). |
|
||||
| `src/config.py` | флаги | (если нужны) новые kill-switch/настройки TTL — с дефолтами, не меняющими прод-инварианты. |
|
||||
| `src/main.py` (`/queue`) | наблюдаемость | (опц.) отразить дедуп/skip-терминалов в снимке `reconcile`. |
|
||||
|
||||
**НЕ трогать:** `src/stages.py` (`STAGE_TRANSITIONS`), `src/qg/checks.py` (`QG_CHECKS`), схему БД, контракты `handle_status_start` / `handle_verdict`, F-1 (`reconcile_gate_once`), F-3.
|
||||
|
||||
## 2. Требования к F-2 (src/reconciler.py)
|
||||
|
||||
### TR-1. Исключить терминальные статусы из actionable-выборки
|
||||
`_reconcile_plane_project` НЕ должен подавать задачи в терминальном Plane-статусе (`Done` и прочие completed-группы, `Cancelled`) ни в `list_issues_by_state`, ни в последующее сравнение веток.
|
||||
- Требование проектно-независимое: работает на enduro И orchestrator, независимо от того, «схлопывает» ли проект статусы по UUID.
|
||||
- Различение `Done`/`Cancelled` (completed) от `approved`/`rejected` (review) НЕ должно опираться только на голый UUID, если проект их алиасит. Допустимый ориентир — группа состояния Plane (`state.group`: `completed`/`started`/`unstarted`/`backlog`/`cancelled`) либо явный набор логических ключей терминалов. Выбор — за архитектором.
|
||||
|
||||
### TR-2. `_note_unblock` — только при реальном state change
|
||||
`_note_unblock` (лог + Telegram + инкремент `unblocked_total`) ВЫЗЫВАЕТСЯ ТОЛЬКО когда диспетчеризованный обработчик фактически изменил состояние задачи (advance / replayed transition, реально сдвинувший стадию). No-op dispatch (задача уже в целевом состоянии) → нотификация НЕ отправляется.
|
||||
- Сейчас `_dispatch` (`asyncio.run(coro_fn(...))`) отбрасывает результат, а `_note_unblock` зовётся безусловно. Требуется механизм подтверждения изменения (напр. сравнение стадии задачи до/после dispatch через `get_task_by_plane_id`, либо проброс сигнала из обработчика). Конкретику выбирает архитектор; контракт обработчиков `handle_*` менять НЕ обязательно (предпочтительно сравнение состояния до/после на стороне reconciler).
|
||||
- Восстановить соответствие docstring `_note_unblock`: «Fires only on an actual state change … never per idle tick».
|
||||
|
||||
### TR-3. Дедуп / идемпотентность нотификаций
|
||||
Reconciler НЕ должен слать повторное уведомление о той же задаче, если её состояние не менялось с прошлого тика. TR-1+TR-2 закрывают основной кейс (done более не входит в выборку и не нотифицируется); TR-3 — дополнительная страховка (best-effort), чтобы любой будущий no-op путь не дал повторного спама.
|
||||
|
||||
## 3. Требования к статус-кэшу (src/plane_sync.py) — secondary
|
||||
|
||||
### TR-4. Устаревший `_STATES_CACHE` обновляется без рестарта
|
||||
После появления нового Plane-статуса процесс не должен бесконечно держать устаревший набор. Допустимые подходы (выбор архитектора, можно комбинировать):
|
||||
- TTL на запись кэша (напр. `ORCH_PLANE_STATES_TTL_S`, дефолт разумный, 0/неуст. = прежнее поведение для совместимости);
|
||||
- flush-on-unknown: при детекте неизвестного статуса в вебхуке/реконсилере — вызвать существующий `reload_project_states(pid)` и перезапросить;
|
||||
- админ-эндпоинт/сигнал для ручного flush без рестарта.
|
||||
`reload_project_states()` уже существует — переиспользовать как примитив сброса, новую логику сброса не дублировать.
|
||||
|
||||
## 4. Изменения API
|
||||
- Новых обязательных endpoint'ов нет.
|
||||
- Опционально (TR-4, на усмотрение архитектора): admin-эндпоинт сброса кэша статусов (напр. `POST /admin/plane-states/reload`) — если выбран этот вариант flush. Должен быть защищён/идемпотентен; документировать в README таблице API.
|
||||
- Снимок `GET /queue` (блок `reconcile`) — без ломающих изменений; допустимо добавить поля наблюдаемости (skip-терминалов / dedup-счётчик).
|
||||
|
||||
## 5. Изменения схемы БД
|
||||
**Нет.** Дедуп TR-3 реализуется in-memory (best-effort, как существующие счётчики `unblocked_total`/`last_unblocked`, AC-11 ORCH-053 допускает их сброс при рестарте) либо через сравнение живого состояния Plane/БД. Миграции не требуются.
|
||||
|
||||
## 6. Требования к новым QG checks
|
||||
Нет. Реестр `QG_CHECKS` не меняется.
|
||||
|
||||
## 7. Инварианты (обязаны сохраниться)
|
||||
- INV-1. Source of truth F-2 — Plane (НЕ меняем).
|
||||
- INV-2. never-raise на единицу работы (per-issue / per-project / per-tick) сохранён.
|
||||
- INV-3. Kill-switch `ORCH_RECONCILE_ENABLED` (+ `ORCH_RECONCILE_PLANE_ENABLED` гасит только F-2) — работают.
|
||||
- INV-4. F-1 / F-3 поведение не изменено.
|
||||
- INV-5. 0 jobs / 0 токенов для синхронизированных задач (как сейчас) сохранено.
|
||||
- INV-6. Легитимная разблокировка реально-потерянного approved/in_progress webhook продолжает работать (нет регресса F-2).
|
||||
- INV-7. Self-hosting: тик reconciler НИКОГДА не рестартит/не роняет прод-контейнер.
|
||||
|
||||
## 8. Артефакты pipeline, которые надо обновить в ТОМ ЖЕ PR
|
||||
- `CLAUDE.md` — если меняется наблюдаемое поведение reconciler/кэша (раздел про reconciler/правила).
|
||||
- `docs/architecture/README.md` — секция «Reconciler … (ORCH-053)»: уточнить исключение терминалов + дедуп; при TR-4 — секция «Plane Sync».
|
||||
- `docs/architecture/adr/adr-0007-reconciler.md` (или новый per-WI ADR `docs/work-items/ORCH-068/06-adr/ADR-001-…`) — зафиксировать решение по терминалам/группе состояния и по кэшу.
|
||||
- `CHANGELOG.md` — запись о фиксе (`fix:`).
|
||||
- `.env.example` / `.env.staging` — если введён новый флаг (TTL/kill-switch).
|
||||
|
||||
## 9. Замечания по приёмке/тестированию
|
||||
- Регресс-тест ОБЯЗАН покрывать: задача в `Done` (синхронизирована) → тик F-2 = 0 нотификаций, на enduro И orchestrator проектах (terminal не зависит от алиасинга).
|
||||
- Тест НЕ должен делать реальных сетевых вызовов — мокать `list_issues_by_state` / `get_project_states` / `send_telegram` / `_dispatch` (handle_*).
|
||||
84
docs/work-items/ORCH-068/03-acceptance-criteria.md
Normal file
84
docs/work-items/ORCH-068/03-acceptance-criteria.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# Критерии приёмки — ORCH-068
|
||||
|
||||
Формат: каждый AC имеет чёткое условие PASS/FAIL. Задача принимается только при ВСЕХ PASS.
|
||||
|
||||
## Основное (P0) — livelock / спам
|
||||
|
||||
### AC-1. Синхронизированная done-задача → тишина
|
||||
**Дано:** задача в Plane `state=Done`, БД `stage=done`, активных job нет.
|
||||
**Когда:** выполняется один тик F-2 (`reconcile_plane_once` / `_reconcile_plane_project`).
|
||||
- PASS: `_note_unblock` НЕ вызван; `send_telegram` НЕ вызван; `unblocked_total` не изменился; создано 0 jobs.
|
||||
- FAIL: любое уведомление/лог «разблокирована»/инкремент счётчика для этой задачи.
|
||||
|
||||
### AC-2. Терминалы исключены из actionable-выборки
|
||||
**Дано:** проект, где `Done` (и/или `Cancelled`) по UUID совпадает/«схлопнут» с `approved`/`rejected`.
|
||||
**Когда:** `_reconcile_plane_project` формирует набор и обходит issues.
|
||||
- PASS: issue в терминальном статусе (completed-группа / `Cancelled`) НЕ попадает ни в одну из веток `in_progress/approved/rejected`; для неё F-2 — no-op silence.
|
||||
- FAIL: терминальная issue заходит в ветку approved/rejected/in_progress.
|
||||
|
||||
### AC-3. `_note_unblock` только при реальном state change
|
||||
**Дано:** dispatch обработчика (`handle_verdict`/`handle_status_start`) фактически НЕ изменил стадию задачи (no-op, задача уже в целевом состоянии).
|
||||
- PASS: `_note_unblock` НЕ вызван.
|
||||
- FAIL: `_note_unblock` вызван после no-op dispatch.
|
||||
|
||||
### AC-4. Дедуп по неизменному состоянию
|
||||
**Дано:** две последовательные итерации тика по одной и той же синхронизированной задаче, состояние между тиками не менялось.
|
||||
- PASS: суммарно 0 повторных уведомлений по этой задаче.
|
||||
- FAIL: повторное уведомление на втором тике без изменения состояния.
|
||||
|
||||
### AC-5. Нет регресса легитимной разблокировки F-2
|
||||
**Дано:** задача, у которой Plane=`Approved`, а локальная стадия НЕ продвинулась (реально потерянный verdict-webhook), grace выдержан, активных job нет.
|
||||
**Когда:** тик F-2.
|
||||
- PASS: `handle_verdict(approved)` доигран; задача продвинута; `_note_unblock` вызван РОВНО один раз (реальный state change).
|
||||
- FAIL: задача не продвинута ИЛИ нотификация не отправлена ИЛИ отправлена многократно.
|
||||
|
||||
### AC-6. Аналогично для in_progress-старта и rejected-отката
|
||||
- PASS: потерянный `In Progress` (task is None) → старт пайплайна + 1 unblock; потерянный `Rejected` → откат + 1 unblock — оба только при реальном изменении.
|
||||
- FAIL: ложный/повторный unblock или отсутствие легитимного.
|
||||
|
||||
## Инварианты (P0)
|
||||
|
||||
### AC-7. Деньги/ресурсы не тратятся на синхронизированные задачи
|
||||
- PASS: 0 jobs, 0 agent_runs, 0 токенов для done/cancelled задач (как до бага).
|
||||
- FAIL: любой созданный job/agent_run.
|
||||
|
||||
### AC-8. never-raise сохранён
|
||||
**Дано:** `list_issues_by_state` / `get_project_states` / `_dispatch` / `send_telegram` бросают исключение.
|
||||
- PASS: тик не падает; ошибка изолирована (per-issue / per-project), логируется; остальные задачи обрабатываются.
|
||||
- FAIL: непойманное исключение роняет тик/поток.
|
||||
|
||||
### AC-9. Kill-switch'и работают
|
||||
- PASS: `ORCH_RECONCILE_ENABLED=false` → F-1 и F-2 не выполняются; `ORCH_RECONCILE_PLANE_ENABLED=false` → F-2 не выполняется, F-1 работает.
|
||||
- FAIL: любой свитч не гасит соответствующую ветку.
|
||||
|
||||
### AC-10. F-1 / F-3 / реестры / схема БД не изменены
|
||||
- PASS: `STAGE_TRANSITIONS`, `QG_CHECKS`, схема БД, контракты `handle_*`, поведение F-1/F-3 — без изменений (diff не затрагивает).
|
||||
- FAIL: любое изменение перечисленного.
|
||||
|
||||
### AC-11. Self-hosting безопасность
|
||||
- PASS: ни один путь reconciler не рестартит/не роняет прод-контейнер `orchestrator`.
|
||||
- FAIL: обратное.
|
||||
|
||||
## Secondary (P1) — кэш статусов
|
||||
|
||||
### AC-12. Устаревший `_STATES_CACHE` обновляется без рестарта
|
||||
**Дано:** после старта процесса в Plane появился новый статус (его UUID отсутствует в кэше).
|
||||
**Когда:** срабатывает выбранный механизм (TTL истёк / flush-on-unknown / ручной flush).
|
||||
- PASS: следующий `get_project_states` возвращает свежий набор, включающий новый статус; webhook на новый статус даёт корректное pipeline-действие БЕЗ рестарта.
|
||||
- FAIL: процесс продолжает отдавать устаревший набор → «no pipeline action».
|
||||
|
||||
### AC-13. Совместимость кэша по умолчанию
|
||||
- PASS: при дефолтных настройках (TTL не задан / flush не сработал) поведение `get_project_states` не регрессирует; enduro по-прежнему получает свои UUID, fallback на `_DEFAULT_STATES` при недоступности API сохранён.
|
||||
- FAIL: регресс резолва статусов или потеря fallback.
|
||||
|
||||
## Документация (P0 по правилам проекта)
|
||||
|
||||
### AC-14. Документация обновлена в том же PR
|
||||
- PASS: обновлены применимые из {`docs/architecture/README.md` (Reconciler/Plane Sync), ADR, `CHANGELOG.md`, `CLAUDE.md`, `.env.example`}; reviewer подтверждает.
|
||||
- FAIL: поведение изменено, доки/ADR/CHANGELOG не обновлены.
|
||||
|
||||
## Тесты (P0)
|
||||
|
||||
### AC-15. `pytest tests/ -q` зелёный
|
||||
- PASS: весь набор тестов проходит; добавлены регресс-тесты из `04-test-plan.yaml`, включая done→silence на enduro и orchestrator.
|
||||
- FAIL: любой красный тест или отсутствие регресс-теста на основной баг.
|
||||
122
docs/work-items/ORCH-068/04-test-plan.yaml
Normal file
122
docs/work-items/ORCH-068/04-test-plan.yaml
Normal file
@@ -0,0 +1,122 @@
|
||||
work_item: ORCH-068
|
||||
description: >
|
||||
Регрессионные и модульные тесты на устранение livelock reconciler F-2
|
||||
(спам _note_unblock для синхронизированной done-задачи) и связанного бага
|
||||
кэша статусов. Все тесты офлайн: Plane API / Telegram / dispatch мокаются.
|
||||
Целевые модули: src/reconciler.py, src/plane_sync.py.
|
||||
|
||||
tests:
|
||||
# ---------- P0: основной баг (livelock / спам) ----------
|
||||
- id: TC-01
|
||||
type: unit
|
||||
description: >
|
||||
Синхронизированная done-задача (Plane=Done, БД=done, нет активных job):
|
||||
один тик F-2 -> _note_unblock НЕ вызван, send_telegram НЕ вызван,
|
||||
unblocked_total не изменился, 0 jobs. (AC-1, AC-7)
|
||||
module: tests/test_reconciler_plane.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-02
|
||||
type: unit
|
||||
description: >
|
||||
Терминал «схлопнут» с approved по UUID: issue в Done с тем же UUID, что и
|
||||
approved-набор, НЕ заходит ни в одну ветку in_progress/approved/rejected
|
||||
(silence). Проверка проектно-независимого исключения терминалов. (AC-2)
|
||||
module: tests/test_reconciler_plane.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-03
|
||||
type: unit
|
||||
description: >
|
||||
Cancelled терминал также исключён из actionable-выборки -> тик = silence,
|
||||
0 нотификаций. (AC-2)
|
||||
module: tests/test_reconciler_plane.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-04
|
||||
type: unit
|
||||
description: >
|
||||
_note_unblock не вызывается после no-op dispatch: handle_verdict не сдвинул
|
||||
стадию (задача уже в целевом состоянии) -> 0 нотификаций. (AC-3)
|
||||
module: tests/test_reconciler_plane.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-05
|
||||
type: unit
|
||||
description: >
|
||||
Дедуп: два последовательных тика по одной синхронизированной задаче без
|
||||
изменения состояния -> суммарно 0 повторных уведомлений. (AC-4)
|
||||
module: tests/test_reconciler_plane.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-06
|
||||
type: unit
|
||||
description: >
|
||||
Нет регресса: Plane=Approved, локальная стадия не продвинута, grace выдержан,
|
||||
нет активных job -> handle_verdict доигран, задача продвинута, _note_unblock
|
||||
вызван РОВНО один раз. (AC-5)
|
||||
module: tests/test_reconciler_plane.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-07
|
||||
type: unit
|
||||
description: >
|
||||
Нет регресса для in_progress (task is None -> старт пайплайна, 1 unblock) и
|
||||
rejected (task существует -> откат, 1 unblock), оба только при реальном
|
||||
изменении состояния. (AC-6)
|
||||
module: tests/test_reconciler_plane.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-08
|
||||
type: unit
|
||||
description: >
|
||||
never-raise: list_issues_by_state / get_project_states / _dispatch /
|
||||
send_telegram бросают исключение -> тик не падает, ошибка изолирована и
|
||||
залогирована, прочие issues обработаны. (AC-8)
|
||||
module: tests/test_reconciler_plane.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-09
|
||||
type: unit
|
||||
description: >
|
||||
Kill-switch: reconcile_enabled=False -> F-2 не выполняется;
|
||||
reconcile_plane_enabled=False -> F-2 не выполняется, F-1 не затронут. (AC-9)
|
||||
module: tests/test_reconciler_plane.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-10
|
||||
type: integration
|
||||
description: >
|
||||
End-to-end F-2 на двух проектах (enduro И orchestrator): задача в Done на
|
||||
каждом -> тик reconcile_plane_once = 0 нотификаций / 0 jobs на обоих,
|
||||
независимо от алиасинга статусов проекта. Главный регресс-тест бага. (AC-1, AC-2)
|
||||
module: tests/test_reconciler_plane.py
|
||||
expected: PASS
|
||||
|
||||
# ---------- P1: связанный баг кэша статусов ----------
|
||||
- id: TC-11
|
||||
type: unit
|
||||
description: >
|
||||
Устаревший _STATES_CACHE обновляется без рестарта: после появления нового
|
||||
статуса срабатывает выбранный механизм (TTL/flush) -> следующий
|
||||
get_project_states содержит новый статус. (AC-12)
|
||||
module: tests/test_plane_states_cache.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-12
|
||||
type: unit
|
||||
description: >
|
||||
Совместимость по умолчанию: при дефолтных настройках get_project_states не
|
||||
регрессирует — enduro отдаёт свои UUID, fallback на _DEFAULT_STATES при
|
||||
недоступности API сохранён. (AC-13)
|
||||
module: tests/test_plane_states_cache.py
|
||||
expected: PASS
|
||||
|
||||
# ---------- P0: общий прогон ----------
|
||||
- id: TC-13
|
||||
type: integration
|
||||
description: >
|
||||
Полный набор pytest tests/ -q зелёный (нет регресса в reconciler/plane/qg/
|
||||
stage_engine). (AC-15)
|
||||
module: tests/
|
||||
expected: PASS
|
||||
Reference in New Issue
Block a user