[AUDIT 2026-06-22] ПТИЦА deep-audit: реестр дефектов (цифры/логика/минусы/дизайн) #1871

Closed
opened 2026-06-22 07:55:29 +00:00 by lekss361 · 5 comments
Owner

Сводный реестр по результатам read-only deep-аудита живой платформы (Site Finder + Мера/trade-in) от 2026-06-22. Каждый пункт с доказательством (file:line / SQL / axe / screenshot). Полные evidence-файлы: _audit_ptica_0622/{A_tradein_data,B_sitefinder_data,C_ui_design,D_frontend_honesty}.md.

Severity: 🔴 неверная цифра/выдумка-как-факт · 🟠 misleading aggregation/сломанная логика · 🟡 дизайн/a11y · 🟢 косметика. Это зонтичная issue — по мере работы выносить P1 в отдельные тикеты и линковать.


🔴 P1 — выдумка-как-факт (доверие финдиректора)

  • §22 сценарии идентичны. conservative=base=aggressive по projected_demand на всех горизонтах; все 393 отчёта в проде имеют demand_norm_coefficient=1.0. Фронт рисует 3 разноцветные карточки/линии одинаковых чисел без guard.

    • Корень: demand_normalization.py:287-302 (honesty-gate confidence=='low' фаерит всегда — rate-sensitivity регрессия ЕКБ не проходит gate n≥30∧R²≥0.1∧slope<0). Фронт ForecastChart.tsx:130-158, ScenarioCards.tsx:65-122.
    • SQL: 66:41:0106129:11 h6 base=aggr=cons=2409.1.
    • DoD: чинить нормализацию ЛИБО схлопнуть 3→1 на фронте с caveat «сценарная дифференциация недоступна». scope/backend (+frontend).
  • Ghost-anchor: confidence='high' при n_analogs=0. estimate 5fcc1e99 «Екатеринбург, 20/4», median 38 450 067 ₽, sources=['yandex_valuation'], при истории листингов дома 4.2–6.5 млн.

    • Корень: estimator.py:2316-2326 (anchor фаерит при listings_clean=[]), :2477. Фронт EstimateResult.tsx:185 отрендерит «Высокая · 0 объектов».
    • DoD: запрет confidence='high' при n_analogs==0; downgrade→low+caveat; фронт-guard. scope/backend.
  • ptica-adapt помечает стабы isReal:true. encumbrances:{value:PLACEHOLDER,isReal:true}; buy_signal→«наблюдать» при deficit_index==null,isReal:true; engineering pct=0 при null. ParcelPassportCard.tsx:36 рендерит «—» обычной типографикой = неотличимо от измеренного.

    • Корень: ptica-adapt.ts:130, 231-233, 513, 577-589, 797; InvestScoreBlock.tsx:69.
    • DoD: notReal-поля → isReal:false+caption полным предложением, визуальный mute. scope/frontend.

🟠 P2 — misleading aggregation / сломанная логика

  • invest_score = сырая POI-сумма, подаётся как «скор». scorer.py — пустой стаб (10 строк докстринга). parcels.py:1612-1623 (Σ w×max(0,1−d/1000), SCORE_MAX_REFERENCE=40). Advisory-caption только в title= (hover). DoD: видимый лейбл «POI-скор 0–40, advisory». scope/backend+frontend.
  • Velocity маппинг 17% (264/1550 ЕКБ) → почти везде rosreestr-fallback с прокси 45 м²/сделка, не раскрытым. velocity.py gate <0.50, прокси :581. DoD: surface coverage% + proxy в confidence. scope/backend.
  • market_trend=null у всех — rosreestr MAX(period_start_date)=2026-01-01 (stale 5.5 мес), окно «0-3 мес» пусто, без staleness-таймстампа. DoD: чинить ETL + отдать «источник устарел» vs «нет сделок». scope/backend.
  • CIAN 89.3% устарел → невидим эстиматору (15 038/16 836 старше 14д; фильтр scraped_at>NOW()-14d). Циклы банов (4 за 14д). Связано #885/#883.
  • DomClick: 0 листингов при enabled=true — 8 прогонов status='done', total_seen=0, без error. domclick.py:271 _is_blocked_page не ловит QRATOR. → #1846.
  • 797 дублей yandex + 93 cian (2-3 active-строки/source_id) → раздувают n_analogs. Dedup есть в anchor (estimator.py:1539), нет в radius-пути _fetch_analogs/_stratify_candidates. scope/backend.
  • Avito 54.2% NULL lat + 410 active с не-ЕКБ координатами (Питер/Тюмень/Уфа). ЕКБ-фильтр только URL при ingest (avito.py:1773), не coord-фильтр на запросе. URL-часть #1840; coord-filter NEW.
  • MOI горизонт-инвариантен (116.6 на h6=h12; 117.6 на h18=h24). demand_supply_forecast.py:703 (demand/horizon сокращает horizon). DoD: раскрыть лимитацию либо сменить знаменатель.
  • Velocity fallback-константа 7.6× завышена_EKB_MEDIAN_FALLBACK=4500 (velocity.py:41) vs реальная медиана 593–766 м²/мес. Фаерит только при DB-error (latent). DoD: 4500→~750.
  • Широкий коридор >80% на split-домах (Хохрякова 48 — 148%, Красина 6 — 170%): дом разбит на 3 house_id разной этажности. Связано #1795; split — NEW.

