docs(#116): Р-7 решено — §7 подтверждает и догадки из грязного текста; все решения приняты, раздел решений без обсуждения

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Andrey Epifancev 2026-10-17 19:14:19 +04:00
parent bcb6b0b527
commit d2572d2a6b

View File

@ -1,7 +1,7 @@
# Единый алгоритм нормализации ББ/ОФР (scan-gateway и tabular-parser) — дизайн
Issue: arm-ka-docs#116. Статус: черновик; текущая цепочка описана, целевая картина по шагам 1–9 — предложение, ждёт
решения владельца Р-7; Р-1…Р-6 решены (brainstorming 17.10.2026).
Issue: arm-ka-docs#116. Статус: целевая картина по шагам 1–9 согласована с владельцем (решения Р-1…Р-7, 17.10.2026);
следующий шаг — спека (дельты OpenSpec, контракт v1.3, §11/§12 в `05-domain-rules.md`, DBML v5.19).
## Цель
@ -316,9 +316,8 @@ sheet:<A>,<B>`. `DISCLOSURE` и форма без колонки кодов —
## Целевая картина
Каждый шаг ниже: **вход = выход предыдущего шага**, единый выход для обоих сервисов, таблица «различие → к чему
приводим → что меняется в scan-gateway → что меняется в tabular-parser». Решения владельца помечены датой; остальное —
предложение (17.10.2026), решения, которые нужны от владельца, собраны в конце (Р-1…Р-7). Имена полей — рабочие,
уточняются при написании спеки.
приводим → что меняется в scan-gateway → что меняется в tabular-parser». Решения владельца помечены датой; сводка решений
Р-1…Р-7 — в конце (все приняты 17.10.2026). Имена полей — рабочие, уточняются при написании спеки.
Принципы, из которых выведены решения по строкам:
@ -539,9 +538,9 @@ column_index?}`, а не строка.
**Подтверждение проверкой (вопрос владельца 17.10.2026).** Проверка §7 — арбитр, уверенность — подсказка там, где
проверки нет. По каждому значению сервис считает `needs_review`:
- `true`, если `confidence` ниже порога (Р-5: 100) **и** значение не покрыто сошедшимся жёстким соотношением §7 в своей
колонке (не входит ни в одно, соотношение не сошлось или оно мягкое); для `is_recognized = false` — то же правило,
если Р-7 = да, иначе всегда `true`;
- `true`, если `confidence` ниже порога (Р-5: 100) или `is_recognized = false` (число собрано из грязного текста,
Р-7) **и** значение не покрыто сошедшимся жёстким соотношением §7 в своей колонке (не входит ни в одно, соотношение
не сошлось или оно мягкое);
- `true` у всех ячеек соотношения в колонке, где оно не сошлось, независимо от уверенности;
- иначе `false`: значение подтверждено проверкой, не подсвечивается и статус не трогает; сырой текст и уверенность
остаются в подсказке ячейки.
@ -550,7 +549,9 @@ column_index?}`, а не строка.
кодом. Не покрыто проверками и остаётся на уверенности: поля шапки, справочные строки ОФР 25xx / 29xx, детализация
без проверки родителя, `DISCLOSURE`, колонки, где есть только мягкие соотношения. Риск — две взаимно компенсирующие
ошибки в одном соотношении; принимается (перекрёстные соотношения баланса его снижают). Закрывает AURORA-1524 без
ущерба для 1519. Распространение на `is_recognized = false` — Р-7.
ущерба для 1519. Сошедшееся жёсткое равенство подтверждает и догадку из грязного текста (Р-7, решение владельца
17.10.2026): «(7744536}» → −7 744 536 при 2100 = 2110 − 2120 верна; случайное совпадение требует второй,
компенсирующей ошибки в том же равенстве.
**Код и наименование строки (Р-5, решение владельца 17.10.2026).** Уверенность кода подтверждается не §7 (перепутанные
соседи 1220 и 1230 дают ту же сумму раздела), а структурой: код есть в перечне кодов формы и стоит по возрастанию
@ -589,7 +590,7 @@ column_index?}`, а не строка.
делать при расхождении (владелец 17.10.2026: «наверное, будем пытаться сопоставить»). В сервисах уверенность и
текст наименования на статус не влияют.
### Решения, которые нужны от владельца
### Решения владельца (Р-1…Р-7, 17.10.2026)
- **Р-1** (шаг 1, п. 2) — **решено 17.10.2026: копия по скрипту.** Платформа не собирает Python-пакеты и не кладёт их
в свой Nexus, поэтому общий код — dataclass-ы шага 1 (сериализуемые в json, golden-файлы в fixtures), шаги 2–8 и
@ -619,6 +620,30 @@ column_index?}`, а не строка.
документе без даты с предупреждением `error` (`needs_check`, подтверждение руками); пропуск отвергнут как тихая
потеря периода. Относительные подписи бланка 66н («На отчётную дату», «На 31 декабря предыдущего года», …)
добавляются в словарь периодов и считаются от даты отчёта.
- **Р-7** (шаг 8, «Подтверждение проверкой») — снимать ли подсветку сошедшимся соотношением §7 и с `is_recognized =
false` (число собрано из грязного текста), а не только с низкой уверенности; предложение — да: сошедшаяся проверка
сильнее догадки о мусоре.
- **Р-7** (шаг 8, «Подтверждение проверкой») — **решено владельцем 17.10.2026: да.** Сошедшееся жёсткое соотношение §7
снимает подсветку и с `is_recognized = false`; такой документ может получить `done` и автоподтвердиться, сырой
текст остаётся в подсказке ячейки. Варианты «всегда подсвечивать» и «снимать подсветку, но не автоподтверждать»
отвергнуты: первый возвращает ложные подсветки AURORA-1524, второй даёт статус «требует проверки» без подсветок.
## Decisions made without discussion
Решения агента 17.10.2026, принятые при оформлении целевой картины без отдельного обсуждения с владельцем; все
обратимы правкой спеки или словаря.
1. **Уровни предупреждений** (шаг 8, п. 2): `error` — то, что меняет данные или их полноту (нет строки заголовка,
колонка без даты, тип по кодам противоречит заголовку, колонки сегмента не совпали); `info` — остальное (пропущена
подпись из словаря исключений, дробные при «тыс. руб.»). Цена ошибки: лишний или пропущенный `needs_check`,
правится таблицей уровней в спеке.
2. **`DISCLOSURE` всегда `done`** без условий о раскладке, строках и проверках — сохранено текущее поведение парсера.
Цена: пояснения не проверяются; так и сейчас.
3. **Порог столбца кодов** — «кодов ≥ 3 и доля среди непустых ≥ порога» взят у парсера как есть; `relaxed` для одиноких
продолжений снят, потому что продолжения склеиваются в шаге 1. Цена: таблица с одним-двумя кодами без столбца кодов
→ документ без строк с `needs_check`.
4. **Начальный словарь исключений подписей** («Изменение», «Отклонение», «%», «Темп», «Доля», «Примечание») — по тестам
парсера; пополняется словарём, не кодом.
5. **Грамматика `locator`** — пары `ключ:значение` через `;`, ключи по источнику. Цена: минимальная, формат уже такой.
6. **`value`, который не число** (дата, логическое) в колонке сумм — разбор как текст. Цена: минимальная.
7. **`checks` отсутствует у документа без строк**, обязателен у `BALANCE` / `INCOME` со строками.
8. **Рабочие имена** `FormCandidate`, `TableLayout`, `RawLine`, `needs_review`, `line_status`, `line_code_text`,
`arm-statements`, `api/src/arm_statements/`, `sync-statements` — по образцу существующих (`sync-web.sh`); меняются
при написании спеки без последствий.