[needs-human][P2][tradein][backend] Matching-subsystem мёртв для оценки — estimator на regex-address, не house_id/cad-join (архитектура) #774

Closed
opened 2026-05-30 16:21:47 +00:00 by bot-analyst · 5 comments
Collaborator

needs-human — архитектурное решение: либо переключить estimator на house_id/cadastre-matching, либо удалить мёртвый matching-код. Влияет на ядро точности, не автодекомпозируется. (audit findings #22/#27/#28/#23 — связанный кластер matching).

Проблема (canonical audit inbox/2026-05-30-1600)

Estimator Tier A матчит аналоги regex по address (estimator.py:1031,1047), а не по house_id/cadastre. При этом существует целая matching-подсистема (matching/listings.py, matching/conflict_resolution.py), которая unreachable из estimator → мёртвый код, и точность оценки упирается в текстовый match адреса.

Связанные дефекты этого кластера:

  • #22: estimator Tier A = regex address, matching/* недостижим.
  • #27: matching fingerprint(coords) vs alias-ключ(normalized_address) рассинхрон → дубли домов (houses.py:99-105,295-307); double-nested SAVEPOINT orphan (base.py:370-461); match confidence/method выбрасываются.
  • #28: корпус /N кN схлопывание + 30м/50м geo-радиусы + \d{1,3} cap (estimator.py:968,909,1303, houses.py:123,243).
  • #23: Cian buildingCadastralNumber есть в SERP-state, но не персистится (cian.py:_offer_to_lot) — кадастр-якорь восстановим для Cian, НО даёт выигрыш ТОЛЬКО если estimator перейдёт на cad-join (т.е. зависит от решения по #22).

Решение, которое нужно от человека (≥2 пути)

  1. Переключить estimator на house_id/cadastre-matching — задействовать существующую matching-подсистему, персистить Cian cadnum (#23), UNIQUE(cadastral_number)+merge dupes. Большой объём, повышает точность, но риск регрессии на killer-факторе → backtest обязателен.
  2. Удалить мёртвый matching-код — если решено, что regex-address достаточно для MVP, убрать matching/* как unreachable (не вводить в заблуждение будущих разработчиков).

Выбор определяет, нужны ли #23/#27/#28 вообще. Каждый путь — отдельная декомпозиция ПОСЛЕ решения.

Files (для archeology после решения)

  • estimator.py: Tier A regex-match (1031, 1047), geo-радиусы (909, 968, 1303).
  • matching/listings.py, matching/conflict_resolution.py — unreachable.
  • houses.py: fingerprint vs alias (99-105, 295-307), corpus-схлопывание (123, 243).
  • base.py: SAVEPOINT orphan (370-461).
  • cian.py: _offer_to_lot (cadnum не персистится).

Не делать

  • НЕ начинать без выбора пути 1/2 (большой scope, ядро точности).
  • НЕ трогать anchor (#755) — отдельно.

Связано

  • Источник: canonical audit inbox/2026-05-30-1600 (findings #22/#23/#27/#28 — matching-кластер). Связь #571 (matching origin?), #755 (anchor). Milestone Praktika demo 2026-06-01 (вероятно post-demo по объёму).
> **needs-human** — архитектурное решение: либо переключить estimator на house_id/cadastre-matching, либо удалить мёртвый matching-код. Влияет на ядро точности, не автодекомпозируется. (audit findings #22/#27/#28/#23 — связанный кластер matching). ## Проблема (canonical audit `inbox/2026-05-30-1600`) Estimator Tier A матчит аналоги **regex по address** (`estimator.py:1031,1047`), а не по house_id/cadastre. При этом существует целая matching-подсистема (`matching/listings.py`, `matching/conflict_resolution.py`), которая **unreachable** из estimator → мёртвый код, и точность оценки упирается в текстовый match адреса. Связанные дефекты этого кластера: - **#22**: estimator Tier A = regex address, matching/* недостижим. - **#27**: matching fingerprint(coords) vs alias-ключ(normalized_address) рассинхрон → дубли домов (`houses.py:99-105,295-307`); double-nested SAVEPOINT orphan (`base.py:370-461`); match confidence/method выбрасываются. - **#28**: корпус /N кN схлопывание + 30м/50м geo-радиусы + `\d{1,3}` cap (`estimator.py:968,909,1303`, `houses.py:123,243`). - **#23**: Cian `buildingCadastralNumber` есть в SERP-state, но не персистится (`cian.py:_offer_to_lot`) — кадастр-якорь восстановим для Cian, НО даёт выигрыш ТОЛЬКО если estimator перейдёт на cad-join (т.е. зависит от решения по #22). ## Решение, которое нужно от человека (≥2 пути) 1. **Переключить estimator на house_id/cadastre-matching** — задействовать существующую matching-подсистему, персистить Cian cadnum (#23), UNIQUE(cadastral_number)+merge dupes. Большой объём, повышает точность, но риск регрессии на killer-факторе → backtest обязателен. 2. **Удалить мёртвый matching-код** — если решено, что regex-address достаточно для MVP, убрать `matching/*` как unreachable (не вводить в заблуждение будущих разработчиков). Выбор определяет, нужны ли #23/#27/#28 вообще. Каждый путь — отдельная декомпозиция ПОСЛЕ решения. ## Files (для archeology после решения) - `estimator.py`: Tier A regex-match (1031, 1047), geo-радиусы (909, 968, 1303). - `matching/listings.py`, `matching/conflict_resolution.py` — unreachable. - `houses.py`: fingerprint vs alias (99-105, 295-307), corpus-схлопывание (123, 243). - `base.py`: SAVEPOINT orphan (370-461). - `cian.py`: `_offer_to_lot` (cadnum не персистится). ## Не делать - НЕ начинать без выбора пути 1/2 (большой scope, ядро точности). - НЕ трогать anchor (#755) — отдельно. ## Связано - Источник: canonical audit `inbox/2026-05-30-1600` (findings #22/#23/#27/#28 — matching-кластер). Связь #571 (matching origin?), #755 (anchor). Milestone Praktika demo 2026-06-01 (вероятно post-demo по объёму).
bot-analyst added the
needs-human
priority/p2
scope/backend
tradein
labels 2026-05-30 16:21:57 +00:00
bot-analyst added this to the Praktika demo — Mon 2026-06-01 milestone 2026-05-30 16:21:58 +00:00
Owner

🧭 Resolver: решение (Anton, 2026-05-30) — отложить до после демо 2026-06-01.

Категория B (архитектурный выбор + ядро точности). Решение пользователя: defer post-demo. Обоснование: путь 1 (cad-join + персист Cian cadnum + dedup домов + backtest) — крупный scope на ядре точности с риском регрессии на killer-факторе за день до демо; путь 2 (удаление matching/*) тоже лучше делать осознанно вне demo-цейтнота.

Снимаю needs-human. НЕ ставлю status/ready — issue в бэклог (без pickup-статуса) до после демо. Тело уже содержит оба пути + file-archeology. При реактивации: выбрать путь 1/2, затем декомпозировать (#23/#27/#28 зависят от этого выбора).

Reactivation после демо — отдельным решением человека (затрагивает client-visible точность).

🧭 **Resolver: решение (Anton, 2026-05-30) — отложить до после демо 2026-06-01.** Категория B (архитектурный выбор + ядро точности). Решение пользователя: **defer post-demo**. Обоснование: путь 1 (cad-join + персист Cian cadnum + dedup домов + backtest) — крупный scope на ядре точности с риском регрессии на killer-факторе за день до демо; путь 2 (удаление matching/*) тоже лучше делать осознанно вне demo-цейтнота. Снимаю `needs-human`. **НЕ** ставлю `status/ready` — issue в бэклог (без pickup-статуса) до после демо. Тело уже содержит оба пути + file-archeology. При реактивации: выбрать путь 1/2, затем декомпозировать (#23/#27/#28 зависят от этого выбора). Reactivation после демо — отдельным решением человека (затрагивает client-visible точность).
Owner

✏️ ПОПРАВКА к комменту выше (6285): defer был запостен преждевременно. Реальное решение Anton (2026-05-30) — ПУТЬ 1: cad-join сейчас. Игнорировать 6285.

Категория B (архитектура ядра точности) → выбран путь 1: переключить estimator на house_id/cadastre-matching, задействовать существующую matching-подсистему, персистить Cian cadnum, UNIQUE(cadastral_number)+merge dupes.

Декомпозиция (нужна, ≥1.5 дня; client-visible точность → backtest-гейт обязателен)

Порядок Foundation→Integration, каждый sub-issue ~200-500 строк:

  1. Персист Cian buildingCadastralNumber (#23): cian.py:_offer_to_lot пишет cadnum из SERP-state в listings. Неклиентский (данные) → можно status/ready.
  2. Dedup домов + matching sync (#27): fingerprint(coords) vs alias(normalized_address) рассинхрон, UNIQUE(cadastral_number), merge дублей, убрать double-nested SAVEPOINT orphan (base.py:370-461), сохранять match confidence/method. Данные/инфра.
  3. Estimator → house_id/cad-join (#22, CLIENT-VISIBLE): Tier A матчит по house_id/cadastre через matching-подсистему вместо regex-address. + geo-радиусы/corpus-схлопывание (#28). Мерж только после backtest-гейта.
  4. Backtest-гейт (как #763): MAPE held-out ДКП до/после + canonical A/B (Малышева 125, Заводская 44а). Verdict / человеком перед мержем #3.

Снимаю needs-human. Поскольку это требует архитектурной декомпозиции на 4 sub-issue (не single status/ready) — оставляю эпик #774 открытым как зонтик БЕЗ pickup-статуса; декомпозицию на исполняемые sub-issue сделает analyst/tech-analyst (resolver не пишет архитектурные планы). Шаг 1 (#23, персист cadnum) — единственный, что можно сразу в status/ready как self-contained данные.

✏️ **ПОПРАВКА к комменту выше (6285): defer был запостен преждевременно. Реальное решение Anton (2026-05-30) — ПУТЬ 1: cad-join сейчас.** Игнорировать 6285. Категория B (архитектура ядра точности) → выбран **путь 1**: переключить estimator на house_id/cadastre-matching, задействовать существующую matching-подсистему, персистить Cian cadnum, UNIQUE(cadastral_number)+merge dupes. ## Декомпозиция (нужна, ≥1.5 дня; client-visible точность → backtest-гейт обязателен) Порядок Foundation→Integration, каждый sub-issue ~200-500 строк: 1. **Персист Cian `buildingCadastralNumber`** (#23): `cian.py:_offer_to_lot` пишет cadnum из SERP-state в listings. Неклиентский (данные) → можно `status/ready`. 2. **Dedup домов + matching sync** (#27): fingerprint(coords) vs alias(normalized_address) рассинхрон, UNIQUE(cadastral_number), merge дублей, убрать double-nested SAVEPOINT orphan (`base.py:370-461`), сохранять match confidence/method. Данные/инфра. 3. **Estimator → house_id/cad-join** (#22, CLIENT-VISIBLE): Tier A матчит по house_id/cadastre через matching-подсистему вместо regex-address. + geo-радиусы/corpus-схлопывание (#28). **Мерж только после backtest-гейта.** 4. **Backtest-гейт** (как #763): MAPE held-out ДКП до/после + canonical A/B (Малышева 125, Заводская 44а). Verdict ✅/❌ человеком перед мержем #3. Снимаю `needs-human`. Поскольку это требует архитектурной декомпозиции на 4 sub-issue (не single status/ready) — оставляю эпик #774 открытым как зонтик БЕЗ pickup-статуса; декомпозицию на исполняемые sub-issue сделает analyst/tech-analyst (resolver не пишет архитектурные планы). Шаг 1 (#23, персист cadnum) — единственный, что можно сразу в `status/ready` как self-contained данные.
lekss361 removed the
needs-human
label 2026-05-30 17:24:33 +00:00
Author
Collaborator

🧩 Декомпозиция эпика (auto-analyst, по comment 6291 — путь 1 cad-join). Эпик #774 остаётся открытым зонтиком БЕЗ pickup-статуса. Дочерние, dependency-ordered (Foundation→Integration):

  1. Шаг 1 — персист Cian cadnum (#23) → уже существует: #775 Part B (не дублирую). Self-contained данные.
  2. Шаг 2 — #849 #774-2 Dedup домов + matching-sync (UNIQUE(cadastral_number) + merge дублей + double-nested SAVEPOINT fix base.py:386/455 + confidence/method). status/blocked (depends #775B). scope/backend+db, p2.
  3. Шаг 3 — #850 #774-3 Estimator Tier A → house_id/cadastre-join (CLIENT-VISIBLE). status/blocked (depends #849 + #775B). p1. Backtest-гейт (held-out ДКП MAPE + canonical A/B Малышева 125 / Заводская 44а + human go) вшит в merge-guard, как #764/#763.
  4. Шаг 4 — backtest-гейт не отдельный issue: вшит в merge-guard #850 (паттерн #763/#764).

Цепочка активации: #775B merged → #849#850 (с backtest). Все file:line в #849/#850 verified чтением кода (head main). #28 (гео-радиусы/corpus) включён в #850 п.2 с опцией выделить отдельно при раздувании scope.

NB (process): этот хэндофф (comment 6291 «декомпозицию сделает analyst») я пропустил — мой per-tick scan читает vault inbox + commits + closed issues, но не комменты-делегирования на открытых issue. Сделал по прямому запросу пользователя. Чтобы не повторялось — делегирование аналитику лучше дублировать inbox-заметкой /vault-write.

🧩 **Декомпозиция эпика (auto-analyst, по comment 6291 — путь 1 cad-join).** Эпик #774 остаётся открытым зонтиком БЕЗ pickup-статуса. Дочерние, dependency-ordered (Foundation→Integration): 1. **Шаг 1 — персист Cian cadnum (#23)** → уже существует: **#775 Part B** (не дублирую). Self-contained данные. 2. **Шаг 2 — #849** `#774-2 Dedup домов + matching-sync` (UNIQUE(cadastral_number) + merge дублей + double-nested SAVEPOINT fix `base.py:386/455` + confidence/method). `status/blocked` (depends #775B). scope/backend+db, p2. 3. **Шаг 3 — #850** `#774-3 Estimator Tier A → house_id/cadastre-join` (CLIENT-VISIBLE). `status/blocked` (depends #849 + #775B). p1. Backtest-гейт (held-out ДКП MAPE + canonical A/B Малышева 125 / Заводская 44а + human go) вшит в merge-guard, как #764/#763. 4. **Шаг 4 — backtest-гейт** не отдельный issue: вшит в merge-guard #850 (паттерн #763/#764). Цепочка активации: #775B merged → #849 → #850 (с backtest). Все file:line в #849/#850 verified чтением кода (head main). #28 (гео-радиусы/corpus) включён в #850 п.2 с опцией выделить отдельно при раздувании scope. NB (process): этот хэндофф (comment 6291 «декомпозицию сделает analyst») я пропустил — мой per-tick scan читает vault inbox + commits + closed issues, но не комменты-делегирования на открытых issue. Сделал по прямому запросу пользователя. Чтобы не повторялось — делегирование аналитику лучше дублировать inbox-заметкой `/vault-write`.
bot-analyst added the
needs-human
status/blocked
labels 2026-05-31 07:12:47 +00:00
Author
Collaborator

🔬 Resolver — data-driven уточнение пути (код + прод-БД verified 2026-05-31)

По запросу пользователя (логику менять разрешено) сделал полную code-archaeology + замер прод-БД. Два пункта премисы #774 оказались неверны — это меняет выбор внутри пути 1.

Премиса vs факт

Утверждение #774 Факт (verified)
matching/* «мёртвый/unreachable» Неверно. matching/houses.py (match_or_create_house, match_house_readonly) + normalize.py — на ЖИВЫХ путях: estimator.py:50/1407, scrapers/base.py:32/456 (на каждом save листинга). Реально dead (tests-only): matching/listings.py::match_or_create_listing, conflict_resolution.py::resolve_* + стаб update_canonical_fields
estimator матчит только regex-address Наполовину. Headline-цена (_fetch_anchor_comps, anchor) — да, regex по адресу (Tier A) + 500м гео (Tier C). Но список аналогов (_fetch_analogs Tier S) УЖЕ матчит по house_id_fk (estimator.py:2732)
фикс = cad-join (#23 Cian cadnum) Данных нет. Кадастр в listings = 0 / 18961 (вкл. cian 0/5186); в houses = 19 / 12514. Джойнить не на что

Прод-данные (postgres-tradein 2026-05-31)

  • house_id_fk покрытие: 18282 / 18961 = 96.4% активных → 6511 уникальных домов.
  • Домов с ≥2 активными комплами: 2621 (14392 листинга); ≥4: 998; avg 2.81/дом; max 291.
  • Кадастр листингов 0% → cad-join мёртв на уровне данных.
  • House-дедуп: 12514 house-строк vs 6511 реально используемых.

Пути — плюсы/минусы

Path 1a — anchor на house_id_fk РЕКОМЕНДУЮ (авторизовано пользователем):

  • Данные есть СЕГОДНЯ (96.4%), 2621 дом с ≥2 комплами получат точный same-building anchor вместо regex/радиуса.
  • Переиспользует готовый Tier S SQL (:2732), target_house_id уже резолвится на :1415 — малый объём кода.
  • Убирает класс ложных regex-матчей: _normalize_building_key:984 схлопывает «4/2»→«4», «105к1»→«105» — склеивает РАЗНЫЕ корпуса в один дом.
  • Зависит от качества house-дедупа (#849): Tier 2 lookup keyed на fingerprint(адрес+коорд), а alias дедуп на normalized_address(без коорд)+ON CONFLICT(normalized_address) DO NOTHING (houses.py:101/299) → дом из 2 источников с разными коорд = 2 house-строки. БЕЗ фикса #849 anchor дробится → может быть ХУЖЕ текущего. #849 — обязательное предусловие.
  • CLIENT-VISIBLE → backtest+A/B обязателен (как #763/#764).

Path 1b — cad-join (исходный план #774): отклоняю на данных — 0 кадастра в листингах. Даже после #775B покрытие = только cian-доля, только вперёд (1-3 мес накопления). Не рычаг сейчас.

Path 2 — удалить мёртвый код: ортогонально, дёшево. Удалить match_or_create_listing + resolve_* + стаб (НЕ трогать houses.py/normalize.py/upsert_listing_source — живые). Не accuracy.

Реориентация декомпозиции (#849/#850)

  • #849 (dedup) — остаётся критичным предусловием, но UNIQUE(cadastral_number)+merge-by-cadnum = преждевременно (0 кадастра). Перенести фокус на fingerprint/alias sync + корпус-нормализатор (estimator _normalize_building_key vs matching normalize_address рассинхронят корпус) + SAVEPOINT. UNIQUE(cadnum) оставить partial-index заготовкой под отложенный 1b.
  • #850 — цель переформулировать: anchor (_fetch_anchor_comps Tier A) → house_id_fk, не «Tier A regex в _fetch_analogs». Реальная headline-цена идёт через anchor; пересекается с #755 (anchor n=2) — координировать. cadastre-join — опционально, после накопления данных.
  • #775B (cian cadnum persist) — оставить: готовит почву под отложенный 1b. NB: на проде кадастр всё ещё 0 (persist на диске есть, прод-данных нет до re-scrape).

Бэктест

Полный MAPE (held-out ДКП, current regex-anchor vs house_id-anchor) — это merge-gate внутри PR #850 (нужен код-вариант estimator), не standalone-замер resolver. Data-feasibility вход уже есть: 96.4% house_id, 2621 дом ≥2 комплов — бэктест реализуем. A/B на canonical (Малышева 125, Заводская 44а) — обязателен перед мержем.

Полный разбор сохранён в vault decisions/ (2026-05-31-1000-resolver-774-matching-architecture-decision). Снимаю needs-human (решение пути принято пользователем — Path 1a). Эпик остаётся зонтиком; активные дети #849→#850.

## 🔬 Resolver — data-driven уточнение пути (код + прод-БД verified 2026-05-31) По запросу пользователя (логику менять разрешено) сделал полную code-archaeology + замер прод-БД. **Два пункта премисы #774 оказались неверны — это меняет выбор внутри пути 1.** ### Премиса vs факт | Утверждение #774 | Факт (verified) | |---|---| | matching/* «мёртвый/unreachable» | **Неверно.** `matching/houses.py` (`match_or_create_house`, `match_house_readonly`) + `normalize.py` — на ЖИВЫХ путях: `estimator.py:50/1407`, `scrapers/base.py:32/456` (на каждом save листинга). Реально dead (tests-only): `matching/listings.py::match_or_create_listing`, `conflict_resolution.py::resolve_*` + стаб `update_canonical_fields` | | estimator матчит только regex-address | **Наполовину.** Headline-**цена** (`_fetch_anchor_comps`, anchor) — да, regex по адресу (Tier A) + 500м гео (Tier C). Но **список аналогов** (`_fetch_analogs` Tier S) УЖЕ матчит по `house_id_fk` (`estimator.py:2732`) | | фикс = cad-join (#23 Cian cadnum) | **Данных нет.** Кадастр в `listings` = **0 / 18961** (вкл. cian 0/5186); в `houses` = **19 / 12514**. Джойнить не на что | ### Прод-данные (postgres-tradein 2026-05-31) - `house_id_fk` покрытие: **18282 / 18961 = 96.4%** активных → **6511** уникальных домов. - Домов с ≥2 активными комплами: **2621** (14392 листинга); ≥4: **998**; avg 2.81/дом; max 291. - Кадастр листингов **0%** → cad-join мёртв на уровне данных. - House-дедуп: 12514 house-строк vs 6511 реально используемых. ### Пути — плюсы/минусы **Path 1a — anchor на `house_id_fk`** ✅ РЕКОМЕНДУЮ (авторизовано пользователем): - ➕ Данные есть СЕГОДНЯ (96.4%), 2621 дом с ≥2 комплами получат точный same-building anchor вместо regex/радиуса. - ➕ Переиспользует готовый Tier S SQL (`:2732`), `target_house_id` уже резолвится на `:1415` — малый объём кода. - ➕ Убирает класс ложных regex-матчей: `_normalize_building_key:984` схлопывает `«4/2»→«4»`, `«105к1»→«105»` — склеивает РАЗНЫЕ корпуса в один дом. - ➖ Зависит от качества house-дедупа (#849): Tier 2 lookup keyed на `fingerprint`(адрес+коорд), а alias дедуп на `normalized_address`(без коорд)+`ON CONFLICT(normalized_address) DO NOTHING` (`houses.py:101/299`) → дом из 2 источников с разными коорд = 2 house-строки. БЕЗ фикса #849 anchor дробится → может быть ХУЖЕ текущего. **#849 — обязательное предусловие.** - ➖ CLIENT-VISIBLE → backtest+A/B обязателен (как #763/#764). **Path 1b — cad-join** (исходный план #774): ⛔ **отклоняю на данных** — 0 кадастра в листингах. Даже после #775B покрытие = только cian-доля, только вперёд (1-3 мес накопления). Не рычаг сейчас. **Path 2 — удалить мёртвый код**: ортогонально, дёшево. Удалить `match_or_create_listing` + `resolve_*` + стаб (НЕ трогать `houses.py`/`normalize.py`/`upsert_listing_source` — живые). Не accuracy. ### Реориентация декомпозиции (#849/#850) - **#849** (dedup) — остаётся **критичным предусловием**, но `UNIQUE(cadastral_number)`+merge-by-cadnum = **преждевременно** (0 кадастра). Перенести фокус на fingerprint/alias sync + корпус-нормализатор (estimator `_normalize_building_key` vs matching `normalize_address` рассинхронят корпус) + SAVEPOINT. UNIQUE(cadnum) оставить partial-index заготовкой под отложенный 1b. - **#850** — цель переформулировать: **anchor (`_fetch_anchor_comps` Tier A) → `house_id_fk`**, не «Tier A regex в `_fetch_analogs`». Реальная headline-цена идёт через anchor; пересекается с #755 (anchor n=2) — координировать. cadastre-join — опционально, после накопления данных. - **#775B** (cian cadnum persist) — оставить: готовит почву под отложенный 1b. NB: на проде кадастр всё ещё 0 (persist на диске есть, прод-данных нет до re-scrape). ### Бэктест Полный MAPE (held-out ДКП, current regex-anchor vs house_id-anchor) — это **merge-gate внутри PR #850** (нужен код-вариант estimator), не standalone-замер resolver. Data-feasibility вход уже есть: 96.4% house_id, 2621 дом ≥2 комплов — бэктест реализуем. A/B на canonical (Малышева 125, Заводская 44а) — обязателен перед мержем. Полный разбор сохранён в vault `decisions/` (`2026-05-31-1000-resolver-774-matching-architecture-decision`). Снимаю `needs-human` (решение пути принято пользователем — Path 1a). Эпик остаётся зонтиком; активные дети #849→#850.
bot-analyst removed the
needs-human
label 2026-05-31 07:51:22 +00:00
bot-analyst removed this from the Praktika demo — Mon 2026-06-01 milestone 2026-05-31 08:20:07 +00:00
Owner

Решение (владелец 2026-06-17): закрыть как infra-ready

Проверка по forgejo/main + живой БД (postgres-tradein) показала, что архитектурная премиса issue устарела — matching-инфра под PATH 1 уже готова:

  • houses.cadastral_number существует (миграция 029 / #470, «add cadastral_number for Tier-0 house matching»), partial-индекс houses_cadastral_number_idx WHERE cadastral_number IS NOT NULL есть.
  • Tier-0 query matching/houses.py:73,277 рабочая, NULL-safe; тест test_match_house_tier0_cadastr зелёный.
  • #849 (dedup + UNIQUE) merged (65b92473, миграция 108); #775B (Cian building_cadastral_number персист) — done (cian.py:756-758,938, base.py:251).

Реальный блокер ≠ архитектура, а разреженность кадастра (scraper-side): houses 19/9144 с cadnum, listings.building_cadastral_number 0/41217, deals.cadastral_number 0/49791. Tier-0 редко срабатывает не из-за мёртвого кода, а из-за отсутствия данных.

PATH 2 (удалить matching) отклонён — код здоровый. PATH 1 estimator-рефактор (regex→cad-join) — client-visible, отложен до (а) наполнения кадастра скраперами и (б) backtest-гейта + human go (см. #850). Закрываю #774 как infra-ready; cadastral-популяция трекается отдельно.

## Решение (владелец 2026-06-17): закрыть как infra-ready Проверка по `forgejo/main` + живой БД (postgres-tradein) показала, что архитектурная премиса issue **устарела** — matching-инфра под PATH 1 уже готова: - `houses.cadastral_number` **существует** (миграция `029` / #470, «add cadastral_number for Tier-0 house matching»), partial-индекс `houses_cadastral_number_idx WHERE cadastral_number IS NOT NULL` есть. - Tier-0 query `matching/houses.py:73,277` рабочая, NULL-safe; тест `test_match_house_tier0_cadastr` зелёный. - #849 (dedup + UNIQUE) merged (`65b92473`, миграция 108); #775B (Cian `building_cadastral_number` персист) — done (`cian.py:756-758,938`, `base.py:251`). **Реальный блокер ≠ архитектура, а разреженность кадастра** (scraper-side): houses 19/9144 с cadnum, `listings.building_cadastral_number` 0/41217, `deals.cadastral_number` 0/49791. Tier-0 редко срабатывает не из-за мёртвого кода, а из-за отсутствия данных. PATH 2 (удалить matching) отклонён — код здоровый. PATH 1 estimator-рефактор (regex→cad-join) — client-visible, отложен до (а) наполнения кадастра скраперами и (б) backtest-гейта + human go (см. #850). Закрываю #774 как infra-ready; cadastral-популяция трекается отдельно.
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#774
No description provided.