Skip to content

Latest commit

 

History

History
105 lines (87 loc) · 13.3 KB

File metadata and controls

105 lines (87 loc) · 13.3 KB

🤖 AGENTS.md: Инструкции и Архитектурные Правила (ScanReader Modernized)

Назначение файла: Главное руководство, свод архитектурных правил, инвариантов и протоколов разработки для AI-ассистентов в проекте распознавания судебных и исполнительных документов ScanReader. Базовый стек: Python 3.9+, Pydantic v2, OpenAI API / Ollama / vLLM (Qwen2.5-VL), Pillow, PyMuPDF, openpyxl, pandas, pytest. Основной пакет: src/scan_reader/ (структура PEP 517/621, единый источник правды). Контур безопасности: Закрытый корпоративный периметр. Локальный кэш без утечек памяти и секретов.


1. Архитектурный ландшафт платформы

                       ┌─────────────────────────────────────────┐
                       │   LegalDocPlatformFacade (facade.py)    │
                       │   Синхронный и пакетный API обработки    │
                       └────────────────────┬────────────────────┘
                                            │
        ┌───────────────────┬───────────────┴───────────────────┬───────────────────┐
        ▼                   ▼                                   ▼                   ▼
 ┌──────────────┐    ┌──────────────┐                    ┌──────────────┐    ┌──────────────┐
 │ file_proc    │    │ type_registry│                    │ Zero-Trust   │    │ Exporter     │
 │ (PDF, Image, │    │ (Плагины     │                    │ Auditor      │    │ (Excel       │
 │  DOCX, RTF)  │    │  doc_types/) │                    │ & Guardrails │    │  openpyxl)   │
 └──────────────┘    └──────────────┘                    └──────────────┘    └──────────────┘
        │                   │                                   │                   │
        └───────────────────┴───────────────┬───────────────────┴───────────────────┘
                                            ▼
                       ┌─────────────────────────────────────────┐
                       │           src/scan_reader/core/         │
                       │ utils, io_utils, token_tracker,         │
                       │ rate_limiter, cache, loader, json_exp   │
                       └─────────────────────────────────────────┘

2. Железные инженерные правила (Core Invariants)

🔴 Правило 0: Plan-First (Обязательное составление и утверждение плана)

  • Запрещено вносить любые изменения в код, схемы или плагины без предварительного составления детального плана и его утверждения.

🔴 Правило 1: Нулевая терпимость к «тихим сбоям» (Zero Silent Failures)

  • Запрещен паттерн except: pass.
  • Все ошибки логируются через get_logger() и изолируются в возвращаемых структурах (status: FAILED, errors: [...]), не прерывая пакетную обработку остальных документов.

🔴 Правило 2: Zero-Trust верификация юридических данных (verifier/)

  • Никогда не доверять выходу VLM вслепую.
  • Все ИНН (10 и 12 знаков), СНИЛС (11 знаков), ОГРН/ОГРНИП, БИК и расчетные счета обязаны верифицироваться алгоритмическими контрольными суммами.
  • Суммы сверяются по правилам, объявленным в verification.json плагина. Сверка обязана сравнивать два и более числа; наличие одного числа не является проверкой.
  • Пределы взыскания: 50 % / 70 % по ст. 99 229-ФЗ и 20 % по ст. 138 ТК РФ. Для вреда здоровью лимит 50 % не применяется вовсе (ФЗ № 314-ФЗ от 06.03.2019), и отдельного процентного потолка для него нет — нельзя утверждать обратное.
  • Даты процессуальных актов проверяются на хронологическую непротиворечивость.
  • Кросс-модальный гейт обязан указывать происхождение эталона (gate_source, gate_independent). Эталон от той же модели, что и извлечение, не является независимой сверкой и должен помечаться предупреждением.

🔴 Правило 3: Плагинная изоляция типов документов (doc_types/)

  • Ядро системы не содержит знаний о конкретных типах документов. Ни verifier/, ни core/ не упоминают ни одного имени поля или идентификатора плагина — это проверяется тестом-сканером по исходникам ядра.
  • Каждый тип документа оформляется как самодостаточный плагин в doc_types/<type_id>/ с 7 обязательными файлами: manifest.json, schema.py, prompt.md, classifier_rules.json, flat_columns.json, benchmark.json, autonomous.json.
  • Восьмой файл — verification.json: декларация проверок (стороны и их идентификаторы, банковский блок, правила сверки денег, лимит удержания, правила хронологии, поля гейта). Файл необязателен: плагин без него проходит только общие проверки, и добавление нового типа сводится к созданию папки.
  • Пути в verification.json допускают альтернативы через | (court.act_date|act_date) — один и тот же реквизит у разных типов лежит в разных местах.

