[CRITICAL] tradein: Tier A «тот же дом» матчит листинги по всей области без гео-предиката → цена в 4-5 раз выше реальной #2581

Closed
opened 2026-07-31 14:02:17 +00:00 by lekss361 · 0 comments
Owner

Найдено веерным аудитом тихих дефектов (эпик #2576), подтверждено состязательной проверкой. Самая опасная находка: уверенная неверная цена, помеченная самым доверенным тиром.

Суть

backend/app/services/estimator.py:1764-1783 (_fetch_anchor_comps), ключ — _normalize_building_key:1649.

SQL якорного тира: LIKE '%<улица>%' AND address ~ <house_re>ни ST_DWithin, ни города, ни house_id_fk, ни LIMIT. При этом _normalize_building_key намеренно выбрасывает городские токены, поэтому «Серов, ул. Ленина, 5» и екатеринбургский «пр. Ленина, 5» дают идентичный ключ. Из ~40 200 активных листингов ~40 191 — Екатеринбург.

Это единственный запрос к listings в файле без гео-предиката (в соседних местах ST_DWithin есть: строки 1860, 4761, 4849, 4975).

Вред

«Серов, ул. Ленина, 5», 2к 50 м² → якорь по екатеринбургским листингам ≈150-190 тыс ₽/м² → итог 8-9 млн вместо ~1.7 млн. Помечено тиром same_building, текст «Оценка построена по N аналогам из того же дома», уверенность high/medium.

Почему все страховки не срабатывают

Отключены структурно именно при anchor_tier == 'A':

  • _apply_corridor_clamp:5186-5189 — ранний возврат для 'A', городской коридор ДКП физически не может прижать результат;
  • radius-floor :2827 требует anchor is None;
  • понижение из-за грубой геолокации :3036 — явное != "A";
  • MAD-отсечка :1996-2005 для 'A' ослаблена;
  • гейт #audit-1 недостижим (n≥4 by construction).

Хуже всего: глушит честный областной путь

#oblast-D deals-headline-fallback:2980-2986 требует anchor_tier is None. То есть ровно для городов, ради которых делался областной фолбэк по сделкам Росреестра, утёкший екатеринбургский якорь отменяет правильную цену.

Близнец уже чинился

Тот же дефект в Tier S (_fetch_analogs:4761) закрыт коммитом f9ae6f0c с прод-цифрами: «Серов ask-head 186k vs sold 30k; Н.Тагил 187k vs deal-corridor 89k». В якорный путь фикс не внесли. Комментарий :1902-1908 («same-building anchor pool для oblast не формируется») — ложная посылка.

Тест-страж test_estimator_deals_headline_fallback_oblast_d.py:71 использует MagicMock(), из-за чего Tier A возвращает пустоту и регрессия для набора тестов невидима.

Что сделать

Добавить гео-ограничение в якорный запрос (по образцу уже починенного Tier S) и/или вернуть городской токен в ключ здания. Обязательно: тест на кейсе «Серов, Ленина, 5» с екатеринбургскими листингами в базе, который падает до фикса. Плюс починить тест-страж, чтобы он перестал быть слепым.

Найдено веерным аудитом тихих дефектов (эпик #2576), подтверждено состязательной проверкой. **Самая опасная находка: уверенная неверная цена, помеченная самым доверенным тиром.** ## Суть `backend/app/services/estimator.py:1764-1783` (`_fetch_anchor_comps`), ключ — `_normalize_building_key:1649`. SQL якорного тира: `LIKE '%<улица>%' AND address ~ <house_re>` — **ни `ST_DWithin`, ни города, ни `house_id_fk`, ни LIMIT**. При этом `_normalize_building_key` намеренно выбрасывает городские токены, поэтому «Серов, ул. Ленина, 5» и екатеринбургский «пр. Ленина, 5» дают идентичный ключ. Из ~40 200 активных листингов ~40 191 — Екатеринбург. Это единственный запрос к `listings` в файле без гео-предиката (в соседних местах `ST_DWithin` есть: строки 1860, 4761, 4849, 4975). ## Вред «Серов, ул. Ленина, 5», 2к 50 м² → якорь по екатеринбургским листингам ≈150-190 тыс ₽/м² → итог **8-9 млн вместо ~1.7 млн**. Помечено тиром `same_building`, текст «Оценка построена по N аналогам из того же дома», уверенность high/medium. ## Почему все страховки не срабатывают Отключены структурно **именно при** `anchor_tier == 'A'`: - `_apply_corridor_clamp:5186-5189` — ранний возврат для 'A', городской коридор ДКП физически не может прижать результат; - radius-floor `:2827` требует `anchor is None`; - понижение из-за грубой геолокации `:3036` — явное `!= "A"`; - MAD-отсечка `:1996-2005` для 'A' ослаблена; - гейт `#audit-1` недостижим (n≥4 by construction). ## Хуже всего: глушит честный областной путь `#oblast-D deals-headline-fallback:2980-2986` требует `anchor_tier is None`. То есть **ровно для городов, ради которых делался областной фолбэк по сделкам Росреестра**, утёкший екатеринбургский якорь отменяет правильную цену. ## Близнец уже чинился Тот же дефект в Tier S (`_fetch_analogs:4761`) закрыт коммитом f9ae6f0c с прод-цифрами: «Серов ask-head 186k vs sold 30k; Н.Тагил 187k vs deal-corridor 89k». В якорный путь фикс не внесли. Комментарий `:1902-1908` («same-building anchor pool для oblast не формируется») — **ложная посылка**. Тест-страж `test_estimator_deals_headline_fallback_oblast_d.py:71` использует `MagicMock()`, из-за чего Tier A возвращает пустоту и регрессия для набора тестов невидима. ## Что сделать Добавить гео-ограничение в якорный запрос (по образцу уже починенного Tier S) и/или вернуть городской токен в ключ здания. Обязательно: тест на кейсе «Серов, Ленина, 5» с екатеринбургскими листингами в базе, который падает до фикса. Плюс починить тест-страж, чтобы он перестал быть слепым.
Sign in to join this conversation.
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#2581
No description provided.