Add a resumable standard-library normalization pipeline for the downloaded CBD archive. It produces canonical bilingual metadata, sanitized HTML, plain text, deterministic fragments, checksums, quality markers, and an SQLite processing manifest while preserving the raw source. Recover document-list pagination when the Ministry API exhausts request retries, and cover that scenario with a regression test. Document the normalization workflow and frontend-search MVP plan, include the source functional specification, ignore local runtime logs, and bump the backend version to 0.2.1.
11 KiB
Задание агенту: нормализация документов ЦБД Минюста КР
Цель
Реализовать первую рабочую версию воспроизводимого нормализатора локального
архива data/minjust-cbd. Нормализованные данные должны быть пригодны для
последующей загрузки в OpenSearch, backend API и RAG, но подключение этих
сервисов в текущую задачу не входит.
Текущее состояние
- загрузчик находится в
backend/ingestion/minjust_cbd.py; - сырой архив хранится в
data/minjust-cbdи исключён из Git; - в манифесте 209 811 успешно загруженных документов;
- 13 кодов остаются в таблице
errorsи отсутствуют в таблицеdocuments; - документ содержит
metadata.jsonи каталогeditions; - редакция содержит
metadata.json,ru.htmlи/илиky.html, иногда изображения; - HTML создан Microsoft Word, может содержать некорректный
<meta charset=unicode>, служебные стили и неполную разметку; - файлы архива записаны загрузчиком в UTF-8;
- часть документов одноязычная, а часть не содержит HTML-текста.
Обязательные ограничения
- Не изменять и не перезаписывать
data/minjust-cbd. - Не запускать полный проход по архиву во время автоматических тестов.
- Не подключать PostgreSQL, OpenSearch, OCR, embeddings, машинный перевод и сетевые API.
- Сначала использовать стандартную библиотеку. Новая зависимость допустима только если на реальных образцах доказано, что стандартный HTML-парсер не обеспечивает корректность или безопасность.
- Все записи выполнять атомарно.
- Ошибка одного документа не должна останавливать длительный прогон.
- Повторный запуск должен пропускать неизменившиеся документы.
- Не изменять пользовательские файлы
logs/, исходный DOCX и несвязанные незакоммиченные изменения.
Размещение
Использовать существующую backend-структуру:
backend/
normalization/
minjust_cbd.py
Результат по умолчанию:
data/minjust-normalized/
manifest.sqlite3
documents/<document_code>/document.json
documents/<document_code>/editions/<edition_code>/edition.json
documents/<document_code>/editions/<edition_code>/<lang>/content.html
documents/<document_code>/editions/<edition_code>/<lang>/content.txt
documents/<document_code>/editions/<edition_code>/<lang>/fragments.json
Каталог уже покрывается правилом игнорирования data/.
Канонические данные
document.json
Сохранить как минимум:
schema_version;source_code;- двуязычные
class,type,title,name,status; - номера и даты без юридически неподтверждённых выводов;
- флаги публичности;
- органы, публикации, ключевые слова и классификаторы с сохранением дерева;
- пути листьев иерархий для будущих фильтров;
- ссылки из
Referencesбез выдумывания связей; available_languages;- список редакций;
- путь к источнику и SHA-256 исходных файлов;
- версию нормализатора и время обработки.
Пустые строки привести к null, но не переводить значения и не заменять
официальные формулировки собственными.
edition.json
Сохранить:
- исходный код редакции;
- двуязычное название;
- исходный тип;
- доступные языки;
- изображения без бинарных данных;
- контрольные суммы источников;
- признаки качества.
Не считать дату из Name датой вступления редакции в силу и не назначать
актуальную редакцию без подтверждённого правила источника.
Языковой вариант
Для каждого имеющегося ru.html или ky.html сформировать:
content.html— безопасный HTML для frontend;content.txt— извлечённый текст с сохранением смысловых переносов;fragments.json— упорядоченные адресуемые блоки.
Сырой HTML всегда читать как UTF-8, не доверяя его meta charset.
Очистка HTML
- удалить
script,style,meta,link, комментарии и служебные элементы; - удалить обработчики событий, inline-стили и опасные URL;
- разрешить минимальный набор структурных тегов: заголовки, абзацы,
pre, списки, таблицы, безопасные ссылки, изображения и базовое текстовое выделение; - нормализовать Unicode в NFC;
- преобразовать неразрывные пробелы и избыточные пробелы только в
content.txt, не искажая отображаемый юридический текст; - не загружать внешние ресурсы;
- относительные изображения связывать только с файлами внутри редакции;
- неизвестную или сломанную разметку сохранять как текст, а не терять молча.
Фрагменты
Минимальная версия должна создавать фрагмент для каждого содержательного блочного элемента. Распознавание статей и пунктов допускается только простыми проверяемыми правилами RU/KY; обычный абзац является fallback.
Каждый фрагмент содержит:
- стабильный
id; document_code,edition_code,language;- порядковую позицию;
- тип блока;
- чистый текст;
- SHA-256 текста.
Идентификатор должен быть детерминированным и включать документ, редакцию, язык и позицию. Не добавлять сложное сопоставление фрагментов между редакциями — это отдельная будущая задача.
Манифест и возобновление
SQLite-манифест должен хранить:
- код документа;
- SHA-256 набора исходных файлов;
- версию схемы и нормализатора;
- время успешной обработки;
- состояние и текст последней ошибки.
Если checksum и версия нормализатора не изменились, документ пропускается.
После успешной повторной обработки ошибка удаляется. Добавить --limit и
понятный терминальный прогресс, пригодный для долгого запуска.
CLI и импорт из будущего backend
CLI запускается из корня репозитория:
python3 backend/normalization/minjust_cbd.py
Предусмотреть параметры:
--input;--output;--limit;--refresh;--log-level.
Основную функцию можно импортировать без запуска CLI. Не создавать планировщик, очередь задач или framework-интеграцию.
Проверки
Добавить один компактный тестовый модуль, который проверяет:
- русскую редакцию;
- кыргызскую редакцию;
- двуязычную редакцию;
- Word HTML с опасным
script, inline-стилем иjavascript:URL; - документ без HTML;
- повторный запуск и пропуск неизменившегося документа;
- продолжение после ошибки одного документа;
- детерминированные fragment ID и checksums.
Провести пилотный read-only запуск на небольшой реальной выборке через
--limit, не нормализовать весь архив в рамках разработки.
Документация и версия
- описать запуск, структуру результата и ограничения в
backend/README.md; - отметить реализацию в
docs/operations/project-status.md; - это новая обратно совместимая backend-функция: увеличить minor-версию backend по SemVer;
- обновить все отображаемые backend-версии и footer, не меняя версию Telegram-бота;
- frontend по-прежнему помечать как не созданный.
Критерии приёмки
- сырой архив не изменён;
- тесты проходят;
git diff --checkпроходит;- пилотный запуск завершается без остановки на отдельных ошибках;
- повторный пилотный запуск пропускает неизменившиеся документы;
- unsafe HTML не попадает в
content.html; - каждый фрагмент прослеживается до документа, редакции, языка и исходного файла;
- отсутствуют молча потерянные HTML или ошибки;
- реализация не содержит PostgreSQL/OpenSearch/RAG-кода «на будущее».
Акылдаш · Telegram-бот v0.2.2 · Backend v0.2.1 · Frontend — не создан