# Второе занятие: пять проверок

Правим catalog.py и models.py. Готовый транспорт client.py менять не требуется. После правок перезапускаем `run_client.py`, сохраняя псевдоним и файл идентичности. Локальная ошибка должна быть исправлена до следующей проверки. Преподаватель может запускать проверку одного участника.

## 1. Присутствие
Запустите исходную раздатку, дождитесь запроса преподавателя или автоопроса каждые 5 минут. ФИО передаётся автоматически отдельно. Рабочий маршрут default/v1 уже есть, можно перенести свою творческую обработку из первой практики.

## 2. Разные модели
Напишите register_model и run_inference. Зарегистрируйте default, upper, reverse. Для первого шага допускается внутренний каталог по имени; перед проверкой выдавайте метаданные version=v1. default — ваша творческая мока, возвращающая строку. upper — точный text.upper(), reverse — точный text[::-1]. Никаких префиксов и worker_id внутри этих двух ответов. Отсутствующее model выбирает default. Для проверки default должен возвращать строку без исключения.

## 3. Разные версии
Расширьте ключ каталога до (model,version). Две функции frame/v1 и frame/v2 возвращают ровно три строки:
```
=====
исходный запрос без изменений
=====
```
```
-----
исходный запрос без изменений
-----
```
Без завершающего перевода строки. Проверочный запрос однострочный, включая пробелы и Unicode. У frame версия по умолчанию v1. Сервер вызывает v1, v2, снова v1, затем frame без версии. Метаданные ответа должны совпадать с исполнением. Реализация через обёртку/декоратор рекомендована, проверяется поведение. Повторная регистрация существующей пары должна вызывать ошибку, не заменять код.

## 4. Ответ-ошибка (дополнительно)
Неизвестное имя: MODEL_NOT_FOUND. Неизвестная версия существующей frame: VERSION_NOT_FOUND. Зарегистрируйте broken/v1 — функцию, которая выбрасывает исключение. Запускатор возвращает INFERENCE_ERROR. В готовом client.py поддержано преобразование `ValueError('КОД')` в поле error. Проверка после трёх ошибок вызывает upper: клиент должен остаться жив. Явно неправильный запрос нельзя подменять default.

## 5. Пакет моделей с сервера (бонус)
Отдельная презентация: https://topic02.130.193.40.80.sslip.io/materials/bonus.html
Пошаговые средства Python и контракт: BONUS.md.

Реализуйте install_release(manifest). INSTALL передаёт `{"registry_url":"/registry/models"}`. Получите releases, пройдите по всему списку, скачайте и проверьте каждый файл, загрузите infer и зарегистрируйте соответствующие model/version. Сейчас это семь выпусков: server_echo, oracle_location, oracle_name, weather_mood, coin_oracle, dad_joke, ascii_cat (v1). Не зашивайте список в установщик.

После INSTALLED сервер вызовет каждый выпуск. Точное ожидаемое поведение видно в исходниках; все функции сохраняют входную строку. Отметка ставится только за весь пакет. Повторная установка одинакового выпуска не должна ломать клиент. Готового установщика в ученической раздатке нет; отдельные операции объяснены в бонусной презентации. Ошибки из задания 4 также разбираются там.

## Свой пульт (сквозное развитие)
Ваш отправитель из первой практики теперь выбирает model/version. Можно сохранять любимые запросы, сравнивать v1/v2, показывать каталог, историю и ошибки. Это личный инструмент для следующих занятий, отдельной обязательной проверки «домашки ради домашки» нет.
