Teach · документ требованийTeach · requirements document

Функциональные требования мобильного репетитора TeachFunctional requirements for the Teach mobile tutor

Что должна делать система, чтобы работал метод «объяснение → практика без подсказок → разбор → повторы»: по экранам, по сущностям и по серверной генерации. Статусы отражают состояние сборки 0.1.0 (30) в TestFlight и сервера на Fly.io.What the system must do for the method “explanation → practice without hints → recap → reviews” to work: by screen, by entity and by server-side generation. Statuses reflect build 0.1.0 (30) in TestFlight and the server on Fly.io.

ВерсияVersion
1.24 · 2 ноября 20261.24 · 2 November 2026
КлиентClient
React Native · Expo SDK 57, iOS-first, Android той же кодовой базойReact Native · Expo SDK 57, iOS-first, Android from the same codebase
СерверServer
.NET 10, SQLite с копией в Tigris; модели по ролям через OpenRouter (SR-17).NET 10, SQLite with a copy in Tigris; per-role models via OpenRouter (SR-17)
ИсточникиSources
DESIGN.md, TEACH-MOBILE-BRIEF.md, docs/ai-content.md, docs/superpowers/specs/2026-10-06-native-ios-redesign-design.md
РеализованоDoneработает в текущей сборкеworks in the current build ЧастичноPartialесть ограничения, описаны в строкеhas limitations, described in the row ПланPlannedне начатоnot started
1

Назначение и границыPurpose and scope

Teach — мобильный репетитор по любой теме, не только по языкам. Пользователь формулирует, что и зачем хочет освоить; система строит короткие уроки на источниках, проверяет практикой без подсказок, превращает ошибки в записи и возвращает их как карточки повторов. Аудитория первой версии — автор и команда, монетизация вне рассмотрения.Teach is a mobile tutor for any topic, not only languages. The user states what they want to learn and why. The system builds short lessons from sources, tests with practice without hints, turns mistakes into records and brings them back as review cards. The audience of the first version is the author and the team; monetization is out of scope.

В границахIn scope

  • Вход через Apple, локальный профиль настроек.Sign-in with Apple, local settings profile.
  • Создание предмета: тема, сужение, миссия, источники, план.Creating a subject: topic, narrowing, mission, sources, plan.
  • Уроки из фиксированного набора блоков, сессия на телефоне, разбор.Lessons from a fixed set of blocks, a session on the phone, a recap.
  • Повторы по FSRS с прогнозом нагрузки и режимом запоминания, справочники, голосовой ввод ответов.Reviews on FSRS with a load forecast and a recall mode, references, voice input for answers.
  • Виджет iOS на главном экране и экране блокировки.iOS widget on the Home Screen and the Lock Screen.
  • Серверная генерация уроков, справочников и оценка свободных ответов.Server-side generation of lessons and references, and grading of free-form answers.

Вне границ первой версииOut of scope for the first version

  • Речевые модели voice-to-voice и собственный синтез речи: разговор с бадди (FR-66) строится на платформенном распознавании и системной озвучке, голос через модель не проходит.Voice-to-voice speech models and custom speech synthesis: buddy talk (FR-66) is built on platform speech recognition and system text-to-speech; voice never passes through the model.
  • Сообщества и внешние площадки практики (бриф §2.10).Communities and external practice venues (brief §2.10).
  • Командная аналитика, экспорт данных, оплата.Team analytics, data export, payments.
  • Веб-версия: web используется только для превью разработчика.Web version: web is used only for the developer preview.
2

Метод как источник требованийThe method as a source of requirements

Принципы из брифа §2, которые напрямую диктуют поведение интерфейса. Каждый принцип ниже имеет требования, ссылающиеся на него.Principles from brief §2 that directly drive interface behavior. Each principle below has requirements that refer to it.

ПринципPrincipleЧто это значит для продуктаWhat it means for the product
M-1Миссия — якорь.The mission is the anchor.Каждый урок отвечает, зачем он, ссылкой на миссию; миссия версионируется, история не удаляется. План версионируется так же: каждая версия с автором, причиной и «почему» (FR-33).Each lesson says why it matters by referring to the mission; the mission is versioned, its history is never deleted. The plan is versioned the same way: every version has an author, a reason and a “why” (FR-33).
M-2Знания из источников.Knowledge comes from sources.Уроки строятся на найденных материалах с уровнем доверия, у объяснения есть источник.Lessons are built on found materials with a trust level; every explanation has a source.
M-3Знание лёгкое, навык трудный.Knowledge is easy, skill is hard.Объяснение мягкое, практика без подсказок, разбор только после попытки.The explanation is gentle, practice has no hints, the recap opens only after an attempt.
M-4Ошибки — память системы.Mistakes are the system's memory.Каждая практика создаёт запись об усвоенном; из записей считаются повторы, следующий урок и пометки в справочниках.Every practice creates a learning record; reviews, the next lesson and marks in references are computed from records.
M-5Урок — одна победа.One lesson, one win.Одна цель, один цикл практики, жёсткий бюджет длины.One goal, one practice cycle, a strict length budget.
M-6Зона ближайшего развития.Zone of proximal development.Следующий шаг и этап плана выбираются по записям, не по самооценке и не по номеру урока.The next step and the plan stage are chosen from records, not from self-assessment and not by lesson number.
M-7Справочники живут дольше уроков.References outlive lessons.Сжатая суть конденсируется из уроков и доступна офлайн.The condensed gist is distilled from lessons and is available offline.
3

Роли и сущностиRoles and entities

Одна роль — ученик. Тестировщик и автор пользуются тем же интерфейсом. Сущности повторяют модель данных брифа §5.3.There is one role: the learner. Testers and the author use the same interface. The entities follow the data model in brief §5.3.

СущностьEntityСодержаниеContentsГде живётWhere it lives
SubjectТема, короткое имя, фокус, язык предмета, источники, план, текущий этапTopic, short name, focus, subject language, sources, plan, current stageклиент (SQLite) + серверclient (SQLite) + server
MissionТекущая формулировка и история версийCurrent wording and version historyклиент, копия на сервере (FR-44)client, a copy on the server (FR-44)
LessonШаги explain / choice / input / order / free с записями recTitle и recNoteSteps explain / choice / input / order / free with recTitle and recNote recordsсервер, копия в клиентеserver, copy on the client
LearningRecordЧто оказалось неочевидным, результат, номер урока, этапWhat turned out non-obvious, result, lesson number, stageсервер + карточки в клиентеserver + cards on the client
ReviewItemКарточка повтора с состоянием FSRS и журналом ответовReview card with FSRS state and answer logклиент, копия на сервере (FR-44)client, a copy on the server (FR-44)
ReferenceСправочник: группа, название, строки «термин | описание», пометка ошибкиReference: group, title, “term | description” rows, mistake markклиент, глоссарий с сервераclient, glossary from the server
SettingsЯзык, тема, напоминания, лимит повторов, режим записи; настройки предметаLanguage, theme, reminders, review cap, recording mode; subject settingsклиент, копия на сервере (FR-44)client, a copy on the server (FR-44)
4

Вход и профильSign-in and profile

IDТребованиеRequirementСтатусStatus
FR-00Интро при первом входеIntro on first launchЧетыре экрана про метод: репетитор по любой теме, урок — одна победа, повторы и справочники, голос. Показывается один раз, затем открывается мастер первого предмета, потому что в системе ещё ничего нет.Four screens about the method: a tutor for any topic, one lesson is one win, reviews and references, voice. Shown once; then the wizard for the first subject opens, because the system has nothing in it yet.QA: A-02, A-03РеализованоDone
FR-01Вход через AppleSign in with AppleЭкран входа: знак, слоган, кнопка «Продолжить с Apple». Имя из первого входа запоминается, потому что Apple отдаёт его один раз.Sign-in screen: logo, tagline, “Continue with Apple” button. The name from the first sign-in is stored, because Apple returns it only once.QA: A-01РеализованоDone
FR-02Вход через GoogleSign in with GoogleКнопка показывается только при настроенных client id; без них скрыта в релизной сборке.The button is shown only when client ids are configured; without them it is hidden in the release build.QA: нет кейсаQA: no caseЧастичноPartial
FR-03Выход сбрасывает только токенSign-out clears only the tokenЛокальная БД привязана к id аккаунта и остаётся (копия данных лежит и на сервере, FR-44); при повторном входе всё на месте. Двухшаговое подтверждение.The local DB is bound to the account id and stays (a copy of the data is also kept on the server, FR-44); on the next sign-in everything is in place. Two-step confirmation.QA: A-04РеализованоDone
FR-04ПрофильProfileСистемная форма iOS (с v1.18): аккаунт с числами «за месяц» и «сегодня» из журнала ответов; группы Напоминания, Повторы и голос, Приложение; «Выйти» — через системное окно подтверждения. Никакой геймификации.A native iOS form (since v1.18): the account with “this month” and “today” counts from the answer log; groups Reminders, Reviews and voice, App; “Sign out” goes through a system confirmation dialog. No gamification.QA: K-06РеализованоDone
FR-05Язык интерфейса ru/enInterface language ru/enМгновенная смена всех строк UI; контент уроков не переводится, а метки, которые сервер пишет в урок («Урок N ·», «этап 0N ·», «миссия ·», «Глоссарий»), клиент показывает на языке интерфейса; строки помещаются в одну строку на 390px.All UI strings switch instantly; lesson content is not translated, while the labels the server writes into a lesson («Урок N ·», «этап 0N ·», «миссия ·», «Глоссарий») are shown by the client in the interface language; strings fit in one line at 390px.QA: K-01РеализованоDone
FR-06Тема: системная, светлая, тёмнаяTheme: system, light, darkВыбор в профиле: «Системная» (по умолчанию), «Светлая», «Тёмная». Выбранная тема действует и на системные таб-бар, шапки и листы.Chosen in the profile: “System” (default), “Light”, “Dark”. The chosen theme also applies to the system tab bar, headers and sheets.QA: K-02РеализованоDone
FR-07НапоминанияRemindersЕжедневное локальное уведомление: утро 9:00, вечер 19:00; «тихие выходные» оставляют будни. Выключатель «Напоминания» в Профиле (по умолчанию включён) снимает расписание и прячет «Когда» и «Тихие выходные»; положение выключателя сохраняется в аккаунте и переезжает на новый телефон. Разрешение спрашивается при включении, расписание перестраивается при смене настроек, выход его снимает. Работает офлайн, сервер не участвует.A daily local notification: morning 9:00, evening 19:00; “Quiet weekends” keeps weekdays only. The “Reminders” switch in Profile (on by default) removes the schedule and hides “When” and “Quiet weekends”; its position is saved with the account and moves to a new phone. Permission is requested when reminders are turned on, the schedule is rebuilt when settings change, and sign-out removes it. Works offline; the server is not involved.QA: K-07РеализованоDone
FR-08Подсказка о новой сборкеNew build promptПри запуске на iOS клиент спрашивает сервер о последней выложенной сборке (On launch on iOS the client asks the server for the latest published build (GET /app/latest) и, если она новее установленной, показывает на «Сегодня» карточку «Есть сборка N» с кнопкой в TestFlight; крестик прячет её до следующего запуска. Без сети и на последней сборке карточки нет. Номер задаётся после выгрузки командой). If it is newer than the installed one, “Today” shows a “Build N is out” card with a button to TestFlight; the close button hides it until the next launch. Offline or on the latest build there is no card. After the upload the number is set with scripts/release-ios.sh N --set-latest или в разделе «Выпуск» админки (FR-75.6) и действует без рестарта сервера; пока номера в базе нет, берётсяor in the console «Выпуск» (Release) section (FR-75.6) and takes effect without a server restart; while the database has no number, Teach__App__LatestIosBuild из конфигурации.from the configuration is used.QA: B-06, K-05, O-08РеализованоDone
FR-74Восстановление на новом телефонеRestore on a new phoneПри первом входе на новом телефоне (в аккаунте нет своих предметов и ответов) до интро показывается экран «Восстанавливаю ваши предметы…», и приложение собирает с сервера предметы с планом, текущие уроки и справочники, карточки повторов с прежним расписанием, всю историю ответов, включая ответы удалённых предметов (числа «за месяц» и «сегодня» те же, что на старом телефоне; прогноз нагрузки), по предметам — режим запоминания, длительность урока, миссию с историей и язык предмета, затем настройки приложения (язык интерфейса, тема, напоминания, лимит в день, режим записи), позицию в демо и удалённые демо. Удалённые предметы не возвращаются. Предметы, созданные до входа по Apple (до 11 сентября 2026), возвращаются, если старый телефон с синхронизацией успел отправить их в состоянии аккаунта. Без сети или при сбое сервера экран «Не удалось связаться с сервером» предлагает «Повторить» и «Начать заново»; «Начать заново» открывает обычный первый вход; копия на сервере остаётся прежней, пока на этом телефоне не изменены настройки или предметы, а после первого такого изменения состояние аккаунта с телефона заменяет серверное (побеждает более новое). Не переносятся прерванная сессия урока, отметки «Пройдено сегодня», строка «за неделю: N ошибок закрыто · K темы окрепли» на «Сегодня» (она появится после следующего урока), итог последнего разговора, неотправленные записи и разговоры старого телефона. Если старый телефон не запускал сборку с синхронизацией, вернутся свои предметы, уроки и справочники (они уже на сервере), но не карточки, ответы и предметы, созданные до входа по Apple.On the first sign-in on a new phone (the account has no own subjects and no answers) the “Restoring your subjects…” screen is shown before the intro, and the app collects from the server the subjects with their plans, current lessons and references, review cards with their old schedule, the whole answer history, answers of deleted subjects included (the “this month” and “today” numbers are the same as on the old phone; the load forecast), per subject the recall mode, lesson length, the mission with its history and the subject language, then the app settings (interface language, theme, reminders, daily cap, recording mode), the demo position and removed demos. Deleted subjects do not come back. Subjects created before Apple sign-in (before 11 September 2026) come back if the old phone with sync managed to send them in the account state. Offline or when the server fails, the “Couldn't reach the server” screen offers “Try again” and “Start fresh”; “Start fresh” opens the usual first launch; the server copy stays as it was until settings or subjects are changed on this phone, and after the first such change the phone's account state replaces the server one (the newer wins). Not carried over: an interrupted lesson session, “Done today” marks, the “this week: N fixed · K topics stronger” line on “Today” (it appears again after the next lesson), the outcome of the last talk, and unsent records and talks of the old phone. If the old phone never ran a build with sync, the own subjects, lessons and references come back (they are already on the server), but not cards, answers and subjects created before Apple sign-in.QA: F-09, F-10, K-08, K-09РеализованоDone
5

