Andrey Epifancev 90ea429642 docs(#116): proposal и дельты спек единой нормализации ББ/ОФР
- proposal: зачем, что меняется, порядок выкладки «сначала ядро», non-goals
- statement-normalization: шаги 1–8 общего кода arm_statements (кандидат, раскладка, статусы строк,
  значения, §7, needs_review, структурная проверка кода, уровни предупреждений, статус)
- recognition-contract: файл результата и конверт v2.0, переход 1.x → 2.0
- tabular-recognition-service, scan-gateway: адаптеры шага 1 и что уходит из сервисов
- arm-core: хранение v2.0, агрегат по коду, document_issue, RECOGNIZED, PATCH lines/columns/confirmed,
  порядок 409, миграция v5.19, crm_id ГСК/ГСЗ
- arm-web: экран проверки формы по новым полям
- design.md: автозамена между файлами — §9.5 п. 3, а не §12 п. 3

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
2026-10-18 00:40:50 +04:00

115 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Why
Формы ББ/ОФР сегодня нормализуются двумя разными конвейерами: scan-gateway (PDF → ИС Сканирование) и tabular-parser
(Excel). У них разные правила раскладки таблицы, отбора строк, разбора сумм, проверок §7 и статуса; ядро не доверяет
ни одному из них и пересчитывает проверки и статус заново по косвенным признакам, дважды дедуплицирует строки и держит
третью и четвёртую копии словарей (§7 и «код → наименование»). Пользователь видит последствия как отдельные «ошибки
распознавания» — AURORA-1406, 1462, 1511, 1517, 1519, 1522, 1523, 1524, 1634: строки молча пропадают, повтор кода
теряет сумму, «чистая» ячейка с потерянной цифрой не подсвечивается, предупреждения сервисов нигде не видны.
Дизайн `design.md` (финальная версия, решения владельца Р-1…Р-19 от 17.10.2026, три раунда ревью) приводит оба
сервиса к одной цепочке шагов 1–9 с единым выходом каждого шага и общим кодом шагов 2–8; ядро хранит результат как
пришёл и пересчитывает его тем же общим кодом только после правок аналитика.
Срез: вне плана срезов `09-delivery-plan.md` — переработка Среза 2b (Excel-формы), Среза 3a (OCR-нормализатор) и
Среза 3b (формы в ядре). Issue RSHB/arm-ka-docs#116.
## What Changes
- **Общий код нормализации** — новый репозиторий `arm-statements`, пакет `arm_statements/` (Р-1): типы шага 1
(`FormCandidate`, `Cell`), шаги 2–8 (раскладка, отбор строк, значения, код и наименование, сборка документа,
самопроверки §7, статус и `needs_review`), словари §7 (полный и упрощённый наборы), периодов, заголовков форм,
подписей колонок, упорядоченные перечни кодов форм по редакциям и вариантам, диапазоны кодов. Словаря «код →
наименование» в пакете нет (Р-3). В tabular-parser, scan-gateway и arm-core пакет лежит копией, которую раскладывает
и проверяет скрипт `sync-statements` репозитория docs (по образцу `sync-web.sh`).
- **Строки не выбрасываются молча:** статусы строк `ok` | `unreadable` | `missing` | `detail`, `row_index`, `ref`,
сырой текст кода и ячейки (`text`) доезжают до БД и экрана; повтор кода — законный случай, все строки сохраняются
(Р-4, Р-8). **BREAKING** для потребителей: `line_code` становится nullable.
- **Качество структурно и с привязкой к месту:** `needs_review` у значения, строки и полей шапки; «подтверждение
проверкой» §7 вместо порога уверенности (Р-5, Р-7, Р-11, Р-12, Р-16, Р-17); `document.status` у каждого документа;
предупреждения — структуры `{code, severity, message, line_refs, column_index, field}` вместо строк.
- **Контракт `recognition-result.schema.json` v2.0** (MAJOR, Р-9) и конверт `recognition-result-message.schema.json`
v2.0 (структурные `metrics.warnings`); запрос `recognition-request` остаётся v1.0. Путь ОСВ в tabular-parser
меняется только в части структуры предупреждений и `document.status`.
- **arm-core:** DBML v5.19 и одна миграция (статусы и порядок строк, `needs_review`, `is_confirmed`, `source_text`,
`period_kind`, `form_variant`, таблица `document_issue`, снятие уникальности `(meta_id, line_code)` и — для ББ/ОФР —
`document (stored_file_id, document_type, osv_account_code)`, `recognition_job.statements_version`,
`related_group.crm_id` по arm-core#112); «агрегат формы по коду» вместо «одна строка на код»; приём 1.x и 2.0 на
время перехода; новое условие `RECOGNIZED`; PATCH `…/statement` с `lines`, `columns`, `values[].confirmed`; 409
`LINES_UNRESOLVED` и `DUPLICATE_FORM` при подтверждении.
- **arm-web:** экран проверки формы — строки со статусами на своих местах, расшифровки под переключателем, подсветка
только по `needs_review`, предупреждения и нарушения у места, назначение кода, «Это расшифровка», подтверждение кода
и ячейки, дата колонки.
- **Документы:** `05-domain-rules.md` — §11 становится общей главой нормализации ББ/ОФР с подразделами по
источникам, §12 — заголовок-редирект; §7 — «посчитанное» соотношение, `abs_terms` и знак, упрощённый набор; §9.3,
§9.5 — статус, маппинг и подтверждение формы по v2.0. `07-open-questions.md` — закрыты OQ-36, OQ-141 (Р-8) и
вопросы, снятые решениями дизайна; новые вопросы — склейка половинок формы (Р-15) и открытое в дизайне.
`frontend-api-guide.md` — новые поля формы и PATCH (после реализации).
Читают и пишут контракт: `arm-core` (читает результат и конверт, публикует запрос), `tabular-parser` и `scan-gateway`
(читают запрос, пишут результат и конверт). Дочерние change'и (заводятся при планировании, по одному на репозиторий):
`arm-statements` (новый), RSHB/arm-core, RSHB/arm-tabular-parser, RSHB/arm-scan-gateway, RSHB/arm-web; связанная
задача — RSHB/arm-core#112 (`related_group.crm_id` входит в ту же миграцию, Р-10).
### Порядок выкладки — «сначала ядро» (обязателен)
1. `arm-statements` — пакет с тестами; `sync-statements` в docs.
2. docs: контракт v2.0, DBML v5.19, правила (этот change).
3. arm-core: миграция v5.19, маппер 2.0 рядом с маппером 1.x, приём ack и конвертов 1.x и 2.0, PATCH, экранные поля
API. До этого шага ни один сервис не шлёт 2.0: первый же `line_code = null` дал бы файлу `ERROR`.
4. arm-web: экран по новым полям (поля 1.x-документов заполнены по умолчанию — экран работает и на них).
5. tabular-parser и scan-gateway переходят на 2.0 в любом порядке относительно друг друга.
6. После перехода обоих сервисов маппер 1.x удаляется из ядра отдельным PR (не в этом change).
Копии схем в сервисах (`api/contracts/`, тест идентичности в `make check`) после слияния контракта v2.0 в docs
устаревают: каждый сервис обновляет копию в своём PR шага 5, ядро — в PR шага 3.
## Non-goals
- Разбор ОСВ (`classify.py`, `to_money` ОСВ, правила §1) не меняется; путь ОСВ в tabular-parser меняется только в
структуре предупреждений и `document.status`.
- Переключатель «как в файле» (порядок строк по `row_index`) на экране — не в этой работе (Р-14).
- Склейка двух половинок формы из одного файла в ядре не предоставляется — файл перезагружают; вопрос в
`07-open-questions.md` (Р-15). Склейка страниц из разных файлов (OQ-140) — тоже нет.
- Восстановление строк по наименованию (OQ-149) и сопоставление формы без колонки кодов по именам строк (OQ-139) — нет.
- Запрос `recognition-request` остаётся v1.0; subject'ы NATS, `Nats-Msg-Id`, ack и повторы не меняются по механике.
- Межформенная проверка `1370 − 1370(нач. года) = 2400` остаётся в ядре и мягкой; формулы §7 по редакциям (OQ-146) и
знаки 2410/2420 (OQ-12) не пересматриваются.
- Замена пакета-копии на зависимость из Nexus платформы — не сейчас (платформа Python-пакеты не собирает, Р-1).
- Приведение единиц измерения сверх числового формата ячейки (OQ-138) — нет.
## Capabilities
### New Capabilities
- `statement-normalization`: общая цепочка нормализации ББ/ОФР (шаги 1–8) — пакет `arm_statements`, его типы,
правила и словари, `sync-statements`.
- `tabular-recognition-service`: адаптер Excel шага 1 в tabular-parser и что остаётся в сервисе (чтение книги, листы
ОСВ, сборка конверта v2.0).
- `scan-gateway`: адаптер json ИС шага 1 в scan-gateway и что остаётся в сервисе (горячие папки, склейка набора json,
`raw/`, сборка конверта v2.0).
- `arm-core`: хранение результата v2.0 (DBML v5.19), агрегат по коду, `document_issue`, условие `RECOGNIZED`, PATCH
формы, порядок 409 подтверждения, приём 1.x и 2.0.
- `arm-web`: экран проверки формы ББ/ОФР по новым полям.
### Modified Capabilities
- `recognition-contract`: файл результата и конверт — v2.0; правила перехода (ядро принимает 1.x и 2.0, «сначала
ядро»); статус и структурные предупреждения у всех документов, включая ОСВ.
## Impact
- Новый репозиторий `arm-statements`; скрипт `sync-statements` и цель Makefile в docs (вызывается из `make check-full`
потребителей, не из `make check`).
- tabular-parser: `parser/statements/*` (кроме разбора книги и адаптера шага 1) уходит в общий код; словари
`statement_checks.yaml`, `statement_periods.yaml`, `statement_headers.yaml` переезжают в пакет; путь ОСВ — структура
предупреждений и `document.status`.
- scan-gateway: `normalizer/ocr/text|dates|amounts` становятся общими разборами, `layout|rows|header|document` — шагами
2–6 общего кода; `api/rules/statement_lines.yaml` удаляется, `statement_labels.yaml` и `ocr_lookalikes.yaml` уходят в
словари пакета.
- arm-core: миграция v5.19 (`financial_statement_*`, `document`, `document_issue`, `recognition_job`,
`related_group`), `result_mapping`, `statement_mapping`, `statements`, `documents`, `auto_confirm`, схемы API формы;
`api/rules/statement_checks.yaml` удаляется (копия словаря §7), `statement_lines.yaml` остаётся только словарём имён.
- arm-web: `widgets/DocumentReview` (экран [41]), типы API.
- Решение v5.13 «`needs_review` считается, не хранится» пересматривается (design, Decisions № 17).
- Риск окна выкладки: пока сервис шлёт 1.x, документы его конвейера получают статус по прежнему правилу D-6 и поля
v2.0 по умолчанию — экран и подтверждение работают, новых сигналов качества нет.