🟡 P3 — дизайн / a11y / observability

  • Нет <h1> на analysis v1 (3×h2+11×h3) и v2-кокпите — сломана иерархия заголовков.
  • Emoji в бизнес-вердиктах (🚫🟢🪷⚠) — нарушает нейтральный тон.
  • Графики мимо токенов — SVG fills rgb(37,99,235)/rgb(25,112,56)/rgb(124,58,237) вместо --viz-1..5.
  • v2-кокпит перегруз — 110 box-shadow + 131 inline-SVG; v1 — 31 SVG + «128 факторов» в один скролл.
  • Аббревиатуры не расшифрованы на первом экране — ДКП/IMV/CV (preview), ЗОУИТ/ОСР/ВСЕГЕИ (analysis).
  • Прогноз без доверит. интервалаForecastChart без band; confidenceLevelToValue() (0.85/0.55/0.25) объявлен без вызовов (латентный риск фабрикации точности). forecast-helpers.ts:122-130.
  • yandex scrape_runs.total_seen=0 во всех прогонах при реальной записи в БД (observability врёт).
  • n1_city_sweep enabled=false с 16.06 → N1 невидим эстиматору. Связано #854.

🟢 Косметика

  • Footer Документация/API/Источники = dead #; v2 legal-строка ALL-CAPS; site-finder лендинг h1 16px; units_sold расходится competitor-блок (is_sold) vs MarketMetrics (is_sold OR contract_date) — 1612 юнитов недосчёт.

Подтверждено / можно закрыть

  • #1781 (cian-первичка заморожена) — фактически РАЗМОРОЖЕН (refresh с 16.06, last scraped 2026-06-22 07:21). Verify + close.
  • geology/zoning data_available=false, deals/SberIndex time-adjust — honest-stub, работают корректно .

Дедуп (не перезаводить, ссылаться)

#1790 · #915/#885/#883 · #562 · #1184 · #1846 · #1781 · #1772/#1773/#1774 · #1795 · #1843 · #1850 · #1840 · #854 · #7.

