diff --git a/openspec/changes/use-installed-statements-library/.openspec.yaml b/openspec/changes/archive/2026-11-10-use-installed-statements-library/.openspec.yaml similarity index 100% rename from openspec/changes/use-installed-statements-library/.openspec.yaml rename to openspec/changes/archive/2026-11-10-use-installed-statements-library/.openspec.yaml diff --git a/openspec/changes/use-installed-statements-library/design.md b/openspec/changes/archive/2026-11-10-use-installed-statements-library/design.md similarity index 100% rename from openspec/changes/use-installed-statements-library/design.md rename to openspec/changes/archive/2026-11-10-use-installed-statements-library/design.md diff --git a/openspec/changes/use-installed-statements-library/proposal.md b/openspec/changes/archive/2026-11-10-use-installed-statements-library/proposal.md similarity index 100% rename from openspec/changes/use-installed-statements-library/proposal.md rename to openspec/changes/archive/2026-11-10-use-installed-statements-library/proposal.md diff --git a/openspec/changes/use-installed-statements-library/specs/documents-api/spec.md b/openspec/changes/archive/2026-11-10-use-installed-statements-library/specs/documents-api/spec.md similarity index 100% rename from openspec/changes/use-installed-statements-library/specs/documents-api/spec.md rename to openspec/changes/archive/2026-11-10-use-installed-statements-library/specs/documents-api/spec.md diff --git a/openspec/changes/use-installed-statements-library/specs/statement-checks/spec.md b/openspec/changes/archive/2026-11-10-use-installed-statements-library/specs/statement-checks/spec.md similarity index 100% rename from openspec/changes/use-installed-statements-library/specs/statement-checks/spec.md rename to openspec/changes/archive/2026-11-10-use-installed-statements-library/specs/statement-checks/spec.md diff --git a/openspec/changes/use-installed-statements-library/specs/statement-library/spec.md b/openspec/changes/archive/2026-11-10-use-installed-statements-library/specs/statement-library/spec.md similarity index 100% rename from openspec/changes/use-installed-statements-library/specs/statement-library/spec.md rename to openspec/changes/archive/2026-11-10-use-installed-statements-library/specs/statement-library/spec.md diff --git a/openspec/changes/use-installed-statements-library/tasks.md b/openspec/changes/archive/2026-11-10-use-installed-statements-library/tasks.md similarity index 100% rename from openspec/changes/use-installed-statements-library/tasks.md rename to openspec/changes/archive/2026-11-10-use-installed-statements-library/tasks.md diff --git a/openspec/changes/use-installed-statements-library/verification.md b/openspec/changes/archive/2026-11-10-use-installed-statements-library/verification.md similarity index 100% rename from openspec/changes/use-installed-statements-library/verification.md rename to openspec/changes/archive/2026-11-10-use-installed-statements-library/verification.md diff --git a/openspec/specs/documents-api/spec.md b/openspec/specs/documents-api/spec.md index 30109a0..453b60d 100644 --- a/openspec/specs/documents-api/spec.md +++ b/openspec/specs/documents-api/spec.md @@ -443,7 +443,7 @@ RELATION_SOFT`, `severity = info`; `line_ids` — все строки `ok` ко строк `detail` (ближайшая строка `ok` выше по `row_index`; нет такой — `null`, строка остаётся `detail`), записи `document_issue` видов `relation` / `soft` (заменяются целиком независимо от источника), статус. Относительные даты колонок (`period_kind`, `statement-normalization`) пересчитываются от даты отчёта после правки `header.report_date` и -`columns[].period_date`. Отличие `statements_version` задания от версии копии ядра — `document_issue` +`columns[].period_date`. Отличие `statements_version` задания от версии установленной библиотеки ядра — `document_issue` `STATEMENTS_VERSION_MISMATCH` (`info`); у задания без версии (`1.x`) запись не пишется. Записи `core` `CODE_NOT_IN_DICTIONARY`, `CODE_NOT_IN_EDITION` (только четырёхзначные коды), `NAME_MISMATCH` и `STATEMENTS_VERSION_MISMATCH` пересчитываются заменой; `NAME_MISMATCH` не ставится строке с назначенным аналитиком кодом; @@ -476,13 +476,21 @@ RELATION_SOFT`, `severity = info`; `line_ids` — все строки `ok` ко - **THEN** запись `RELATION_FAILED` пересоздана с новыми `expected` / `actual`; `POST …/confirm` без акцепта — 409 `CHECKS_NOT_PASSED` +#### Scenario: Совпадение версии установленного дистрибутива +- **WHEN** форма из существующей фикстуры результата 2.0 принята с `service.statements_version`, равной версии установленной библиотеки без внутреннего `VERSION` +- **THEN** поле версии проходит валидацию и `STATEMENTS_VERSION_MISMATCH` не создаётся + +#### Scenario: Разные версии библиотеки и сервиса +- **WHEN** та же форма принята с непустой версией сервиса, отличающейся от версии установленной библиотеки +- **THEN** создаётся `STATEMENTS_VERSION_MISMATCH` уровня `info` без ослабления валидации результата + ### Requirement: Словари ядра и достройка шаблонных строк -Копия словаря §7 ядра (`api/rules/statement_checks.yaml`) SHALL быть удалена: проверки ядро считает копией пакета -`arm_statements`. `api/rules/statement_lines.yaml` SHALL оставаться только словарём имён (код → наименования по +Копия словаря §7 ядра (`api/rules/statement_checks.yaml`) SHALL быть удалена: проверки ядро считает установленной библиотекой +`arm_statements` (дистрибутив `pylib-ai-arm-statements`). `api/rules/statement_lines.yaml` SHALL оставаться только словарём имён (код → наименования по редакциям): у кода может быть несколько имён (синонимы и законные повторы кода в бланке, Р-20), загрузчик повтор кода в редакции MUST NOT запрещать; сверка наименования — с любым именем кода; шаблонная строка берёт первое имя. Порядок и -состав редакций — из копии перечня кодов пакета (`code_orders.editions`); код словаря имён, которого нет в перечне своей -редакции, — ошибка проверки (тест согласованности, `sync-statements --check`). В редакции `fsbu4` словарь имён SHALL быть +состав редакций — из перечня кодов установленной библиотеки (`code_orders.editions`); код словаря имён, которого нет в перечне своей +редакции, — ошибка проверки (тест согласованности с установленной библиотекой). В редакции `fsbu4` словарь имён SHALL быть дополнен вторыми именами законных повторов 1220 «НДС, начисленный по отгрузке», 1520 «Обязательство по аренде», 2410 «Налог при упрощенной системе налогообложения» (Р-20) и кодами печатной формы 1С 1105 «Гудвил», 1130 «Нематериальные поисковые активы», 1140 «Материальные поисковые активы», 1530 «Доходы будущих периодов», 2460 «Прочее» (имена — по @@ -492,7 +500,7 @@ RELATION_SOFT`, `severity = info`; `line_ids` — все строки `ok` ко молча. #### Scenario: Код словаря вне перечня -- **WHEN** в `statement_lines.yaml` у редакции есть код, которого нет в перечне этой редакции копии пакета +- **WHEN** в `statement_lines.yaml` у редакции есть код, которого нет в перечне этой редакции установленной библиотеки - **THEN** проверка согласованности словаря с перечнем падает #### Scenario: Код есть только у строки unreadable diff --git a/openspec/specs/statement-checks/spec.md b/openspec/specs/statement-checks/spec.md index 2949952..ab54bfa 100644 --- a/openspec/specs/statement-checks/spec.md +++ b/openspec/specs/statement-checks/spec.md @@ -8,7 +8,7 @@ ### Requirement: Соотношения §7 по колонкам Проверки SHALL считаться чистой функцией по текущим `financial_statement_value.amount` документа для каждой колонки -отдельно по словарю §7 копии пакета `arm_statements` (`statement-normalization`; своей копии словаря ядро не держит): +отдельно по словарю §7 установленной библиотеки `arm_statements` (`statement-normalization`; своей копии словаря ядро не держит): соотношение **посчитано**, если непуста цель (левая часть) или хотя бы один член (есть строка `ok` с кодом и непустой суммой); если пусто всё — соотношение пропускается. В посчитанном соотношении отсутствующий код и пустая сумма в арифметике — 0, но пустая цель при непустых членах и непустая цель при пустых членах — нарушение (пустая цель даёт diff --git a/openspec/specs/statement-library/spec.md b/openspec/specs/statement-library/spec.md new file mode 100644 index 0000000..5ebe035 --- /dev/null +++ b/openspec/specs/statement-library/spec.md @@ -0,0 +1,54 @@ +# statement-library Specification + +## Purpose +Поставка общей нормализации форм как устанавливаемой библиотеки с правилами и идентификатором версии, доступной ядру без встроенной копии исходников. + +## Requirements + +### Requirement: Установка локальной библиотеки +Команда `make install` SHALL устанавливать или переустанавливать дистрибутив `pylib-ai-arm-statements` в окружение backend `api/.venv` из соседнего репозитория `../pylib_ai_arm_statements`. Путь SHALL переопределяться через `STATEMENTS_DIR`. При отсутствии окружения команда SHALL создавать его на Python 3.11. + +#### Scenario: Повторная установка после изменения библиотеки +- **WHEN** разработчик выполняет `make install` после изменения исходников или YAML-правил локальной библиотеки +- **THEN** backend получает обновлённую библиотеку, даже если номер версии дистрибутива не изменён + +#### Scenario: Другой путь к исходникам +- **WHEN** разработчик выполняет `make install STATEMENTS_DIR=/tmp/local-statements` +- **THEN** библиотека устанавливается из указанного каталога в окружение backend + +### Requirement: Подготовка окружения разработки +При установке `api/requirements.txt` команда `make venv` SHALL пропускать строки с префиксами `raisa_` и `pylib_ai`. Обработка `requirements-dev.txt` SHALL сохраняться: исключаются вложенные строки `-r`. После установки requirements локальная библиотека SHALL устанавливаться в окружение backend. + +#### Scenario: Внутренний пакет не запрашивается из реестра +- **WHEN** requirements содержит `pylib_ai_arm_statements==0.1.1` и выполняется `make venv` +- **THEN** этот пакет не запрашивается из реестра по requirements и устанавливается из локального репозитория + +### Requirement: Совместимость импортов и ресурсов +Установленная библиотека SHALL предоставлять импорт `arm_statements` и необходимые YAML-правила. Нормализация и загрузка стандартных правил MUST работать без каталога `api/arm_statements/` и без обращения к исходникам соседнего репозитория во время исполнения. + +#### Scenario: Стандартные правила из установленного пакета +- **WHEN** установлен собранный дистрибутив и backend загружает стандартные правила +- **THEN** `statement_checks.yaml` и остальные необходимые YAML доступны внутри пакета; ошибка отсутствующего файла не возникает + +### Requirement: Версия установленной библиотеки +Версия библиотеки SHALL определяться непустым стандартным маркером `VERSION`, а при его отсутствии или пустом содержимом — метаданными дистрибутива `pylib-ai-arm-statements`. Если оба источника недоступны, результат SHALL быть `None`. Явно переданный отсутствующий или пустой файл SHALL возвращать `None` без подстановки метаданных. + +#### Scenario: Пакет без внутреннего VERSION +- **WHEN** у установленного дистрибутива версии `0.1.1` нет внутреннего `VERSION` +- **THEN** версия библиотеки равна `0.1.1`, а не `None` + +#### Scenario: Приоритет маркера +- **WHEN** внутренний `VERSION` содержит непустой идентификатор, а метаданные содержат версию дистрибутива +- **THEN** возвращается идентификатор из `VERSION` без окружающих пробелов + +#### Scenario: Явно указанный файл отсутствует +- **WHEN** вызывающий передаёт путь к отсутствующему файлу версии +- **THEN** возвращается `None`, даже если дистрибутив установлен + +#### Scenario: Пустой стандартный маркер +- **WHEN** стандартный `VERSION` пуст, но метаданные дистрибутива доступны +- **THEN** возвращается версия дистрибутива + +#### Scenario: Нет доступного идентификатора +- **WHEN** стандартного маркера и метаданных дистрибутива нет +- **THEN** возвращается `None`