bot-backend
9de867631b
feat(tradein/ui): честное раскрытие покрытия диапазона в hero ( #2209 )
...
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 8s
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Successful in 1m3s
Хинт диапазона expected_sold дополнен замеренной точностью: «фактическая
цена продажи попадает в диапазон в ~80% случаев (июль 2026)» — по живому
бэктесту на реальных ДКП Росреестра (n=276, coverage 81.5%, engine=full).
Раскрытие вместо молчаливой выдачи Q1-Q3 за прогнозный интервал —
acceptance-пункт «явно раскрыть точность/покрытие» из #2209 .
Refs #2209
2026-07-03 00:23:03 +03:00
19ecd941f3
fix(tradein/ui): единый source-registry + честные знаменатели/лейблы источников ( #2211 ) ( #2227 )
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 Trade-In / build-frontend (push) Successful in 3m3s
Deploy Trade-In / deploy (push) Successful in 1m4s
2026-07-02 20:57:26 +00:00
d63122d3e4
fix(tradein/v2): честная подача интервала оценки — одна цифра-герой + честный разброс
...
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
Оценщик жаловался на «большой интервал» между рекомендованной ценой и
оценкой. Бэктест: ширину коридора косметически не сузить (реальная рыночная
дисперсия + asking→sold gap). Чиним подачу, не число (математика не тронута).
Витрина /trade-in/v2 (активная, wired на real data через mapResultPanel):
- deltaLabel «К РЫНКУ» → «К ОБЪЯВЛ.» (mappers.ts + fixtures.ts): −N% —
разрыв «объявление → ожидаемая сделка», а не «скидка от нас».
- ResultPanel: честная подпись под ценовыми карточками — «Диапазоны
показывают разброс цен на рынке, а не погрешность оценки». Широкий
диапазон не читается как неуверенность расчёта.
- Иерархия expected_sold=headline / median=baseline / ДКП=справочно уже
была (audit H2, #2062/#2081) — не трогаем.
Легаси-витрина / (HeroSummary), тот же принцип и устранение конфликта термина:
- hero-duo: expected_sold — цифра-герой («Оценка · ожидаемая цена продажи»,
34px, accent), median — вторичный «Рекомендованная цена в объявлении»
(20px, приглушённый) вместо двух равнозначных 28px-блоков «Выставить»/
«Получить». Новый модификатор .hero-duo--sold-primary.
- Диапазон sold подписан «рыночный разброс» + honest hint «Диапазон отражает
разброс цен по рынку, а не погрешность оценки».
- Бейдж «−N%» → «−N% к объявлению» + title (разрыв asking↔сделка, не скидка).
- OfferCard: «Оценка по рынку» → «Цена в объявлении» (median ≠ «оценка»;
слово «оценка» на витрине = expected_sold).
Проверка: tsc --noEmit чисто; next build чисто (lint+types, 13 роутов).
2026-07-02 19:16:37 +03:00
3187419eb8
feat(tradein/ui): manual-review banner + premium-building badge on estimate ( #2002 )
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 1m53s
Deploy Trade-In / deploy (push) Successful in 52s
2026-06-27 19:09:46 +00:00
27766acf38
fix(trade-in/ui): расшифровка ДКП/IMV/CV + графики на --viz токены + убрать emoji из вердиктов ( #1871 )
...
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
- HeroSummary: все вхождения ДКП/IMV/CV обёрнуты в <abbr title="..."> с расшифровкой
- IMVBenchmark: «Avito IMV» → abbr с title
- HeroSummary/HeroTransparency: emoji ⚠️ заменены на span-точки var(--warn) + текст
- PriceHistoryChart: stroke="#2563eb"/"#ea580c" → var(--viz-1)/var(--viz-4)
- PriceRangeBar: "#bfdbfe"/"#1d4ed8" → color-mix(--viz-1)/var(--viz-1)
- SellTimeSensitivity: hardcoded bg-цвета → --success-soft/--accent-soft/--warn-soft/--danger-soft; border → var(--viz-1)
- MapCard: пины обновлены на hex-значения --viz-1/--viz-3/--viz-4 (Leaflet JS, не CSS-контекст)
- MapPicker: комментарий -- viz-1 hex (Leaflet constraint)
2026-06-26 19:16:55 +03:00
41e9c820c9
fix(tradein/estimator): ghost-anchor invariant guard — n_analogs=0 forces low (audit #1871 P1.2)
...
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
Audit #1871 P1.2: estimate 5fcc1e99 показывал confidence='high' при
n_analogs=0 (median 38.45M ₽, sources=['yandex_valuation']) при реальной
истории листингов дома 4.2-6.5M. По prod-DB это ЕДИНСТВЕННАЯ legacy-строка
от 2026-05-30, давно expired (TTL оценок = 1 день, все 66 high/medium-c-n<5
строк expired). Текущий mainline уже честен. Фикс — defensive invariant,
чтобы ghost не мог родиться снова из будущих external-valuation-blend /
rehydrate / migration путей.
Backend (estimator.py):
- helper _enforce_zero_analog_low(confidence, n_analogs, explanation, ...)
форсит 'low' + caveat когда n_analogs==0 and confidence!='low'.
Идемпотентен (low+0 → low без дубля caveat), не трогает high+N>0, реальный
median внешнего сервиса сохраняется (fake-коэффициенты не вводятся),
logger.warning для observability.
- Вызов перед сборкой AggregatedEstimate в estimate_quality (единственный
уязвимый return-путь; _empty_estimate хардкодит low — структурно безопасен).
- +5 unit-тестов (high+0→low+caveat, medium+0→low, low+0 идемпотент,
high+N unchanged, None-explanation).
Frontend (HeroSummary, HeroTransparency, history):
- effectiveConfidence = n_analogs===0 ? 'low' : confidence — defensive depth
на случай legacy-rehydrate / контракт-drift. Caveat-текст из backend
confidence_explanation (не хардкод). Type-safe (ConfidenceLevel).
Refs #1871
2026-06-23 11:05:34 +05:00
7080cce40e
feat(trade-in/ui): структурный analog_tier, address_precision в деталях, expected_sold бар, ratio_basis всегда
...
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
- types/trade-in.ts: добавлен AnalogTier тип и analog_tier? поле в AggregatedEstimate (опциональное, graceful при absent/null)
- HeroTransparency: resolveCompsTier() предпочитает analog_tier (структурный, без парсинга строки), fallback на compsTier() эвристику при absent/null; добавлена строка «Точность адреса» в collapsible «Как рассчитано» из address_precision с предупреждением при low+approximate
- HeroSummary: третий бар «Ожидаемая цена сделки» (expected_sold_price_rub/low/high) с отличным цветом (viz-5/6) — graceful при null; ratio_basis показывается всегда: per_rooms→«по сделкам той же планировки», global_fallback→прежний текст
2026-06-20 15:00:45 +03:00
44fdab2d5e
feat(tradein/ui): две равноправные hero-цены (выставить/получить) + компактный ряд бенчмарков, убрать дубли
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
2026-06-20 10:14:27 +03:00
3b38b3f004
feat(tradein-fe): уведомление при global_fallback asking→sold ratio (тонкий сегмент) ( #882 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m35s
Deploy Trade-In / deploy (push) Successful in 36s
Co-authored-by: bot-frontend <bot-frontend@gendsgn.local>
Co-committed-by: bot-frontend <bot-frontend@gendsgn.local>
2026-05-31 10:41:54 +00:00
679e75b9e8
fix(tradein): resilience-хвост аудита #770 (findings #25-33) ( #793 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m38s
Deploy Trade-In / deploy (push) Successful in 35s
Co-authored-by: bot-frontend <bot-frontend@gendsgn.local>
Co-committed-by: bot-frontend <bot-frontend@gendsgn.local>
2026-05-30 17:13:31 +00:00
93f85154a5
fix(tradein): gate «0,00 млн ₽» в не-headline секциях при insufficient_data ( #748 ) ( #751 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m34s
Deploy Trade-In / deploy (push) Successful in 1m7s
Co-authored-by: bot-frontend <bot-frontend@gendsgn.local>
Co-committed-by: bot-frontend <bot-frontend@gendsgn.local>
2026-05-30 15:58:19 +00:00
1b8e3b1f25
fix(tradein): confidence «средняя» → amber + FIXME для compsTier ( #742 ) ( #746 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Successful in 1m32s
Deploy Trade-In / deploy (push) Successful in 36s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Co-authored-by: bot-frontend <bot-frontend@gendsgn.local>
Co-committed-by: bot-frontend <bot-frontend@gendsgn.local>
2026-05-30 15:44:37 +00:00
798fb12b4c
feat(tradein): HeroSummary empty-state при insufficient_data ( #740 ) ( #743 )
...
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / build-frontend (push) Successful in 1m34s
Deploy Trade-In / deploy (push) Successful in 34s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Co-authored-by: bot-frontend <bot-frontend@gendsgn.local>
Co-committed-by: bot-frontend <bot-frontend@gendsgn.local>
2026-05-30 15:37:13 +00:00
6609d7a4cb
feat(tradein): trust + actions (how-calculated, freshness, PDF, lead CTA) in result header ( #689 )
...
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Failing after 54s
Deploy Trade-In / deploy (push) Has been skipped
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 08:16:12 +00:00
f43d593cf6
feat(tradein): brand-by-account + result IA redesign (distinct asking/sale prices) ( #683 )
...
Deploy Trade-In / changes (push) Successful in 4s
Deploy Trade-In / test (push) Successful in 23s
Deploy Trade-In / build-backend (push) Successful in 43s
Deploy Trade-In / build-frontend (push) Successful in 1m37s
Deploy Trade-In / deploy (push) Successful in 36s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-30 06:45:14 +00:00
96f02d37f3
feat(tradein): blend Avito IMV anchor into estimate + ДКП corridor advisory ( #651 , #652 ) ( #674 )
...
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Successful in 46s
Deploy Trade-In / build-frontend (push) Successful in 1m38s
Deploy Trade-In / deploy (push) Successful in 36s
Co-authored-by: bot-backend <bot-backend@gendsgn.local>
Co-committed-by: bot-backend <bot-backend@gendsgn.local>
2026-05-29 17:42:06 +00:00
7d749f4080
feat(tradein): dual-display asking vs expected-sold in HeroSummary ( #648 S5a) ( #664 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m47s
Deploy Trade-In / deploy (push) Successful in 36s
2026-05-29 14:00:49 +00:00
492dd0aba6
feat(tradein): бейдж точности адреса (qc_geo) на карточке оценки (accuracy #1 )
...
Честность к пользователю: показываем насколько точно определён адрес —
«до дома» / «до улицы» / «приблизительно» — рядом с confidence.
- schemas/trade_in.py: address_precision: Literal["house","street","approximate"]|None
- estimator.py: _qc_geo_to_precision (qc_geo 0→house, 1→street, ≥2→approximate,
None→None), set в основном return + _empty_estimate
- api/v1/trade_in.py: get_estimate + estimate_pdf теперь rehydrate'ят DaData-поля
(canonical_address, house_cadnum, house_fias_id, address_precision, metro_nearest)
из row — раньше на ?id= reopen / в PDF вся Q1-обогащёнка пропадала (поймал
code-reviewer). Колонки уже persisted, фикс read-path.
- frontend: AddressPrecision type + precision-badge в HeroSummary (.card-meta),
токены --success/--accent-2/--bg-card-alt, без новых токенов.
Канон: tech-analyst (план) → backend-engineer + frontend-engineer → code-reviewer
(✅ APPROVE, поймал reopen-path gap) → fold-in fix. Tests: 7 passed, tsc clean, ruff clean.
match_house_readonly wiring отложен (fast-follow).
2026-05-28 15:37:33 +05:00
92d00ec874
feat(tradein-ui): mock-disclaimer + progressive enrichment + UX polish ( #517 )
Deploy Trade-In / build-frontend (push) Successful in 1m42s
Deploy Trade-In / deploy (push) Successful in 35s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-backend (push) Has been skipped
2026-05-24 12:58:39 +00:00
9b2a54788b
fix(tradein): восстановленная оценка показывает этаж/площадь, не 0/0
...
AggregatedEstimate не нёс параметры целевой квартиры (площадь, этаж,
комнаты, год, тип дома). HeroSummary брал их из формы-инпута — у
свежей оценки работало, но при открытии оценки по ссылке (?id=, из
Истории) формы нет → «Сводка» показывала «ЭТАЖ 0/0, Площадь 0 м²».
Параметры теперь проходят сквозь весь стек:
- AggregatedEstimate + TS-тип получили area_m2/rooms/floor/
total_floors/year_built/house_type/repair_state/has_balcony;
- estimate_quality заполняет их из payload, get_estimate — из строки
trade_in_estimates (колонки там уже есть);
- HeroSummary читает из estimate с откатом на input.
Заодно в TS-тип добавлен пропущенный est_days_on_market.
2026-05-22 15:50:19 +05:00
TradeIn Deploy
1941c3d7df
fix(tradein): фото аналога в Сводке + честный статус источников
...
UI-баги, замеченные при обзоре результата оценки:
- HeroSummary: блок hero-photo был пустым серым плейсхолдером (в
макете там фото, в коде слот не подключён). Теперь показывает фото
первого аналога с картинкой; onError → fallback на плейсхолдер.
- SourcesProgress: источники без данных после завершения оценки
оставались в статусе idle с подписью «ожидает запрос» — выглядело
как зависший запрос. Теперь после готовности → «нет данных»
(терминальный статус).
2026-05-22 12:02:56 +05:00
lekss361
02267d0306
feat: add tradein-mvp subproject (Trade-In Estimator под /trade-in)
...
- FastAPI backend: PostGIS estimator + 3 scrapers (Avito/Cian/Yandex)
- Next.js 15 frontend: tradein.html mockup design, basePath=/trade-in
- WeasyPrint PDF (Брусника-style 4-page report)
- Address autocomplete с typo-tolerance + 6 EKB presets
- Изолированный docker stack gendesign-tradein (отдельная postgres БД)
- Caddy inline routes: gendsgn.ru/trade-in/* и /trade-in/api/v1/*
- Forgejo Actions: .forgejo/workflows/deploy-tradein.yml (shell-based GHCR login)
- Триггер только по paths: tradein-mvp/** (не пересекается с deploy.yml)
- Образы: ghcr.io/lekss361/gendesign-tradein-{backend,frontend}:latest
Первый запуск на сервере (вручную, один раз):
- создать /opt/gendesign/tradein-mvp/.env.runtime (postgres pwd, contact email)
- docker network create gendesign_shared (если нет)
- docker compose -p gendesign-tradein up -d
- docker compose -p gendesign exec caddy caddy reload
2026-05-21 00:25:39 +03:00