Сводный реестр по результатам read-only deep-аудита живой платформы (Site Finder + Мера/trade-in) от 2026-06-22. Каждый пункт с доказательством (file:line / SQL / axe / screenshot). Полные evidence-файлы: `_audit_ptica_0622/{A_tradein_data,B_sitefinder_data,C_ui_design,D_frontend_honesty}.md`. Severity: 🔴 неверная цифра/выдумка-как-факт · 🟠 misleading aggregation/сломанная логика · 🟡 дизайн/a11y · 🟢 косметика. Это **зонтичная** issue — по мере работы выносить P1 в отдельные тикеты и линковать. --- ## 🔴 P1 — выдумка-как-факт (доверие финдиректора) - [ ] **§22 сценарии идентичны.** conservative=base=aggressive по `projected_demand` на всех горизонтах; все 393 отчёта в проде имеют `demand_norm_coefficient=1.0`. Фронт рисует 3 разноцветные карточки/линии одинаковых чисел без guard. - Корень: `demand_normalization.py:287-302` (honesty-gate `confidence=='low'` фаерит всегда — rate-sensitivity регрессия ЕКБ не проходит gate n≥30∧R²≥0.1∧slope<0). Фронт `ForecastChart.tsx:130-158`, `ScenarioCards.tsx:65-122`. - SQL: 66:41:0106129:11 h6 base=aggr=cons=2409.1. - DoD: чинить нормализацию ЛИБО схлопнуть 3→1 на фронте с caveat «сценарная дифференциация недоступна». scope/backend (+frontend). - [ ] **Ghost-anchor: `confidence='high'` при `n_analogs=0`.** estimate 5fcc1e99 «Екатеринбург, 20/4», median 38 450 067 ₽, sources=`['yandex_valuation']`, при истории листингов дома 4.2–6.5 млн. - Корень: `estimator.py:2316-2326` (anchor фаерит при `listings_clean=[]`), `:2477`. Фронт `EstimateResult.tsx:185` отрендерит «Высокая · 0 объектов». - DoD: запрет `confidence='high'` при `n_analogs==0`; downgrade→low+caveat; фронт-guard. scope/backend. - [ ] **`ptica-adapt` помечает стабы `isReal:true`.** `encumbrances:{value:PLACEHOLDER,isReal:true}`; buy_signal→«наблюдать» при `deficit_index==null,isReal:true`; engineering pct=0 при null. `ParcelPassportCard.tsx:36` рендерит «—» обычной типографикой = неотличимо от измеренного. - Корень: `ptica-adapt.ts:130, 231-233, 513, 577-589, 797`; `InvestScoreBlock.tsx:69`. - DoD: notReal-поля → `isReal:false`+caption полным предложением, визуальный mute. scope/frontend. ## 🟠 P2 — misleading aggregation / сломанная логика - [ ] **invest_score = сырая POI-сумма**, подаётся как «скор». `scorer.py` — пустой стаб (10 строк докстринга). `parcels.py:1612-1623` (`Σ w×max(0,1−d/1000)`, `SCORE_MAX_REFERENCE=40`). Advisory-caption только в `title=` (hover). DoD: видимый лейбл «POI-скор 0–40, advisory». scope/backend+frontend. - [ ] **Velocity маппинг 17%** (264/1550 ЕКБ) → почти везде rosreestr-fallback с прокси 45 м²/сделка, не раскрытым. `velocity.py` gate `<0.50`, прокси `:581`. DoD: surface coverage% + proxy в confidence. scope/backend. - [ ] **`market_trend=null` у всех** — rosreestr `MAX(period_start_date)=2026-01-01` (stale 5.5 мес), окно «0-3 мес» пусто, без staleness-таймстампа. DoD: чинить ETL + отдать «источник устарел» vs «нет сделок». scope/backend. - [ ] **CIAN 89.3% устарел → невидим эстиматору** (15 038/16 836 старше 14д; фильтр `scraped_at>NOW()-14d`). Циклы банов (4 за 14д). Связано #885/#883. - [ ] **DomClick: 0 листингов при `enabled=true`** — 8 прогонов `status='done'`, `total_seen=0`, без error. `domclick.py:271` `_is_blocked_page` не ловит QRATOR. → #1846. - [ ] **797 дублей yandex + 93 cian** (2-3 active-строки/source_id) → раздувают `n_analogs`. Dedup есть в anchor (`estimator.py:1539`), нет в radius-пути `_fetch_analogs`/`_stratify_candidates`. scope/backend. - [ ] **Avito 54.2% NULL lat + 410 active с не-ЕКБ координатами** (Питер/Тюмень/Уфа). ЕКБ-фильтр только URL при ingest (`avito.py:1773`), не coord-фильтр на запросе. URL-часть #1840; coord-filter NEW. - [ ] **MOI горизонт-инвариантен** (116.6 на h6=h12; 117.6 на h18=h24). `demand_supply_forecast.py:703` (`demand/horizon` сокращает horizon). DoD: раскрыть лимитацию либо сменить знаменатель. - [ ] **Velocity fallback-константа 7.6× завышена** — `_EKB_MEDIAN_FALLBACK=4500` (`velocity.py:41`) vs реальная медиана 593–766 м²/мес. Фаерит только при DB-error (latent). DoD: 4500→~750. - [ ] **Широкий коридор >80%** на split-домах (Хохрякова 48 — 148%, Красина 6 — 170%): дом разбит на 3 house_id разной этажности. Связано #1795; split — NEW. ## 🟡 P3 — дизайн / a11y / observability - [ ] **Нет `<h1>`** на analysis v1 (3×h2+11×h3) и v2-кокпите — сломана иерархия заголовков. - [ ] **Emoji в бизнес-вердиктах** (🚫🟢🪷⚠) — нарушает нейтральный тон. - [ ] **Графики мимо токенов** — SVG fills `rgb(37,99,235)`/`rgb(25,112,56)`/`rgb(124,58,237)` вместо `--viz-1..5`. - [ ] **v2-кокпит перегруз** — 110 box-shadow + 131 inline-SVG; v1 — 31 SVG + «128 факторов» в один скролл. - [ ] **Аббревиатуры не расшифрованы** на первом экране — ДКП/IMV/CV (preview), ЗОУИТ/ОСР/ВСЕГЕИ (analysis). - [ ] **Прогноз без доверит. интервала** — `ForecastChart` без band; `confidenceLevelToValue()` (0.85/0.55/0.25) объявлен без вызовов (латентный риск фабрикации точности). `forecast-helpers.ts:122-130`. - [ ] **yandex `scrape_runs.total_seen=0`** во всех прогонах при реальной записи в БД (observability врёт). - [ ] **n1_city_sweep `enabled=false`** с 16.06 → N1 невидим эстиматору. Связано #854. ## 🟢 Косметика - [ ] Footer Документация/API/Источники = dead `#`; v2 legal-строка ALL-CAPS; site-finder лендинг `h1` 16px; units_sold расходится competitor-блок (`is_sold`) vs MarketMetrics (`is_sold OR contract_date`) — 1612 юнитов недосчёт. --- ## ✅ Подтверждено / можно закрыть - **#1781 (cian-первичка заморожена) — фактически РАЗМОРОЖЕН** (refresh с 16.06, last scraped 2026-06-22 07:21). Verify + close. - geology/zoning `data_available=false`, deals/SberIndex time-adjust — **honest-stub, работают корректно** ✅. ## Дедуп (не перезаводить, ссылаться) #1790 · #915/#885/#883 · #562 · #1184 · #1846 · #1781 · #1772/#1773/#1774 · #1795 · #1843 · #1850 · #1840 · #854 · #7.
lekss361 added the
analytics
bug
needs-human
priority/p1
site-finder
tradein
labels 2026-06-22 07:55:57 +00:00
Collaborator

