openspec: архив use-statements-library (AURORA-1677)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d56fbb5541
commit
e63e83235b
@ -98,7 +98,7 @@ SHALL хватать `OPENBAO__MINIO__*`, `OPENBAO__NATS__NATS_URL`, `SCAN_HOTFO
|
|||||||
успешным, если `error.code == ""` (поле `error` реального успешного ответа — `{"code": "", "message": ""}`, а не `null`;
|
успешным, если `error.code == ""` (поле `error` реального успешного ответа — `{"code": "", "message": ""}`, а не `null`;
|
||||||
отсутствующий или `null` `error` ошибкой не считается), и ошибочным, если `error.code` непуст, `parse_error` не `null`
|
отсутствующий или `null` `error` ошибкой не считается), и ошибочным, если `error.code` непуст, `parse_error` не `null`
|
||||||
либо корень ответа файла не является объектом JSON (ошибка этого файла — `INVALID_FORMAT`); успех MUST NOT определяться
|
либо корень ответа файла не является объектом JSON (ошибка этого файла — `INVALID_FORMAT`); успех MUST NOT определяться
|
||||||
проверкой «`error` не `null`». Конверт (включая ack `processing`) и файл результата несут `schema_version = "2.0"`, `result_schema_version = "2.0"`; `service.statements_version` (содержимое `api/arm_statements/VERSION`) SHALL быть в файле результата, в конверте `service` — `{name, version}`. Если ошибочны **все** файлы — `status = error`, `error.code` и `error.message` берутся у
|
проверкой «`error` не `null`». Конверт (включая ack `processing`) и файл результата несут `schema_version = "2.0"`, `result_schema_version = "2.0"`; `service.statements_version` (версия установленной библиотеки, полученная через `statements_version()`) SHALL быть в файле результата, в конверте `service` — `{name, version}`. Если ошибочны **все** файлы — `status = error`, `error.code` и `error.message` берутся у
|
||||||
первого ошибочного файла по имени (для `parse_error` и не-объекта — `INVALID_FORMAT`); если код ИС этого файла не
|
первого ошибочного файла по имени (для `parse_error` и не-объекта — `INVALID_FORMAT`); если код ИС этого файла не
|
||||||
входит в перечень кодов контракта, `error.code = UNKNOWN_ERROR`, а исходный код SHALL быть указан в `error.message`.
|
входит в перечень кодов контракта, `error.code = UNKNOWN_ERROR`, а исходный код SHALL быть указан в `error.message`.
|
||||||
Если есть хотя бы один успешный файл — документы собираются из успешных файлов по требованию «Нормализация ответа ИС в `statementDocument`», а статус определяется по требованию «Статус результата нормализации». `metrics.warnings` SHALL быть списком структур предупреждений (`code`, `severity`, `message`, `locator`, …) по схеме v2.0 — одним и тем же в конверте и в файле результата (предел 100 структур, `message` до 1000 символов; при переполнении остаются все `error`, затем `info`). Каждый ошибочный json набора SHALL давать предупреждение `JSON_FAILED` (`error`, `locator = file:<имя json>`, `message = "<код ИС>: <сообщение ИС>"`; для `parse_error` и не-объекта — код `INVALID_FORMAT`), в том числе когда ошибочны все json; исключение при разборе таблицы — `TABLE_PARSE_ERROR` (`error`, `locator = file:<имя json>;table:<i>`, `message = "BACKEND_PARSING_ERROR: <тип>: <текст>"`). Успешный json без `data_ocr`, без `table_structure` или с пустым `table_structure` SHALL давать `JSON_FAILED`. Если предупреждений нет, поле `warnings` SHALL быть опущено.
|
Если есть хотя бы один успешный файл — документы собираются из успешных файлов по требованию «Нормализация ответа ИС в `statementDocument`», а статус определяется по требованию «Статус результата нормализации». `metrics.warnings` SHALL быть списком структур предупреждений (`code`, `severity`, `message`, `locator`, …) по схеме v2.0 — одним и тем же в конверте и в файле результата (предел 100 структур, `message` до 1000 символов; при переполнении остаются все `error`, затем `info`). Каждый ошибочный json набора SHALL давать предупреждение `JSON_FAILED` (`error`, `locator = file:<имя json>`, `message = "<код ИС>: <сообщение ИС>"`; для `parse_error` и не-объекта — код `INVALID_FORMAT`), в том числе когда ошибочны все json; исключение при разборе таблицы — `TABLE_PARSE_ERROR` (`error`, `locator = file:<имя json>;table:<i>`, `message = "BACKEND_PARSING_ERROR: <тип>: <текст>"`). Успешный json без `data_ocr`, без `table_structure` или с пустым `table_structure` SHALL давать `JSON_FAILED`. Если предупреждений нет, поле `warnings` SHALL быть опущено.
|
||||||
@ -143,6 +143,10 @@ SHALL хватать `OPENBAO__MINIO__*`, `OPENBAO__NATS__NATS_URL`, `SCAN_HOTFO
|
|||||||
- **WHEN** успешный json не содержит `data_ocr.table_structure` или `table_structure: []`
|
- **WHEN** успешный json не содержит `data_ocr.table_structure` или `table_structure: []`
|
||||||
- **THEN** этот json даёт `JSON_FAILED`; если успешных json с таблицами нет — конверт `status = error`
|
- **THEN** этот json даёт `JSON_FAILED`; если успешных json с таблицами нет — конверт `status = error`
|
||||||
|
|
||||||
|
#### Scenario: Версия установленной библиотеки в результате
|
||||||
|
- **WHEN** установлен пакет `pylib_ai_arm_statements==0.1.1` и успешно нормализуется `aep_6.json`
|
||||||
|
- **THEN** файл результата содержит `service.statements_version = "0.1.1"`, конверт содержит только `service.name` и `service.version`; чтение локальной копии `api/arm_statements/VERSION` не требуется
|
||||||
|
|
||||||
### Requirement: Таймаут ожидания ответа
|
### Requirement: Таймаут ожидания ответа
|
||||||
Если готовый набор ответа (см. «Передача файла…») не появился до дедлайна, сервис SHALL опубликовать конверт `status = error`, `error.code = TIMEOUT`;
|
Если готовый набор ответа (см. «Передача файла…») не появился до дедлайна, сервис SHALL опубликовать конверт `status = error`, `error.code = TIMEOUT`;
|
||||||
повторная отправка файла в ИС MUST NOT выполняться.
|
повторная отправка файла в ИС MUST NOT выполняться.
|
||||||
@ -231,7 +235,7 @@ SHALL отражать состояние.
|
|||||||
- **THEN** опубликован `TIMEOUT`, входящий файл и каталог `Output/<job_id>/` (если есть) не тронуты
|
- **THEN** опубликован `TIMEOUT`, входящий файл и каталог `Output/<job_id>/` (если есть) не тронуты
|
||||||
|
|
||||||
### Requirement: Нормализация ответа ИС в `statementDocument`
|
### Requirement: Нормализация ответа ИС в `statementDocument`
|
||||||
Шлюз SHALL оставить у себя обмен с ИС Сканирование (горячие папки, опрос, срок, склейку набора json в `raw/{job_id}.json` до нормализации, очистку папки) и адаптер «таблица `table_structure[i]` json → `FormCandidate`»; шаги 2–8 SHALL выполняться копией пакета `arm_statements` (`api/arm_statements/`, правке не подлежит). Адаптер SHALL: создавать кандидата на каждую таблицу каждого успешного json; копировать шапку json (`organization`, `inn`, `units`, `date`) в шапку каждой своей таблицы как `Cell` (`text = form_name`, `confidence` ИС); передавать `label.form_name` таблицы как заголовок в `evidence` (тип — общим правилом шага 1 по словарю заголовков пакета, `type_hint(okud_text, title_text, rules)`, у OCR `okud_text = None`); строить плотную сетку по `row_index` и `column_index` ИС (пустые позиции — `null`), `Cell.ref = row:<row_index>`; `locator = file:<имя json>;table:<i>`. `value` у OCR-ячеек всегда `null`, `source = OCR`. Нарушенная структура таблицы ИС SHALL давать исключение адаптера и `TABLE_PARSE_ERROR` всей таблицы, остальные таблицы разбираются. Статус конверта SHALL определяться только `envelope_status` пакета; перевод документов и предупреждений в контракт — только `to_contract` / `warning_to_contract` пакета.
|
Шлюз SHALL оставить у себя обмен с ИС Сканирование (горячие папки, опрос, срок, склейку набора json в `raw/{job_id}.json` до нормализации, очистку папки) и адаптер «таблица `table_structure[i]` json → `FormCandidate`»; шаги 2–8 SHALL выполняться установленной библиотекой `arm_statements` (дистрибутив `pylib_ai_arm_statements`). Адаптер SHALL: создавать кандидата на каждую таблицу каждого успешного json; копировать шапку json (`organization`, `inn`, `units`, `date`) в шапку каждой своей таблицы как `Cell` (`text = form_name`, `confidence` ИС); передавать `label.form_name` таблицы как заголовок в `evidence` (тип — общим правилом шага 1 по словарю заголовков пакета, `type_hint(okud_text, title_text, rules)`, у OCR `okud_text = None`); строить плотную сетку по `row_index` и `column_index` ИС (пустые позиции — `null`), `Cell.ref = row:<row_index>`; `locator = file:<имя json>;table:<i>`. `value` у OCR-ячеек всегда `null`, `source = OCR`. Нарушенная структура таблицы ИС SHALL давать исключение адаптера и `TABLE_PARSE_ERROR` всей таблицы, остальные таблицы разбираются. Статус конверта SHALL определяться только `envelope_status` пакета; перевод документов и предупреждений в контракт — только `to_contract` / `warning_to_contract` пакета.
|
||||||
|
|
||||||
#### Scenario: Один json — ББ и ОФР
|
#### Scenario: Один json — ББ и ОФР
|
||||||
- **WHEN** json `aep_3.json` содержит две таблицы — «Бухгалтерский баланс» и «Отчет о финансовых результатах» — под общей шапкой
|
- **WHEN** json `aep_3.json` содержит две таблицы — «Бухгалтерский баланс» и «Отчет о финансовых результатах» — под общей шапкой
|
||||||
@ -333,3 +337,32 @@ SHALL отражать состояние.
|
|||||||
#### Scenario: Тесты на своих subject'ах
|
#### Scenario: Тесты на своих subject'ах
|
||||||
- **WHEN** тесты интеграционные (`tests/integration/`) запускаются при работающих контейнерах стенда на том же NATS
|
- **WHEN** тесты интеграционные (`tests/integration/`) запускаются при работающих контейнерах стенда на том же NATS
|
||||||
- **THEN** тесты используют уникальные subject'ы из настроек и не получают и не забирают сообщения стенда
|
- **THEN** тесты используют уникальные subject'ы из настроек и не получают и не забирают сообщения стенда
|
||||||
|
|
||||||
|
### Requirement: Локальная установка библиотеки нормализации
|
||||||
|
Окружение сервиса SHALL устанавливать `pylib_ai_arm_statements` из локального источника без обращения за ним в PyPI. `requirements.txt` SHALL фиксировать версию `0.1.1`; `make venv` SHALL исключать `pylib_ai*` из установки по этому файлу и устанавливать библиотеку из `STATEMENTS_DIR` (по умолчанию `../pylib_ai_arm_statements`). `make install` SHALL переустанавливать её в окружение backend. Сервис MUST NOT содержать копию `api/arm_statements/`.
|
||||||
|
|
||||||
|
#### Scenario: Создание окружения
|
||||||
|
- **WHEN** выполнен `make venv` при доступной локальной библиотеке версии `0.1.1`
|
||||||
|
- **THEN** в `api/.venv` установлена библиотека, импорт `arm_statements` работает без копии в проекте, пакет `pylib_ai_arm_statements` не запрашивается в PyPI
|
||||||
|
|
||||||
|
#### Scenario: Переустановка библиотеки из указанного пути
|
||||||
|
- **WHEN** выполнен `make install STATEMENTS_DIR=<локальный путь>` с доступным исходным пакетом
|
||||||
|
- **THEN** пакет установлен или переустановлен в `api/.venv`, окружение создано при его отсутствии
|
||||||
|
|
||||||
|
#### Scenario: Локальный источник недоступен
|
||||||
|
- **WHEN** выполняется `make venv` или `make install`, а `STATEMENTS_DIR` не содержит доступного устанавливаемого пакета
|
||||||
|
- **THEN** команда завершается ошибкой и не заменяет локальный источник загрузкой библиотеки из PyPI
|
||||||
|
|
||||||
|
### Requirement: Образ содержит установленную библиотеку
|
||||||
|
`make docker-build` SHALL собирать образ с библиотекой из `STATEMENTS_DIR`, переданной дополнительным контекстом сборки. Образ SHALL поддерживать импорт `arm_statements` и запуск нормализатора без доступа к каталогу исходников библиотеки на хосте во время работы.
|
||||||
|
|
||||||
|
#### Scenario: Автономный образ
|
||||||
|
- **WHEN** образ собран через `make docker-build` с локальной библиотекой версии `0.1.1`
|
||||||
|
- **THEN** в образе доступны импорт `arm_statements`, словари и версия `0.1.1`; монтирование исходников библиотеки при запуске не требуется
|
||||||
|
|
||||||
|
### Requirement: Недоступная версия библиотеки препятствует старту
|
||||||
|
Сервис MUST NOT стартовать, если версия библиотеки нормализации не определена. Ошибка SHALL указывать на установленную библиотеку и способ её установки, без инструкции синхронизации копии исходников.
|
||||||
|
|
||||||
|
#### Scenario: Версия не определена
|
||||||
|
- **WHEN** при создании нормализатора API библиотеки не возвращает версию и явная версия не задана
|
||||||
|
- **THEN** создание приложения завершается ошибкой с указанием выполнить `make install`
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user