fix(jivo-bot): мягкий ИЛИ-поиск при пустом строгом + стоп-тема «у меня … баланс» с разрывом слов

Два живых бага демо 12.07.2026 (TDD, 34/34 зелёные):
- KnowledgeSearch: websearch_to_tsquery требует ВСЕ слова вопроса; «зачем он нужен»
  ронял поиск в пусто → добавлен мягкий запасной проход через ИЛИ (plainto | )
- BotAnswerService STOP_PATTERN: «какой у меня сейчас баланс» проскакивал стоп-тему
  (слова между «у меня» и «баланс») → допускаем до 3 слов разрыва, сч[её]т
- Протокол: журнал 12.07 (аккаунт Jivo, канал, цвет, ключ zofyNxmnRP, стенд-проверка)
- Скриншоты живой проверки виджета в findings

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-07-12 09:30:53 +03:00
parent d9bfb4f360
commit ba3108e94c
12 changed files with 64 additions and 9 deletions
@@ -35,6 +35,15 @@ it('находит по синонимам из topics («закинуть де
->and($hits[0]->title)->toBe('Как пополнить баланс');
});
it('находит статью, даже если часть слов вопроса в текстах отсутствует', function () {
// websearch_to_tsquery связывает слова через И: слово «нужен» в статье не встречается,
// строгий запрос даёт пусто — нужен мягкий запасной поиск через ИЛИ (живой баг 12.07.2026).
$hits = app(KnowledgeSearch::class)->search('Что такое проект и зачем он нужен?', 3);
expect($hits)->not->toBeEmpty()
->and($hits[0]->title)->toBe('Что такое проект');
});
it('на вопрос не по теме возвращает пусто', function () {
expect(app(KnowledgeSearch::class)->search('какая погода в москве', 3))->toBeEmpty();
});