🔴 Все три P1 закрыты и задеплоены в прод (2026-06-23)

P1.1 — §22 сценарии идентичныPR #1873 (merge fd107ae, deployed)
Honest collapse: backend детектирует conservative==base==aggressive (math.isclose по projected_demand_units + deficit_index на всех горизонтах) → флаг scenarios_collapsed → 3 UI-поверхности (ScenariosBlock/ScenarioCards/ForecastChart) + PDF/Excel схлопываются в ОДНУ карточку «Базовый» + caveat. demand_normalization.py не тронут (контракт честный). +18 unit.

P1.2 — Ghost-anchor confidence='high' при n_analogs=0PR #1874 (merge dfa1e27, deployed via deploy-tradein.yml)
Уточнение по факту prod-DB: ghost 5fcc1e99 — единственная legacy-строка от 2026-05-30, давно expired (estimates TTL = 1 день; все 66 high/medium-c-n<5 строк expired). Текущий live-код уже честен. Фикс — defensive invariant _enforce_zero_analog_low (n_analogs=0 → forced low + caveat, реальный median сохранён) перед AggregatedEstimate + frontend effectiveConfidence guard в HeroSummary/HeroTransparency/history. +5 unit.

P1.3 — ptica-adapt помечает заглушки isReal:truePR #1875 (merge 85d9137, deployed)
5 honesty-фиксов (recon нашёл 3, adversarial code-review нашёл ещё 2 drawer-зеркала): encumbrances (passport-card + 2 drawer registry), buySignalFromForecast при di==null, adaptBuySignalGauge synthetic-50-as-real. .kvPlaceholder += opacity:0.7. Числа не выдумываются — только корректные isReal:false + honest caption + mute. +5 unit.


Дальше по реестру: 🟠 P2 (10 пунктов), 🟡 P3 (h1, emoji, viz-токены, аббревиатуры, CI band). P3 «v2-кокпит перегруз» снят — v2 откатили в PR #1872.

## 🔴 Все три P1 закрыты и задеплоены в прод (2026-06-23) **P1.1 — §22 сценарии идентичны** → [PR #1873](https://git.gendsgn.ru/lekss361/gendesign/pulls/1873) (merge `fd107ae`, deployed) Honest collapse: backend детектирует `conservative==base==aggressive` (`math.isclose` по `projected_demand_units` + `deficit_index` на всех горизонтах) → флаг `scenarios_collapsed` → 3 UI-поверхности (ScenariosBlock/ScenarioCards/ForecastChart) + PDF/Excel схлопываются в ОДНУ карточку «Базовый» + caveat. `demand_normalization.py` не тронут (контракт честный). +18 unit. **P1.2 — Ghost-anchor `confidence='high'` при `n_analogs=0`** → [PR #1874](https://git.gendsgn.ru/lekss361/gendesign/pulls/1874) (merge `dfa1e27`, deployed via `deploy-tradein.yml`) **Уточнение по факту prod-DB:** ghost `5fcc1e99` — единственная legacy-строка от 2026-05-30, **давно expired** (estimates TTL = 1 день; все 66 `high/medium`-c-`n<5` строк expired). Текущий live-код уже честен. Фикс — defensive invariant `_enforce_zero_analog_low` (n_analogs=0 → forced low + caveat, реальный median сохранён) перед `AggregatedEstimate` + frontend `effectiveConfidence` guard в HeroSummary/HeroTransparency/history. +5 unit. **P1.3 — ptica-adapt помечает заглушки `isReal:true`** → [PR #1875](https://git.gendsgn.ru/lekss361/gendesign/pulls/1875) (merge `85d9137`, deployed) **5 honesty-фиксов** (recon нашёл 3, adversarial code-review нашёл ещё 2 drawer-зеркала): encumbrances (passport-card + 2 drawer registry), `buySignalFromForecast` при `di==null`, `adaptBuySignalGauge` synthetic-50-as-real. `.kvPlaceholder += opacity:0.7`. Числа не выдумываются — только корректные `isReal:false` + honest caption + mute. +5 unit. --- Дальше по реестру: 🟠 P2 (10 пунктов), 🟡 P3 (h1, emoji, viz-токены, аббревиатуры, CI band). P3 «v2-кокпит перегруз» снят — v2 откатили в [PR #1872](https://git.gendsgn.ru/lekss361/gendesign/pulls/1872).
Collaborator

