Добавить нормализацию документов ЦБД Минюста КР #8

Merged
admin merged 2 commits from feature/minjust-document-normalization into main 2026-08-12 06:54:19 +00:00
Owner

Что сделано

  • добавлен возобновляемый нормализатор локального архива ЦБД без внешних Python-зависимостей;
  • формируются канонические двуязычные метаданные, безопасный HTML, чистый текст и детерминированные фрагменты;
  • добавлены SHA-256, показатели качества, атомарная публикация результатов и SQLite-манифест для пропуска неизменившихся документов и повторной обработки ошибок;
  • загрузчик теперь пересоздаёт временный список документов после исчерпания повторов запроса страницы, а не только после HTTP 404;
  • добавлены тесты нормализатора и регрессионный тест восстановления пагинации;
  • добавлены план frontend поисковой СПС, исходное функциональное задание и задание агенту по нормализации;
  • локальные data/ и logs/ исключены из Git;
  • версия backend повышена до 0.2.1.

Ограничения этой версии

OCR, перевод, юридическое сопоставление редакций, PostgreSQL/OpenSearch и RAG намеренно оставлены для следующих этапов. Исходный архив не изменяется.

Проверка

  • PYTHONPATH=backend python3 -m unittest backend/test_minjust_cbd.py backend/test_minjust_normalization.py -v — 8 тестов, OK;
  • python3 -m unittest discover -s tools/telegram-bot -v — 6 тестов, OK;
  • python3 -m py_compile backend/ingestion/minjust_cbd.py backend/normalization/minjust_cbd.py — OK;
  • git diff --check — OK;
  • полный проход ранее нормализовал 209811 документов без ошибок.
## Что сделано - добавлен возобновляемый нормализатор локального архива ЦБД без внешних Python-зависимостей; - формируются канонические двуязычные метаданные, безопасный HTML, чистый текст и детерминированные фрагменты; - добавлены SHA-256, показатели качества, атомарная публикация результатов и SQLite-манифест для пропуска неизменившихся документов и повторной обработки ошибок; - загрузчик теперь пересоздаёт временный список документов после исчерпания повторов запроса страницы, а не только после HTTP 404; - добавлены тесты нормализатора и регрессионный тест восстановления пагинации; - добавлены план frontend поисковой СПС, исходное функциональное задание и задание агенту по нормализации; - локальные data/ и logs/ исключены из Git; - версия backend повышена до 0.2.1. ## Ограничения этой версии OCR, перевод, юридическое сопоставление редакций, PostgreSQL/OpenSearch и RAG намеренно оставлены для следующих этапов. Исходный архив не изменяется. ## Проверка - PYTHONPATH=backend python3 -m unittest backend/test_minjust_cbd.py backend/test_minjust_normalization.py -v — 8 тестов, OK; - python3 -m unittest discover -s tools/telegram-bot -v — 6 тестов, OK; - python3 -m py_compile backend/ingestion/minjust_cbd.py backend/normalization/minjust_cbd.py — OK; - git diff --check — OK; - полный проход ранее нормализовал 209811 документов без ошибок.
agent added 1 commit 2026-08-12 05:32:43 +00:00
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.
Author
Owner

Независимое code review

Итог: перед слиянием нужны исправления.

Замечания

  1. Высокая — ошибочная конфигурация путей может удалить исходный архив. backend/normalization/minjust_cbd.py:534-545, backend/normalization/minjust_cbd.py:574-577. Код не проверяет пересечение input_root и output. Если передать одинаковые пути (например, --input data/minjust-cbd --output data/minjust-cbd), целевой каталог output/documents/<code> совпадает с исходным документом: publish_directory() переносит сырой каталог в .previous, ставит на его место нормализованный результат и затем удаляет backup. На временных данных сценарий воспроизведён: metadata.json исходника исчез, остался document.json. Это прямо нарушает обязательное требование не изменять data/minjust-cbd. Нужно до открытия manifest и обработки документов сравнить resolve() путей (с учётом symlink) и отклонять равные/пересекающиеся input/output; добавить регрессионный тест.

  2. Средняя — manifest может навсегда скрыть отсутствующий результат после прерывания публикации. backend/normalization/minjust_cbd.py:517-531, backend/normalization/minjust_cbd.py:569-572. publish_directory() сначала переносит target в .previous, затем ставит staged на его место. Если процесс завершится между этими операциями, target отсутствует, но manifest по-прежнему содержит прежний success. При следующем обычном запуске совпадение checksum/schema/version приводит к skipped, без проверки существования documents/<code>/document.json и без восстановления .previous. Сценарий воспроизведён в /tmp: повторный запуск вернул skipped=1, target остался отсутствовать. Нужны восстановление незавершённой публикации при старте и/или проверка целевого результата перед skip; добавить тест имитации прерывания.

  3. Низкая — некорректный URL в HTML валит нормализацию всего документа вместо удаления атрибута. backend/normalization/minjust_cbd.py:222-225, backend/normalization/minjust_cbd.py:236-255. urlsplit() может выбросить ValueError; пример href="http://[" воспроизведён. Ошибка из санитайзера переводит весь документ в error. На входной границе безопаснее считать такой href/src недопустимым и удалить атрибут; нужен граничный тест.

