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

3.4 KiB
Raw Blame History

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 работает, его лог сообщает каталоги и число найденных пар фикстур