From 5b3486878433947285c55bbc3552ce7c807bf804 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Tue, 6 Oct 2026 21:58:24 +0400 Subject: [PATCH] =?UTF-8?q?docs(2b):=20OQ-143=20=D1=80=D0=B5=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=BE,=20st07,=20=D1=82?= =?UTF-8?q?=D0=B5=D0=BA=D1=81=D1=82=20=D0=BF=D1=80=D0=BE=D0=BF=D1=83=D1=81?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BB=D0=B8=D1=81=D1=82=D0=BE=D0=B2,=20tasks.md?= =?UTF-8?q?=20=D0=BF=D0=BE=20=D1=84=D0=B0=D0=BA=D1=82=D1=83=20(O-9,=20M-2,?= =?UTF-8?q?=20M-4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs #26 Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01EAKRDNzXtRrwmWz9z6PZu3 --- context/05-domain-rules.md | 8 ++++---- context/06-test-data.md | 5 +++-- context/07-open-questions.md | 2 +- context/09-delivery-plan.md | 7 +++---- dev/qa-guide.md | 2 +- .../changes/slice-2b-statement-parser/tasks.md | 14 +++++++------- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/context/05-domain-rules.md b/context/05-domain-rules.md index f825e68..a7941d0 100644 --- a/context/05-domain-rules.md +++ b/context/05-domain-rules.md @@ -241,8 +241,8 @@ result-osv-needs-check.json`. | `error` / `RECOGNITION_FAILED` | непредвиденное исключение; одна строка `Тип: сообщение`, стек — в лог ERROR | Формат определяется по сигнатуре байтов (zip → XLSX, либо XLSB при наличии `xl/workbook.bin`; OLE2 → XLS), а не по -`file_type` запроса; несовпадение — предупреждение. Листы форм ББ/ОФР (§12 п. 1) и листы без признаков ОСВ пропускаются с -предупреждением (`sheet=<имя> skipped: statement (slice 2b)` / `skipped: нет признаков ОСВ`). Другие предупреждения: +`file_type` запроса; несовпадение — предупреждение. Листы без признаков ОСВ и форм пропускаются с +предупреждением (`sheet=<имя> skipped: нет признаков ОСВ или формы`; листы форм теперь разбираются, §12). Другие предупреждения: `sheet=<имя> hierarchy=<стратегия>` (всегда), свёрнутое сальдо, нераспознанное число (с номером строки), не найденное поле шапки, «нет строк данных». xlsb не содержит outline level — каскад начинается с отступа (предупреждение «xlsb: outline level недоступен»). @@ -893,8 +893,8 @@ OQ-92 (пустые «Организация»/«Группа компаний» ОСВ в порядке листов, затем формы. Шаблоны (коды есть, сумм нет, шапки нет) — `needs_check`. 11. **Отложено**: запасной путь по именам строк (OQ-139), нормализация единиц (OQ-138), признак продолжения в контракте и склейка страниц из разных файлов в ядре (OQ-140, Срез 3), строки без кода (OQ-141), образцы ФСБУ (OQ-142), лист - продолжения с единственной кодовой строкой (OQ-143: лист ОФР НПЗ с одной строкой 2400 не распознаётся как форма и - теряется, `min_codes` = 3). + продолжения с единственной кодовой строкой (OQ-143 реализовано: после листа формы хватает одного кода, + `min_codes_continuation` = 1; первая страница по-прежнему требует `min_codes` = 3). Что это даёт ядру: один маппинг `statementDocument → document + financial_statement_*` для PDF и Excel (маппинг форм — Срез 3); экран «Проверка распознавания» для Excel-источника показывает не страницы, а таблицу — UI-решение вне парсера. diff --git a/context/06-test-data.md b/context/06-test-data.md index 2226cf2..04fce8e 100644 --- a/context/06-test-data.md +++ b/context/06-test-data.md @@ -156,7 +156,7 @@ arm-tabular-parser#11, OQ-131…OQ-135. ИНН организаций в шап | Раскладка | Где | Особенности | |---|---|---| | 1С-xls постранично | `unagrande-co/2024-FY/`, `unagrande-group/{2024-FY,2025-Q3}/` | один файл = одна страница формы; на странице 1 титул (организация, ИНН, ОКПО, единица «в тыс. рублей», ОКЕИ, аудитор со **своим** ИНН), на странице 2 только «Форма 0710001 с.2»; пятизначные подстроки (11101…), значения в рублях с копейками при «тыс. руб.»; страниц 1 ББ в пакете нет (только актив) и ОФР Групп 2024 — только стр. 2 | -| Многолистовая xlsx ФСБУ 4/2023 | `npz/2025-Q3/` | ББ на 5 листах, ОФР на 3; заголовок формы после титула; листы 2–5 без заголовка и маркера; строка 1105 «Гудвил», подстроки 12301…, строка без кода с суммами; лист ОФР с одной строкой 2400 (OQ-143) | +| Многолистовая xlsx ФСБУ 4/2023 | `npz/2025-Q3/` | ББ на 5 листах, ОФР на 3 (третий — одна строка 2400, присоединяется как продолжение); заголовок формы после титула; листы 2–5 без заголовка и маркера; строка 1105 «Гудвил», подстроки 12301…, строка без кода с суммами; лист ОФР с одной строкой 2400 (OQ-143) | | `TDSheet` 66н | `mezheninovskaya/2025-Q3/` | вся форма на одном листе, дата тройкой «30 \| 9 \| 2025» числами, двухстрочные заголовки, строка нумерации колонок, значения — тысячи с дробной частью | | Шаблоны | `templates/` | 66н и ФСБУ 4/2023: коды есть, сумм и шапки нет; заголовок на две строки; в шаблоне ФСБУ «АКТИВ» и код 1110 в одной строке (OQ-142) | @@ -171,7 +171,7 @@ arm-tabular-parser#11, OQ-131…OQ-135. ИНН организаций в шап коммит в `fixtures`. Оракулы корректности — манифест и property-тест `tests/fixtures/test_statements_property.py` (манифест покрывает каждый файл; тип, статус и видимая причина `needs_check` каждого документа совпадают с ожиданиями). -**Синтетика** `fixtures/statements-xlsx/synthetic/st01…st06` (генератор `tabular-parser/api/tests/synthetic/generate_statements.py`, +**Синтетика** `fixtures/statements-xlsx/synthetic/st01…st07` (генератор `tabular-parser/api/tests/synthetic/generate_statements.py`, ожидания — `tests/synthetic/test_statement_synthetic_files.py`, описание — README каталога): | Файл | Что проверяет | @@ -181,6 +181,7 @@ arm-tabular-parser#11, OQ-131…OQ-135. ИНН организаций в шап | `st03_no_codes` | форма без колонки кодов → `needs_check`, «колонка кодов не найдена» (OQ-139) | | `st04_mixed_book` | книга: лист ОСВ + лист баланса, порядок документов ОСВ → форма | | `st05_continuation_only` | одинокая страница 2 → `needs_check`, предупреждение о продолжении (OQ-140) | +| `st07_single_code_continuation` | ОФР без 2400 на первом листе и лист-продолжение с единственной кодовой строкой 2400 присоединяется (OQ-143) | | `st06_header_variants` | варианты, которых нет в реальных файлах: старое название ОФР, расшифровки/ОДДС/ОИК, форма только с ОКУД 0710xxx, организация в «», «Адрес», «Пояснения», числовая дата (покрытие словарей `statement_*.yaml`) | ## 5. Прочее diff --git a/context/07-open-questions.md b/context/07-open-questions.md index c8aec64..7f26256 100644 --- a/context/07-open-questions.md +++ b/context/07-open-questions.md @@ -148,7 +148,7 @@ | OQ-140 | Страница-продолжение в отдельном файле (1С печатает ББ/ОФР постранично, один файл = страница): склейка в ядре по ЮЛ + период + тип формы; признак `is_continuation` / `form_page` в контракте (MINOR, две необязательных поля) | решение владельца 06.10.2026 (вопрос 2), design 2b D-8 | §12 п. 9, Срез 3, контракт v1.x | допущение принято: страницы разных файлов не склеиваются; страница 2 без шапки — документ с пустой шапкой и `needs_check`, «загрузите форму одним файлом» | | OQ-141 | Строка без кода, но с суммами в ОФР ФСБУ 4/2023 (НПЗ «Реализация иного имущества…»): хранить ли (OQ-36 расширяется с расшифровочных строк на строки с суммами) | `fixtures/statements-xlsx/npz`, design 2b D-6 | Срез 3, DBML `financial_statement_line` (хранит только строки с кодом) | допущение принято: строки без кода не отдаются, при наличии сумм — предупреждение «строк без кода с суммами пропущено: N» | | OQ-142 | Образец ФСБУ 4/2023 (`templates/ББ после 01.01.2025.xlsx`): «АКТИВ» и код 1110 в одной строке из-за объединённых ячеек; шаблоны (коды есть, сумм и шапки нет) не данные. Нужен ли их разбор вообще | `fixtures/statements-xlsx/templates`, design 2b D-8 | §12 п. 10, тесты | допущение принято: шаблоны дают `needs_check` (шапка пустая, значения `null`); разбор шаблонов как источника данных не планируется, пока владелец не скажет иначе | -| OQ-143 | Лист продолжения с **единственной** кодовой строкой (книга НПЗ: лист ОФР с одной строкой 2400): `min_codes` = 3 → лист не распознаётся как форма и пропускается, строка 2400 теряется при `needs_check` документа. Понизить порог / принимать лист по близости к открытому документу ОФР / маркеру продолжения | tabular-parser design 2b: решение №25, O-9 | §12 п. 2, п. 9; полнота ОФР НПЗ | открыт: отложено на финальное ревью 2b; допущение — строка 2400 листа продолжения НПЗ в результате отсутствует | +| OQ-143 | Лист продолжения с **единственной** кодовой строкой (книга НПЗ: лист ОФР с одной строкой 2400): `min_codes` = 3 → лист не распознаётся как форма и пропускается, строка 2400 теряется при `needs_check` документа. Понизить порог / принимать лист по близости к открытому документу ОФР / маркеру продолжения | tabular-parser design 2b: решение №25, O-9 | §12 п. 2, п. 9; полнота ОФР НПЗ | **реализовано в 2b (финальная волна, I-1):** лист с 1–2 кодами форм после листа формы берётся как продолжение (`min_codes_continuation = 1` в словаре) и присоединяется при совпадении числа колонок сумм и типа формы; не присоединён — `needs_check` и предупреждение; первая страница с 1–2 кодами формой не считается. Строка 2400 НПЗ в результате есть | Служебные идентификаторы в DBML/аналитике: `ANL-nnn` — замечания аналитика к макету; `ARCH-nnn` — архитектурные решения; `DECISION-n` — решения по модели; `FIX-nn` — исправления дефектов v4. diff --git a/context/09-delivery-plan.md b/context/09-delivery-plan.md index 45d42a2..a9688ea 100644 --- a/context/09-delivery-plan.md +++ b/context/09-delivery-plan.md @@ -116,14 +116,13 @@ Change'и: `tabular-parser/openspec/changes/slice-2a-osv-parser` (issue arm-tabu - **Реализовано (ветка `feat/14-slice-2b-statement-parser`, tabular-parser PR #16; docs — PR #27, ветка `feat/26-slice-2b-statement-parser`):** `BookParser` + конвейер форм `statements/`, словари `statement_*.yaml`, контракт v1.2 (`DISCLOSURE`, `checks`, границы периода ОСВ; копии схемы в arm-core PR #27 и scan-gateway PR #5), `§12`/`§7` по - решениям владельца. Тесты: манифест `api/tests/statements_manifest.yaml` (18 реальных файлов), синтетика `st01`–`st06`, - golden `expected_statement_parse/` (18 + 6 снимков), интеграционный тест воркера на книге НПЗ. + решениям владельца. Тесты: манифест `api/tests/statements_manifest.yaml` (18 реальных файлов), синтетика `st01`–`st07`, + golden `expected_statement_parse/` (18 + 7 снимков), интеграционный тест воркера на книге НПЗ. - **Объём:** парсер + контракт v1.2; **маппинг форм в ядре (`statementDocument → document + financial_statement_*`) — Срез 3**. По факту `done` только у форм Межениновской; остальные `needs_check` по данным файлов (рубли с копейками при «тыс. руб.», страницы без шапки, шаблоны) — OQ-138, OQ-140. - **Не сделано / риски:** единицы не нормализуются (OQ-138); форма без колонки кодов не разбирается (OQ-139); страницы - в разных файлах не склеиваются (OQ-140); строки без кода не хранятся (OQ-141); лист ОФР НПЗ с единственной строкой 2400 - теряется (OQ-143); после контракта v1.2 `docs/contracts/**` заморожены (копии схемы в arm-core и scan-gateway должны совпадать с ними; в tabular-parser версия закреплена тестом `api/tests/unit/test_contract_v12.py`, побайтное сравнение копий — вручную через `diff` при раскатке); косметика T1.1/T2.x уходит в следующий MINOR. + в разных файлах не склеиваются (OQ-140); строки без кода не хранятся (OQ-141); после контракта v1.2 `docs/contracts/**` заморожены (копии схемы в arm-core и scan-gateway должны совпадать с ними; в tabular-parser версия закреплена тестом `api/tests/unit/test_contract_v12.py`, побайтное сравнение копий — вручную через `diff` при раскатке); косметика T1.1/T2.x уходит в следующий MINOR. ### Срез 2c — Загрузка файлов и маппинг результата в ядре (`arm-core`) — реализован, ожидает ревью и merge diff --git a/dev/qa-guide.md b/dev/qa-guide.md index 8e3fdaa..6e6a0a0 100644 --- a/dev/qa-guide.md +++ b/dev/qa-guide.md @@ -388,7 +388,7 @@ ENV_FILE=.env.test .venv/bin/python -m src.parser.cli "/путь/к/файлу.x `checks.soft_relations_failed` и `duplicate_line_codes`; в `metrics.warnings` — предупреждение об единицах («значений с дробной частью при единице тыс. руб.: N из M»: значения как в файле, не нормализованы, OQ-138), «колонка кодов не найдена», «страница-продолжение без шапки». Ожидания по реальным файлам — `../tabular-parser/api/tests/statements_manifest.yaml` и -таблица «файл → статус» в README `tabular-parser`; файлы — `../fixtures/statements-xlsx/` (синтетика `st01…st06`). +таблица «файл → статус» в README `tabular-parser`; файлы — `../fixtures/statements-xlsx/` (синтетика `st01…st07`). Постраничные xls из 1С (страница 2 отдельным файлом, ББ только актив) и формы в рублях при шапке «тыс. руб.» дают `needs_check` — это штатно (OQ-138, OQ-140), не баг; `done` ожидается только у форм, где §7 сходится (Межениновская). diff --git a/openspec/changes/slice-2b-statement-parser/tasks.md b/openspec/changes/slice-2b-statement-parser/tasks.md index cbdb4ab..29a6e34 100644 --- a/openspec/changes/slice-2b-statement-parser/tasks.md +++ b/openspec/changes/slice-2b-statement-parser/tasks.md @@ -3,15 +3,15 @@ Задачи выполняются в ветке `feat/26-slice-2b-statement-parser`; детализация — в плане superpowers вместе с дочерним change tabular-parser. -- [ ] 1. Контракт v1.2: `docs/contracts/recognition-result.schema.json` — `DISCLOSURE`, `statementDocument.checks`, +- [x] 1. Контракт v1.2: `docs/contracts/recognition-result.schema.json` — `DISCLOSURE`, `statementDocument.checks`, `osvDocument.header.period_start/period_end/is_from_year_start`, заголовок и описание «1.2» (design D-1); проверка схемы валидатором JSON Schema на всех примерах. -- [ ] 2. Примеры: `result-statement-minimal.json` (+`checks`, «1.2»), новый `result-statement-excel.json`, +- [x] 2. Примеры: `result-statement-minimal.json` (+`checks`, «1.2»), новый `result-statement-excel.json`, `result-osv-minimal.json` (границы периода) (design D-2). - [ ] 3. Спека `openspec/specs/recognition-contract` синхронизируется из дельты при архивации; до этого — дельта в change. -- [ ] 4. `05-domain-rules.md` §12 — решения владельца и уточнения (design D-3); §7 — пометка жёстких/мягких соотношений. -- [ ] 5. `06-test-data.md` — раздел `statements-xlsx/**`, манифест, golden `expected_statement_parse/`, синтетика. -- [ ] 6. `03-architecture.md` — контракт 1.2, `BookParser`, порядок раскатки MINOR; `09-delivery-plan.md` — Срез 2b. -- [ ] 7. `07-open-questions.md` — новые OQ (единицы против копеек; форма без колонки кодов; страница-продолжение в +- [x] 4. `05-domain-rules.md` §12 — решения владельца и уточнения (design D-3); §7 — пометка жёстких/мягких соотношений. +- [x] 5. `06-test-data.md` — раздел `statements-xlsx/**`, манифест, golden `expected_statement_parse/`, синтетика. +- [x] 6. `03-architecture.md` — контракт 1.2, `BookParser`, порядок раскатки MINOR; `09-delivery-plan.md` — Срез 2b. +- [x] 7. `07-open-questions.md` — новые OQ (единицы против копеек; форма без колонки кодов; страница-продолжение в отдельном файле; строка без кода с суммами в ОФР ФСБУ; образец ФСБУ «АКТИВ»+1110), статус OQ-131. -- [ ] 8. `docs/dev/qa-guide.md` §6.7 — прогон парсера на формах; README `docs/contracts/` (если есть) — v1.2. +- [x] 8. `docs/dev/qa-guide.md` §6.7 — прогон парсера на формах; README `docs/contracts/` (если есть) — v1.2.