feat(tradein-estimator): unique-address-based confidence threshold #513
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
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#513
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/tradein-confidence-unique-addresses"
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?
Problem
In
_compute_confidencethresholds were on rawn_analogs. WithMIN_ANALOGS_PER_SOURCE=5quota + same-building lots,n=10could come from just 2-3 unique buildings →confidence=highwas overstated.Fix
unique_addr ≥ 7 AND iqr_pct < 15%unique_addr ≥ 4OR (unique_addr ≥ 2 AND iqr_pct < 25%)avg_lots_per_addr > 2.5(anti-concentration bias)scripts/probe-confidence-distribution.pyto tune p75 threshold from real data.Roadmap
PR 4 of 8 —
[[Decision_TradeIn_DataQuality_8PR_Roadmap]]. Lands independently of PR #507; if order differs at merge time, one will need rebase (own-branch, --force-with-lease).Verify
Deep Code Review — PR #513
Status: APPROVE
Files: 2 (estimator.py P0 logic · probe script P3 ops tool) · +122/-16
Roadmap: PR 4/8 of Decision_TradeIn_DataQuality_8PR_Roadmap — aligned.
Correctness — sound
unique_addrs = {(lot.get('address') or '').strip().lower() for lot in listings if lot.get('address')}— корректно нормализует case + whitespace, отбрасывает пустые/None addresses.avg_lots_per_addr = n_analogs / max(unique_addr_count, 1)— нет division by zero.unique≥7 ∧ iqr<15%, medium=unique≥4 ∨ (unique≥2 ∧ iqr<25%), low — иначе. Downgrade приavg_lots_per_addr > 2.5маппитсяhigh→medium,medium→low, low не трогается.listings=None/[]fallback (unique_addr_count = n_analogs, avg=1.0) сохраняет обратную совместимость для любых не-estimate_qualitycallers.median_ppm2==0shortcut в начале функции остаётся — пустойlistings_cleanотрабатывает прежним путём, не доходя до новой логики.n=10, 1 уникальный адрес→ base=low, downgrade не применяется (уже low) — correct.n=12, 3 адреса по 4 лота, iqr<25%→ base=medium → downgrade=low — correct.n=14, 7 адресов по 2, iqr<15%→ base=high, avg=2.0≤2.5 → high — correct.Cross-PR compatibility
_compute_confidence(...)(строки 565-568 base) — будет реальный merge conflict, автор это явно оговорил в body (own-branch rebase). Функционально совместимы: tier_note из #507 присоединяется поверх explanation из #513 (explanation + tier_note + repair_note).Performance
listings_clean(≤50 cap из_fetch_analogs). Negligible.Security
Tests
_compute_confidenceне добавлены. В baseline их тоже не было, поэтому это not a regression. Roadmap acceptance (для тестовых estimate'ов с 1-2 уникальными адресами но n=10 — confidence снижается до medium/low) можно покрыть в follow-up — функция pure, легко тестируется.probe-confidence-distribution.py— ops tool, не unit test.quantiles(n=4)[2]==p75корректно. Redundant inlinep75_idxcalc — minor.Conventions
text()+ named params — OK.Nitpick (Low — не блокирует)
n_analogs=1: новый текст"Найдено 1 аналогов из 1 разных адресов"— грамматически некорректно (раньше было"Только 1 аналог"с правильным согласованием). Стоит вернуть склонение либо использовать форму с числительным:f"Найдено {n_analogs} {_plural_analogs(n_analogs)} из {unique_addr_count} {_plural_addr(unique_addr_count)}".Positive
listings: ... | None = Nonedefault.Verdict
Logic корректна, edge cases закрыты, backward-compatible, roadmap-aligned. Грамматическая мелочь не блокирует. Approving and merging.