fix(tradein/matching): город развёртки доезжает до стража Tier-2a — межгородские склейки домов (#2777) #2808

Merged
bot-backend merged 1 commit from fix/2777-cross-city-matching into main 2026-08-10 08:51:15 +00:00

1 commit

Author SHA1 Message Date
f2b56c52b1 fix(tradein/matching): город развёртки доезжает до стража Tier-2a, адрес дозаполняется
All checks were successful
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 7s
CI / changes (pull_request) Successful in 8s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 4m1s
Бескоординатная карточка областного формата («ул. Кирова,4» — города в адресе НЕТ)
садилась в одноимённый дом другого города: ключ Tier-2a = sha256(адрес|lat|lon), без
координат он вырождается в один нормализованный адрес и становится глобально уникальным
в house_address_aliases. Прод 2026-08-10: 7303 из 21603 алиасов — такие ключи, 6047 из них
без токена города вовсе. Страж от этой коллизии в матчере был, но выводил город из ТЕКСТА
адреса (resolve_city_token), а областной SERP города не называет — сам код это и описывал
как «residual, needs sweep-context».

Sweep-context был собран и не доезжал: save_listings знает город-цель batch'а, прогоняет
его через свой гео-guard и пишет в listings.city, а _link_listing_to_house города не
получал и у match_or_create_house такого параметра не было. Признак лежал в соседней
колонке той же строки. Теперь он идёт через границу вызова (Protocol → адаптер → хук),
и его достижимость сторожит тест по образцу #2674 — структурной проверки сигнатуры мало.

Город здесь — НЕЗАВИСИМОЕ наблюдение (какой город запрашивала развёртка), а не второе
поле, выведенное из той же строки адреса: ровно то, на чём в #2690 сорвалось усиление
ключа через gar_house_guid.

Отдельно: listings.address не обновлялся при ON CONFLICT вообще — строка, вставленная без
адреса, оставалась безадресной навсегда, даже когда следующий скрейп адрес приносил (прод:
862 строки). Это и есть «привязка при пустом адресе» из #2777: 95 таких строк имеют
house_id_fk, потому что в момент матчинга адрес БЫЛ (fingerprint/new без адреса структурно
невозможны — алиаса с пустым ключом на проде 0). Дозаполняем COALESCE(existing, new) —
перезапись откатила бы чистку адресов миграциями 062/108/124.

Потолок правки назван числом в коде: 30 из 35 межгородских склеек закрываются, 5 — нет
(приходящая карточка ЕКБ, алиас завёл областной дом; города владельца алиаса мы не знаем).
Посёлки внутри ЕКБ-развёртки (Кедровка, 12 км) не ловятся вовсе — гранулярность признака
город, не населённый пункт. Уже сшитые дома НЕ трогаются.

Refs #2777
2026-08-10 13:24:47 +05:00