I-1: _find_total сначала берёт первую строку корневого уровня с текстом ровно «Итого»
(новый ключ total_row_exact в osv_headers.yaml) и лишь без неё — первую по total_row.
Контрагент «Итого-Сервис» на плоском листе без outline и отступов больше не обрезает таблицу.
O-3: предупреждение о хвосте считает числа только в колонках таблицы (text_col…right_edge
из TableHeader); контрольные суммы правее таблицы (rb/2024-Q1) его не дают, ослабление
в test_classify_real откачено. Синтетика s32: итог «Итого по счету 60» без точного «Итого»
(нужна тесту покрытия для запасного паттерна total_row).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
AURORA-1663: словарь строк data_types.yaml — «Кол-во» даёт QUANTITY, «Вал» без
точки больше не CURRENCY (материал «Вал» на счёте 10); метка — «Вал.» и код
валюты.
AURORA-1664: _find_total берёт первую «Итого» на корневом уровне оформления
(раньше — последнюю), вторая итоговая строка сразу за ней по-прежнему часть
таблицы; всё ниже вне документа. Числа в хвосте дают предупреждение «ниже
таблицы (после «Итого») есть числа» без смены статуса. Закрывает tp#7 M-2.
Предупреждение появляется и у реальной фикстуры rb/2024-Q1 (контрольные суммы
правее таблицы под «Итого») — тест property допускает его.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
В BIFF5/7 без CODEPAGE xlrd декодировал байтовые строки как latin-1: кириллица
превращалась в мусор, лист ОСВ не находился (INVALID_DOCUMENT). Теперь такая
книга читается с encoding_override=cp1251 и получает предупреждение уровня книги
«xls без кодовой страницы — строки прочитаны как cp1251». Книги с CODEPAGE и
BIFF8 читаются как прежде. Проба CODEPAGE — on_demand-открытие (только globals).
Для теста добавлен минимальный писатель BIFF5 в контейнере OLE2
(tests/synthetic/xls_writer.py), умеющий не писать CODEPAGE.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
По колонке соотношение считается, только если хотя бы одна подстрока родителя имеет значение
(amount не null; ноль — значение). Совпадает с arm-core.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
statement_money вместо to_money в разборе строк форм, предупреждения о неразобранном формате и об xlsb,
сравнение условий формата с точностью Excel (15 значащих цифр), тесты и тексты.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Хвосты ревью Task 3: формулировка направления листа в spec/design (T3.1), тесты противоречия сведений и приоритета подсказки (T3.2), assert на glue.ok (T3.4).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Строки ИНН не в дереве: с суммами — сосед с теми же суммами (совпали оба — по направлению);
без сумм — сосед по направлению листа: подсказка шапки, иначе единогласные сведения пар по
суммам и однозначных блоков детей. Противоречие или отсутствие сведений — строка без пары.
Хвосты ревью Task 2: тест подразделения переписан на итоговый результат (T2.9); в спеке
уточнены реквизит «нерез.» (только лист, design #14) и защита «над, в дереве» с подсказкой
шапки (design #16) (T2.10); опечатка в докстринге _parent_can_own (T2.11).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Модуль inn_rows: строка с одним ИНН сопоставляется с наименованием в дереве (родитель или ребёнок), без пары
остаётся с причиной; подсказка шапки InnHint отменяет контрольную сумму. row_data_type стал публичным.
ASCII-проверка ИНН (ревью T1.2), комментарий про zip(strict=False) (T1.3), тест «770123456²» (T1.1).
Решения 12–13 в design.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- NATSSettings: subject'ы запроса и ответа из окружения (имена контракта по умолчанию), проверка формата и попарного
различия; NATS_SEED и NATS_JWT — SecretStr; request_subjects() для request_subject(pipeline, subjects).
- hide_input_in_errors во всех классах настроек: ошибка «нет поля» не печатает вход группы с JWT и seed.
- build_nats_auth читает секреты через get_secret_value().
- Схемы контракта скопированы из docs/contracts (request, result-message).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Строка блока заголовка «Контрагенты.ИНН» под «Контрагенты» — тот же реквизит,
что элемент списка субконто варианта 2: в group_schema не попадает, у владельца
has_inn, строки склеиваются glue_inn_attributes. Общая часть вариантов —
_attach_inn_attribute и _positions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
В шапке варианта 2 «субконто: Контрагенты, Контрагенты.ИНН» 1С выводит ИНН
отдельной строкой на уровень глубже контрагента. Парсер принимал реквизит за
второй уровень контрагентов: строка ИНН становилась контрагентом с именем
«2370012036.0» и без ИНН, у наименования ИНН тоже не было, в свод ядра
попадали обе строки.
- header: элемент «<группировка>.ИНН» — InnAttribute, в group_schema не
попадает, у владельца has_inn = true; GroupSchema.positions держит позицию
для классификатора;
- classify: строка реквизита — OTHER с ИНН ячейки (column_inn, R-24);
glue_inn_attributes отдаёт ИНН контрагенту, убирает строку, поднимает её
детей; не склеилось (несколько строк, суммы не равны, ИНН не распознан или
расходится) — OTHER, предупреждение, needs_check; пустая ячейка (физлицо) —
склейка без ИНН (R-1);
- readers: целый float из xls читается как int — без «.0».
Файл банка: 713 из 716 контрагентов с ИНН, 3 физлица без ИНН, status done.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
У 91 и 99 строки аналитики несут только обороты, сальдо закрыто на субсчёт закрытия
(91.09), поэтому каждая ОСВ 91 получала needs_check. Список счетов — данные
api/rules/osv_checks.yaml (accounts_without_analytic_balance: 91, 99; 90 не входит).
- тождество строки на таких счетах не проверяется;
- «сумма детей = родитель» сохраняется: обороты всегда, сальдо — только у родителя
с дочерними субсчетами (корень -> субсчета); у родителя с одной аналитикой сальдо
не сверяется;
- «Итого» сверяется как обычно;
- строка относится к счёту списка по коду ближайшего счёта ветки (91, 91.01; не 910).
Тесты: unit checks/rules, манифест osv_dkb_expectations (две ОСВ 91 теперь done).
README, CLAUDE.md, openspec/specs/osv-parsing, api/rules/README.md обновлены.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
Тот же источник настроек, что в arm-core#44: приоритет обычный env -> OPENBAO__APP__* -> .env -> умолчание;
неизвестное имя — ошибка при старте; ключ APP не ломает OpenBAOSettings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EAKRDNzXtRrwmWz9z6PZu3
- OQ-138 (решение владельца 06.10.2026): единицы шапки верны; жёсткое расхождение до rounding_tolerance_percent = 0,001 %
от наибольшего по модулю числа соотношения — округление итогов: soft_relations_failed + предупреждение, статус не
меняется. НПЗ, ОФР стр. 1 Унагранде Компани и Групп теперь done.
- N-1/N-2: лист с 1–2 кодами — продолжение только сразу после листа формы, коды из диапазона формы открытого документа;
присоединение видно в предупреждениях. N-3: негативные тесты BookParser и StatementParser.
- M-9: пятизначная подстрока относится к ближайшей четырёхзначной строке выше с теми же тремя цифрами (12310 под 1230).
- N-4: на продолжении без шапки колонка «Пояснения» узнаётся по коротким значениям и не даёт line_name.
- T7.1: ответ с ошибкой листа ОСВ называет неразобранные листы форм; T7.2: metrics.rows для форм — в спеке.
make check-full: 2217 passed, интеграция 10 passed; golden 138/138 (снимки — arm-ka-fixtures fix/20-golden).
Refs #20
Co-Authored-By: Claude Opus 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
Номер 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
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
Манифест 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
Генератор st02: значения ST02_VALUES сходятся по всем жёстким соотношениям. _upper_header_row: верхняя строка берётся,
только если подпись склеивается с датой в период. Refs #14
Co-Authored-By: Claude Sonnet <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
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
Перенесено 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
Добавлен тест, проверяющий, что ИНН аудитора НИКОГДА не берётся, даже когда
аудиторский блок расположен РАНЬШЕ (выше) строк с ИНН организации.
Лист:
- Строка 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