Commit Graph

6 Commits

Author SHA1 Message Date
Дмитрий b1b1686b0e fix(bot): прогон 250 вопросов × 2 режима — 11 находок закрыто, все проверены перепрогоном
Владелец: «проверь их обоих на тех 250 вопросах» → «правь все».
Разбор: docs/superpowers/findings/2026-07-14-bot-250-both-modes-run.md

Цены оказались вылечены полностью (0 выдуманных цен на 500 ответов), но вылез другой
пласт — бот путал гостя с вошедшим клиентом и импровизировал там, где правды нет в статьях.

ЧТО ПОЧИНЕНО (было → стало на перепрогоне):
- Гостю приписывали счёт и подарок («у вас уже есть 1000 ₽, они лежат на счёте») 2 → 0.
  У гостя нет ни счёта, ни подарка: он не зарегистрирован.
- Вошедшему называли его баланс подарком портала 2 → 0 и подсовывали сценарий новичка
  («живите на подарок», «создайте первый проект») — подарок он потратил давно.
- Вошедшему врали про состояние проектов («два работают», а работает один) 4 → 0
  и про заявки («сегодня 12», а сегодня 0) 1 → 0.
- «Сотая заявка уже дешевле» 2 → 0: ступень меняется по ОБЪЁМУ (первая — 500 заявок).
- «1000 ₽ хватит на несколько десятков заявок» 1 → 0. По решению владельца число заявок
  на подарок НЕ называем вообще: сколько придёт, зависит от источника.
- «Поднимите лимит — заявок будет больше» 1 → 0: лимит это ПОТОЛОК, а не источник.
- «Такого не бывает» про списание без заявки 1 → 0: на проде фантомные списания БЫЛИ.
- «Для Москвы — Московскую область» 1 → 0: Москва и СПб — самостоятельные субъекты.
- Обрубки фраз после чистки сторожем («Они лежат…», «Нажмите её…») 3 → 0.

ЗАМЕЧАНИЕ ВЛАДЕЛЬЦА ПО ЖИВОМУ ЛОГУ: «номера это и есть заявки, а он их делит».
Фраза «мы не продаём номера поштучно» была ВЫДУМКОЙ бота — в статьях её нет.
Теперь: номер = заявка = лид = контакт, продаём любой объём (хоть одну штуку),
минимального заказа нет; спросили цену — бот называет цифру ПЕРВОЙ фразой.
Живьём: «Сколько стоит один номер?» → «Заявка стоит от 55 ₽ до 25 ₽».

ПРАВДА ПРО ВОЗВРАТ ДЕНЕГ вынесена в статью vozvrat-deneg.md — дословно из «Политики
возврата» (/legal/refund): остаток по заявлению на почту, до 3 рабочих дней, за вычетом
комиссий; стоимость переданных заявок не возвращается. Раньше бот придумывал процедуру.

Плюс: сторож больше не считает выдумкой число, названное САМИМ клиентом («можно купить
всего 5 номеров?»); демо-стенд перестал сам себе противоречить (счётчик проекта «сегодня»
разошёлся с числом сделок); добавлен прогонщик bot:run-questions для таких проверок.

Тесты: бот 258/258, весь бэкенд 2738/2744 (0 падений). Сторож не перестарался: из 250
старых одобренных ответов режет целиком 1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 18:32:40 +03:00
Дмитрий 7b7718d319 fix(bot): бот врал про цены живым гостям — брал ВСЕ версии сетки тарифов разом
Живой разговор на боевом 14.07.2026: гость спросил цену, бот назвал «500 ₽ за первую
заявку месяца» (такого тарифа нет — сетка 55→25 ₽), клиент поймал на вранье и ушёл.

Три поломки из одного разговора:

1. ЦЕНЫ. В pricing_tiers лежат ЧЕТЫРЕ версии сетки (старые хранятся с датой начала
   действия). Портал берёт свежую через PricingTierRepository, а LivePrices читал
   таблицу напрямую и склеивал все версии: «ступень 1 — 500 ₽; ступень 1 — 70 ₽;
   ступень 1 — 55 ₽…». Сторож вранья был бессилен — 500 ₽ и правда лежало в поданных
   модели статьях. Теперь сетку берём тем же способом, что и «Биллинг» в кабинете.

