✅ Локально полный ci-check: 12847 тестов, 0 падений, 14 гардов
版本 1.2610.4618
Новое
Импорт сверяет медиа с описью, строка в отчёте
Секретарь отвечает гостю о свободных номерах и ценах
Опись медиа в бэкапе с размером и sha256
AI-секретарь сдаёт звонок человеку, а не молчит
AI-секретарь отвечает на звонок и говорит с гостем
Голос приложения уходит собеседнику через INCALL_MUSIC
Фаза 2 оптимизатора — телефонная книга Android (GSD system-contacts-phase2) в beta
Журнал называет расходящуюся таблицу
Отчёты о сбоях и статистика своими переключателями (№406)
Мастер оптимизатора гостей с откатом обратными правками
Общий ИИ-кэш только с согласия «Улучшать ИИ» (№406)
Из приложения можно удалить аккаунт (№406)
Звонилка сама говорит, что не настроено
Раздел «ИИ и голос» с таблицей ролей
Склад на планшете двухпанельный
№403 ремонт, готовность звонилки
E2E-шифрование синка ключом команды
Буллеты тарифа на языке приложения
Исправления
Значки и текст на стеклянных карточках, срез 2
Текст акцентом на стеклянных карточках, срез 1
«Сохранить» канала продаж читается
AI-секретарь слышит гостя и ведёт диалог в звонке
Имя карточки в «Ночной» и иконки поиска поверх фон-картинки
Светлый статус-бар терминальных экранов и читаемый акцент на диалогах стилей
Форма брони: 0 ночей, null в имени гостя, отказ минимума ночей
Правка брони больше не уходит в занятый номер
Код соседа видно над клавиатурой
Код соседа вводится при крупном шрифте
Чистка тумбстоунов автора с гардом ссылок
Полоска остатка читается в Sky Light
Строгие стили без пилюль целиком
Цены, звонки и главный экран без пилюль
Баннер разрешений не просвечивает
Рабочие экраны без пилюль в строгих стилях
Текст терминальных экранов светлый в любой теме
Настройки без пилюль в строгих стилях
Кошелёк платит через Робокассу (#360)
Тумбстоун всегда DELETE
Mesh и TeamSync находят свою команду по владельцу
Кнопки гаснут честно, меню ⋮ докручивается
Раздача не смешивает снимки
Локальная правка будит синк сразу
Заголовки терминальных экранов читаются в светлой теме
Встроенный ИИ включается по-настоящему
Голос говорит правду
Догон пропущенного после переподключения
Узел пускает телефон и по локальному адресу
Удалённый гость снимается со строк журнала, проверка голоса настоящая
Один звонок, одна запись
Панель долгого тапа звонилки говорит за себя
Остаток склада сходится по журналу
Адрес гостя, дубли на «Гостях», заголовок оптимизатора
№403 ремонт, след отказа распознавания
Карточки держат текст поверх своей фон-картинки
Данные оптимизатора гостей
Зашифрованные дельты с сервера доезжают до пиров, экран объясняет 403 ключа
Навигация и списки оптимизатора гостей
Процент остатка читается и совпадает с пилюлей
Тариф в приложении без облачного бэкапа (№406)
№403 ремонт, журнал звонков
Остаток склада доезжает до команды
Склад переживает поворот, таскбар и крупный шрифт
У статуса брони своё время
№403 ремонт, три карточки звонков
Оптимизатор гостей со страховочным снимком
Сдача охоты №388 влита живой сессией
Fix/echo-guard-garbled-and-tail-stop → beta
File-sync без холостых обходов фото и с хвостом для мёртвых файлов
Fix/confirm-no-self-barge-in → beta
Fix/ai-mode-switch-guard → beta
Блокировка учётки и удаление пула
Цена со склада и предупреждение о возврате
Отчёт по складу
Инвентаризация приводит остаток к факту, расход сверх остатка предупреждает
Серия броней из звонка сохраняет цену каждой брони
Выход стирает выбор номеров презентации
Номер в tel: URI звонка маскируется
Монитор здоровья ИИ не стучится в мёртвый адрес
Модели узла знают свою роль
Своя команда находится по владельцу, права не уходят в FULL
Откат ИИ-поиска броней ищет текстом
Повторное «Применить рекомендуемые» спрашивает про дорогую модель
«Настройка ИИ» говорит правду о раскладке
Улучшения
Батарея больше не красит карточку готовности
版本 1.2610.4391
Новое
Пир спрашивает перед перезаписью данных БС
🛡️ «Шаблон»/«Заменить БД» чужого бэкапа на пире команды — отдельный вопрос, главная кнопка «Отмена» (вариант B владельца)
🔄 Роль читается в момент показа диалога, неизвестная — как пир; тексты про перезапись и «только локально» исправлены
Исправления
Сброс пароля и сосед при лимите и пустом ответе объясняют причину
🛠️ Общий `httpFailureText` для экранов мимо репозитория: пустое тело и `"error":""` → запасной текст, 429 → «подождите», HTML прокси и длинное тело не показываются
Регистрация при лимите и пустом ответе объясняет причину
💬 Пустое «Ошибка: » заменено строкой «Слишком много попыток… подождите несколько минут» (ru/en)
«Всё равно оформи» в голосе не теряет контекст
💬 Короткий ответ с «всё равно/всё-таки» — уточнение с историей
«Речь не найдена» словами при пустом ответе узла
💬 (Часть: текст отказа; след на строке — остаток)
Team Sync снова видит свою команду (, владелец)
🧠 Своя команда — по своему id или по владельцу; строка лечится heartbeat-ом, в т.ч. после импорта снимка
🧼 «Принять без настройки» убрана по решению владельца
«Номер снят с продажи» в ИИ-чате звучит вопросом
💬 Room_inactive: причина и варианты вместо «Повторите запрос»
Отказ виден внутри окна формы и диалога выбора
🪟 (Возврат ретеста №368)
«Сосед #N» в расчётах на языке приложения
🌍 Data-слой больше не подставляет русскую заглушку имени, экраны берут ресурс
Локализованный текст больше не замерзает на старте процесса
🌍 Поколение локали LanguageManager.localeEpoch сбрасывает кэши локализованного текста (Application, индекс поиска настроек)
🔗 (Фикс №364 охота, мерж по решению владельца — №367 разбор)
Шторка загрузки: фаза словами, честная скорость, «Отменить»
«О приложении»: перенос строк, честная «Проверить снова», живая карточка обновлений
Отчёт импорта говорит правду о потерях
📋 Итог предпросмотра (снесено/откатано) и строка о командной сверке в отчёте после импорта
Восстановленный пир ждёт базовую станцию
🛡️ После своего restore не-БС пир 10 мин не пушит всю базу на hash_mismatch(BASE_STATION) и не копит серию convergence-guard
Отказ фичи виден человеку, а не только журналу
🚨 Девять мест во ViewModel, где спиннер гас молча, теперь говорят отказ оверлеем на языке приложения
🧾 Журнал не тронут: английская трасса цены и записи моделей провайдера на месте
🧷 Семь законных фоновых мест объявлены маркером в коде, планка класса _tools/kt-refusal-swallowed-check.py: 16 → 0
Лимит частоты больше не разлогинивает ()
🚨 429/408 на refresh → Failed.Network: сессия и данные объекта целы
版本 1.2610.4343
Новое
«Быстрая продажа» в меню карточки гостя
Исправления
Отказ use case показывается текстом языка приложения
Непарная скобка в регэкспе больше не роняет ИИ-чат ()
🚨 `CustomApiDefaults`: `\}\}` вместо голой `}}` — ICU на аппарате больше не бросает PatternSyntaxException в <clinit>, Custom-провайдер и чат на профиле узла живы
💬 Краш уже в prod (19c9164f4) — релиз за владельцем
Журнал не подставляет русский e.message своих исключений
Плеер объясняет отказ, лечилка путей фото, список исчезающих строк
🔊🩹🔍 Остатки зоны бэкапов (,)
Одна точка в откате, честная пятёрка устройств
✏️ «Неполный откат» склеивается без двойной точки
📊 Отчёт ФЗ-374 берёт пять устройств по трафику, затем времени и MAC
💬 Сдача фоновой смены №298, влита живой сессией
После сброса нет второго главного
🛡️ Авто-создание команды не делает аппарат вторым главным, если своё главное видно в discovery (сырой id и mDNS-хеш)
📢 Отказ виден баннером экрана; развилка B/C ждёт владельца в
💬 Сдача фоновой смены №297, влита живой сессией
Адрес роутера стирается, Custom шлёт тело
🧹 Сохранённый адрес роутера можно стереть: «Сохранить» активна по несохранённым изменениям, мониторинг отвязывается
📨 Пресет Custom без шаблона шлёт OpenAI-совместимое тело с экранированным промптом
💬 Сдача фоновой смены №295, влита живой сессией
«Включить ИИ» выдаёт согласия и на голос
🎙️ Включение встроенного ИИ выдаёт все три облачных согласия (LLM, ASR, TTS) одним списком
🔐 Гейт диалога требует все три, а не только LLM
💬 Сдача фоновой смены №289, влита живой сессией
Перетаскивание кнопки-столбика долгим тапом
🛠️ Fix/fab-drag-stale-offset: жест больше не замыкает устаревшее смещение
📒 Backup.log всегда, с ротацией и без ПДн; «Поделиться журналом операций» на «Обслуживание БД» ()
Исправления
Импорт бэкапа из другой сборки переносит пути медиа в свой filesDir
🎧 Записи звонков и фото номеров из архива беты живые в релизе ()
🩹 Уже импортированные записи лечатся сами при старте и раз в 6 ч
Сброс Team Account выходит из команды на сервере
🚪 «Сбросить Team Account» сначала говорит серверу `leave-team`; нет связи — сброс не выполняется и об этом сказано
🛡️ Запоздавший ответ heartbeat'а не воскрешает команду, членство и роль БС (гейт по ключу команды)
🔁 Выбор роли возвращает в команду (`rejoin-team`) и пишет ключ — синк поднимается без перелогина
版本 1.2609.4212
Новое
Мастер ИИ без дорогой модели
Свои Wi-Fi-учётки спутникам брони
🎉 При заселении каждый спутник брони получает персональную учётку Wi-Fi (решение владельца: всем спутникам при заселении)
🔐 Жизненный цикл как у основного гостя: продление, выезд, отмена; открепление от заселённой брони — отложенное снятие без блокировки повторной выдачи
🧠 Воркер роутера видит спутников в пяти запросах «активной брони»: учётка не сносится как «грант без срока», журнал ФЗ-374 и «Активные» знают номер спутника
📶 Диалог заселения со всеми парами логин/пароль (и с календаря), «Wi-Fi спутников» в карточке брони с SMS на телефон спутника
🏨 Монитор считает устройства спутников в номере; дельта booking_guests будит воркер БС
🎉 К брони прикрепляются гости-спутники: блок «Сопровождающие» внизу карточки гостя формы — поиск по имени и телефону, создание нового гостя с предзаполнением, «−» с «Отменить»
🔎 Бронь находится по любому своему гостю: список броней, глобальный поиск, профиль («Спутником: N»), календарь «Фамилия +N», чипы в карточке и диалоге брони
🗄️ Синкуемая таблица booking_guests (миграция 32→33, детерминированный uuid пары, 7 реестров синка, пустая таблица не рвёт отпечаток со старыми сборками)
🛡️ Форма брони больше не перечитывает бронь при возврате с другого экрана и не теряет спутников молча на «Назад»
🚧 Вне цикла: Wi-Fi-учётки спутникам (multi-guests-wifi), смена основного гостя, split-folio, ИИ-инструменты
Один платёж — несколько броней (вариант A) влит в ствол
🧱 Payments.receipt_group_uuid + миграция v31→v32: доли одного перевода делят общий ключ
🎉 Экран «Оплата за несколько броней» из меню гостя, из брони и из карточки предоплаты: по долгам, поровну, остаток — аванс гостя
🧾 Карточка платежа показывает гостя и состав поступления, аннулирует долю или всё поступление; правка платежа без брони больше не тупик
🤖 ИИ: register_payment с allocations и авторазнесением при точном совпадении с долгами, новый allocate_payment для уже записанной предоплаты
📊 Выручка, статистика и метрики считают поступление одной транзакцией; удалённые платежи больше не попадают в выручку и поиск ИИ
🛡️ Полный ci-check локально и на сервере зелёный: 11 217 тестов, 16 гардов; ревью кода, синка и регрессий закрыты
🧮 JournalEnglishTraceRatchetTest считает три рода дверей; TAG_FORM_RUSSIAN_MAX=6 — видимый долг, наряд взят №239
Номер брони в имени гостя отбивается до карточки
🎯 Guest_name из номера или кода брони — отказ с подсказкой про booking_id (платёж и скидка)
🤫 Молчим при известной брони, guest_id или guest_phone; ноль номером не считаем
🟢 Полный прогон 11460/0, семь зондов красные
Код брони доходит до инструмента
🎯 Строка-код в booking_id любого инструмента → число единственной брони (за барьерами реестра, до проверки аргументов)
🛡️ Неоднозначный или неизвестный код — отказ; номера парами «#id (код …)» для HumanBookingRefs
🟢 Полный прогон 11453/0, семь зондов красные
Отказ по Wi-Fi виден
Служба станции уходит с ролью
📡 Симптом 1 (№239 ремонт)
Сотрудник в задаче уборки
Пустые замеры сводки не нули
Ручная цена не выключает сборы
Один звонок, одна запись
Форма не подменяет взрослых
Выход доводится до конца
Черновик брони сверяет id с базой
Оверлей закрывается на отбое
Фоновая публикация без модалки тарифа
Маркер схемы БД в манифесте
Отказ и «не спрашивали» больше не пустота
Бронь, названная кодом, доходит до брони
Владение ценой оператора на обоих уровнях
🎯 Класс три брата (чип ноги, первая нога, посев серии)
Файл и строка звонка уходят вместе
🎯 Класс 2 → 0, `performCleanup` и `deleteCall`
Модуль звонков пробрасывает отмену
🎯 Класс 146 → 0, гейт стережёт `presentation/call` с потолком 0
🛠️ Попутно — ствол снова зелёный: `ExportWorkPickTest` на общем вырезателе комментариев
Денежные суммы календаря режутся под потолок SQLite
🚨 Календарь отдавал все брони окна (до ±180 дней) в `IN (:bookingIds)` одним списком — на Android 11 при тысяче броней `too many SQL variables` вместо чипов «Долг»/«Оплачено»
🧠 Нарезка живёт в реализациях репозиториев (`queryInChunks`, пачки по 900): защищены все вызывающие `getPaidSumsByBookingIds`/`getInvoiceNetSumsByBookingIds`, а не только календарь; строка результата обоих запросов — один `booking_id` (`GROUP BY`), склейка точная
Экран обслуживания БД не рапортует чужой экспорт
🚨 Подписка на `full_backup_export` падала на `infos.lastOrNull()` и при каждом входе выдавала вчерашний `SUCCEEDED` за свежий — снекбар «Full Backup экспортирован» без единого нажатия, ровно там, куда заходят за копией перед необратимой операцией
🧠 Выбор записи вынесен в `pickReportableExport`: своя работа, незавершённая либо та, что экран видел идущей; чужой завершённый прогон — никогда
🔐 Итог настоящей работы доезжает и тогда, когда `KEEP` отбросил повторный запуск и `trackedExportWorkId` указывает в пустоту (`seenUnfinishedExportIds`); `trackedExportWorkId` — `@Volatile`, его пишут с IO
版本 1.2609.4081
Исправления
Одна таблица подписей оплаты и закрытая партия дефолтов
🌍 Строка «Method» карточки ИИ и семь дефолтов-подписей компонентов больше не показывают русский текст на en-US
🔴 Видимый РУССКИЙ текст карточки изменился для CARD и ONLINE — осознанно, чтобы не заводить шестую таблицу того же enum (подробности в теле фикса)
🛡️ Новый гард «одна таблица подписей», четыре бара с зондами; охват и имя теста приведены к факту по находке ревью
📉 `CyrillicDefaultParamMax` 10 → 3: остаток — данные тенанта, разобран построчно в baseline
🎯 Три пары разных статусов печатались одним словом, теперь таблица одна и все девять различимы
🔐 Побочный регресс защиты от выдумок модели найден ревью и закрыт разведением стороны данных и стороны обвинения; словарь вынесен в свой файл, god-файл стал короче
👀 Три круга ревью, каждый нашёл настоящее; по третьему выводу не согласился и снял вопрос замером
Карточка подтверждения говорит на языке интерфейса
👀 Ревью: сверка всех 17 превью с шаблонами построчно, русский текст дословно прежний; развёл имя-близнец маппера уборки по замечанию ревьюера
🚨 Рядом с честным `QUOTA_EXCEEDED` печаталась строка «first device» — диагноз, обратный происходящему; именно на ней разбор боевого отказа 2026-09-22 ушёл не туда
🧠 Отказ теперь логируется своей веткой с типизированной причиной
💬 Планки нет намеренно: правка меняет ТОЛЬКО диагностическую строку, наблюдаемую лишь в логе; оракул ретеста — logcat при живом отказе по квоте, он расписан в карточке
Отказ приходит ДО смены роли, гард боевых аппаратов выровнен
🚨 Сухой прогон переноса роли БС разбирает конверт настроек: приёмник отказывает на шаге проверки, а не после того, как роль уже уехала на сервер и отменять нечего
🎉 Отдельный код `CONFIG_REJECTED` — отказ больше не утверждает «роль сменилась» там, где она не менялась
🔐 `VerifyLiveDeviceAgents` сторожит троих боевых: добавлен rmx3709 (несёт станцию, в гарде его не было вовсе), убран A5010 (владелец вывел в стендовые 2026-09-22)
📦 Карточка `oneplus5t-tester` — стендовый актор с рутом; заведена `rmx3709-tester` (только чтение)
Подписи ролей и режимов переводятся
🌍 Три энама получили `displayNameRes`; чипы ролей, режим синхронизации и состояние ASR-модели больше не остаются русскими на английском интерфейсе
🧾 Готовая русская строка сохранена отчётам и сообщениям об отказе доступа
🚨 Передача роли базовой станции срывалась на шаге 4 из 7: приёмник не подтверждал нулевую часть, и экран винил в этом «повреждение данных»
🧠 Причина — гонка: оба конца peer-канала отдавали КАЖДЫЙ кадр своей корутине, манифест и часть уезжали врозь, часть читала запись сессии до сохранения манифеста и отбрасывалась молча
📦 Кадр соединения теперь кладётся в его очередь, которую разбирает ровно одна корутина; очередь без предела, чтобы цикл кадров не голодал и pong Ktor разбирался вовремя
🔐 Часть без манифеста получает отказ вместо тишины — страховка на любую перестановку кадров
🧭 Открытое место мастера перестало держаться за мёртвую сессию: решение вынесено чистой функцией, поле сведено к одному замку
💬 Диагноз на экране больше не врёт: «не подтвердили» отделено от «повредилось», а страховая копия называет виноватое устройство
🔍 Отказ отправки поднят с d на w — в релизе R8 вырезает d, и потерянный кадр не оставлял следа вообще
🧾 Шесть новых планок, одиннадцать зондов, два прохода ревью (второй нашёл дыру в самом лекарстве)
✅ Полный ci-check зелёный: 13 гардов и весь набор юнит-тестов
Журнал заговорил на языке интерфейса
🎉 20 записей журнала (пул уборки в карточке комнаты, отмена изменений, календарь цен) уехали в ресурсы
🧠 Закрыта непрозрачная дверь в `UndoViewModel` — упали ОБА потолка ратчета: 120 → 100 и 59 → 58
📦 Подписи полей аудита сведены в один `AuditFieldLabels.kt`: экран и журнал больше не расходятся
🔬 Планка локали среза (6 проверок) и три зонда по одному ограничению на мутанта
🎉 Строка журнала подтягивает остальные номера того же контакта из книги Android
🎯 Гость отдаёт ВСЕ свои телефоны с подписями типа, а не два поля из строки
🚨 Выдача поиска в ветке «звонков по запросу нет» получила свайп — раньше его там не было вовсе
🧼 Строка выдачи определена один раз на обе ветки; `PHONE_CONTACT_TYPES` стал каноном
🎨 Подложка карточки — как у панели долгого тапа (surface 0.95, скругление 20)
💾 Проверено на realme Ultra: контакт с двумя номерами, гость с подписью «Мобильный», оба направления
🧾 10998 юнит-тестов и 14 гейтов зелёные; гард отправляемого текста починен по дороге
Fix/i18n-journal-call-history → beta
🌍 История звонков и обратная связь: 14 записей, остаток presentation 134 → 120
🔴 Русский фолбэк внутри интерполяции вынесен своим ключом
🔬 Первый ключ с ДВУМЯ точками вызова — и планка это сторожит числом, а не фактом
Fix/i18n-journal-room-edit → beta
🌍 Журнал карточки номера следует за языком интерфейса: 8 записей, остаток presentation 142 → 134
🛠️ Отказ удаления номера перестал печатать сырую русскую строку домена — нарушался записанный контракт `RoomHasBookingsException`
🔬 Зондом доказана третья слепая зона: русский, доезжающий АРГУМЕНТОМ, невидим всем десяти планкам программы. Названа в KDoc ратчета, заведена карточкой класса
Улучшения
В списке номеров остались только номера
🧼 Подсказка «Выберите номер» снята: карточка поверх затемнённого списка и так очевидна
🎯 Номера стали ближе к пальцу — меньше ход до нужной строки
💾 Проверено на realme Ultra: и один номер, и два, оба направления
版本 1.2609.4025
Исправления
Fix/i18n-journal-ai-models → beta
🌍 Журнал настроек AI-моделей следует за языком интерфейса: 11 записей, остаток программы по presentation 152 → 142
🧹 Слепая зона `OPAQUE_MAX` впервые уменьшилась: 60 → 59
🔬 Три мутанта, три целевые планки красные, остальные и ратчет зелёные
Улучшения
🔧 Свели prod обратно на линию беты — без форса и без правки защит
📦 Влили `origin/prod` в ствол обратным мержем: содержимого он не несёт, деревья четырёх релиз-мержей идентичны их бета-родителям
🧼 После этого `prod` перематывается на бету обычным пушем, и гард «релиз обязан быть перемоткой» снова выполним
🛡️ Понадобилось потому, что четыре релиза подряд (#347–#350) сделаны мерж-коммитами, и ветки разошлись: перематывать было нечего
💾 Форс-пуш и снятие защиты с `prod` не потребовались