No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#674
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/tradein-651-652-accuracy"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
KILLER demo fix. Radius-median systematically underestimated premium/view units ~2x (no class/segment correction; the real Avito IMV + ДКП data were in the DB but unused).
#651 — blend the real Avito IMV anchor (house_imv_evaluations, per house_id — the populated table; avito_imv_evaluations is empty) one-directional RAISE-ONLY: when IMV recommended > median×1.15, median = blend(median, IMV, w=0.5) and range_high extends to IMV higher. Behind config flags (estimate_imv_blend_*, default on), fully null-guarded → no-op when IMV absent.
#652 — surface a ДКП corridor (rosreestr deals, ₽/m², advisory + soft ±25% sanity note, NO hard clamp).
Schema: avito_imv + dkp_corridor on AggregatedEstimate. Frontend (tradein-mvp/frontend, the DEPLOYED UI): IMV caption + corridor line in HeroSummary; TS types added; tsc clean. Backend ruff clean; 9 new + 43 regression tests pass.
Validated on live DB (e.g. Б. Ельцина 6, 80m², Центр: 19.7M→25.8M, range→33.5M).
⚠️ KNOWN GAP: IMV coverage is partial across the golden premium set — Сакко-Ванцетти 99 / Олимпийская 5 / Ткачёва 13 (Clever Park) have NO IMV anchor yet, so those specific demo addresses still under-estimate until IMV is scraped for them (#562). Full 53-case KPI to be run on the live stack post-deploy.
Milestone 6 (Praktika demo). Closes #651, Closes #652
Verdict: FIX (changes needed before merge). The Avito IMV blend + ДКП corridor are well-built (one-directional raise, feature-flagged, threshold-gated x1.15, weight clamped [0,1], graceful-None on missing data, additive/optional schema + strict TS, no div-by-zero/NaN). But there is one client-facing correctness bug that must be fixed before merge.
1. CRITICAL -- stale
expected_sold_*after the blend.expected_sold_price/expected_sold_range_low/expected_sold_range_high/expected_sold_per_m2are computed atestimator.py:1035-1038from the PRE-blendmedian_price/range_high/median_ppm2. The #651 blend then mutatesmedian_price,median_ppm2,range_highat:1219-1227but never recomputes theexpected_sold_*values. Both are surfaced together inHeroSummary.tsx-- headline asking = blendedmedian_price_rub(line 272), "ожидаемая цена продажи" = un-blendedexpected_sold_price_rub(line 300). In your own test scenario (median 50M -> blended 75M, ratio ~0.9) the UI would show asking 75M / expected-sold 45M and a computed discount of1 - 45/75 = 40%(HeroSummary line 86) -- a nonsensical trade-in offer shown to the client. The stale values are also persisted totrade_in_estimates(:1294/:1360).Fix: move the asking->sold computation to AFTER the blend block, or re-derive
expected_sold_*from the post-blend median/range/ppm2 (applyasking_to_sold_ratioonce, after:1227). Then add a consistency test: when the blend fires, assertexpected_sold_price == round(blended_median * asking_to_sold_ratio).2. MINOR (follow-up OK, not blocking) -- IMV anchor has no rooms/area band.
estimator.py:686-715ranks the closest rooms+area row viaORDER BYbut has noWHEREband onrooms/area_m2. A house with only a studio IMV record will still return it as the anchor for a 3-room target (best-available wins), and since the blend fires whenanchor > median x 1.15, a mismatched larger/different unit could inflate a smaller target. Consider a guard (abs(Δrooms) <= 1or an area band) before treating the row as a usable anchor.Test gaps to close alongside the fix:
expected_sold_*<-> blended-median consistency (the bug above)._fetch_dkp_corridorcount >= 3/ ±25% slack branch (:1247-1257).weightclampmax(0, min(1, weight))not exercised with out-of-range input.Re-request review after the fix; I will re-review at the new head SHA.
Fixed both findings:
Also added weight-clamp [0,1] and corridor count-branch tests. ruff clean; 26 blend/expected_sold + 145 estimator regression pass.
Re-requesting review.
Re-review after fix. Critical bug RESOLVED: expected_sold_* now computed AFTER the #651 IMV-blend (post-blend median/range/ppm2), removing the stale pre-blend values that produced inconsistent asking/sold in HeroSummary. Verified by new full-path test test_expected_sold_consistent_with_blended_median (pre-blend 6M -> blended 12M, asserts expected_sold == round(blended_medianratio)). Also fixed the rooms/area anchor band-guard (abs(rooms-:rooms)<=1, area_m2 BETWEEN :area0.7..1.3, NULL-graceful, CAST(:x AS type) psycopg v3 ? no ::) with tests, plus weight-clamp and DKP-count<3 tests, and DATABASE_URL -> postgresql+psycopg://. Blend math vetted sound prior review. APPROVE.
Code APPROVED — but a rebase is now required before merge (not a code issue).
The fix is correct and I approved it. However, sibling PR #673 merged into
mainmoments ago, and both PRs modifytradein-mvp/backend/app/services/estimator.py, so this PR is now non-mergeable (base moved → conflict). My merge attempt returned 405.Action: rebase onto current
forgejo/main(resolve theestimator.pyoverlap — your IMV-blend +expected_soldreordering vs #673's_with_budgettime-budget wrapping; they touch different regions ofestimate_quality, should be a clean textual resolution). No code changes needed beyond the rebase. Re-request review afterward; I will re-review + merge at the new head SHA.Apologies for the churn — this is on the review side (I merged two estimator.py PRs in the same pass). Going forward siblings touching a shared file will be merged across separate passes.
Rebased onto current main (head
70a1f60) after #673 merged. Resolved the estimator.py + config.py overlap: both #651 helpers (_fetch_house_imv_anchor / _apply_imv_blend / _fetch_dkp_corridor) and #673's _with_budget guard coexist; config.py keeps the IMV-blend + time-budget + quota blocks. estimate_quality body auto-merged (4 _with_budget calls + 6 blend refs both present). ruff clean; 30 blend/expected_sold/null-floor tests pass. No code changes beyond the rebase. Re-requesting review.Re-affirm APPROVE after rebase onto post-#673 main. Verified: 0 conflicts, mergeable=true, no _with_budget duplication (it is in base from merged #673; #674 diff does not re-add it), approved fix intact (expected_sold computed post-blend + rooms/area band-guard), IMV-blend logic unchanged from prior approval. Merging now.