Методология: кто и как давил на бота
Слабое место любых «тестов чат-бота» — скриптовый прогон: заранее написанные реплики, которым всё равно, что ответил бот. Здесь иначе: 17 диалогов писались ход за ходом — персона читала настоящий ответ Linda и реагировала, как живой раздражённый/уставший/уверенный человек. Плюс пробы кнопок (Разбор · Подсказка · Перевод) на каждом характерном ходу.
Даня
RU · A0 · голос-firstНоль португальского, общается голосом, любая обратная связь «ты ошибся» на правильную фразу — удар по мотивации. Сценарии: кафе, доставка, педиатр, числа/сдача, эмоциональный срыв, застенчивость.
Марина
RU · A2 · типичные мид-ошибкиГод в Бразилии, говорит со смешанными RU+PT репликами и типичными ошибками уровня (род, ser/estar). Проверяет: дисциплину коррекций, слух сцены, «не учи меня говорить bom dia». Сценарии: padaria, цены, возврат товара, сосед, жалоба.
Аня
RU · B1 · иммерсия PT-onlyДва года в Бразилии, режим полной иммерсии, тонкие ошибки (subjuntivo, кальки). Проверяет: стабильность иммерсии, точность грамматики, обращение с продвинутым взрослым. Сценарии: банк, педиатр, полировка грамматики, возврат, эмоциональный.
После симуляций — проверка на живом боте с ротированным токеном: команды, сессии с гэпом −50 минут, онбординг с нуля, кнопки с повторными тапами, анализ TTS-озвучки и голос-сьют из 8 записей — от чистого португальского до тяжёлого акцента и тишины:
«Заслужил ли бот, чтобы экспат завтра открыл его вместо Google Translate?»
Одна линза на весь аудит. Не «есть ли баги» — баги есть всегда. Вопрос — возвращается ли живой человек. Каждая персона в конце дала свой вердикт по этой линзе (раздел 04).
Что подтвердилось: фиксы Phase 0–3 держатся
Сначала хорошее — и это не дежурная вежливость, а главный итог регрессии: в своей зоне ответственности фиксы прошлого захода живы, включая headline-баг первого аудита.
Голосовое «научи признаваться в любви» → «Разбор» учит 💡 Eu te amo • Eu — я…
— целевую фразу, а не глоссы русского. Live 711795.
Оба зонда у Ани вернули русский перевод, не PT→PT-пересказ: Ах, бразильская бюрократия!..
0 русских пузырей на 26 ходов B1; стресс-тест с вброшенным «вялая» пройден — ответ остался в PT.
Гэп −50 минут → новый session_id, тема врача не перетекла в пиццу; /new — «🆕 Начали с чистого листа».
Повторный тап по «Разбору» → ⏳, без дублей и повторной генерации. Подсказка — безупречна во всех пробах.
3 тапа + строка цели: язык (флаги+эндонимы), уровень в человеческих словах («🌱 С нуля»), цель — всё в профиле.
Найденные дыры
Ядро уже «хорошо» — и именно поэтому стало видно следующий слой. Ниже — каталог по серьёзности: P0 — рушит доверие или сам факт работы продукта; P1 — портит ежедневный опыт; P2 — мелочи, чинятся одним проходом. У каждой дыры: что происходит, доказательство, где в коде.
Самая доверенная поверхность правит правильное — и пропускает ошибки
Строка 💡 приходит автоматически на каждый ход — ей верят больше всего. И именно она «исправляет» нормальный разговорный бразильский на письменный/европейский, правит фразы, которым сама научила два хода назад, молча меняет текст под значком ✓ — и на тех же ходах пропускает реальные ошибки («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()Кириллический транскрипт правильной фразы получает выдуманную ошибку
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 — нет кириллических примеров и правила фонетического сопоставленияПолная сцена пройдена — система записала ноль
Живая сцена кафе целиком (привет → заказ → цена → спасибо): зачтено 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Бот в Telegram месяц работал на старом коде — и молча потерял память
У репозитория нет git remote — CI из RUNBOOK был фикцией. Токен поллил недосягаемый сервер с кодом до Phase 0–3: все фиксы в живом Telegram не работали до этого захода. Вторая часть: миграции к локальной БД не накатаны, и best-effort-обработка молча превратила бота в безпамятного — история не писалась с 06-08, ни одна метрика об этом не кричала.
токен ротирован, старый инстанс мёртв, актуальный код поднят локально — но «works 24/7» из CLAUDE.md сейчас не факт, а надеждаАудит R2 · TL;DR п.3
main.py без fail-fast при schema drift · Sentry DSN не заданБот не отличает русскую реплику от попытки на португальском
Метка 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_ATTEMPTB1 платит «налог на спор» каждую сессию
Доктрина иммерсии захардкожена «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»)«Поняли бы меня в padaria?» — сигнала нет вообще
Голосовое сообщение получает только текстовый recast; КАК произнесено — продукт не отвечает. Дыра ровно в JTBD «понять, готов ли я к завтра». Назвал сам владелец по живому использованию.
владелец: «итоговое сообщение не разбирается с точки зрения скоринга произношения»Owner-finding O1 · 2026-06-11
src/core/voice.py AzureTranscriber — Pronunciation Assessment едет тем же Azure-вызовомВернулся к непрочитанному войсу — а [Текст] уже снят
По коду это дизайн (кнопки только под последним обменом), но в голос-first скролле ощущается как поломка: войс есть, расшифровать нечем.
владелец: кнопки пропадают с прошлых сообщений; ощущается как багOwner-finding O2 · SPEC §11.2 _retire_buttons
tg_message_id → строка историиГолосовой ответ на вопрос цели — тишина
FSM принимает только текст; голос-first юзер на последнем шаге решит, что бот сломан. Финал «начнём прямо сейчас» при этом ничего не начинает.
голосовой ответ на вопрос цели — полная тишинаlive-онбординг
«Você está certo» — женщине
Гендера в профиле нет; ты/вы скачет между ответами; системные нотисы говорят о Линде в мужском роде («не смог обработать»).
«Você está certo» Ане — ломает «бот знает мою жизнь» мгновенноanya pediatra T3
Бот научил несуществующей грамматике
На прямой вопрос B1 — сначала «не парься об этом» (это её заявленная цель!), потом правило futuro do subjuntivo, которое порождает «se eu ter». Исправился, только когда она поймала.
её системная ошибка «se + indicativo» встретилась 4 раза — и ни разу не названаanya N5/N8
Бот просит сделать шаг, который только что сделан
Марина спрашивает цену — бот отвечает «попробуй спросить цену». Заказала фрукты — он переучивает заказ и игнорирует её вопрос. «Скрипт, а не собеседник» — главная причина уйти обратно в Google Translate.
она спрашивает цену; бот: «Tenta você — como pergunta o preço?»marina padaria T3 · N3
src/core/scenarios.py — бит инъектится безусловно, без правила skip-if-done- V2slow_phrase с русской глоссой — медленная озвучка прочитает «(Хорошо!)» по-русски
- V3[[CHUNK: …]] утёк в реплику — внутренний маркер виден юзеру
- D9ремарки в пузыре — «(segurando o celular indignada)», «Escute e repita» в текстовом чате
- T1анти-чанк глоссинг — «por favor» разбирается по словам, хотя это одна единица
- T2стены повторов — та же полная карточка 2–3 хода подряд; «шпаргалка без лишнего» игнорится
- T5пробы лезут не в свою роль — «Перевод» даёт урок, «Разбор» назначает свои задания
- T6арифметика сдачи врёт — 5,50 вместо 3,50 в ролевой игре кассира
- T4нет памяти ошибок — «se+indicativo» ×4 за аудит, паттерн ни разу не назван
- U1«что мы обсуждали?» после гэпа — вопрос молча игнорируется
- U2/level — две строки — «Твой уровень: A0. Засчитано умений: 0»; прогресса не видно
- U3нет тихого режима — «говорю тихо в очереди» → войс в ответ
- E1«anywhere» в русском каркасе — EN/PT-вкрапления в RU-прозе
- O3«🆕 Новая ситуация» ничего не объясняет — владелец не знает, что делает кнопка
Вердикты персон: ответы на линзу
«Заслужил ли бот, чтобы экспат завтра открыл его вместо Google Translate?» — итог каждой персоны, дословно из заметок.
«Завтра откроет; через две недели без R2 + S1 — нет.»
Подбор фраз — ровно то, что нужно выживанию. Но голосовой цикл, который говорит «неправильно» на правильное, — самый большой риск оттока; а три пройденные сцены без единой засчитанной победы хоронят обещание «вижу свой рост».
«Скорее да — за контент; со скрипом — за разговор.»
«Словарный материал именно тот, что нужен экспату (nota fiscal, síndico, CDC)… Но recast-слой штрафует правильные фразы, сцены начинаются с „скажи bom dia" для человека, живущего в Бразилии год. Починить N1–N4 — и это будет однозначное „да".»
«Да, с оговоркой: каждую сессию платит „налог на спор".»
Ценность реальна и не гуглится: CDC/Procon, регистр, телефонная техника. Но бот стартует с A0-дрилла, и до своего уровня надо «доспорить»; а recast на B1 настолько шумный, что она научится игнорировать ровно ту поверхность, которая должна полировать её грамматику.