# Deep Review — Phase 5: Verdict + merge > Supporting reference. Verdict шаблон + auto-merge policy. ## Verdict format (строго) ```markdown ## Deep Code Review — verdict ### Summary - **Status**: ✅ APPROVE / ⚠️ MINOR / 🟡 MEDIUM / 🟠 HIGH / 🔴 BLOCK - **Files reviewed**: N (P0: a, P1: b, P2: c, P3: d) - **Lines**: +X / -Y - **Time spent**: ~M min - **PR**: #N (если есть) ### 🔴 Critical (BLOCK push/merge) - [ ] `path/file.py:42` — описание + конкретный fix (code snippet) - [ ] `data/sql/95_foo.sql:12` — `ALTER TABLE ... NOT NULL DEFAULT 0` на 50M rows заблокирует таблицу. Split: ADD NULL → backfill batched → SET NOT NULL отдельным PR ### 🟠 High (должен быть пофиксен до merge) - [ ] `path/file.ts:84` — race condition: state update в onSettled() при unmounted component - [ ] `backend/app/api/v1/parcels.py:201` — N+1: цикл с `await db.execute(...)`, переделать на `IN (:ids)` ### 🟡 Medium (желательно fix, но не блокирующее) - [ ] `file.py:120` — `except Exception: pass` swallow'ит ошибки ### 🟢 Low / nits (можно отдельным PR) - [ ] `file.py:50` — naming `data` слишком generic, `parcels_by_district` ### Cross-file impact analysis - `backend/app/services/site_finder/foo.py` изменил signature `find_parcels()` → callers обновлены: `api/v1/parcels.py:88` ✅, но `tasks.py:142` всё ещё передаёт старый kwarg ❌ - `frontend/src/types/site-finder.ts` regen нужен — `npm run codegen` не запущен в этом PR ### Vault cross-check - Похожий fix был в `fixes/Bug_Worker_Ready_EarlyReturn.md` — паттерн использован корректно ✅ - Decision `decisions/2026-05-12-no-mutable-defaults.md` — этот PR не нарушает - Если bug fix, но нет entry в `fixes/` → ⚠️ нужна docs (medium severity) ### Performance findings - `EXPLAIN ANALYZE` на новом query `parcels.find_by_district`: - Seq Scan на `rosreestr_parcels` (5.2M rows) — нужен index `(district_id, status)` - Estimated cost 12.4k → с индексом 0.8 ### Positive observations - ✅ `ON CONFLICT DO UPDATE` использован корректно в bulk_upsert - ✅ `CREATE INDEX CONCURRENTLY` в миграции ### Recommended next steps 1. Worker (backend-engineer): fix 🔴 #1 + 🟠 #1, push fixup commit 2. После fixup: run `npm run codegen` в frontend 3. Перед merge: проверить EXPLAIN на проде через MCP postgres 4. Создать vault entry `fixes/.md` ### Сomplexity / blast radius score - **Risk**: Low / Medium / High / Critical - **Reversibility**: Easy revert / DB migration needs manual rollback / Data loss on revert - **Recommended merge window**: anytime / business hours only / pre-deploy freeze ``` ## Когда BLOCK (🔴) — обязательные триггеры 1. Hardcoded secret / token / password в commit (даже test files) 2. SQL injection vector 3. Auth bypass на admin endpoint 4. Migration без rollback plan (если меняет / удаляет данные) 5. Breaking API change без deprecation / migration path 6. Удаление prod данных без явного approval 7. `--no-verify` / `--force` / `--amend` в недавних коммитах ветки 8. **Прямой push в main** (HEAD == main, не feature branch) 9. `ALTER TABLE ... NOT NULL DEFAULT` на таблице >1M rows без batched backfill 10. `CREATE INDEX` (не CONCURRENTLY) на prod таблице >1M rows 11. `DROP COLUMN` / `DROP TABLE` без 2-stage rollout 12. Celery task без idempotency маркера (вернёт дубли при retry) 13. Scraper без dedup ключа в `ON CONFLICT` ## Когда APPROVE (✅) - Нет critical / high issues - Cross-file impact проверен — все callers consistent - Conventions OK (psycopg v3, httpx, ruff, TS strict) - Backward compat сохранён - Performance не регрессирует (или регрессия документирована и acceptable) - Vault entry создана для нетривиальных fixes / decisions - Tests есть для новой бизнес-логики (если applicable per scope) - Pre-flight: на feature branch, нет force / no-verify в истории ## Auto-merge policy (PR review mode) При review открытых Forgejo PR — если verdict **✅ APPROVE** (нет 🔴/🟠/🟡): **мержи сам, любой scope** (user override 2026-05-16: «после аппрув в ревью можешь мерджить все что угодно»). ### Pre-merge checks (все обязательны) 1. `curl -sH "$H" "$REPO/pulls/" | jq '{state,mergeable,draft,head:.head.sha}'` → `state=open` (не уже merged), `mergeable=true` (no conflicts), `draft=false` 2. Head SHA не изменился после твоего review (нет fixup push'ей с момента scan'а файлов) 3. CI status passing — Forgejo Actions UI или `curl -sH "$H" "$REPO/commits//status"` ### Merge команда (Forgejo) ```bash # Через MCP (preferred): mcp__forgejo__merge_pull_request (Do=squash, delete_branch_after_merge=true) # Или curl: curl -sH "$H" -H "Content-Type: application/json" \ -X POST "$REPO/pulls//merge" \ -d '{"Do":"squash","delete_branch_after_merge":true}' # Post-merge confirmation comment: curl -sH "$H" -H "Content-Type: application/json" \ -X POST "$REPO/issues//comments" \ -d '{"body":"Merged via deep-code-reviewer — verdict ✅ APPROVE."}' ``` Forgejo API возвращает пустой body при успехе merge → verify через GET pulls/ что `state == merged`. ### Когда НЕ мержить даже при APPROVE - `mergeable=false` (conflicts) → comment "approved but has conflicts — rebase needed" - CI failing → comment "approved but CI red — wait for green" - Draft PR → comment "approved, ready when undrafted" - Head SHA changed после твоего scan'а → НЕ мержь stale verdict, re-review нужен