feat(statements): парсер ББ и ОФР из Excel, контракт v1.2 (Срез 2b) #16

Merged
aep merged 43 commits from feat/14-slice-2b-statement-parser into main 2026-10-06 21:38:00 +03:00
Owner

Код Среза 2b: парсер ББ и ОФР из Excel + контракт v1.2 (ветка раньше содержала только спеку). Refs #14. Сквозной change: RSHB/arm-ka-docs PR #27 (issue #26). Верхнеуровневый план: docs/superpowers/plans/2026-10-06-slice-2b-statement-parser.md в ветке docs.

Что сделано

  • BookParser (src/parser/book.py): классификация листов книги (ОСВ / форма / продолжение / прочее), OsvParser стал конвейером листа, get_parser отдаёт BookParser. Порядок документов: ОСВ, затем формы; статус книги по худшему документу; INVALID_DOCUMENT — нет ни ОСВ, ни форм.
  • Пакет src/parser/statements/ (columns, detect, header, lines, checks, merge, statement): колонка кодов (порог 60 %, диапазоны ББ 1100–1799 / ОФР 2100–2999 / расшифровки 5xxx), колонки-периоды, шапка (ИНН не аудитора), строки с кодами (в т.ч. пятизначные), самопроверка соотношений §7 (жёсткие/мягкие, допуск ±1, abs_terms для знаков 1С), склейка листов-продолжений, критерий ok.
  • Словари — данные: api/rules/statement_headers.yaml, statement_periods.yaml, statement_checks.yaml (+ модели и валидаторы в rules.py).
  • Контракт v1.2 (MINOR): DISCLOSURE, statementDocument.checks, osvDocument.header.period_start/period_end/is_from_year_start; копия схемы и примеры байт в байт с docs; CONTRACT_VERSION не менялся.
  • Границы периода ОСВ в шапке (period_start, period_end, is_from_year_start).
  • Тесты: манифест реальных форм (api/tests/statements_manifest.yaml), property-тест, golden expected_statement_parse/ (18 реальных + 7 синтетических), синтетика st01–st07, интеграционный тест книги НПЗ через воркер. README «Парсер форм (ББ/ОФР)», CLAUDE.md сервиса.

Как проверить

make -C <tabular-parser> check            # линт + юнит (2205 passed)
make -C <tabular-parser> up && make -C <tabular-parser> check-full   # + интеграция (10 passed)
make -C <tabular-parser> test-fixtures    # реальные файлы, ~150 с (порог 288 с)
make -C <tabular-parser> golden-check     # 138 из 138 без изменений
cd tabular-parser && openspec validate slice-2b-statement-parser --strict

CLI на форме: см. README, раздел «Запуск на файле».

Таблица «файл → статус» (манифест)

Реальные формы — 18 файлов; done только у Межениновской. Остальное — данные файла, а не дефект разбора: страницы без шапки, «только актив», шаблоны, значения в рублях с копейками при шапке «тыс. руб.» (OQ-138; допуск ±1 не менялся — решение владельца).

Файл Документы: тип — статус (причина)
unagrande-co/2024-FY/Б.Б Лист 1.xls BALANCE — needs_check (только актив: 1600 = 1700 не сходится)
unagrande-co/2024-FY/Б.Б. Лист 2.xls BALANCE — needs_check (страница 2 без шапки)
unagrande-co/2024-FY/ОФР. Лист 1.xls INCOME — needs_check (по факту: значения в рублях с копей��ами при шапке тыс. руб., итоги 2100/2200/2300 округлены до тысяч и расходятся с суммой частей (OQ-138))
unagrande-co/2024-FY/ОФР. Лист 2 .xls INCOME — needs_check (страница 2 без шапки)
unagrande-group/2024-FY/ББ. Лист 1 .xls BALANCE — needs_check (только актив)
unagrande-group/2024-FY/ББ. Лист 2 (2).xls BALANCE — needs_check (страница 2 без шапки)
unagrande-group/2024-FY/ОФР. Лист 2.xls INCOME — needs_check (страница 2 без шапки, стр. 1 в пакете нет)
unagrande-group/2025-Q3/ББ. Лист 1 3кв.25.xls BALANCE — needs_check (только актив)
unagrande-group/2025-Q3/ББ. Лист 2 3кв.25.xls BALANCE — needs_check (страница 2 без шапки)
unagrande-group/2025-Q3/ОФР. Лист 1 3кв.25.xls INCOME — needs_check (по факту: значения в рублях с копейками при шапке тыс. руб., 2100 расходится на 17.50/9.43 руб., 2200/2300 — округление итогов до тысяч (OQ-138))
unagrande-group/2025-Q3/ОФР. Лист 2 3кв.25.xls INCOME — needs_check (страница 2 без шапки)
npz/2025-Q3/Бухгалтерская отчетность за Январь - Сентябрь 2025 г. (НОВОРОССИЙСКИЙ ПРОКАТНЫЙ ЗАВОД).xlsx BALANCE — needs_check (1600 = 1700 расходится на 1.94/9.02/2.48 руб.: значения в рублях при шапке тыс. руб. (OQ-138)); INCOME — needs_check (по факту: рубли с копейками при шапке тыс. руб., 2100/2200/2300 расходятся с округлёнными итогами (OQ-138); лист продолжения с единственной строкой 2400 присоединён (O-9))
mezheninovskaya/2025-Q3/1_Форма1_бух_09.xlsx BALANCE — done
mezheninovskaya/2025-Q3/1_Форма2_бух_09.xlsx INCOME — done
templates/ББ до 01.01.2025.xlsx BALANCE — needs_check (шаблон без сумм и шапки); DISCLOSURE — done (по факту: «Примечания» шаблона образуют пустой документ DISCLOSURE)
templates/ББ после 01.01.2025.xlsx BALANCE — needs_check (шаблон)
templates/ОФР_до 01.01.2025.xlsx INCOME — needs_check (шаблон)
templates/ОФР_после 01.01.2025.xlsx INCOME — needs_check (шаблон)

Rulings I made

