Витрина лендинга: пустой пересчёт больше не считается успешным, а итог игры «Проверьте себя» говорит, что квартиры отобраны #3550
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
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#3550
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/landing-showcase-and-game"
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?
Две правки в витрине публичного лендинга МЕРЫ, по коммиту на issue.
#3511: пустой прогон витрины сделок больше не считается успешным
Что было.
_job_landing_showcase_deals(app/services/product_handlers.py) всегда ставил прогонуdone. У счётчиков витрины (considered/eligible/written) нет ни одного ключа из_RESULT_COUNTER_KEYSкита, поэтомуrun_brought_dataвозвращаетstatus == "done", то есть судит только по статусу. Прогон сwritten = 0(задача уже сделалаDELETE+ пустойINSERTи закоммитила) сбрасывал часы свежести так же, как удачный. Блок на странице пропадал, а сводка просроченных молчала.Почему это важно сейчас. С #3469 задача стоит в суточном расписании: прод 17.09,
next_run_at2026-09-18 06:22 UTC. Последние 5 прогонов (13–17.09) всеdone,written = 20,eligible158–160. Пока всё в порядке, но любая правка оценщика, которая сдвинет расхождения за полосу, опустошит витрину без тревоги.Что сделано. Если
writtenравен 0, прогон помечаетсяmark_failedс причиной «витрина пуста: прогон не записал ни одной строки (written=0)». В лог пишетсяlogger.errorсconsidered/eligible. Непустой прогон, как и раньше, завершаетсяmark_done.Тест по значению (
tests/test_3469_showcase_schedule.py). Проверка идёт тем же путём, что и сводка: обработчик ставит статус, затемfreshness_rowsиstale_sources.ctx.runsздесь не мок с проверкой вызова: он записывает финал прогона строкой_STALE_SOURCES_SQL.landing_showcase_dealsв списке просроченных;Чего здесь нет. Витрина по-прежнему пустеет, и на странице вместе с таблицей пропадает дата пересчёта. В issue вариант «показывать прежний набор» назван решением продукта, в приёмку он не входит. После правки пустоту заметит сводка через 3 такта от последнего непустого прогона.
#2903: итог игры «Проверьте себя» говорит, что квартиры отобраны
Что было. Всё, что просили в issue, уже сделано раньше (#3229,
b72dbc5d): раунды из реальных ДКП, прогноз через спайн бэктеста, заранее посчитанный набор вlanding_showcase_deals, без адреса. Но с24679432(12.09) витрина, а значит и раунды игры (pickVariedDeals(showcase.deals)), содержит только сделки с расхождением от −5 до +20 %. На проде 17.09err_pctу 20 строк лежит от −4,55 до 17,93, медиана |err| 6,5 %. Лента и таблица «Точность» полосу называют. Игра не называла: итоговая плитка «ошибка МЕРЫ на этих же квартирах» выходила без оговорки и читалась как точность расчёта.Что сделано.
GuessGameV3получил обязательный пропbandSelected. Под плитками итога теперь две фразы. Первая, только еслиbandSelected: «Квартиры для игры взяты из отобранной полосы, где МЕРА разошлась с ценой ДКП от −5 % до +20 %: это не вся сверка». Вторая, всегда: «Медиана расхождения МЕРЫ по всей сверке — X (N сделок)».BAND_MIN_PCT/BAND_MAX_PCT, медиана — изBACKTEST.priceError(landing-facts), как в подписи таблицы. Гейт чисел зелёный.page.tsxпередаётbandSelected={allWithinBand(deals)}. Та же самопроверка стоит у ленты и таблицы: если на странице лежат строки старого прогона (вне полосы), про полосу ничего не утверждается..gameFinalNote(composesaccFootnote).Тест по значению (
__tests__/landing-v3-render.test.tsx). Игра проходится кликами до итога.bandSelected→ в итоге есть «отобранной полосы … от -5 % до +20 % … не вся сверка», медиана и размер выборки изBACKTEST.priceError;bandSelected={false}→ про полосу ни слова, медиана сверки на месте.Прогоны
DATABASE_URL=… uv run python -m pytest tests/ -q -p no:cacheprovider→ 6227 passed, 42 skipped, rc=0 (после rebase на origin/main 34642e1d; новых коммитов в main не было)tests/test_3469_showcase_schedule.py→ 12 passed, 1 skipped (живой Postgres-тест само-скипается без базы), rc=0uv run ruff check app tests→ All checks passed, rc=0;ruff format --checkна изменённых файлах → already formattednpx tsc --noEmitrc=0;npx vitest run→ 32 files, 297 passed, rc=0;eslintпо изменённым файлам rc=0;npm run check:mera-public-isolationrc=0Фальсификация
Исходник копировался в scratchpad, правился руками, после прогона восстанавливался,
diff -qчистый.#3511, условие
if not counters.get("written")заменено наif False(старое поведение, всегдаmark_done):#2903, (а) фраза про полосу выключена (
false ? …):(б) самопроверка выключена (
true ? …):Деплой
Пересоздаются
tradein-backend/tradein-scraper(обработчик) иtradein-frontend. Миграций нет. Перед деплоем проверитьSELECT source FROM scrape_runs WHERE status='running': 17.09 в 07:2x UTC там шлиdomclick_city_sweep_moskva,avito_city_sweep,avito_city_sweep_verkhnyaya_pyshma.Приёмка на проде (после деплоя)
docker exec tradein-scraper grep -n "written=0" /app/app/services/product_handlers.pyнаходит новую ветку. Прогон 18.09 около 06:22 UTC с непустой витриной →scrape_runs.status='done',written=20. Пустой прогон, если случится →status='failed',errorначинается с «витрина пуста», а сводка назовёт источник через 3 суток от последнего непустого. Проверить до 19.09.Closes #3511
Closes #2903
🤖 Generated with Claude Code