Andrey Epifancev 248f8b0c74 openspec(#116): спека по ревью K-1…K-25 и решениям владельца Р-20…Р-22; решения S-26…S-52
- design.md: Р-20 (законные повторы кода в перечне, синонимы в словаре имён), Р-21 (мягкое соотношение, сошедшееся
  точно, подтверждает неуверенное значение), Р-22 (S-1…S-25 приняты с оговорками; отмечены утверждённые владельцем);
  решения при доработке S-26…S-52 с ценой ошибки
- statement-normalization: отдельное требование sync-statements (пути, VERSION, коды 0 / 10 / 20 / 2), словарь
  единиц и ОКЕИ, ref Excel с кавычками, нумерация с двойниками и пропуском, номер колонки, содержимое строки, столбец
  кодов у DISCLOSURE, упрощённый 2400 мягкий, Р-20 / Р-21 со сценариями, обе редакции перечня, интерфейс функции
  статуса, TABLE_PARSE_ERROR / SHEET_OTHER уровня файла
- arm-core: признак строки правки row_index IS NULL, header_source, формы без checks (1.x и миграция) — §7 ядром в
  document_issue, codes / column_index, RESULT_STATUS_INCONSISTENT, синонимы и «итого по разделу», PATCH
  organization_name / confirmed: false / подтверждение даты, LINE_CODE_TAKEN, акцепт и подтверждения, LINES_UNRESOLVED
  с текстом, «того же периода», откат миграции
- recognition-contract: MODIFIED «Копия контракта … идентична» — сверка по MAJOR копии, *.v1.schema.json на окне;
  1.x — MAPPING_WARNING / LEGACY_WARNING; okei, column_index, пустые массивы DISCLOSURE, статус ОСВ одной формулировкой
- quality-checks (новая дельта): make check охватывает копию arm_statements, make check-full — statements-check
- tabular-recognition-service: манифест statements_manifest.yaml — failed_relations страниц 2 баланса (K-25)
- scan-gateway, arm-web: TABLE_PARSE_ERROR файла; подсказки шапки, снятие подтверждений, LINE_CODE_TAKEN
- proposal: шаг 0 выкладки, перечни кодов, ожидания на реальных сканах, Impact

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
2026-10-18 02:17:36 +04:00

7.3 KiB
Raw Blame History

ADDED Requirements

Requirement: Адаптер Excel шага 1

tabular-parser SHALL оставить у себя чтение книги (лимиты PARSE_MAX_BYTES, PARSE_TIMEOUT_SECONDS, формат по сигнатуре, лимиты zip и объединённых ячеек, UNREADABLE), классификацию листов (ОСВ — отдельный путь; форма; продолжение; прочее) и адаптер «блок формы на листе → FormCandidate» общего кода; шаги 2–8 по формам SHALL выполняться копией пакета arm_statements. Адаптер SHALL: выделять блоки форм на листе по заголовку или ОКУД (без кодов между ними блоки сливаются, заголовок после кодов — новая форма); собирать шапку каждого блока в его границах (организация, ИНН без ИНН аудитора, ОКПО, ОКОПФ, ОКФС, единицы, дата, адрес) как Cell с confidence = 100; заполнять у каждой ячейки text по числовому формату (tp#42) и value, ref = <лист>!<A1> (имя листа в одинарных кавычках по правилу Excel, если в нём есть что-то кроме букв, цифр и _); дописывать листы-продолжения в сетку открытой формы до раскладки (маркер «Форма … с.2» или позиция листа; проверки типа, диапазона кодов и, при трёх и более кодах, числа колонок — как join_blocker), записывая границы листов в segment_breaks. Несовпадение формата с file_type — предупреждение файла FILE_TYPE_MISMATCH (info). Лист без признаков ОСВ и формы, без type_hint и кодов — предупреждение файла SHEET_OTHER (info, locator = sheet:<имя>), документа нет.

Scenario: Книга ББ + ОФР

  • WHEN книга содержит лист «Баланс» (ОКУД 0710001), лист «Баланс (2)» с маркером «Форма 0710001 с.2» и лист «ОФР»
  • THEN адаптер выдаёт два кандидата: BALANCE с locator = sheet:Баланс,Баланс (2) и одной сеткой из двух листов (segment_breaks — первая строка второго листа) и INCOME с locator = sheet:ОФР

Scenario: Ссылки ячеек

  • WHEN код строки стоит в ячейке C27 листа «Баланс»
  • THEN ref строки — Баланс!C27; у листа «Бухгалтерский баланс. Лист 1» — 'Бухгалтерский баланс. Лист 1'!C27

Requirement: Строки без кода и неизвестные колонки в Excel

tabular-parser SHALL отдавать строки без кода с содержимым со статусами detail / missing / unreadable (Р-8; ранее не отдавались, OQ-36 / OQ-141), числовые колонки с нераспознанной подписью — колонкой без даты и error (ранее пропускались), повторы кодов — всеми строками без duplicate_line_codes.

Scenario: НПЗ «Реализация иного имущества»

  • WHEN в ОФР ФСБУ 4/2023 строка «Реализация иного имущества…» без кода с суммами стоит под строкой 2340
  • THEN в результате строка detail с parent_ref строки 2340; ранее она отбрасывалась со счётчиком

Requirement: Манифест ожиданий на реальных формах

Манифест tabular-parser/api/tests/statements_manifest.yaml SHALL быть обновлён в PR перехода на 2.0 по правилу «посчитанного» соотношения §7 (пустая цель при непустых членах — нарушение): failed_relations страниц 2 баланса без 1600 получают ["1600 = 1700"] — unagrande-co/2024-FY/Б.Б. Лист 2.xls, unagrande-group/2024-FY/ББ. Лист 2 (2).xls, unagrande-group/2025-Q3/ББ. Лист 2 3кв.25.xls (было [], причина «страница 2 без шапки» остаётся); страницы 1 «только актив» (Б.Б Лист 1.xls, ББ. Лист 1 .xls, ББ. Лист 1 3кв.25.xls) сохраняют ["1600 = 1700"] (теперь как «непустая цель при пустых членах»). Статусы done (Межениновская ББ и ОФР, НПЗ ББ и ОФР, ОФР «Лист 1» Унагранде ×2) MUST NOT меняться: их строки без кода уходят в detail, строки шапки выше заголовка — в title. Остальные записи манифеста пересчитываются прогоном и правятся только с объяснением в описании PR.

Scenario: Страница 2 баланса

  • WHEN разбирается unagrande-group/2025-Q3/ББ. Лист 2 3кв.25.xls (есть 1700, нет 1600)
  • THEN документ needs_check, в checks.relations_failed — 1600 = 1700 с пустой целью

Requirement: Путь ОСВ в контракте v2.0

У osvDocument tabular-parser SHALL выдавать status (done, когда контрольные суммы §1.4 листа сошлись, иначе needs_check — прежние условия §1.6, применённые к листу) и warnings[] — прежние предупреждения листа структурами с severity = info и кодом с префиксом OSV_; строк вида sheet=<имя> <текст> в metrics.warnings больше нет. Остальной разбор ОСВ не меняется.

Scenario: Предупреждение ОСВ

  • WHEN на листе ОСВ есть строка без родителя
  • THEN у документа ОСВ предупреждение {code: "OSV_…", severity: "info", message}, статус документа по §1.6

Requirement: Статус книги

Статус конверта tabular-parser SHALL вычисляться по общему правилу: done ⇔ все документы done ∧ нет предупреждений файла уровня error; книга без листов ОСВ и форм — error INVALID_DOCUMENT. Порядок документов — сначала ОСВ в порядке листов, затем формы.

Scenario: Книга только из пояснений

  • WHEN книга содержит только листы пояснений (0710003, «Пояснения»)
  • THEN документы DISCLOSURE со статусом done, конверт done