fix(mera-public): подписи метрик снижения цены и бенчмарк отчёта не называют площадку
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 11s
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 Trade-In / frontend-checks (pull_request) Successful in 1m12s
CI Trade-In / backend-tests (pull_request) Successful in 5m5s

Замечание юриста (Сайт_МЕРА_v2, п.3): публичный измеримый контент не должен
строиться на названных данных площадок.

- landing_stats.py: note метрик price_cut_share_pct / price_cut_median_pct_per_month
  «Только Домклик (…)» → «Только одна из площадок (…)». Текст персистится в
  landing_stats.note и рендерится на лендинге в блоке «цена ошибки» — после
  деплоя нужен пересчёт (refresh_landing_stats), деплой кода note не перепишет.
- HeroSummary.tsx / IMVBenchmark.tsx: убраны видимые «IMV» и title
  «Information Market Value» / «Индекс Market Value» — бренд-термин оценочной
  модели площадки; подпись — «оценочная модель» + sourcePublicLabel.
- public-copy-no-platform-names.test.ts: «IMV», «Information Market Value»
  добавлены в BANNED (гейт 34/34).
This commit is contained in:
bot-backend 2026-09-04 11:27:32 +03:00
parent 9cb5bf3fa3
commit 76b24e9f4d
4 changed files with 14 additions and 7 deletions

View file

@ -305,9 +305,12 @@ def collect_landing_metrics(db: Session) -> list[dict[str, Any]]:
).first()
if row is not None and row.n:
n = int(row.n)
# Публичная подпись метрики: площадка не называется (норма publicLabel,
# решение 31.08.2026); фактически это Домклик — единственный источник,
# где триггер пишет стартовую цену. Текст персистится в landing_stats.note.
base_note = (
f"Только Домклик (единственный источник, где триггер пишет стартовую цену), "
f"наблюдение от {_PRICE_SPAN_DAYS} дней, изменения свыше "
"Только одна из площадок (единственный источник, где фиксируется "
f"стартовая цена), наблюдение от {_PRICE_SPAN_DAYS} дней, изменения свыше "
f"{_PRICE_MAX_ABS_PCT}% отброшены как смена объекта"
)
metrics.append(

View file

@ -88,6 +88,10 @@ const BANNED = [
"Avito Оценка",
"Я.Оценка",
"Циан Оценка",
// Бренд-термины оценочной модели Avito: «IMV» / «Information Market Value».
// Идентификаторы (IMVBenchmark, imvPrice) границей слова не задеваются.
"IMV",
"Information Market Value",
];
/**

View file

@ -529,13 +529,13 @@ export function HeroSummary({ estimate, input, onResubmit, isResubmitting = fals
)}
</div>
{/* Компактный ряд бенчмарков: Avito IMV · Cian · ДКП
{/* Компактный ряд бенчмарков: оценочные модели площадок (avito_imv, cian_valuation) · ДКП
Вторичный контекст-якорь под hero, не конкурирует по размеру. */}
{!insufficientData && (imvPrice !== null || estimate.cian_valuation?.sale_price_rub != null || showDkp) && (
<div className="hero-benchmarks">
{imvPrice !== null && (
<div className="bench-chip">
<span className="bench-chip__src">{sourcePublicLabel("avito_imv")} <abbr title={`Information Market Value — независимая оценка рыночной стоимости (${sourcePublicLabel("avito_imv")})`}>IMV</abbr></span>
<span className="bench-chip__src" title="Оценочная модель площадки — независимая оценка рыночной стоимости">{sourcePublicLabel("avito_imv")}</span>
<span className="bench-chip__val mono">{formatMln(imvPrice)} </span>
</div>
)}
@ -595,10 +595,10 @@ export function HeroSummary({ estimate, input, onResubmit, isResubmitting = fals
{imvPrice !== null && (
<div
className="price-figure-imv mono"
title={`Индекс Market Value (${sourcePublicLabel("avito_imv")}) по этому дому — реальный рыночный якорь`}
title={`Оценочная модель площадки (${sourcePublicLabel("avito_imv")}) по этому дому — реальный рыночный якорь`}
style={{ marginTop: 6, fontSize: 12, color: "var(--muted)" }}
>
{sourcePublicLabel("avito_imv")} <abbr title={`Information Market Value — независимая оценка рыночной стоимости (${sourcePublicLabel("avito_imv")})`}>IMV</abbr>: {formatMln(imvPrice)}
{sourcePublicLabel("avito_imv")}, оценочная модель: {formatMln(imvPrice)}
</div>
)}
</div>

View file

@ -51,7 +51,7 @@ export function IMVBenchmark({ benchmark, isLoading }: Props) {
return (
<section className="imv-benchmark" aria-label={`Оценка ${SRC_LABEL}`}>
<header className="imv-benchmark__head">
<span className="imv-benchmark__title">{SRC_LABEL} <abbr title={`Information Market Value — независимая оценка рыночной стоимости (${SRC_LABEL})`}>IMV</abbr></span>
<span className="imv-benchmark__title" title="Оценочная модель площадки — независимая оценка рыночной стоимости">{SRC_LABEL} · оценочная модель</span>
</header>
<div className="imv-benchmark__row">
<div className="imv-benchmark__metric">