Commit graph

1912 commits

Author SHA1 Message Date
02f49e795c feat(report): nav scrollspy + offset-jump, чат в плавающее окно справа (#958) (#2104)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 3m20s
Deploy / deploy (push) Successful in 1m16s
2026-06-30 10:29:02 +00:00
de4704f6cd fix(concept): step="any" — stepMismatch блокировал submit «Рассчитать концепцию» (#1953) (#2103)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 3m8s
Deploy / deploy (push) Successful in 1m16s
2026-06-30 10:09:55 +00:00
975c400536 feat(section7): editable section footprint + корпус plural/program hint (#1953) (#2102)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Successful in 1m57s
Deploy / build-frontend (push) Successful in 3m34s
Deploy / build-worker (push) Successful in 3m41s
Deploy / deploy (push) Successful in 1m32s
2026-06-30 09:48:11 +00:00
e359fb4b95 feat(section7): unify «Концепция» into one engine driven by building_program (#1953) (#2101)
All checks were successful
Deploy / deploy (push) Successful in 1m14s
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 3m13s
2026-06-30 08:35:55 +00:00
5f84008cb3 fix(site-finder): §4.2 «Качество данных» — inline-стили (Tailwind flex/gap не применяется) (#1953) (#2100)
All checks were successful
Deploy / build-frontend (push) Successful in 3m28s
Deploy / changes (push) Successful in 9s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / deploy (push) Successful in 1m15s
2026-06-30 07:33:11 +00:00
005ce2f4ad fix(site-finder): §4.2 «Качество данных» — воздух вокруг разделителя (#1953) (#2099)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 3m22s
Deploy / deploy (push) Successful in 1m19s
2026-06-30 07:13:16 +00:00
f448b550b5 feat(site-finder): §7 «Концепция» — методики + синхронизация подписей (#1953, batch D) (#2098)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 3m30s
Deploy / deploy (push) Successful in 1m14s
2026-06-29 12:24:21 +00:00
d9915c7834 fix(site-finder): unify §3 «Сети» table↔map source + enrich popups (#1953, batch C) (#2097)
All checks were successful
Deploy / build-backend (push) Has been skipped
Deploy / build-frontend (push) Successful in 3m4s
Deploy / changes (push) Successful in 7s
Deploy / build-worker (push) Has been skipped
Deploy / deploy (push) Successful in 1m21s
2026-06-29 11:56:11 +00:00
1337fadb49 fix(forecast): §6 honesty layer — pegged deficit, non-residential caveat, segment/pipeline note (#1953) (#2096)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 3m21s
Deploy / deploy (push) Successful in 1m14s
2026-06-29 11:26:35 +00:00
86f0797499 fix(site-finder): report microcopy batch A — gate titles, breadcrumb area, §4.2/4.3 (#1953) (#2095)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 3m8s
Deploy / deploy (push) Successful in 1m19s
2026-06-29 08:29:34 +00:00
a35d42f1c7 fix(site-finder): invest-score advisory flag + velocity data-honesty + h1 a11y (#1926) (#2094)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Successful in 5m22s
Deploy / build-frontend (push) Successful in 6m11s
Deploy / build-worker (push) Successful in 7m53s
Deploy / deploy (push) Successful in 2m23s
2026-06-29 06:42:50 +00:00
caffd9b28d Merge pull request 'fix(tradein/v2): убрать средний скаттер «ЦЕНА × СРОК ПРОДАЖИ» из результата' (#2093) from fix/tradein-v2-drop-result-scatter into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Successful in 50s
Deploy Trade-In / build-frontend (push) Successful in 1m58s
2026-06-28 23:21:11 +00:00
267e5dfc5b fix(tradein/v2): убрать средний скаттер «ЦЕНА × СРОК ПРОДАЖИ» из результата
All checks were successful
CI / changes (pull_request) Successful in 7s
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
По фидбэку: куцый inline-скаттер в 02 РЕЗУЛЬТАТ мало что говорил и дублировал
полный price×time график в Аналитике. Удалён; ряд диапазонов теперь grid 1fr 1fr —
два range-бара (объявления/сделки) на всю ширину, читаются прямее. Полный
точечный график остаётся в оверлее Аналитики (таб 06).

- ResultPanel.tsx: удалён scatter-блок (title + SVG + легенда + «Подробнее»),
  grid ряда «1fr 168px 1fr» -> «1fr 1fr»; убраны ставшие мёртвыми токены
  scatterDeal / line3.
- data.scatterMini в контракте оставлен (маппер всё ещё считает, просто не
  потребляется) — чистку контракта можно сделать отдельно.

tsc + next build green.
2026-06-29 02:20:45 +03:00
11a7018e78 Merge pull request 'feat(tradein/sale-share): тумблер «Сейчас / За 45 дней» + фильтр «мин. объявлений»' (#2092) from feat/tradein-sale-share-45d-toggle into main
All checks were successful
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m52s
Deploy Trade-In / deploy (push) Successful in 53s
2026-06-28 23:13:14 +00:00
0ea850c957 feat(tradein/sale-share): тумблер «Сейчас / За 45 дней» + фильтр «мин. объявлений»
All checks were successful
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 / changes (pull_request) Successful in 7s
#3: переключатель окна метрики (now/45д) — меняет показываемый %
(sale_share_pct↔sale_share_pct_45d), счётчик (active_secondary↔listings_45d) и
сортировку (share_desc↔share_45d_desc, active_desc↔count_45d_desc). 45д-данные
уже были в API — фронт их не показывал (потому тумблер и не находился).
#2: поле «Мин. объявлений в доме» — client-side фильтр по оконному счётчику.

Frontend-only (бэк/API/deps не тронуты). typecheck clean.
NB: маркеры карты пока по now-метрике (мелкий follow-up).
2026-06-29 02:12:04 +03:00
4863e67f27 Merge pull request 'fix(tradein/v2): источники N1+Restate вон, Домклик в текст; disabled-палитра до AA (#2081 follow-up)' (#2091) from fix/tradein-v2-audit-round2b into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m48s
Deploy Trade-In / deploy (push) Successful in 50s
2026-06-28 23:03:48 +00:00
c362b8592a fix(tradein/v2): источники N1+Restate вон, Домклик в текст; disabled-палитра до AA (#2081)
All checks were successful
CI / changes (pull_request) Successful in 6s
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
- M9 correction: #2086 ошибочно убрал Домклик из «как считаем» (по stale-ссылке на
  #1968 «drop dead domklik»), но live-проверка под админом показала Домклик живым
  (реально даёт лоты). Возвращён в текст. N1.RU + RESTATE убраны из SOURCE_SLOTS
  (мёртвые — всегда «нет данных», не учитываем) → плитки и счётчик «N / 7» → «N / 5».
  TOTAL_SOURCES = SOURCE_SLOTS.length (единый источник истины: плитки/счётчик/текст
  не расходятся). Итог: Циан, Я.Недвижимость, Авито, Домклик (+ Росреестр сделки).
- C1 residual: disabledValue («—» no-data) #c2cdd9 1.4:1 -> #656b71 4.61:1;
  disabledLabel («нет данных») #aab7c5 1.7:1 -> #636b73 4.62:1. Аудит #2081 флагал
  «нет данных», #2086 дотемнил только muted-шкалу — disabled-палитру пропустил.

tsc + next build green. Найдено live-проверкой /trade-in/v2 под админом (реальная оценка).
2026-06-29 02:03:16 +03:00
69845ddcee fix(tradein/avito-detail): живой прогрев сессии + батч-на-сессию — снимает 403 на curl-backfill (#1551)
All checks were successful
Deploy Trade-In / changes (push) Successful in 12s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m27s
Deploy Trade-In / build-backend (push) Successful in 51s
Deploy Trade-In / deploy (push) Successful in 1m37s
2026-06-28 22:34:38 +00:00
cbe56cab0e Merge pull request 'fix(tradein): cadastre ЖКХ-fallback + COALESCE merge-key + median-floors guard' (#2090) from feat/tradein-zhkh-cadastre-plus into main
Some checks failed
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Has been cancelled
2026-06-28 22:34:15 +00:00
078dadc440 fix(tradein): cadastre ЖКХ-fallback + COALESCE merge-key + median-floors guard
All checks were successful
CI / changes (pull_request) Successful in 7s
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
Серия sale-share data-quality (по находкам юзера):
- house_dedup_merge: cluster_key → tradein_canon_addr(COALESCE(short_address,
  full_address, address)) — ловит дубли с район-noise в address (Вайнера 66).
- zhkh_flats_loader: cadastre-fallback (searchByAddress по cadastreNumber,
  guid-независимо) — резолвит дома где gar_house_guid ≠ ЖКХ houseGuid
  (Переходный 6: guid→0, cadastre→165). CLI --cadastre.
- мигр.153: плаузибилити-гард по медиане этажности листингов — denom >=
  GREATEST(total_floors, median(listings.total_floors), 8); отсекает gar-недосчёт
  башен без ЖКХ (gar=9 vs листинги 19-26 эт → NULL).

ruff clean, pytest 36 green.
2026-06-29 01:32:48 +03:00
169201bb8c Merge pull request 'feat(tradein/sale-share): standalone «Поиск домов» — de-Mera + gendsgn.ru/sale-share' (#2088) from feat/tradein-sale-share-standalone into main
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy Trade-In / changes (push) Successful in 12s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy / build-frontend (push) Successful in 33s
Deploy / build-backend (push) Successful in 36s
Deploy / build-worker (push) Successful in 35s
Deploy / deploy (push) Successful in 1m21s
Deploy Trade-In / build-frontend (push) Successful in 2m7s
Deploy Trade-In / deploy (push) Successful in 50s
2026-06-28 22:23:52 +00:00
bb54de6000 feat(tradein/sale-share): standalone «Поиск домов» — de-Mera + gendsgn.ru/sale-share
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Поиск домов (доля квартир в продаже) вынесен в отдельный продукт, отвязан от
бренда «Мера» (Мера = оценка вторички). Только UI + 1 строка Caddy, бэк не тронут.

- app/sale-share/layout.tsx: своя metadata (title «Поиск домов — gendsgn»).
- components/trade-in/SaleShareHeader.tsx: своя шапка — продукт «Поиск домов»,
  без MeraMark и Mera-табов; UserMenu (auth) сохранён.
- app/sale-share/page.tsx: Topbar → SaleShareHeader; убраны «Мера» из
  breadcrumb/footer. Функционал/API (/trade-in/api/...) не тронут.
- Caddyfile: gendsgn.ru/sale-share → redir /trade-in/sale-share (короткий адрес;
  basePath=/trade-in → true vanity-URL требует отдельного app).
2026-06-29 01:09:26 +03:00
89fb666d88 Merge pull request 'fix(tradein/v2): UI/UX аудит round 2 — AA-контраст, честность чисел, a11y (#2081)' (#2086) from fix/tradein-v2-audit-round2 into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m55s
Deploy Trade-In / deploy (push) Successful in 52s
2026-06-28 22:03:38 +00:00
f5a7f9b437 fix(tradein/v2): UI/UX audit round 2 — AA contrast, honesty, a11y (#2081)
All checks were successful
CI / changes (pull_request) Successful in 8s
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
C1 (tokens): darken muted scale to WCAG AA (>=4.5:1 vs worst-case canvas
  #e6eef7); reclassify primary labels muted->body2 across components.
H1 (mappers): planning chip derived from rooms actually present in the
  analog set («Все планировки» when heterogeneous) — no number shifted.
H2 (ResultPanel): make «ОЖИДАЕМАЯ ЦЕНА СДЕЛКИ» the headline (accent
  border/tint/glow + larger value); demote ДКП·Росреестр to a muted
  СПРАВОЧНО reference tile. All three values + mapResultPanel wiring intact.
H3 (mappers): parseAddress keeps the house number for prefix-less
  addresses («Белинского, 86»); prefixed path unchanged.
M4 (page/HeroBar/Footer): gate dead controls (КАК РАССЧИТАНО / PDF /
  ДЕЙСТВИТЕЛЕН ДО / footer validity) on hasEstimate (mounted && estimate && !insufficient).
M5 (LocationDrawer): real dialog — role=dialog/aria-modal/aria-labelledby
  + focus-trap + <button> close + Esc preventDefault/stopPropagation.
M6 (ParamsPanel): address autocomplete -> combobox ARIA + Arrow/Home/End/
  Enter/Escape keyboard nav (mirrors Dd listbox).
M7 (Sources/Cache/Analytics/History): ARIA table semantics over the grids;
  Analytics scroll region keyboard-focusable (clears the serious
  scrollable-region-focusable axe violation); chart SVGs get role=img+title+aria-label.
M8 (CacheView): normalize the ВРЕМЯ column (normTime) to consistent minute precision.
M9 (LocationDrawer): honest «как считаем» source list (Циан, Я.Недвижимость,
  Авито, N1.ru + Росреестр) — drop dead Домклик/Restate per #1968.
M10 (ParamsPanel/mapMarkers): subject pin shows the subject's own area; drop
  analog pins overlapping the subject center (was misread as subject data).
M11 (ObjectSummary/SourcesView): label «медиана объявлений»; hide all-«—» columns/rows.
M13 (page): clamp artboard scale >=0.88 so micro-type doesn't drop below ~8px.
L1 (Analytics): suppress fake «X–Y дн» range when n<2.
L2 (Analytics): drop zero-data series from price-history subtitle.
L7 (TopNav): replace hardcoded #6f8195 icon strokes with tokens.muted.

tsc + next build green. No FE test infra in tradein-mvp/frontend — parseAddress
verified via standalone harness (6/6). Backend data-contract items M1/M2/M3/H4
(source counter, ratio vs medians, bargain bases, cross-source dedup) filed
separately — not FE bugs. L6 (blueprint-grid axe-blindness) deferred: base
gradient + glass surfaces keep axe contrast «incomplete» regardless, so the
authoritative check stays the manual computed-color sweep.
2026-06-29 01:01:30 +03:00
31e7816967 Merge pull request 'fix(tradein/dedup): canon cluster-key + geo/digit guard в house-merge (P4c)' (#2085) from fix/tradein-house-dedup-canon into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / deploy (push) Successful in 51s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m27s
Deploy Trade-In / build-backend (push) Successful in 55s
2026-06-28 21:53:15 +00:00
7cf6267b48 fix(tradein/dedup): canon cluster-key + geo/digit guard в house-merge
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
merge_duplicate_houses кластеризовал дома по exact lower(trim(address)) →
варианты написания одного здания (ул. Вайнера,66 vs улица Вайнера, 66) не
схлопывались, расщепляя долю в sale-share. Ключ кластера → tradein_canon_addr
(ул→улица, стрип город/район, КОРПУС сохранён). Гарды против over-merge:
- гео ≤250м (canon стрипует город; прод-дубли Мраморская 34к4 в 222м; города
  региона-66 в км+ → 250м безопасно от cross-town);
- canon обязан содержать цифру (номер дома) — исключает вырожденные
  «екатеринбург»/«сооружение».
Re-pointing/audit/dry-run/идемпотентность не тронуты. 26 passed.
2026-06-29 00:50:57 +03:00
a96af4c19c Merge pull request 'fix(tradein/sale-share): гард по этажности — отсечь near-neighbor mis-match' (#2084) from fix/tradein-floors-guard into main
All checks were successful
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m26s
Deploy Trade-In / deploy (push) Successful in 51s
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 53s
2026-06-28 21:32:23 +00:00
ebc3813648 fix(tradein/sale-share): гард по этажности — отсечь near-neighbor mis-match
All checks were successful
CI / changes (pull_request) Successful in 8s
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
Гео-фильтр ≤300м (мигр.150) широк для плотной застройки: к 5-этажному дому
(Мраморская 34к4) примагничены чужие листинги 9/16/19-этажных башен (Благодатская
15, Мраморская 6) на 229-282м — все <300м, фильтр не отсекал.

- мигр.152: +houses.zhkh_floors (parse zhkh_floors_raw "10-30"→max); гард во view
  во всех 5 FILTER: считать листинг только если abs(l.total_floors -
  COALESCE(zhkh_floors, total_floors)) <= 3 (или этажность неизвестна). Гео-фильтр
  300м сохранён.
- buildings_query.build_listings_query: тот же гард в детальной выдаче.

Прод-замер: отсекает 2754 листинга (12%) height-mismatched. Покрытие этажности
75% total_floors / 73% ЖКХ. ruff clean, pytest 26 green.
2026-06-29 00:31:09 +03:00
1b515f4e94 Merge pull request 'fix(tradein/sale-share): дедуп карточки листингов + чистка голых алиасов (#4 + P4a)' (#2083) from fix/tradein-clean-bare-aliases into main
All checks were successful
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m26s
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-backend (push) Successful in 55s
Deploy Trade-In / deploy (push) Successful in 50s
2026-06-28 21:23:55 +00:00
b105e0a500 fix(tradein/sale-share): дедуп карточки листингов + чистка голых алиасов
All checks were successful
CI / changes (pull_request) Successful in 8s
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
#4 Карточка дома показывала cross-площадочные дубли (Искровцев 33: 2 квартиры
= 4 строки avito/domklik/cian). build_listings_query теперь дедуплит по сигнатуре
(rooms, round(area_m2), floor) — как v_building_sale_share мигр.148 — одна строка
на квартиру, представитель = самый дешёвый, +колонка sources[] (площадки).
Гео-фильтр ≤300м (мигр.150) сохранён. +BuildingListing.sources в схеме.

P4a Мигр.151: DELETE 6338/21720 голых алиасов house_address_aliases (без номера
дома) — сток, в который сваливались безномерные листинги (Tier-2b). Матчер уже
захардненен (P1 #2082), голые не регенерируют. Алиасы — регенерируемый кэш,
house_id_fk/house_sources не тронуты.

ruff clean, pytest test_buildings_api 26 green.
2026-06-29 00:22:20 +03:00
ec4c7e9e6a Merge pull request 'fix(tradein/matching): не сваливать листинги в чужой дом (P1-P3 хардненинг матчера)' (#2082) from fix/tradein-house-match-hardening into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m33s
Deploy Trade-In / build-backend (push) Successful in 56s
Deploy Trade-In / deploy (push) Successful in 1m9s
2026-06-28 21:07:39 +00:00
384c4e7ac3 fix(tradein/matching): не сваливать листинги в чужой дом (P1-P3)
All checks were successful
CI / changes (pull_request) Successful in 8s
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
Три гарда в match_or_create_house (+ P2 в match_house_readonly):
- P1: не матчить/алиасить голую улицу (normalized_address без номера дома)
- P2: отклонять Tier-3 гео-кандидата, если номера домов различаются
- P3: не цементировать слабый гео-матч (0.7) как alias-ключ здания

Хелперы has_house_number/house_number_token (по хвостовому токену —
«улица 8 марта» это улица, не дом). Корень mis-bucketing: house 131237
стянул 8 разных Мамина-номеров + голую улицу. Юнит + поведенческие тесты,
603 matching/normalize/house зелёных. Аффектит только НОВЫЕ матчи;
чистка cemented-данных — отдельной миграцией (P4).
2026-06-29 00:06:13 +03:00
bd3562b6bd Merge pull request 'fix(tradein/sale-share): гео-фильтр числителя ≤300м — отсечь mis-bucketed листинги' (#2080) from feat/tradein-sale-share-geofilter into main
Some checks failed
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 55s
Deploy Trade-In / changes (push) Successful in 13s
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m34s
Deploy Trade-In / deploy (push) Failing after 10m2s
2026-06-28 20:25:48 +00:00
f617c323bd fix(tradein/sale-share): гео-фильтр числителя ≤300м — отсечь mis-bucketed листинги
All checks were successful
CI / changes (pull_request) Successful in 9s
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
Листинги примагничиваются к НЕ ТОМУ дому (кривой house_id_fk): прод-замер 373
дома (5.5%) / 1685 листингов (7.2%) дальше 300м от своего дома. Пример — house
131237 «Мамина-Сибиряка 126» (ЖКХ=51 кв, знаменатель ВЕРНЫЙ): из 20 активных
листингов реально его ~2, остальные — Свердлова 32 / Азина 31 (до 2.2км) →
ложная доля 39% вместо ~4%.

- мигр.150: v_building_sale_share — числители (active/45д) + медианы считают
  только листинги ≤300м от geom дома (ST_DistanceSphere; листинг/дом без geom —
  keep). Знаменатель не тронут.
- buildings_query.build_listings_query: тот же гео-фильтр в детальной выдаче
  (карточка дома больше не показывает чужие листинги).

Симуляция на проде: меняется 351 дом, обнуляется 164 (чистые «мусорные вёдра»),
числитель −8.3%. Мамина-126: 20→2. Это митигация на уровне view; корневой фикс
house_id_fk-матчера — отдельно. ruff clean, pytest 24 green.
2026-06-28 23:24:05 +03:00
0f82b58265 Merge pull request 'fix(tradein/v2): a11y contrast — source badges ≥AA в оверлеях (#2062)' (#2079) from fix/tradein-v2-a11y-contrast into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 2m7s
Deploy Trade-In / deploy (push) Successful in 56s
2026-06-28 19:21:36 +00:00
848a44c629 fix(tradein/v2): a11y contrast — source badges ≥AA в оверлеях (#2062)
All checks were successful
CI / changes (pull_request) Successful in 7s
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
Прод-QA P3 нашёл 10 axe color-contrast (serious) в оверлее 05: 9px source-бейджи tokens.muted (#6f8195) на badgeTint ≈3,3:1 < AA. SourcesView badge muted→body2 (≈6,3:1); HistoryView ДКП source badge accent→accentDeep (≈5:1, синий сохранён). Закрывает хвост item-9 (микро-лейблы <4.5:1) → axe 0 и в оверлеях.
2026-06-28 22:21:10 +03:00
565d5c906b Merge pull request 'fix(tradein/v2): a11y P3b — клавиатурная форма 01 (#2062)' (#2078) from fix/tradein-v2-a11y-form into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m34s
Deploy Trade-In / build-frontend (push) Successful in 2m19s
Deploy Trade-In / build-backend (push) Successful in 44s
Deploy Trade-In / deploy (push) Successful in 1m31s
2026-06-28 18:58:34 +00:00
32a58c91c5 fix(tradein/v2): a11y P3b — клавиатурная форма 01 (#2062)
All checks were successful
CI / changes (pull_request) Successful in 7s
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
Закрывает headline аудита: «с клавиатуры/скринридера нельзя завершить оценку».
Визуально без изменений — UA-chrome кнопок сброшен явно (Tailwind preflight в
tradein-mvp не подключён, кнопки не наследуют font-family).

- Dd-дропдаун (КОМНАТ/ТИП/РЕМОНТ) + РАДИУС: trigger div→<button role=combobox
  aria-haspopup=listbox aria-expanded aria-controls aria-activedescendant
  aria-label>; панель role=listbox, опции role=option/aria-selected + active-
  highlight. Клавиши Arrow↑↓/Home/End/Enter/Space/Esc/Tab (общий comboKeyDown,
  паттерн aria-activedescendant — фокус остаётся на кнопке).
- БАЛКОН → role=radiogroup + два <button role=radio aria-checked> (roving
  tabindex + стрелки + Space/Enter); tri-state (null = ни один не выбран) сохранён.
- Инпуты: <label htmlFor>/id; aria-invalid + aria-describedby на ошибках
  адреса/площади (id ошибки).
- Кнопки зума карты: div→<button aria-label>, «−» реально disabled на полу зума.

Мышиный поток идентичен прежнему; клавиатура аддитивна. code-reviewer  (UA-chrome
покрыт, keyboard/mouse корректны).
2026-06-28 21:58:03 +03:00
ec03a43283 Merge pull request 'feat(tradein/zhkh): ЖКХ-приоритет знаменателя «квартир в доме» + loader' (#2077) from feat/tradein-zhkh-denominator into main
Some checks failed
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m27s
Deploy Trade-In / build-backend (push) Has been cancelled
2026-06-28 18:56:34 +00:00
77c01b6d3b feat(tradein/zhkh): ЖКХ-приоритет знаменателя «квартир в доме» + loader
All checks were successful
CI / changes (pull_request) Successful in 7s
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
ГАР дико недосчитывает квартиры в МКД (прод-замер: Крауля 89А ГАР=11 vs
ЖКХ=429; 27 из 347 домов ГАР ≥2× недосчёт). ГИС ЖКХ точнее — резолвит ~90%
вторички с gar_house_guid.

- мигр.149: COALESCE знаменателя → ЖКХ ПЕРВЫЙ
  (zhkh_flat_count, gar_flat_count, total_units, flat_count) во всех 7 местах
  view v_building_sale_share; +houses.zhkh_year/zhkh_floors_raw; +transparency-
  колонки zhkh_flat_count/flat_count_source.
- app/services/zhkh_flats_loader.py + app/tasks/zhkh_flats_load.py: фетч ГИС ЖКХ
  searchByAddress (батч ≤100 по gar_house_guid == ЖКХ houseGuid, pageIndex=1,
  cookieless), идемпотентный UPDATE houses.zhkh_* (CAST(:x AS type) +
  IS DISTINCT FROM gate, SAVEPOINT-чанки, dry-run).

Безопасно к мержу: до ручного прогона loader'а zhkh_flat_count=NULL → COALESCE
падает на ГАР → поведение идентично до-149. ruff clean, pytest 8 green.
2026-06-28 21:55:05 +03:00
f60f2b24e6 Merge pull request 'fix(tradein/v2): a11y P3a — нативные контролы + модальный диалог + aria-live (#2062)' (#2076) from fix/tradein-v2-a11y-native into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m51s
Deploy Trade-In / deploy (push) Successful in 53s
2026-06-28 18:30:09 +00:00
7066117cb8 fix(tradein/v2): a11y P3a — нативные контролы + модальный диалог + aria-live (#2062)
All checks were successful
CI / changes (pull_request) Successful in 6s
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
CRITICAL-доступность (часть 1): клавиатура/скринридер. Без визуальных изменений
(chrome-reset кнопок вынесен в CSS-классы, :hover и font-size сохранены).

- Клик-only <div> → нативные <button>: nav-табы (+aria-current), user-меню
  (aria-haspopup/expanded + Esc-close), «Выйти», «Подробнее →» (ResultPanel,
  +aria-label по разделу), строки 03 СВОДКИ (ObjectSummary, +aria-label).
- SectionOverlay → настоящая модалка: role=dialog, aria-modal, aria-labelledby,
  Esc-close, фокус на диалог при открытии, focus-trap (Tab/Shift+Tab),
  возврат фокуса на триггер при закрытии; «← К ОЦЕНКЕ» → <button>.
- page.tsx: aria-live="polite" role=status — «Идёт расчёт… / Оценка готова /
  Недостаточно данных / Ошибка»; фон (content-wrap) inert когда открыт
  оверлей или drawer (overlay/drawer остаются интерактивны).

Остаётся P3b: ParamsPanel-форма (Dd→listbox+клавиши, БАЛКОН→radiogroup,
input <label>/aria) — заход «с клавиатуры можно завершить оценку».
2026-06-28 21:29:19 +03:00
0641183ecd fix(tradein): дедуп объявлений по квартире + over_100 NULL-фикс (500 на списке) (148) (#2075)
All checks were successful
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m29s
Deploy Trade-In / build-backend (push) Successful in 58s
Deploy Trade-In / deploy (push) Successful in 1m15s
2026-06-28 18:04:32 +00:00
efa2dc75ea Merge pull request 'feat(tradein/scheduler): cooperative drain coverage for sweeps/full-loads (phase 3a)' (#2074) from feat/tradein-sweep-drain-coverage into main
Some checks failed
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Has been cancelled
2026-06-28 18:04:02 +00:00
b45a819cb6 fix(tradein): канон срезает гео-префиксы (Россия/Екатеринбург/мкр/пр-т) + REINDEX — покрытие 38%→~70% (147) (#2073)
All checks were successful
Deploy Trade-In / changes (push) Successful in 14s
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 31s
Deploy Trade-In / test (push) Successful in 1m33s
Deploy Trade-In / build-backend (push) Successful in 27s
Deploy Trade-In / deploy (push) Successful in 53s
2026-06-28 17:54:26 +00:00
3320805723 feat(tradein/scraper): cooperative SIGTERM-drain coverage for sweep/full-load loops (#1182 Phase 3a)
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Extend the cooperative shutdown-drain (Phase 2) to the long sweep and
full-load loops in scrape_pipeline.py so they stop CLEANLY on SIGTERM
instead of being hard-cancelled at the 80s _drain_inflight timeout.

At every between-unit checkpoint that already polls scrape_runs.is_cancelled
(user-cancel) we add an ALONGSIDE shutdown_requested() branch:
  - anchor-loop sweeps (avito/yandex/cian city) + avito newbuilding +
    domclick pre-SERP: update_heartbeat + mark_done(partial) + return;
  - full-load on_bucket callbacks (cian/yandex/avito): raise a distinct
    RuntimeError("shutdown") sentinel, handled next to the existing
    "cancelled" sentinel -> mark_done(partial), skipping the detail phase;
  - cian full-load detail loop: break -> existing post-loop mark_done.

Drain finalizes as mark_done(partial), NOT mark_cancelled (that stays
user-cancel only). is_cancelled -> user-cancel semantics are unchanged, and
behaviour is identical when shutdown_requested() is False. No resume_cursor
or paused status yet (Phase 3b, deferred): this is drain-coverage only.

Tests: tests/test_sweep_drain.py covers both structural variants -
run_avito_city_sweep / run_cian_city_sweep (anchor-loop) and
run_avito_full_load (on_bucket sentinel): shutdown flips True after the
first unit, asserting the sweep stops at the checkpoint, calls mark_done
with partial counters, never calls mark_cancelled, and does not process
later anchors/buckets/phases.
2026-06-28 20:52:30 +03:00
eab3d928d6 Merge pull request 'fix(tradein/v2): UI/UX-аудит P2 — контент/честность/иерархия (#2062)' (#2072) from fix/tradein-v2-uiux-p2-content into main
Some checks failed
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m28s
Deploy Trade-In / build-backend (push) Has been cancelled
Deploy Trade-In / build-frontend (push) Has been cancelled
2026-06-28 17:52:28 +00:00
1722309372 fix(tradein/v2): UI/UX-аудит P2 — контент/честность/иерархия (#2062)
All checks were successful
CI / changes (pull_request) Successful in 7s
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
- Опц. поля больше не шлют непроверенные дефолты в ценовую модель:
  ТИП/РЕМОНТ → «Не указано»→undefined, БАЛКОН tri-state (null пока не
  трогали) → undefined.
- Валидация у поля: красная рамка + сообщение под адресом/площадью,
  показываются ВСЕ блокеры (не только первый); низ — только серверная ошибка.
- Копирайт «вы»: «если знаете»; кэш-строка → «ДАННЫЕ АКТУАЛЬНЫ ·
  ДЕЙСТВИТЕЛЕН 24 Ч»; drawer без жаргона (убраны (asking)/POI).
- Даты сделок Росреестра → «янв 2026» (месяц, не фейк-день 01.01);
  бренды источников без method-суффиксов (РОСРЕЕСТР/АВИТО/ДОМКЛИК);
  «эталон»→«опорная цена».
- График истории цен: зум оси Y к реальному диапазону данных + динамические
  подписи оси; легенда серии показывается только при наличии линии.
- 3 цены весомее (font-weight 400); медиана-маркеры range-баров → тонкий тик
  (не выглядит как draggable-ручка); фото здания — синий duotone +
  десатурация (не крадёт первый взгляд у цен).
- Таблицы аналогов/сделок: площадь/комнаты/этаж вынесены из адресной ячейки
  в колонку ПАРАМЕТРЫ; ↗→› в СВОДКЕ.

Сознательно НЕ тронуто: перераспределение accent-синего (item 9) — axe уже 0,
а широкое снятие акцента конфликтует с «не ломать HUD-палитру»; монотонность
тиров срока продажи не форсируется (это были бы выдуманные данные).
2026-06-28 20:51:49 +03:00
2a38561175 feat(tradein): второй % «за 45 дней» + zhkh-знаменатель slot (146) (#2071)
Some checks failed
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Has been cancelled
2026-06-28 17:51:38 +00:00
c8e7cb1c79 perf(objective_lots): inline DISTINCT ON for 3 view-fullscan consumers + cache landing stats (#1953) (#2067)
All checks were successful
Deploy / build-frontend (push) Has been skipped
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Successful in 2m8s
Deploy / build-worker (push) Successful in 3m16s
Deploy / deploy (push) Successful in 5m41s
2026-06-28 17:25:41 +00:00