Что проверено

  • изучен полный diff origin/main...07381ad (17 файлов);
  • PYTHONPATH=backend python3 -m unittest backend/test_minjust_cbd.py backend/test_minjust_normalization.py -v8 тестов, OK;
  • python3 -m unittest discover -s tools/telegram-bot -v6 тестов, OK;
  • python3 -m py_compile backend/ingestion/minjust_cbd.py backend/normalization/minjust_cbd.pyOK;
  • git diff --check origin/main...HEADOK;
  • отдельно проверены санитайзер, конфликт input/output и состояние после прерванной публикации на временных данных. Полный проход и запись в локальный data/ не выполнялись.

Остальная реализация выглядит целостно: нормализатор использует стандартную библиотеку, сохраняет происхождение и контрольные суммы, разделяет RU/KY, публикует документ через staging и изолирует ошибку отдельной записи; исправление восстановления пагинации покрыто регрессионным тестом. Остаточные риски после перечисленных исправлений: отсутствие межпроцессной блокировки и стоимость полного повторного хеширования архива примерно из 210 тысяч документов.

## Независимое code review **Итог: перед слиянием нужны исправления.** ### Замечания 1. **Высокая — ошибочная конфигурация путей может удалить исходный архив.** `backend/normalization/minjust_cbd.py:534-545`, `backend/normalization/minjust_cbd.py:574-577`. Код не проверяет пересечение `input_root` и `output`. Если передать одинаковые пути (например, `--input data/minjust-cbd --output data/minjust-cbd`), целевой каталог `output/documents/<code>` совпадает с исходным документом: `publish_directory()` переносит сырой каталог в `.previous`, ставит на его место нормализованный результат и затем удаляет backup. На временных данных сценарий воспроизведён: `metadata.json` исходника исчез, остался `document.json`. Это прямо нарушает обязательное требование не изменять `data/minjust-cbd`. Нужно до открытия manifest и обработки документов сравнить `resolve()` путей (с учётом symlink) и отклонять равные/пересекающиеся input/output; добавить регрессионный тест. 2. **Средняя — manifest может навсегда скрыть отсутствующий результат после прерывания публикации.** `backend/normalization/minjust_cbd.py:517-531`, `backend/normalization/minjust_cbd.py:569-572`. `publish_directory()` сначала переносит target в `.previous`, затем ставит staged на его место. Если процесс завершится между этими операциями, target отсутствует, но manifest по-прежнему содержит прежний `success`. При следующем обычном запуске совпадение checksum/schema/version приводит к `skipped`, без проверки существования `documents/<code>/document.json` и без восстановления `.previous`. Сценарий воспроизведён в `/tmp`: повторный запуск вернул `skipped=1`, target остался отсутствовать. Нужны восстановление незавершённой публикации при старте и/или проверка целевого результата перед skip; добавить тест имитации прерывания. 3. **Низкая — некорректный URL в HTML валит нормализацию всего документа вместо удаления атрибута.** `backend/normalization/minjust_cbd.py:222-225`, `backend/normalization/minjust_cbd.py:236-255`. `urlsplit()` может выбросить `ValueError`; пример `href="http://["` воспроизведён. Ошибка из санитайзера переводит весь документ в `error`. На входной границе безопаснее считать такой `href/src` недопустимым и удалить атрибут; нужен граничный тест. ### Что проверено - изучен полный diff `origin/main...07381ad` (17 файлов); - `PYTHONPATH=backend python3 -m unittest backend/test_minjust_cbd.py backend/test_minjust_normalization.py -v` — **8 тестов, OK**; - `python3 -m unittest discover -s tools/telegram-bot -v` — **6 тестов, OK**; - `python3 -m py_compile backend/ingestion/minjust_cbd.py backend/normalization/minjust_cbd.py` — **OK**; - `git diff --check origin/main...HEAD` — **OK**; - отдельно проверены санитайзер, конфликт input/output и состояние после прерванной публикации на временных данных. Полный проход и запись в локальный `data/` не выполнялись. Остальная реализация выглядит целостно: нормализатор использует стандартную библиотеку, сохраняет происхождение и контрольные суммы, разделяет RU/KY, публикует документ через staging и изолирует ошибку отдельной записи; исправление восстановления пагинации покрыто регрессионным тестом. Остаточные риски после перечисленных исправлений: отсутствие межпроцессной блокировки и стоимость полного повторного хеширования архива примерно из 210 тысяч документов.
agent added 1 commit 2026-08-12 06:49:58 +00:00
Reject overlapping source and destination roots before any write so normalization cannot replace the raw Ministry archive.

