proposal, design (D-1…D-9, решения без обсуждения №1–12), дельты спек image-recognition-gateway (папки, очистка под флагом, нормализация, справочники с редакциями, статусы) и scan-emulator (пара по sha256, набор по умолчанию). tasks.md заполняется планом. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
7.0 KiB
Proposal: Срез 3a — горячие папки как у armka_file_worker и нормализатор OCR → statementDocument v1.2
Срез: 3a, первая половина Среза 3 «ББ/ОФР: scan-gateway, маппинг форм, логические проверки» (../docs/context/09-delivery-plan.md).
Репозиторий: scan-gateway. Issue: RSHB/arm-scan-gateway#6.
Соседние: fixtures — пары PDF+JSON и ocr/expected_normalize/ (issue заводится при плане); docs — bounded-PR без change
(03-architecture.md, OQ-137, §11.1 п. 6 и п. 9, новые OQ). Срез 3b (маппинг statementDocument в ядре, проверки §7,
подтверждение, чек-лист) — отдельный change в arm-core.
Why
Срез 0 оставил scan-gateway с NullNormalizer: любой успешный ответ ИС Сканирование превращается в NOT_IMPLEMENTED.
Срез 2b даёт ядру statementDocument v1.2 из Excel; чтобы ядро в 3b маппило формы одним кодом для обоих источников,
PDF-путь должен отдавать тот же документ. Второй повод — 06.10.2026 в контуре проверен PDFWorker старого АРМ
(RSHB/armka_file_worker): его раскладка горячих папок ИС принята владельцем как эталон (OQ-137), а модуль очистки OCR
(ofr_result_conversion) разрешено переносить (§11.1 05-domain-rules.md, единственное исключение для reference-old-arm).
What Changes
- Горячие папки (
src/gateway/): входящий файл —<Input>/<job_id>.<ext>(расширение исходного имени в нижнем регистре) вместо<job_id>_<original_name>; временный.partпо-прежнему в<SCAN_TMP_DIR>(решение владельца: вInputвременных файлов не класть, ИС может их подхватить), rename без замены — существующее назначение считается доставленным. Новый методcleanup(job_id, ext)под флагомSCAN_CLEANUP(по умолчаниюfalse): удаляетOutput/<job_id>/*.json, каталог, входящий файл (и его.done-вариант эмулятора) и осиротевший.part; любое удаление только при включённом флаге (на SMB может не быть прав). Ошибка удаления не меняет исход задания. - Эмулятор (
src/scan_emulator/): входящий<uuid>.<ext>; пара фикстур ищется по sha256 содержимого среди не-JSON файловSCAN_FIXTURES_DIR(aep_6.pdf→aep_6.json+aep_6_*.json); промах → наборSCAN_EMULATOR_DEFAULT, если задан, иначе ответ-ошибкаINVALID_DOCUMENT..part/.tmp/.doneигнорируются. - Нормализатор (
src/normalizer/ocr/):OcrNormalizerреализует протоколNormalizerСреза 0 — конвейер чистых функцийtext→dates→amounts→layout→rows→header→document; проверенные на стенде функции старого ядра (двойники,|, разбор дат, суммы, раскладка с шапкой и без) переносятся дословно по §11.1; выход — pydantic-модели контракта v1.2 (StatementDocument), по одному документу на таблицуtable_structure[i].checksне считаются (их считает ядро в 3b для обоих источников). - Статусы: ошибочные файлы — как в Срезе 0; из успешных собираются документы; ни одной таблицы →
error RECOGNITION_FAILED; всё распознано →done, иначеneeds_check; причины — вmetrics.warnings. - Правила как данные (
api/rules/):statement_lines.yamlс редакциями форм (66nдо отчётности за 2024 включительно — изcodes_mappingстарого ядра;fsbu4с 2025 — пустая, данные положит владелец),ocr_lookalikes.yaml,statement_labels.yaml. Загружаются и валидируются при старте. - Настройки:
SCAN_CLEANUP,SCAN_RULES_DIR,SCAN_EMULATOR_DEFAULT;SCAN_TMP_DIRостаётся. Dev-compose:SCAN_CLEANUP=true. - Тесты: юнит по функциям, golden на
../fixtures/ocr/aep_3.json,aep_6.json(эталоны../fixtures/ocr/expected_normalize/), обновлённые тесты горячих папок, эмулятора, воркера; roundtrip с эмулятором.
Non-goals
- Маппинг
statementDocumentвfinancial_statement_*, проверки §7, подтверждение документа, чек-лист, UI — Срез 3b. - Изменение контракта (v1.2 заморожен): редакция формы в конверт не добавляется (OQ, кандидат в MINOR 1.3).
- Расшифровки без кода (OQ-36), склейка одной формы из нескольких таблиц (OQ-77),
DISCLOSUREиз OCR. - Заполнение словаря редакции
fsbu4и подбор пар PDF+JSON — владелец, отдельный PR в fixtures. - Перенос обвязки старого ядра (
json_to_db_rows, запись в БД,pdfworker_results.py).
Параграфы 05-domain-rules.md
§11 (структура ответа ИС, маппинг таблица → документ), §11.1 п. 1–9 (очистка OCR-текста), §12 п. 4 (разбор дат —
общий смысл с Excel-путём). Правила, которых в 05 нет и которые вводятся этим change'ом: редакции форм в справочнике
кодов (ASSUMPTION(OQ-12): состав 2025 года не задан), is_recognized колонок шапки. Таблицы DBML не затрагиваются
(сервис без БД).
Открытые вопросы, затрагиваемые change'ом
OQ-137 (уточнить: Tmp остаётся, очистка под флагом), OQ-36 (строки без кода не отдаются), OQ-77 (одна форма двумя
таблицами — два документа с предупреждением), OQ-12 (редакции форм и §7), новые: права на удаление на SMB-шаре;
редакция формы в контракте; §7/§12 по редакциям для 2b и 3b.