Andrey Epifancev 561eaa5c71 docs: соглашения шаблона в CLAUDE.md и OpenSpec change slice-0-skeleton
Срез 0 (issue #1): раздел «Соглашения шаблона» (что оставлено от шаблона команды, что
вырезается, что добавляется); change openspec/changes/slice-0-skeleton — proposal, design
с таблицей «Decisions made without discussion», спеки и tasks; в openspec/config.yaml
строки с двоеточием взяты в кавычки (YAML разбирал их как словари).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-03 02:43:41 +04:00

47 lines
3.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Spec Delta: scan-emulator
## Purpose
Эмулятор ИС Сканирование для разработки и тестов: воспроизводит протокол горячих папок и формат ответов Content AI,
отдавая реальные ответы из `../fixtures/ocr` по имени файла, чтобы конвейер `scan-gateway` проверялся без доступа к
банковской системе.
## ADDED Requirements
### Requirement: Эмулятор отвечает по протоколу горячих папок
Процесс `python -m src.scan_emulator` SHALL опрашивать входящий каталог каждую секунду; для нового файла
`<uuid>_<name>.<ext>` через `SCAN_EMULATOR_DELAY` секунд (по умолчанию 2) SHALL создать `<output>/<uuid>/<uuid>.json`;
после обработки входящий файл SHALL быть переименован в `<uuid>_<name>.<ext>.done`, чтобы не обрабатываться повторно.
#### Scenario: Один файл
- **WHEN** во входящем каталоге появляется `3f1c…_aep_5.pdf`
- **THEN** через ≤ 5 с существует `Output/3f1c…/3f1c….json`, а входящий файл переименован в `…pdf.done`
### Requirement: Ответ берётся из фикстур по имени
Эмулятор SHALL искать в `SCAN_FIXTURES_DIR` файл `<name>.json`, затем `<name>*.json` (первый по алфавиту), где `<name>` —
имя входящего файла без префикса `<uuid>_` и расширения; содержимое SHALL быть записано в ответ с `file_uid = <uuid>`.
#### Scenario: Точное имя
- **WHEN** входящий файл — `…_aep_5.pdf`, в фикстурах есть `aep_5.json`
- **THEN** ответ равен `aep_5.json` с заменённым `file_uid`
#### Scenario: Префикс
- **WHEN** входящий файл — `…_aep_8.pdf`, в фикстурах есть `aep_8_form4.json`
- **THEN** ответ равен `aep_8_form4.json` с заменённым `file_uid`
### Requirement: Неизвестный файл — ошибка в формате Content AI
Если пара не найдена, эмулятор SHALL записать ответ `{"file_uid": "<uuid>", "error": {"code": "INVALID_DOCUMENT",
"message": "<имя>: нет эталонного ответа в фикстурах"}, "data_ocr": []}`.
#### Scenario: Нет пары
- **WHEN** входящий файл — `…_unknown.pdf`
- **THEN** ответ содержит `error.code = INVALID_DOCUMENT` и пустой `data_ocr`; `scan-gateway` публикует конверт с тем же кодом
### Requirement: Эмулятор запускается из того же образа
В `docs/dev/docker-compose.yml` сервис `scan-emulator` SHALL использовать образ `scan-gateway` с командой
`python -m src.scan_emulator`, общий том `hotfolder` и `../../fixtures/ocr`, смонтированный только для чтения.
#### Scenario: Compose
- **WHEN** выполнен `docker compose --profile services up -d`
- **THEN** контейнер `scan-emulator` работает, его лог сообщает каталоги и число найденных пар фикстур