Новый предметNew subject

Мастер из пяти шагов, создаётся с вкладки «Предметы». Каждый сетевой шаг показывает состояние загрузки и ошибку с повтором, кнопка «Дальше» ждёт данных.A five-step wizard, started from the “Subjects” tab. Each network step shows a loading state and an error with retry; the “Next” button waits for data.

01ТемаTopicсвободная формулировка, чипы-примерыfree-form wording, example chips
02СужениеNarrowingтри фокуса от модели или свойthree focus options from the model or your own
03МиссияMission«зачем», до 100 символов“why”, up to 100 characters
04ИсточникиSourcesчетыре с уровнем доверия, исключение тапомfour with a trust level, tap to exclude
05ПланPlanтри этапа, эхо миссииthree stages, mission echo
IDТребованиеRequirementСтатусStatus
FR-17Мастер из пяти шаговFive-step wizardТема → сужение → миссия → источники → план; счётчик 1/5…5/5 с полосой прогресса. «Дальше» неактивна, пока поле пустое или данные ещё грузятся; сетевой шаг показывает загрузку и ошибку с «Повторить». Крестик на любом шаге закрывает мастер, предмет не создаётся. Подпись шага «План»: план пересматривается, когда закрывается этап или меняется миссия; править его можно в любой момент (FR-33).Topic → narrowing → mission → sources → plan; a 1/5…5/5 counter with a progress bar. “Next” is disabled while the field is empty or data is still loading; a network step shows loading and an error with “Retry”. The close button on any step closes the wizard; no subject is created. The “Plan” step caption: the plan is revised when a stage closes or the mission changes; you can edit it at any time (FR-33).QA: C-01, C-02, C-03, C-06, C-08РеализованоDone
FR-10Короткое имя предметаShort subject nameИз формулировки темы сервер даёт имя в одно слово («Итальянский», «Выступления»); два коротких слова — только если одним не назвать. Имя идёт в строки и карточки предметов, чипы фильтра и название уроков, полная формулировка остаётся описанием. Название фокуса рядом с именем — не длиннее 30 символов.From the topic wording the server derives a one-word name (“Italian”, “Speaking”); two short words only if one word cannot name it. The name is used in subject rows and cards, filter chips and lesson titles; the full wording remains the description. The focus title next to the name is at most 30 characters.QA: C-07РеализованоDone
FR-11Язык предметаSubject languageОпределяется при создании по таблице из 20 языков: код для распознавания речи и локализованные имена ru/en.Determined at creation from a table of 20 languages: a code for speech recognition and localized ru/en names.QA: H-04РеализованоDone
FR-12Источники через поиск, не из памяти моделиSources from search, not from model memoryWeb search на сервере, уровень доверия высокое/среднее/низкое; выбор пользователя передаётся в генерацию. Поиск идёт фоновой задачей с опросом статуса (M-2).Web search on the server, trust level high/medium/low; the user's selection is passed to generation. The search runs as a background job with status polling (M-2).QA: C-04РеализованоDone
FR-13Первый урок готовится в фонеThe first lesson is prepared in the backgroundПосле «Готово» экран закрывается сразу; строка предмета на «Сегодня» проходит этапы «Ищу источники → Отбираю по доверию → Собираю первый урок», затем «Урок готов». Без спиннера. Следующие уроки этапов поиска не показывают: сразу «Собираю урок N».After “Done” the screen closes at once; the subject row on “Today” goes through the stages “Finding sources → Filtering by trust → Building first lesson”, then “Lesson ready”. No spinner. Later lessons skip the search stages and go straight to “Building lesson N”.QA: B-03РеализованоDone
FR-14Первый урок — стартовая диагностикаThe first lesson is the Initial check-inКалибровка без правильного ответа (бейдж «ПРИНЯТО»), свободный рассказ, одна настоящая проверка по источнику без подготовки: над ней кикер «СТАРТ» с подписью «этому ещё не учили», в разборе она показана как «ТОЧКА ОТСЧЁТА», не как ошибка. Всё уходит в записи.Calibration without a correct answer (badge “ACCEPTED”), a free-form account, and one real check from the source without preparation: above it is the “BASELINE” kicker with the caption “Not taught yet”; in the recap it is shown as “STARTING POINT”, not as a mistake. Everything goes into records.QA: D-06, E-03РеализованоDone
FR-15Сбой генерации не блокируетA generation failure does not blockПредмет остаётся, строка предмета показывает «Не удалось собрать урок»; нажатие на строку повторяет подготовку; удалённый во время подготовки предмет не воскресает. Опрос терпит сбои сети и 5xx до трёх минут (деплой сервера), 4xx — ошибка сразу. «Повторить» после сбоя на сервере ставит урок в очередь заново — в том числе первый, у которого нет разбора; идущую подготовку повтор не дублирует.The subject stays; the subject row shows “Could not build the lesson”, and tapping the row retries the preparation; a subject deleted during preparation does not come back. Polling tolerates network failures and 5xx for up to three minutes (server deploy); a 4xx is an error at once. After a server-side failure, “Retry” queues the lesson again — including the first one, which has no recap; a preparation already in progress is not duplicated.QA: B-04, C-05, L-04РеализованоDone
FR-16Несколько предметовMultiple subjectsПредметов может быть сколько угодно: у каждого свой урок, состояние подготовки, прерванная сессия, повторы, справочники и настройки. Id выдаёт монотонный счётчик и не переиспользует после удаления; предмет со старой версии сохраняет свой id, поэтому его данные переживают обновление. У каждого предмета свой цвет из 12 приглушённых (демо — синий и оранжевый, новый получает первый свободный); его можно сменить в настройках предмета (сетка 6×2); цвет хранится в настройках предмета, поэтому удаление другого предмета его не меняет.There can be any number of subjects. Each has its own lesson, preparation state, interrupted session, reviews, references and settings. Ids come from a monotonic counter and are not reused after deletion; a subject from an older version keeps its id, so its data survives the update. Each subject has its own color out of 12 muted ones (the demos are blue and orange, a new one gets the first free color); it can be changed in subject settings (a 6×2 grid); the color is stored in the subject’s settings, so deleting another subject does not change it.QA: J-06РеализованоDone
6

Урок и разборLesson and recap

IDТребованиеRequirementСтатусStatus
FR-20Фиксированный набор блоковFixed set of blocksШаги explain, choice, input, order, free. Модель заполняет схему, а не изобретает разметку.Steps explain, choice, input, order, free. The model fills a schema; it does not invent markup.QA: D-01…D-05РеализованоDone
FR-21Объяснение мягкоеGentle explanationКикер «ЗАЧЕМ · миссия», заголовок, до двух абзацев, карточка «ПРИМЕР», источник; уровень доверия показывается только как предупреждение при среднем и низком (M-1, M-2, M-3).Kicker “WHY · mission”, a title, up to two paragraphs, an “EXAMPLE” card, a source; the trust level is shown only as a warning when it is medium or low (M-1, M-2, M-3).QA: D-01РеализованоDone
FR-22Практика без подсказокPractice without hintsРазбор открывается только после «Ответить»; выбор фиксируется, у верного варианта ✓ на зелёной подложке, у неверного ✕ на красной и короткое встряхивание (VoiceOver читает «ВЕРНО» / «ВАШ ВЫБОР»); разбор выезжает листом снизу с бадди и «Дальше», лист можно утянуть вниз за ручку — это то же, что «Дальше» (с v1.19); при ошибке ввода показывается «КАК ПРАВИЛЬНО» (M-3).The recap opens only after “Answer”; the choice is locked, the correct option shows ✓ on a green background, a wrong one ✕ on a red one with a short shake (VoiceOver reads “CORRECT” / “YOUR PICK”); the recap slides up as a sheet with the buddy and “Next” and can be dragged down by its grabber, which equals “Next” (since v1.19); after a wrong input “CORRECT ANSWER” is shown (M-3).QA: D-02, D-03, D-16РеализованоDone
FR-23Проверка ответов на устройствеAnswer checking on the deviceВыбор и порядок точно; ввод по группам синонимов; свободный ответ по ключевым словам критериев. Немедленно, без ожидания сети.Choice and order are checked exactly; input by synonym groups; a free-form answer by criteria keywords. Immediate, without waiting for the network.QA: D-02…D-05РеализованоDone
FR-24Оценка свободного ответа по смыслуFree-form answers graded by meaningСессия спрашивает сервер при ответе (потолок 4 с) и берёт его вердикт: «Vorrei un biglietto, gentilmente» засчитывается как вежливая просьба без ключевого «per favore». Таймаут, ошибка или офлайн — остаётся проверка по ключевым словам, сеть урок не задерживает.On an answer the session asks the server (4 s ceiling) and takes its verdict: “Vorrei un biglietto, gentilmente” counts as a polite request without the keyword “per favore”. On timeout, error or offline the keyword check stays; the network does not delay the lesson.QA: D-05РеализованоDone
FR-25РазборRecapВердикт «Чистая сессия / Есть что закрепить», «k из n с первой попытки», карточки «УЙДЁТ В ПОВТОРЫ» с интервалом из FSRS, источник, кнопка «Сомневаюсь» отмечает запись и снимается повторным нажатием (на сервер пока не уходит).Verdict “Clean session / Things to reinforce”, “k of n on first try”, “GOES TO REVIEWS” cards with an interval from FSRS, a source. The “Doubt this” button flags a record and a second tap clears the flag (not sent to the server yet).QA: E-01, E-02, E-04РеализованоDone
FR-26«Готово» замыкает цикл“Done” closes the loopЗаписи становятся карточками повторов, отметка «Пройдено сегодня», для пользовательского предмета записи уходят на сервер и запускают следующий урок; если заготовка подошла (FR-35), урок приходит сразу (M-4).Records become review cards and the “Done today” mark appears. For a user subject, records go to the server and start the next lesson; if the prefetch fits (FR-35), the lesson arrives at once (M-4).QA: E-05, E-06РеализованоDone
FR-29Прогресс внутри урока сохраняетсяProgress inside a lesson is savedКрестик на любом шаге сохраняет снимок сессии в предмете; следующее открытие того же урока продолжает с активного шага с ответами пройденных. Снимок удаляется после разбора и при новом уроке.The close button on any step saves a session snapshot in the subject; the next time the same lesson opens, it resumes from the active step with the answers of completed steps. The snapshot is deleted after the recap and when a new lesson arrives.QA: D-08РеализованоDone
FR-28Свайпы по шагамSwiping between stepsСвайп вправо показывает пройденные шаги с замороженным ответом и разбором, свайп влево — вперёд до активного; с неотвеченного шага вперёд нельзя, с отвеченного свайп равен «Дальше». На пройденном шаге ввод и микрофон отключены, кнопка «К текущему шагу» возвращает. В повторах то же.Swipe right shows completed steps with the frozen answer and recap; swipe left moves forward up to the active step. You cannot move forward from an unanswered step; on an answered step the swipe equals “Next”. On a completed step input and the microphone are disabled; the “Back to current step” button returns. The same applies in reviews.QA: D-07, D-09, D-10РеализованоDone
FR-27Выход крестикомExit with the close buttonИз сессии крестик сохраняет прогресс и возвращает на «Сегодня» (FR-29). Из разбора крестик равен «Готово»: ошибки уже случились и должны стать памятью системы, записи сохраняются и следующий урок запускается (M-4).In a session the close button saves progress and returns to “Today” (FR-29). In the recap the close button equals “Done”: the mistakes have already happened and must become the system's memory, so records are saved and the next lesson starts (M-4).QA: D-08, E-05РеализованоDone
FR-38Бадди в сессииBuddy in sessionДок над главной кнопкой: знак из четырёх точек и слово состояния — «Читайте», «Ваш ход», «Слушаю», «Читаю пример», «Думаю», реакции «Верно / Частично / Не совсем» и «Принято» для шагов без оценки (калибровка, промах на диагностике). Показывает, чья очередь, и реагирует на ответ один раз на шаг; уважает «Уменьшение движения», объявляется VoiceOver, лёгкая хаптика. Вне сессии не появляется.A dock above the main button: a four-dot mark and a state word — “Read on”, “Your turn”, “Listening”, “Reading the example”, “Thinking”, the reactions “Correct / Partly / Not quite”, and “Noted” for ungraded steps (calibration, a miss in the Initial check-in). It shows whose turn it is and reacts to an answer once per step; it respects “Reduce Motion”, is announced by VoiceOver and uses light haptics. It does not appear outside a session.QA: D-11…D-15РеализованоDone
7

Прогрессия и планProgression and plan

