Разработка
Подготовка окружения
Одного uv sync для зелёного прогона тестов недостаточно:
uv sync # группы default и dev
npm --prefix webapp ci # без этого inv test пропустит фронтенд
inv test пропускает набор тестов фронтенда, когда нет
webapp/node_modules, а CI — нет: прогон без npm ci неполный. Добавление
python-зависимости требует ещё и uv lock; CI ставит зависимости с --frozen.
languages.toml нужен только чтобы запустить приложение, и inv dev создаёт
его из languages.example.toml.
Команды
| Задача | Команда |
|---|---|
| Линт, форматирование и проверка типов | uv run inv pre |
| Полный набор тестов (Python + фронтенд) | uv run inv test |
| Только Python-тесты | uv run pytest |
| Только тесты фронтенда | npm --prefix webapp test |
| Дев-сервер с автоперезагрузкой | uv run inv dev |
Сборка PWA в _static/ |
uv run inv build-static |
| Список всех задач | uv run inv --list |
Префикс uv run не нужен внутри активированного .venv.
Warning
Никогда не вызывайте Ruff напрямую. inv pre запускает ruff, ruff-format,
pyrefly и хуки гигиены файлов с настройками проекта — это единственная
проверка, совпадающая с CI.
Для горячей перезагрузки при работе над Vue запустите дев-сервер Vite во втором
терминале — он проксирует /api на бэкенд, слушающий порт 8080:
npm --prefix webapp run dev # http://127.0.0.1:5173
vite dev не регистрирует service worker. Поведение офлайн и PWA проверяйте на
настоящей сборке _static/.
Язык интерфейса
Строки PWA лежат в webapp/src/i18n/{en,ru}.js и достаются через t("key");
переключатель в шапке пишет выбор в localStorage, а клиент отправляет его в
заголовке Accept-Language при каждом запросе к API. Подсказки, которые
показывает сам бэкенд — проверка ввода и ошибки неизвестного языка, — лежат в
src/echo_words/i18n.py и выбираются по этому заголовку для каждого запроса.
Оба набора тестов проверяют, что в двух каталогах ровно одинаковые ключи, так
что строка, добавленная в одном языке, не пропадёт молча в другом.
Текст, который сервер отдаёт в общую историю и поток событий, — статусы карточек
и сам разбор — не зависит от клиента и так не переводится. Язык разбора задаётся
ECHOWORDS_TARGET_LANG.
Тесты
Каждый новый модуль или функция приезжают с тестами в том же коммите. Никаких
настоящих сетевых вызовов, синхронизаций Anki, обращений к LLM или TTS в
тестах — все границы подменяются. Стенд в experiments/ — санкционированное
исключение, в CI он не входит.
CI прогоняет матрицу Python 3.12/3.13, набор тестов Vitest и Ruff. Отчёты публикуются в Allure.
Спецификации
В spec/ лежат функциональное описание и записи о принятых решениях —
интервальные повторения, TTS, LLM-бэкенд, интерфейс и хост
развёртывания. На этот сайт они не публикуются. Если spec/ и код расходятся,
прав код.