№ Решение Цена ошибки
R-1 Временный скрипт проверки схемы в задаче 1 — в scratchpad контроллера нулевая
R-2 (design #12) В scan-gateway вместе с v1.2 догнан v1.1 (OsvRow.extra, пример result-osv-needs-check.json): копия схемы обязана совпадать с docs побайтно лишний необязательный OsvRow.extra, откатывается отдельным коммитом
R-3 (design #14) Golden schema_version 1.1→1.2 (113 файлов) пересозданы сразу в worktree fixtures, симлинк переключён; основной checkout fixtures не тронут коммит в fixtures-ветке раньше плана; откат — reset ветки
R-4 (design #15) docs/contracts/** после задачи 1 заморожены (копии в arm-core#27 / scan-gateway#5 на ревью); T1.1/T2.1/T2.2/T2.3 — follow-up три косметических замечания живут до следующего MINOR
R-5 (design #16) T6.I1 (osv.py не знал STATEMENT_CONTINUATION) закрыт заменой osv.py::parse на BookParser в задаче 7 (+ тест) если бы T7 не покрыла — поймало бы финальное ревью
R-6 (design #17) Соотношение проверяется в колонке, только если присутствует его цель; отсутствующие члены = 0; подстроки — когда есть форма без итоговой строки при наличии членов этим соотношением не ловится
R-7 (design #18) Словарь statement_checks.yaml не ослаблен (жёсткие 1100…1500, 2100…2300 остаются strict: true); данные теста плана исправлены меняется одна строка yaml
R-8 (design #19) Для подстрок общий допуск ±1 расхождение в 1 единицу у подстрок не ловится
R-9 (design #20) _RELATION/_TERM допускают пятизначные коды справа (plan-mandated), явные правила из yaml валидатор ограничивает четырёхзначными закрыто валидатором
R-10 (design #21) Принять отклонения задачи 12: продолжение без колонки кодов → needs_check книги; OTHER-продолжение по правилам ББ; form_name не передаётся лишний needs_check на редком листе
R-11 (design #22) → R-13 (design #23) Допуск ±1 не менялся; баланс НПЗ ожидаемо needs_check (рубли с копейками при шапке «тыс. руб.»; 1600 = 1700 расходятся на 1.94 / 9.02 / 2.48 руб.) — решение владельца, вариант А если владелец передумает — допуск/нормировка единиц в словаре (OQ-138)
R-12 Fix round 2 задачи 13 отдан свежему исполнителю на sonnet (не резюм haiku) лишний контекст
R-14 (design #24) ОФР НПЗ и ОФР Унагранде (стр. 1) по факту needs_check (2100 расходится на 17.50 / 9.43 / 1416, единицы), допуск ±1 не менялся; сценарий «Знаки 1С» перенесён на Межениновскую если владелец хочет done на реальных ОФР — допуск/нормировка в словаре
R-15 (design #26) Наши OQ-137…142 перенумерованы в OQ-138…143: в main OQ-137 занят вопросом о горячих папках ссылки на OQ-13x в старых комментариях/описаниях
R-16 (design #27) Одна волна фиксов по финальному ревью: I-1 (лист с единственной кодовой строкой присоединяется как продолжение, порог в словаре) + M-10, I-2, I-3, M-1…M-8, M-11, T13.5, T15.1, T15.2; остальное — follow-up I-1 расширил парсер после ревью задач (N-1: ложные присоединения листов после формы)
O-1 (операционное) Контроллер запустил Docker Desktop (open -a Docker) для make up интеграционных тестов задачи 15 нет
O-12 В трейлере Claude-Session коммитов финальной волны URL сессии вместо UUID; историю не переписывали неединообразный трейлер

Находки и статусы

Статус каждой находки: fixed <коммит> / deferred / rejected <причина>. Коммиты — tabular-parser (если не указано иное). Deferred уйдут в follow-up issue при закрытии.

Маркер Суть Статус
T1.1 / T2.1 $comment схемы упоминает «1.1» (plan-mandated, R-4) deferred
T1.2 format: date не проверяется без format_checker в check-скрипте deferred
T1.3 число «3» в примере произвольно rejected: косметика примера
T2.2 пример result-statement-excel.json — needs_check при одном мягком нарушении (R-4); плюс M-12: у BALANCE нет 1700 при relations_failed: [] deferred
T2.3 result-statement-minimal.json (OCR) получил checks, что противоречит «нет объекта = не проверялось» deferred
T2.4 необязательные негативные тесты rejected: вне брифа
T3.1 / T3.2 догон v1.1 в scan-gateway; CONTRACT_VERSION остаётся 1.0 fixed (описания PR arm-core#27, scan-gateway#5)
O-1 make golden-update в T2 переписал 113 golden в основном checkout fixtures fixed: закрыт R-3 (основной checkout чист, проверено финальным ревью)
O-2 отчёт реализатора T5 без вывода тестов; контроллер прогнал сам fixed (правило «вывод команд в отчёте»)
T4.I1 okud DISCLOSURE pattern не по брифу fixed 6a3661c
T4.1–T4.6 перепарсинг RelationRule; повтор any(...); нет проверки lo<=hi; FormType не в __all__; нет негативных тестов словарей; неточный комментарий periods deferred
T5.1–T5.5 мёртвые noqa; шумные константы; непокрытая ветка; лишние вычисления; «Пояснения» только в header_row deferred
T6.I1 osv.py не обрабатывал STATEMENT_CONTINUATION fixed 43ee753 (R-5)
T6.1 устаревшие statement_markers (M-6) fixed 1abe212
T6.2 _OKUD_CODE литерал в detect.py, английский комментарий, type: ignore (M-5) fixed 1abe212
T6.3–T6.5 производительность classify; пробелы в тестах; ложное «продолжение» на «прочем» deferred
T7.1 / T7.2 предупреждения пропуска форм при ошибке ОСВ-листа; семантика metrics.rows форм deferred
O-3 бриф T7 неточен про golden s12/s14 deferred (принято)
T8.I1 диапазон «Январь - Май 2025» давал неверные границы периода fixed f279157
T8.1–T8.4 пробелы в тестах границ периода deferred
T8.5 ветка «одиночный месяц» в bounds_span слишком широка (= I-2) fixed 1abe212
O-4 для «Январь - Май» quarter=Q4/is_cumulative остаются от правила «год» deferred (вместе с OQ-131)
T9.I1 тест охраны ИНН аудитора не проверял охрану (3 раунда) fixed cb0bd06
T9.1–T9.5, O-5 приватный импорт в тесте; кавычки аннотации; фолбэк организации без теста; okpo без границы аудитора; неточные номера строк deferred
T10.I1 / T10.I2 порог дробной доли зашит в код; нет теста границы 10 % fixed aad6310
T10.1–T10.6 float в сравнении (закрыт целочисленным сравнением, финальное ревью); дубликаты с повторами; merged_origin; перегруженный тест; минус-знак; RED не показан deferred (T10.1/T10.2 закрыты кодом)
T10.7 README/тест для fractional_share_percent (M-7) fixed 1abe212
T11.I1–I4 ослабление yaml; пропуск правила при отсутствии цели; нулевой допуск подстрок; расширение _RELATION fixed 72e5656, b9e6e31 (R-6…R-9)
T11.1 / T11.2 / O-6 is_subline по равенству моделей; устаревший раздел в fix-отчёте; 1600=1700 на фрагментах deferred / принято
T12.1 предупреждение о дробных считалось по листу, мёртвые счётчики (M-11) fixed 1abe212
T12.2, T12.4–T12.9 избыточная ветка lonely; O(n·m); побочный эффект _document; вакуумный тест; docstring; повтор form_name; нет теста дубликата в продолжении deferred
T12.3 can_join игнорировал тип формы (M-10) fixed 1abe212
O-7 D-8 «лист ОСВ между страницами» не реализуем интерфейсом deferred (принято)
T13.I1–I4 st02 подогнана под ответ; тест не проверял сценарии спеки; слабые st04/st01; пустая autouse-фикстура; дефект _upper_header_row fixed fad0c10, e7552dc, 4907935 (+ fixtures f938255, b63c0a5)
T13.3 / T13.4 нет отрицательного теста _upper_header_row; константа посреди файла deferred (T13.3 покрыт в финальной волне)
T13.5 _upper_header_row: верхняя строка при склейке хотя бы одной колонки fixed 1abe212
T13.6 api/uv.lock попал в коммит 4907935 (M-1) fixed 336f4d6
O-8 relations_failed / soft_relations_failed не попадали в wire (exclude_unset) fixed 1b17f2e
T14.I1 FailedRelation.actual не по ближайшему варианту abs_terms fixed d82940a (+ fixtures ba600fc)
T14.I2 property-тест вакуумен для complete: false fixed 6cd2ea8
T14.1, T14.2, T14.5, T14.6 нет теста уровня документа для checks; sheets через locator.count(","); document_ok не покрывает has_code_column; слабый explained_needs_check deferred
T14.3 ОКВЭД в шапке design/05-domain-rules при удалённой метке rejected: в 05-domain-rules ОКВЭД не упоминается, design описывает содержимое файла
T14.4 шаблон «ББ до» даёт пустой DISCLOSURE done из блока «Примечания» deferred (закреплено манифестом)
T15.1 / T15.2 README «Ограничения» п.1 неточен; тест воркера INCOME слабый fixed 1abe212
T15.3 / T15.4 README про «лишние снимки» форм; остановка compose deferred
T16.I1, T16.2, T16.3 docs: 88 vs 113 файлов; цитаты предупреждений; «байт в байт» fixed docs 4729e40
T16.4 статус PR в 09-delivery-plan устареет после merge deferred
O-9 (= I-1) лист ОФР НПЗ с единственной строкой 2400 терялся молча fixed 1abe212 (+ fixtures 9586207)
O-10 (= M-3) design D-11 обещал НПЗ done fixed 15fb561
O-11 в main docs занят OQ-137 fixed: R-15, docs 9235e6a, tabular-parser be47e82
O-13 интеграционный прогон финальной волны не был показан fixed: make check-full контроллером (ниже)
C-n Critical из финального ревью нет
I-1 см. O-9 fixed 1abe212
I-2 см. T8.5 fixed 1abe212
I-3 пустой line_name при line_name_confidence = 100 у итогов и «в том числе» fixed 1abe212 (+ fixtures 9586207)
M-1…M-8, M-10, M-11 uv.lock; tasks.md; D-11; §1.1 и README про текст пропуска; слово «тыс»/ОКУД в коде; statement_markers; fractional_share_percent; нумерация/нули в «строках без кода»; can_join; одно предупреждение на документ fixed 336f4d6, 1abe212, 15fb561, docs 5b34868
M-9 подстроки с 10-го номера (11510, 15110…) не попадают в _subline_rules deferred
M-12 примеры контракта противоречат описанию схемы (= T2.2/T2.3), обязательно до Среза 3 deferred
N-1 ослабленный порог (min_codes_continuation = 1) допускает ложные присоединения листов после формы; при совпадении числа колонок строка молча присоединяется и документ может остаться done deferred (значимая; реальные фикстуры не затронуты)
N-2 book.py:109: «была форма раньше», а не «сразу после листа формы» deferred
N-3 нет негативных BookParser-тестов шлюза продолжений deferred
N-4 «Пояснения» без шапки таблицы на продолжении могут стать line_name deferred
N-5 design D-10 («periods.yaml не правится») противоречит правке I-2 (not_single_month); конфликт при rebase на #11 deferred

На что обратить внимание человеку

  • N-1: ослабленный порог продолжений (min_codes_continuation = 1) может присоединить посторонний лист с единственным числом в диапазоне кодов к последнему документу (при совпадении числа колонок — молча). На реальных файлах не проявляется; follow-up с охраной «сразу после листа формы» и негативными тестами.
  • Реальные ОФР Унагранде и НПЗ — needs_check из-за единиц (OQ-138); если нужно done — решение по допуску/нормировке единиц.
  • Копии схемы в arm-core#27 и scan-gateway#5 не менялись с этой ветки.
  • Docker Desktop запускал контроллер для интеграционных тестов (make up).

Порядок мержа

docs #27 → arm-core #27 и scan-gateway #5 → fixtures (feat/14-statements-golden; иначе make test-fixtures на main упадёт) → этот PR. Новые номера вопросов: OQ-138…143 (OQ-137 в main занят горячими папками).

Deferred → follow-up issue

См. строки deferred в таблице находок (при закрытии собираются в «Follow-ups from #14»).

🤖 Generated with Claude Code

**Код Среза 2b: парсер ББ и ОФР из Excel + контракт v1.2** (ветка раньше содержала только спеку). Refs #14. Сквозной change: RSHB/arm-ka-docs PR #27 (issue #26). Верхнеуровневый план: `docs/superpowers/plans/2026-10-06-slice-2b-statement-parser.md` в ветке docs. ## Что сделано - `BookParser` (`src/parser/book.py`): классификация листов книги (ОСВ / форма / продолжение / прочее), `OsvParser` стал конвейером листа, `get_parser` отдаёт `BookParser`. Порядок документов: ОСВ, затем формы; статус книги по худшему документу; `INVALID_DOCUMENT` — нет ни ОСВ, ни форм. - Пакет `src/parser/statements/` (columns, detect, header, lines, checks, merge, statement): колонка кодов (порог 60 %, диапазоны ББ 1100–1799 / ОФР 2100–2999 / расшифровки 5xxx), колонки-периоды, шапка (ИНН не аудитора), строки с кодами (в т.ч. пятизначные), самопроверка соотношений §7 (жёсткие/мягкие, допуск ±1, `abs_terms` для знаков 1С), склейка листов-продолжений, критерий `ok`. - Словари — данные: `api/rules/statement_headers.yaml`, `statement_periods.yaml`, `statement_checks.yaml` (+ модели и валидаторы в `rules.py`). - Контракт v1.2 (MINOR): `DISCLOSURE`, `statementDocument.checks`, `osvDocument.header.period_start/period_end/is_from_year_start`; копия схемы и примеры байт в байт с docs; `CONTRACT_VERSION` не менялся. - Границы периода ОСВ в шапке (`period_start`, `period_end`, `is_from_year_start`). - Тесты: манифест реальных форм (`api/tests/statements_manifest.yaml`), property-тест, golden `expected_statement_parse/` (18 реальных + 7 синтетических), синтетика st01–st07, интеграционный тест книги НПЗ через воркер. README «Парсер форм (ББ/ОФР)», CLAUDE.md сервиса. ## Как проверить ```bash make -C <tabular-parser> check # линт + юнит (2205 passed) make -C <tabular-parser> up && make -C <tabular-parser> check-full # + интеграция (10 passed) make -C <tabular-parser> test-fixtures # реальные файлы, ~150 с (порог 288 с) make -C <tabular-parser> golden-check # 138 из 138 без изменений cd tabular-parser && openspec validate slice-2b-statement-parser --strict ``` CLI на форме: см. README, раздел «Запуск на файле». ## Таблица «файл → статус» (манифест) Реальные формы — 18 файлов; **`done` только у Межениновской**. Остальное — данные файла, а не дефект разбора: страницы без шапки, «только актив», шаблоны, значения в рублях с копейками при шапке «тыс. руб.» (OQ-138; допуск ±1 не менялся — решение владельца). | Файл | Документы: тип — статус (причина) | |---|---| | `unagrande-co/2024-FY/Б.Б Лист 1.xls` | BALANCE — needs_check (только актив: 1600 = 1700 не сходится) | | `unagrande-co/2024-FY/Б.Б. Лист 2.xls` | BALANCE — needs_check (страница 2 без шапки) | | `unagrande-co/2024-FY/ОФР. Лист 1.xls` | INCOME — needs_check (по факту: значения в рублях с копей��ами при шапке тыс. руб., итоги 2100/2200/2300 округлены до тысяч и расходятся с суммой частей (OQ-138)) | | `unagrande-co/2024-FY/ОФР. Лист 2 .xls` | INCOME — needs_check (страница 2 без шапки) | | `unagrande-group/2024-FY/ББ. Лист 1 .xls` | BALANCE — needs_check (только актив) | | `unagrande-group/2024-FY/ББ. Лист 2 (2).xls` | BALANCE — needs_check (страница 2 без шапки) | | `unagrande-group/2024-FY/ОФР. Лист 2.xls` | INCOME — needs_check (страница 2 без шапки, стр. 1 в пакете нет) | | `unagrande-group/2025-Q3/ББ. Лист 1 3кв.25.xls` | BALANCE — needs_check (только актив) | | `unagrande-group/2025-Q3/ББ. Лист 2 3кв.25.xls` | BALANCE — needs_check (страница 2 без шапки) | | `unagrande-group/2025-Q3/ОФР. Лист 1 3кв.25.xls` | INCOME — needs_check (по факту: значения в рублях с копейками при шапке тыс. руб., 2100 расходится на 17.50/9.43 руб., 2200/2300 — округление итогов до тысяч (OQ-138)) | | `unagrande-group/2025-Q3/ОФР. Лист 2 3кв.25.xls` | INCOME — needs_check (страница 2 без шапки) | | `npz/2025-Q3/Бухгалтерская отчетность за Январь - Сентябрь 2025 г. (НОВОРОССИЙСКИЙ ПРОКАТНЫЙ ЗАВОД).xlsx` | BALANCE — needs_check (1600 = 1700 расходится на 1.94/9.02/2.48 руб.: значения в рублях при шапке тыс. руб. (OQ-138)); INCOME — needs_check (по факту: рубли с копейками при шапке тыс. руб., 2100/2200/2300 расходятся с округлёнными итогами (OQ-138); лист продолжения с единственной строкой 2400 присоединён (O-9)) | | `mezheninovskaya/2025-Q3/1_Форма1_бух_09.xlsx` | BALANCE — done | | `mezheninovskaya/2025-Q3/1_Форма2_бух_09.xlsx` | INCOME — done | | `templates/ББ до 01.01.2025.xlsx` | BALANCE — needs_check (шаблон без сумм и шапки); DISCLOSURE — done (по факту: «Примечания» шаблона образуют пустой документ DISCLOSURE) | | `templates/ББ после 01.01.2025.xlsx` | BALANCE — needs_check (шаблон) | | `templates/ОФР_до 01.01.2025.xlsx` | INCOME — needs_check (шаблон) | | `templates/ОФР_после 01.01.2025.xlsx` | INCOME — needs_check (шаблон) | ## Rulings I made | № | Решение | Цена ошибки | |---|---|---| | R-1 | Временный скрипт проверки схемы в задаче 1 — в scratchpad контроллера | нулевая | | R-2 (design #12) | В scan-gateway вместе с v1.2 догнан v1.1 (`OsvRow.extra`, пример `result-osv-needs-check.json`): копия схемы обязана совпадать с docs побайтно | лишний необязательный `OsvRow.extra`, откатывается отдельным коммитом | | R-3 (design #14) | Golden `schema_version` 1.1→1.2 (113 файлов) пересозданы сразу в worktree fixtures, симлинк переключён; основной checkout fixtures не тронут | коммит в fixtures-ветке раньше плана; откат — reset ветки | | R-4 (design #15) | `docs/contracts/**` после задачи 1 заморожены (копии в arm-core#27 / scan-gateway#5 на ревью); T1.1/T2.1/T2.2/T2.3 — follow-up | три косметических замечания живут до следующего MINOR | | R-5 (design #16) | T6.I1 (osv.py не знал `STATEMENT_CONTINUATION`) закрыт заменой `osv.py::parse` на `BookParser` в задаче 7 (+ тест) | если бы T7 не покрыла — поймало бы финальное ревью | | R-6 (design #17) | Соотношение проверяется в колонке, только если присутствует его цель; отсутствующие члены = 0; подстроки — когда есть | форма без итоговой строки при наличии членов этим соотношением не ловится | | R-7 (design #18) | Словарь `statement_checks.yaml` не ослаблен (жёсткие 1100…1500, 2100…2300 остаются `strict: true`); данные теста плана исправлены | меняется одна строка yaml | | R-8 (design #19) | Для подстрок общий допуск ±1 | расхождение в 1 единицу у подстрок не ловится | | R-9 (design #20) | `_RELATION/_TERM` допускают пятизначные коды справа (plan-mandated), явные правила из yaml валидатор ограничивает четырёхзначными | закрыто валидатором | | R-10 (design #21) | Принять отклонения задачи 12: продолжение без колонки кодов → `needs_check` книги; `OTHER`-продолжение по правилам ББ; `form_name` не передаётся | лишний `needs_check` на редком листе | | R-11 (design #22) → R-13 (design #23) | Допуск ±1 не менялся; баланс НПЗ ожидаемо `needs_check` (рубли с копейками при шапке «тыс. руб.»; 1600 = 1700 расходятся на 1.94 / 9.02 / 2.48 руб.) — решение владельца, вариант А | если владелец передумает — допуск/нормировка единиц в словаре (OQ-138) | | R-12 | Fix round 2 задачи 13 отдан свежему исполнителю на sonnet (не резюм haiku) | лишний контекст | | R-14 (design #24) | ОФР НПЗ и ОФР Унагранде (стр. 1) по факту `needs_check` (2100 расходится на 17.50 / 9.43 / 1416, единицы), допуск ±1 не менялся; сценарий «Знаки 1С» перенесён на Межениновскую | если владелец хочет `done` на реальных ОФР — допуск/нормировка в словаре | | R-15 (design #26) | Наши OQ-137…142 перенумерованы в OQ-138…143: в main OQ-137 занят вопросом о горячих папках | ссылки на OQ-13x в старых комментариях/описаниях | | R-16 (design #27) | Одна волна фиксов по финальному ревью: I-1 (лист с единственной кодовой строкой присоединяется как продолжение, порог в словаре) + M-10, I-2, I-3, M-1…M-8, M-11, T13.5, T15.1, T15.2; остальное — follow-up | I-1 расширил парсер после ревью задач (N-1: ложные присоединения листов после формы) | | O-1 (операционное) | Контроллер запустил Docker Desktop (`open -a Docker`) для `make up` интеграционных тестов задачи 15 | нет | | O-12 | В трейлере `Claude-Session` коммитов финальной волны URL сессии вместо UUID; историю не переписывали | неединообразный трейлер | ## Находки и статусы Статус каждой находки: `fixed <коммит>` / `deferred` / `rejected <причина>`. Коммиты — tabular-parser (если не указано иное). Deferred уйдут в follow-up issue при закрытии. | Маркер | Суть | Статус | |---|---|---| | T1.1 / T2.1 | `$comment` схемы упоминает «1.1» (plan-mandated, R-4) | deferred | | T1.2 | `format: date` не проверяется без format_checker в check-скрипте | deferred | | T1.3 | число «3» в примере произвольно | rejected: косметика примера | | T2.2 | пример `result-statement-excel.json` — `needs_check` при одном мягком нарушении (R-4); плюс M-12: у BALANCE нет 1700 при `relations_failed: []` | deferred | | T2.3 | `result-statement-minimal.json` (OCR) получил `checks`, что противоречит «нет объекта = не проверялось» | deferred | | T2.4 | необязательные негативные тесты | rejected: вне брифа | | T3.1 / T3.2 | догон v1.1 в scan-gateway; `CONTRACT_VERSION` остаётся 1.0 | fixed (описания PR arm-core#27, scan-gateway#5) | | O-1 | `make golden-update` в T2 переписал 113 golden в основном checkout fixtures | fixed: закрыт R-3 (основной checkout чист, проверено финальным ревью) | | O-2 | отчёт реализатора T5 без вывода тестов; контроллер прогнал сам | fixed (правило «вывод команд в отчёте») | | T4.I1 | okud DISCLOSURE pattern не по брифу | fixed 6a3661c | | T4.1–T4.6 | перепарсинг RelationRule; повтор `any(...)`; нет проверки lo<=hi; `FormType` не в `__all__`; нет негативных тестов словарей; неточный комментарий periods | deferred | | T5.1–T5.5 | мёртвые noqa; шумные константы; непокрытая ветка; лишние вычисления; «Пояснения» только в header_row | deferred | | T6.I1 | `osv.py` не обрабатывал `STATEMENT_CONTINUATION` | fixed 43ee753 (R-5) | | T6.1 | устаревшие `statement_markers` (M-6) | fixed 1abe212 | | T6.2 | `_OKUD_CODE` литерал в detect.py, английский комментарий, `type: ignore` (M-5) | fixed 1abe212 | | T6.3–T6.5 | производительность classify; пробелы в тестах; ложное «продолжение» на «прочем» | deferred | | T7.1 / T7.2 | предупреждения пропуска форм при ошибке ОСВ-листа; семантика `metrics.rows` форм | deferred | | O-3 | бриф T7 неточен про golden s12/s14 | deferred (принято) | | T8.I1 | диапазон «Январь - Май 2025» давал неверные границы периода | fixed f279157 | | T8.1–T8.4 | пробелы в тестах границ периода | deferred | | T8.5 | ветка «одиночный месяц» в `bounds_span` слишком широка (= I-2) | fixed 1abe212 | | O-4 | для «Январь - Май» quarter=Q4/is_cumulative остаются от правила «год» | deferred (вместе с OQ-131) | | T9.I1 | тест охраны ИНН аудитора не проверял охрану (3 раунда) | fixed cb0bd06 | | T9.1–T9.5, O-5 | приватный импорт в тесте; кавычки аннотации; фолбэк организации без теста; okpo без границы аудитора; неточные номера строк | deferred | | T10.I1 / T10.I2 | порог дробной доли зашит в код; нет теста границы 10 % | fixed aad6310 | | T10.1–T10.6 | float в сравнении (закрыт целочисленным сравнением, финальное ревью); дубликаты с повторами; `merged_origin`; перегруженный тест; минус-знак; RED не показан | deferred (T10.1/T10.2 закрыты кодом) | | T10.7 | README/тест для `fractional_share_percent` (M-7) | fixed 1abe212 | | T11.I1–I4 | ослабление yaml; пропуск правила при отсутствии цели; нулевой допуск подстрок; расширение `_RELATION` | fixed 72e5656, b9e6e31 (R-6…R-9) | | T11.1 / T11.2 / O-6 | `is_subline` по равенству моделей; устаревший раздел в fix-отчёте; 1600=1700 на фрагментах | deferred / принято | | T12.1 | предупреждение о дробных считалось по листу, мёртвые счётчики (M-11) | fixed 1abe212 | | T12.2, T12.4–T12.9 | избыточная ветка lonely; O(n·m); побочный эффект `_document`; вакуумный тест; docstring; повтор `form_name`; нет теста дубликата в продолжении | deferred | | T12.3 | `can_join` игнорировал тип формы (M-10) | fixed 1abe212 | | O-7 | D-8 «лист ОСВ между страницами» не реализуем интерфейсом | deferred (принято) | | T13.I1–I4 | st02 подогнана под ответ; тест не проверял сценарии спеки; слабые st04/st01; пустая autouse-фикстура; дефект `_upper_header_row` | fixed fad0c10, e7552dc, 4907935 (+ fixtures f938255, b63c0a5) | | T13.3 / T13.4 | нет отрицательного теста `_upper_header_row`; константа посреди файла | deferred (T13.3 покрыт в финальной волне) | | T13.5 | `_upper_header_row`: верхняя строка при склейке хотя бы одной колонки | fixed 1abe212 | | T13.6 | `api/uv.lock` попал в коммит 4907935 (M-1) | fixed 336f4d6 | | O-8 | `relations_failed` / `soft_relations_failed` не попадали в wire (`exclude_unset`) | fixed 1b17f2e | | T14.I1 | `FailedRelation.actual` не по ближайшему варианту `abs_terms` | fixed d82940a (+ fixtures ba600fc) | | T14.I2 | property-тест вакуумен для `complete: false` | fixed 6cd2ea8 | | T14.1, T14.2, T14.5, T14.6 | нет теста уровня документа для checks; `sheets` через `locator.count(",")`; `document_ok` не покрывает `has_code_column`; слабый `explained_needs_check` | deferred | | T14.3 | ОКВЭД в шапке design/05-domain-rules при удалённой метке | rejected: в 05-domain-rules ОКВЭД не упоминается, design описывает содержимое файла | | T14.4 | шаблон «ББ до» даёт пустой DISCLOSURE `done` из блока «Примечания» | deferred (закреплено манифестом) | | T15.1 / T15.2 | README «Ограничения» п.1 неточен; тест воркера INCOME слабый | fixed 1abe212 | | T15.3 / T15.4 | README про «лишние снимки» форм; остановка compose | deferred | | T16.I1, T16.2, T16.3 | docs: 88 vs 113 файлов; цитаты предупреждений; «байт в байт» | fixed docs 4729e40 | | T16.4 | статус PR в 09-delivery-plan устареет после merge | deferred | | O-9 (= I-1) | лист ОФР НПЗ с единственной строкой 2400 терялся молча | fixed 1abe212 (+ fixtures 9586207) | | O-10 (= M-3) | design D-11 обещал НПЗ `done` | fixed 15fb561 | | O-11 | в main docs занят OQ-137 | fixed: R-15, docs 9235e6a, tabular-parser be47e82 | | O-13 | интеграционный прогон финальной волны не был показан | fixed: `make check-full` контроллером (ниже) | | C-n | Critical из финального ревью | нет | | I-1 | см. O-9 | fixed 1abe212 | | I-2 | см. T8.5 | fixed 1abe212 | | I-3 | пустой `line_name` при `line_name_confidence = 100` у итогов и «в том числе» | fixed 1abe212 (+ fixtures 9586207) | | M-1…M-8, M-10, M-11 | uv.lock; tasks.md; D-11; §1.1 и README про текст пропуска; слово «тыс»/ОКУД в коде; statement_markers; fractional_share_percent; нумерация/нули в «строках без кода»; can_join; одно предупреждение на документ | fixed 336f4d6, 1abe212, 15fb561, docs 5b34868 | | M-9 | подстроки с 10-го номера (11510, 15110…) не попадают в `_subline_rules` | deferred | | M-12 | примеры контракта противоречат описанию схемы (= T2.2/T2.3), обязательно до Среза 3 | deferred | | N-1 | ослабленный порог (`min_codes_continuation = 1`) допускает ложные присоединения листов после формы; при совпадении числа колонок строка молча присоединяется и документ может остаться `done` | deferred (значимая; реальные фикстуры не затронуты) | | N-2 | `book.py:109`: «была форма раньше», а не «сразу после листа формы» | deferred | | N-3 | нет негативных BookParser-тестов шлюза продолжений | deferred | | N-4 | «Пояснения» без шапки таблицы на продолжении могут стать `line_name` | deferred | | N-5 | design D-10 («periods.yaml не правится») противоречит правке I-2 (`not_single_month`); конфликт при rebase на #11 | deferred | ## На что обратить внимание человеку - **N-1**: ослабленный порог продолжений (`min_codes_continuation = 1`) может присоединить посторонний лист с единственным числом в диапазоне кодов к последнему документу (при совпадении числа колонок — молча). На реальных файлах не проявляется; follow-up с охраной «сразу после листа формы» и негативными тестами. - Реальные ОФР Унагранде и НПЗ — `needs_check` из-за единиц (OQ-138); если нужно `done` — решение по допуску/нормировке единиц. - Копии схемы в arm-core#27 и scan-gateway#5 не менялись с этой ветки. - Docker Desktop запускал контроллер для интеграционных тестов (`make up`). ## Порядок мержа docs #27 → arm-core #27 и scan-gateway #5 → fixtures (`feat/14-statements-golden`; иначе `make test-fixtures` на main упадёт) → **этот PR**. Новые номера вопросов: OQ-138…143 (OQ-137 в main занят горячими папками). ## Deferred → follow-up issue См. строки `deferred` в таблице находок (при закрытии собираются в «Follow-ups from #14»). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 1 commit 2026-10-06 12:21:52 +03:00
Proposal, design (D-1…D-11, решения без обсуждения №1–№11), новая capability statement-parsing,
дельта tabular-recognition-service (BookParser, schema_version 1.2), tasks. Решения владельца 06.10.2026:
только парсер и контракт; страницы-продолжения без склейки между файлами; единицы как есть; пятизначные
подстроки как строки; контракт MINOR 1.2; без запасного пути по именам.

Refs #14

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
aep added 1 commit 2026-10-06 12:54:05 +03:00
Шаблоны ФСБУ разносят год по ячейкам «20» и « г.», по тексту дату не собрать; требование к ним — разбор без ошибки
и needs_check.

Refs #14

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
aep added 1 commit 2026-10-06 13:09:38 +03:00
aep added 1 commit 2026-10-06 13:25:34 +03:00
Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
aep added 1 commit 2026-10-06 13:34:01 +03:00
Refs #14

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
aep added 27 commits 2026-10-06 18:38:59 +03:00
Refs #14

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Паттерн из брифа \b07100(0[3-9]|[1-9]\d)\b содержал дефисы в диапазонах и отвергался валидатором.
Переписан с альтернацией: \b07100(0(3|4|5|6|7|8|9)|(1|2|3|4|5|6|7|8|9)\d)\b
Добавлены граничные тесты для OKUD кодов (0710003, 0710010 → DISCLOSURE; 0710000 → None).

Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Refs #14
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Refs #14

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Листы-продолжения форм (STATEMENT_CONTINUATION) идут в конвейер форм, а не в разбор ОСВ (R-5).

Refs #14

Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Refs #14

Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Refs #14

Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Реализация Task 9: parse_header() извлекает значения полей из шапки документа ББ/ОФР
по меткам словаря Rules.statement_headers с особыми правилами:
- ИНН ниже блока аудитора пропускается (Review Focus)
- Организация ищется после метки, при пустом значении — выше с признаком ОПФ
- Дата из подзаголовка формы или тройки число/месяц/год
- Единицы, адрес, ОКПО, ОКОПФ/ОКФС по меткам; все найденные поля получают confidence=100
- При отсутствии продолжения блока метка берётся как form_name, остальные поля None

Тесты: 6 базовых сценариев + test_inn_skips_auditor_block (обязательный).

Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Обнаружена важная находка (T9.I1): test_inn_skips_auditor_block в ONE_C fixture
проходил из-за структуры данных (org INN выше auditor INN), не благодаря guard.
Добавлены два явных guard-теста, которые ПАДАЮТ БЕЗ guard и ПРОХОДЯТ с guard:

(a) test_inn_from_auditor_block_only_is_none — только block аудитора в шапке:
    Без guard (last_row): _inn находит auditor INN = 9999999999 ✗
    С guard (min(last_row, auditor_from-1)): находит Nothing = None ✓

(b) test_inn_from_auditor_above_organization_inn_line — org INN до auditor block:
    Оба случая находят org INN = 1234567890, но без guard мог бы найти auditor ✓

Дополнительно:
- Удалён импорт приватной _FULL_CONFIDENCE; использован литерал 100 с noqa
- Убрана необходимая кавычка в аннотации _report_date (datetime.date | None)
- Все 8 тестов зелены: 2085 passed в make check

Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Обнаружено: test_inn_from_auditor_above_organization_inn_line не тестирует guard,
т.к. org INN всегда раньше auditor block в реальных файлах. Без guard первый найденный
INN всё равно организации (появляется раньше). Guard не differentiates этот сценарий.

Удалены:
- test_inn_skips_auditor_block — ложноположительный, docstring утверждал Review Focus,
  но тест проходит из-за порядка (org INN раньше auditor), не из-за guard.
  Функциональность покрыта test_one_c_header.
- test_inn_from_auditor_above_organization_inn_line — guard не differentiates;
  добавлен в попытке тестировать сценарий, невозможный по дизайну.

Оставлен test_inn_from_auditor_block_only_is_none — единственный тест, где guard
реально нужен: без org INN, только auditor блок → guard исключает его, возвращает None.

Guard работает корректно: тестирует edge case отсутствия org INN.

Итог: 6 тестов, все честны относительно требований к guard.

Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Добавлен тест, проверяющий, что ИНН аудитора НИКОГДА не берётся, даже когда
аудиторский блок расположен РАНЬШЕ (выше) строк с ИНН организации.

Лист:
- Строка 3-5: блок аудитора (auditor_from=3)
  - Строка 4: аудиторский ИНН = 7716021332
- Строки 6-8: организация
  - Строка 8: org ИНН = 3249004697

С охраной min(last_row, auditor_from-1) = min(9, 2) = 2:
  Поиск в строках 1-2, ИНН не найден → header.inn is None ✓ GREEN

Без охраны (поиск в строках 1-9):
  Аудиторский ИНН найден первым → header.inn = 7716021332 ✗ RED

Этот тест доказывает, что guard критически важен для исключения аудитора.

Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Перенесено FRACTIONAL_SHARE в api/rules/statement_headers.yaml как fractional_share_percent (1..100),
добавлена валидация в StatementHeaderRules, целочисленное сравнение: fractional * 100 >= numeric * percent.
Добавлены тесты границ: ровно 10% (2 из 20), ниже 10% (1 из 12), без падения при нулевых числовых значениях.
Проверено RED мутацией: смена >= на > → падение теста граничного условия.

Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Refs #14

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
R-6: проверка только если цель присутствует (в колонке)
R-8: убран zero tolerance для подстрок, общий tolerance
R-7: тесты с полными данными (подкомпоненты)
R-9: валидация — явные правила 4-цифр, подстроки 5-цифр
R-7: усиление abs_terms теста (цепочка 2100→2200→2300)

Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
T11.I2: + test_target_absent_no_violations (INCOME: нет 2200; BALANCE: нет 1100)
T11.I2: + test_target_present_members_absent_as_zero (1100=100 без подстатей → нарушение)
test_relation_holds_with_abs_terms: Добавлены ненулевые значения 2210/2220/2330/2350
  1С: 2210=-50, 2220=-30, 2330=-20, 2350=-10
  66н: 2210=50, 2220=30, 2330=20, 2350=10

Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Refs #14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
StatementParser заменяет SkippingStatementParser; продолжение присоединяется к последнему открытому документу;
duplicate_line_codes — уникальные коды; потерянный лист-продолжение (нет колонки кодов) даёт needs_check.

Refs #14

Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Refs #14

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Refs #14
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
T13 round 1/5:
- st02: 1100=200, 1210=-50, 1200=-50 для выполнения всех проверок (1600 = 1100 + 1200, 1700 = 1300)
- Расширены тесты st01-st05: проверка колонок, типов документов, значений
- Исправлена фикстура _require_synthetic: используется statement_synthetic_skip_reason
- Добавлены константы для магических чисел
- Русские комментарии в коде

Refs #14
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Без подписи «Код» строкой заголовка выбиралась нижняя строка с датами; верхняя («На 31 декабря», «Изменение, %»)
оставалась над заголовком: колонка без периода не попадала в skipped_labels, метки периодов не склеивались.
Тест синтетики st02 проверяет точное предупреждение, две колонки и отсутствие значений «Изменение, %».

Refs #14

Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Генератор st02: значения ST02_VALUES сходятся по всем жёстким соотношениям. _upper_header_row: верхняя строка берётся,
только если подпись склеивается с датой в период. Refs #14

Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
aep added 11 commits 2026-10-06 21:13:21 +03:00
Баланс НПЗ расходится по 1600 = 1700 на 1.94 / 9.02 / 2.48 руб. (значения в
рублях при шапке «тыс. руб.», OQ-137): статус книги needs_check, допуск ±1
не меняется. Сценарий «Полные формы сходятся» ограничен формами Межениновской.

Refs #14

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Манифест statements_manifest.yaml по 18 реальным файлам statements-xlsx (сверен
прогоном парсера, R-13, OQ-137), property-тест по манифесту, снимки форм в
golden_helpers/golden_update/test_golden, словари форм в покрытии, синтетика
st06 для вариантов заголовков. Мёртвые записи словаря удалены (name_caption,
метки okved и okud_label) либо покрыты st06.

Refs #14

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Знаки 1С доказываются на ОФР Межениновской; ОФР НПЗ и Унагранде расходятся из-за
единиц (OQ-137). У НПЗ INCOME на двух листах, лист с одной строкой 2400 пропускается.

Refs #14

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
StatementChecks собирался пустым и дополнялся append, а to_wire сериализует только
заданные поля: нарушения не доходили до JSON. Списки теперь задаются явно, пустой
список у проверенного документа сериализуется (checks.relations_failed = []).

Refs #14

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Refs #14

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Refs #14

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Тест ожидает needs_check (рубли при шапке «тыс. руб.», OQ-137).

Refs #14

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Номер OQ-137 в main docs занят вопросом о раскладке горячих папок; design: решение №26.

Refs #14

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
Refs #14

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EAKRDNzXtRrwmWz9z6PZu3
I-1: лист с 1–2 кодами после листа формы — продолжение (min_codes_continuation в словаре).
M-10: тип формы маркера продолжения запрещает присоединение к документу иного типа.
I-2: одиночный месяц не задаёт границы при дате на число/квартале (not_single_month).
I-3: название строки из ближайшей текстовой ячейки левее кодов, пустое имя без confidence.
M-5: units_thousands и okud_code в словаре, без type: ignore в detect.py.
M-8: строка нумерации и нули не считаются строкой без кода с суммами.
M-11: предупреждение о дробных значениях — одно на документ.
T13.5: _upper_header_row возвращает верхнюю строку при склейке хотя бы одной колонки.
M-6/M-7/T15.1/T15.2: остатки statement_markers, описание fractional_share_percent, README, тест воркера.

Refs #14

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EAKRDNzXtRrwmWz9z6PZu3
Refs #14

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EAKRDNzXtRrwmWz9z6PZu3
aep changed title from openspec: спека Среза 2b — парсер ББ и ОФР из Excel, контракт v1.2 (на ревью) to feat(statements): парсер ББ и ОФР из Excel, контракт v1.2 (Срез 2b) 2026-10-06 21:14:13 +03:00
aep merged commit 1b9296f966 into main 2026-10-06 21:38:00 +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#16
No description provided.