Формы через arm_statements, контракт результата v2.0 (#54) #55

Merged
aep merged 15 commits from feat/54-statements-v2 into main 2026-10-19 07:38:07 +03:00
Owner

Closes #54. Цель, план: arm-ka-docs#116, план 4 (openspec/changes/unified-statement-normalization/plans/2026-10-18-plan-4-tabular-parser.md). Парный PR fixtures (golden): RSHB/arm-ka-fixtures (ветка feat/25-statements-v2-golden, issue #25).

НЕ СЛИВАТЬ

Условие слияния: ядро с приёмом контракта 2.0 (части А и Б плана 3) выложено, docs #117 слит (слит). Первый же результат 2.0 даст файлу ERROR у ядра 1.x. Порядок: сначала PR fixtures (golden), сразу за ним этот PR. Слияние — только по команде владельца. Копия пакета: statements-check = 0 (arm-statements@3390f92), в описании «копия отстала» нет.

Что сделано

  • Адаптер Excel шага 1 (свой код): ячейка Excel → Cell (текст по числовому формату, value, ref <лист>!<A1>), блоки форм, вид листа, шапка → HeaderCells, склейка листов-продолжений → FormCandidate (segment_breaks). Шаги 2–8 выполняет копия пакета arm_statements (только публичный API).
  • Контракт результата и конверта 2.0 (запрос остаётся 1.0): service.statements_version, структурные metrics.warnings, у ОСВ status и warnings[] с кодами OSV_* (info). Копия схем идентична docs (тест vendored_contracts).
  • Удалены собственный конвейер форм (statements/{checks,columns,detect,header,lines,merge,statement}.py), legacy_models.py, словари форм rules/statement_*.yaml.
  • OpenSpec change unified-normalization-tp (дельты statement-parsing, tabular-recognition-service, osv-parsing; design.md с P4-1…P4-22 и R-1…R-14). Архивация — по правилу «после выкладки».
  • Копия пакета обновлена до arm-statements@3390f92 (правило владельца Р-44: столбец без подписи правее последней подписанной колонки с числами — не колонка сумм, предупреждение NUMBERS_OUTSIDE_TABLE), отдельным коммитом f5d071f.

Реальные формы: манифест и результаты

Доля done по документам форм (19 документов в 18 файлах): до 6, после 6 (НПЗ ×2, Межениновская ×2, ОФР «Лист 1» Унагранде ×2). Статусы всех файлов совпали с манифестом. Изменения манифеста (api/tests/statements_manifest.yaml):

  • «Лист 2» баланса Унагранде ×3 (unagrande-co/2024-FY/Б.Б. Лист 2.xls, unagrande-group/2024-FY/ББ. Лист 2 (2).xls, unagrande-group/2025-Q3/ББ. Лист 2 3кв.25.xls): failed_relations: ["1600 = 1700"] вместо [] — v2.0 проверяет соотношение с пустой целью по самой странице (спека, «посчитанное» соотношение §7); статус needs_check прежний.
  • Новое поле error_warnings (точное множество кодов error документа) у каждого документа: страницы 2 и ОФР «Лист 2» — NO_ORGANIZATION_NO_INN; шаблоны — PERIOD_UNKNOWN (+ NO_ORGANIZATION_NO_INN, SEGMENT_COLUMNS_MISMATCH у ББ «до»); остальные — [].
  • Межениновская 1_Форма1_бух_09.xlsx первоначально давала needs_check из-з�� посторонних формул аналитика (V45, W57, U58, V58, V72, W72) в столбцах без подписи периода; решение владельца — правило в пакете (docs #123, Р-44); теперь done, колонки M/Q/S, NUMBERS_OUTSIDE_TABLE (info).
  • Проверка уникальности кодов строк снята (повторы законны, Р-4).

Проверки

make check с фикстурами 2884 passed; без фикстур 1820 passed / 91 skipped; make golden-check 0 (152 файла); make statements-check 0; openspec validate unified-normalization-tp --strict valid; интеграционные тесты (свой compose-проект, NATS/MinIO на портах 24222/29000, общий стек не тронут) 10 passed; docker build ок, в образе statements_version = 3390f92.

Rulings I made

  • R-1: docs-worktree на origin/main (#117 слит). Цена: нет.
  • R-2: предупреждение tp #47 «xls без кодовой страницы…» = XLS_NO_CODEPAGE пакета (info, файл), нового OSV_* нет, текст reader'а сохранён. Цена: правка book.py и golden.
  • R-3: P4-n и R-n — в design.md change'а tabular-parser, docs не правятся. Цена: перенос в docs вручную.
  • R-4: задача 1 (markdown-дельты) без отдельного task-ревью; покрыта openspec validate --strict и финальным ревью.
  • R-5: проверка диапазона numeric(18,2) в display_amount не возвращается (P4-4); диапазон выдаёт пакет. Цена: нет после удаления старого конвейера.
  • R-6: для |raw| ≥ 1e15 без округления до 15 значащих цифр; пробел групп — U+0020, как в примере docs. Цена: расхождение с NBSP русского Excel, на value/статус не влияет.
  • R-7: ячейки из одних цифр не подзаголовок даты. Цена: подзаголовок «2025» не распознаётся.
  • R-8: ячейка в строке с подписью «Код» не заголовок формы (подпись колонки «Пояснения» делала лист-продолжение НПЗ формой DISCLOSURE). Решение владельца: оставить, посмотреть позже. Цена: заголовок и «Код» в одной строке теряют заголовок (T5.3).
  • R-9: предупреждения адаптера без документа — предупреждения файла со своим locator; порядок metrics.warnings — reader, затем по листам; XLS_NO_CODEPAGE / OSV_XLSB_NO_OUTLINE — флаги BookRead.
  • R-10: НПЗ, ОФР, строки «Реализация иного имущества…» (F34, F44) — одни прочерки (0 с форматом [=0]"-"), по спеке не строки данных; пакет их не выдаёт; прочерк в 0 не превращаем. Вопрос владельцу O-8.2: сценарий спеки «Реализация иного имущества… с суммами» не соответствует файлу.
  • R-11: задача 9 (удаление) без отдельного task-ревью, покрыта финальным.
  • R-12: стоп Р-31 по Межениновской снят владельцем (вариант «а»).
  • R-13: plan_sheets получает deadline (регрессия TIMEOUT, финальное ревью I-1).
  • R-14: интеграционные тесты и docker-build — на собственном compose-проекте и теге, общий стек не тронут.

Находки (маркер, суть, статус)

Исправлено: T3.1 (старый пут�� удалён, be5ad8c); T5.1 (0d82b5c); T5.5/T7.3 (deadline, 2fce780); T6.1, T6.5, O-1.1 (71f596c); T7.I-1, T7.I-2, T7.M-1 (9e69479); T7.6 (2fce780); O-7.1, O-7.2 (be5ad8c); Р-31 (f5d071f); финальное ревью I-1…I-4, M-1, M-6 (2fce780, 0d82b5c, 4d30718, b583b04). Отклонено: T3.4 (совпадает с Excel), O-4.1.
Полная таблица — в ledger SDD.

Deferred (в follow-up issue при закрытии)

T3.2, T3.3 (cell_ref и имена вида A1), T4.1–T4.10 (в т. ч. T4.3/O-8.1 мусор в organization_name шаблонов «после 01.01.2025»), T5.2–T5.4, T6.2–T6.4, T7.1–T7.5, T7.7, T7.8, T8.1 (после ответа по O-8.2), T8.2, F-M2 (мёртвый код detect.classify_sheet, BookRead.warnings/read_book), F-M3 (general_text без 15 значащих цифр), F-M5 (xlsb без outline в книге без ОСВ не логируется), O-8.2 (вопрос владельцу).

Парный PR fixtures: RSHB/arm-ka-fixtures#27

🤖 Generated with Claude Code

Closes #54. Цель, план: arm-ka-docs#116, план 4 (`openspec/changes/unified-statement-normalization/plans/2026-10-18-plan-4-tabular-parser.md`). Парный PR fixtures (golden): RSHB/arm-ka-fixtures (ветка feat/25-statements-v2-golden, issue #25). ## НЕ СЛИВАТЬ Условие слияния: ядро с приёмом контракта 2.0 (части А и Б плана 3) выложено, docs #117 слит (слит). Первый же результат 2.0 даст файлу `ERROR` у ядра 1.x. Порядок: сначала PR fixtures (golden), сразу за ним этот PR. Слияние — только по команде владельца. Копия пакета: `statements-check` = 0 (arm-statements@3390f92), в описании «копия отстала» нет. ## Что сделано - Адаптер Excel шага 1 (свой код): ячейка Excel → `Cell` (текст по числовому формату, value, `ref <лист>!<A1>`), блоки форм, вид листа, шапка → `HeaderCells`, склейка листов-продолжений → `FormCandidate` (`segment_breaks`). Шаги 2–8 выполняет копия пакета `arm_statements` (только публичный API). - Контракт результата и конверта 2.0 (запрос остаётся 1.0): `service.statements_version`, структурные `metrics.warnings`, у ОСВ `status` и `warnings[]` с кодами `OSV_*` (info). Копия схем идентична docs (тест `vendored_contracts`). - Удалены собственный конвейер форм (`statements/{checks,columns,detect,header,lines,merge,statement}.py`), `legacy_models.py`, словари форм `rules/statement_*.yaml`. - OpenSpec change `unified-normalization-tp` (дельты `statement-parsing`, `tabular-recognition-service`, `osv-parsing`; `design.md` с P4-1…P4-22 и R-1…R-14). Архивация — по правилу «после выкладки». - Копия пакета обновлена до arm-statements@3390f92 (правило владельца Р-44: столбец без подписи правее последней подписанной колонки с числами — не колонка сумм, предупреждение `NUMBERS_OUTSIDE_TABLE`), отдельным коммитом f5d071f. ## Реальные формы: манифест и результаты Доля `done` по документам форм (19 документов в 18 файлах): до 6, после 6 (НПЗ ×2, Межениновская ×2, ОФР «Лист 1» Унагранде ×2). Статусы всех файлов совпали с манифестом. Изменения манифеста (`api/tests/statements_manifest.yaml`): - «Лист 2» баланса Унагранде ×3 (`unagrande-co/2024-FY/Б.Б. Лист 2.xls`, `unagrande-group/2024-FY/ББ. Лист 2 (2).xls`, `unagrande-group/2025-Q3/ББ. Лист 2 3кв.25.xls`): `failed_relations: ["1600 = 1700"]` вместо `[]` — v2.0 проверяет соотношение с пустой целью по самой странице (спека, «посчитанное» соотношение §7); статус `needs_check` прежний. - Новое поле `error_warnings` (точное множество кодов `error` документа) у каждого документа: страницы 2 и ОФР «Лист 2» — `NO_ORGANIZATION_NO_INN`; шаблоны — `PERIOD_UNKNOWN` (+ `NO_ORGANIZATION_NO_INN`, `SEGMENT_COLUMNS_MISMATCH` у ББ «до»); остальные — `[]`. - Межениновская `1_Форма1_бух_09.xlsx` первоначально давала `needs_check` из-з�� посторонних формул аналитика (V45, W57, U58, V58, V72, W72) в столбцах без подписи периода; решение владельца — правило в пакете (docs #123, Р-44); теперь `done`, колонки M/Q/S, `NUMBERS_OUTSIDE_TABLE` (info). - Проверка уникальности кодов строк снята (повторы законны, Р-4). ## Проверки `make check` с фикстурами 2884 passed; без фикстур 1820 passed / 91 skipped; `make golden-check` 0 (152 файла); `make statements-check` 0; `openspec validate unified-normalization-tp --strict` valid; интеграционные тесты (свой compose-проект, NATS/MinIO на портах 24222/29000, общий стек не тронут) 10 passed; `docker build` ок, в образе `statements_version` = 3390f92. ## Rulings I made - R-1: docs-worktree на `origin/main` (#117 слит). Цена: нет. - R-2: предупреждение tp #47 «xls без кодовой страницы…» = `XLS_NO_CODEPAGE` пакета (info, файл), нового `OSV_*` нет, текст reader'а сохранён. Цена: правка `book.py` и golden. - R-3: P4-n и R-n — в `design.md` change'а tabular-parser, docs не правятся. Цена: перенос в docs вручную. - R-4: задача 1 (markdown-дельты) без отдельного task-ревью; покрыта `openspec validate --strict` и финальным ревью. - R-5: проверка диапазона `numeric(18,2)` в `display_amount` не возвращается (P4-4); диапазон выдаёт пакет. Цена: нет после удаления старого конвейера. - R-6: для |raw| ≥ 1e15 без округления до 15 значащих цифр; пробел групп — U+0020, как в примере docs. Цена: расхождение с NBSP русского Excel, на value/статус не влияет. - R-7: ячейки из одних цифр не подзаголовок даты. Цена: подзаголовок «2025» не распознаётся. - R-8: ячейка в строке с подписью «Код» не заголовок формы (подпись колонки «Пояснения» делала лист-продолжение НПЗ формой DISCLOSURE). Решение владельца: оставить, посмотреть позже. Цена: заголовок и «Код» в одной строке теряют заголовок (T5.3). - R-9: предупреждения адаптера без документа — предупреждения файла со своим locator; порядок `metrics.warnings` — reader, затем по листам; `XLS_NO_CODEPAGE` / `OSV_XLSB_NO_OUTLINE` — флаги `BookRead`. - R-10: НПЗ, ОФР, строки «Реализация иного имущества…» (F34, F44) — одни прочерки (`0` с форматом `[=0]"-"`), по спеке не строки данных; пакет их не выдаёт; прочерк в 0 не превращаем. Вопрос владельцу O-8.2: сценарий спеки «Реализация иного имущества… с суммами» не соответствует файлу. - R-11: задача 9 (удаление) без отдельного task-ревью, покрыта финальным. - R-12: стоп Р-31 по Межениновской снят владельцем (вариант «а»). - R-13: `plan_sheets` получает `deadline` (регрессия TIMEOUT, финальное ревью I-1). - R-14: интеграционные тесты и `docker-build` — на собственном compose-проекте и теге, общий стек не тронут. ## Находки (маркер, суть, статус) Исправлено: T3.1 (старый пут�� удалён, be5ad8c); T5.1 (0d82b5c); T5.5/T7.3 (deadline, 2fce780); T6.1, T6.5, O-1.1 (71f596c); T7.I-1, T7.I-2, T7.M-1 (9e69479); T7.6 (2fce780); O-7.1, O-7.2 (be5ad8c); Р-31 (f5d071f); финальное ревью I-1…I-4, M-1, M-6 (2fce780, 0d82b5c, 4d30718, b583b04). Отклонено: T3.4 (совпадает с Excel), O-4.1. Полная таблица — в ledger SDD. ### Deferred (в follow-up issue при закрытии) T3.2, T3.3 (cell_ref и имена вида A1), T4.1–T4.10 (в т. ч. T4.3/O-8.1 мусор в `organization_name` шаблонов «после 01.01.2025»), T5.2–T5.4, T6.2–T6.4, T7.1–T7.5, T7.7, T7.8, T8.1 (после ответа по O-8.2), T8.2, F-M2 (мёртвый код `detect.classify_sheet`, `BookRead.warnings`/`read_book`), F-M3 (`general_text` без 15 значащих цифр), F-M5 (xlsb без outline в книге без ОСВ не логируется), O-8.2 (вопрос владельцу). Парный PR fixtures: https://git.aepif.ru/RSHB/arm-ka-fixtures/pulls/27 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 15 commits 2026-10-18 21:21:41 +03:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Тест test_npz_candidates красный: НПЗ — BLOCKED (Р-31), см. отчёт задачи 5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Ячейка в строке с подписью «Код» (словарь пакета) не открывает блок формы:
«Пояснения» на листах-продолжениях НПЗ больше не даёт DISCLOSURE.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
- копия схем и примеров контракта v2.0 (запрос остаётся v1.0), модели result/common/message/request;
  ResultWarning/FileWarning, статус и предупреждения у документов, строки forms v2.0, service.statements_version
- statements/pipeline.py: кандидаты адаптера -> normalize_candidate -> to_contract / warning_to_contract
- BookParser: статус книги через envelope_status, SHEET_OTHER / FILE_TYPE_MISMATCH / XLS_NO_CODEPAGE как предупреждения
  файла, OSV_* и OSV_XLSB_NO_OUTLINE в документах ОСВ, тексты иерархии по спеке
- воркер, app и CLI получают statements_version из require_statements_version()
- старые модели документа формы вынесены в statements/legacy_models.py до удаления старого конвейера (задача 9)
- OpenSpec: MODIFIED «Парсер — заменяемый интерфейс» в дельте tabular-recognition-service

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Удалены модули statements/{checks,columns,detect,header,lines,merge,statement,legacy_models}.py, словари
rules/statement_{headers,periods,checks}.yaml и их тесты. Словари форм и шаги 2–8 — в пакете arm_statements.
Rules без полей statement_*; покрытие словарей ОСВ (DICTIONARIES) без словарей форм. Документация сервиса
переписана под адаптер форм, контракт 2.0 и коды OSV_*.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
I-1: plan_sheets проверяет дедлайн на каждом листе (регрессия против main).
I-2: тесты исключения пакета на кандидате (RECOGNITION_FAILED с
предупреждениями файла), TIMEOUT в адаптере и конвейере, RulesError в get_parser.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
M-1: _separate считает form_amount_columns, следующий лист без маркера
больше не получает ложный SHEET_NOT_JOINED.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
I-3: дельты osv-parsing (листы ОСВ, иерархия, golden, XLS_NO_CODEPAGE) и
перечень словарей api/rules; пункт об архивации (Purpose спек) в tasks.md.
I-4: README, CLAUDE.md и docstring hierarchy.py совпадают с кодом, пример
вывода CLI переснят. M-6: tasks.md, proposal.md, design.md с решениями P4/R.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
aep changed title from Формы через arm_statements, контракт результата v2.0 (НЕ СЛИВАТЬ до выкладки ядра) to Формы через arm_statements, контракт результата v2.0 (#54) 2026-10-19 07:37:52 +03:00
aep merged commit 4d1709ae0d into main 2026-10-19 07:38:07 +03: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: RSHB/arm-tabular-parser#55
No description provided.