fix(tradein/estimator): устранить остаточные кросс-сорс дубли (#2291) #2417

Merged
lekss361 merged 2 commits from fix/tradein-dedup-residual-2291 into main 2026-07-04 12:58:16 +00:00
Owner

Summary

После трёх итераций (#2269, #2290, #2265) выживало 10.9% кросс-сорс дублей (705 из 6442; 127 — кадастр-конфликты by design, не трогаем). Этот PR закрывает 2 из 4 оставшихся классов (473 из ~578 нерешённых пар):

  • ё/е-нормализация (~60 пар)s.replace("ё","е") в _parse_street_house.
  • mkr-fallback misfire (334 пары) — новая ветка «bare-street перед номером дома» в _parse_street_house, между существующими type-word ветками и mkr-fallback. Для адресов вида «Заречный м-н, Готвальда, 24» (голая улица без типа-слова после района) — раньше mkr-fallback хватал район вместо реальной улицы.
  • Area-bucket straddle (139 пар) — ±1 допуск area-бакета в street-composite union внутри _dedup_cross_source (banker's rounding: 38.5→38 vs 39.0→39 держал живой дубль «Рассветной 6к1»). Скоуп строго на street-union, cadnum-union и сама area_bucket не тронуты.

Класс 4 (пустые токены, ~50 пар — «40-летия Комсомола,32Г» и т.п.) явно НЕ фиксится в этом PR — низкий ROI, частично нефиксируем регексом.

Adversarial review (deep-code-reviewer, 2 раунда):
1-й раунд — verdict major: bare-street ветка фабриковала уличный токен на голых 2-сегментных адресах без mkr/район-контекста («ВИЗ, 24», «Академический, 24», «ЖК Некий, 24» — раньше безопасно ("", ""), over-merge риск хуже исходного бага).
Fixup — ветка теперь требует явный mkr/район-маркер в БОЛЕЕ РАННЕМ сегменте (не просто «сегмент перед домом похож на улицу»). Reviewer протестировал живьём доп. 7+ adversarial-адресов (Компрессорный/Уралмаш/Химмаш/Ботанический/Пионерский и т.п.) — все корректно ("", "").
2-й раунд — verdict approve.

Regression guards (проверены живьём reviewer'ом)

  • мкр. ЖБИ, улица Сыромолотова("сыромолотова", "") (#2265, branch 1)
  • мкр Пионерский, 5 → mkr-fallback как раньше
  • Заречный м-н, Готвальда, 24("готвальда", "24") (целевой кейс)
  • Cadnum-конфликт + разный house-no по-прежнему блокируют area-tolerance union (guard_house не тронут)

Test plan

  • uv run --project backend pytest backend/tests/test_estimator_dedup_cross_source_2087.py backend/tests/test_estimator_anchor_dedup_gap_2265.py backend/tests/test_backtest_regression_gate.py -q — 58 passed
  • Полный backend test suite — зелёный (кроме 1 pre-existing неродственного test_search_cache_hit, известный ordering-артефакт)
  • Ruff чист
  • post-deploy: live-перезамер дублей на реальных данных (postgres-tradein) + проверка что «Рассветная 6к1» / cadastre 23b8ada1 схлопывается

Refs #2291

## Summary После трёх итераций (#2269, #2290, #2265) выживало 10.9% кросс-сорс дублей (705 из 6442; 127 — кадастр-конфликты by design, не трогаем). Этот PR закрывает 2 из 4 оставшихся классов (473 из ~578 нерешённых пар): - **ё/е-нормализация (~60 пар)** — `s.replace("ё","е")` в `_parse_street_house`. - **mkr-fallback misfire (334 пары)** — новая ветка «bare-street перед номером дома» в `_parse_street_house`, между существующими type-word ветками и mkr-fallback. Для адресов вида «Заречный м-н, Готвальда, 24» (голая улица без типа-слова после района) — раньше mkr-fallback хватал район вместо реальной улицы. - **Area-bucket straddle (139 пар)** — ±1 допуск area-бакета в street-composite union внутри `_dedup_cross_source` (banker's rounding: 38.5→38 vs 39.0→39 держал живой дубль «Рассветной 6к1»). Скоуп строго на street-union, cadnum-union и сама `area_bucket` не тронуты. Класс 4 (пустые токены, ~50 пар — «40-летия Комсомола,32Г» и т.п.) явно НЕ фиксится в этом PR — низкий ROI, частично нефиксируем регексом. **Adversarial review (deep-code-reviewer, 2 раунда):** 1-й раунд — verdict `major`: bare-street ветка фабриковала уличный токен на голых 2-сегментных адресах без mkr/район-контекста («ВИЗ, 24», «Академический, 24», «ЖК Некий, 24» — раньше безопасно `("", "")`, over-merge риск хуже исходного бага). Fixup — ветка теперь требует явный mkr/район-маркер в БОЛЕЕ РАННЕМ сегменте (не просто «сегмент перед домом похож на улицу»). Reviewer протестировал живьём доп. 7+ adversarial-адресов (Компрессорный/Уралмаш/Химмаш/Ботанический/Пионерский и т.п.) — все корректно `("", "")`. 2-й раунд — **verdict `approve`.** ## Regression guards (проверены живьём reviewer'ом) - `мкр. ЖБИ, улица Сыромолотова` → `("сыромолотова", "")` (#2265, branch 1) - `мкр Пионерский, 5` → mkr-fallback как раньше - `Заречный м-н, Готвальда, 24` → `("готвальда", "24")` (целевой кейс) - Cadnum-конфликт + разный house-no по-прежнему блокируют area-tolerance union (guard_house не тронут) ## Test plan - [x] `uv run --project backend pytest backend/tests/test_estimator_dedup_cross_source_2087.py backend/tests/test_estimator_anchor_dedup_gap_2265.py backend/tests/test_backtest_regression_gate.py -q` — 58 passed - [x] Полный backend test suite — зелёный (кроме 1 pre-existing неродственного `test_search_cache_hit`, известный ordering-артефакт) - [x] Ruff чист - [ ] post-deploy: live-перезамер дублей на реальных данных (postgres-tradein) + проверка что «Рассветная 6к1» / cadastre 23b8ada1 схлопывается Refs #2291
lekss361 added 2 commits 2026-07-04 12:52:53 +00:00
bare-street branch before mkr-fallback (334), е/е fold (~60), +-1 area-bucket
tolerance on street-union (139) - class 4 (empty tokens, ~50) explicitly deferred, low ROI.
fix(tradein/estimator): сузить bare-street ветку до 3-сегментного district-chain паттерна (#2291)
All checks were successful
CI / changes (pull_request) Successful in 8s
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 1m0s
0de77690e9
Deep-review нашёл over-merge риск: bare-street ветка фабриковала уличный токен на голых
2-сегментных адресах без mkr/район-контекста ("ВИЗ, 24" и т.п.) — теперь требует явный
mkr-маркер в более раннем сегменте, ограничивая ветку заявленным 3-сегментным паттерном.
lekss361 merged commit a0c609caf4 into main 2026-07-04 12:58:16 +00:00
lekss361 deleted branch fix/tradein-dedup-residual-2291 2026-07-04 12:58:16 +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#2417
No description provided.