Требования
Реализуйте CLI-каталог домашней библиотеки с командами add, list, update, delete и find. У книги есть уникальный стабильный ID, название, автор, год издания, ISBN как необязательная строка, жанр и состояние чтения: unread, reading или read. Название и автор обязательны; год должен быть целым в разумном диапазоне 0–9999. При добавлении программа сама создаёт ID и печатает его, чтобы им можно было пользоваться дальше. Find ищет подстроку без учёта регистра по названию, автору и жанру. List поддерживает фильтр --status и всегда сортирует книги по названию без учёта регистра, затем по ID.
Храните данные в одном JSON-файле, путь к которому задаётся общим флагом --data; если флаг не указан, используйте library.json в текущей директории. Команды update и delete требуют --id. Update принимает поля через именованные флаги, меняет только переданные поля и повторно проверяет итоговую запись. Неизвестный ID — понятная ошибка. Дублирующийся ISBN допускается, поскольку это не всегда одна и та же запись. При первом запуске отсутствие файла означает пустую библиотеку; операция чтения списка ничего не должна записывать на диск.
Каждая изменяющая команда читает весь файл, проверяет корректность JSON и уникальность ID, выполняет изменение и атомарно заменяет файл через временный файл в той же директории и rename. Повреждённый JSON нельзя трактовать как пустой каталог или перезаписывать: завершитесь с ошибкой, сохранив байты исходника. Ошибки ввода-вывода должны быть понятными и ненулевыми. Добавьте тесты командной логики и файлового поведения с временными каталогами.
Структура программы
Вынесите правила книги и поиска в internal/library: тип записи, проверку полей, фильтрацию и сортировку. Отдельно реализуйте JSON-хранилище чтения и атомарной записи; main.go только разбирает команду, связывает хранилище с операцией и выводит результат или ошибку. Ошибки возвращайте вызывающему коду, не завершайте процесс из пакета.