2. ССЫЛКИ МИМО ТЕМЫ. У статьи «Собрать источники — цена, очередь…» слово «цена» стоит
   в заголовке, а в синонимах «50 рублей» — она перебивала «Тарифы» на любом денежном
   вопросе. Теперь берём САМУЮ совпавшую статью и только при уверенном совпадении
   (совпавшие слова покрывают хотя бы половину вопроса); на коротком уточнении новую
   ссылку не подсовываем, если человек уже получил одну.

3. ОТВЕТ С СЕРЕДИНЫ ФРАЗЫ. «Но если вы хотите понять…» — клиент решил, что ему хамят.
   Висящий союз снимался ДО того, как выбрасывалась отговорка «в инструкции этого нет».
   Порядок исправлен (AnswerGuard::polishStart).

Плюс по решению владельца: на «сколько стоит заявка?» бот сразу называет вилку
«от 55 ₽ за заявку до 25 ₽ при большом объёме» (метка {{вилка}} из живой сетки).

Тесты бота: 240/240, из них 6 новых — воспроизводят тот разговор и падали на старом коде.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 15:32:15 +03:00
Дмитрий c320e095e1 fix(bot): ювелирная доводка после второго круга судей
- «скидка ЗА ОБЪЁМ» больше не считается просьбой скидки: бот отвечает про
  ступени тарифа, а не уводит к специалисту.
- «где посмотреть мою ступень / мой лимит» — вопрос про портал, а не про
  личные данные клиента: эскалация снята.
- Цена ↔ ниша/регион: правило по СМЫСЛУ (AnswerGuard::priceTiedToNiche).
  Враньё «цена зависит от ниши» возвращалось ПЯТЬЮ формулировками —
  регулярка на каждую не работает. Честное «цена НЕ зависит от региона»
  сохраняется.
- Вырезано: «на тысячу выйдет от 2 до 20 заявок» (реально максимум 4),
  «работаем не со всеми нишами» / «есть направления, с которыми мы не
  сотрудничаем» (ограничений по нишам НЕТ), «не берёт трубку — забей»
  (такую заявку МЕНЯЮТ), «баланс на паузе не потратится», выдуманные сроки
  зачисления по счёту.
- Промпт: цена только от ступени объёма; запретных ниш нет.
- Статьи: тронута ТОЛЬКО строка topics (синонимы поиска), тексты не менялись.

Тесты 126/126. Бот НЕ на проде.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 05:35:11 +03:00
Дмитрий c5125e981e feat(bot): выбор модели + три замка безопасности + инструкция 51 статья
Прогнал 250 вопросов через настоящий вебхук шесть раз и сравнил четыре модели
вслепую силами судей-агентов. Итоги — в docs findings.

Модель. Появился переключатель services.jivo_bot.llm: yandex (данные не покидают
РФ) либо aitunnel (зарубежные модели через российский шлюз). По слепому сравнению
Claude Haiku 4.5 выиграл финал у Gemini 157:24 и у обеих моделей Яндекса: он
полнее, точнее по кнопкам и цифрам и говорит как человек, а не справочник.

Три замка, потому что живая модель = самоуверенная модель:
- PersonalDataMask — телефоны и почта вырезаются ДО отправки в любую модель
  (клиент оставляет номер в чате; за границу ПДн уходить не должны).
- ChatTextCleaner — markdown и смайлики (Jivo их не рисует): было 191 ответ
  с разметкой, стало 0.
- AnswerGuard — режет юридические гарантии («вас не оштрафуют», «мы гарантируем»,
  «не нарушаем закон») и ЛЮБУЮ цену, которой нет в выданных статьях. Пусто после
  чистки → зовём живого специалиста.