🔴 Правило 4: Безопасный парсинг вывода моделей (_safe_parse_json)

  • Все ответы от VLM/LLM обязаны проходить через _safe_parse_json из core.utils с обязательной очисткой рассуждений <think>...</think> (Qwen/DeepSeek) и извлечением JSON из markdown code blocks.

🔴 Правило 5: Атомарный ввод-вывод и маскирование секретов (core.io_utils)

  • Запись артефактов и отчетов производится атомарно через write_atomic (временный файл + fsync + замена) во избежание повреждения файлов при сбоях питания/процесса.
  • Логирование и CLI сообщения автоматически фильтруют токены, пароли и паспортные данные через mask_secret().
  • Маскирование обязано покрывать record.args, а не только record.msg: вызов logger.info("токен %s", secret) иначе утекает. Маскируются только строки — приведение чисел к str ломает спецификаторы %d.
  • Все модули пакета обязаны использовать get_logger(), а не сырой logging.getLogger: последний обходит фильтр маскирования.

🔴 Правило 6: Разделение ответственности «схема ↔ аудитор»

  • СХЕМА (core/fields.py + schema.py плагина) отвергает то, что не может быть значением поля: длину, диапазон, допустимый набор, контрольную сумму идентификатора. Обязательны ge=0 на денежных полях, pattern на ИНН/КПП/БИК, model_validator(mode="after") для сверки идентификаторов.
  • АУДИТОР (verifier/) отвергает то, что семантически невозможно: арифметику, хронологию, статутные лимиты, неподтверждённые реквизиты.
  • Правило наименьшей строгости: нечитаемое значение не должно молча превращаться в пустое. parse_russian_currency("-150000") обязан вернуть -150000.0, чтобы ограничение ge=0 дало понятную ошибку, а не «поле не заполнено».
  • Плагины используют общие примеси ValidatedPartyMixin и ValidatedBankMixin; переобъявление inn/kpp в подклассе конфликтует с ними и запрещено.
  • Корневая модель плагина обязана объявлять __test__ = False.
  • Модели Pydantic, содержащие слово Test, обязаны иметь атрибут __test__ = False.

🔴 Правило 7: Кроссплатформенная санитизация имен файлов и UTF-8

  • При экспорте артефактов имена файлов очищаются через sanitize_filename().
  • Консольный вывод настраивается через setup_console_utf8() (единственная реализация; io_utils.configure_streams — её псевдоним).

🔴 Правило 8: Честность измерений и статусов

  • Статус верификации не является доказательством правильности. zero_trust_verified означает «все применимые проверки пройдены», а не «100 %». Формулировки «100 % подтверждено» и «готов к безоговорочному автоимпорту» в документации запрещены.
  • Поле, отсутствующее с обеих сторон при сравнении с эталоном, исключается из знаменателя, а не получает 100 баллов. Поле, выдуманное моделью и отсутствующее в эталоне, штрафуется и ломает validation_passed.
  • Тип поля в benchmark.json обязан быть из известного словаря (exact, numeric/number, text/string, inn, date); неизвестный тип отвергается при загрузке плагина. Сравнение сумм строкой (а не числом) — недопустимо.
  • Любая метрика сопровождается measurement_caveats: каким режимом измерена, сколько документов сверено с эталоном, на скольких полях держится цифра. Сводка запуска обязана передавать эти сведения дальше, а не отбрасывать их.
  • Эталон сам подлежит проверке: невалидный ИНН/СНИЛС/БИК в data/ground_truth/ делает измерение бессмысленным, поскольку система штрафуется за несуществующую ошибку.

3. Протокол тестирования

Запуск полного тестового сьюта:

py -3 -m pytest

Замер тестового покрытия пакета (порог — 70 %):

py -3 -m pytest --cov=scan_reader --cov-report=term-missing

Проверка линтером и типами:

py -3 -m ruff check src tests examples
py -3 -m mypy