Recover an interrupted directory publication before resume checks and require the normalized target to exist before skipping a manifest success.

Treat malformed link and image URLs as unsafe attributes, add regressions for all review findings, and bump the backend version to 0.2.2.
Author
Owner

Повторное code review после 752bd38

Итог: замечания из предыдущего review закрыты, PR можно сливать.

Проверка прежних замечаний

  1. HIGH — пересечение input/output: закрыто. Добавленный validate_roots() сравнивает разрешённые абсолютные пути и отклоняет равенство, вложение output в input и input в output до создания выходного каталога и manifest. Тест проверяет все три варианта и неизменность исходного metadata.json.

  2. MEDIUM — восстановление .previous и ошибочный skip: закрыто. recover_directory(target) вызывается перед вычислением решения о skip: если target отсутствует, backup атомарно возвращается на место; если target уже опубликован, оставшийся backup удаляется. Дополнительная проверка target.is_dir() не позволяет manifest со статусом success пропустить полностью отсутствующий результат. Регрессионный тест воспроизводит прерывание target -> .previous и подтверждает восстановление до skip.

  3. LOW — malformed URL: закрыто. safe_link() и safe_image() теперь перехватывают ValueError от urlsplit() и считают URL небезопасным. Тест покрывает href="http://[" и src="http://["; документ нормализуется, URL отсутствует в безопасном HTML.

Регрессии и проверки

Новых блокирующих замечаний в diff 07381ad..752bd38 не найдено. Исправления локальны, не добавляют зависимостей, backend patch-версия корректно повышена до 0.2.2, документация и footer-версии обновлены.

  • PYTHONPATH=backend python3 -m unittest backend/test_minjust_cbd.py backend/test_minjust_normalization.py -v10 тестов, OK;
  • python3 -m unittest discover -s tools/telegram-bot -v6 тестов, OK;
  • python3 -m py_compile backend/ingestion/minjust_cbd.py backend/normalization/minjust_cbd.pyOK;
  • git diff --check origin/main...HEADOK.

Полный проход и изменения локального data/ не выполнялись. Неблокирующие прежние остаточные риски (межпроцессная блокировка и стоимость полного повторного хеширования около 210 тысяч документов) остаются отдельными будущими задачами и не препятствуют слиянию этого PR.

## Повторное code review после `752bd38` **Итог: замечания из предыдущего review закрыты, PR можно сливать.** ### Проверка прежних замечаний 1. **HIGH — пересечение input/output: закрыто.** Добавленный `validate_roots()` сравнивает разрешённые абсолютные пути и отклоняет равенство, вложение output в input и input в output до создания выходного каталога и manifest. Тест проверяет все три варианта и неизменность исходного `metadata.json`. 2. **MEDIUM — восстановление `.previous` и ошибочный skip: закрыто.** `recover_directory(target)` вызывается перед вычислением решения о skip: если target отсутствует, backup атомарно возвращается на место; если target уже опубликован, оставшийся backup удаляется. Дополнительная проверка `target.is_dir()` не позволяет manifest со статусом `success` пропустить полностью отсутствующий результат. Регрессионный тест воспроизводит прерывание `target -> .previous` и подтверждает восстановление до skip. 3. **LOW — malformed URL: закрыто.** `safe_link()` и `safe_image()` теперь перехватывают `ValueError` от `urlsplit()` и считают URL небезопасным. Тест покрывает `href="http://["` и `src="http://["`; документ нормализуется, URL отсутствует в безопасном HTML. ### Регрессии и проверки Новых блокирующих замечаний в diff `07381ad..752bd38` не найдено. Исправления локальны, не добавляют зависимостей, backend patch-версия корректно повышена до `0.2.2`, документация и footer-версии обновлены. - `PYTHONPATH=backend python3 -m unittest backend/test_minjust_cbd.py backend/test_minjust_normalization.py -v` — **10 тестов, OK**; - `python3 -m unittest discover -s tools/telegram-bot -v` — **6 тестов, OK**; - `python3 -m py_compile backend/ingestion/minjust_cbd.py backend/normalization/minjust_cbd.py` — **OK**; - `git diff --check origin/main...HEAD` — **OK**. Полный проход и изменения локального `data/` не выполнялись. Неблокирующие прежние остаточные риски (межпроцессная блокировка и стоимость полного повторного хеширования около 210 тысяч документов) остаются отдельными будущими задачами и не препятствуют слиянию этого PR.
admin merged commit 30065925e4 into main 2026-08-12 06:54:19 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: agent/akyldash#8