Andrey Epifancev 12ae96ba6e Библиотека arm_statements вместо копий: спеки, контекст, инструменты docs (AURORA-1677)
- спеки statement-normalization, quality-checks, arm-core, recognition-contract — дельты под библиотеку
- удалены sync-statements, statements-check, test-sync-statements; новая statements-orders-check в make check
- снимок для контура: без шага 0a, цель install вырезается (иначе проверка «нет uv» падает)
- 03-architecture, 05-domain-rules, 00-workspace-layout, dev/checks.md, contour-transfer-guide; баннеры убраны

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 16:45:19 +04:00

12 KiB
Raw Blame History

MODIFIED Requirements

Requirement: Предупреждения и нарушения документа — document_issue

Ядро SHALL хранить предупреждения и нарушения документа в document_issue: вид (warning | relation | soft), код, уровень (error | info), сообщение, список line_id, column_id (колонка формы) или column_index (столбец предупреждения, которого нет среди колонок формы), поле шапки, источник (service | core); для нарушений — codes (коды цели и членов), текст соотношения, expected, actual. Нарушение из checks.relations_failed — kind = relation, code = RELATION_FAILED, severity = error; из soft_relations_failed — kind = soft, code = RELATION_SOFT, severity = info; line_ids — все строки ok кодов codes в документе. При загрузке пишутся предупреждения и checks результата (источник service) и проверки ядра уровня info (источник core): CODE_NOT_IN_DICTIONARY (кода нет в словаре имён редакции документа), CODE_NOT_IN_EDITION (код не из перечня редакции документа и его варианта — по перечню кодов библиотеки arm_statements), NAME_MISMATCH, RESULT_STATUS_INCONSISTENT. Редакция документа для этих проверок — edition точки входа пакета для пересчёта (statement-normalization): редакция с лучшей подпоследовательностью кодов строк ok документа, при равенстве — по эффективной дате; так бланк 66н, сданный в 2025 году, проверяется по 66n, а не по дате. Поле edition ответа GET …/statement и выбор шаблонных строк по-прежнему — по дате периода (§7 «Полный состав формы»). document_issue ведётся у любого документа файла: у ОСВ — предупреждения osvDocument.warnings результата 2.0 (вид warning, источник service, OSV_*, info). При перезагрузке файла записи документа удаляются вместе с ним. При пересчёте после правки записи relation и soft заменяются целиком независимо от источника; записи warning источника service сохраняются, кроме снимаемых правкой: правка header.report_date (в том числе подтверждение тем же значением) снимает PERIOD_UNKNOWN, REPORT_DATE_UNPARSED, REPORT_DATE_UNCERTAIN; правка header.inn или header.organization_name — NO_ORGANIZATION_NO_INN; правка columns[].period_date — COLUMN_WITHOUT_DATE и COLUMN_DATE_UNCERTAIN этой колонки; прочие error сервиса снимаются только перезагрузкой файла. При удалении шаблонной строки её id SHALL убираться из line_ids всех записей документа. GET …/statement и POST …/confirm SHALL читать нарушения §7 только из document_issue.

Scenario: Дата колонке

  • WHEN у колонки предупреждение COLUMN_WITHOUT_DATE, аналитик ставит ей period_date через PATCH
  • THEN предупреждение удаляется, статус пересчитывается

Scenario: Неснимаемое предупреждение

  • WHEN у документа SEGMENT_COLUMNS_MISMATCH, аналитик правит значения
  • THEN предупреждение остаётся; документ можно подтвердить вручную (оно подтверждение не блокирует)

Scenario: Бланк 66н в 2025 году без ложного info

  • WHEN форма Межениновской за 3 кв. 2025 на бланке 66н с кодом 1120 (в перечне fsbu4 его нет)
  • THEN редакция документа для проверок ядра — 66n (подпоследовательность длиннее), CODE_NOT_IN_EDITION у 1120 нет

Scenario: Пропущенная колонка

  • WHEN в результате предупреждение COLUMN_SKIPPED с column_index = 5, колонки 5 среди columns[] нет
  • THEN запись document_issue с column_index = 5 и column_id = null; экран показывает её у документа

Requirement: Пересчёт после правки

