AURORA-1864: группа альтернатив соотношений 2400 (§7, OQ-12, спека шага 7) #209

Merged
aep merged 1 commits from feat/3-checks-group into main 2026-11-06 21:59:40 +03:00
6 changed files with 157 additions and 7 deletions

View File

@ -828,7 +828,8 @@ one_sided = ровно одна из amount_a, amount_b равна 0 (знак
`1200 = 1210 + 1220 + 1230 + 1240 + 1250 + 1260`; `1300 = 1310 + 1320 + 1340 + 1350 + 1360 + 1370`;
`1400 = 1410 + 1420 + 1430 + 1450`; `1500 = 1510 + 1520 + 1540 + 1550`; `1600 = 1100 + 1200`; `1700 = 1300 + 1400 + 1500`.
ОФР: `2100 = 2110 − 2120`; `2200 = 2100 − 2210 − 2220`; `2300 = 2200 + 2310 + 2320 − 2330 + 2340 − 2350`;
`2400 = 2300 − 2410 + 2420` (знаки 2410/2420/2430 — по ФСБУ 4/2023 уточнить [открыто]).
`2400 = 2300 − 2410 + 2420` или `2400 = 2300 + 2410 + 2460` (знак 2410 не определяется — см. группу альтернатив ниже;
знаки 2420/2430 по ФСБУ 4/2023 — OQ-12 [открыто]).
Межформенная: `1370(отчётная дата) − 1370(начало года) = 2400(ОФР за период)` — при расхождении КА может акцептовать
с комментарием (`financial_statement_meta.checks_accepted_*`).
@ -839,9 +840,9 @@ one_sided = ровно одна из amount_a, amount_b равна 0 (знак
пересчитывает тем же кодом только после правок аналитика; своей копии словаря у ядра нет. Правила счёта:
- **Жёсткие** (нарушение → `needs_check`): ББ — `1100`, `1200` (+1215), `1300`, `1400`, `1500`, `1600 = 1100 + 1200`,
`1700 = 1300 + 1400 + 1500`, `1600 = 1700`; ОФР — `2100`, `2200`, `2300`. **Мягкие** (`info`, `ASSUMPTION(OQ-12)`): `2400 =
2300 − 2410 + 2420` и варианты ФСБУ 4/2023 (`2400 = 2300 + 2410 + 2460`, `2410 = 2411 + 2412`), `2500 = 2400 + 2510 +
2520 + 2530`, «сумма пятизначных подстрок = родитель» (по колонке — только если хотя бы одна подстрока родителя в ней
`1700 = 1300 + 1400 + 1500`, `1600 = 1700`; ОФР — `2100`, `2200`, `2300`. **Мягкие** (`info`): `2400 =
2300 − 2410 + 2420` и `2400 = 2300 + 2410 + 2460` (группа альтернатив, ниже), `2410 = 2411 + 2412`, `2500 = 2400 +
2510 + 2520 + 2530`, «сумма пятизначных подстрок = родитель» (по колонке — только если хотя бы одна подстрока родителя в ней
непуста: `amount` не `null`, ноль — значение; AURORA-1527). Мягкое соотношение на статус и подсветку не влияет, но
**сошедшееся точно** (расхождение в пределах допуска ±1, без «округления») подтверждает неуверенные значения своих
кодов (Р-21, §11.9): так покрываются 2400, 2410, 2411, 2412, 2460, 25xx и пятизначные подстроки.
@ -862,12 +863,21 @@ one_sided = ровно одна из amount_a, amount_b равна 0 (знак
с этими членами по модулю (1С выгружает расходы со знаком минус, 66н — в скобках). Такое соотношение сходится при
любом знаке члена и потому **подтверждает величину, но не знак**: знак сомнительной ячейки подтверждается конвенцией
колонки (§11.9).
- **Группа альтернатив** (`group` в `statement_checks.yaml`; AURORA-1864, решение владельца 27.10.2026). Мягкие
соотношения одной цели одной формы и варианта могут быть альтернативами: в колонке сошлась хоть одна — нарушений
группы нет; не сошлась ни одна — в `soft_relations_failed` одно нарушение, ближайшая к цели альтернатива (при пустой
цели или пустых членах — первая по словарю). `group` только у мягких и с одной целью — иначе словарь не загружается.
Группы — соотношения 2400 обоих наборов: **знак 2410 не определяется**, принимается любой вариант (расход —
`2300 − 2410`, со знаком минус, в скобках или без знака; доход по налогу ФСБУ 4/2023 — `2300 + 2410`). Жёсткие
проверки, подсветка, `needs_check` и подтверждение значений (Р-21) группой не меняются; каждая альтернатива
подтверждает свои коды, как отдельное мягкое соотношение. Формула старого бланка с 2430/2450 не добавляется.
- **Упрощённый набор.** Набор выбирается по `form_variant` документа (§11.7): у упрощённой формы нет подытогов 1100 /
1200 (ББ) и 2100 / 2200 / 2300 (ОФР), свои равенства по бланку упрощённой формы (приказ 66н, прил. 5;
`ASSUMPTION` до первого образца в fixtures): ББ — `1600 = 1150 + 1170 + 1210 + 1230 + 1250` (жёсткое), `1700 = 1300 +
1350 + 1360 + 1410 + 1450 + 1510 + 1520 + 1550` (жёсткое), `1600 = 1700` (жёсткое); ОФР — `2400 = 2110 − 2120 − 2330 +
2340 − 2350 − 2410` (**мягкое**, как `2400` полного набора: знак 2410 не определён, OQ-12; `abs_terms` те же; решение
владельца 18.10.2026, Р-22 / S-5). Оба набора — в одном словаре `statement_checks.yaml`. Без упрощённого набора полный
2340 − 2350 − 2410` и `2400 = 2110 − 2120 − 2330 + 2340 − 2350 + 2410` (**мягкие**, группа альтернатив, как `2400`
полного набора; `abs_terms` — 2120, 2330, 2350, у первого ещё 2410; решение владельца 18.10.2026, Р-22 / S-5;
вторая альтернатива — AURORA-1864). Оба набора — в одном словаре `statement_checks.yaml`. Без упрощённого набора полный
дал бы нарушения «пустой цели» на каждой упрощённой форме. `form_variant = null` (документ, оставшийся в БД с времён до
v5.19, если база не очищена) — полный набор; у результата 1.x вариант определяется по структуре кодов при приёме.
- **Родитель пятизначной подстроки** — ближайшая четырёхзначная строка выше с теми же первыми тремя цифрами, иначе код

View File

@ -17,7 +17,7 @@
| OQ-09 | Правила элиминации ОФР (2110/2120/2310/2320/2330): точный состав субсчетов, источник средневзвешенной ставки НДС, выбор субсчетов «работником ПА самостоятельно» | FNR03 | срез 6 | не реализовывать авто-элиминацию ОФР до решения; только ручные `correction` |
| OQ-10 | Гудвилл: входит ли стр. 1350 (добавочный капитал) в базу участия; УК из ББ (1310) или из ОСВ 80/83 | DBML, DOC-259025, FNR03 | срез 6 | допущение: 1310 из ББ; 1350 — настраиваемый флаг, по умолчанию выключен. **06.11:** DOC-259025 (Лысенко, 03.11) — «для УК используется 1310», 1350 в формулу не входит; так реализовано (arm-core #222), флага нет; подтверждение методологов (AURORA-1369) не получено |
| OQ-11 | Строка «ППА» в КФО (правило № 1, когда у А нет ОСВ 03) — что это и куда | FNR03 | срез 6 | не реализовывать |
| OQ-12 | Формулы ОФР: знаки 2410/2420/2430 по ФСБУ 4/2023 vs 66н; состав 1100 (1120–1140) | DOC-221281 | срез 3 | допущение: формулы §7, строки без значения = 0; **расширение 07.10.2026:** формулы и справочники по редакциям форм (`66n` / `fsbu4`) — OQ-146 |
| OQ-12 | Формулы ОФР: знаки 2410/2420/2430 по ФСБУ 4/2023 vs 66н; состав 1100 (1120–1140) | DOC-221281 | срез 3 | допущение: формулы §7, строки без значения = 0; **06.11.2026 закрыт в части 2410** (AURORA-1864, решение владельца 27.10.2026): знак 2410 не определяется, соотношения 2400 — группа альтернатив §7 (`2300 − 2410` и `2300 + 2410`); 2420/2430 и состав 1100 — открыты; **расширение 07.10.2026:** формулы и справочники по редакциям форм (`66n` / `fsbu4`) — OQ-146 |
| OQ-13 | `confidence` от ИС Сканирование — доли 0..1 или проценты 0..100; имя поля организации (`full_name` vs `form_name`) | FNR02 vs `aep_*.json` | срез 3 (scan-gateway) | **закрыт для scan-gateway (04.10.2026, по `aep_3.json`, `aep_6.json`):** `confidence` — числа 0–100 (не доли); название организации — `data_ocr.organization.form_name` (шумный OCR-текст), ИНН — `inn.form_name`, единицы — `units.form_name`, дата — `date.form_name` (в `aep_6.json` мусор); `full_name`/`inn.inn`/`units.measurement` из ТЗ в реальных файлах нет. Нормализация — Срез 3 |
| OQ-14 | `reporting_date` в JSON ИС Сканирование — «ждём обновлённый JSON» | FNR01 | срез 3 | **уточнено (04.10.2026):** отдельного поля `reporting_date` в ответе нет; `date.form_name` ненадёжен (в `aep_6.json` — «Общество с ограниченной ответственностью», в `aep_3.json` — «2\|0\|2\|4\|»); даты колонок — в строке-шапке `rows[0]` таблицы («На 30 июня 2025 г» в `aep_6.json`), в `aep_3.json` шапки нет. Допущение прежнее: парсить из шапки таблицы, при её отсутствии — `NEEDS_CHECK`; решение — Срез 3 |
| OQ-15 | Таймаут OCR 5 мин / 0 повторов (ТЗ 3) vs outbox с повторами (DBML) | DOC-037736 | срез 3 | решено DBML: `max_attempts` OCR = 1, парсер = 3 |

View File

@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-11-06

View File

@ -0,0 +1,30 @@
## Context
Решение согласовано владельцем 27.10.2026 (комментарий в AURORA-1864): мягкие соотношения одной цели объединяются в
группу альтернатив, знак 2410 не определяется. Реализация — `arm_statements/checks.py` (`checks_from`) и загрузчик
словаря (`loader.py`); RSHB/pylib_ai_arm_statements#3.
## Decisions
- Группа считается в `checks_from` по паре (колонка, `group`) среди уже посчитанных исходов; `evaluate_relations` и
исходы для шага 8 не меняются — поэтому подсветка и Р-21 остаются прежними (каждая альтернатива подтверждает
значения сама, как раньше).
- «Сошлась» — расхождение в пределах допуска ±1 (`within_tolerance`), как для мягкого соотношения без группы.
- Проверки «`group` только у мягкого» и «у группы одна цель» — в загрузчике: жёсткая группа означала бы, что статус документа зависит от
выбора альтернативы, а этого решение не предусматривает.
## Decisions made without discussion
| Дата | Решение | Обоснование | Цена ошибки |
|---|---|---|---|
| 2026-11-06 | Имя группы в словаре — `net_profit` для обоих наборов | Группа — по форме и варианту (`relations_for`), одно имя не смешивает полный и упрощённый наборы; имя описывает цель 2400 | Нулевая: имя только в словаре, наружу не выходит |
| 2026-11-06 | Если у всех несошедшихся альтернатив пуста цель или все члены (сравнить не с чем) — выдаётся первая по словарю | Расхождения нет, «ближайшую» выбрать не по чему; порядок словаря детерминирован | Низкая: текст нарушения другой альтернативы, сам факт нарушения тот же |
| 2026-11-06 | При равном расхождении выдаётся первая по словарю | Детерминированность | Нулевая |
| 2026-11-06 | Тест `test_simplified_income_soft` (2400 = 500 при 1000 − 600 ± 50) теперь ожидает нарушение новой альтернативы `… + 2410` — она ближе к цели (450 против 350) | Прямое следствие правила «ближайшая к цели» | Нулевая: данные теста неверны в обоих вариантах |
## Risks / Trade-offs
- Новая альтернатива упрощённого набора (`… + 2410`) при совпадении подтверждает неуверенные значения своих кодов
(Р-21), включая положительный 2410 — это и есть желаемое поведение для дохода по налогу.
- Документы, загруженные до выкладки 0.1.4, сохраняют прежние `checks` до пересчёта (правка аналитика) — ложное
предупреждение у них останется; переразбор не планируется.

View File

@ -0,0 +1,34 @@
## Why
Замечание тестировщика заказчика 23.10.2026 (AURORA-1864, ООО «Фавор плюс», ООО «Фактор»): у ОФР с положительной строкой
2410 «Налог на прибыль» (доход по налогу, ФСБУ 4/2023) появляется мягкое нарушение «2400 = 2300 − 2410 + 2420», хотя
форма верна (2400 = 2300 + 2410). 2410 — член `abs_terms`: правая часть считается и как записано, и с |2410|, но оба
варианта вычитают 2410. Второе соотношение «2400 = 2300 + 2410 + 2460» на таких данных сходится, а первое всё равно
выдаёт предупреждение. Аналитик видит «некорректную проверку».
## What Changes
- Словарь `statement_checks.yaml` (библиотека `pylib_ai_arm_statements` 0.1.4, RSHB/pylib_ai_arm_statements#3):
необязательный ключ `group` у мягких соотношений — группа альтернатив одной цели. В колонке сошлась хоть одна —
нарушений группы нет; не сошлась ни одна — одно нарушение, ближайшая к цели. `group` у жёсткого — ошибка загрузки.
- Соотношения 2400 ОФР — одна группа в полном наборе (`2400 = 2300 − 2410 + 2420`, `2400 = 2300 + 2410 + 2460`) и в
упрощённом (существующее + новое `2400 = 2110 − 2120 − 2330 + 2340 − 2350 + 2410`).
- Документы контекста: `05-domain-rules.md` §7 (правило группы, знак 2410 не определяется), `07-open-questions.md`
OQ-12 — закрыт в части знака 2410.
- Контракт `recognition-result` не меняется: формат `soft_relations_failed` прежний, меняется только состав нарушений.
Подъём версии библиотеки до 0.1.4 в arm-core, tabular-parser, scan-gateway — отдельными PR после merge AURORA-1677
(переезд на библиотеку; merge придержан владельцем до выкатки гудвилла).
## Non-goals
- Жёсткие проверки, подсветка, `needs_check`, подтверждение значений шагом 8 (Р-21) — без изменений.
- Формула старого бланка с 2430/2450 не добавляется.
- Словари по редакциям 66н / ФСБУ 4/2023 (OQ-146, OQ-150, AURORA-1554) — отдельная задача.
- Переразбор уже загруженных документов: новые проверки применяются к новым загрузкам и к пересчёту после правок.
## Impact
- Спека `statement-normalization` — требование «Шаг 7 — самопроверки §7».
- Репозитории: pylib_ai_arm_statements (код и словарь), arm-ka-docs (этот change); подъём пина в arm-core,
arm-tabular-parser, arm-scan-gateway — после AURORA-1677.

View File

@ -0,0 +1,74 @@
## MODIFIED Requirements
### Requirement: Шаг 7 — самопроверки §7
Шаг 7 SHALL считаться у обоих источников одним словарём `statement_checks.yaml` и выдавать `StatementChecks
{relations_failed[], soft_relations_failed[]}`; каждое нарушение — `{column_index, relation, codes, expected,
actual}`, где `codes` — коды цели и членов соотношения. Правила:
- значение кода в колонке — сумма по всем строкам `ok` с этим кодом; строки `detail`, `unreadable`, `missing` в
соотношения не входят; нарушение относится ко всем строкам его кодов;
- соотношение **посчитано**, если непуста цель или хотя бы один член (есть строка `ok` с кодом и `amount` не `null`);
пусто всё — соотношение пропускается; пустая цель при непустых членах и непустая цель при пустых членах — нарушение;
- жёсткое соотношение не сошлось, если расхождение больше допуска ±1 в единицах формы **и** больше 0,001 % наибольшего
по модулю числа соотношения — тогда оно в `relations_failed`; расхождение в пределах округления и мягкие
соотношения — в `soft_relations_failed`;
- члены `abs_terms` (2120, 2210, 2220, 2330, 2350, 2410) сравниваются и как записаны, и по модулю; такое соотношение
подтверждает величину, но не знак (шаг 8);
- набор соотношений — по `form_variant` (полный или упрощённый); `form_variant = null` — полный. В упрощённом наборе
соотношения ББ жёсткие, а `2400 = 2110 − 2120 − 2330 + 2340 − 2350 − 2410` и `2400 = 2110 − 2120 − 2330 + 2340 −
2350 + 2410` ОФР — мягкие, как `2400` полного набора;
- **группа альтернатив** (`group` в словаре, только у мягких соотношений одной формы и варианта): в колонке сошлась
хоть одна альтернатива — ни одна не попадает в `soft_relations_failed`; не сошлась ни одна — в
`soft_relations_failed` одно нарушение, ближайшая к цели альтернатива (меньшее расхождение; при пустой цели или пустых
членах — первая по словарю). `group` у жёсткого соотношения и разные цели в одной группе — ошибка загрузки словаря. Соотношения 2400 каждого
набора — одна группа: полный — `2400 = 2300 − 2410 + 2420` и `2400 = 2300 + 2410 + 2460`, упрощённый — два варианта
выше. Знак 2410 (расход или доход по налогу, ФСБУ 4/2023) не определяется — принимается любая альтернатива (OQ-12).
Группа не меняет жёстких проверок, подсветки, `needs_check` и подтверждения значений (шаг 8, Р-21);
- родитель пятизначной подстроки — ближайшая четырёхзначная строка выше с теми же первыми тремя цифрами, иначе код из
первых четырёх цифр; «сумма подстрок = родитель» (мягкое) — только если хотя бы одна подстрока в колонке непуста.
`checks` SHALL быть у каждого `BALANCE` / `INCOME` со строками и отсутствовать у документа без строк.
`duplicate_line_codes` MUST NOT выдаваться.
#### Scenario: «БАЛАНС» без кода
- **WHEN** строка «БАЛАНС» ушла в `detail` (код потерян), в колонке есть 1100 и 1200
- **THEN** соотношение `1600 = 1100 + 1200` посчитано и нарушено (пустая цель при непустых членах), в
`relations_failed`
#### Scenario: Лист только с активом
- **WHEN** в ББ заполнены 1100, 1200, 1600, а 1300–1700 отсутствуют
- **THEN** `1600 = 1700` нарушено (непустая цель при пустых членах), документ `needs_check`
#### Scenario: Повтор кода в соотношении
- **WHEN** две строки 2410 с суммами 100 и 649
- **THEN** в соотношениях код 2410 равен 749
#### Scenario: Упрощённый ОФР с доходом по налогу
- **WHEN** у упрощённого ОФР 2410 записан со знаком дохода, 2400 с ним сходится только по `2400 = 2110 − 2120 − 2330 +
2340 − 2350 + 2410`
- **THEN** нарушений по 2400 в `soft_relations_failed` нет
#### Scenario: Доход по налогу в полной форме (AURORA-1864)
- **WHEN** в колонке ОФР 2300 = 100, 2410 = 20 (без минуса и скобок), 2400 = 120
- **THEN** `2400 = 2300 − 2410 + 2420` не сошлось, но сошлось `2400 = 2300 + 2410 + 2460` из той же группы — нарушений
по 2400 в `soft_relations_failed` нет
#### Scenario: Расход по налогу в полной форме
- **WHEN** 2300 = 100, 2410 = −20 или (20) или 20, 2400 = 80
- **THEN** сходится `2400 = 2300 − 2410 + 2420` — нарушений по 2400 в `soft_relations_failed` нет
#### Scenario: Неверная чистая прибыль — одно нарушение
- **WHEN** 2300 = 100, 2410 = 20, 2400 = 150 — не сходится ни одна альтернатива группы
- **THEN** в `soft_relations_failed` одно нарушение по 2400 — `2400 = 2300 + 2410 + 2460` (`actual` 120 ближе к 150,
чем 80); документ из-за него не `needs_check`
#### Scenario: Группа считается по колонке
- **WHEN** в первой колонке 2400 сходится с одной из альтернатив, во второй — ни с одной
- **THEN** нарушение по 2400 одно и только у второй колонки
#### Scenario: Группа у жёсткого соотношения
- **WHEN** в `statement_checks.yaml` у соотношения со `strict: true` указан `group`
- **THEN** словарь не загружается (ошибка загрузки `statement_checks.yaml`)
#### Scenario: Округление итогов
- **WHEN** `1600 = 1700` расходится на 9,02 при итогах ~17 млрд
- **THEN** нарушение в `soft_relations_failed`, на статус и подсветку не влияет