Аудит R2 · защита тестирования · 10–11 июня 2026

91 ход против бота: что держится — и где он врёт.

Это не «прокликали и понравилось». Три персоны вели адаптивные диалоги — каждая следующая реплика писалась после чтения реального ответа бота, — а затем актуальный код прошёл живую партию в Telegram: голос, кнопки, сессии, онбординг. Каждый вывод ниже подкреплён цитатой из транскрипта или живым сообщением.

3×17персоны × адаптивных диалогов
91ход симуляций, реальные LLM-вызовы
8голосовых в live-партии, включая реальный голос Дани
0изменений прод-кода: заход «смотрим, не чиним»
01

Методология: кто и как давил на бота

Слабое место любых «тестов чат-бота» — скриптовый прогон: заранее написанные реплики, которым всё равно, что ответил бот. Здесь иначе: 17 диалогов писались ход за ходом — персона читала настоящий ответ Linda и реагировала, как живой раздражённый/уставший/уверенный человек. Плюс пробы кнопок (Разбор · Подсказка · Перевод) на каждом характерном ходу.

🎙

Даня

RU · A0 · голос-first

Ноль португальского, общается голосом, любая обратная связь «ты ошибся» на правильную фразу — удар по мотивации. Сценарии: кафе, доставка, педиатр, числа/сдача, эмоциональный срыв, застенчивость.

6 диалогов · 32 хода · daniel_*.jsonl
🛒

Марина

RU · A2 · типичные мид-ошибки

Год в Бразилии, говорит со смешанными RU+PT репликами и типичными ошибками уровня (род, ser/estar). Проверяет: дисциплину коррекций, слух сцены, «не учи меня говорить bom dia». Сценарии: padaria, цены, возврат товара, сосед, жалоба.

6 диалогов · 33 хода · marina_*.jsonl
📋

Аня

RU · B1 · иммерсия PT-only

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

5 диалогов · 26 ходов · anya_*.jsonl
Live-партия: актуальный код, настоящий Telegram (сообщения 711768–711852)

После симуляций — проверка на живом боте с ротированным токеном: команды, сессии с гэпом −50 минут, онбординг с нуля, кнопки с повторными тапами, анализ TTS-озвучки и голос-сьют из 8 записей — от чистого португальского до тяжёлого акцента и тишины:

чистый PT ✓тяжёлый RU-акцент ✗RU+PT смесь ✓ числа ✓тихая речь ✓тишина ✓RU-мета ✓реальный голос Дани ✓

«Заслужил ли бот, чтобы экспат завтра открыл его вместо Google Translate?»

Одна линза на весь аудит. Не «есть ли баги» — баги есть всегда. Вопрос — возвращается ли живой человек. Каждая персона в конце дала свой вердикт по этой линзе (раздел 04).

02

Что подтвердилось: фиксы Phase 0–3 держатся

Сначала хорошее — и это не дежурная вежливость, а главный итог регрессии: в своей зоне ответственности фиксы прошлого захода живы, включая headline-баг первого аудита.

D1Headline-баг мёртв и вживую

Голосовое «научи признаваться в любви» → «Разбор» учит 💡 Eu te amo • Eu — я… — целевую фразу, а не глоссы русского. Live 711795.

D6«Перевод» → русский

Оба зонда у Ани вернули русский перевод, не PT→PT-пересказ: Ах, бразильская бюрократия!..

IMMИммерсия не сваливается в RU

0 русских пузырей на 26 ходов B1; стресс-тест с вброшенным «вялая» пройден — ответ остался в PT.

D11Сессии режутся честно

Гэп −50 минут → новый session_id, тема врача не перетекла в пиццу; /new — «🆕 Начали с чистого листа».

BTNКнопки идемпотентны

Повторный тап по «Разбору» → ⏳, без дублей и повторной генерации. Подсказка — безупречна во всех пробах.

ONBОнбординг пишет профиль

3 тапа + строка цели: язык (флаги+эндонимы), уровень в человеческих словах («🌱 С нуля»), цель — всё в профиле.

03

Найденные дыры

Ядро уже «хорошо» — и именно поэтому стало видно следующий слой. Ниже — каталог по серьёзности: P0 — рушит доверие или сам факт работы продукта; P1 — портит ежедневный опыт; P2 — мелочи, чинятся одним проходом. У каждой дыры: что происходит, доказательство, где в коде.

