Каждый из 3 рекламных каналов (Яндекс/ВК/Телеграм) получает свои 11 сроков + days;
движок считает решение по каждому каналу отдельно (decideForPlatform, чистая функция);
сроки переезжают на sales_ad_audience_platforms; recalc сводит на фирму для backward-compat
читателей (СМС/карточки); sync-джобы включают номера по срокам своей площадки; заодно
чинится рассинхрон ВК-джоба (читал singleton вместо строки площадки). Состав/СМС/заезд
из поиска — Фаза 2.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Task 1 плана «кусок B». firmRow() в SalesAdAudienceController (firms()/allFirms())
теперь отдаёт rubric, warmup_started_at (ISO8601), manager_id/manager_name (через
prospect.sales_user_id) и агрегаты warming_active/warming_channels (yandex/vk/mts/sms).
Заглушка smsWarmedFirmIds() — Task 3 наполнит связью с СМС-рассылкой.
Тест AdAudienceWarmingFieldsTest — TDD (failing → green), плюс regression-прогон
72 тестов AdAudience* и composer stan (0 ошибок, phpstan-baseline.neon дополнен
записью под Pest actingAs() в новом тестовом файле — по конвенции остальных тестов).
10 задач по TDD: бэкенд (firmRow +ниша/дата/менеджер/состояние/каналы, маршрут
назначения для СМС, sms-канал, блок warming в проспектах), фронт (composable
useWarmingFirms + 4 ячейки, v-data-table на 4 экранах, фильтры, select-all,
карточки воронки), полный регресс.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Портальная часть (пункты 1,2,3,5,6,7): общий движок таблицы на v-data-table,
ниша+дата колонки и фильтры, Отметить все+счётчик, показ менеджера +
назначение на СМС, пагинация 10/25/50/100, пометки греётся/прогрет + значки
каналов на карточках. Пункт 4 (поиск клиентов) — следующим заходом.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
9 задач через TDD: миграция таблицы настроек площадок + бэкфилл из state,
модель SalesAdAudiencePlatform, джоб Яндекса на строку площадки,
контроллер по {platform}, маршруты /warming/{platform}, фронт (API +
общая обёртка трёх страниц + меню), уборка старого экрана + схема v8.81,
регресс «поведение не изменилось» + предполёт.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Кусок A (к реализации): фундамент «фирма на площадке», таблица настроек
по площадкам (свой рубильник/пороги/синхронизация), три пункта меню
Яндекс/ВК/Телеграм; поведение прогрева не меняется, 177 номеров → «Яндекс».
Куски B (витрина: значки на карточках, колонки «Греются/Прогреты», история
эпизодов, СМС) и C (раздельные сроки) — дорожная карта. Плюс справочник 11 сроков.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Начальник отдела продаж отмечает фирмы прогрева галочками, пишет текст,
видит цену ДО отправки и журнал после. Отправки СМС в проекте не было
вообще — ни у СМС-центра (только баланс и HLR), ни у МТС (только файл).
Что сделано:
- разъём провайдера SmsProvider: новый оператор подключается одним файлом
- заглушка FakeSmsProvider — модуль работает и проверяется ДО согласования
имени отправителя у операторов (это недели), иначе разработку не закончить
- маршрутизация по оператору: билайновский номер уходит через Билайн за
4,75 ₽, прочие через МТС — без ручного выбора канала
- стоп-лист: кто отписался, тому не шлём никогда, проверка перед списанием
- отбор получателей с шестью причинами пропуска, все ДО траты денег
- списание скопировано с AutopodborChargeService; пока клиента нет
(tenant_id пуст) с баланса не берём — платим оператору напрямую
- оператор номера доезжает из «Поиска клиентов» в прогрев (был известен
и оплачен ДаДате, но терялся при передаче)
Мультиклиентность в костях: колонка tenant_id во всех четырёх таблицах
СМС с первого дня, NULL = «Лидерра сама». Клиент добавляется строкой,
а не переделкой модуля.
Найдено и закрыто при исполнении:
- замок от двойного списания стоял не на том соединении: кампания на
pgsql_supplier, деньги на pgsql, lockForUpdate по кампании отпускался
сразу. На бою два запуска списали бы дважды, обрыв — оставил бы пометку
«оплачено» при неушедших деньгах. Источник правды перенесён в
balance_transactions под замок по тенанту. Доказано тестом: старый код
списывал 700 вместо 850
- приём в портал требовал phones строкой по regex — словарь с оператором
получал 422, в базу не доезжало ничего. Тесты были зелёные, потому что
звали сервис МИМО контроллера. Проверка теперь принимает оба формата,
тест идёт через HTTP
- телефоны директоров в contacts остаются строками (договор
SalesProspectController), словари — только в верхнем phones
Заодно вылечена мигающая поломка 48 тестов доставки лидов: помощник
createRoutingSnapshotFromProject клал снимок на сегодня, а LeadRouter
после 21:00 МСК ищет завтрашний (вечерний переворот заливки) — вечерние
прогоны падали, дневные проходили. Помощник теперь зеркалит активную дату
роутера в любой час. Регрессия SnapshotHelperTimeOfDayTest замораживает
22:00 МСК и пинит инвариант. Боевой LeadRouter не тронут.
Тесты: 84 бэкенд + фронт по экрану + 397 поисковика, весь набор 3226
зелёный, статанализ чист. Все защиты проверены вырезанием.
План: docs/superpowers/plans/2026-07-20-sms-progrev-modul.md
Спека: docs/superpowers/specs/2026-07-20-sms-progrev-modul-design.md
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
docs(александра): передача по стройке — лёгкий оператор и точило
Приняли архитектуру по замыслу владельца: наставник не даёт подсказку
на каждый ход, а точит промпт оператора в фоне. Замер: лёгкий промпт
2.60с против 3.14с, наставник успевает лишь в 35% ходов — итого 0.77с.
Точило ВЫБИРАЕТ блоки из 13, а не пишет текст: промпт собирается кодом,
поэтому дрейфа нет. Опасные темы выбираются кодом мгновенно, оттенки —
моделью в фоне, её не ждём никогда.
В файле: где что лежит, замки лаборатории, эталон боевого с возвратом,
состав 13 блоков и утверждённый ответ про источник заявок, пять
провалившихся попыток ускорения с числами, карта задержек, ловушки
и открытые вопросы за владельцем.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
Путь человека рвался пополам: лендинг и кабинет считали разные счётчики,
а вход и регистрация не писались вообще. Почему люди бросают регистрацию,
узнать было нельзя.
Счётчик лендинга 110476275 становится счётчиком полного пути и грузится
на всех страницах кабинета. Прежний счётчик кабинета 110494416 не тронут,
его история цела, на страницах кабинета работают оба.
Что сделано:
- загрузчик Метрики поднимает счётчики по области: public или app
- белый список раскладок: новая раскладка Метрику НЕ получает по умолчанию
- формы входа и регистрации закрыты от записи классом ym-hide-content
- метка utm не теряется при заходе сразу в кабинет минуя лендинг
Найдено при исполнении и закрыто:
- почта выводится в заголовке ДВУХ экранов, то есть вне формы: класс на форме
её не накрывал, утекла бы в записи открытым текстом. Замаскирована точечно
- Метрика, единожды запустившись, пишет дальше сама и роутером не выключается.
Админ входит через общий /login и идёт в админку к чужим телефонам.
Корни админки и портала продаж закрыты ym-hide-content
- ключ metrika в config/services.php был объявлен ДВАЖДЫ: раздвоил его мой
же merge 42e907c8 от 14.07. PHP молча берёт последний, правка первого блока
не дала бы ничего и не выругалась. Дубль вычищен, прочие конфиги проверены
В кабинете Метрики включена галочка «включая поддомены»: счётчик принимал
данные только с liderra.ru и молча выбрасывал бы всё из кабинета.
Заодно погашен долг по статанализу: 63 ошибки держали коммит. Все до одной
в тестах, в боевом коде ноль. Природа ложная — анализатор не понимает
устройство Pest и ругается на обычный вызов внутри теста. Их гасят списком
игнора, а список пересобирали 18.07, тогда как тесты добавлялись 19-20.07,
в том числе мои по рекламной аудитории. Список пересобран, стало 0 ошибок.
Долг накопился в том числе потому, что вчера я обошёл эту проверку.
Тесты: 27 новых, все проверены вырезанием защиты. Полный набор 202 файла зелёный.
План: docs/superpowers/plans/2026-07-20-skvoznoy-put-do-vebvizora.md
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Два дня работы: звук (хрип от несовпадения A-law/µ-law, заворот высоких,
канал proxy.market) и механика разговора (сторож эха ел вопросы клиента,
глухота между её же предложениями, поток мозга по предложениям).
Ответ по существу 6.05с → 3.64с, пауз внутри реплики 2 → 0.
В файле: что читать следующей сессии, чем мерить, 8 ловушек
и незакрытый слой, который за владельцем.
Номер боевой линии не пишем — сторож ПДн прав, правило одно для всех
телефонов; номер берётся из журнала моста.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Постановка владельца 19.07.2026: на экране «Последние списки» нужен фильтр под
выбранную нишу, галочки на списках и групповые действия (удалить / собрать телефоны /
прогреть / отдать менеджеру) — все только по горячим фирмам.
Решения владельца зафиксированы: горячие = 70+, уже собранных и отданных пропускаем
и сообщаем сколько, перед платным действием и удалением спрашиваем с числом,
Телеграм и СМС — заглушки до готовности модулей.
Найдено при проектировании: прогрев берёт только фирмы с собранным мобильным, значит
порядок работы — телефоны → прогрев → менеджер; после прогрева на нашей стороне не
оставалось следа (добавляем пометку площадки); показ 1000 списков требует переноса
счётчиков в колонки, иначе главная разбирает всю базу на каждое открытие.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Одно поле channels не растягивается на третью площадку — сочетаний восемь.
Заменяем тремя галочками ch_yandex/ch_vk/ch_mts с переносом значений:
на бою 99 фирм со значением yandex, они получают ch_yandex.
Для МТС — выгрузка файлом: программного доступа к рекламе в Telegram у них
нет, их REST API умеет только SMS (проверено по документации 20.07).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Владелец сравнил новые картинки с прежними и сразу увидел: «со слитками
поярче было». Так и есть — на первых двух горячее светящееся ядро вышло
САМО СОБОЙ, и выбрал он их именно за это, а в промпте про свет не было
ни слова. Следующая пара без указания получилась матовой и тусклой.
Дописал в общую часть промпта: ценная сторона обязана быть источником
света, а не просто тёплым цветом — горячее ядро, слитки ловят свет и
сияют, контраст яркости выжимать до предела.
Замер для сверки (средняя яркость / самые яркие точки):
было матово: 33.5/166 и 43.1/192 при промахе мимо стиля
прежние одобренные: 26.7/102 и 32.4/137
Числа тут вторичны — решает глаз владельца, но замер помогает поймать
явный провал до показа.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🪤 С первой попытки модель отдала для 9:16 ШИРОКУЮ картинку, дорисовав
чёрные полосы сверху и снизу до вертикали. В Историях это читается как
брак. Лечится прямым запретом на полосы плюс требованием перестроить
сюжет по вертикали: клики сыплются сверху, золото собирается снизу.
Проверять полосы дёшево: средняя яркость верхней и нижней десятой части
кадра против центра. У letterbox верх ~0, у настоящей композиции все три
близки.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
В плане исправлена последняя проверка: она была написана так, будто
миграция уже на боевом. До выката она обязана падать «column channels
does not exist» — это правильный результат, а не поломка. Отмечены
выполненными 65 шагов.
В передачу дописано состояние ВК (кабинет, охват меньше сотни, открытый
вопрос по API) и три грабли вечера: вырезанная субагентом защита,
негодный тест на защиту, и git commit без явных путей.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Файл случайно попал в коммит 7e7c5b6f — был уже застейджен параллельной
сессией (пере-генерируется пост-коммит хуком, коммитить нельзя, см.
границы задачи). Восстанавливает содержимое к версии на aaeab9c6.
Task 6 плана 2026-07-19-vybor-ploshadki-progreva.md — начальник видит
площадку прогрева каждой фирмы (Яндекс/ВК/оба), отмечает строки галочкой
и жмёт одну из трёх кнопок массовой смены; api-слой зовёт уже готовый
POST /api/sales/ad-audience/channels.
Поле channels у фирмы с бэкфиллом «яндекс» существующим 64, фильтр состава
в яндексовой заливке, приём площадки от «Поиска клиентов», массовая смена
кнопками, колонка «Где греем», джоб заливки в ВК с тремя состояниями.
Тело обращения к API ВК вынесено за рамки плана намеренно: документация
закрыта до получения доступа, гадать нельзя. Джоб, порог 2000 и тесты
пишутся сейчас, меняться будет только тело одного метода.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Признак channels у фирмы, три кнопки и колонка «Где греем» на экране
начальника, заливка в ВК с тремя статусами (нет доступа / ждёт объёма /
работает). Порог автомата у ВК — 2000 номеров, это его же документация.
Зафиксированы находки 19.07: охват списка в ВК меньше сотни при 111
загруженных номерах, и что «111 из 111» у Яндекса — проверка формата,
а не совпадений. Открытый вопрос про перезапись списка в API ВК помечен
явно — уточняется при получении доступа.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Модуль на бою, две боевые поломки найдены и исправлены (права у ночного
пересчёта, отсутствующий confirm сегмента). Сегмент 58034825 создан порталом,
111 из 111 номеров приняты. Пошаговый план на утро + риск порога в 100 номеров.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Создание сегмента — два шага, а не один: upload_csv_file даёт статус uploaded
(черновик, в списке Аудиторий его нет и Директу он не виден), и только
segment/{id}/confirm сохраняет сегмент. Второй шаг отсутствовал — 19.07 заливка
на бою отчиталась успехом, id записался, а в Аудиториях было пусто.
content_type для телефонов строго 'crm'. Регресс-тест закрывает.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
На бою джоб бежит вне веб-запроса, то есть на дефолтной роли crm_app_user,
у которой нет прав на sales_prospects — пересчёт падал с permission denied
и не работал вообще. Планировщик теперь передаёт pgsql_supplier, как это
делает SalesProspectsAdvanceJob. Регресс-тест закрывает.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Код ушёл прошлым коммитом без своего теста — досылаю.
Проверяет, что судья вычитывает «до первого звука» и «до ответа
по существу» из журнала БОЯ, а не только со стенда.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Прежде мост считал «до первого звука» и «до ответа по существу» и печатал
их только на стенде — в бою они умирали в памяти, и судья не мог сказать,
сколько человек ждал ответа. Вид строки у стенда и боя один и тот же,
поэтому разбор общий.
188 тестов зелёные.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Утренняя чистка ПДн искала только в app/ и docs/ и пропустила моя/sales-finder —
папка скрыта от обычного поиска, номер оставался живым в трёх тестах (26 раз).
Заменён на фиктивный 79990000001, все 321 тест зелёные.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Буклет 2:3 Директ не принимает. Два формата под требования Яндекса
(квадрат 1:1 и широкий 16:9), текста на картинке нет кроме логотипа,
макет телефона и карточка с номером убраны — риск модерации по 152-ФЗ.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Номера, заведённые до v8.77, остались без firm_id. Ночной пересчёт обходит
фирмы и такой номер не видит, а заливка видела — он крутился бы вечно.
Нашёл rls-reviewer при сквозной проверке.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Task 8 плана v2 (реклама на кандидатов): начальник видит таблицу фирм на
прогреве (человеческие подписи состояний: «Реклама идёт», «Прогрет — ждёт
менеджера» и т.п.), кнопкой «Назначить менеджера» заводит карточку в воронку
через POST /api/sales/ad-audience/firms/{id}/assign, и правит 11 сроков
планировщика понятными фразами («Сколько дней греем до звонка менеджера» и
т.д.) вместо технических ключей.
Список менеджеров переиспользует существующий listSalesManagers() —
отдельного маршрута не заводили. api/sales.ts дополнен типами и функциями
для двух новых бэкенд-ручек Task 7 (firms/assign), которых там ещё не было.
Тест положен в tests/Frontend/ (а не в views/sales/__tests__/, как в плане) —
это единственный путь, который реально подключён в vitest.config.ts; мокает
модуль api/sales.ts, а не global.fetch — экран ходит через axios-обёртку.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Task 7 плана v2 (реклама на кандидатов): начальник видит список фирм
на прогреве (GET /api/sales/ad-audience/firms) и назначает менеджера
(POST .../assign) — из снимка фирмы рождается карточка «Потенциальные
клиенты» стадии new, реклама дальше следует за стадией карточки.
PATCH /api/sales/ad-audience теперь принимает все 11 сроков планировщика,
GET отдаёт их в durations.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(судья): судит только ЕЁ голос + второе ухо отделяет крепкие находки от слабых
Полное заключение 19.07 вскрыло две беды судьи. Владелец: сначала судья, потом голос.
1. СУДИЛ ЧУЖОЙ ГОЛОС. Доложил «велено „шарвутся", услышано „шорвутся"» — а
«шарвутся» сказал КЛИЕНТ. Судья сверял весь журнал целиком, обе стороны, и
писал в брак Александры чужое произношение. Лечение не выкидыванием слова:
каждое ожидаемое слово теперь помнит, КТО его должен был сказать, и находка
докладывается только по её речи. Выравнивание по-прежнему по ВСЕЙ записи —
иначе её слова начнут цепляться к клиентским; отсекаем на докладе, не на сверке.
Прибор частиц слушает звук и тем более не знает, чей голос — судит только те
слова, которые велели сказать ей.
Было 8 звуковых находок → стало 6, ушли обе клиентские.
2. НЕ ОТЛИЧАЛ «голос сказал плохо» от «ухо не расслышало» — выглядит одинаково.
Второе ухо другого устройства (модель разметки букв, уже стоит, качать нечего)
слушает ту же запись. Оба уха не расслышали — находка крепкая; второе
расслышало верно — слабая.
🔴 Первая версия СНИМАЛА слабые — и убила «затишье», которое владелец
подтвердил СВОИМ УХОМ: второе ухо расслышало это слово верно. Правило «оба
уха обязаны ошибиться» режет правду. Второе ухо — СВИДЕТЕЛЬ, а не судья:
говорит, насколько находка крепкая, а не есть ли она. Теперь понижение до
СИГНАЛА: видно в статистике, приговор не двигает, накопитель на пачке
разговоров сам отделит системное от случайного.
Итог по записи: 6 находок, 3 крепкие («первые»→«первое», «как-то» 81% и 114%),
3 слабые (в том числе подтверждённое владельцем «затишье»).
🪤 Испытания начали тянуть тяжёлые модели и вставать намертво. В conftest
общая заглушка: гигабайтным моделям в испытаниях не место, кому нужна
настоящая — подменяет явно у себя.
Тестов 173 → 183.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
Task 5 плана v2: RecalcAdAudienceJob (routes/console.php, дневное 03:10 МСК) ночью
сверяет стадию связанной карточки sales_prospects с последней запомненной у фирмы
(sales_ad_audience_firms.stage_seen/stage_changed_at) и зовёт AdAudienceScheduler,
чтобы проставить каждому номеру состояние active/paused/stopped.
Найдена и закрыта дыра в исходном плане: ни prospect->updated_at (двигается ЛЮБОЙ
правкой карточки — заметка менеджера ложно продлевала бы рекламу), ни firm->assigned_at
(момент назначения менеджера, не смены стадии) не годились источником даты «сколько
фирма сидит в текущей стадии». Решение: фирма сама хранит эту дату — миграция
2026_07_20_110000 (+2 nullable-колонки, db/CHANGELOG_schema.md v8.78). Новый тест
«правка карточки не перезапускает отсчёт рекламы» закрывает ровно эту дыру.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(судья): ловит «как-то» — частица после дефиса не бывает ударной
Владелец: на 0:35 «как-то» и «когда-то» звучат криво, лови. Следа в тексте нет
— ухо записало их верно, с дефисом. Значит дефект чисто звуковой.
🔑 ПОЧЕМУ ЭТО ИЗМЕРИМО, когда абсолютное ударение — нет. Сравниваем два слога
ОДНОГО слова, сказанных одним голосом в один момент. Не надо угадывать, какой
слог в слове ударный (две попытки провалились, потолок 53% против 51% у
болвана) — достаточно, что частица не должна быть приметнее корня. Правило
языка, не список слов: -то, -нибудь, -либо, -ка безударны в ЛЮБОМ слове.
🔴 ПОРОГ ВЗЯТ ИЗ САМОЙ РЕЧИ, а не подогнан под названные случаи. Замер по 133
словам записи: обычная безударная последняя гласная звучит примерно в 30% силы
сильнейшей гласной корня, у трёх четвертей слов — ниже 50%. Отсюда порог 50%.
Испытание запрещает менять его вне этих границ.
Живой прогон, 4 слова с частицей:
0:36 «как-то» → 81% силы корня 🔴 НАЗВАН ВЛАДЕЛЬЦЕМ
0:55 «как-то» → 114% 🔴 владелец не называл, судья нашёл сам
2:37 «смотрите-ка» → 113% 🔴 то же
0:34 «когда-то» → 35%, чисто — по замеру это норма, подгонять не стал
🪤 РАЗГАДКА ПРОВАЛА АКУСТИКИ. Замер показал: все гласные выходили ровно по
0.021 с. Модель ставит по одной вспышке на букву, а между ними молчит — если
считать буквой только вспышку, длительность перестаёт что-либо значить. Мой
вчерашний «фикс» ровно это и сделал (60% → 52%). Пустые кусочки возвращены
предыдущей букве: так из привязки и получаются протяжённости звуков.
🪤 ЛОЖНАЯ ТИШИНА, пойманная на живом прогоне: ухо режет «как-то» на «как» и
«-то», прибору доставался огрызок без корня — и он докладывал «чисто» на всех
четырёх словах. Молчание, похожее на «проверено», хуже выдумки: выдумку видно,
а это нет. Куски склеиваются обратно, огрызок без корня к суду не принимается.
Тестов 162 → 173.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
Коммит d2c2ec43 от 19.07 оторвался от main (dangling, ни в одной ветке):
чистка ПДн и YandexAudienceClient в основную ветку так и не попали.
Номера заменены на фиктивные 7999000000X, клиент и его тесты внесены заново.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(судья): ударение ловится ПО СЛЕДУ В ТЕКСТЕ — подтверждённый случай пойман
Владелец переслушал запись и назвал живой дефект: на 1:40 она говорит
«зАтишье» вместо «затИшье». Плюс сказал: не правь Александру, правь судью,
чтобы ловил.
🔑 КЛЮЧ, который дала эта правда. Ухо записало слово как «затЕшье» — не так,
как велено. Это и есть след: в русском безударная гласная РЕДУЦИРУЕТСЯ.
Ударение съехало → бывшая ударная «и» стала безударной → съехала в «е» →
распознавалка честно написала другую букву. Значит уехавшее ударение видно
В БУКВАХ, и городить акустику для него не нужно.
Прибор: согласные слова совпали, а гласная — нет. Это устройство языка,
а не список слов: проверено на «молоко/малоко», «сторона/старана»,
«телефон/тилефон» — работает на слове, которого мы в глаза не видели.
Разделение по смыслу, тоже из устройства языка: ПОСЛЕДНЯЯ гласная в русском —
это окончание (падеж, число, лицо), а ударение живёт в теле слова. Разошлась
последняя — доклад про окончание (признак 3); разошлась не последняя — про
ударение (признак 46). Иначе владелец не поймёт, что чинить.
Проверка на всей живой записи, 296 слов — 4 находки, ни одной лишней:
признак 46: «затишье» → «затешье», гласная 2-го слога ← ПОДТВЕРЖДЁН ВЛАДЕЛЬЦЕМ
признак 3: «пациенты» → «пациента», «ступеней» → «ступень»,
«проверяете» → «проверяйте»
🔴 Акустический разбор остаётся отвергнутым (две попытки, потолок 53% против
51% у тупого угадывания) — запись о нём в NENADYOZHNO уточнена: речь про метод,
а не про признак. На подтверждённом случае акустика ПРОМОЛЧАЛА, текст поймал.
Тестов 153 → 162.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
feat(судья): ударения нормальным методом — сделано, измерено, ПРОВАЛЕНО честно
Владелец: доводить ударения нормальным методом. Доведено. Не работает,
и я это показываю числами, а не прячу.
ЧТО СДЕЛАНО НОРМАЛЬНО (в отличие от первой попытки):
· привязка звука к БУКВАМ (wav2vec2 + просмотр путей CTC на numpy) —
границы гласных больше не угадываются по провалам громкости,
а вычисляются: мы знаем буквы, которые она произносила;
· высота тона автокорреляцией — третья примета, которой не было вовсе,
а в русском она выдаёт ударение сильнее прочих;
· приметность слога по трём приметам, тон считается по УХОДУ от среднего
тона этого же говорящего (у мужчин и женщин высота разная).
ЗАМЕР НА ТЕХ ЖЕ СЛОВАХ, что и первая попытка (иначе сравнивать нельзя):
первая попытка ............ 40%
вторая, как есть .......... 52%
ПОТОЛОК по всем весам ..... 53%
тупое «всегда 2-й слог» ... 51% ← вот с чем надо сравнивать
только громкость .......... 52%
только тон ................ 37%
Прибор не несёт НИЧЕГО сверх угадывания. Дело не в весах и не в ошибке кода:
сами приметы на этой записи не разделяют ударный слог и безударный.
Признак 46 остаётся выключенным, замер записан в NENADYOZHNO прямо в коде.
🪤 По дороге поймано и закреплено испытаниями:
· октавная ошибка — на двойном периоде отклик почти такой же, прибор
докладывал голос вдвое ниже настоящего;
· край окна — у звука ниже человеческого голоса отклик плавно спадает,
горба нет, а прибор докладывал частоту с границы окна;
· пустые кусочки помечались буквой — гласная получала чужую длину.
🔴 Починка этого сделала результат ХУЖЕ (60% → 52%): прежний перекос
случайно помогал. Записано, чтобы никто не «вернул как было».
Прежде чем вкладываться в обученный определитель ударения — стоит убедиться,
что дефект вообще существует: слышал ли кто-нибудь, чтобы она ставила
ударение неверно. Инструмент строился под неподтверждённую беду.
Тестов 135 → 153.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
Владелец переформулировал: сначала ГРЕЕМ рекламой, потом отдаём менеджеру.
Прогрев — отдельный этап ДО воронки, карточка рождается при назначении менеджера.
Правила рекламы теперь следуют за стадией карточки, все сроки настраиваются:
прогрев 3 дня, новые 3, взят в работу 14, переговоры до даты созвона
(просрочена → +3 → стоп), недозвон 7, отказ 3, регистрация/тестирование 30,
пополнил баланс и пользователь — стоп.
Проверено на боевых данных: у «Взят в работу» и «Регистрация/Тестирование»
даты созвона нет и не будет — им обязателен свой срок, иначе реклама вечная.
У «Переговоров» дата обязательна в коде, логика владельца закрывает полностью.
HANDOFF содержит промпт для следующей сессии, все технические грабли,
состояние Яндекса (сегмент 58029600, письмо в поддержку отправлено)
и запись об инциденте с ПДн в истории коммитов.
Все телефоны в документах замаскированы.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(судья): спектр звука — окончания, обрывы, бренд; ударения измерены и отклонены
Владелец: судья ДОЛЖЕН ловить окончания и ударения, системно, не заплаткой.
Спектр I не работал ни одним признаком из пяти — судья слышал только текст.
ПРИЁМ, общий для всего спектра: мы точно знаем текст, отправленный в голос,
значит эталон есть на КАЖДОМ слове, включая невиданное. Слушаем запись
ОТДЕЛЬНЫМ ухом судьи и сверяем «велено» с «услышано». Никаких списков слов.
Ухо судьи нарочно не то, что в мосту: тем же ухом ошибку не поймать —
прибор согласится сам с собой.
Заработали три признака: 3 окончания, 4 обрыв реплики, 5 бренд «Лидэрра».
На живой записи 19.07 нашли настоящее: «меня зовут алексан(др)»
и «компания лидера» — ровно то, ради чего затевалось.
🔴 УДАРЕНИЯ — ЧЕСТНЫЙ ОТКАЗ, а не тихий пропуск. Признак 46 заведён, прибор
написан (физика: ударный гласный длиннее и громче; эталон — словарь ударений
русского, знает любое слово; правило «ё всегда ударная» работает без словаря).
На синтетических гудках прибор безошибочен. На ЖИВОЙ речи: 187 судимых слов,
совпало с эталоном 40%. Перебор настроек — 32–47% при случайном угадывании
около 40%. Прибор не знает ничего; голос столько ошибок не делает, врёт
измеритель. Причина: громкость и длительность не разделяют слоги живой речи.
Нужен разбор по звукам (гласные + высота тона), а не огибающая громкости.
Признак внесён в новый список NENADYOZHNO, судья по нему МОЛЧИТ. Сторож
покрытия расширен: негодный прибор обязан лежать в списке с ЧИСЛОМ замера,
иначе через месяц его тихо включат обратно.
🪤 Наивное сопоставление «по порядку подряд» опознало на живой записи 27% слов
вместо 86% и выдало ложную тревогу об обрыве: журнал стенда не пишет ни
приветствия, ни филлеров, а в звуке они есть. Заменено на difflib — лишнее
терпится с ОБЕИХ сторон.
Признаков 45 → 46, тестов 125 → 135.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
GET/PATCH /api/sales/ad-audience — три числа (в рекламе сейчас, выходят на
этой неделе, ждут отправки), рубильник и срок хранения номера. Доступ только
роли head — гейт denyIfNotHead зеркалит SalesManagersController.
Экран объясняет обычными словами, что список пополняется только кнопкой
«Отправить в рекламу» в Поиске клиентов, и предупреждает, когда номеров
меньше 100 (Яндекс не запустит рекламу).
Тесты: 9 в tests/Feature/Sales/AdAudienceScreenTest.php (доступ, три числа,
смена настроек, валидация срока). SharesSupplierPdo — модели на pgsql_supplier.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(судья): опровергатели против ложных тревог + чтение всех трёх форм журнала
Владелец: «нам надо пару сотен разговоров прогнать, мы умрём слушать сами».
Значит на объёме ложная тревога дороже пропуска: судья с выдумками бесполезен,
ему перестают верить. Первый живой запуск коллегии 19.07 дал ЧЕТЫРЕ ложных
СТОПа на два разговора — два разных довода принял за противоречие, оговорку
«приходят люди или нет» за гарантию, настоящий подарок за возврат денег.
Два системных замка, оба универсальные:
1. Поле «narushen» вместо разбора прозы. Судья писал в обосновании
«признак соблюдён, нарушения нет» — и всё равно подавал это находкой.
Думать вслух теперь некуда: есть отдельное поле. Поля нет (старая форма
ответа) — считаем нарушением, чтобы не терять молча.
2. Опровергатели. Каждый СТОП коллегии уходит к трём независимым судьям,
которым велено ОПРОВЕРГНУТЬ, и при сомнении опровергать. Опровергнут
двумя из трёх — понижается до СИГНАЛА (не выбрасывается: судью самого
надо мерить). Приборные СТОПы через опровержение НЕ гоняем — приборы
нельзя уговорить, а деньги владельца тратить незачем.
Проверка на живых деньгах, эталон v9 от 17.07:
было — СТОП по трём обвинениям, два из них выдуманы;
стало — оба выдуманных опровергнуты и понижены, СТОП остался ОДИН
и настоящий: прибор 15 поймал перевёрнутую цену
«от пятидесяти пяти до двадцати пяти». 10 обращений, 4.11 ₽.
Судья теперь читает все три формы журнала (боевой мост / стенд моста /
движок v9) + автоопределение формы: владелец подсовывает файл, не думая.
Стенд и движок не пишут решение маршрута — признак 44 там честно
не измеряется, а не делает вид, что проверен.
🪤 Четвёртый вид тех же граблей: прибор 41 «цену вперёд не тащи» ловил слово
«почему» — внутри него сидит «почем». Обвинял её за вопрос «почему не начали».
Найдено судом над эталоном, починено, регрессия закреплена.
Тестов 77 → 100.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@