IDТребованиеRequirementСтатусStatus
FR-30Следующий урок по записямNext lesson from recordsПосле каждого разбора сервер генерирует урок N: закрыть самую свежую ошибку, не повторять верное; промпт получает этап плана явно, длительность из настроек предмета задаёт бюджет (M-6).After each recap the server generates lesson N: close the most recent mistake, do not repeat what was correct. The prompt receives the plan stage explicitly; the duration from subject settings sets the budget (M-6).QA: E-06, E-07РеализованоDone
FR-31Этап плана по результатамPlan stage from resultsЭтап закрывается, когда два последних урока этапа сделаны на ≥ 75 % и ≥ 60 % с первой попытки, диагностика не в счёт; страховка — после шести уроков этап закрывается в любом случае. Закрытие этапа — рубеж: план впереди пересматривается, закрытие последнего этапа его продолжает (FR-33).A stage closes when the last two lessons of the stage are done at ≥ 75 % and ≥ 60 % on first try; the Initial check-in does not count. As a safeguard, a stage closes after six lessons in any case. Closing a stage is a boundary: the plan ahead is revised, and closing the last stage extends it (FR-33).QA: E-08, E-09, E-10, E-11, E-12РеализованоDone
FR-32Индикатор этапаStage indicatorНа «Сегодня» в плитке «Следующий урок» — сегменты этапов и строка «Урок K · ~M мин · этап N из 3»; на «Предметах» — кольцо этапа в цвете предмета и «Этап N из 3 · название» (VoiceOver: «Этап N из 3»). Этап приходит с сервера.On Today the “Next lesson” tile shows stage segments and the line “Lesson K · ~M min · stage N of 3”; on Subjects a stage ring in the subject color and “Stage N of 3 · title” (VoiceOver: “Stage N of 3”). The stage comes from the server.QA: B-03, E-08РеализованоDone
FR-33Живой планLiving planПлан предмета живёт на сервере версиями. Когда этап закрывается (уверенно или по потолку уроков) или меняется миссия, отдельный вызов модели пересматривает этапы впереди: может переписать, добавить, убрать, переставить этапы, вставить этап-закрепление, дописать продолжение; пройденные этапы и текущий не меняются, закрытие последнего этапа продолжает план. Изменение применяется сразу, следующий урок собирается по нему; на «Сегодня» — «· план обновлён», на карточке цели — точка и одна фраза «почему», полный план — в листе «План» («Пройдено», «Сейчас» с подписью, когда этап закроется, «Впереди» с метками «новый» / «изменён»). Кольцо итога закрывает этап только тогда, когда его закроет сервер. Миссия, изменённая на телефоне, уходит на сервер (и без сети — при возврате сети). План правит и человек: в режиме правки листа («Изменить») — текст текущего этапа, этапы впереди (переписать, добавить, удалить, переставить, как в списках iOS); правка видна сразу, на сервер уходит через очередь и без сети — при возврате сети, затронутые этапы помечаются «ваш» и модель их не переписывает; если план успел измениться, правка не применяется и лист один раз просит внести её заново. «Этот этап я уже знаю — дальше» закрывает текущий этап: готовый урок уходит без записей, план пересматривается, следующий урок собирается по новому этапу (недоступно на диагностике и пока урок готовится). «Вернуть прежний план» отменяет последнее изменение моделью (вернувшиеся этапы — «ваши»). «История изменений» показывает версии плана с автором и причиной. «Дальше», возврат и история — только в сети; у демо правки нет.The subject plan lives on the server in versions. When a stage closes (with confidence or by the lesson cap) or the mission changes, a separate model call revises the stages ahead: it may rewrite, add, remove or reorder stages, insert a consolidation stage, or extend the plan; passed stages and the current one never change, and closing the last stage extends the plan. A change applies at once and the next lesson is built from it; “Today” shows “· plan updated”, the goal card shows a dot and a one-line “why”, and the full plan is in the “Plan” sheet (“Done”, “Now” with a caption on when the stage closes, “Ahead” with “new” / “changed” marks). The recap ring closes a stage only when the server will. A mission edited on the phone reaches the server (offline — once the network is back). The person edits the plan too: in the sheet’s edit mode (“Edit”) — the current stage’s text and the stages ahead (rewrite, add, delete, reorder, as in iOS lists); the edit shows at once and reaches the server through a queue, offline — once the network is back; touched stages are marked “yours” and the model does not rewrite them; if the plan changed in the meantime, the edit is not applied and the sheet asks once to make it again. “I already know this stage — next” closes the current stage: the ready lesson goes away without records, the plan is revised and the next lesson is built for the new stage (not available on the Initial check-in or while a lesson is being prepared). “Restore the previous plan” undoes the model’s last change (restored stages become “yours”). “Change history” lists plan versions with author and reason. “Next”, restore and history need a connection; the demo cannot be edited.QA: E-09, E-10, E-11, E-12, E-13, E-14, E-15, E-16, E-17, E-18, E-19, E-20, E-21, E-22, L-09, L-10, L-11РеализованоDone
FR-34Два демо-предметаTwo demo subjects«Английский» (собеседования, фокус «Рассказ о себе») и «Выступления» (миссия «уверенно выступить перед командой на 10 минут»). Сгенерированы живым сервером: источники, план на пять этапов, диагностика и цепочка уроков 2–6 с глоссарием; зашиты статично с меткой «демо». После разбора открывается следующий урок, этап плана сменяется после двух уверенных уроков, глоссарий пополняется; после урока 6 демо ведёт в мастер своего предмета. Карточки повторов и глоссарии засеваются один раз на аккаунт.“English” (job interviews, focus “Talking about yourself”) and “Speaking” (mission “speak confidently in front of the team for 10 minutes”). Generated by the live server: sources, a five-stage plan, an Initial check-in and a chain of lessons 2–6 with a glossary; embedded statically with a “demo” label. After the recap the next lesson opens, the plan stage changes after two confident lessons, and the glossary grows; after lesson 6 the demo leads into the wizard for your own subject. Review cards and glossaries are seeded once per account.QA: B-01РеализованоDone
FR-35Предзагрузка одного урока вперёдPrefetch one lesson aheadКогда открыт урок N, сервер заготавливает N+1 на текущем этапе по записям на этот момент. После разбора заготовка отдаётся сразу, если этап не сменился и верных ответов не меньше половины; иначе выбрасывается, и урок собирается заново по свежим записям. Дальше одного урока не генерируем: следующий шаг должен видеть последние ошибки (M-6).When lesson N is open, the server prefetches N+1 at the current stage from the records at that moment. After the recap the prefetched lesson is served at once if the stage has not changed and at least half of the answers are correct; otherwise it is discarded and the lesson is built again from fresh records. We do not generate more than one lesson ahead: the next step must see the latest mistakes (M-6).QA: E-06, E-07, L-02РеализованоDone
FR-37Подготовка предметов независимаSubjects are prepared independentlyНесколько предметов могут готовиться одновременно: этап и ошибка хранятся по предмету, сбой одного не помечает остальные. Вторая генерация того же предмета не запускается. Сбой первого урока после создания предмета на сервере повторяется на том же предмете: сервер ставит урок заново (или клиент дожидается уже идущей генерации), второй предмет не создаётся.Several subjects can be prepared at the same time: the stage and the error are stored per subject, and a failure in one does not mark the others. A second generation of the same subject does not start. If the first lesson fails after the subject is created on the server, the retry works on that same subject: the server queues the lesson again (or the client waits for the generation already running); no second subject is created.QA: B-07, L-04РеализованоDone
FR-36Возобновление после перезапускаResume after restartЕсли приложение закрыли, пока урок готовился, при запуске клиент продолжает ждать урок с сервера, не отправляя разбор повторно; строка предмета не зависает на «Готовится…».If the app was closed while a lesson was being prepared, on launch the client keeps waiting for the lesson from the server without resending the recap; the subject row does not get stuck on “Preparing…”.QA: K-03РеализованоDone
8

ПовторыReviews

IDТребованиеRequirementСтатусStatus
FR-40Сроками владеет алгоритмThe algorithm owns due datesFSRS без краткосрочных шагов: ошибка → 1 день, успех → 3 дня на новой карточке в режиме «Обычно» (FR-46), дальше интервал растёт. Модель к срокам не допускается, ручного редактирования нет.FSRS without short-term steps: mistake → 1 day, success → 3 days for a new card in “Normal” mode (FR-46); after that the interval grows. The model has no say in due dates; there is no manual editing.QA: F-03РеализованоDone
FR-41Одна учебная точка — одна карточкаOne learning point, one cardУчебная точка — шаг конкретного урока: пересдача того же урока пересчитывает срок карточки, шаг нового урока создаёт новую. Карточка хранит сам вопрос, поэтому повтор задаёт именно его, даже когда предмет ушёл к следующим урокам. Старые карточки своих предметов, записанные до этого, при запуске приложения находят свой урок в истории уроков на сервере по заголовку записи и получают сохранённый вопрос.A learning point is a step of a specific lesson: retaking the same lesson recalculates the card's due date, a step of a new lesson creates a new card. The card stores the question itself, so the review asks exactly that question even after the subject has moved on to later lessons. Older cards of user subjects, recorded before this change, find their lesson in the server lesson history by the record title at app launch and get the stored question.QA: F-02РеализованоDone
FR-42Экран «Повторы»“Reviews” screenКолода карточек на сегодня (свайп — просмотр без оценки); «Начать · N карточек» собирает сессию из вопросов, породивших карточки, с учётом лимита в день; список «Позже». Бейдж вкладки «Повторы» и блок повторов на «Сегодня» показывают число карточек на сегодня.A deck of today’s cards (swipe to preview, no grading); “Start · N cards” builds a session from the questions that produced the cards, within the daily cap; a “Later” list. The “Reviews” tab badge and the reviews block on “Today” show the number of cards due today.QA: B-02, F-01, F-02, F-04РеализованоDone
FR-43ОфлайнOfflineКарточки, журнал ответов и FSRS живут в SQLite на устройстве; сессия повторов не требует сети. Копия на сервере нужна для смены телефона (FR-44).Cards, the answer log and FSRS live in SQLite on the device; a review session needs no network. The server copy is for switching phones (FR-44).QA: F-07РеализованоDone
FR-44Синхронизация повторов с серверомReview sync with the serverТелефон в фоне отправляет на сервер карточки повторов, ответы с отметкой времени и состояние аккаунта (настройки приложения и предметов, позицию в демо); сервер хранит копию для смены телефона. Отправка идёт через 5 секунд после изменения, при запуске, при возврате в приложение и при уходе его в фон, по одной за раз; без сети или при сбое сервера данные остаются в очереди и уходят позже. Карточку решает более новое изменение, ответы только добавляются. Первый запуск сборки с синхронизацией выгружает всё, что уже есть на телефоне. Без входа в аккаунт (общий токен сборки) синхронизация выключена (SR-21): очередь, в том числе удаления предметов, ждёт токена аккаунта.The phone sends review cards, answers with a timestamp and the account state (app and subject settings, the demo position) to the server in the background; the server keeps a copy for switching phones. Sending starts 5 seconds after a change, at launch, when the app is brought back and when it goes to the background, one at a time; offline or when the server fails, the data stays queued and goes out later. The newer change wins for a card, answers are only appended. The first launch of a build with sync uploads everything already on the phone. Without an account sign-in (the shared build token) sync is off (SR-21): the queue, subject deletions included, waits for an account token.QA: F-08, F-09, L-06РеализованоDone
FR-45Прогноз нагрузкиLoad forecastПод кнопкой «Начать» на «Повторах» блок «НАГРУЗКА · 2 НЕДЕЛИ»: строка «~6 мин в день · пик — чт, ~11 мин» и 14 столбиков; сегодняшний — цветом акцента, остальные — стопкой цветов предметов (лимит дня режет предметы пропорционально). Пик не показывается, если совпадает со средним; при нулевой нагрузке строка «Повторов не ожидается». Расчёт детерминированный, на устройстве: каждая карточка идёт по FSRS с ответом «помню» до конца горизонта, после каждого показа на следующий день добавляется ожидаемая доля ошибок 1 − R; новые карточки добавляются по притоку предмета за последние 14 дней с его долей ошибок первого ответа, предмет на паузе притока не даёт. На «Все» действует лимит в день из профиля с переносом остатка, чип предмета считает только его карточки и без лимита. Минуты — по 30 с на карточку, как в блоке повторов на «Сегодня». Без карточек блока нет; интерактива нет, VoiceOver читает блок одной фразой.Under the “Start” button on “Reviews” there is a “LOAD · 2 WEEKS” block: the line “~6 min a day · peak Thu, ~11 min” and 14 bars; today’s bar is in the accent color, the others are stacks of subject colors (the daily cap cuts the subjects in proportion). The peak is hidden if it equals the average; with zero load the line reads “No reviews expected”. The calculation is deterministic and runs on the device: each card follows FSRS with a “recalled” answer to the end of the horizon, and after each showing the expected mistake share 1 − R is added to the next day. New cards are added from the subject's intake over the last 14 days with its first-answer mistake rate; a paused subject adds no intake. On “All” the daily cap from the profile applies and the remainder carries over; a subject chip counts only its own cards and has no cap. Minutes are 30 s per card, as in the reviews block on “Today”. Without cards there is no block; there is no interaction; VoiceOver reads the block as one phrase.QA: N-10, N-15РеализованоDone
FR-46Режим запоминанияRecall modeВ настройках предмета секция «Запоминание»: «Поддерживать», «Обычно», «Интенсивно» — цель FSRS 0,85 / 0,90 / 0,95. По умолчанию «Обычно», поэтому у обновившихся сроки не меняются. В каждой ячейке «~N мин» — прогноз нагрузки предмета после переключения (FR-45), под сегментом подсказка («≈ 9 из 10 вспомните к сроку повтора»); без карточек вместо минут «—» и «Нагрузка появится после первых уроков». Переключение без подтверждения сразу пересчитывает сроки карточек предмета от последнего ответа, журнал ответов не меняется; у недавних карточек (короткий интервал, до 9 дней в режиме «Интенсивно») срок может стать на 1–2 дня ближе исходного. Новые ответы планируются с целью своего предмета, в том числе в смешанной сессии «Все» и в подписи разбора «уйдёт в повторы через N дней». Пример: новая карточка, дважды подряд отвеченная верно в срок, вернётся через 31, 14 или 6 дней соответственно. Режим — параметр алгоритма, а не ручные сроки (FR-40, FR-73); ползунка цели нет.Subject settings have a “Recall” section: “Maintain”, “Normal”, “Intensive” — FSRS target 0.85 / 0.90 / 0.95. The default is “Normal”, so due dates do not change for users who update. Each cell shows “~N min” — the subject's load forecast after switching (FR-45); under the segment there is a hint (“You recall ≈ 9 of 10 on time”); without cards the cells show “—” instead of minutes, with “Load appears after the first lessons”. Switching needs no confirmation and immediately recalculates the due dates of the subject's cards from the last answer; the answer log does not change. For recent cards (short interval, up to 9 days in “Intensive” mode) the due date may move 1–2 days earlier than before. New answers are scheduled with the target of their own subject, including in a mixed “All” session and in the recap caption “GOES TO REVIEWS” with “in N days”. Example: a new card answered correctly on time twice in a row comes back in 31, 14 or 6 days respectively. The mode is an algorithm parameter, not manual due dates (FR-40, FR-73); there is no target slider.QA: J-04, N-11, N-12РеализованоDone
FR-47Виджет на главном экране и экране блокировкиWidget on the Home Screen and the Lock ScreenВиджет «Teach» для iOS. Главный экран: малый — «ПОВТОРЫ · СЕГОДНЯ», число карточек, минуты и подпись; средний — итог и до трёх предметов в порядке «Сегодня» (имя, «5 карт.», статус урока теми же словами, что в строке предмета на «Сегодня»; у предмета на паузе статуса нет), остальные — «+N». Экран блокировки: круглый (число карточек и короткая подпись), прямоугольный («Teach», итог, «Урок готов») и строчный виды, названий предметов там нет. Число совпадает с блоком повторов на «Сегодня»: приложение считает расписание на сейчас и 7 ближайших полуночей той же формулой и передаёт его виджету, поэтому число меняется в полночь без запуска приложения. Пустая очередь — «Всё повторено» и «Следующие — завтра, 5» или готовый урок; без предметов — «Создайте первый предмет»; после выхода — «Войдите в Teach». Тап открывает по ссылке teach:// «Повторы» (строка предмета — с выбранным чипом этого предмета), «Сегодня» или «Предметы». Статус урока обновляется, пока открыто приложение (push — SR-09). Без кнопок, колец, стриков и процентов. Проверено на симуляторе по чек-листу QA 5.14 (все пять видов, светлая и тёмная тема, английский интерфейс, ссылки, выход из аккаунта); Release-архив с App Group подписывается.The “Teach” widget for iOS. Home Screen: small — “REVIEWS · TODAY”, the card count, minutes and a caption; medium — a summary and up to three subjects in “Today” order (name, “5 cards”, lesson status in the same words as in the subject row on “Today”; a paused subject has no status), the rest as “+N”. Lock Screen: circular (card count and a short caption), rectangular (“Teach”, summary, “Lesson ready”) and inline families; no subject names there. The count matches the reviews block on “Today”: the app computes the schedule for now and the next 7 midnights with the same formula and passes it to the widget, so the count changes at midnight without launching the app. Empty queue — “All reviewed” and “Next — tomorrow, 5”, or a ready lesson; no subjects — “Create your first subject”; after sign-out — “Sign in to Teach”. A tap opens a teach:// link to “Reviews” (a subject row opens it with that subject’s chip selected), “Today” or “Subjects”. The lesson status updates while the app is open (push — SR-09). No buttons, rings, streaks or percentages. Verified on the simulator against QA checklist 5.14 (all five families, light and dark theme, English interface, links, sign-out); the Release archive with an App Group is signed.QA: N-01…N-09, N-13, N-14РеализованоDone
FR-48Итог недели на «Сегодня»Weekly summary on “Today”Внизу «Сегодня» строка «за неделю: N ошибок закрыто · K темы окрепли» по журналу ответов; до первого пройденного урока строки нет.At the bottom of Today, the line “this week: N fixed · K topics stronger” from the answer log; there is no line until the first completed lesson.QA: B-05РеализованоDone
9