P0четыре находки, рушащие доверие и базовую работу
R1 · recast-ложь

Самая доверенная поверхность правит правильное — и пропускает ошибки

Строка 💡 приходит автоматически на каждый ход — ей верят больше всего. И именно она «исправляет» нормальный разговорный бразильский на письменный/европейский, правит фразы, которым сама научила два хода назад, молча меняет текст под значком ✓ — и на тех же ходах пропускает реальные ошибки («as pessoas fala», «meu amiga»).

<s>fui no</s> <b>fui à</b> padaria — а «Разбор» на том же ходу говорит обратное: «no/na — это нормально»marina padaria T1 · слои противоречат друг другу
«Ensina-me a confessar amor» — европейская форма в бразильском ботеlive 711785 · B1-хвост
владелец: «иногда зачёркивается, иногда нет — нет системы, хаотично реагирует»Owner-finding O4 · 2026-06-11
src/core/prompts.py MODE_RECAST / MODE_RECAST_VOICE · src/core/conversation.py _recast()
R2 · голос судится по буквам

Кириллический транскрипт правильной фразы получает выдуманную ошибку

STT пишет русскими буквами то, что слышит. Бот сравнивает буквы, а не звуки: правильное произнесение помечается ошибкой, числа подменяются (6,70 → 67), а из акцентного мусора бот уверенно «восстанавливает» фразу, которой не было. Для голос-first юзера это главный риск оттока: «я не боюсь говорить плохо» умирает, когда тебя правят за правильное.

«нао обригадо» (= Não, obrigado — правильно) → «Разница в первом слове — "Não"» + потрачен бюджет коррекцииdaniel emotional T3
из акцентного мусора «Бундае и Юг верал лампы дикфей» бот уверенно сочинил «Bom dia e você já almoçou?»live 711800
src/core/prompts.py MODE_RECAST_VOICE — нет кириллических примеров и правила фонетического сопоставления
S1 · победы не существуют

Полная сцена пройдена — система записала ноль

0 × WIN · can_do_count = 0 · 91 ход + live

Живая сцена кафе целиком (привет → заказ → цена → спасибо): зачтено 2 бита из 4, победы нет. Механизм найден: модель мид-сценой сама эмитит свободный тег ([[SCENARIO: cafe_order_complete]]) → код считает это новым сценарием и сбрасывает счётчик; финальный бит с инструкцией WIN больше никогда не рендерится. Бот празднует прозой — система не записывает. Обещание «вижу свой рост» в продукте не существует.

steps_done 2→0 ровно в момент «Ты прошёл весь диалог от заказа до получения»daniel cafe T5 · корень B2 найден
src/core/scenario.py:65 record() · src/core/scenarios.py приглашение к freeform-id
X1 · прода не было

Бот в Telegram месяц работал на старом коде — и молча потерял память

У репозитория нет git remote — CI из RUNBOOK был фикцией. Токен поллил недосягаемый сервер с кодом до Phase 0–3: все фиксы в живом Telegram не работали до этого захода. Вторая часть: миграции к локальной БД не накатаны, и best-effort-обработка молча превратила бота в безпамятного — история не писалась с 06-08, ни одна метрика об этом не кричала.

токен ротирован, старый инстанс мёртв, актуальный код поднят локально — но «works 24/7» из CLAUDE.md сейчас не факт, а надеждаАудит R2 · TL;DR п.3
нет remote/CI · main.py без fail-fast при schema drift · Sentry DSN не задан
P1восемь находок, портящих ежедневный опыт
I1 · input-type мёртв

Бот не отличает русскую реплику от попытки на португальском

Метка L1_UTTERANCE ни разу не выстрелила за 91 ход; у Дани 11 из 32 ходов остались без типа — и тогда его русский зачёркивается recast'ом, а «Разбор» глоссит русские слова («тараторят → falam muito rápido»).

11/32 ходов input_type=None; L1_UTTERANCE не выстрелил ни разу за аудитdaniel_NOTES B3 · хвост D1/D7
src/core/conversation.py classify_input_hint() · prompts.py fallback PT_ATTEMPT
S3 · A0-доктрина для всех

B1 платит «налог на спор» каждую сессию

