From 716d80902d4b43f01f8f51807a6cf080eaf11b48 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Sat, 3 Oct 2026 17:53:56 +0400 Subject: [PATCH] =?UTF-8?q?chore:=20=D0=BF=D0=BB=D0=B0=D0=BD=20=D0=B8?= =?UTF-8?q?=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20SDD=20?= =?UTF-8?q?=D0=B8=D0=B7=20tasks.md=20change'=D0=B0,=20=D1=81=D0=BB=D1=83?= =?UTF-8?q?=D0=B6=D0=B5=D0=B1=D0=BD=D1=8B=D0=B5=20=D0=BA=D0=B0=D1=82=D0=B0?= =?UTF-8?q?=D0=BB=D0=BE=D0=B3=D0=B8=20=D0=B2=20.gitignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docs/superpowers/plans/2026-10-03-slice-0-skeleton*.md сгенерирован 1:1 из openspec/changes/slice-0-skeleton/tasks.md (заголовки «Task N» для скриптов subagent-driven-development, Global Constraints из спеки и CLAUDE.md). .gitignore: .codegraph/, .superpowers/, .bounded, .DS_Store. Co-Authored-By: Claude Fable 5.1 --- .gitignore | 4 +- .../plans/2026-10-03-slice-0-skeleton.md | 67 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 docs/superpowers/plans/2026-10-03-slice-0-skeleton.md diff --git a/.gitignore b/.gitignore index c09eafc..34c68f6 100644 --- a/.gitignore +++ b/.gitignore @@ -327,4 +327,6 @@ docker-compose.yml .dockerignore .vscode my_project_env -.cursorignore \ No newline at end of file +.cursorignore.codegraph/ +.superpowers/ +.bounded diff --git a/docs/superpowers/plans/2026-10-03-slice-0-skeleton.md b/docs/superpowers/plans/2026-10-03-slice-0-skeleton.md new file mode 100644 index 0000000..ce8d1a4 --- /dev/null +++ b/docs/superpowers/plans/2026-10-03-slice-0-skeleton.md @@ -0,0 +1,67 @@ +# Срез 0 — скелет tabular-parser — план исполнения (Срез 0) + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Branch:** `feat/1-slice-0-skeleton` (worktree `.wt/slice-0/tabular-parser`). **Issue:** #1. +**Spec:** `openspec/changes/slice-0-skeleton/` — proposal.md, design.md, specs/*/spec.md этого change'а. Спека — единственный источник истины при рулингах; этот план сгенерирован из её `tasks.md` 1:1 (номера в скобках — исходные номера задач tasks.md; по завершении задачи отметить её `- [x]` и в `tasks.md`). + +## Global Constraints + +- Сервис без БД и фронта (DECISION-4): видит только NATS и S3. Раскладка шаблона, команды из `api/`. +- Платформа: Python 3.11, NATS **без JetStream** (подписка queue group `tabular-parser`, ack `status = processing` до чтения S3, process-local LRU `job_id`, публикация с повторами), один бакет S3, Nexus недоступен, CI нет (`make check` / `make check-full`). +- Контракт: копии схем из `../docs/contracts/` в `api/contracts/` байт в байт; `service.name = "tabular-parser"`; результат `results/{file_id}/{job_id}/result.json`; `Nats-Msg-Id` по правилам контракта; заглушка парсера — `NOT_IMPLEMENTED`. +- Парсер — интерфейс без NATS/S3; никаких координат ячеек, букв колонок, имён листов в коде (Срез 2 — вне этого плана). +- Ошибки транспорта → конверт `status = error` (`SCHEMA_MISMATCH`, `FILE_READ_ERROR`, `UNKNOWN_ERROR`); процесс не падает. +- Линтеры: ruff (120, E,F,I,UP,B,PL) + mypy; pytest-asyncio auto; маркеры `integration`/`fixtures`. +- Язык комментариев/коммитов — русский, идентификаторы — английские; коммит заканчивается строкой `Co-Authored-By: Claude Fable 5.1 `. + +## Задачи + +### Task 1: [1.1] Удалить `web/`, `setup/.npmrc`, npm-шаги из `setup/setup.sh`, `api/alembic/`, `a + +- [ ] Удалить `web/`, `setup/.npmrc`, npm-шаги из `setup/setup.sh`, `api/alembic/`, `api/alembic.ini`, `api/src/db/`, `api/src/models/`, `api/src/repositories/`; из `.gitignore` убрать `Dockerfile`; проверка: `git status` показывает только удаления и `.gitignore`; `python -c "import src"` пока падает ожидаемо (чинится в 1.2) + +### Task 2: [1.2] `src/app.py` + +- [ ] `src/app.py`: убрать mount SPA/`os.makedirs("web")`, CORS, SMB-сессию, импорт `raisa_fastapi_protected_api`; `src/core/config.py`: убрать `DBSettings`, `SMBSettings`, оставить `MINIO`, `NATS`; добавить `ENV_FILE`, `SERVICE_NAME="tabular-parser"`, `NATS_ENABLED=true`, `WORKER_CONCURRENCY=1`, `PUBLISH_RETRIES=3`, `DONE_CACHE_SIZE=1000`; `requirements.txt` без `asyncpg`, `SQLAlchemy`, `alembic`, `smbprotocol`, `argon2-cffi`, `raisa_fastapi_protected_api`; проверка: `pip install -r requirements.txt` в чистом venv (python3.11), `python run_server.py` стартует c `.env.example`, `/healthcheck` 200 + +### Task 3: [1.3] `README.md` — описание сервиса (назначение, команды `make`, env, запуск против c + +- [ ] `README.md` — описание сервиса (назначение, команды `make`, env, запуск против compose), `CLAUDE.md` — актуализировать раздел «Соглашения шаблона» по факту вырезанного; проверка: все упомянутые файлы существуют + +### Task 4: [2.1] `api/pyproject.toml` (ruff + +- [ ] `api/pyproject.toml` (ruff: line-length 120, E,F,I,UP,B,PL; mypy с плагином pydantic), `requirements-dev.txt` = `-r requirements.txt` + ruff, mypy, pytest, pytest-asyncio, pytest-env, httpx, jsonschema; `Makefile`: `venv` (python3.11), `lint`, `test`, `test-integration`, `check`, `check-full`, `up`; проверка: `make venv && make lint` зелёные + +### Task 5: [2.2] `Dockerfile` (`python + +- [ ] `Dockerfile` (`python:3.11-slim`), `.env.example`, `.env.test`; проверка: `docker build -t tabular-parser .` успешен + +### Task 6: [3.1] `api/contracts/` — копии трёх схем + `examples/` из `../docs/contracts` + +- [ ] `api/contracts/` — копии трёх схем + `examples/` из `../docs/contracts`; `src/contract/` — pydantic-модели (`RecognitionRequest`, `RecognitionResultMessage` со статусами `processing | done | needs_check | error`, `RecognitionResult`, `OsvDocument`, `StatementDocument`, деньги как `Decimal` ↔ строка); `tests/unit/test_contract.py` — идентичность с docs (skip без docs), валидация примеров, round-trip модели → JSON → схема; проверка: тесты зелёные + +### Task 7: [4.1] `src/parser/__init__.py` + +- [ ] `src/parser/__init__.py`: протокол `Parser`, `ParseOutcome`, `NullParser` (`NOT_IMPLEMENTED`); `api/rules/README.md`; `tests/unit/test_null_parser.py`; проверка: заглушка возвращает код и сообщение, не трогая входные байты + +### Task 8: [4.2] `src/core/clients.py` + +- [ ] `src/core/clients.py`: `S3Storage.get_bytes(bucket, key)`, `put_json(bucket, key, obj)`; `src/core/nats.py`: подключение (с/без nkeys, автопереподключение), `subscribe_requests(queue="tabular-parser", cb)`, `publish(subject, payload, msg_id)` с повторами; проверка: unit-тесты с фейковым соединением; интеграционный тест подключения к compose-NATS без JetStream и получения сообщения с заголовком + +### Task 9: [4.3] `src/core/worker.py` + +- [ ] `src/core/worker.py`: `on_request(msg)`: валидация → множество `job_id` в работе/обработано (LRU) → ack `processing` → очередь; рабочая корутина: S3 get → `Parser` → S3 put результата → конверт → publish; таблица ошибок D-5; `metrics.duration_ms`; запуск/остановка в lifespan при `NATS_ENABLED`; `/healthcheck.nats`; проверка: unit-тесты с фейками — сценарии spec (ack раньше результата, повторный запрос, NOT_IMPLEMENTED, FILE_READ_ERROR, SCHEMA_MISMATCH без ack, подмена парсера → `done`, повтор публикации) + +### Task 10: [4.4] `tests/integration/test_roundtrip.py` (маркер `integration`) + +- [ ] `tests/integration/test_roundtrip.py` (маркер `integration`): положить файл в MinIO `uploads/…`, опубликовать `request-tabular.json`, собрать сообщения `recognition.result`: первое — `processing`, второе — `error NOT_IMPLEMENTED` с правильными `Nats-Msg-Id`; повторная публикация запроса даёт только ещё один ack; проверка: зелёный против compose + +### Task 11: [5.1] `make check-full` + +- [ ] `make check-full`: `make check` + `pytest -m integration` + `docker build`; проверка: зелёный против compose docs на ветке `feat/1-slice-0-skeleton` + +### Task 12: [5.2] Прогон DoD + +- [ ] Прогон DoD: `make up` → `make check-full` → ручная проверка из `docs/dev/README.md` («проверка окружения»); `openspec validate slice-0-skeleton --strict`; вывод `make check-full` — в описание PR +