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) — дизайн # Единый алгоритм нормализации ББ/ОФР (scan-gateway и tabular-parser) — дизайн
Issue: arm-ka-docs#116. Статус: черновик; текущая цепочка описана, целевая картина по шагам 1–9 — предложение, ждёт Issue: arm-ka-docs#116. Статус: целевая картина по шагам 1–9 согласована с владельцем (решения Р-1…Р-7, 17.10.2026);
решения владельца Р-7; Р-1…Р-6 решены (brainstorming 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». Решения владельца помечены датой; остальное — приводим → что меняется в scan-gateway → что меняется в tabular-parser». Решения владельца помечены датой; сводка решений
предложение (17.10.2026), решения, которые нужны от владельца, собраны в конце (Р-1…Р-7). Имена полей — рабочие, Р-1…Р-7 — в конце (все приняты 17.10.2026). Имена полей — рабочие, уточняются при написании спеки.
уточняются при написании спеки.
Принципы, из которых выведены решения по строкам: Принципы, из которых выведены решения по строкам:
@ -539,9 +538,9 @@ column_index?}`, а не строка.
**Подтверждение проверкой (вопрос владельца 17.10.2026).** Проверка §7 — арбитр, уверенность — подсказка там, где **Подтверждение проверкой (вопрос владельца 17.10.2026).** Проверка §7 — арбитр, уверенность — подсказка там, где
проверки нет. По каждому значению сервис считает `needs_review`: проверки нет. По каждому значению сервис считает `needs_review`:
- `true`, если `confidence` ниже порога (Р-5: 100) **и** значение не покрыто сошедшимся жёстким соотношением §7 в своей - `true`, если `confidence` ниже порога (Р-5: 100) или `is_recognized = false` (число собрано из грязного текста,
колонке (не входит ни в одно, соотношение не сошлось или оно мягкое); для `is_recognized = false` — то же правило, Р-7) **и** значение не покрыто сошедшимся жёстким соотношением §7 в своей колонке (не входит ни в одно, соотношение
если Р-7 = да, иначе всегда `true`; не сошлось или оно мягкое);
- `true` у всех ячеек соотношения в колонке, где оно не сошлось, независимо от уверенности; - `true` у всех ячеек соотношения в колонке, где оно не сошлось, независимо от уверенности;
- иначе `false`: значение подтверждено проверкой, не подсвечивается и статус не трогает; сырой текст и уверенность - иначе `false`: значение подтверждено проверкой, не подсвечивается и статус не трогает; сырой текст и уверенность
остаются в подсказке ячейки. остаются в подсказке ячейки.
@ -550,7 +549,9 @@ column_index?}`, а не строка.
кодом. Не покрыто проверками и остаётся на уверенности: поля шапки, справочные строки ОФР 25xx / 29xx, детализация кодом. Не покрыто проверками и остаётся на уверенности: поля шапки, справочные строки ОФР 25xx / 29xx, детализация
без проверки родителя, `DISCLOSURE`, колонки, где есть только мягкие соотношения. Риск — две взаимно компенсирующие без проверки родителя, `DISCLOSURE`, колонки, где есть только мягкие соотношения. Риск — две взаимно компенсирующие
ошибки в одном соотношении; принимается (перекрёстные соотношения баланса его снижают). Закрывает AURORA-1524 без ошибки в одном соотношении; принимается (перекрёстные соотношения баланса его снижают). Закрывает AURORA-1524 без
ущерба для 1519. Распространение на `is_recognized = false` — Р-7. ущерба для 1519. Сошедшееся жёсткое равенство подтверждает и догадку из грязного текста (Р-7, решение владельца
17.10.2026): «(7744536}» → −7 744 536 при 2100 = 2110 − 2120 верна; случайное совпадение требует второй,
компенсирующей ошибки в том же равенстве.
**Код и наименование строки (Р-5, решение владельца 17.10.2026).** Уверенность кода подтверждается не §7 (перепутанные **Код и наименование строки (Р-5, решение владельца 17.10.2026).** Уверенность кода подтверждается не §7 (перепутанные
соседи 1220 и 1230 дают ту же сумму раздела), а структурой: код есть в перечне кодов формы и стоит по возрастанию соседи 1220 и 1230 дают ту же сумму раздела), а структурой: код есть в перечне кодов формы и стоит по возрастанию
@ -589,7 +590,7 @@ column_index?}`, а не строка.
делать при расхождении (владелец 17.10.2026: «наверное, будем пытаться сопоставить»). В сервисах уверенность и делать при расхождении (владелец 17.10.2026: «наверное, будем пытаться сопоставить»). В сервисах уверенность и
текст наименования на статус не влияют. текст наименования на статус не влияют.
### Решения, которые нужны от владельца ### Решения владельца (Р-1…Р-7, 17.10.2026)
- **Р-1** (шаг 1, п. 2) — **решено 17.10.2026: копия по скрипту.** Платформа не собирает Python-пакеты и не кладёт их - **Р-1** (шаг 1, п. 2) — **решено 17.10.2026: копия по скрипту.** Платформа не собирает Python-пакеты и не кладёт их
в свой Nexus, поэтому общий код — dataclass-ы шага 1 (сериализуемые в json, golden-файлы в fixtures), шаги 2–8 и в свой Nexus, поэтому общий код — dataclass-ы шага 1 (сериализуемые в json, golden-файлы в fixtures), шаги 2–8 и
@ -619,6 +620,30 @@ column_index?}`, а не строка.
документе без даты с предупреждением `error` (`needs_check`, подтверждение руками); пропуск отвергнут как тихая документе без даты с предупреждением `error` (`needs_check`, подтверждение руками); пропуск отвергнут как тихая
потеря периода. Относительные подписи бланка 66н («На отчётную дату», «На 31 декабря предыдущего года», …) потеря периода. Относительные подписи бланка 66н («На отчётную дату», «На 31 декабря предыдущего года», …)
добавляются в словарь периодов и считаются от даты отчёта. добавляются в словарь периодов и считаются от даты отчёта.
- **Р-7** (шаг 8, «Подтверждение проверкой») — снимать ли подсветку сошедшимся соотношением §7 и с `is_recognized = - **Р-7** (шаг 8, «Подтверждение проверкой») — **решено владельцем 17.10.2026: да.** Сошедшееся жёсткое соотношение §7
false` (число собрано из грязного текста), а не только с низкой уверенности; предложение — да: сошедшаяся проверка снимает подсветку и с `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`); меняются
при написании спеки без последствий.