Единая нормализация ББ/ОФР: адаптер OCR → arm_statements, контракт результата 2.0 (arm-ka-docs#116) #47

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

Closes #46. Ссылки: arm-ka-docs#116, PR fixtures RSHB/arm-ka-fixtures#26 (golden).

scan-gateway разбирает набор json ИС адаптером шага 1 (одна таблица ИС — один FormCandidate) и копией общего пакета arm_statements (шаги 2–8); файл результата и конверт — по контракту v2.0 (запрос остаётся 1.x); структурные предупреждения файла JSON_FAILED, TABLE_PARSE_ERROR, TABLE_LOST, TABLE_SKIPPED. Собственный нормализатор шагов 2–8, normalizer/rules.py, api/rules/*.yaml и SCAN_RULES_DIR удалены. OpenSpec change: openspec/changes/statements-v2.

Слияние — после выкладки ядра, принимающего 2.0 (план 3, части А и Б); PR fixtures (#26) — ПЕРВЫМ

Слияние — только по команде владельца.

Проверки

  • Копия пакета обновлена до arm-statements@3390f92 (правило шага 2 Р-44: столбец без подписи правее последней подписанной колонки сумм — вне таблицы, предупреждение NUMBERS_OUTSIDE_TABLE, info, document; arm-statements #6, docs #123) отдельным коммитом.
  • make check: 1208 passed. make statements-check: код 0 (копия синхронна с arm-statements@3390f92).
  • После обновления реальные ответы ИС перепрогнаны: статусы всех шести наборов прежние, make golden-update не дал diff — golden не менялся (в PR fixtures#26 ничего добавлять не пришлось).
  • make check-full целиком не запускался: на машине работает стек владельца (arm-ka). Шаги прогнаны по отдельности: интеграционные тесты — 11 passed на отдельном compose-проекте (порты 24222/29000, снят после прогона), make docker-build — образ собран.
  • Доля done по golden: aep_3 — needs_check (ББ, ОФР); aep_5 — error (INVALID_DOCUMENT); aep_6 — needs_check (ББ, ОФР); aep_8_form4 — error; «БО 1 кв 2025» — done (2/2); «Бухгалтерская отчетность 1 кв.25» — done (2/2). Неожиданных needs_check нет (Р-31 не сработало).

Находки

Findings

Маркер Суть Статус
T2.1 нет теста «строка без ячеек в таблице с ячейками» deferred
T2.2 в broken нет column_index=bool и «ячейка не объект» fixed e6d55a3
T2.3 комментарий к if cells/default=0 в adapter.py deferred
T3.I-1 код ошибки набора от первого ошибочного при успешном json fixed 3b9e1f6
T3.1 assert isinstance в answer_set.py (-O) deferred
T3.2 нет тестов усечения 300 / BAD_ENTRY fixed e6d55a3
T3.3 res.error без None-проверки в тестах deferred
T3.4 дубль NO_TABLES_MESSAGE fixed ae2922e
T3.5 invalid_file/response_error публичные deferred
T4.I-1 locator/line_refs/locator документа без clean_text (суррогаты) fixed edd3d03
T4.1 при >100 error остаются первые 100 — docstring fixed e6d55a3
T4.2 кейсы моделей в CASES test_contract fixed e6d55a3
T4.3 устаревший комментарий SUCCESS_ANSWER fixed e6d55a3
T4.4 слабое утверждение test_success_answer_helper_from_worker_tests deferred
T4.5 docstring Normalizer: BACKEND_PARSING_ERROR fixed e6d55a3
T4.6 default_rules() на каждый normalize в NullNormalizer rejected (default_rules под @cache)
T6.1 приватный _outcome_metrics в golden_update.py deferred
T6.2 error-ветка golden не проверяется схемой rejected (файла результата при error нет)
T6.3 skipif дублирует маркер fixtures deferred
M-1 README: устаревшее ограничение OQ-36 fixed e6d55a3, 3a89a82
M-2 README: TABLE_SKIPPED в причинах RECOGNITION_FAILED fixed e6d55a3
M-3 решение R-7 не записано в design.md fixed e6d55a3
M-4 spec.md: level → severity fixed e6d55a3
M-5 docstring Normalizer fixed e6d55a3
M-6 docstring _limit_warnings fixed e6d55a3
M-7 пробелы тестов (300, adapter broken, CASES) fixed e6d55a3
M-8 Review Focus: RF1 «ни одна строка не пропала», RF3 date.form_name не проверены явно deferred
O-1 relations_failed в aep_3 повторяются по колонкам (поведение пакета) deferred (пакет, план 1)
O-2 make check-full целиком не запускался (общий стек владельца); шаги прогнаны по отдельности на своём compose-проекте deferred
O-3 одиночный суррогат в тексте ячейки OCR не чистится ни пакетом, ни шлюзом (было и раньше) deferred
O-4 build_result вне try в _accept_answer (структура прежняя) deferred

Rulings I made

  • R-1 трейлер коммитов Co-Authored-By: Claude Opus 5.5 + Claude-Session из плана.
  • R-2 (Р-36) примеры контракта: только копии существующих верхнего уровня.
  • R-3 усечение 300 символов (P5-9) применяется к тексту исключения, не ко всей строке «Тип: текст».
  • R-4 NormalizeOutcome вынесен в src/normalizer/outcome.py с реэкспортом (цикл импортов).
  • R-5 app.py вызывает OcrNormalizer() без аргумента (import arm_statements разрешён только в src/normalizer/** и tests).
  • R-6 сравнение golden временно под skip между T4 и T6 (снято в T6).
  • R-7 смешанный набор (ошибочный json + успешный без таблиц/документов) → RECOGNITION_FAILED; код первого ошибочного — только если успешных json нет.
  • P5-1…P5-20 — в openspec/changes/statements-v2/design.md.

🤖 Generated with Claude Code

Closes #46. Ссылки: arm-ka-docs#116, PR fixtures RSHB/arm-ka-fixtures#26 (golden). scan-gateway разбирает набор json ИС адаптером шага 1 (одна таблица ИС — один `FormCandidate`) и копией общего пакета `arm_statements` (шаги 2–8); файл результата и конверт — по контракту v2.0 (запрос остаётся 1.x); структурные предупреждения файла `JSON_FAILED`, `TABLE_PARSE_ERROR`, `TABLE_LOST`, `TABLE_SKIPPED`. Собственный нормализатор шагов 2–8, `normalizer/rules.py`, `api/rules/*.yaml` и `SCAN_RULES_DIR` удалены. OpenSpec change: `openspec/changes/statements-v2`. ## Слияние — после выкладки ядра, принимающего 2.0 (план 3, части А и Б); PR fixtures (#26) — ПЕРВЫМ Слияние — только по команде владельца. ## Проверки - Копия пакета обновлена до arm-statements@3390f92 (правило шага 2 Р-44: столбец без подписи правее последней подписанной колонки сумм — вне таблицы, предупреждение `NUMBERS_OUTSIDE_TABLE`, info, document; arm-statements #6, docs #123) отдельным коммитом. - `make check`: 1208 passed. `make statements-check`: код 0 (копия синхронна с arm-statements@3390f92). - После обновления реальные ответы ИС перепрогнаны: статусы всех шести наборов прежние, `make golden-update` не дал diff — golden не менялся (в PR fixtures#26 ничего добавлять не пришлось). - `make check-full` целиком не запускался: на машине работает стек владельца (arm-ka). Шаги прогнаны по отдельности: интеграционные тесты — 11 passed на отдельном compose-проекте (порты 24222/29000, снят после прогона), `make docker-build` — образ собран. - Доля `done` по golden: aep_3 — needs_check (ББ, ОФР); aep_5 — error (INVALID_DOCUMENT); aep_6 — needs_check (ББ, ОФР); aep_8_form4 — error; «БО 1 кв 2025» — done (2/2); «Бухгалтерская отчетность 1 кв.25» — done (2/2). Неожиданных needs_check нет (Р-31 не сработало). ## Находки ## Findings | Маркер | Суть | Статус | |---|---|---| | T2.1 | нет теста «строка без ячеек в таблице с ячейками» | deferred | | T2.2 | в broken нет column_index=bool и «ячейка не объект» | fixed e6d55a3 | | T2.3 | комментарий к `if cells`/default=0 в adapter.py | deferred | | T3.I-1 | код ошибки набора от первого ошибочного при успешном json | fixed 3b9e1f6 | | T3.1 | assert isinstance в answer_set.py (-O) | deferred | | T3.2 | нет тестов усечения 300 / BAD_ENTRY | fixed e6d55a3 | | T3.3 | res.error без None-проверки в тестах | deferred | | T3.4 | дубль NO_TABLES_MESSAGE | fixed ae2922e | | T3.5 | invalid_file/response_error публичные | deferred | | T4.I-1 | locator/line_refs/locator документа без clean_text (суррогаты) | fixed edd3d03 | | T4.1 | при >100 error остаются первые 100 — docstring | fixed e6d55a3 | | T4.2 | кейсы моделей в CASES test_contract | fixed e6d55a3 | | T4.3 | устаревший комментарий SUCCESS_ANSWER | fixed e6d55a3 | | T4.4 | слабое утверждение test_success_answer_helper_from_worker_tests | deferred | | T4.5 | docstring Normalizer: BACKEND_PARSING_ERROR | fixed e6d55a3 | | T4.6 | default_rules() на каждый normalize в NullNormalizer | rejected (default_rules под @cache) | | T6.1 | приватный _outcome_metrics в golden_update.py | deferred | | T6.2 | error-ветка golden не проверяется схемой | rejected (файла результата при error нет) | | T6.3 | skipif дублирует маркер fixtures | deferred | | M-1 | README: устаревшее ограничение OQ-36 | fixed e6d55a3, 3a89a82 | | M-2 | README: TABLE_SKIPPED в причинах RECOGNITION_FAILED | fixed e6d55a3 | | M-3 | решение R-7 не записано в design.md | fixed e6d55a3 | | M-4 | spec.md: level → severity | fixed e6d55a3 | | M-5 | docstring Normalizer | fixed e6d55a3 | | M-6 | docstring _limit_warnings | fixed e6d55a3 | | M-7 | пробелы тестов (300, adapter broken, CASES) | fixed e6d55a3 | | M-8 | Review Focus: RF1 «ни одна строка не пропала», RF3 date.form_name не проверены явно | deferred | | O-1 | relations_failed в aep_3 повторяются по колонкам (поведение пакета) | deferred (пакет, план 1) | | O-2 | make check-full целиком не запускался (общий стек владельца); шаги прогнаны по отдельности на своём compose-проекте | deferred | | O-3 | одиночный суррогат в тексте ячейки OCR не чистится ни пакетом, ни шлюзом (было и раньше) | deferred | | O-4 | build_result вне try в _accept_answer (структура прежняя) | deferred | ## Rulings I made - R-1 трейлер коммитов `Co-Authored-By: Claude Opus 5.5` + Claude-Session из плана. - R-2 (Р-36) примеры контракта: только копии существующих верхнего уровня. - R-3 усечение 300 символов (P5-9) применяется к тексту исключения, не ко всей строке «Тип: текст». - R-4 `NormalizeOutcome` вынесен в `src/normalizer/outcome.py` с реэкспортом (цикл импортов). - R-5 `app.py` вызывает `OcrNormalizer()` без аргумента (import arm_statements разрешён только в `src/normalizer/**` и tests). - R-6 сравнение golden временно под skip между T4 и T6 (снято в T6). - R-7 смешанный набор (ошибочный json + успешный без таблиц/документов) → `RECOGNITION_FAILED`; код первого ошибочного — только если успешных json нет. - P5-1…P5-20 — в `openspec/changes/statements-v2/design.md`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 11 commits 2026-10-18 19:32:45 +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
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
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
aep added 1 commit 2026-10-18 20:30:42 +03:00
aep merged commit 1d05b9e2b3 into main 2026-10-19 07:38:23 +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-scan-gateway#47
No description provided.