Andrey Epifancev 248f8b0c74 openspec(#116): спека по ревью K-1…K-25 и решениям владельца Р-20…Р-22; решения S-26…S-52
- design.md: Р-20 (законные повторы кода в перечне, синонимы в словаре имён), Р-21 (мягкое соотношение, сошедшееся
  точно, подтверждает неуверенное значение), Р-22 (S-1…S-25 приняты с оговорками; отмечены утверждённые владельцем);
  решения при доработке S-26…S-52 с ценой ошибки
- statement-normalization: отдельное требование sync-statements (пути, VERSION, коды 0 / 10 / 20 / 2), словарь
  единиц и ОКЕИ, ref Excel с кавычками, нумерация с двойниками и пропуском, номер колонки, содержимое строки, столбец
  кодов у DISCLOSURE, упрощённый 2400 мягкий, Р-20 / Р-21 со сценариями, обе редакции перечня, интерфейс функции
  статуса, TABLE_PARSE_ERROR / SHEET_OTHER уровня файла
- arm-core: признак строки правки row_index IS NULL, header_source, формы без checks (1.x и миграция) — §7 ядром в
  document_issue, codes / column_index, RESULT_STATUS_INCONSISTENT, синонимы и «итого по разделу», PATCH
  organization_name / confirmed: false / подтверждение даты, LINE_CODE_TAKEN, акцепт и подтверждения, LINES_UNRESOLVED
  с текстом, «того же периода», откат миграции
- recognition-contract: MODIFIED «Копия контракта … идентична» — сверка по MAJOR копии, *.v1.schema.json на окне;
  1.x — MAPPING_WARNING / LEGACY_WARNING; okei, column_index, пустые массивы DISCLOSURE, статус ОСВ одной формулировкой
- quality-checks (новая дельта): make check охватывает копию arm_statements, make check-full — statements-check
- tabular-recognition-service: манифест statements_manifest.yaml — failed_relations страниц 2 баланса (K-25)
- scan-gateway, arm-web: TABLE_PARSE_ERROR файла; подсказки шапки, снятие подтверждений, LINE_CODE_TAKEN
- proposal: шаг 0 выкладки, перечни кодов, ожидания на реальных сканах, Impact

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

47 lines
4.9 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.

## ADDED Requirements
### Requirement: Адаптер json ИС шага 1
scan-gateway SHALL оставить у себя обмен с ИС Сканирование (горячие папки, опрос, срок, склейку набора json в
`raw/{job_id}.json` до нормализации, очистку папки) и адаптер «таблица `table_structure[i]` json → `FormCandidate`»;
шаги 2–8 SHALL выполняться копией пакета `arm_statements`. Адаптер SHALL: создавать кандидата на каждую таблицу каждого
успешного json; копировать шапку json (`organization`, `inn`, `units`, `date`) в шапку каждой своей таблицы как `Cell`
(`text = form_name`, `confidence` ИС); передавать `label.form_name` таблицы как заголовок в `evidence` (тип — общим
правилом шага 1 по словарю заголовков, `statement_labels.yaml` уходит в словарь пакета); строить плотную сетку по
`row_index` и `column_index` ИС (пустые позиции — `null`), `Cell.ref = row:<row_index>`; `locator =
file:<имя json>;table:<i>`. `value` у OCR-ячеек всегда `null`.
#### Scenario: Один json — ББ и ОФР
- **WHEN** json `aep_3.json` содержит две таблицы — «Бухгалтерский баланс» и «Отчет о финансовых результатах» — под
общей шапкой
- **THEN** два кандидата с `locator` `file:aep_3.json;table:0` и `…;table:1`, у каждого копия шапки json
### Requirement: Ошибки набора json
Ошибочный json набора (`parse_error`, непустой `error.code`, корень не объект) при хотя бы одном успешном соседе SHALL
давать предупреждение файла `JSON_FAILED` (`error`, `locator = file:<имя json>`, в `message` — код и сообщение ИС);
все json ошибочны — конверт `error` с кодом первого. Исключение при разборе таблицы — предупреждение **файла**
`TABLE_PARSE_ERROR` (`error`, `locator = file:<имя json>;table:<i>`; документа у таблицы нет), остальные таблицы
разбираются; ни одной таблицы не разобрано — `error RECOGNITION_FAILED`.
#### Scenario: Таблица упала при разборе
- **WHEN** разбор `table:1` json `aep_3.json` бросил исключение, `table:0` разобрана
- **THEN** документ `BALANCE` из `table:0`; в `metrics.warnings` — `TABLE_PARSE_ERROR` уровня `error` с `locator =
"file:aep_3.json;table:1"`; конверт `needs_check`; ядро не автоподтверждает документы файла
#### Scenario: Потерянный ОФР (решение № 28 среза 3a)
- **WHEN** `<job_id>.json` успешен (ББ), а `<job_id>_ofr.json` вернул `INVALID_DOCUMENT`
- **THEN** документ ББ получает свой статус; в `metrics.warnings` — `JSON_FAILED` уровня `error`; конверт
`needs_check`; ядро не автоподтверждает документы файла
### Requirement: Что уходит из шлюза
scan-gateway SHALL удалить `api/rules/statement_lines.yaml` и подстановку наименований по справочнику, срезание
уверенности кода до 99 по справочнику, выбор редакции для имён (`_choose_edition`), пропуск строк с нечисловым и пустым
кодом со счётчиками, правило «оставлена первая строка» при повторе кода, синтез шапки, правило «ячейки под колонкой
нет → `confidence = 0`, не распознано», привязку `is_recognized` к `confidence` и правило «любое предупреждение →
`needs_check`». Модули `normalizer/ocr/text|dates|amounts` переезжают в общие разборы пакета, `layout|rows|header|
document` — в шаги 2–6 пакета; `ocr_lookalikes.yaml` — в словарь пакета.
#### Scenario: Строки без кода в aep_3
- **WHEN** в `aep_3.json` строки «БАЛАНС» и «Выручка» имеют пустой код, а в колонке значения мусор `211(1 |`
- **THEN** строки попадают в результат со статусами (`detail` под строкой с кодом, `missing` в начале таблицы) и сырым
текстом; счётчиков «строк без кода с суммами пропущено» нет