fix(gate): area-gate ЗОУИТ utility-easement blocker (sub-17) — снять over-block can_build (#1881) #1892

Merged
bot-backend merged 1 commit from fix/zouit-engineering-area-gate into main 2026-06-24 10:09:09 +00:00
Collaborator

Проблема (прод-замер 2026-06-24)

ZOUIT_OVERLAP_SUB17 (единственный subcategory-blocker = охранная зона ЛЭП/газа/трубопровода) был хард-блокером на ЛЮБОЕ пересечение → блокировал 434/574 (75.6%) участков как «нельзя строить МКД» (→ can_build_mkd=false у 90%). После фикса резолва зон (#1891) это стало главным лимитом видимости financial_estimate.

Но реальное покрытие участка sub-17 зонами (true polygon overlap, geography): median=6%, p90=47%, только 1/17 >60% — тонкие инж-коридоры. По РФ охранная зона ограничивает застройку внутри полосы, не весь участок (МКД сажается на незанятой части). Хард-блок на 6%-покрытии неверен.
Доказательство: 66:41:0303006:930 (22%), :0204014:90 (14%), :0204028:22 (14%) хард-блокированы; 66:41:0204016:229 (нет sub-17) → can_build=true и даёт financial_estimate.

Фикс (area-gate)

  • _get_zouit_overlaps + _get_cad_zouit_overlaps: coverage_pct (доля площади участка под зоной, geography м², NULLIF-guard от /0).
  • compute_gate_verdict: sub-17 (и cad network/blocker) агрегируются (sum-capped — консервативно к блоку) → блокер только если покрытие > settings.gate_zouit_engineering_blocker_min_coverage (0.6, env-tunable), иначе ZOUIT_ENGINEERING_PARTIAL warning с % покрытия. Больше нет 4× дубль-блокеров.
  • СЗЗ/OKN/прочие ЗОУИТ — без изменений (warnings). main_vri/резидентность — без изменений.
  • coverage_pct отсутствует (legacy/synthetic) → 0 → warning (документировано: дамп всегда даёт coverage; ложный хард-блок дороже).

Ожидаемый эффект

Прод: thin-strip Ж-5 участки (6-22% покрытия) → can_build=FalseTrue + ZOUIT_ENGINEERING_PARTIAL warning → financial_estimate фаерит для развязанной buildable-массы. Провалидирую на проде.

Test plan

  • +помесь тестов: area-gate (thin→warning, full→blocker), агрегация (sum-capped, many-small-strips, missing→0), coverage helper, verdict end-to-end (residential+thin→can_build=True; +full→False). 131 combined passed.
  • Полный бэкенд локально: 3459 passed, 0 failed, coverage 70.35% (gate 65%). ruff чисто. psycopg3 чисто (::geography приклеен к ), не к :bind).
  • Схема не менялась (gate_verdict/nspd_zouit_overlaps = dict[str,Any]) → api-types regen не нужен.
  • code-review: 2× approve, 0 majors (adversarial under-blocking lens: parcel-fraction в geography, sum-capped к блоку, threshold tunable, missing→warning безопасно).

Порог 0.6

Продуктовое решение по прод-распределению (median 6%, p90 47% → блокирует только экстремальный хвост). Tunable через GATE_ZOUIT_ENGINEERING_BLOCKER_MIN_COVERAGE.

Refs #1881

🤖 Generated with Claude Code

## Проблема (прод-замер 2026-06-24) `ZOUIT_OVERLAP_SUB17` (единственный subcategory-blocker = охранная зона ЛЭП/газа/трубопровода) был **хард-блокером на ЛЮБОЕ пересечение** → блокировал **434/574 (75.6%)** участков как «нельзя строить МКД» (→ `can_build_mkd=false` у 90%). После фикса резолва зон (#1891) это стало **главным лимитом видимости** `financial_estimate`. Но реальное покрытие участка sub-17 зонами (true polygon overlap, geography): **median=6%, p90=47%, только 1/17 >60%** — тонкие инж-коридоры. По РФ охранная зона ограничивает застройку **внутри полосы**, не весь участок (МКД сажается на незанятой части). Хард-блок на 6%-покрытии неверен. Доказательство: `66:41:0303006:930` (22%), `:0204014:90` (14%), `:0204028:22` (14%) хард-блокированы; `66:41:0204016:229` (нет sub-17) → can_build=true и **даёт financial_estimate**. ## Фикс (area-gate) - `_get_zouit_overlaps` + `_get_cad_zouit_overlaps`: `coverage_pct` (доля площади участка под зоной, geography м², `NULLIF`-guard от /0). - `compute_gate_verdict`: sub-17 (и cad network/blocker) **агрегируются** (sum-capped — консервативно к блоку) → блокер **только** если покрытие > `settings.gate_zouit_engineering_blocker_min_coverage` (**0.6**, env-tunable), иначе **`ZOUIT_ENGINEERING_PARTIAL` warning** с % покрытия. Больше нет 4× дубль-блокеров. - СЗЗ/OKN/прочие ЗОУИТ — без изменений (warnings). `main_vri`/резидентность — без изменений. - `coverage_pct` отсутствует (legacy/synthetic) → 0 → warning (документировано: дамп всегда даёт coverage; ложный хард-блок дороже). ## Ожидаемый эффект Прод: thin-strip Ж-5 участки (6-22% покрытия) → `can_build=False`→**`True`** + `ZOUIT_ENGINEERING_PARTIAL` warning → **financial_estimate фаерит** для развязанной buildable-массы. Провалидирую на проде. ## Test plan - [x] +помесь тестов: area-gate (thin→warning, full→blocker), агрегация (sum-capped, many-small-strips, missing→0), coverage helper, verdict end-to-end (residential+thin→can_build=True; +full→False). 131 combined passed. - [x] **Полный бэкенд локально: 3459 passed, 0 failed**, coverage 70.35% (gate 65%). ruff чисто. psycopg3 чисто (`::geography` приклеен к `)`, не к `:bind`). - [x] Схема не менялась (`gate_verdict`/`nspd_zouit_overlaps` = `dict[str,Any]`) → api-types regen не нужен. - [x] code-review: **2× approve, 0 majors** (adversarial under-blocking lens: parcel-fraction в geography, sum-capped к блоку, threshold tunable, missing→warning безопасно). ## Порог 0.6 Продуктовое решение по прод-распределению (median 6%, p90 47% → блокирует только экстремальный хвост). Tunable через `GATE_ZOUIT_ENGINEERING_BLOCKER_MIN_COVERAGE`. Refs #1881 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bot-backend added 1 commit 2026-06-24 09:57:01 +00:00
fix(gate): area-gate ЗОУИТ utility-easement blocker (sub-17) — снять over-block
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 1m52s
CI / backend-tests (pull_request) Successful in 11m34s
bc1da8eac9
ZOUIT_OVERLAP_SUB17 (единственный subcategory-blocker = охранная зона
ЛЭП/газа/трубопровода) был ХАРД-блокером на ЛЮБОЕ пересечение → блокировал
434/574 (75.6%) участков как «нельзя строить МКД». Прод-замер: реальное
покрытие участка этими зонами median=6%, p90=47%, только 1/17 >60% — тонкие
инж-коридоры. По РФ охранная зона ограничивает застройку ВНУТРИ полосы, а не
весь участок (МКД сажается на незанятой части). Хард-блок на 6%-покрытии неверен
и (после фикса резолва зон #1891) прятал financial_estimate у ~90% участков.

Фикс: area-gate.
- quarter_dump_lookup._get_zouit_overlaps + _get_cad_zouit_overlaps: добавлен
  coverage_pct (доля площади участка под зоной, в geography м², NULLIF-guard).
- gate_verdict.compute_gate_verdict: sub-17 (и cad network/blocker) АГРЕГИРУЮТСЯ
  (sum-capped, консервативно к блоку) → блокер ТОЛЬКО если покрытие >
  settings.gate_zouit_engineering_blocker_min_coverage (0.6, env-tunable), иначе
  WARNING ZOUIT_ENGINEERING_PARTIAL с % покрытия. Больше нет 4× дубль-блокеров.
  СЗЗ/OKN/прочие ЗОУИТ — без изменений (warnings). main_vri/резидентность — без
  изменений.
- coverage_pct отсутствует (legacy/synthetic) → трактуем как 0 → warning
  (документировано: дамп всегда даёт coverage; ложный хард-блок дороже).

Тесты: +помесь gate/aggregation/coverage (131 combined passed); правка
_make_zouit_row (7-я колонка coverage_pct) в tests/test_quarter_dump_lookup.py.
Полный бэкенд локально: 2 failed → fixed → перепроверка. ruff чисто. Схема не
менялась (gate_verdict/overlaps — dict[str,Any], api-types regen не нужен).

Refs #1881
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
bot-backend merged commit a45dfd4ee3 into main 2026-06-24 10:09:09 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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#1892
No description provided.