СправочникиReferences

IDТребованиеRequirementСтатусStatus
FR-50Вкладка «Справочники»“References” tabСистемный поиск в шапке по названиям и строкам всех справочников; смарт-плитки «Все термины» и «Слабые места» с числом строк (вторая включает фильтр со «Сбросить»); справочники сгруппированы по предметам в порядке «Сегодня», у глоссария значок «Aa»; детальный экран с таблицей «термин 126px | описание», подразделами и поиском в шапке (M-7).A system search in the header across titles and rows of all references; smart tiles “All terms” and “Weak spots” with row counts (the second turns on a filter with “Reset”); references grouped by subject in the “Today” order, with an “Aa” icon for the glossary; a detail screen with a “term 126px | description” table, subsections and a search in the header (M-7).QA: G-02, G-03, G-04РеализованоDone
FR-51Глоссарий из уроковGlossary from lessonsПосле каждого урока сервер извлекает 3–6 терминов и сливает их в глоссарий предмета без дублей; глоссарий приходит с уроком и ложится в SQLite, предмет появляется на вкладке сразу.After each lesson the server extracts 3–6 terms and merges them into the subject glossary without duplicates; the glossary arrives with the lesson and is stored in SQLite, and the subject appears on the tab at once.QA: G-01РеализованоDone
FR-52Другие группы справочниковOther reference groupsГрамматика, цель, чек-листы — конденсация по типу предмета; масштаб «50 уроков → ~8 справочников».Grammar, goal, checklists — condensation by subject type; scale “50 lessons → ~8 references”.ПланPlanned
FR-53Пометка ошибок по записямMistake marks from recordsСтрока справочника отмечена значком «!», пока по связанной с ней карточке повторов последний ответ неверный: ошибка в уроке, при пересдаче или в повторах, запись «путался» из разговора с бадди. Связи ставит сервер при генерации: глоссарий урока знает, какие шаги-вопросы проверяют термин, запись разговора — к каким терминам глоссария относится. Верный ответ по карточке снимает значок сразу и без сети. Промахи стартовой диагностики значков не дают. Тап по отмеченной строке открывает лист «Где ошиблись»: что было не так, откуда (урок или разговор) и когда повтор. «Слабые места» и «слабых: N» считают по тем же пометкам; на новом телефоне пометки те же. Старые предметы получают связи с уроков после обновления.A reference row shows a “!” badge while the last answer on a review card linked to it is wrong: a mistake in a lesson, on a retake or in reviews, or a “confused” record from a talk with the buddy. The server sets the links at generation time: a lesson’s glossary knows which question steps check a term, and a talk record knows which glossary terms it is about. A correct answer on the card removes the badge at once and offline. Misses in the Initial check-in give no badges. Tapping a marked row opens the “Where it went wrong” sheet: what went wrong, where (lesson or talk) and when the review is due. “Weak spots” and “weak: N” count the same marks; a new phone shows the same marks. Older subjects get links from lessons made after the update.QA: G-03, G-04, G-07, G-08, G-09, G-10, G-11, G-12, L-08РеализованоDone
10

ГолосVoice

IDТребованиеRequirementСтатусStatus
FR-60Платформенное распознаваниеPlatform speech recognitionSFSpeechRecognizer на iOS, SpeechRecognizer на Android; промежуточные результаты по словам ложатся в поле, текст правится вручную. Проверено на iPhone 16 Pro Max.SFSpeechRecognizer on iOS, SpeechRecognizer on Android; word-by-word interim results go into the field, and the text can be edited by hand. Verified on iPhone 16 Pro Max.QA: H-01, H-02РеализованоDone
FR-61Режим записи из профиляRecording mode from the profile«Удерживать» — одна реплика на нажатии, «Без рук» — непрерывно до повторного тапа.“Hold” — one utterance per press; “Hands-free” — continuous until the next tap.QA: H-02, H-03РеализованоDone
FR-62Язык распознавания из предметаRecognition language from the subjectПиллы «язык интерфейса / язык предмета» с локализованными именами; для языкового предмета по умолчанию язык предмета. В повторах язык берётся у предмета карточки текущего шага.Pills “interface language / subject language” with localized names; for a language subject the subject language is the default. In reviews the language comes from the subject of the current step's card.QA: H-04, F-05РеализованоDone
FR-63Голос никогда не блокируетVoice never blocksКнопка микрофона скрыта, если STT недоступен или голос выключен у предмета; ошибки распознавания лишь останавливают запись; текстовый ввод доступен всегда.The microphone button is hidden if STT is unavailable or voice is off for the subject; recognition errors only stop recording; text input is always available.QA: H-01, H-05, H-06РеализованоDone
FR-65Озвучка примеровExamples read aloudСистемный синтез речи на устройстве (AVSpeechSynthesizer / TextToSpeech), без сети и без токенов: кнопка «динамик» у карточки «ПРИМЕР», у вариантов выбора, реплик для упорядочивания и правильного ответа, в уроках и в повторах. Голос — язык предмета; смешанный текст режется по письменности, и русские куски читаются русским голосом по очереди с иностранными. Выключается в настройках предмета; для неязыковых предметов и без установленного голоса кнопок нет.On-device system speech synthesis (AVSpeechSynthesizer / TextToSpeech), with no network and no tokens: a “speaker” button on the “EXAMPLE” card, on choice options, on lines to order and on the correct answer, in lessons and in reviews. The voice matches the subject language; mixed text is split by script, and Russian parts are read by a Russian voice, alternating with the foreign ones. Turned off in subject settings; there are no buttons for non-language subjects or when no voice is installed.QA: I-01…I-07, F-06РеализованоDone
FR-66Голосовой разговор с баддиBuddy voice talkСвободный разговор голосом по теме предмета, 3–5 минут. Вход: «Поговорить» в плитке «Следующий урок» или кнопка со знаком бадди в строке предмета на «Сегодня». Экран (с v1.17): мягкое свечение цвета предмета сверху, шапка «✕ · Этап N · тема · таймер», ✕ завершает разговор, в центре крупный бадди со статусом «Ваш ход / Слушаю / Думаю / Говорю», над микрофоном крупно последняя реплика бадди (длинная прокручивается, во время записи под ней серым распознанная речь), стеклянная кнопка микрофона 88 pt с кольцом уровня голоса. Тап начинает запись, повторный тап заканчивает, тап во время речи бадди перебивает и сразу слушает. Реплики бадди короткие, 1–3 предложения, обращение на «ты» как характер персонажа; интерфейс остаётся на «вы». Схема: платформенное распознавание → текстовая модель → системная озвучка; первая фраза озвучивается по мере стриминга (~1–1.5 с). Проверено на заглушке модели в веб-превью; прогон на устройстве с реальной моделью — по чек-листу QA 5.13. Макет: канвас «Разговор с бадди» (Claude Design), светлая и тёмная темы.A free voice conversation on the subject topic, 3–5 minutes. Entry: “Talk” on the “Next lesson” tile or the buddy button in a subject row on “Today”. Screen (since v1.17): a soft glow of the subject’s color at the top, the header “× · Stage N · topic · timer”, × ends the talk, the big buddy in the middle with the status “Your turn / Listening / Thinking / Speaking”, the buddy’s last line shown large above the mic (a long one scrolls; while recording, the recognized speech is shown in grey below it), and a glass 88 pt microphone button with a voice level ring. A tap starts recording, a second tap ends it, and a tap while the buddy is speaking interrupts it and starts listening at once. Buddy lines are short, 1–3 sentences, in an informal register as part of the character; the interface keeps the formal register. Pipeline: platform recognition → text model → system text-to-speech; the first sentence is spoken as it streams (~1–1.5 s). Verified with a model stub in the web preview; the device run with the real model follows QA checklist 5.13. Mockup: the canvas “Разговор с бадди” (“Buddy talk”) in Claude Design, light and dark themes.QA: M-01…M-04, M-06, M-08…M-11, M-13…M-19РеализованоDone
FR-67Контекст разговора экономит токеныTalk context saves tokensБадди опирается на дайджест предмета (тема, фокус, миссия, текущий этап, глоссарий, свёртка записей об усвоенном и ошибках) объёмом 1–2 тыс. токенов; дайджест пересобирается моделью роли Digest после каждого разбора, а не на каждую реплику. Промпт из трёх слоёв с кэшем: персона и правила, дайджест предмета, хвост диалога. История держится в последних 10 репликах, старое сворачивается в две фразы. Уроки целиком в контекст не попадают. Ориентир стоимости: ~$0.003 за реплику на sonnet, ~$0.05 за разговор на 20 реплик.The buddy relies on a subject digest (topic, focus, mission, current stage, glossary, a rollup of learning records and mistakes) of 1–2 thousand tokens. The digest is rebuilt by the Digest role model after each recap, not on every line. A three-layer prompt with cache: persona and rules, subject digest, dialogue tail. History keeps the last 10 lines; older lines are folded into two sentences. Whole lessons do not go into the context. Cost estimate: ~$0.003 per line on sonnet, ~$0.05 per 20-line talk.QA: M-05, M-07РеализованоDone
FR-68Разговор оставляет записиA talk leaves recordsПо окончании разговора сервер извлекает, что пользователь подтвердил уверенно и где путался, и сохраняет как записи с пометкой «разговор» (не больше пяти на разговор); они влияют на следующий урок. Запись «путался» получает вопрос для повтора (выбор или ввод), телефон заводит из него карточку повторов, а итог виден на «Сегодня» подписью под кнопками плитки или под строкой предмета до следующего урока. Записи приходят со сборки 26.When a talk ends, the server extracts what the user confirmed with confidence and where they got confused, and saves these as records marked “talk” (at most five per talk); they affect the next lesson. A “confused” record gets a review question (a choice or an input), the phone turns it into a review card, and the outcome shows on Today as a caption under the tile buttons or the subject row until the next lesson. Records arrive with build 26.QA: M-12, M-20, M-21, M-22, M-23, L-05РеализованоDone
FR-64Детектор произношенияPronunciation detectorРаспознанный текст показывает, что услышано, а не что задумано; явное использование для языковых предметов.The recognized text shows what was heard, not what was meant; explicit use for language subjects.ПланPlanned
11

