[EPIC] ПТИЦА analysis report — UX + data-honesty аудит (на примере 66:41:0205010:287) #1953

Closed
opened 2026-06-27 08:44:13 +00:00 by bot-backend · 6 comments
Collaborator

Контекст

Живой walkthrough отчёта Site Finder на реальном участке 66:41:0205010:287 (Ремпутьмаш, Железнодорожный р-н, ЕКБ, ~10.54 га, ВРИ «земли под объектами ж/д транспорта», внутри СЗЗ собственного завода). Страница /site-finder/analysis/... рендерит старый light-отчёт (Section1–6: AnalysisPageContent → Section1ParcelInfo → EgrnPropertyTable), не кокпит /ptica.

Расследование (8 агентов, доведено до root-cause с прод-доказательствами) выявило 16 багов, 9 data-quality, 11 jargon/UX, 7 фич-запросов.

Два главных вывода

  1. 🔴 Индекс дефицита = −1.00 ВЕЗДЕ — вырожденный (basis mismatch), не реальный сигнал. Спрос = district-wide велосити (все классы/форматы), сегмент применяется только в demand-no-op; предложение = весь сток района → спрос ≪ предложения → clamp −1.0. Обесценивает весь Раздел 6 (сценарии, вердикты «избегать», квартирография). → #I6
  2. 🟠 «Срок продажи 0 мес» / «% продано —» — регрессия от #1944: _SUPPLY_BATCH_SQL джойнит flats по глобальной MAX(snapshot_date), а domrf_kn_flats per-object → supply=0. → #I3

Смысловой вывод по участку: он в СЗЗ собственного завода → жильё ограничено по СанПиН 2.2.1/2.1.1.1200-03 → фин-модель пустая (корректно). Это надо показывать явно (баннер). → #I4

