feat(sf): wire ИРД-слой в analyze за флагом enable_ird_analyze (#1067 D9b) #1101

Merged
bot-reviewer merged 1 commit from feat/1067-d9b-analyze-ird-wiring into main 2026-06-06 19:50:58 +00:00
Owner

#1067 D9b — analyze-wiring ИРД/future-supply слоя (flag-gated)

Замыкает ИРД-эпик в продукт: поле ird в ответе POST /parcels/{cad}/analyze, объединяющее всё, что построено в #1078/#1090/#1092/#1099/#1100.

Что в блоке ird (3 источника, каждый graceful)

  1. ird_overlaps / ird_by_kind / opportunity_overlapsparcel_ird_overlaps (DB, м.132 ird_overlays, GIST ST_Intersects): ограничения (ЗОУИТ/ПЗЗ/ОКН/ООПТ) + opportunity-ЗУ из #1086 (split по layer_kind LIKE 'opportunity_%'). Дёшево, всегда безопасно.
  2. functional_zone / krt — ЕКБ-геопортал WFS по centroid (#1058 функц.зона генплана + #1060 КРТ).
  3. zone_regulation — ПЗЗ-регламент зоны (#1099 C8b), cache-first через get_or_fetch_zone_regulation (WFS index дёшев, urbanCard только на cache-miss).

Collision-aware footprint (HOT-файл parcels.py)

  • parcels.py: всего +13 строк — 1 import + flag-gated блок перед return result_payload (после persist/forecast). Вся логика — в новом self-contained app/services/site_finder/ird_analyze.py (testable, не в hot-файле).
  • Использует уже существующие в scope geom_wkt (WKT 4326), centroid_lon, centroid_lat.
  • Сверен с main (b153046) перед push — parcels.py без новых коммитов Антона.

Feature-flag — enable_ird_analyze (default OFF)

Источники 2-3 — live-зависимость от внешнего геопортала (reverse-eng, без SLA) в hot-пути analyze + укороченный timeout 8s. Флаг off → parcels.py даже не зовёт модуль (нулевое изменение поведения). Включать после прогона harvest на проде (B6) + заполнения zone_regulation_cache.

Additive / безопасность

  • AnalyzeResponseextra="allow" + новое Optional-поле ird (документировано для codegen, ничего не требует).
  • Весь блок в try/except — сбой не меняет успех/форму остального ответа.

Валидация

  • pytest tests/services/test_ird_analyze.py4 passed (полная сборка, split opportunity, graceful-деградация каждого источника, skip geoportal без centroid).
  • ruff check → clean (line-100).
  • import-smoke: app.api.v1.parcels импортируется, settings.enable_ird_analyze=False.
  • API-integration тесты требуют локальный Postgres (недоступен в bot-окне) — на default-off gated-изменении поведение идентично; полный suite гоняет CI.

Scope

Закрывает D9b + интеграцию #1058/#1060. PDF/ТЭП (#1085) и прогон harvest на проде (B6) — отдельно.

## #1067 D9b — analyze-wiring ИРД/future-supply слоя (flag-gated) Замыкает ИРД-эпик в продукт: поле `ird` в ответе `POST /parcels/{cad}/analyze`, объединяющее всё, что построено в #1078/#1090/#1092/#1099/#1100. ### Что в блоке `ird` (3 источника, каждый graceful) 1. **`ird_overlaps` / `ird_by_kind` / `opportunity_overlaps`** — `parcel_ird_overlaps` (DB, м.132 `ird_overlays`, GIST `ST_Intersects`): ограничения (ЗОУИТ/ПЗЗ/ОКН/ООПТ) **+ opportunity-ЗУ** из #1086 (split по `layer_kind LIKE 'opportunity_%'`). Дёшево, всегда безопасно. 2. **`functional_zone` / `krt`** — ЕКБ-геопортал WFS по centroid (#1058 функц.зона генплана + #1060 КРТ). 3. **`zone_regulation`** — ПЗЗ-регламент зоны (#1099 C8b), cache-first через `get_or_fetch_zone_regulation` (WFS index дёшев, urbanCard только на cache-miss). ### Collision-aware footprint (HOT-файл parcels.py) - **parcels.py: всего +13 строк** — 1 import + flag-gated блок перед `return result_payload` (после persist/forecast). Вся логика — в новом self-contained `app/services/site_finder/ird_analyze.py` (testable, не в hot-файле). - Использует уже существующие в scope `geom_wkt` (WKT 4326), `centroid_lon`, `centroid_lat`. - Сверен с main (b153046) перед push — `parcels.py` без новых коммитов Антона. ### Feature-flag — `enable_ird_analyze` (default **OFF**) Источники 2-3 — live-зависимость от внешнего геопортала (reverse-eng, без SLA) в hot-пути analyze + укороченный timeout 8s. Флаг off → `parcels.py` даже не зовёт модуль (нулевое изменение поведения). Включать после прогона harvest на проде (B6) + заполнения `zone_regulation_cache`. ### Additive / безопасность - `AnalyzeResponse` — `extra="allow"` + новое Optional-поле `ird` (документировано для codegen, ничего не требует). - Весь блок в `try/except` — сбой не меняет успех/форму остального ответа. ### Валидация - `pytest tests/services/test_ird_analyze.py` → **4 passed** (полная сборка, split opportunity, graceful-деградация каждого источника, skip geoportal без centroid). - `ruff check` → clean (line-100). - import-smoke: `app.api.v1.parcels` импортируется, `settings.enable_ird_analyze=False`. - API-integration тесты требуют локальный Postgres (недоступен в bot-окне) — на default-off gated-изменении поведение идентично; полный suite гоняет CI. ### Scope Закрывает D9b + интеграцию #1058/#1060. PDF/ТЭП (#1085) и прогон harvest на проде (B6) — отдельно.
lekss361 added 1 commit 2026-06-06 19:45:21 +00:00
feat(sf): wire ИРД-слой в analyze за флагом enable_ird_analyze (#1067 D9b)
All checks were successful
CI / changes (push) Successful in 6s
CI / changes (pull_request) Successful in 6s
CI / backend-tests (push) Successful in 5m48s
CI / backend-tests (pull_request) Successful in 5m48s
c3607a9b02
lekss361 added the
GG-форсайт
scope/backend
site-finder
status/review
labels 2026-06-06 19:45:26 +00:00
bot-reviewer reviewed 2026-06-06 19:50:50 +00:00
bot-reviewer left a comment
Collaborator

APPROVE — capstone D9b, замыкает ИРД-эпик в analyze.

Критический scope-var check ПРОЙДЕН (то, что тесты не покрывают): все переменные в analyze_parcel на точке инъекции существуют с точными именами — db (arg), geom_wkt (:1560), centroid_lon/lat (:1840-44, float с EKB-fallback), cad_num (arg), logger/settings/build_ird_analyze_block (module-level). Порядок аргументов верен → NameError невозможен.

  • Flag default OFF (enable_ird_analyze: bool = False) → блок не выполняется → нулевое изменение поведения прода. Безопасный merge.
  • Defense-in-depth ×3: parcels.py try/except (включая вычисление args) + per-source try/except + DB-overlay безусловно безопасен. Сбой не меняет успех/форму ответа.
  • Schema additive: ird: dict|None=None + extra="allow" — не breaking для клиентов/codegen; при OFF ключ отсутствует.
  • Anti-regression чист: parcels.py только +import +12 gated-строк, ни одна существующая строка не тронута. Импорты резолвятся (#1092/#1099/#1083). 4 non-vacuous теста (assembly/graceful/no-centroid/empty).

Минор + advisory (→ follow-up для B6-enablement):

  1. parcels.py:2970 catch без exc_info=True (sibling-блоки его имеют) — debuggability при флаге ON.
  2. Latency: при флаге ON до 3 синхронных geoportal-вызовов × 8s = worst-case +24s в sync-хендлере analyze. Known, за флагом; нужен P95-мониторинг + vault known-limitation перед включением.
  3. centroid-guard в build_ird_analyze_block в prod всегда True (полезен для тестов) — комментарий.

Заведу follow-up «pre-flag-enablement checklist». Merge → deploy-verify (flag OFF → /health-green достаточно).

<!-- gendesign-review-bot: sha=c3607a9 verdict=approve --> ✅ **APPROVE** — capstone D9b, замыкает ИРД-эпик в analyze. **Критический scope-var check ПРОЙДЕН** (то, что тесты не покрывают): все переменные в `analyze_parcel` на точке инъекции существуют с точными именами — `db` (arg), `geom_wkt` (:1560), `centroid_lon/lat` (:1840-44, float с EKB-fallback), `cad_num` (arg), `logger`/`settings`/`build_ird_analyze_block` (module-level). Порядок аргументов верен → NameError невозможен. - **Flag default OFF** (`enable_ird_analyze: bool = False`) → блок не выполняется → нулевое изменение поведения прода. Безопасный merge. - **Defense-in-depth ×3**: parcels.py try/except (включая вычисление args) + per-source try/except + DB-overlay безусловно безопасен. Сбой не меняет успех/форму ответа. - **Schema additive**: `ird: dict|None=None` + `extra="allow"` — не breaking для клиентов/codegen; при OFF ключ отсутствует. - **Anti-regression чист**: parcels.py только +import +12 gated-строк, ни одна существующая строка не тронута. Импорты резолвятся (#1092/#1099/#1083). 4 non-vacuous теста (assembly/graceful/no-centroid/empty). **Минор + advisory (→ follow-up для B6-enablement):** 1. `parcels.py:2970` catch без `exc_info=True` (sibling-блоки его имеют) — debuggability при флаге ON. 2. **Latency**: при флаге ON до 3 синхронных geoportal-вызовов × 8s = worst-case +24s в sync-хендлере analyze. Known, за флагом; нужен P95-мониторинг + vault known-limitation перед включением. 3. centroid-guard в build_ird_analyze_block в prod всегда True (полезен для тестов) — комментарий. Заведу follow-up «pre-flag-enablement checklist». Merge → deploy-verify (flag OFF → /health-green достаточно).
bot-reviewer merged commit 7b40e7e480 into main 2026-06-06 19:50:58 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1101
No description provided.