Предметы и настройки предметаSubjects and subject settings

IDТребованиеRequirementСтатусStatus
FR-70Миссия версионируетсяThe mission is versionedКарточка предмета на «Предметах»: кикер «Миссия · vN», текущая формулировка, зачёркнутая история; «Изменить миссию» (до 100 символов) правит на месте и создаёт новую версию (M-1).Subject card on Subjects: a “Mission · vN” kicker, the current wording, struck-through history; “Edit mission” (up to 100 characters) edits in place and creates a new version (M-1).QA: J-01РеализованоDone
FR-71Настройки предметаSubject settingsСистемная форма iOS (с v1.18), удаление предмета — через системное окно подтверждения. Пауза уроков (повторы продолжают приходить), длительность 3/5/10 (по умолчанию 10; уходит на сервер как бюджет урока), режим запоминания (FR-46), сложность, голос и язык распознавания. Применяются мгновенно. Прежняя норма повторов предмета 10/20/50 нигде не применялась и заменена режимом запоминания; единственный лимит повторов в день — общий, в профиле.A native iOS form (since v1.18); deleting a subject goes through a system confirmation dialog. Pause lessons (reviews keep coming), length 3/5/10 (default 10; sent to the server as the lesson budget), recall mode (FR-46), difficulty, voice and recognition language. Applied instantly. The former per-subject review quota 10/20/50 was never applied and is replaced by the recall mode; the only daily review cap is the global one in the profile.QA: J-02, J-03, J-04РеализованоDone
FR-72Удаление предметаDeleting a subjectДвухшаговое подтверждение; удаляются предмет, настройки, карточки повторов и справочники. Удаление уходит на сервер: предмет помечается удалённым (мягкое удаление, SR-21), пропадает из ответов сервера для пользователя и не возвращается на новом телефоне (FR-74).Two-step confirmation; the subject, its settings, review cards and references are deleted. The deletion goes to the server: the subject is marked deleted (soft delete, SR-21), disappears from the server's answers for the user and does not come back on a new phone (FR-74).QA: J-05, G-06, F-10, L-07РеализованоDone
FR-73Не добавлятьDo not addВыбор алгоритма интервалов и ручное редактирование сроков — запрещены спецификацией.Choosing the interval algorithm and editing due dates by hand are forbidden by the spec.СоблюденоObserved
12

Сервер и генерацияServer and generation

Клиент не держит ключей модели и не планирует обучение. Оркестратор на сервере собирает контекст, зовёт модель, валидирует ответ и хранит уроки, записи и справочники.The client holds no model keys and does not plan learning. The orchestrator on the server builds the context, calls the model, validates the response and stores lessons, records and references.