🟠 P2 tradein-batch + 🟡 P3 закрыты (2026-06-23) — итог сессии: 9 PR

P2 site-finder

  • velocity fallback 4500→750 + coverage/proxy disclosure + market_trend stalenessPR #1876 (deployed). market_trend теперь различает source_stale (rosreestr до 2026-01) / no_deals / ok.
  • invest_score честный лейбл + MOIPR #1877 (deployed). «Инвест-балл»→«POI-скор · 0–40 · оценочный» (Section1/legacy/CompareTable/landing), scoreColor пороги 0–100→0–40. MOI горизонт-инвариант — убрана дублирующая колонка (математически корректен, не баг).

P2 tradein (чувствительный estimator.py)

  • Avito coord bbox-filterPR #1879 (deployed). Prod-verified: 406 не-ЕКБ координат (Питер/Тюмень/Уфа) просачивались через avito_detail без bbox-валидации. DRY-хелпер + ingest-guard.
  • dedup (source,source_id) + split-house disclosurePR #1880 (deploying). dedup в 4 radius-тирах (флаг ON); split-дом коридор 148-170% → confidence↓ + caveat (флаг default OFF). Merge house_id отклонён (вреден — Tier A намеренно обходит house_id).

🟡 P3 UI/a11y → PR #1878 (deployed)

<h1> добавлен; emoji→Lucide (4 файла); ЗОУИТ/ОЗ расшифрованы; ForecastChart axis-hex задокументирован (canvas не резолвит var()).


Уточнения severity по prod-DB (аудит склонен преувеличивать по сырым данным)

  • P1.2 ghost-anchor — единственная legacy-строка, давно expired (TTL 1 день).
  • P2 dedup — дубли 13× меньше аудита (yandex 48 vs 797, cian 9 vs 93) — почти вычищено с момента аудита.
  • P2 avito coord — подтверждён актуальным (406 не-ЕКБ + 51.6% NULL).