После каждого PATCH формы ядро SHALL пересчитывать checks, needs_review, form_variant, родителей строк detail и статус точкой входа пакета для пересчёта по сохранённым данным (statement-normalization; конвенция знака — по source_text), с правилами: is_modified или is_confirmed значения ⇒ needs_review = false; line_code_modified или is_confirmed строки ⇒ needs_review строки = false; значения строк detail — needs_review = false (Р-23), у строки, выведенной из detail назначением кода, needs_review её значений считается по общему правилу; акцепт ⇒ жёсткие нарушения не учитываются; правленые ячейки в голосование знака не входят. Результат пишется: needs_review строк и значений, form_variant, parent_row_index всех строк detail (ближайшая строка ok выше по row_index; нет такой — null, строка остаётся detail), записи document_issue видов relation / soft, статус. Отличие statements_version задания от версии библиотеки ядра (версия установленного дистрибутива pylib-ai-arm-statements) — document_issue STATEMENTS_VERSION_MISMATCH (info); у задания без версии (1.x) запись не пишется. Один PATCH — один пересчёт и одна запись аудита RECOGNIZED_DATA_EDIT. Акцепт SHALL сбрасываться правкой данных — суммы, кода или статуса строки, даты колонки, поля шапки; подтверждение или снятие подтверждения (confirmed) и подтверждение даты отчёта или даты колонки тем же значением акцепт MUST NOT сбрасывать (Р-25, S-47).

Scenario: Подтверждение ячейки без правки

  • WHEN аналитик подтверждает ячейку с needs_review = true без изменения суммы
  • THEN is_confirmed = true, confirmed_by/at, is_modified не ставится, needs_review = false, аудит; акцепт проверок, если был, сохраняется

Scenario: Снятие подтверждения

  • WHEN аналитик снимает подтверждение с ячейки (confirmed: false), которая не покрыта соотношением
  • THEN is_confirmed = false, needs_review = true после пересчёта, аудит

Scenario: Родитель уходит в расшифровки

  • WHEN у строки 1150 две расшифровки (detail, parent_row_index = 1150), аналитик отмечает саму 1150 расшифровкой
  • THEN после пересчёта родитель всех трёх строк detail — ближайшая строка ok выше 1150; строк над ними нет — null (на экране — в начале раздела)

Requirement: Словари ядра и достройка шаблонных строк

Копия словаря §7 ядра (api/rules/statement_checks.yaml) SHALL удаляться: проверки ядро считает библиотекой arm_statements. api/rules/statement_lines.yaml SHALL оставаться только словарём имён (код → наименования по редакциям): у кода может быть несколько имён (синонимы и законные повторы кода в бланке, Р-20), загрузчик повтор кода в редакции MUST NOT запрещать; сверка наименования — с любым именем кода; шаблонная строка берёт первое имя. Порядок и состав редакций — из перечня кодов библиотеки; что все коды словаря имён есть в перечне своей редакции, сверяет тест ядра test_name_dictionary_codes_in_code_orders (в make check). В PR перехода ядра на v2.0 словарь имён SHALL быть дополнен: в редакции fsbu4 — вторые имена законных повторов 1220 «НДС, начисленный по отгрузке», 1520 «Обязательство по аренде», 2410 «Налог при упрощенной системе налогообложения» (Р-20) и коды печатной формы 1С 1105 «Гудвил», 1130 «Нематериальные поисковые активы», 1140 «Материальные поисковые активы», 1530 «Доходы будущих периодов», 2460 «Прочее» (имена — по fixtures/ocr и шаблонам банка); без этого законные повторы РБ, Счастливочной и aep_6 и любой неуверенный 1105 дают NAME_MISMATCH. Шаблонные строки достраиваются по словарю имён (одна на код); код, у которого есть хотя бы одна строка ok из файла, шаблоном MUST NOT достраиваться; строки unreadable / missing не заменяются шаблонной строкой молча.

Scenario: Код есть только у строки unreadable

  • WHEN у формы нет строки ok с кодом 1250, но есть строка unreadable «ИЧ,250»
  • THEN шаблонная строка 1250 достраивается пустой, строка unreadable показывается отдельно со статусом

Scenario: Два имени у кода

  • WHEN в редакции fsbu4 словаря имён код 1520 записан дважды — «Кредиторская задолженность» и «Обязательство по аренде»
  • THEN словарь загружается; шаблонная строка 1520 одна, с именем «Кредиторская задолженность»

Scenario: Гудвил с заголовком раздела в имени

  • WHEN строка 1105 (уверенность 67) с наименованием «АКТИВ I. Внеоборотные активы Гудвил»
  • THEN справочное «Гудвил» (≥ 5 символов) входит в него — совпало, NAME_MISMATCH нет