Поиск по инструкции переписан: выбрасываются вопросительные слова (из-за них
«какие у вас тарифы» находило выгрузку в Excel), ранжирование сперва по заголовку
и синонимам, выдача — три РАЗНЫЕ статьи и каждая целиком, плюс починка опечаток
(«каг сазадь праэкт») и учёт прошлой реплики в коротких «а это платно?».

Инструкция: 40 → 51 статья. Новые — по фактам владельца: бесплатный тест и
подарок 1000 ₽, «мы канал, а не реклама», СМС → через час звонок, средние
показатели (8–12 из 100 разговаривают, ещё 5–7 по СМС), номер не вернётся
30 дней, замена брака, вывод остатка, поддержка 24/7, удаление данных, ниши.
Вычищено враньё: минус баланса, «списали без заявки», пауза вечером, выходные,
«Вся РФ», статус «Отказ» (его нет — есть «Не реализовано»), amoCRM, платный
повторный сбор, нарастающий итог тарифных ступеней.

Тесты: 106 из 106. Каждая найденная тупость закреплена тестом.

НЕ НА ПРОДЕ. Выкат — только по прямой команде владельца.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 20:44:48 +03:00
Дмитрий 47afefbb10 feat(bot): цены бот тянет сам из настроек — вручную актуализировать больше не надо
Вопрос владельца: «а цены в нём надо актуализировать руками или он сам тянет?»
Ответ был неприятный: руками. Цифры (300/50 руб, тарифные ступени) стояли текстом
в статьях — поменяли бы цену в админке, бот продолжил бы врать про деньги.

Теперь в статьях стоят метки {{цена_подбора}}, {{цена_изучения}}, {{тарифы}},
а сервис LivePrices подставляет живые значения из system_settings и pricing_tiers
В МОМЕНТ ОТВЕТА — без переиндексации базы знаний. Нет цены в настройках — метка
не протекает клиенту, бот отсылает к экрану, где цена написана всегда.

Из текстов экскурсий цифры цен тоже убраны (фронт не знает БД): шаг подсвечивает
строку с ценой в самом окне — она всегда актуальная.

Проверено живьём: поменял цену в настройках на 450 — бот сразу назвал 450.
Pest 42/42 (3 новых теста), Vitest каталога 8/8.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 14:06:04 +03:00
Дмитрий 9ff19f3cc3 @
feat(bot): всеобъемлющая инструкция (36 статей) + 31 узкая экскурсия, которая открывает окна

Живой урок владельца 12.07.2026: «дубли чистятся в 2-х местах, а бот выдумал третье»,
«стыдно такого бота показывать», «видео показываем полное, а я спрашиваю про одно —
надо резать», «надо не только кнопку показывать, а и что за ней».

База знаний: 17 обзорных статей → 36 узких по темам. Портал обойдён целиком
(5 агентов): все экраны, окна, подсказки «(?)», тексты ошибок, внутренние правила.
Новое, чего бот не знал: дубли в ДВУХ местах (Поле и Предложения) + окно «источник
уже есть»; правило 18:00; почему приходит меньше лимита; оплата по счёту и акты;
списания; безопасность и 2FA; отчёты; массовые действия; регистрация.

Экскурсии: 15 → 31, каждая на свою тему (3–7 шагов). Раннер GuidedTour научен
шагу `open` — сам открывает окно/вкладку и подсвечивает то, что ВНУТРИ
(окно дублей, форму подбора, диалог пополнения, панель тарифов, карточку сделки).
99 новых якорей data-tour расставлено по всему порталу (4 агента).

Поиск: веса в tsvector (заголовок A / синонимы B / текст C) — иначе на «чистка
дублей» первой всплывала статья «Списания» из-за мимоходного упоминания «поля».

Тесты: Pest бот 39/39, Vitest 1222/1222. Новые сторожа: у каждой статьи есть
экскурсия; экскурсия не короче 3 и не длиннее 7 шагов; каждая цель экскурсии
реально существует в разметке; экскурсии про действия обязаны открывать окно.
Живая проверка в браузере: экскурсия про дубли сама открыла окно объединения
и перешла на второе место чистки.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@
2026-07-12 12:56:22 +03:00