IDТребованиеRequirementСтатусStatus
SR-01Единый интерфейс контентаSingle content interfaceКлиент ходит только в ContentService; реализация HTTP включается адресом сервера, без него — локальная заглушка.The client talks only to ContentService; the HTTP implementation is enabled by a server address, and without one a local stub is used.РеализованоDone
SR-02Структурированный вывод по схемеStructured output by schemaМодель заполняет плоскую схему шага; сервер разворачивает её в доменный урок; заголовок карточки, строку уровня «этап N · фокус» и кикер «зачем» ставит сам, потому что модель путает номер этапа с номером урока.The model fills a flat step schema; the server expands it into a domain lesson. The server sets the card title, the level line “stage N · focus” and the “why” kicker itself, because the model confuses the stage number with the lesson number.QA: L-02РеализованоDone
SR-03Валидация смыслаSemantic validationВарианты без дублей, перестановки, критерии, обязательные записи, бюджет длины по длительности урока; невалидный урок и сбой вызова модели (сеть, шлюз, запасной путь без схемы) уходят на повтор, до трёх попыток (M-5); неверный ключ повтором не лечится и сразу даёт сбой.Options without duplicates, permutations, criteria, required records, a length budget by lesson duration; an invalid lesson and a failed model call (network, gateway, schema-less fallback) are regenerated, up to three attempts (M-5); an invalid key is not retried and fails at once.QA: L-02РеализованоDone
SR-04Долгие операции — фоновые задачиLong operations are background jobsПоиск источников, подготовка урока и следующий урок идут задачами с опросом статуса: iOS обрывает HTTP-запрос через 60 с.Source search, lesson preparation and the next lesson run as jobs with status polling: iOS drops an HTTP request after 60 s.QA: C-04, L-02РеализованоDone
SR-05Промпты версионируютсяPrompts are versionedВерсия промптов пишется в урок и отдаётся в health; правка педагогики не требует релиза клиента.The prompt version is written into the lesson and returned by health; a pedagogy change does not need a client release.РеализованоDone
SR-06Кэш промптаPrompt cacheМетодика и контекст предмета — стабильные префиксы под кэш; меняется только хвост с записями.The methodology and the subject context are stable prefixes for the cache; only the tail with records changes.РеализованоDone
SR-07Доступ по токенуToken accessВсе запросы, кроме health, требуют bearer-токен; ключи модели (OPENROUTER_API_KEY, на время перехода ANTHROPIC_API_KEY) только в секретах сервера.All requests except health require a bearer token; model keys (OPENROUTER_API_KEY, and ANTHROPIC_API_KEY during the transition) live only in server secrets.QA: L-01РеализованоDone
SR-08Привязка данных к аккаунтуData bound to the accountСервер проверяет Apple identityToken по ключам Apple и меняет его на токен аккаунта; у предмета есть владелец, чужие предметы не видны и не отдаются по id. Предметы, созданные до входа, остаются у общего владельца и доступны всем авторизованным — иначе они пропали бы у тестировщиков при обновлении.The server verifies the Apple identityToken against Apple keys and exchanges it for an account token. A subject has an owner; other users' subjects are not visible and are not returned by id. Subjects created before sign-in stay with a shared owner and are available to all authorized users — otherwise testers would lose them on update.РеализованоDone
FR-75АдминкаAdmin consoleСтраницаThe /console/ на том же сервере — вся админская работа безpage on the same server does all admin work without curl: шесть разделов FR-75.1–FR-75.6, интерфейс только на русском, для компьютера. Вход — общим токеном сервера (: six sections FR-75.1–FR-75.6, Russian-only interface, meant for a computer. Sign-in is with the shared server token (Teach:ApiToken): токен проверяется запросом): it is checked with a GET /admin/overview; на 401 и 403 — «Токен не подошёл», так что обычный токен тестировщика не входит. Токен QA входит только на чтение (FR-75.7). Токен хранится в браузере этого адреса и уходит только заголовком на свои request, and 401 or 403 gives «Токен не подошёл» (Token rejected), so a plain tester token does not get in. A QA token gets in read-only (FR-75.7). The token is kept in this address's browser storage and goes only as a header to the server's own /admin/*; «Выйти» стирает его, любой 401 в работе возвращает на вход. Страница публична, но данных в ней нет: всё приходит из; «Выйти» (Sign out) erases it, and any 401 during work returns to sign-in. The page is public but holds no data: everything comes from /admin/*, а они без токена отвечают 401, обычным токенам тестировщиков и аккаунтов — 403. Для, which answer 401 without a token and 403 to plain tester and account tokens. For /console сервер ставитthe server sets Content-Security-Policy (только свой адрес, без встраивания в чужие страницы) и(own origin only, no framing by other pages) and Referrer-Policy: no-referrer; темы, реплики, ошибки модели и прочий пользовательский текст выводятся как текст, разметкой не становятся. Опасные действия — отозвать токен, вернуть или удалить предмет, снять или удалить профиль, поставить или сбросить номер сборки — только через диалог, который называет, что произойдёт; удаление предмета и профиля — после ввода его названия. От сущности можно перейти к связанной: аккаунт → предмет → урок → строка журнала → предмет. Содержимое (уроки, план, миссию, записи) админка не правит; тексты промптов и ответов модели не показывает — журнал их не хранит.; topics, talk turns, model errors and other user text are shown as text and never become markup. Dangerous actions — revoking a token, restoring or deleting a subject, unassigning or deleting a profile, setting or resetting the build number — go only through a dialog that says what will happen; deleting a subject or a profile also needs its name typed in. Each entity links to the related ones: account → subject → lesson → journal row → subject. The console does not edit content (lessons, plan, mission, records) and does not show prompt or reply texts — the journal does not store them.QA: O-01, O-09, O-10, O-11, O-12РеализованоDone
FR-75.1Пульс«Пульс» (Pulse)Стартовый экран: окно 1, 7, 14 или 30 дней (по умолчанию 7). Активные аккаунты — владельцы, у которых за окно был урок, ответ на повтор или разговор, — и из них новые (первый токен в окне); уроков собрано и из них пропущено «Дальше»; разговоров начато; модель — вызовы, ошибки, доля запасного пути и расход в USD, итог и по ролям; предметы в статусе «сбой» и застрявшие в подготовке дольше 10 минут — списками до 50 со ссылками на предмет и владельца; номер последней сборки и его источник (база или конфигурация) со ссылкой на «Выпуск».The start screen: a 1, 7, 14 or 30 day window (7 by default). Active accounts — owners with a lesson, a review answer or a talk in the window — and how many of them are new (first token in the window); lessons built and how many of them were skipped with «Дальше» (Next); talks started; the model — calls, errors, fallback share and USD spend, in total and per role; subjects in the failed status and subjects stuck in preparation for more than 10 minutes — lists of up to 50 linking to the subject and the owner; the latest build number and its source (database or configuration) with a link to «Выпуск» (Release).QA: O-02РеализованоDone
FR-75.2Люди«Люди» (People)Список аккаунтов — по строке на владельца (The account list — one row per owner (apple:…, tester:…, shared), собранного из токенов, предметов и синхронизации: тип, имя тестировщика, первый и последний заход (по токенам), живые и удалённые предметы, профиль моделей; недавно заходившие выше, поиск по части владельца, до 200 строк. «Выдать токен тестировщику»: имя → токен показывается один раз, с кнопкой «Скопировать» и предупреждением, что больше его не увидеть. Карточка аккаунта: токены (создан, последний раз использован, отозван) с кнопкой «Отозвать»; все предметы, включая удалённые пользователем (помечены), со ссылками в «Предмет изнутри», «Вернуть» у удалённых и «Удалить совсем» у любых — предмет уходит с уроками, записями, справочниками и разговорами, журнал генераций остаётся; профиль моделей — назначить или снять (у) gathered from tokens, subjects and sync: kind, tester name, first and last visit (by tokens), live and deleted subjects, model profile; recently seen owners first, search by part of the owner, up to 200 rows. «Выдать токен тестировщику» (Issue a tester token): name → the token is shown once, with a «Скопировать» (Copy) button and a warning that it cannot be seen again. The account card: tokens (created, last used, revoked) with «Отозвать» (Revoke); all subjects, including those deleted by the user (marked), linking to «Предмет изнутри» (Subject inside), with «Вернуть» (Restore) on deleted ones and «Удалить совсем» (Delete for good) on any — the subject goes together with its lessons, records, references and talks, the generation journal stays; the model profile — assign or unassign (not for shared нет); повторы — карточек, ответов за 14 дней, открытых ошибок (FR-53) и когда телефон последний раз прислал состояние (FR-44).); reviews — cards, answers in 14 days, open mistakes (FR-53) and when the phone last sent its state (FR-44).QA: O-03, O-04РеализованоDone
FR-75.3Предмет изнутри«Предмет изнутри» (Subject inside)Что получил ученик, без проверки владельца; предмет открывается из аккаунта, «Пульса», журнала или полем «id предмета» в шапке. Экран предмета: тема, название, владелец, статус, этап подготовки, текущий урок (и из заготовки ли он), этап и версия плана, длительность урока, последняя ошибка, даты, удалён ли; фокус и миссия, прежняя миссия, если её ещё не учёл пересмотр; источники; план и история версий (автор, причина, «почему», из какой версии восстановлен); уроки — номер, этап, версия плана, модель, пропущен ли, дата, строка журнала; записи по урокам с отметкой верно/неверно, записи из разговоров — группой «Из разговоров»; справочники; дайджест для бадди; заготовка следующего урока; разговоры; вызовы модели по предмету. Урок — шаги в читаемом виде (заголовки, тексты, вопросы, варианты, правильные ответы), кнопка «Сырой JSON» и строка журнала, из которой урок собран. Разговор — реплики по ролям, свёрнутое старое и итог извлечения записей.What the learner got, without the owner check; a subject opens from an account, «Пульс» (Pulse), the journal, or the «id предмета» (subject id) field in the header. The subject screen: topic, name, owner, status, preparation stage, current lesson (and whether it came from the prefetch), plan stage and version, lesson length, last error, dates, whether it is deleted; focus and mission, the previous mission if a revision has not taken it into account yet; sources; the plan and its version history (author, reason, “why”, which version it was restored from); lessons — number, stage, plan version, model, skipped or not, date, journal row; records by lesson marked right/wrong, talk records as the «Из разговоров» (From talks) group; references; the buddy digest; the next-lesson prefetch; talks; model calls for the subject. A lesson — its steps in readable form (titles, texts, questions, options, correct answers), a «Сырой JSON» (Raw JSON) button and the journal row it was built from. A talk — turns by role, the folded older part and the record extraction outcome.QA: O-05РеализованоDone
FR-75.4Модели и профили«Модели и профили» (Models and profiles)Раскладка по ролям — модель, транспорт, лимит вывода, источник, предупреждения каталога — и как её видит заданный владелец. Профили (SR-20): создать, изменить (провайдер, роль → модель, заметка), удалить после ввода имени; ошибки проверки сервера показываются у формы; назначенный профиль не удаляется — сервер отвечает 409, админка называет владельцев. Назначения: кто на каком профиле, назначить владельцуThe per-role mapping — model, transport, output limit, source, catalog warnings — and how a given owner sees it. Profiles (SR-20): create, edit (provider, role → model, note), delete after typing the name; the server's validation errors are shown at the form; an assigned profile is not deleted — the server answers 409 and the console names the owners. Assignments: who is on which profile, assign to an owner tester:<имяname> (любой текст без переводов строк) или(any text without line breaks) or apple:<sub>, снять., unassign.QA: O-06РеализованоDone
FR-75.5Журнал генераций«Журнал генераций» (Generation journal)Сводка (SR-18) за 1, 7, 14 или 30 дней (по умолчанию 14) с фильтром профиля: по ролям и моделям — вызовы, ошибки, запасной путь, формат, задержки p50/p95, первый токен, токены, цена, качество уроков. Строки с фильтрами роль, модель, профиль, «только ошибки» и предмет (ссылка с экрана предмета), по 50, 200 или 500; строка раскрывается во все поля, id предмета в ней — ссылка на предмет. Фильтры хранятся в адресе экрана.The summary (SR-18) for 1, 7, 14 or 30 days (14 by default) with a profile filter: per role and model — calls, errors, fallback, format, p50/p95 latency, first token, tokens, price, lesson quality. Rows filtered by role, model, profile, «только ошибки» (errors only) and subject (a link from the subject screen), 50, 200 or 500 at a time; a row expands into all its fields, and the subject id in it links to the subject. The filters live in the screen address.QA: O-07РеализованоDone
FR-75.6Выпуск«Выпуск» (Release)Номер последней сборки для подсказки «Есть сборка N» (FR-08): текущее значение и его источник (база или конфигурация), когда обновлён, отдельной строкой — запасное значение из конфигурации, ссылка обновления (только показ). «Поставить» принимает целое от 0 до 1000000 (0 выключает подсказку) и срабатывает после подтверждения; «Сбросить к конфигурации» есть, только когда номер из базы. Номер хранится в базе сервера и действует сразу, без рестарта; пишут его этот экран иThe latest build number for the “Build N is out” nudge (FR-08): the current value and its source (database or configuration), when it was updated, the configuration fallback on its own line, and the update link (shown only). «Поставить» (Set) takes a whole number from 0 to 1000000 (0 turns the nudge off) and acts after confirmation; «Сбросить к конфигурации» (Reset to configuration) appears only when the number comes from the database. The number is stored in the server database and takes effect at once, without a restart; it is written by this screen and by scripts/release-ios.sh N --set-latest. Без номера в базе действует. With no number in the database, Teach__App__LatestIosBuild из конфигурации — запасное значение.from the configuration applies as the fallback.QA: O-08РеализованоDone
FR-75.7Доступ QA только на чтениеRead-only QA accessВ «Людях» у «Выдать токен тестировщику» есть галочка «и админка на чтение (QA)». С ней выдаётся токен QA: в API он обычный тестировщик (In «Люди» (People), «Выдать токен тестировщику» (Issue a tester token) has a box «и админка на чтение (QA)» (and read-only console, QA). With it ticked, a QA token is issued: in the API it is a plain tester (tester:<имя>, свои предметы), а в админку входит и видит все разделы. Менять он ничего не может: кнопок «Выдать токен», «Отозвать», «Вернуть», «Удалить совсем», правки профилей и назначений, «Поставить» и «Сбросить» нет, в шапке плашка «Только чтение»; сервер на любые записи в, own subjects), and it can sign in to the console and see every section. It cannot change anything: there are no «Выдать токен», «Отозвать», «Вернуть», «Удалить совсем», profile and assignment edits, «Поставить» or «Сбросить» buttons, and the header shows a «Только чтение» (Read-only) badge; the server answers 403 to any write to /admin/* отвечает 403. Тип токена виден в карточке аккаунта («QA, админка на чтение»); отзывается он, как любой токен, кнопкой «Отозвать» — общий токен при этом никому не передаётся.. The token kind shows in the account card («QA, админка на чтение»); it is revoked like any token with «Отозвать» (Revoke), so the shared token is never handed out.QA: O-12, O-13РеализованоDone
SR-09Push о готовности урокаPush when a lesson is readyНужен либо EAS-проект (ключи APNs держит Expo), либо ключ APNs .p8 и отправка из сервера — то и другое требует учётных данных. Пока разрыв закрыт иначе: возврат из фона и запуск перезапускают опрос готовности, поэтому доготовившийся урок появляется сразу.Needs either an EAS project (Expo holds the APNs keys) or an APNs .p8 key with sending from the server — both require credentials. For now the gap is closed differently: returning from the background and launching the app restart readiness polling, so a lesson that finished in the meantime appears at once.ПланPlanned
SR-10Задачи воркера трёх видовThree kinds of worker jobsСобрать текущий урок, заготовить следующий, продвинуть заготовку в текущие. Заготовка живёт в предмете отдельно от текущего урока и не меняет его статус; повторный запрос предзагрузки — no-op.Build the current lesson, prefetch the next one, promote the prefetch to current. The prefetch lives in the subject separately from the current lesson and does not change its status; a repeated prefetch request is a no-op.РеализованоDone
SR-11Разбор идемпотентенThe recap is idempotentПовторная отправка разбора того же урока (перезапуск клиента, «Повторить») не дублирует записи и не запускает лишнюю генерацию: если следующий урок уже готов, ответ «ready».Resending the recap of the same lesson (client restart, “Retry”) does not duplicate records and does not start extra generation: if the next lesson is ready, the response is “ready”.QA: L-03РеализованоDone
SR-12Очередь переживает перезапуск сервераThe queue survives a server restartОчередь в памяти; при старте предметы со статусом «в подготовке» ставятся в очередь заново, незавершённая предзагрузка сбрасывается.The queue is in memory; on startup, subjects with the “preparing” status are queued again, and an unfinished prefetch is reset.РеализованоDone
SR-15Именные токены тестировщиковNamed tester tokensОбщий токен остаётся админским: под ним выдаются, перечисляются и отзываются именные токены. Хранятся хешами (SHA-256), значение показывается один раз, отзыв действует сразу и не трогает остальные; видно, когда токен использовался последний раз.The shared token remains the admin token: named tokens are issued, listed and revoked under it. They are stored as hashes (SHA-256), the value is shown once, revocation takes effect at once and does not affect other tokens; the last time each token was used is visible.РеализованоDone
SR-13Плавная остановкаGraceful shutdownПо SIGINT/SIGTERM воркер дорабатывает текущий урок при живом сервере (до 150 с, Fly ждёт 160 с), и только потом хост останавливается; деплой посреди генерации не стоит повторного вызова модели. Замер на Fly: 22 с дожидания с ответами 200, ~10 с на перезапуск. С Litestream сигнал доходит до сервера так же, а копия базы делает последнюю отправку после его остановки.On SIGINT/SIGTERM the worker finishes the current lesson while the server is still alive (up to 150 s; Fly waits 160 s), and only then does the host stop; a deploy in the middle of generation does not cost a repeated model call. Measured on Fly: 22 s of draining with 200 responses, ~10 s per restart. With Litestream the signal reaches the server the same way, and the database copy makes a final push after the server stops.РеализованоDone
SR-16Эндпоинт разговора со стримингомTalk endpoint with streamingPOST /talks/{id}/turns с ответом по SSE: клиент отправляет распознанный текст, сервер отдаёт реплику бадди по кускам, первое предложение уходит в озвучку до конца генерации. История разговора хранится на сервере и обрезается; дайджест предмета лежит в строке предмета и обновляется задачей воркера после разбора. Модель роли Talk (в коде по умолчанию sonnet, на проде gemini-3.1-flash-lite) с низким effort иwith an SSE response: the client sends the recognized text, the server returns the buddy line in chunks, and the first sentence goes to speech before generation ends. Talk history is stored on the server and trimmed; the subject digest lives in the subject row and is updated by a worker job after the recap. The Talk role model (sonnet by default in code, gemini-3.1-flash-lite in production) with low effort and max_tokens 400 (с учётом thinking). Вызов400 (including thinking). The POST /talks/{id}/end синхронно извлекает и возвращает записи разговора (статус done, empty или failed); пока извлечение идёт, ответ 409.call synchronously extracts and returns the talk records (status done, empty or failed); while extraction is running, the answer is 409.QA: M-03, M-06, L-05РеализованоDone
SR-17Шлюз моделей и OpenRouterModel gateway and OpenRouterВызовы модели идут через шлюз:Model calls go through the gateway: anthropic/* — Messages API через Anthropic SDK, остальные модели — Chat Completions OpenRouter. Модель каждой роли задаётся настройкой без релиза клиента; прямой Anthropic остаётся путём отката. Модель без поддержки схемы получает один повтор без схемы, урок проходит валидатор. Запросы к OpenRouter — сuse the Messages API via the Anthropic SDK, other models use OpenRouter Chat Completions. The model for each role is set by configuration without a client release; direct Anthropic remains the rollback path. A model without schema support gets one retry without the schema, and the lesson goes through the validator. Requests to OpenRouter are sent with data_collection: deny. РольThe Replan (пересмотр плана, FR-33) по умолчанию берёт модель ролиrole (plan revision, FR-33) defaults to the model of the Plan role.РеализованоDone
SR-18Журнал генераций и сводкаGeneration journal and summaryСтрока на каждый вызов модели: роль, модель, транспорт, задержка, токены, цена, ошибка, формат; без текстов промптов и ответов, хранение 90 дней. Урок помнит модель и этап. Админская сводка по ролям и моделям: ошибки, запасной путь, p50/p95, цена; для уроков — верно с первой попытки, валидатор, уроков до закрытия этапа.One row per model call: role, model, transport, latency, tokens, cost, error, format; no prompt or response texts; kept for 90 days. A lesson remembers its model and stage. An admin summary by role and model: errors, fallback path, p50/p95, cost; for lessons — correct on first try, validator, lessons until the stage closes.РеализованоDone
SR-19Непрерывная копия базыContinuous database copyLitestream отправляет изменения базы в Tigris раз в секунду, снимок раз в сутки, история 7 дней; снимки тома Fly — 14 дней. При пропаже тома база восстанавливается из Tigris до старта сервера. Копия для разбора —Litestream pushes database changes to Tigris every second, a snapshot once a day, 7 days of history; Fly volume snapshots are kept for 14 days. If the volume is lost, the database is restored from Tigris before the server starts. A copy for analysis: litestream restore на Mac. Без секрета бакета сервер работает как раньше.on a Mac. Without the bucket secret the server works as before.РеализованоDone
SR-20Профили моделей по тестировщикамModel profiles per testerИменной набор «роль → модель» поверх общей раскладки назначается тестировщику или аккаунту админским API; вызовы модели этого владельца, включая фоновые уроки, идут на моделях профиля, изменения действуют без перезапуска. Журнал пишет профиль, сводка сравнивает профиль с общей раскладкой.A named “role → model” set on top of the shared mapping is assigned to a tester or an account through the admin API. That owner's model calls, including background lessons, run on the profile's models; changes take effect without a restart. The journal records the profile; the summary compares the profile with the shared mapping.РеализованоDone
SR-21СинхронизацияSyncМаршруты /sync/* принимают копию с телефона и отдают её новому: POST /sync/cards (до 500 карточек, побеждает более новая по updatedAt; карточка несёт miss — открытую ошибку, FR-53; без поля — false), POST /sync/answers (до 2000, только добавление, повтор по answerId пропускается), PUT /sync/state (объект до 256 КБ, побеждает более новое), POST /sync/known-subjects (разовая сверка: непустой список своих предметов; остальные свои, созданные больше 5 минут назад, получают мягкое удаление), GET /sync/restore (свои живые предметы с планом, текущим уроком и справочниками — и живые общие, созданные до входа по Apple, если их перечисляет состояние аккаунта, — карточки, ответы, состояние). Данные привязаны к владельцу; под общим токеном сборки — 403 {"error":"sync requires an account"}, чтобы данные разных людей не смешались; неверное тело — 400. DELETE /subjects/{id} — мягкое удаление своего предмета (204, повтор 204, чужой или общий предмет 404, под общим токеном 403 — телефон оставляет удаление в очереди): удалённый предмет для пользователя не существует ни в списке, ни в уроке и разборе, а новый разговор по нему не начать (уже открытый продолжается). Админ видит deletedAt в GET /admin/subjects и возвращает предмет через POST /admin/subjects/{id}/undelete; DELETE /admin/subjects/{id} по-прежнему удаляет физически.The /sync/* routes accept the copy from a phone and give it to a new one: POST /sync/cards (up to 500 cards, the newer updatedAt wins; a card carries miss, its open mistake, FR-53; absent means false), POST /sync/answers (up to 2000, append only, a repeated answerId is skipped), PUT /sync/state (an object up to 256 KB, the newer one wins), POST /sync/known-subjects (a one-time reconciliation: a non-empty list of own subjects; the other own ones created more than 5 minutes ago get a soft delete), GET /sync/restore (own live subjects with plan, current lesson and references — plus live shared ones created before Apple sign-in if the account state lists them — cards, answers, state). Data is bound to the owner; under the shared build token the answer is 403 {"error":"sync requires an account"}, so that data of different people is not mixed; a malformed body is 400. DELETE /subjects/{id} is a soft delete of the user's own subject (204, repeat 204, a stranger's or shared subject 404, under the shared token 403 — the phone keeps the deletion queued): a deleted subject does not exist for the user — not in the list, the lesson or the recap, and a new talk cannot be started on it (a talk that is already open keeps working). The admin sees deletedAt in GET /admin/subjects and brings a subject back with POST /admin/subjects/{id}/undelete; DELETE /admin/subjects/{id} still deletes physically.QA: L-06, L-07, L-08РеализованоDone
SR-22Версии плана и пересмотрPlan versions and revisionКаждая версия плана — строка PlanVersions (автор, причина, «почему», этап, строка журнала вызова); Subjects.PlanJson — копия последней версии в той же транзакции; предметы без версий получают версию 1 при старте сервера. Разбор, закрывший этап, ставит рубеж (PendingReplan), воркер сначала пересматривает план вызовом роли Replan с детерминированной проверкой ответа (1–4 этапа, закреплённые на месте, id по названию), потом сдвигает этап и собирает урок; сбой — переход по старому плану. PUT /subjects/{id}/mission { text, editedAt }: 204, пустой или длиннее 300 — 400, чужой — 404, старая правка — без действий; новая миссия пересматривает этапы после текущего. Статус урока и /sync/restore несут plan (с id и by), planVersion, planChange; готовый урок — stageCloseAt (порог закрытия этапа). Новые поля необязательные, сборки 35 и раньше их не читают.Each plan version is a PlanVersions row (author, reason, “why”, stage, journal row of the call); Subjects.PlanJson is a copy of the latest version written in the same transaction; subjects without versions get version 1 at server start. A recap that closes a stage sets a boundary (PendingReplan); the worker first revises the plan with a Replan role call and a deterministic check of the answer (1–4 stages, pinned stages in place, ids by title), then moves the stage and builds the lesson; on failure it moves by the old plan. PUT /subjects/{id}/mission { text, editedAt }: 204; empty or longer than 300 — 400; someone else’s — 404; an older edit does nothing; a new mission revises the stages after the current one. The lesson status and /sync/restore carry plan (with id and by), planVersion, planChange; a ready lesson carries stageCloseAt (the stage-closing threshold). New fields are optional; builds 35 and earlier ignore them.QA: L-09РеализованоDone
SR-23Правка плана человекомPlan edits by the personМаршруты предмета, владелец под любым токеном; чужой или удалённый предмет — 404; baseVersion не равна текущей версии — 409 { error: "stale", plan, planVersion, planStage }. PUT /subjects/{id}/plan { baseVersion, current?: { t, d }, ahead: [{ id?, t, d }] }: до 8 этапов впереди, t 1–60, d до 140, без повторов id — иначе 400; новые, переписанные и переставленные (вне наибольшей общей подпоследовательности старого и нового порядка) этапы закрепляются (by: "user"); без изменений — 200 без новой версии, иначе версия User / UserEdit; ответ { plan, planVersion, planStage }. POST …/plan/skip { baseVersion }: 202 { status: "preparing" } — готовый урок помечается Skipped (в сводку генераций не входит), рубеж StageSkipped, задача Prepare; 409 preparing / diagnostic. POST …/plan/revert { baseVersion }: этапы зоны последней версии модели — из предыдущей версии, закреплённые; версия User / Revert с restoredFrom; готовый урок не пересобирается; 409 nothing. Статус урока и /sync/restore несут planRevertable. GET …/plan/history — версии от новых к старым: version, author, reason, why, at, stageIndex, restoredFrom, stages. Заготовка следующего урока, собранная по старому плану, отбрасывается.Subject routes, the owner under any token; someone else’s or a deleted subject — 404; baseVersion not equal to the current version — 409 { error: "stale", plan, planVersion, planStage }. PUT /subjects/{id}/plan { baseVersion, current?: { t, d }, ahead: [{ id?, t, d }] }: up to 8 stages ahead, t 1–60, d up to 140, no repeated id — otherwise 400; new, rewritten and moved (outside the longest common subsequence of the old and new order) stages are pinned (by: "user"); no change — 200 without a new version, otherwise a User / UserEdit version; the response is { plan, planVersion, planStage }. POST …/plan/skip { baseVersion }: 202 { status: "preparing" } — the ready lesson is marked Skipped (left out of the generation summary), a StageSkipped boundary, a Prepare job; 409 preparing / diagnostic. POST …/plan/revert { baseVersion }: the zone of the model’s last version comes back from the previous version, pinned; a User / Revert version with restoredFrom; the ready lesson is not rebuilt; 409 nothing. The lesson status and /sync/restore carry planRevertable. GET …/plan/history — versions from newest to oldest: version, author, reason, why, at, stageIndex, restoredFrom, stages. A prefetched next lesson built from the old plan is discarded.QA: L-10, L-11РеализованоDone
SR-14Источники ищутся один разSources are searched onceWeb search только при создании предмета; результат хранится в предмете. Предмет старого клиента без источников ищет их один раз перед первым уроком, следующие уроки такого предмета собираются без источников с предупреждением в логе (M-2).Web search runs only when a subject is created; the result is stored in the subject. A subject from an old client without sources searches for them once before the first lesson; later lessons of such a subject are built without sources, with a warning in the log (M-2).РеализованоDone
Замеры на реальной модели, 9 сентября: фокусы 5 с (claude-sonnet-5), план 6 с, источники с web search около 30 с, диагностика 20 с, следующий урок 18–27 с (10-минутный урок из пяти шагов — 27 с), заготовка следующего урока 30 с, оценка свободного ответа 1.4 с. Стоимость предмета с одним уроком порядка 10–20 центов; предзагрузка добавляет одну лишнюю генерацию примерно на каждый провальный или переходный урок.Measurements on the real model, 9 September: focus options 5 s (claude-sonnet-5), plan 6 s, sources with web search about 30 s, Initial check-in 20 s, next lesson 18–27 s (a 10-minute five-step lesson takes 27 s), next-lesson prefetch 30 s, free-form answer grading 1.4 s. A subject with one lesson costs about 10–20 cents; prefetch adds roughly one extra generation for each failed or stage-transition lesson.
13

Данные и офлайнData and offline

IDТребованиеRequirementСтатусStatus
DR-01Локальная БД на аккаунтLocal DB per accountФайл SQLite с id аккаунта в имени; карточки, журнал ответов, справочники, настройки и прогресс. Выход не удаляет. Копия карточек, ответов и настроек лежит на сервере (FR-44, SR-21) и возвращается на новом телефоне (FR-74).A SQLite file with the account id in its name; cards, answer log, references, settings and progress. Sign-out does not delete it. A copy of cards, answers and settings is kept on the server (FR-44, SR-21) and comes back on a new phone (FR-74).QA: A-04РеализованоDone
DR-02Офлайн работаютWorks offlineПовторы, справочники, глоссарий, уже скачанные уроки. Не работают: новый предмет, поиск источников, следующий урок.Reviews, references, glossary, already downloaded lessons. Does not work offline: new subject, source search, next lesson.QA: F-07, G-05, K-04РеализованоDone
DR-03МиграцииMigrationsКлиент: версионированные миграции SQLite. Сервер: миграции EF Core при старте; базы, созданные до миграций, переводятся автоматически одной транзакцией (доводка схемы, недостающие индексы, отметка Baseline).Client: versioned SQLite migrations. Server: EF Core migrations on startup; databases created before migrations are converted automatically in one transaction (schema alignment, missing indexes, the Baseline mark).РеализованоDone
DR-04Приватность записейPrivacy of recordsЗаписи об усвоенном — перечень того, чего человек не знает; обучение не видно руководителю, командные агрегаты только обезличенные, экспорт и удаление своих данных.Learning records are a list of what a person does not know. Learning is not visible to a manager, team aggregates are anonymized only, and users can export and delete their own data.ПланPlanned
14

Нефункциональные требованияNon-functional requirements

IDТребованиеRequirementСтатусStatus
NF-01Нативный вид iOSNative iOS lookВид по спеку нативного редизайна (заменил визуальную часть DESIGN.md): системная палитра и шрифт SF Pro, системный таб-бар с бейджем повторов, шапка вкладки в одну строку (название крупным шрифтом, справа аватар профиля, у «Предметов» — отдельная кнопка «+»), листы, урок раскрывается зумом из плитки. Урок, итог и разговор — в цвете предмета (сегменты, CTA, подложка примера, кольцо этапа на итоге); у мастера — шапка листа «Отмена | Новый предмет | k/5» и значок нового предмета в его будущем цвете; разбор ответа выезжает листом снизу; в тёмной теме большие площади цвета (плитка героя, свечение разговора) приглушены. Палитра предметов приглушённая (с v1.18); Профиль и настройки предмета — системные формы iOS (SwiftUI). Виджет и иконка приложения — в палитре приложения: виджет на системных поверхностях с хвойным акцентом, знак иконки белый на хвойном фоне (с v1.19). Контраст текста к фону ≥ 4,5:1 в обеих темах закреплён тестом; у каждого предмета свой системный цвет. Хит-таргеты ≥ 44 pt, Dynamic Type с ограничением ×1,4 в плотных местах, на крупном шрифте плитки встают в колонку; «Уменьшить движение» заменяет жест колоды кнопками. Golos Text — только словотип.The look follows the native redesign spec (it replaced the visual part of DESIGN.md): the system palette and the SF Pro font, the system tab bar with a reviews badge, a one-row tab header (the tab name in large type, the profile avatar on the right, a separate “+” button on Subjects), sheets, and the lesson opening with a zoom from its tile. The lesson, recap and talk use the subject’s color (segments, CTA, example backdrop, a stage ring on the recap); the wizard has a “Cancel | New subject | k/5” sheet header and the new subject’s icon in its future color; the answer recap slides up as a sheet; in dark mode large color areas (the hero tile, the talk glow) are muted. The subject palette is muted (since v1.18); Profile and subject settings are native iOS forms (SwiftUI). The widget and the app icon follow the app palette: the widget on system surfaces with a pine accent, the icon's mark white on pine (since v1.19). Text-to-background contrast ≥ 4.5:1 in both themes is pinned by a test; each subject has its own system color. Hit targets ≥ 44 pt, Dynamic Type capped at ×1.4 in dense spots, tiles stack into one column at large text sizes; Reduce Motion replaces the deck gesture with buttons. Golos Text is used only in the wordmark.РеализованоDone
NF-02Отклик проверки ответаAnswer check response timeПроверка на устройстве без сети — мгновенно; оценка свободного ответа моделью — до 2 с.An on-device check without network is instant; model grading of a free-form answer takes up to 2 s.РеализованоDone
NF-03Ожидание генерацииGeneration waitМастер: шаг источников до минуты с индикацией; первый урок до 60 с в фоне; следующий урок сразу после разбора, если заготовка подошла, иначе до 30 с в фоне.Wizard: the sources step takes up to a minute with a progress indicator; the first lesson up to 60 s in the background; the next lesson arrives right after the recap if the prefetch fits, otherwise up to 30 s in the background.РеализованоDone
NF-04БезопасностьSecurityHTTPS, bearer-токен, ключ модели в секретах; строки назначения для микрофона, распознавания речи, локальной сети.HTTPS, bearer token, model key in secrets; purpose strings for the microphone, speech recognition and local network.РеализованоDone
NF-05ТестыTestsКлиент 407 тестов: движок сессии, FSRS и режимы запоминания, сторы, фильтры справочников, HTTP-контракт, предзагрузка, возобновление, опрос при сбоях сети, несколько предметов и миграция снимка, оценка свободного ответа, расписание напоминаний, прогноз нагрузки, снимок и синхронизация виджета, отправка копии на сервер и восстановление на новом телефоне; сервер 275: валидатор, политика этапов, API-сценарии включая предзагрузку и повторный разбор, миграция схемы, владение предметами и токены, разговор с бадди, шлюз моделей (эталонные запросы, транспорты, запасной путь) и журнал генераций, профили моделей, синхронизация, восстановление и мягкое удаление предметов.Client, 407 tests: session engine, FSRS and recall modes, stores, reference filters, HTTP contract, prefetch, resume, polling under network failures, multiple subjects and snapshot migration, free-form answer grading, reminder schedule, load forecast, widget snapshot and sync, uploading the copy to the server and restoring on a new phone. Server, 275: validator, stage policy, API scenarios including prefetch and repeated recap, schema migration, subject ownership and tokens, buddy talk, model gateway (reference requests, transports, fallback path) and generation journal, model profiles, sync, restore and soft deletion of subjects.РеализованоDone
NF-06AndroidОбщая кодовая база; сборка и STT на Android-устройстве не проверялись.Shared codebase; the build and STT have not been verified on an Android device.ПланPlanned
15

Трассировка и тестированиеTraceability and testing

Документ — основа для тестирования: каждое требование имеет постоянный ID и ссылку видаThis document is the basis for testing: each requirement has a permanent ID and a link of the form /docs/frd.html#FR-47 (ID в таблице кликабелен). Под описанием строки указаны тест-кейсы из(the ID in the table is clickable). Under each row description are the test cases from the тестовой документации QAQA test documentation, которые его проверяют; «нет кейса» отмечает реализованное требование без ручной проверки.that verify it; “no case” marks an implemented requirement without a manual check.

  • Bug report. Указывайте ID требования, которое нарушено, и ID тест-кейса: «FR-46 / N-12». Если поведение расходится с текстом требования, а не с кейсом, — bug в требовании или в кейсе, об этом тоже пишите.Give the ID of the violated requirement and the ID of the test case: “FR-46 / N-12”. If the behavior differs from the requirement text rather than from the case, the bug is in the requirement or in the case; report that too.
  • Статус «План».“Planned” status. Требование не реализовано, кейсы по нему пропускаются.The requirement is not implemented; its cases are skipped.
  • Серверные требованияServer requirements (SR, DR) проверяются в основном автотестами сервера (NF-05); вручную — через API-кейсы L-01…L-11. Админку (FR-75) проверяют кейсы O-01…O-11.(SR, DR) are verified mostly by server automated tests (NF-05); manually, through API cases L-01…L-11. The admin console (FR-75) is covered by cases O-01…O-11.
  • Без ручных кейсов:No manual cases: FR-02 — вход через Google скрыт в релизной сборке, проверять нечего.FR-02 — Google sign-in is hidden in the release build, so there is nothing to check.
  • Техническое устройствоThe technical design каждого требования — на страницеof each requirement is on the технической документацииtechnical documentation, там стоят обратные ссылки на ID.page, which links back to the IDs.
v1.24: доступ QA к админке только на чтение (FR-75.7, сервер) — токен QA выдаётся в «Людях» галочкой «и админка на чтение (QA)», общий токен больше не нужно передавать. Новые кейсы QA O-12, O-13.v1.24: read-only QA access to the console (FR-75.7, server) — a QA token is issued in «Люди» (People) with the «и админка на чтение (QA)» box, so the shared token no longer has to be handed out. New QA cases O-12, O-13.
v1.23: админка (FR-75, сервер) — страница /console/ под общим токеном: «Пульс», «Люди», «Предмет изнутри», «Модели и профили», «Журнал генераций», «Выпуск» (FR-75.1–FR-75.6); номер последней сборки хранится в базе и задаётся админкой или release-ios.sh N --set-latest без рестарта, конфигурация — запасное значение (FR-08). Новые кейсы QA O-01…O-11 (QA 1.23). Всего 170.v1.23: the admin console (FR-75, server) — the /console/ page under the shared token: «Пульс» (Pulse), «Люди» (People), «Предмет изнутри» (Subject inside), «Модели и профили» (Models and profiles), «Журнал генераций» (Generation journal), «Выпуск» (Release) (FR-75.1–FR-75.6); the latest build number is stored in the database and set from the console or with release-ios.sh N --set-latest without a restart, the configuration is the fallback (FR-08). New QA cases O-01…O-11 (QA 1.23). 170 in total.
v1.22: живой план, часть 2 (FR-33, со сборки 37) — правка плана человеком в листе «План» (режим правки, метка «ваш», очередь правок, конфликт), «Этот этап я уже знаю — дальше», «Вернуть прежний план», «История изменений»; новые маршруты плана (SR-23); подпись мастера (FR-17). FR-33 реализовано полностью. Новые кейсы QA E-17…E-22, L-10 и L-11, E-14 дополнен (QA 1.22). Всего 159.v1.22: living plan, part 2 (FR-33, from build 37) — plan edits by the person in the “Plan” sheet (edit mode, the “yours” mark, the edit queue, conflicts), “I already know this stage — next”, “Restore the previous plan”, “Change history”; new plan routes (SR-23); the wizard caption (FR-17). FR-33 is fully done. New QA cases E-17…E-22, L-10 and L-11, E-14 extended (QA 1.22). 159 in total.
v1.21: живой план, часть 1 (FR-33, со сборки 36) — план на сервере версиями, пересмотр моделью на рубежах (этап закрыт, смена миссии), план не кончается, «План обновлён» и лист «План», честное кольцо итога (SR-22, FR-31, M-1, FR-17, SR-17). Новые кейсы QA E-09…E-16 и L-09 (QA 1.21). Всего 151.v1.21: living plan, part 1 (FR-33, from build 36) — the plan on the server in versions, model revision at boundaries (stage closed, mission changed), the plan never ends, “Plan updated” and the “Plan” sheet, an honest recap ring (SR-22, FR-31, M-1, FR-17, SR-17). New QA cases E-09…E-16 and L-09 (QA 1.21). 151 in total.
v1.20: пометки ошибок в справочниках (FR-53, со сборки 35) — значок «!» у строк, связанных с открытыми ошибками, лист «Где ошиблись»; карточка повторов в синхронизации несёт miss (SR-21). Новые кейсы QA G-07…G-12 и L-08, в G-03 и G-04 «ОШИБКА» заменён значком (QA 1.20). Всего 142.v1.20: mistake marks in references (FR-53, from build 35) — a “!” badge on rows linked to open mistakes and the “Where it went wrong” sheet; a review card in sync carries miss (SR-21). New QA cases G-07…G-12 and L-08; in G-03 and G-04 “MISTAKE” is replaced with the badge (QA 1.20). 142 in total.
v1.19: хвосты редизайна (со сборки 34) — лист разбора утягивается вниз за ручку (FR-22); виджет и иконка приложения в палитре приложения (NF-01); встряхивание неверного варианта не повторяется при свайпе назад; значок нового предмета не перекрашивается при закрытии мастера; кольцо итога у демо идёт по этапам цепочки уроков; кольцо микрофона не пульсирует при «Уменьшить движение» и больше не перерисовывает экран разговора; ✕ не вылезает из круга на крупном шрифте; включение и выключение напоминаний идут по очереди; снимок аккаунта со сборки до 33 включает напоминания. Кейсы QA D-02 и N-01 уточнены; в M-12, M-20…M-23 разговор завершается крестиком (кнопки «Завершить» нет), а без итога подписи на «Сегодня» нет (QA 1.19). Всего по-прежнему 135.v1.19: redesign leftovers (from build 34) — the recap sheet can be dragged down by its grabber (FR-22); the widget and the app icon follow the app palette (NF-01); the wrong-option shake no longer replays on swipe back; the new subject's icon keeps its colour while the wizard closes; the demo recap ring follows the lesson chain's stages; the mic ring does not pulse under Reduce Motion and no longer re-renders the talk screen; the ✕ stays inside its circle at large text sizes; reminder on/off operations run one after another; an account snapshot from before build 33 keeps reminders on. QA cases D-02 and N-01 refined; in M-12 and M-20…M-23 the talk ends with × (there is no “Finish” button), and without an outcome there is no caption on “Today” (QA 1.19). Still 135 in total.
v1.18: настройки в системном виде iOS (со сборки 33) — Профиль и настройки предмета стали формами SwiftUI; удаление предмета и выход — через системное окно подтверждения; у предмета выбор цвета из 12; напоминания можно выключить; палитра предметов приглушена по просьбе владельца. Уточнены NF-01, FR-04, FR-07, FR-16, FR-71; кейсы QA A-04, F-10, J-04, J-05, K-07 переписаны, добавлен J-07 — всего 135.v1.18: settings in the native iOS look (from build 33) — Profile and subject settings became SwiftUI forms; deleting a subject and signing out go through a system confirmation dialog; a subject color can be picked out of 12; reminders can be switched off; the subject palette is muted at the owner’s request. NF-01, FR-04, FR-07, FR-16, FR-71 refined; QA cases A-04, F-10, J-04, J-05, K-07 rewritten, J-07 added — 135 in total.
v1.17: режимы фокуса в нативном виде (со сборки 32) — урок, практика, итог и разговор в цвете предмета; разбор ответа — лист снизу; итог с кольцом этапа; разговор с крупным бадди, последней репликой и кольцом уровня голоса у микрофона; мастер с шапкой «Отмена | Новый предмет | k/5». В тёмной теме плитка героя приглушена и без свечения (замечание владельца). Уточнены NF-01, FR-22, FR-66; кейсы QA C-01, D, E-01, M переписаны, добавлен B-08 — всего 134.v1.17: focus modes in the native look (from build 32) — the lesson, practice, recap and talk use the subject’s color; the answer recap is a bottom sheet; the recap has a stage ring; the talk has a big buddy, the last line and a voice level ring around the mic; the wizard has a “Cancel | New subject | k/5” header. In dark mode the hero tile is muted and has no glow (owner feedback). NF-01, FR-22, FR-66 refined; QA cases C-01, D, E-01, M rewritten, B-08 added — 134 in total.
v1.16: шапка вкладок в одну строку (со сборки 31) — название вкладки крупным шрифтом слева, аватар профиля справа в той же строке; «+» на «Предметах» — отдельная кнопка, а не одна капсула с аватаром; при прокрутке название остаётся в шапке. Уточнён NF-01, переписан кейс QA A-05.v1.16: a one-row tab header (from build 31) — the tab name in large type on the left, the profile avatar on the right in the same row; the “+” on Subjects is a separate button rather than one capsule with the avatar; the name stays in the header on scroll. NF-01 refined, QA case A-05 rewritten.
v1.15: нативный iOS-вид (сборки 29–30) — NF-01 переписан под спек редизайна; тема «Системная» (FR-06); цвет у каждого предмета (FR-16); вкладки получили своё лицо: плитка «Следующий урок» и строки предметов на «Сегодня», колода и бейдж на «Повторах», поиск в шапке и смарт-плитки на «Справочниках», кольца этапов на «Предметах» — уточнены FR-10, FR-13, FR-15, FR-32, FR-34, FR-36, FR-42, FR-45, FR-47, FR-48, FR-50, FR-66, FR-68, FR-70; кейсы QA переписаны под новый вид, их по-прежнему 133.v1.15: native iOS look (builds 29–30) — NF-01 rewritten for the redesign spec; a “System” theme (FR-06); a color per subject (FR-16); the tabs got their own faces: the “Next lesson” tile and subject rows on Today, the deck and badge on Reviews, the header search and smart tiles on References, stage rings on Subjects — FR-10, FR-13, FR-15, FR-32, FR-34, FR-36, FR-42, FR-45, FR-47, FR-48, FR-50, FR-66, FR-68, FR-70 refined; the QA cases were rewritten for the new look, still 133 of them.
v1.14: FR-44 «Синхронизация повторов с сервером» реализован — телефон в фоне отправляет карточки, ответы и состояние, новый телефон забирает их при первом входе; новые требования FR-74 «Восстановление на новом телефоне» и SR-21 «Синхронизация»; FR-03, FR-43, FR-72 и DR-01 уточнены; кейсы F-08…F-10, K-08, K-09, L-06 и L-07.v1.14: FR-44 “Review sync with the server” is implemented — the phone sends cards, answers and state in the background, and a new phone collects them on the first sign-in; new requirements FR-74 “Restore on a new phone” and SR-21 “Sync”; FR-03, FR-43, FR-72 and DR-01 are refined; cases F-08…F-10, K-08, K-09, L-06 and L-07.
v1.13: FR-68 «Разговор оставляет записи» реализован — записи разговора, карточки повторов и подпись на «Сегодня»; кейсы M-12, M-20…M-23 и L-05; SR-16 описывает ответ /end.v1.13: FR-68 “A talk leaves records” is implemented — talk records, review cards and the Today caption; cases M-12, M-20…M-23 and L-05; SR-16 describes the /end response.
v1.12: ID у каждой строки и ссылки на тест-кейсы; «Бадди в сессии» получил ID FR-38 (раньше делил FR-30 со следующим уроком); новые строки FR-17 (мастер) и FR-48 (итог недели) описывают уже работающее поведение; новые кейсы B-07, J-06, K-07 закрыли FR-37, FR-16, FR-07; FR-27 согласован с FR-29 — крестик в сессии сохраняет прогресс.v1.12: an ID on every row and links to test cases; “Buddy in session” got its own ID FR-38 (it used to share FR-30 with the next lesson); new rows FR-17 (wizard) and FR-48 (weekly summary) describe behavior that already works; new cases B-07, J-06, K-07 cover FR-37, FR-16, FR-07; FR-27 is aligned with FR-29 — the close button in a session saves progress.
16

Открытые вопросыOpen questions

  • Порог годности заготовки.Prefetch acceptance threshold. Заготовка отбрасывается при менее чем половине верных ответов; порог выбран без статистики, как и пороги этапов, и настраивается на сервере без релиза (FR-35).The prefetch is discarded when fewer than half of the answers are correct; like the stage thresholds, this threshold was chosen without statistics and can be tuned on the server without a release (FR-35).
  • Пороги этапов.Stage thresholds. 75/60 % и потолок в шесть уроков выбраны без статистики; после первых записей тестировщика подстроить на сервере без релиза.75/60 % and the six-lesson ceiling were chosen without statistics; tune them on the server without a release after the first tester records.
  • Push о готовности урока.Push when a lesson is ready. Требует EAS-проекта или ключа APNs: нужно решение владельца, какой путь выбрать (SR-09). От него же зависит свежесть статуса урока в виджете, пока приложение закрыто (FR-47).Requires an EAS project or an APNs key: the owner needs to decide which path to take (SR-09). The freshness of the lesson status in the widget while the app is closed depends on the same decision (FR-47).
  • Голос бадди.Buddy voice. Системный синтез на русском звучит механически; нейроголос Apple включается только настройкой устройства, свой TTS-сервис добавит цену и задержку к каждой реплике (FR-66). Отдельно: перебивание требует одновременных записи и воспроизведения в одной аудиосессии iOS.System speech synthesis in Russian sounds mechanical; the Apple neural voice can only be enabled in device settings, and a custom TTS service would add cost and latency to every line (FR-66). Separately: interruption requires simultaneous recording and playback in one iOS audio session.
Каждое требование прослеживается до принципа метода (M-n), экрана прототипа или контракта сервера в docs/ai-content.md. Статусы обновляются вместе с релизами.Each requirement traces back to a method principle (M-n), a prototype screen or the server contract in docs/ai-content.md. Statuses are updated with each release.