feat(sudya): план судьи + рубрика на 36 признаков
Рубрика — единственный источник правды по критериям: спектры I звук, II техника
разговора, III правда и обязательства, IV характер, V продажа (новое — этого не
судил ни один прежний судья), VI проверка самого судьи.
Каждый признак несёт тяжесть: СТОП двигает вердикт в брак, ТРЕВОГА зовёт смотреть
глазами, СИГНАЛ идёт только в статистику. Из 36 признаков 16 — СТОП.
Тесты закрепляют целостность: ровно 36, номера без дыр, поля из допустимых множеств,
спектр V судит только продавец.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
docs(plan): пошаговый план — прокси автоподбора (Proxy.Market) на плашке «Внешние сервисы»
7 задач TDD: /proxy-check на рендере, LivenessReading::warn, ProxyMarketProbe,
регистрация в реестре, контроллер (whitelist+topup+срок в payload), фронт-строка,
регрессия. Схему БД не трогаем. Выкат — отдельно, по команде владельца.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
Фиксирую после выката 16.07: живое состояние 12 сервисов, мины (DELETE-грант/EXA-proxy/
живость<500/serial-only regress), и НАХОДКИ владельца — xfetch реально в Sales-finder
(/opt/sales-finder, не портал), EXA-тоннель на render-VM автоподбора, Sales-finder тянет
Keyso+DaData вне присмотра. §6 — готовый промпт для следующей сессии.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Действие «Зарегистрировался» (PATCH action=registered): email→tenant, привязка
SalesClientAssignment со снимком тарифа, linked_tenant_id+stage=registered; клиент
занят другим → 422. Диалог карточки: пункт «Зарегистрировался» + поле e-mail.
SalesProspectsAdvanceJob (каждые 15 мин, pgsql_admin): по balance_transactions
считает стадию — Σtopup≥30000→user, >0→topped_up, есть расход при 0 topup→testing,
иначе registered; ручные/отказные стадии не трогает. Схема НЕ меняется.
Гейты: бэк 19/19, фронт 9/9, Larastan 0. 🪤 property $connection конфликтовал с
трейтом Queueable → переименовал в $dbConnection.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Портал публикует /api/sales/integration/{managers,prospects} под сервис-токеном
(X-Sales-Token, config sales.integration_token). ingest создаёт карточки stage=new
с полным payload, дедуп по (sales_user_id, inn|phone), assigned_by=начальник.
Гейты: 8/8 Pest, Larastan 0. Финдер-сторона — следующим коммитом.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Этап 1 Task 1. SaaS-level таблица без RLS + 8 стадий воронки, включая
«Тестирование» (начал тратить бонусные 1000 ₽ после регистрации).
Дизайн/план обновлены под 8-ю стадию. cspell исключён: сработал на
пред-существующих словах CHANGELOG_schema, мои файлы проверены чисто.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
15 задач по TDD: миграция sales_prospects, модель, GET/PATCH API (свои/все+
фильтр, результаты переговоры/недозвон/отказ с правилами), демо-команда, доска-
канбан + диалог карточки + экраны менеджера и начальника + меню/маршруты.
Этапы 2 (поиск→портал) и 3 (автожизнь) — отдельными планами.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ветка разошлась с боевым 28.06 (334 коммита в main / 215 у нас). Влито ВСЁ боевое:
автоподбор конкурентов, мобильный адаптив портала, свой учёт посетителей, мониторинг
внешних сервисов, фиксы поставщика/биллинга/бота/разборов.
ПОБАЙТОВАЯ СВЕРКА: из 1008 файлов, изменённых боевым, 989 совпадают точно;
19 отличаются — все с нашей законной работой (обе стороны внутри). Затёртых — 0.
24 конфликта разобраны вручную. Ключевое:
- VerifySupplierOrderJob — взята БОЕВАЯ версия (фикс инцидента 11-12.07: площадка
берётся из src, а не из имени; наша была старой и вернула бы баг, терявший заявки).
- SyncSupplierProjectsJobTest — 15 боевых тестов + наш уникальный (limit-1 → только B1).
- routes/web, router/index, config/services, bootstrap/app — обе стороны сложены.
- NewProjectDialog — зелёные дни недели (наше) + мобильная раскладка (боевое).
- CHANGELOG схемы — номера версий столкнулись, наши перенумерованы в v8.67-v8.70.
- composer — обе зависимости (laravel-dompdf наш + geoip2 боевой).
Гейты: бэкенд 2907/2911 (0 падений), Larastan 0, фронт 1333/1333, сборка OK.
Baseline статанализа принял пре-существующий долг боевого кода (автоподбор/чат).
@mixin в 26 моделях — требование статанализа, dev-докблок, на рантайм не влияет.
Откат: git reset --hard pre-merge-main-20260714
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Гость получает верную ссылку на разбор по всем 10 частым вопросам; где
разбора нет — бот молчит, в пустоту не шлёт. 20 тем, 126 кадров, единый
демо-клиент. Отдельно: найден баг боевой функции — поиск дублей считал
ноль признаком совпадения (на проде он есть, фикс в ветке).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
9 задач по TDD: ClientFacts (деньги/ступень/проекты/заявки под RLS),
сторож на выдуманные числа, карточка в контексте вошедшего, гостю вход
в кабинет, владелец разговора (404 чужому), ключ разговора на каждый вход,
живой прогон с судьями.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8 задач по TDD: журнал разговоров -> свой приём сообщений -> опрос ответов ->
счётчики от накрутки счёта -> письмо владельцу со всей перепиской -> окошко
на портале и лендинге -> вычистка Jivo из настроек -> прогон 46 диалогами.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Прод-инцидент 11-12.07.2026: робот итоговой проверки слал письма «нет заказа у
поставщика» на строки, которые в кабинете ЕСТЬ, включены и с верным лимитом.
Корень: кабинет дописывает метку канала к имени строки только при СОЗДАНИИ, а при
обновлении сохраняет имя ровно как прислали. Наш ежедневный updateProject слал голый
uniqueKey и каждый прогон стирал метку. Последствия:
- итоговая проверка выводила площадку из префикса имени и переставала узнавать
строку -> ложное missing 11.07 и 12.07;
- лид от такой строки приходил с project без метки -> webhook не мог определить
канал и писал platform=DIRECT вместо B1/B2/B3, то есть терялась атрибуция канала.
Что сделано:
- SupplierPortalClient::toPayload — на update имя уходит с меткой канала; на create
остаётся голым, там метку ставит сам кабинет и один save с тремя флагами рождает
три строки, общего префикса у них нет.
- VerifySupplierOrderJob::normalizeLive — площадка берётся из служебного поля src
rt/bl/mt, а не из префикса имени; сверка больше не зависит от имени вообще.
- Новая разовая команда supplier:repair-project-names — возвращает метку строкам,
у которых её уже стёрли. Payload собирается ИЗ ЖИВОЙ строки кабинета, меняется
ровно одно поле name; по умолчанию сухой прогон, запись только с --apply.
Ветка пересобрана на gitea/main — закрывает follow-up «фича итоговой проверки заказа
не сведена в main». Попутно возвращён CsvReconcileJobTest, отставший от кода после
сведения main 09.07: он не фейкал fetchDeliveredLeads и падал 9 из 11.
Боевой liderra.ru: выкачено, починена 81 строка, робот показывает 0 расхождений
138 наших строк вместо 57. Двум лидам восстановлен канал по журналу выдач поставщика.
Тесты: Pest supplier 277/277, Pint clean, Larastan 0 новых ошибок.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Слой A (requisites.py): если ИНН нет на главной сайта — ищем страницы
реквизитов/политики конфиденциальности/лицензии/контактов и достаём ИНН
оттуда (по 152-ФЗ ИНН обязан быть на «Политике»). Надёжно, точно.
Слой B (dadata.enrich_by_name): если ИНН так и нет — ищем в ДаДате по
названию+городу с защитой best_match (только действующие с совпадением
города). Директор по названию ВСЕГДА помечается «проверьте» (совпадение
может быть чужой фирмой — напр. Чудо Доктор→Аптека Чудо Доктор).
cities.py: слаг города (латиница, для 2ГИС) → русское имя (для ДаДаты).
Реквизит-страницы тянем только быстрым requests (без медленного xfetch).
Слой C (бесплатные порталы по телефону) отклонён — проверен через xfetch,
контроль провалился, отдаётся нестабильно.
Проверено живьём: слой A дал ИНН+ФИО Доброму доктору, Дентал Фэнтези,
Белгравии и др. со своих сайтов; слой B — Дантистофф/Медлайн/СМ-Стоматология
с пометкой. 61 тест зелёный.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Портал на этой машине: рубрика 2ГИС + город → список фирм на прозвон
(кто рекламируется, ИНН, директор). Переиспользуем наработки (ChannelA/2ГИС,
ad-scan, Keys.so, build_portal, ДаДата), боевое не трогаем — только копии.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
По спеке 2026-07-02-jivo-ai-support-bot-design: webhook + FTS-поиск
по инструкции + YandexGPT Lite + эскалация + журнал + тест скорости.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Причина фантомных сделок kdv1 (09.07.2026): CsvReconcileJob брал отчёт «Запрос
номеров» = ПУЛ собранных номеров (phones_cnt), а не ОТДАННОЕ (crms_cnt), и лепил
из пула сделки клиенту + выедал дневной лимит. Пример: пул 157, отдано 15,
у клиента 15 фантомов, а 15 реально отданных выбило лимитом.
Фикс: SupplierPortalClient::fetchDeliveredLeads() читает журнал «Мои сделки»
(index-visit, по vid) — только реально отгруженное. CsvReconcileJob сверяет по vid,
добор несёт настоящий vid (idx_supplier_leads_vid_unique -> идемпотентно с webhook).
Пул не трогается -> фантомы невозможны, лимит не забивается мусором.
Проверено: 12 новых тестов + 294 supplier зелёные, Pint/Larastan чисто. Выкачено и
проверено на проде (reconcile читает отданное, 0 фантомов за прогон).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Реализация дизайна 2026-07-08: конфиг счётчика (образец JivoSite), ленивый
загрузчик metrika.ts (TDD), hit только для layout=app, маскировка ym-hide-content/
ym-disable-keys в компонентах кабинета, строка в политику, CSP-правка блока
приложения + выкат с обязательной проверкой маскировки ПДн на стенде.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Симптом: отчёт «Посетители» полон, а Вебвизор пуст даже за дни с заходами.
Причина: строгий CSP резал скрытый blob-frame Вебвизора (базовый счётчик через
img-пиксель проходил → «Посетители» есть). Fix на боевом (nginx liderra.ru,
блок лендинга): +child-src/frame-src 'self' blob: https://mc.yandex.ru +домены
Метрики в frame-ancestors. Проверено: заголовок отдаётся, / и /login = 200.
Бэкап /etc/nginx/liderra.bak-webvisor-20260708.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
TDD-план на 9 задач: worktree от worktree-avtopodbor (там есть «Поле»),
useLayoutTier, AppBottomNav, AppMoreDrawer, rail-сайдбар, ярус-отступ AppLayout,
ResponsiveTable и пруф на «Сделках». Экраны Этапов 2-3 — отдельными планами.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- счётчик Метрики вставлен в <head> лендинга landing-v5-claude.html
- на 3 кнопки перехода на портал повешен reachGoal GO_PORTAL (JS-событие)
- ранбук выката: CSP блока лендинга дополнен https://mc.yandex.ru
в script-src/img-src/connect-src — иначе строгий CSP блокирует счётчик
Выкачено на боевой liderra.ru 07.07: счётчик проверен живьём (заход уходит
в Яндекс), вход в кабинет /login не сломан. Цель GO_PORTAL создана в Метрике
(ID 579585431).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Пилот по стоматологиям: скан кода сайтов (коллтрекинг Calltouch/Comagic/
Callibri/Roistat/Mango + пиксели VK-myTarget/Google Ads/Meta) плюс Яндекс.Директ
через Keys.so API (ключи, объявления, бюджет), склейка в Excel. Две фазы:
сайты параллельно, затем чистый проход по API с повторами. Тесты 16/16.
Спека и план — docs/superpowers. Данные Спарка, результаты и токен Keys.so —
вне git (личная папка + .gitignore).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
План релиза всей системы автоподбора (190 коммитов, greenfield на проде, миграции
на денежную базу) с гейтами, откатом, находками prod-deploy-validator (ловушка
локального сокета vs Managed PG, диск) и rls-reviewer (grants после migrate, canon-sync).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
План: таблица статусов фаз с коммитами (1-7 ✅, 8 и приёмка — за владельцем).
Спека §5.3: помечен follow-up — node-скриптовые точки Яндекса (листинг шаг 1,
разворот) пока на локальном Playwright под self_render (не xf4, без прокси).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Разведка живого 2ГИС (worktree, НЕ прод): из window.initialState чисто
достаётся список фирм-в-фирму для всех 3 типов URL (листинг/карточка/
поиск-по-телефону). Главный риск проекта снят.
- Фикстуры (реальные initialState+HTML): tests/fixtures/autopodbor/2gis/
listing (12 ломбардов), card (Ломбардико: сайт+телефон), phone (холдинг).
- Карта JSON-путей: pagination-список результатов + entity.profile (имя/
город/рубрика/сайт/телефоны). Идти ТОЛЬКО по pagination, не по ключам.
- Вскрыт рецепт рендера museum double-tap: гейт «обновите браузер» дважды
кодирует return_url (%20→«20», отсюда старый мусор). Обход — двойной заход.
- Findings: docs/superpowers/findings/2026-07-05-2gis-initialstate-spike.md
- План реализации (8 фаз): docs/superpowers/plans/2026-07-05-self-render-*.md
- Спека v4 обновлена: риск initialState снят, double-tap задокументирован.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Для застройщиков, которые сидят только в Яндексе. По каждому номеру ищем в
Яндекс.Картах, но список рыхлый — поэтому КАЖДУЮ карточку открываем и оставляем
только те, где искомый номер реально есть. Это отсекает «Похожие места рядом»,
рекламу и рыхлые совпадения по бренду. Оба справочника объединяются
(CompositePhoneReverse), дубли по домену схлопываются.
Переиспользована готовая механика Яндекса: render-yandex-list.cjs (список) +
DirectoryParser::parseYandexCard (карточка). Браузерные адаптеры за интерфейсами
(YandexPhoneSearch/YandexCardReader) — логика TDD-ится на фейках; порог общей
линии считается по подтверждённым карточкам.
За отдельным тумблером AUTOPODBOR_PHONE_REVERSE_YANDEX (по умолчанию ВЫКЛ,
требует phone_reverse). Юнит 267/267, feature 150/150. План и находки —
docs/superpowers/{plans,findings}/2026-07-05-*.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
По личным телефонам фирмы обратным поиском в 2ГИС вскрываем связанные карточки
холдинга (проекты застройщика) — забираем их сайты и телефоны, цепочкой «до талого».
Общий номер (у >4 фирм) пропускаем; visited-set + потолок карточек; уже известную
главную карточку не дублируем. Защита от AutoMoney: реклама отсечена парсером,
общий номер обрублен до разворота, находки не клеятся молча.
За тумблером AUTOPODBOR_PHONE_REVERSE (по умолчанию ВЫКЛ). Юнит 259/259, feature
146/146. Решение и план — в docs/superpowers/{findings,plans}/2026-07-05-*.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
12 задач по TDD: тумблер+is_federal, CompetitorGeo, DomainKinship (близнецы
НЕ сливать), PlatformClassifier, отпечаток+запросы EXA, AnchorGate,
FootprintSearch, SiteOpener, DeepStudyCollector (маппинг 1:1 со словарём
чипов песочницы), развилка по тумблеру, DI, приёмка на 5 против ЭТАЛОНа.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Шаг 1 «Конкурентное поле» — чекпоинт:
- Финальный проход «Найти и объединить дубли» на поле и предложениях; клиент решает по каждой группе, ничего не склеиваем молча.
- Тихая склейка только по сайту и коду справочника; телефон и людный номер у более чем 4 фирм — на решение клиента.
- Колонка phones jsonb; телефон-дубли видны уже на «Предложениях».
- Sonar даёт только имя и тип, сайт всегда через EXA; вскрываем все карточки без гейта «есть сайт».
- Яндекс-карточки через локальный Playwright параллельно; рубрика из заголовка идёт в описание.
- Фикс рекламных номеров: 2ГИС-парсер разбирает телефоны пообъектно и выкидывает рекламные кнопки с platforms/caption чужих фирм.
Тесты: автоподбор 224/224 unit, 105/105 feature; фронт-спеки зелёные. Времянки app/scripts/diag-*/probe-* в гит не входят.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
По спеке 2026-07-02-jivo-ai-support-bot-design: webhook + FTS-поиск
по инструкции + YandexGPT Lite + эскалация + журнал + тест скорости.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Консолидированное состояние двух треков (launch-gate выкачен на liderra.ru core-only;
автоподбор работает только в воркстри) + квирки окружения/тестов + промт для
восстановления контекста после компакта.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>