bug(#232): cad_zouit fallback не срабатывает когда nspd_quarter_dumps вообще пуст (regression PR #240) #244

Closed
opened 2026-05-17 05:40:01 +00:00 by lekss361 · 1 comment
Owner

Симптом

После merge PR #240 (G2+G3) QA smoke на проде показал:

  • parcel_meta работает (G2)
  • nspd_zouit_overlaps всегда [] (G3 fallback не срабатывает)
  • gate_verdict.verdict_label = "Нужна проверка", warning NO_NSPD_DUMP

Reproducing:

curl -s -X POST https://gendsgn.ru/api/v1/parcels/66:41:0603016:194/analyze \
  | jq '{count: (.nspd_zouit_overlaps | length), gate: .gate_verdict.verdict_label}'
# → {"count": 0, "gate": "Нужна проверка"}

Тестировано на 6 ЕКБ-cad (:1, :10, 66:41:0303018:7, :194, :18, :12) — везде 0.

Root cause

В backend/app/services/site_finder/quarter_dump_lookup.py (~строки 150-151) _get_zouit_overlaps делает:

if not dump_row:  # nspd_quarter_dumps вообще пуст для этого quarter
    return make_empty_result()  # ← возврат ДО fallback path
# fallback срабатывает только когда dump_row exists AND zouit_count == 0

В то время как cad_zouit ЕСТЬ (3 483 строки, прямой ST_Intersects работает за ~1ms), fallback path недостижим, потому что для всех quarter'ов нет dump'а (nspd_quarter_dumps=0 строк глобально из-за blocked harvest_quarter — issue #244).

Fix

Inverter условие: fallback должен срабатывать и когда dump отсутствует:

zouit_count = (dump_row.zouit_count if dump_row else 0)
if zouit_count == 0:
    # try cad_zouit fallback (works even when dump_row is None)
    overlaps = _get_cad_zouit_overlaps(db, parcel_wkt)
    if overlaps:
        return ZouitResult(overlaps=overlaps, source="cad_zouit")
    return make_empty_result()
# ... existing NSPD path

Acceptance

  • POST /api/v1/parcels/66:41:0603016:194/analyze возвращает nspd_zouit_overlaps непустой массив (если в радиусе 200м есть охранные зоны)
  • Хотя бы у одного overlap source == "cad_zouit"
  • gate_verdict.blockers непустой когда есть «охранная зона трубопроводов» из cad_zouit
  • Regression: когда dump_row.zouit_count > 0 (после fix #244) — продолжаем использовать NSPD path, не cad_zouit

Severity

🟠 P1 regression — PR #240 заявил done, но G3 path на проде сейчас всегда пустой. Партнёр #244 (harvest_quarter fix) не разблокирует это — нужен отдельный fix условия.

Прикреплённые

  • PR #240: merge_commit 7d0bc4bb
  • Vault audits/issues_audit_2026_05_16.md — план
  • Vault domains/api/endpoints/Endpoint_Parcel_Analyze.md — текущий контракт

(QA discovery 2026-05-17 через playwright browser_evaluate fetch на cad 66:41:0603016:194)

## Симптом После merge PR #240 (G2+G3) QA smoke на проде показал: - `parcel_meta` ✅ работает (G2) - `nspd_zouit_overlaps` ❌ всегда `[]` (G3 fallback не срабатывает) - `gate_verdict.verdict_label` = "Нужна проверка", warning `NO_NSPD_DUMP` Reproducing: ```bash curl -s -X POST https://gendsgn.ru/api/v1/parcels/66:41:0603016:194/analyze \ | jq '{count: (.nspd_zouit_overlaps | length), gate: .gate_verdict.verdict_label}' # → {"count": 0, "gate": "Нужна проверка"} ``` Тестировано на 6 ЕКБ-cad (`:1`, `:10`, `66:41:0303018:7`, `:194`, `:18`, `:12`) — везде 0. ## Root cause В `backend/app/services/site_finder/quarter_dump_lookup.py` (~строки 150-151) `_get_zouit_overlaps` делает: ```python if not dump_row: # nspd_quarter_dumps вообще пуст для этого quarter return make_empty_result() # ← возврат ДО fallback path # fallback срабатывает только когда dump_row exists AND zouit_count == 0 ``` В то время как cad_zouit ЕСТЬ (3 483 строки, прямой ST_Intersects работает за ~1ms), fallback path недостижим, потому что для **всех** quarter'ов нет dump'а (`nspd_quarter_dumps=0` строк глобально из-за blocked harvest_quarter — issue #244). ## Fix Inverter условие: fallback должен срабатывать **и** когда dump отсутствует: ```python zouit_count = (dump_row.zouit_count if dump_row else 0) if zouit_count == 0: # try cad_zouit fallback (works even when dump_row is None) overlaps = _get_cad_zouit_overlaps(db, parcel_wkt) if overlaps: return ZouitResult(overlaps=overlaps, source="cad_zouit") return make_empty_result() # ... existing NSPD path ``` ## Acceptance - [ ] `POST /api/v1/parcels/66:41:0603016:194/analyze` возвращает `nspd_zouit_overlaps` непустой массив (если в радиусе 200м есть охранные зоны) - [ ] Хотя бы у одного overlap `source == "cad_zouit"` - [ ] `gate_verdict.blockers` непустой когда есть «охранная зона трубопроводов» из cad_zouit - [ ] Regression: когда `dump_row.zouit_count > 0` (после fix #244) — продолжаем использовать NSPD path, не cad_zouit ## Severity 🟠 **P1 regression** — PR #240 заявил done, но G3 path на проде сейчас всегда пустой. Партнёр #244 (harvest_quarter fix) не разблокирует это — нужен **отдельный** fix условия. ## Прикреплённые - PR #240: merge_commit `7d0bc4bb` - Vault `audits/issues_audit_2026_05_16.md` — план - Vault `domains/api/endpoints/Endpoint_Parcel_Analyze.md` — текущий контракт (QA discovery 2026-05-17 через playwright `browser_evaluate` fetch на cad `66:41:0603016:194`)
Collaborator

DRIFT — реализовано (ground-truth 2026-06-13), трекер отставал.

Regression-fix #240 реализован: quarter_dump_lookup.py:165 — при dump_row=None ставит harvest в очередь И делает _get_cad_zouit_overlaps fallback (не возврат до fallback). gate_verdict обрабатывает source=='cad_zouit'. Fallback достижим при пустом nspd_quarter_dumps. Closed.

**DRIFT — реализовано (ground-truth 2026-06-13), трекер отставал.** Regression-fix #240 реализован: quarter_dump_lookup.py:165 — при dump_row=None ставит harvest в очередь И делает _get_cad_zouit_overlaps fallback (не возврат до fallback). gate_verdict обрабатывает source=='cad_zouit'. Fallback достижим при пустом nspd_quarter_dumps. Closed.
Sign in to join this conversation.
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#244
No description provided.