Осталось в #1871 (НЕ сделано — зоны Лёхи / отдельные тикеты)

  • 🟠 CIAN 89% устарел / DomClick 0 — внешний анти-бан (QRATOR/ban-cycles), зона Лёхи (#885/#883/#1846)
  • 🟠 ETL rosreestr встал на 2026-01 — внешний лаг Росреестра / скрейпер (market_trend честно показывает «источник устарел»)
  • 🟠 avito NULL lat 14935 — geocode-cron throughput (недобор, не засорение)
  • 🟡 ForecastChart CI-band — backend не отдаёт p25/p75 (нужны данные)
  • Action items: one-time cleanup 406 avito coords (UPDATE listings SET lat=NULL..., prod-mutation); включить estimate_wide_corridor_disclosure_enabled после проверки порога 0.6 на split-домах.

Все code-fix дефекты P1/P2/P3, что в зоне приложения (не внешний анти-бан/ETL-лаг), закрыты и задеплоены. ~+95 тестов.

## 🟠 P2 tradein-batch + 🟡 P3 закрыты (2026-06-23) — итог сессии: 9 PR ### P2 site-finder - **velocity fallback 4500→750 + coverage/proxy disclosure + market_trend staleness** → [PR #1876](https://git.gendsgn.ru/lekss361/gendesign/pulls/1876) (deployed). market_trend теперь различает `source_stale` (rosreestr до 2026-01) / `no_deals` / `ok`. - **invest_score честный лейбл + MOI** → [PR #1877](https://git.gendsgn.ru/lekss361/gendesign/pulls/1877) (deployed). «Инвест-балл»→«POI-скор · 0–40 · оценочный» (Section1/legacy/CompareTable/landing), scoreColor пороги 0–100→0–40. MOI горизонт-инвариант — убрана дублирующая колонка (математически корректен, не баг). ### P2 tradein (чувствительный estimator.py) - **Avito coord bbox-filter** → [PR #1879](https://git.gendsgn.ru/lekss361/gendesign/pulls/1879) (deployed). Prod-verified: 406 не-ЕКБ координат (Питер/Тюмень/Уфа) просачивались через avito_detail без bbox-валидации. DRY-хелпер + ingest-guard. - **dedup (source,source_id) + split-house disclosure** → [PR #1880](https://git.gendsgn.ru/lekss361/gendesign/pulls/1880) (deploying). dedup в 4 radius-тирах (флаг ON); split-дом коридор 148-170% → confidence↓ + caveat (флаг **default OFF**). Merge house_id отклонён (вреден — Tier A намеренно обходит house_id). ### 🟡 P3 UI/a11y → [PR #1878](https://git.gendsgn.ru/lekss361/gendesign/pulls/1878) (deployed) `<h1>` добавлен; emoji→Lucide (4 файла); ЗОУИТ/ОЗ расшифрованы; ForecastChart axis-hex задокументирован (canvas не резолвит var()). --- ### Уточнения severity по prod-DB (аудит склонен преувеличивать по сырым данным) - **P1.2 ghost-anchor** — единственная legacy-строка, давно expired (TTL 1 день). - **P2 dedup** — дубли **13× меньше** аудита (yandex 48 vs 797, cian 9 vs 93) — почти вычищено с момента аудита. - **P2 avito coord** — подтверждён актуальным (406 не-ЕКБ + 51.6% NULL). ### Осталось в #1871 (НЕ сделано — зоны Лёхи / отдельные тикеты) - 🟠 **CIAN 89% устарел / DomClick 0** — внешний анти-бан (QRATOR/ban-cycles), зона Лёхи (#885/#883/#1846) - 🟠 **ETL rosreestr встал на 2026-01** — внешний лаг Росреестра / скрейпер (market_trend честно показывает «источник устарел») - 🟠 **avito NULL lat 14935** — geocode-cron throughput (недобор, не засорение) - 🟡 **ForecastChart CI-band** — backend не отдаёт p25/p75 (нужны данные) - **Action items:** one-time cleanup 406 avito coords (`UPDATE listings SET lat=NULL...`, prod-mutation); включить `estimate_wide_corridor_disclosure_enabled` после проверки порога 0.6 на split-домах. **Все code-fix дефекты P1/P2/P3, что в зоне приложения (не внешний анти-бан/ETL-лаг), закрыты и задеплоены.** ~+95 тестов.
Collaborator

Прогон 4 core-estimator дефектов (2026-06-26, verify-against-current-code)

Перепроверил 4 backend-дефекта из реестра против текущего кода+прода (workflow). Итог — 3 из 4 уже починены с момента аудита (06-22), 1 пофикшен сейчас:

  • 🔴 Ghost-anchor (confidence='high' при n_analogs=0) — был ЖИВ → пофикшен PR #1920 (merged, деплоится). Корень: при подмене headline на same-building anchor n_analogs перезаписывался на anchor["n"]>0, поэтому _enforce_zero_analog_low (ловит только n==0) не срабатывал. Guard: if not listings_clean and confidence!='low' → 'low' + caveat. deep-review , 8+61 тестов.
  • 🟠 Velocity fallback 4500→750 уже починено (commit adf3ec7, _EKB_MEDIAN_FALLBACK_SQM_PER_MONTH=750.0, тест пинит значение).
  • 🟠 Radius-path dedup (797 yandex + 93 cian дублей) уже починено: rn_dup-window во всех radius-tiers + флаг estimate_radius_dedup_enabled=True (подтверждён ON в проде) + migration 133 (UNIQUE на source,source_id, задеплоен 06-26). Дубли больше не раздувают n_analogs.
  • 🟠 Avito не-ЕКБ координаты не-проблема: Tier W radius-запрос ST_DWithin(geom::geography, radius) — NULL-geom (54% avito) и координаты вне радиуса автоматически исключаются. Засорения оценки нет.

Остальные пункты реестра (§22 сценарии, ptica-adapt isReal, invest_score лейбл, MOI, market_trend ETL, и P3/a11y) — не трогал этим заходом (часть — кокпит-фронт, откатан 06-21; часть — отдельные тикеты/решения).

NB: пункт « #1781 фактически разморожен» в реестре неточен — vtorichka свежая, но cian novostroyki 9598/10003 всё ещё заморожены ≤31.05 (см. мой апдейт в #1781). Не закрывать #1781.

## Прогон 4 core-estimator дефектов (2026-06-26, verify-against-current-code) Перепроверил 4 backend-дефекта из реестра против текущего кода+прода (workflow). Итог — **3 из 4 уже починены с момента аудита (06-22), 1 пофикшен сейчас:** - 🔴 **Ghost-anchor (confidence='high' при n_analogs=0)** — был ЖИВ → **пофикшен PR #1920** (merged, деплоится). Корень: при подмене headline на same-building anchor `n_analogs` перезаписывался на `anchor["n"]>0`, поэтому `_enforce_zero_analog_low` (ловит только n==0) не срабатывал. Guard: `if not listings_clean and confidence!='low' → 'low' + caveat`. deep-review ✅, 8+61 тестов. - 🟠 **Velocity fallback 4500→750** — ✅ уже починено (commit adf3ec7, `_EKB_MEDIAN_FALLBACK_SQM_PER_MONTH=750.0`, тест пинит значение). - 🟠 **Radius-path dedup (797 yandex + 93 cian дублей)** — ✅ уже починено: `rn_dup`-window во всех radius-tiers + флаг `estimate_radius_dedup_enabled=True` (подтверждён ON в проде) + migration 133 (UNIQUE на source,source_id, задеплоен 06-26). Дубли больше не раздувают n_analogs. - 🟠 **Avito не-ЕКБ координаты** — ✅ не-проблема: Tier W radius-запрос `ST_DWithin(geom::geography, radius)` — NULL-geom (54% avito) и координаты вне радиуса автоматически исключаются. Засорения оценки нет. Остальные пункты реестра (§22 сценарии, ptica-adapt isReal, invest_score лейбл, MOI, market_trend ETL, и P3/a11y) — не трогал этим заходом (часть — кокпит-фронт, откатан 06-21; часть — отдельные тикеты/решения). NB: пункт «✅ #1781 фактически разморожен» в реестре **неточен** — vtorichka свежая, но cian **novostroyki 9598/10003 всё ещё заморожены ≤31.05** (см. мой апдейт в #1781). Не закрывать #1781.
Collaborator

Forecast-honesty (backend) — проверено, уже сделано

Перепроверил 3 forecast-дефекта реестра против текущего кода:

  • 🔴 §22 сценарии идентичны уже починено (commit dcccebf, 06-22): forecasting/scenarios.py::_detect_collapsed() + поля ReportScenarios.scenarios_collapsed / scenarios_collapse_reason + 18 тестов + фронт (ScenariosBlock/Section6Forecast). Бэкенд честно сигналит коллапс.
  • 🟠 MOI горизонт-инвариантен — формула математически верна: MOI = supply/monthly_pace по определению не зависит от горизонта (стандартная метрика «месяцев запаса»); горизонт-зависимый сигнал несёт deficit_index. Это не баг бэка — нужен только фронт-тултип (показывать MOI один раз, не дублём по горизонтам). Менять знаменатель НЕ рекомендуется (сломает downstream + стандартную семантику).
  • 🟠 market_trend staleness honest-disclosure уже в бэке (parcels.py: status ∈ source_stale/no_deals/ok + as_of_date, market_trend subscore→0). ETL-рефреш rosreestr (источник устарел) — зона Лёхи.

Итог: bot-safe backend forecast-honesty закрыт. Остаток реестра — фронт-проводка (зависит от состояния UI после отката кокпита 21.06), ETL Лёхи, и кокпит-дефекты (ptica-adapt/invest_score/a11y) — последние могут быть moot до редизайна.

## Forecast-honesty (backend) — проверено, уже сделано Перепроверил 3 forecast-дефекта реестра против текущего кода: - 🔴 **§22 сценарии идентичны** — ✅ уже починено (commit dcccebf, 06-22): `forecasting/scenarios.py::_detect_collapsed()` + поля `ReportScenarios.scenarios_collapsed` / `scenarios_collapse_reason` + 18 тестов + фронт (ScenariosBlock/Section6Forecast). Бэкенд честно сигналит коллапс. - 🟠 **MOI горизонт-инвариантен** — формула **математически верна**: MOI = supply/monthly_pace по определению не зависит от горизонта (стандартная метрика «месяцев запаса»); горизонт-зависимый сигнал несёт `deficit_index`. Это не баг бэка — нужен только фронт-тултип (показывать MOI один раз, не дублём по горизонтам). Менять знаменатель НЕ рекомендуется (сломает downstream + стандартную семантику). - 🟠 **market_trend staleness** — ✅ honest-disclosure уже в бэке (parcels.py: `status` ∈ source_stale/no_deals/ok + `as_of_date`, market_trend subscore→0). ETL-рефреш rosreestr (источник устарел) — зона Лёхи. Итог: bot-safe backend forecast-honesty закрыт. Остаток реестра — фронт-проводка (зависит от состояния UI после отката кокпита 21.06), ETL Лёхи, и кокпит-дефекты (ptica-adapt/invest_score/a11y) — последние могут быть moot до редизайна.
Collaborator

Закрываю зонтик (остаток вынесен в #1926)

Прогнал весь реестр против текущего кода (multi-agent verify). Итог:

Сделано / решено (P1/P2 backend — главное про доверие финдиректора):

  • §22 сценарии идентичны → collapse-detection + поля scenarios_collapsed/collapse_reason (dcccebf)
  • Ghost-anchor confidence=high#1919 (n_analogs=0) + #1920 (anchor+пустой radius)
  • 797 yandex / 93 cian дублей раздували n_analogs → radius-dedup (#1919)
  • Velocity fallback 4500→750 (adf3ec7) + proxy/coverage disclosure backend (velocity.py: velocity_source/objective_coverage_pct/proxy_used/proxy_sqm_per_deal)
  • market_trend null → staleness-disclosure (status: source_stale|no_deals|ok + as_of_date)
  • Avito не-ЕКБ координаты → не-проблема (ST_DWithin(geom::geography) исключает NULL/вне-радиуса)
  • MOI горизонт-инвариантен → формула верна by design (метрика месяцев запаса; horizon-сигнал несёт deficit_index) — только фронт-тултип
  • Аббревиатуры ДКП/IMV/CV + эмодзи + viz-токены в /trade-in → #1922 (на проде деплоем 87364ee)
  • (бонус, тот же аудит-трекинг #1189) geom::geography GIST-индекс → эстиматор-radius 180→40мс (#1924)

🔗 Остаётся, в своих тикетах: CIAN stale/novostroyki-freeze → #1781, #885, #883 · DomClick → #1846 · широкий коридор split-домов → #1772, #1795 · n1_city_sweep off → #854.

📦 Un-ticketed остаток вынесен → #1926 (p3): units_sold недосчёт ~1600 · yandex total_seen=0 observability · invest_score advisory-флаг · фронт-полиш (viz-токены/h1/forecast-band/velocity-rendering — домен frontend-контрибьютора, сначала verify live-поверхности после отката кокпита).

Все P1-доверие-пункты закрыты или решены. Зонтик выполнил роль — закрываю; остаток отслеживается в #1926 + дочерних.

## Закрываю зонтик (остаток вынесен в #1926) Прогнал весь реестр против текущего кода (multi-agent verify). Итог: **✅ Сделано / решено (P1/P2 backend — главное про доверие финдиректора):** - §22 сценарии идентичны → collapse-detection + поля `scenarios_collapsed/collapse_reason` (dcccebf) - Ghost-anchor `confidence=high` → #1919 (n_analogs=0) + #1920 (anchor+пустой radius) - 797 yandex / 93 cian дублей раздували n_analogs → radius-dedup (#1919) - Velocity fallback 4500→750 (adf3ec7) + proxy/coverage disclosure backend (velocity.py: `velocity_source/objective_coverage_pct/proxy_used/proxy_sqm_per_deal`) - market_trend null → staleness-disclosure (`status: source_stale|no_deals|ok` + `as_of_date`) - Avito не-ЕКБ координаты → **не-проблема** (ST_DWithin(geom::geography) исключает NULL/вне-радиуса) - MOI горизонт-инвариантен → формула **верна by design** (метрика месяцев запаса; horizon-сигнал несёт deficit_index) — только фронт-тултип - Аббревиатуры ДКП/IMV/CV + эмодзи + viz-токены в /trade-in → #1922 (на проде деплоем 87364ee) - (бонус, тот же аудит-трекинг #1189) geom::geography GIST-индекс → эстиматор-radius 180→40мс (#1924) **🔗 Остаётся, в своих тикетах:** CIAN stale/novostroyki-freeze → #1781, #885, #883 · DomClick → #1846 · широкий коридор split-домов → #1772, #1795 · n1_city_sweep off → #854. **📦 Un-ticketed остаток вынесен → #1926** (p3): units_sold недосчёт ~1600 · yandex total_seen=0 observability · invest_score advisory-флаг · фронт-полиш (viz-токены/h1/forecast-band/velocity-rendering — домен frontend-контрибьютора, сначала verify live-поверхности после отката кокпита). Все P1-доверие-пункты закрыты или решены. Зонтик выполнил роль — закрываю; остаток отслеживается в #1926 + дочерних. ✅
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#1871
No description provided.