Дочерние задачи

  • P0 I1 — Объект-карточка: площадь/обременения/«обновлено»
  • P0 I2 — «Что хорошо продаётся»: дубли бакетов + фантом Comfort/Комфорт
  • P0 I3 — 4.2: срок продажи 0 мес / %продано (per-object snapshot, регрессия #1944)
  • P0 I4 — ЗОУИТ: сырой cad_zouit/дубли + СЗЗ-смысл/баннер
  • P0 I5 — График дефицита: оси + плоское состояние; фактор «Прогноз» ×4
  • P0 I6 — Индекс дефицита −1.00 везде (basis mismatch) + honesty-guard
  • P1 I7 — Медиана рынка 64k (квартальная n=1 ДКП-медиана)
  • P1 I8 — Сети/точки не на карте
  • P1 I9 — Градрегламент НСПД в Раздел 1
  • P2 I10 — Человеческий язык / микрокопия (6.2/6.3/6.5 + легенды)
  • P2 I11 — Data-quality: objective_lots раздут, n_sold аномалия, registration_date
  • feat I12 — Консолидация фин-модели/Концепции + house-picker → 3D → пересчёт

Номера дочерних — в комментарии ниже.

## Контекст Живой walkthrough отчёта Site Finder на реальном участке **66:41:0205010:287** (Ремпутьмаш, Железнодорожный р-н, ЕКБ, ~10.54 га, ВРИ «земли под объектами ж/д транспорта», **внутри СЗЗ собственного завода**). Страница `/site-finder/analysis/...` рендерит старый light-отчёт (Section1–6: `AnalysisPageContent → Section1ParcelInfo → EgrnPropertyTable`), не кокпит `/ptica`. Расследование (8 агентов, доведено до root-cause с прод-доказательствами) выявило 16 багов, 9 data-quality, 11 jargon/UX, 7 фич-запросов. ## Два главных вывода 1. 🔴 **Индекс дефицита = −1.00 ВЕЗДЕ — вырожденный (basis mismatch), не реальный сигнал.** Спрос = district-wide велосити (все классы/форматы), сегмент применяется только в demand-no-op; предложение = весь сток района → спрос ≪ предложения → clamp −1.0. Обесценивает весь Раздел 6 (сценарии, вердикты «избегать», квартирография). → #I6 2. 🟠 **«Срок продажи 0 мес» / «% продано —» — регрессия от #1944**: `_SUPPLY_BATCH_SQL` джойнит flats по глобальной `MAX(snapshot_date)`, а `domrf_kn_flats` per-object → supply=0. → #I3 Смысловой вывод по участку: он в **СЗЗ собственного завода** → жильё ограничено по СанПиН 2.2.1/2.1.1.1200-03 → фин-модель пустая (корректно). Это надо показывать явно (баннер). → #I4 ## Дочерние задачи - [ ] P0 I1 — Объект-карточка: площадь/обременения/«обновлено» - [ ] P0 I2 — «Что хорошо продаётся»: дубли бакетов + фантом Comfort/Комфорт - [ ] P0 I3 — 4.2: срок продажи 0 мес / %продано (per-object snapshot, регрессия #1944) - [ ] P0 I4 — ЗОУИТ: сырой cad_zouit/дубли + СЗЗ-смысл/баннер - [ ] P0 I5 — График дефицита: оси + плоское состояние; фактор «Прогноз» ×4 - [ ] P0 I6 — Индекс дефицита −1.00 везде (basis mismatch) + honesty-guard - [ ] P1 I7 — Медиана рынка 64k (квартальная n=1 ДКП-медиана) - [ ] P1 I8 — Сети/точки не на карте - [ ] P1 I9 — Градрегламент НСПД в Раздел 1 - [ ] P2 I10 — Человеческий язык / микрокопия (6.2/6.3/6.5 + легенды) - [ ] P2 I11 — Data-quality: objective_lots раздут, n_sold аномалия, registration_date - [ ] feat I12 — Консолидация фин-модели/Концепции + house-picker → 3D → пересчёт Номера дочерних — в комментарии ниже.
Author
Collaborator

Дочерние задачи (заведены)

P0 — баги/честность данных

  • #1954 — Объект-карточка: площадь/обременения/«обновлено»
  • #1955 — «Что хорошо продаётся»: дубли бакетов + фантом Comfort/Комфорт
  • #1956 — 4.2: срок продажи 0 мес / %продано (per-object snapshot, регрессия #1944)
  • #1957 — ЗОУИТ: сырой cad_zouit/дубли + СЗЗ-смысл/баннер
  • #1958 — График дефицита: оси + плоское состояние; фактор «Прогноз» ×4
  • #1959Индекс дефицита −1.00 везде (basis mismatch) + honesty-guard ← главный

P1

  • #1960 — Медиана рынка 64k (квартальная n=1 ДКП-медиана)
  • #1961 — Сети/точки не на карте
  • #1962 — Градрегламент НСПД в Раздел 1

P2

  • #1963 — Человеческий язык / микрокопия (6.2/6.3/6.5 + легенды)
  • #1964 — Data-quality: objective_lots раздут, n_sold аномалия, registration_date

feat

  • #1965 — Консолидация фин-модели/Концепции + house-picker → 3D → пересчёт

Порядок реализации

  1. Батч 1 (быстрые P0, бэкенд parcels.py + view): #1954 (площадь/обновлено), #1960 (медиана threshold), #1955 (obj_class), #1958 (forecast ×4), #1957 (ЗОУИТ дедуп/маппинг).
  2. Батч 2 (фронт light-отчёт): #1954 (encumbrance/fallback), #1958 (оси/flat-state), #1957 (баннер СЗЗ), #1962 (градрегламент), #1961 (карта).
  3. Батч 3 (data-honesty ядро): #1959 (сегментация спроса/предложения) + #1956 (per-object snapshot) — связаны.
  4. Батч 4 (UX-микрокопия): #1963.
  5. Отдельно: #1964 (data-quality расследования), #1965 (фича, обсудить скоуп).
## Дочерние задачи (заведены) **P0 — баги/честность данных** - #1954 — Объект-карточка: площадь/обременения/«обновлено» - #1955 — «Что хорошо продаётся»: дубли бакетов + фантом Comfort/Комфорт - #1956 — 4.2: срок продажи 0 мес / %продано (per-object snapshot, регрессия #1944) - #1957 — ЗОУИТ: сырой cad_zouit/дубли + СЗЗ-смысл/баннер - #1958 — График дефицита: оси + плоское состояние; фактор «Прогноз» ×4 - #1959 — **Индекс дефицита −1.00 везде (basis mismatch) + honesty-guard** ← главный **P1** - #1960 — Медиана рынка 64k (квартальная n=1 ДКП-медиана) - #1961 — Сети/точки не на карте - #1962 — Градрегламент НСПД в Раздел 1 **P2** - #1963 — Человеческий язык / микрокопия (6.2/6.3/6.5 + легенды) - #1964 — Data-quality: objective_lots раздут, n_sold аномалия, registration_date **feat** - #1965 — Консолидация фин-модели/Концепции + house-picker → 3D → пересчёт ### Порядок реализации 1. **Батч 1 (быстрые P0, бэкенд `parcels.py` + view):** #1954 (площадь/обновлено), #1960 (медиана threshold), #1955 (obj_class), #1958 (forecast ×4), #1957 (ЗОУИТ дедуп/маппинг). 2. **Батч 2 (фронт light-отчёт):** #1954 (encumbrance/fallback), #1958 (оси/flat-state), #1957 (баннер СЗЗ), #1962 (градрегламент), #1961 (карта). 3. **Батч 3 (data-honesty ядро):** #1959 (сегментация спроса/предложения) + #1956 (per-object snapshot) — связаны. 4. **Батч 4 (UX-микрокопия):** #1963. 5. **Отдельно:** #1964 (data-quality расследования), #1965 (фича, обсудить скоуп).
Author
Collaborator

Прогресс (сессия 2026-06-27)

Отгружено на прод + verified live:

  • #1954 — площадь (106378), «обновлено» (2026-06-19), обременения (ЗОУИТ:4) — backend PR #1973 + frontend PR #1985
  • #1955 — obj_class проброшен + фантом Comfort→«не указан» (PR #1978) + лейбл «бакет · класс» (PR #1985)
  • #1957 — ЗОУИТ типизация/дедуп (PR #1973) + СЗЗ-баннер/type_zone (PR #1985)
  • #1958 — forecast-фактор ×4→×1 (PR #1973) + оси графика + flat-state (PR #1985)
  • #1960 — медиана 64k→132690 (новостроечный базис) + recommend_mix regression (PR #1978)
  • #1962 — градрегламент НСПД в Раздел 1 + coerceFloat КСИТ-фикс 3D (PR #1987)
  • #1963 — человеческий язык 6.2/6.3/6.5 + легенда дефицита/затоварки (PR #1988)
  • #1961 — сети/точки на карте: репроекция 3857→4326 + полигон-центроиды + радиус 500→2000 (PR #1998); follow-up: backend-geom для osm_noise_sources_ekb (1:1)
  • инфра: prettier 3.9.0 pin (repo-wide CI unblock, PR #1981)

В работе:

  • 🟡 #1959 — индекс дефицита (сегментация спроса+предложения + дедуп-внутри-расчёта). Скоуп сужен: дедуп objective_lots только в forecast-calc (НЕ platform-wide).

Осталось:

  • #1956 — «срок продажи 0 мес» / «% продано —» (per-object snapshot в _SUPPLY_BATCH_SQL, регрессия #1944) — ещё не сделан, следующий
  • #1964 — platform-wide дедуп objective_lots (1.75M) + n_sold аномалия — отдельный осознанный cleanup (частично закрывается дедупом из #1959)
  • #1965 — фича 3D house-picker — отдельный эпик, скоуп на обсуждение

Мелкие follow-up: max_height_m coercion (тот же класс что #1962), скрытие пустой «дата регистрации».

## Прогресс (сессия 2026-06-27) **Отгружено на прод + verified live:** - ✅ #1954 — площадь (106378), «обновлено» (2026-06-19), обременения (ЗОУИТ:4) — backend PR #1973 + frontend PR #1985 - ✅ #1955 — obj_class проброшен + фантом Comfort→«не указан» (PR #1978) + лейбл «бакет · класс» (PR #1985) - ✅ #1957 — ЗОУИТ типизация/дедуп (PR #1973) + СЗЗ-баннер/type_zone (PR #1985) - ✅ #1958 — forecast-фактор ×4→×1 (PR #1973) + оси графика + flat-state (PR #1985) - ✅ #1960 — медиана 64k→132690 (новостроечный базис) + recommend_mix regression (PR #1978) - ✅ #1962 — градрегламент НСПД в Раздел 1 + coerceFloat КСИТ-фикс 3D (PR #1987) - ✅ #1963 — человеческий язык 6.2/6.3/6.5 + легенда дефицита/затоварки (PR #1988) - ✅ #1961 — сети/точки на карте: репроекция 3857→4326 + полигон-центроиды + радиус 500→2000 (PR #1998); *follow-up: backend-geom для osm_noise_sources_ekb (1:1)* - ✅ инфра: prettier 3.9.0 pin (repo-wide CI unblock, PR #1981) **В работе:** - 🟡 #1959 — индекс дефицита (сегментация спроса+предложения + дедуп-внутри-расчёта). Скоуп сужен: дедуп `objective_lots` только в forecast-calc (НЕ platform-wide). **Осталось:** - ⏳ #1956 — «срок продажи 0 мес» / «% продано —» (per-object snapshot в `_SUPPLY_BATCH_SQL`, регрессия #1944) — ещё не сделан, следующий - ⏳ #1964 — platform-wide дедуп `objective_lots` (1.75M) + n_sold аномалия — отдельный осознанный cleanup (частично закрывается дедупом из #1959) - ⏳ #1965 — фича 3D house-picker — отдельный эпик, скоуп на обсуждение Мелкие follow-up: `max_height_m` coercion (тот же класс что #1962), скрытие пустой «дата регистрации».
Author
Collaborator

Финал: все баги/UX/честность отгружены и verified на проде

Закрыто (deployed + прод-verified):

  • #1954 #1955 #1957 #1958 #1960 #1961 #1962 #1963 (PR #1973/#1978/#1985/#1987/#1988/#1998/#1981)
  • #1959 — индекс дефицита больше не −1.0 везде: 12 ячеек / 7 разных значений; MOI комфорт-студия 38.5 vs стандарт-студия 244 (PR #2018, миграция 173 применена)
  • #1956 — supply 0→502/487/225/220, sold_pct 5.8/5.7/3.6/2.7 (не «—»); per-object snapshot (PR #2020)

Итог: 10 PR + repo-wide CI-фикс (prettier pin). Медиана 64k→132690, ЗОУИТ→СЗЗ-баннер, градрегламент НСПД, человеческий язык 6.x, точки на карте, дефицит дифференцируется.

Остаётся (отдельно)

  • #1964 — platform-wide дедуп RAW objective_lots (1.75M) + n_sold=99110 аномалия. Частично закрыт безусловным дедупом из #1959 (compute_market_metrics); полный raw-cleanup отдельно.
  • #1965 — фича house-picker→3D→пересчёт (MassingScene есть, но разорван с compute_financial). Multi-day, скоуп на обсуждение.
  • Мелочь: композит-индекс (obj_id,snapshot_date) на domrf_kn_flats; max_height_m coercion (тот же класс что #1962); backend-geom osm_noise_sources_ekb (карта 1:1, #1961); скрытие пустой «дата регистрации».

Связано: #1945 (domrf flats loader сломан → supply занижен пока не починят; детект живёт через #1948).

## Финал: все баги/UX/честность отгружены и verified на проде ✅ Закрыто (deployed + прод-verified): - ✅ #1954 #1955 #1957 #1958 #1960 #1961 #1962 #1963 (PR #1973/#1978/#1985/#1987/#1988/#1998/#1981) - ✅ **#1959** — индекс дефицита больше не −1.0 везде: 12 ячеек / 7 разных значений; MOI комфорт-студия 38.5 vs стандарт-студия 244 (PR #2018, миграция 173 применена) - ✅ **#1956** — supply 0→502/487/225/220, sold_pct 5.8/5.7/3.6/2.7 (не «—»); per-object snapshot (PR #2020) Итог: 10 PR + repo-wide CI-фикс (prettier pin). Медиана 64k→132690, ЗОУИТ→СЗЗ-баннер, градрегламент НСПД, человеческий язык 6.x, точки на карте, дефицит дифференцируется. ## Остаётся (отдельно) - **#1964** — platform-wide дедуп RAW `objective_lots` (1.75M) + n_sold=99110 аномалия. Частично закрыт безусловным дедупом из #1959 (`compute_market_metrics`); полный raw-cleanup отдельно. - **#1965** — фича house-picker→3D→пересчёт (MassingScene есть, но разорван с `compute_financial`). Multi-day, скоуп на обсуждение. - Мелочь: композит-индекс `(obj_id,snapshot_date)` на domrf_kn_flats; `max_height_m` coercion (тот же класс что #1962); backend-geom `osm_noise_sources_ekb` (карта 1:1, #1961); скрытие пустой «дата регистрации». Связано: #1945 (domrf flats loader сломан → supply занижен пока не починят; детект живёт через #1948).
Author
Collaborator

Финал сессии 2026-06-27/28

Все P0–P2 аудита + фича #1965 + мелочи — отгружены и verified на проде.

Закрыто доп. (после прошлого финал-коммента):

  • #1965 (3D house-picker) — 5 PR (#2023/#2024/#2026/#2029/#2030), end-to-end: Концепция в отчёте → выбор типа дома/этажность/кол-во (или Авто max-FAR) → 3D → живой пересчёт ТЭП/NPV/IRR.
  • Мелочи (PR #2031): индекс idx_kn_flats_obj_snap (миграция 174, под #1956-запрос) + max_height_m coercion (string-баг как #1962) + скрытие пустой «Дата регистрации».

Остаётся открытым (этот эпик трекает):

  • #1964 — полный raw-дедуп objective_lots (1.75M). ⚠️ Это БОЛЬШОЙ ETL/архитектурный эффорт: лоадер пишет append-per-snapshot → ~2.9–4.4× инфляция. Варианты: (а) UPSERT в лоадере, (б) v_objective_lots_latest (DISTINCT ON physflat-key) + репойнт ВСЕХ raw-консьюмеров. Основной эффект уже снят read-time дедупом из #1959 (compute_market_metrics, все 9 forecast/scoring-консьюмеров). Рекомендуется как отдельная focused-задача, не рашить. Сюда же n_sold=99110 аномалия (6.3 фактор).
  • #1945 — domrf flats loader (DOM.РФ WAF) — Лёha-zone (live-браузер). Детект готов (#1948).

Итого по эпику: 13 PR аудита + 5 PR #1965 + CI-фикс. Остаток — два больших отдельных эффорта (#1964, #1945).

## Финал сессии 2026-06-27/28 Все P0–P2 аудита + фича #1965 + мелочи — **отгружены и verified на проде**. **Закрыто доп. (после прошлого финал-коммента):** - ✅ #1965 (3D house-picker) — 5 PR (#2023/#2024/#2026/#2029/#2030), end-to-end: Концепция в отчёте → выбор типа дома/этажность/кол-во (или Авто max-FAR) → 3D → живой пересчёт ТЭП/NPV/IRR. - ✅ Мелочи (PR #2031): индекс `idx_kn_flats_obj_snap` (миграция 174, под #1956-запрос) + `max_height_m` coercion (string-баг как #1962) + скрытие пустой «Дата регистрации». **Остаётся открытым (этот эпик трекает):** - **#1964 — полный raw-дедуп `objective_lots` (1.75M).** ⚠️ Это БОЛЬШОЙ ETL/архитектурный эффорт: лоадер пишет append-per-snapshot → ~2.9–4.4× инфляция. Варианты: (а) UPSERT в лоадере, (б) `v_objective_lots_latest` (DISTINCT ON physflat-key) + репойнт ВСЕХ raw-консьюмеров. **Основной эффект уже снят** read-time дедупом из #1959 (`compute_market_metrics`, все 9 forecast/scoring-консьюмеров). Рекомендуется как отдельная focused-задача, не рашить. Сюда же n_sold=99110 аномалия (6.3 фактор). - **#1945** — domrf flats loader (DOM.РФ WAF) — Лёha-zone (live-браузер). Детект готов (#1948). Итого по эпику: **13 PR аудита + 5 PR #1965 + CI-фикс**. Остаток — два больших отдельных эффорта (#1964, #1945).
Author
Collaborator

#1964 закрыт (PR #2032, deployed + verified)

v_objective_lots_latest (миграция 175) live: дедуп 1 753 283 → 603 049 квартир (2.91×). Репойнт batch/cached консьюмеров на view; 4 request-path (в analyze_parcel) — inline DISTINCT ON с filter-pushdown (EXPLAIN 5854мс→122-1640мс, full-индекс эмпирически опровергнут — view выбирает ol.*, Index-Only-Unique невозможен). n_sold window-mislabel пофикшен (cumulative 380k → windowed 24.9k «за 6 мес»). Дефицит-прогноз #1959 НЕ регрессировал (per-segment supply = deduped market_metrics, не тронут). История (objective_lots_history, sales_series, mv_sales_tracker) не тронута.

deep-review базы + code-review дельты .

Эпик #1953 — закрыт по сути

Все ~30 находок аудита + фича #1965 — отгружены, задеплоены, verified. Единственный открытый пункт — #1945 (domrf flats loader, DOM.РФ WAF) — Лёha-zone (нужен live-браузер); детект уже работает (#1948 алёртит). Можно закрывать эпик после #1945 либо оставить его трекером под #1945.

Запущен финальный end-to-end QA-smoke всего отчёта.

## #1964 закрыт (PR #2032, deployed + verified) `v_objective_lots_latest` (миграция 175) live: дедуп **1 753 283 → 603 049** квартир (2.91×). Репойнт batch/cached консьюмеров на view; 4 request-path (в `analyze_parcel`) — inline `DISTINCT ON` с filter-pushdown (EXPLAIN 5854мс→122-1640мс, full-индекс эмпирически опровергнут — view выбирает `ol.*`, Index-Only-Unique невозможен). n_sold window-mislabel пофикшен (cumulative 380k → windowed 24.9k «за 6 мес»). Дефицит-прогноз #1959 НЕ регрессировал (per-segment supply = deduped market_metrics, не тронут). История (`objective_lots_history`, sales_series, mv_sales_tracker) не тронута. deep-review базы ✅ + code-review дельты ✅. ## Эпик #1953 — закрыт по сути Все ~30 находок аудита + фича #1965 — отгружены, задеплоены, verified. **Единственный открытый пункт — #1945** (domrf flats loader, DOM.РФ WAF) — Лёha-zone (нужен live-браузер); детект уже работает (#1948 алёртит). Можно закрывать эпик после #1945 либо оставить его трекером под #1945. Запущен финальный end-to-end QA-smoke всего отчёта.
Author
Collaborator

Эпик закрыт — все находки отгружены, задеплоены, verified

Последний открытый пункт — #1945 (domrf flats loader, был «Лёha-zone») — починен и валидирован фиксом #2050: run 33 восстановил 193 519 flats / 703 объекта (было 9/1; охват даже шире, чем 417-объектный пик до поломки). Закрыт.

Итог эпика #1953:

  • 11 дочерних багов/честность/UX (#1954–#1964) — закрыты
  • Фича #1965 (3D house-picker) — закрыта
  • #1945 (loader) — закрыт
  • Перф-добивка (#1953 follow-up): #2054 inline competitors (6.9с→0.8с) + covering-индекс (миграция 176) + дроп 3 мёртвых индексов (177) — на проде

Всё verified на проде живыми числами. Закрываю эпик.

## ✅ Эпик закрыт — все находки отгружены, задеплоены, verified Последний открытый пункт — **#1945** (domrf flats loader, был «Лёha-zone») — **починен и валидирован** фиксом #2050: run 33 восстановил **193 519 flats / 703 объекта** (было 9/1; охват даже шире, чем 417-объектный пик до поломки). Закрыт. **Итог эпика #1953:** - 11 дочерних багов/честность/UX (#1954–#1964) — закрыты - Фича #1965 (3D house-picker) — закрыта - #1945 (loader) — закрыт - Перф-добивка (#1953 follow-up): #2054 inline competitors (6.9с→0.8с) + covering-индекс (миграция 176) + дроп 3 мёртвых индексов (177) — на проде Всё verified на проде живыми числами. Закрываю эпик.
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#1953
No description provided.