# Исправленные проблемы проекта YOLO Train TUI Дата исправления и повторной проверки: 2026-07-17 ## Итог Все 11 ранее зафиксированных дефектов исправлены и покрыты регрессионными проверками. | ID | Приоритет | Статус | Исправление | |---|---|---|---| | BUG-001 | Критический | Исправлено | `subprocess_runner.main()` возвращает код, а `SystemExit` создаётся только снаружи обрабатывающего блока | | BUG-002 | Высокий | Исправлено | Перед каждым запуском `prepare_run()` сбрасывает состояние остановки | | BUG-003 | Высокий | Исправлено | Родитель отправляет кооперативный сигнал; принудительный `kill()` используется только после таймаута | | BUG-004 | Высокий | Исправлено | Запрос, сделанный до готовности subprocess, сохраняется и доставляется после маркера `READY` | | BUG-005 | Высокий | Исправлено | Detection-style авторазбиение запрещено для `classify` в UI и конфигурации | | BUG-006 | Средний | Исправлено | `.yaml`/`.yml` разбираются через `yaml.safe_load()`, поле `names` валидируется | | BUG-007 | Средний | Исправлено | Датасет с одним изображением отклоняется с понятной ошибкой | | BUG-008 | Средний | Исправлено | Изображения и метки ищутся рекурсивно с сохранением вложенных путей | | BUG-009 | Средний | Исправлено | Каждый результат создаётся в уникальном `.yolo-tui/splits/` без перезаписи пользовательского `split/` | | BUG-010 | Низкий | Исправлено | Traceback выводится в журнал TUI; абсолютный путь другого пользователя удалён | | BUG-011 | Низкий | Исправлено | Явно указанный отсутствующий или некорректный файл классов вызывает точную ошибку без fallback | ## Жизненный цикл обучения - Дочерний процесс устанавливает обработчики остановки и только затем печатает `__YOLO_TUI_READY__`. - Если пользователь нажал «Остановить» раньше, родитель запоминает запрос и отправляет его после получения маркера готовности. - Дочерний `TrainingRunner` устанавливает `trainer.stop = True`; Ultralytics останавливается между пакетами данных, затем выполняет штатную финализацию и завершающие callbacks. - Если процесс не завершился за 30 секунд, используется принудительный fallback. - После завершения ссылка на subprocess и таймер очищаются; перед следующим запуском флаг остановки сбрасывается. ## Работа с датасетами - Текущий splitter предназначен для задач `detect`, `segment`, `pose` и `obb` со структурой `images/` + `labels/`. - Для `classify` требуется готовый каталог с `train`/`val` и подкаталогами классов; несовместимый переключатель в UI отключён. - Поддерживаются `classes.txt`, `.yaml` и `.yml`; YAML может хранить `names` как список или словарь с последовательными ID от 0. - Явный путь к классам считается обязательным и не заменяется автопоиском при опечатке или ошибке формата. - Split требует минимум два изображения и рекурсивно обрабатывает вложенные каталоги. - Файлы каждого запуска создаются эксклюзивно в отдельном управляемом каталоге. ## Проверка Выполнены команды: ```text uv run pytest -q uv run python -m compileall -q src tests git diff --check ``` Результат: `38 passed`; ошибок компиляции и форматирования diff нет. Регрессионные тесты проверяют: 1. успешный и ошибочный коды `subprocess_runner.main()`; 2. сброс остановки между запусками; 3. кооперативный сигнал вместо немедленного `terminate()`; 4. доставку раннего запроса после готовности subprocess; 5. запрет авторазбиения для `classify`; 6. пользовательские YAML-файлы классов и ошибочный явный путь; 7. датасеты из одного и двух изображений; 8. вложенные изображения и метки; 9. сохранность пользовательского каталога `split/` и уникальность результатов.