Доктрина иммерсии захардкожена «The student is A0» — для всех. Аня (B1) каждую сессию спорит с ботом, чтобы добраться до своего уровня; Марине с годом в Бразилии каждая сцена начинается с «скажи bom dia» (она дважды огрызнулась в симуляции).

«Tente essa frase agora» — на её же только что написанную правильную фразуanya banco T2 · N1
src/core/prompts.py DOCTRINE_PT_IMMERSION («The student is A0»)
O1 · произношение без скоринга

«Поняли бы меня в padaria?» — сигнала нет вообще

Голосовое сообщение получает только текстовый recast; КАК произнесено — продукт не отвечает. Дыра ровно в JTBD «понять, готов ли я к завтра». Назвал сам владелец по живому использованию.

владелец: «итоговое сообщение не разбирается с точки зрения скоринга произношения»Owner-finding O1 · 2026-06-11
src/core/voice.py AzureTranscriber — Pronunciation Assessment едет тем же Azure-вызовом
O2 · кнопки исчезают

Вернулся к непрочитанному войсу — а [Текст] уже снят

По коду это дизайн (кнопки только под последним обменом), но в голос-first скролле ощущается как поломка: войс есть, расшифровать нечем.

владелец: кнопки пропадают с прошлых сообщений; ощущается как багOwner-finding O2 · SPEC §11.2 _retire_buttons
хэндлеры бота · нужен маппинг tg_message_id → строка истории
V1 · онбординг глотает войс

Голосовой ответ на вопрос цели — тишина

FSM принимает только текст; голос-first юзер на последнем шаге решит, что бот сломан. Финал «начнём прямо сейчас» при этом ничего не начинает.

голосовой ответ на вопрос цели — полная тишинаlive-онбординг
P1 · misgendering и регистр

«Você está certo» — женщине

Гендера в профиле нет; ты/вы скачет между ответами; системные нотисы говорят о Линде в мужском роде («не смог обработать»).

«Você está certo» Ане — ломает «бот знает мою жизнь» мгновенноanya pediatra T3
T3 · неверное правило

Бот научил несуществующей грамматике

На прямой вопрос B1 — сначала «не парься об этом» (это её заявленная цель!), потом правило futuro do subjuntivo, которое порождает «se eu ter». Исправился, только когда она поймала.

её системная ошибка «se + indicativo» встретилась 4 раза — и ни разу не названаanya N5/N8
S2 · сцена не слышит юзера

Бот просит сделать шаг, который только что сделан

Марина спрашивает цену — бот отвечает «попробуй спросить цену». Заказала фрукты — он переучивает заказ и игнорирует её вопрос. «Скрипт, а не собеседник» — главная причина уйти обратно в Google Translate.

она спрашивает цену; бот: «Tenta você — como pergunta o preço?»marina padaria T3 · N3
src/core/scenarios.py — бит инъектится безусловно, без правила skip-if-done
P2тринадцать мелочей — чинятся одним проходом (пакет 5)
04

Вердикты персон: ответы на линзу

«Заслужил ли бот, чтобы экспат завтра открыл его вместо Google Translate?» — итог каждой персоны, дословно из заметок.

🎙 Даня · A0 · голос-first
«Завтра откроет; через две недели без R2 + S1 — нет

Подбор фраз — ровно то, что нужно выживанию. Но голосовой цикл, который говорит «неправильно» на правильное, — самый большой риск оттока; а три пройденные сцены без единой засчитанной победы хоронят обещание «вижу свой рост».

daniel_NOTES.md · Аудит R2 §5
🛒 Марина · A2
«Скорее да — за контент; со скрипом — за разговор.»

«Словарный материал именно тот, что нужен экспату (nota fiscal, síndico, CDC)… Но recast-слой штрафует правильные фразы, сцены начинаются с „скажи bom dia" для человека, живущего в Бразилии год. Починить N1–N4 — и это будет однозначное „да".»

marina_NOTES.md · bottom line
📋 Аня · B1 · иммерсия
«Да, с оговоркой: каждую сессию платит „налог на спор".»

Ценность реальна и не гуглится: CDC/Procon, регистр, телефонная техника. Но бот стартует с A0-дрилла, и до своего уровня надо «доспорить»; а recast на B1 настолько шумный, что она научится игнорировать ровно ту поверхность, которая должна полировать её грамматику.

anya_NOTES.md · bottom line