84 Commits

Author SHA1 Message Date
Andrey Epifancev
663ba17716 fix(parser): inn_digits склеивает только группы цифр через пробел (T7.4)
ИНН из текста ячейки колонки ИНН принимается, только если в тексте одна запись цифр:
группы, разделённые пробелом/NBSP/узким пробелом («3528 052718», «ИНН 352819549855»).
«№ 12 от 01.02.2025» и «№ 12 / 3528052718 / …» больше не дают ложный ИНН.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 14:07:33 +04:00
Andrey Epifancev
46c427e3c1 fix(parser): inn_digits извлекает ИНН из текста с обрамлением (T7.1, R-15)
Строгая detect.inn_from_cell не меняется (ей детектор отличает колонку ИНН). inn_digits — режим извлечения для ячеек
выбранной колонки: сначала строгое правило, затем для текстовых ячеек цифры всех групп склеиваются и принимаются при
длине 10/12 (без дополнения нулём). Числовые ячейки во второй шаг не попадают.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 13:50:09 +04:00
Andrey Epifancev
b8f3e32984 openspec: решение R-15 (design №25) — ИНН из текста по цифрам
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 13:46:43 +04:00
Andrey Epifancev
60671bc99d docs(plan): отметка Task 7 выполненной
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 13:46:04 +04:00
Andrey Epifancev
1f2f050838 feat(parser): нормализация сумм и ИНН (Decimal, текстовые форматы)
to_money — единственное место квантования сумм до 0.01 (ROUND_HALF_UP): число из ячейки (уже Decimal(str(value)))
без float-хвостов, текст с пробелами/NBSP/узкими пробелами, запятой, (x), U+2212, экспонентой; прочерки и пусто — None
без предупреждения; нечисловой текст, NaN/Infinity, значения вне numeric(18,2) — None с предупреждением; «-0» → 0.00.
inn_digits делегирует detect.inn_from_cell (одно правило ИНН для детектора и классификатора).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 13:45:59 +04:00
Andrey Epifancev
5a3d6f9c9e openspec: решение R-14 (design №24), уточнение R-13
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 13:41:04 +04:00
Andrey Epifancev
68c5e2cce0 fix(parser): дедлайн внутри стратегий иерархии, тесты дедлайна (T6.1, T6.5)
strategy_sums проверяет Deadline каждые DEADLINE_CHECK_EVERY = 500 шагов
внутреннего перебора поддеревьев (худший случай O(n²) завершается TIMEOUT,
а не висит); линейные стратегии — каждые 500 строк (D-8). Strategy —
Protocol (rows, deadline=None); resolve_levels передаёт дедлайн.
Тесты: истечение внутри sums, проверка перед каждой стратегией, пакинг
линейных стратегий, часы по умолчанию — time.monotonic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 13:40:20 +04:00
Andrey Epifancev
c8cdfa4de7 openspec: решение R-13 (design №23) — пустая ОСВ: hierarchy=trivial, TOTAL без сумм
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 13:33:25 +04:00
Andrey Epifancev
1eef422b6e feat(parser): каскад стратегий иерархии строк (outline → indent → account_pattern → sums)
hierarchy.py: BodyRow, Levels, стратегии outline (сдвиг к 0), indent (ранги
различных отступов — единицы alignment.indent и пробелов не смешиваются),
account_pattern (ранг кода + жирность, ASSUMPTION в docstring), sums
(жадно, без рекурсии); is_consistent, parents (по позициям и уровням,
Review Focus 3), resolve_levels: «Итого» в стратегии не передаётся и
получает уровень 0; меньше двух строк кроме «Итого» — дерево «trivial».
deadline.py: кооперативный Deadline (R-3). Unit-тесты; fixtures-тест — в
Задаче 8 (R-2). Отметки плана и tasks.md 2.3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 13:31:59 +04:00
Andrey Epifancev
8e627e80c5 fix(parser): шапка ОСВ — «за»/«валюта» в названии организации, диапазоны дат с «г.» (T5.1–T5.5, T5.7)
- T5.1: организация исключается только по структурным меткам (лист, счёт, тип данных, параметры, субконто),
  строка периода выбирается по опознанному словарём периоду, метка валюты — только с двоеточием
- T5.2: конец периода — самое короткое начало, которое узнаёт словарь; диапазон «01.01.2025 г. - 31.03.2025 г.» цел
- T5.3: граница по цифрам в правиле счёта из имени файла
- T5.4: тест has_inn для варианта 2 (правило оставлено); T5.5: период только датами -> "" + предупреждение
- T5.7: тест обязательного ключа periods.end

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 13:19:18 +04:00
Andrey Epifancev
83dd241a00 feat(parser): шапка ОСВ и схема группировок (§1.1, §1.5)
- header.py: parse_doc_header (организация, счёт, период, data_type, валюта, вариант шапки,
  предупреждения на русском) и build_group_schema (вариант 1 — метки в text_col, вариант 2 —
  «субконто: …»); has_inn по ячейке ИНН в строке метки (отдельной или в тексте метки)
- periods.yaml: end — конец текста периода («г.», «год»); PeriodRules.end
- линтер координат: Literal[1, 2] не считается индексацией ячейки
- fixtures-тест на 66 файлах: счёт по имени файла одним правилом без исключений

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 13:12:20 +04:00
Andrey Epifancev
5868b348a2 openspec: решение R-12 (design №22) — группы заголовка ОСВ: обороты и конец обязательны
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 13:03:55 +04:00
Andrey Epifancev
0015532019 fix(parser): детектор заголовка — обязательны обороты и конец, ИНН без ведущего нуля (T4.1–T4.4, T4.6)
- T4.1 (R-12): строка групп обязана содержать «обороты» и «сальдо на конец»; строка
  только с «началом» и «концом» (преамбула) пропускается, нет подходящей — InvalidFormatError
  с недостающими группами лучшего кандидата.
- T4.2: сторона в заголовке в одну строку — после пунктуации («Сальдо на начало, Дт», «(Кт)»).
- T4.3: inn_from_cell — общий хелпер ИНН (10/12 цифр); число из 9/11 цифр дополняется
  ведущим нулём; переиспользуется классификатором (Task 8).
- T4.4: колонка ИНН по значениям — не меньше INN_MIN_VALUES = 3 значений-ИНН.
- T4.6: у слитого (в том числе только по вертикали) названия группы поиск подзаголовков
  ограничен его диапазоном.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 13:03:15 +04:00
Andrey Epifancev
a833945669 feat(parser): детекторы листов ОСВ, заголовка таблицы и колонок по содержимому
detect.py: classify_sheet (ОСВ / форма ББ-ОФР / прочее по словарю), find_table_header
(строка с ≥ 2 группами сумм, «Дебет/Кредит» под группой в пределах merged-диапазона
или до следующей группы, заголовок в 1–4 строки, в т.ч. «Нач. сальдо Дт» в одной
ячейке; без «начала»; свёрнутое сальдо в *_debit + collapsed; свёрнутые «Обороты» и
половинчатая пара Дт/Кт — InvalidFormatError с названием группы), text_col, inn_col
(заголовок «ИНН» или ≥ 80 % значений из 10/12 цифр), right_edge, extra_cols,
group_label_rows, first_data_row, is_header_repeat (две группы или копия строки блока).

Pattern.search_normalized — ячейка нормализуется один раз (T3.6). osv_groups: известные
группировки OTHER перечислены явно, чтобы строка-метка «Основные средства» в
неслитом заголовке была частью блока. Хелпер тестов gridbuilder (Sheet из «картинки»).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 12:54:11 +04:00
Andrey Epifancev
fcd609c633 feat(rules): словари ОСВ (заголовки, группировки, периоды, типы данных) и загрузчик
Словари api/rules/{osv_headers,osv_groups,periods,data_types}.yaml и src/parser/rules.py
(normalize_text, Pattern, load_rules, pydantic-валидация с RuntimeError по файлу и ключу,
currency_aliases по R-6). AST-линтер координат tests/unit/parser/test_no_coordinates.py
перенесён из Task 12 (R-7, правила R-4/R-5). Тест формулировок реальных ОСВ.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 12:28:46 +04:00
Andrey Epifancev
c6a768dc70 fix(parser): ячейки из одних пробелов не хранятся в Sheet.cells (T2.1)
make_cell возвращает None для строки, у которой strip() пуст (пробелы, NBSP и
прочие Unicode-пробелы): «пробелы = пусто» на уровне хранения, sheet.cell даёт
EMPTY_CELL. Тесты: пробельные ячейки xlsx/xlsb отсутствуют в cells, строка из
пробелов пуста, merged-диапазон с пробельным origin даёт "".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 12:16:28 +04:00
Andrey Epifancev
ed401a00a3 openspec: решение R-11 (design №21) — расхождения D-1/tasks 1.3 правятся в Task 13
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 12:15:33 +04:00
Andrey Epifancev
b5a3b480b2 feat(parser): модель листа Sheet и читатели xlsx/xls/xlsb
grid.py: Cell, MergedRange, Sheet (1-based, только непустые ячейки, ленивые
индексы строк и merged; диапазоны больше 10 000 ячеек проверяются перебором),
column_letter для диагностики. errors.py: ParserError и коды контракта.
readers: read_book определяет формат по сигнатуре (zip → XLSX/XLSB по
xl/workbook.bin, OLE2 → XLS), предупреждает о несовпадении с file_type;
ошибки библиотек → UnreadableError одной строкой. Числа — Decimal(str(value)),
bool отдельно, даты как datetime; xlsb без outline/merged с предупреждением.
Тесты: синтетическая книга openpyxl, подмена file_type, мусор/обрезанные
файлы, xlsb через подменённый pyxlsb; 66 реальных ОСВ читаются < 5 с с
outline и merged; xls «62 за 3 квартал 2024»: строка 15 — outline 3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 12:11:16 +04:00
Andrey Epifancev
38386b53a2 test: доступ к ../fixtures (ARM_KA_FIXTURES), параметризация по 66 ОСВ; зависимости openpyxl/xlrd/pyxlsb
- requirements: openpyxl==3.1.5, pyxlsb==1.0.10, xlrd==2.0.2, et_xmlfile==2.0.0 (транзитивная)
- tests/fixtures_helpers.py, conftest: фикстура fixtures_dir, параметризация osv_file/synthetic_file, skip маркера fixtures
- pyproject: mypy ignore_missing_imports для openpyxl/xlrd/pyxlsb, disallow_untyped_defs для src.parser.*

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 12:02:40 +04:00
Andrey Epifancev
777d4aa850 contract: needs_check-пример по docs (строка 3 CURRENCY, уровень 2), README v1.1
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 11:59:55 +04:00
Andrey Epifancev
947d2a6a51 contract: v1.1 — OsvRow.extra, CONTRACT_VERSION 1.1, копия схемы
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 11:57:22 +04:00
Andrey Epifancev
f03bfca92d openspec: решения контроллера R-1…R-10 (design №11–20) по pre-flight плана Среза 2a
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 11:54:00 +04:00
Andrey Epifancev
b34e113824 chore: план исполнения Среза 2a (парсер ОСВ, 14 задач)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 11:50:38 +04:00
Andrey Epifancev
6b37a88f26 openspec: уточнения D-4 и сценария пустой ОСВ
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 11:42:51 +04:00
Andrey Epifancev
a6fd2d0535 OpenSpec: change slice-2a-osv-parser (парсер ОСВ §1 — спека)
proposal, design (D-1…D-10), спеки osv-parsing (новая) и tabular-recognition-service (MODIFIED «Парсер — заменяемый
интерфейс»), tasks (13 задач). Решение владельца 05.10.2026: подсрез 2a — только парсер ОСВ.

Issue: RSHB/arm-tabular-parser#5

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 11:41:52 +04:00
aep
277e01d205 Merge pull request 'chore(openspec): архив change slice-0-skeleton' (#4) from chore/archive-slice-0-skeleton into main
Reviewed-on: #4
2026-10-04 18:48:50 +03:00
Andrey Epifancev
6bb111db38 chore(openspec): архив change slice-0-skeleton
Срез 0 реализован и влит (PR #3), change перенесён в openspec/changes/archive, спеки — в openspec/specs.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-04 19:44:42 +04:00
aep
e966ce46bb Merge pull request 'Срез 0: скелет tabular-parser — без фронта и БД, воркер NATS без JetStream, парсер-заглушка, контракт v1.0' (#3) from feat/1-slice-0-skeleton into main
Reviewed-on: #3
2026-10-04 18:41:00 +03:00
Andrey Epifancev
6ae072e502 docs: решения R-36..R-40 (финальный фикс-раунд) в design.md
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:50:22 +04:00
Andrey Epifancev
479a76f81b test: старт с минимальным окружением и страж «без БД и фронта» (M-8)
- test_app: приложение с Settings только из MinIO, адреса NATS и DEBUG
  стартует, /healthcheck отвечает 200 с uptime, version, nats.
- test_layout: в requirements.txt нет asyncpg, SQLAlchemy, alembic,
  smbprotocol, argon2-cffi, raisa_fastapi_protected_api; нет каталогов web/,
  api/alembic/, api/src/{db,models,repositories}/.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:48:34 +04:00
Andrey Epifancev
8685441fcd fix: настройки — SERVICE_NAME только tabular-parser, PUBLISH_RETRIES ≥ 0 (M-1, M-3, M-4, M-5)
- SERVICE_NAME: Literal["tabular-parser"] (R-35); в config.py, .env.example,
  README и CLAUDE.md исправлено «имя queue group» — queue group задаёт
  константа REQUEST_QUEUE_GROUP в core/nats.py.
- PUBLISH_RETRIES: NonNegativeInt — 0 означает одну попытку без повторов,
  как и принимает NatsConnection.
- Удалён неиспользуемый модульный settings = get_settings() из config.py.
- pyproject.toml: убран override mypy для raisa_fastapi_protected_api
  (зависимость удалена D-1).
- tests/conftest.py: фабрика minimal_settings (Settings из временного .env с
  минимальным окружением, окружение процесса скрыто); test_config.py —
  умолчания при минимальном окружении (M-8), PUBLISH_RETRIES=0/-1,
  SERVICE_NAME≠tabular-parser.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:48:34 +04:00
Andrey Epifancev
bf2f60b3b5 fix: NATS — отказ в правах логируется отдельно; drain ограничен 10 с (I-3, M-7)
nats-py 2.14 при Permissions Violation не закрывает соединение и не роняет
subscribe/flush/publish, а только вызывает error_cb. Раньше это логировалось
как «Нет связи с NATS, повторяем подключение» с лимитом раз в минуту. Теперь
_on_error распознаёт «permissions violation» и пишет error
error_category=nats_permission с subject, каждый раз и без серии ошибок
подключения. Исправлены ложные утверждения docstring («ошибки прав
проявляются сразу»).

connect получает drain_timeout=DRAIN_TIMEOUT (10 с вместо 30 с nats-py):
STOP_TIMEOUT воркера + drain укладываются в 30 с платформы.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:46:33 +04:00
Andrey Epifancev
c9cdf7592d docs: спека — когда SCHEMA_MISMATCH не публикуется; nats = off в proposal (I-2, M-2)
Требование «Ошибки транспорта превращаются в результат» приведено к коду:
SCHEMA_MISMATCH публикуется, если читаемы job_id, file_id и attempt и job_id
ещё не известен; иначе — лог (error/warning) без ack и результата. Добавлены
два сценария (их покрывают test_unreadable_request_is_logged_and_dropped и
test_malformed_request_for_{job_in_progress,done_job}_is_dropped).
В proposal.md поле healthcheck nats — ok/down/off.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:45:03 +04:00
Andrey Epifancev
30c3e8281a fix: .dockerignore — в образ не попадают api/.env, api/.venv, кэши и тесты (I-1)
Строка .dockerignore убрана из .gitignore (R-34 отменяет R-11). Образ
собирается `make check-full` из рабочего дерева: раньше в /app/api были
.env с паролем MinIO и .venv (175 МБ), теперь только код, контракты,
правила и requirements (264 КБ).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:44:27 +04:00
Andrey Epifancev
ba4dc41b9e docs: решения R-34 (отмена R-11), R-35 в design.md
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:43:00 +04:00
Andrey Epifancev
71e79670c0 docs: предложение P-4 (порт tabular-parser в docs/dev/README.md)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:35:04 +04:00
Andrey Epifancev
a6da24ba67 chore: отметка 5.2 — прогон DoD пройден (make check-full, ручная проверка, openspec validate)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:33:45 +04:00
Andrey Epifancev
54197a07db docs: README — адрес по умолчанию 0.0.0.0, а .env.example сужает до 127.0.0.1
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:33:45 +04:00
Andrey Epifancev
1bbcdc433e chore: отметка 5.1 — make check-full зелёный
Два подряд прогона: ruff/mypy чисто, unit 247 passed, integration 8 passed,
образ tabular-parser собран.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:31:05 +04:00
Andrey Epifancev
e0b2aaca9a docs: оговорка про queue group в интеграционных тестах, правка CLAUDE.md (T10.3, T3.3)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:29:28 +04:00
Andrey Epifancev
67a4311150 docs: докстринги контракта с точки зрения tabular-parser, паритет subjects с arm-core (T6.1-T6.3)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:29:28 +04:00
Andrey Epifancev
6491fdd538 test: проверка остановки воркера по снятым задачам и устойчивый teardown uploads (T10.1, T10.2)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:29:28 +04:00
Andrey Epifancev
5c96189146 docs: решения R-29..R-33 (интеграционный тест 4.4) в design.md
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:27:30 +04:00
Andrey Epifancev
a62d2e24b1 test: интеграционный round-trip сервиса против compose-NATS и MinIO (задача 4.4)
Приложение поднимается в процессе теста через lifespan с NATS_ENABLED=True; тест в роли ядра кладёт исходник в
uploads/, публикует запрос и собирает recognition.result по своему job_id: ack processing, затем error
NOT_IMPLEMENTED с правильными Nats-Msg-Id и валидные по схеме конверты; повтор запроса — только ещё один ack
(второго результата нет в окне тишины QUIET_WINDOW). Плюс сценарии spec: нет объекта в S3 -> FILE_READ_ERROR и
сервис работает дальше; schema_version 2.0 -> один SCHEMA_MISMATCH без ack.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:23:35 +04:00
Andrey Epifancev
c16a7f6bf6 docs: решения R-27, R-28 (фикс-раунд задачи 4.3) в design.md
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:19:59 +04:00
Andrey Epifancev
b7d4f0c17a test, docs: порядок старта и проверка бакета в тестах приложения; README/CLAUDE.md без устаревших «добавляется задачей», spec без номера рулинга
T9.2: события старта worker.start → nats.start; _connect_s3 — info/warning/error по ответу проверки бакета, клиент
остаётся. T9.3: spec без «R-17». T9.4: README и CLAUDE.md описывают уже существующие файлы без отсылок к будущим задачам.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:18:09 +04:00
Andrey Epifancev
18276e607e fix: воркер — задание не теряется молча при остановке во время ack, невалидный дубль job_id не публикует SCHEMA_MISMATCH
I9.1: после ack повторная проверка приёма — warning error_category=shutdown, job_id снимается из «в работе».
T9.7: невалидное тело с job_id в работе/обработанным — warning и сброс (msg-id настоящего результата не занимается).
T9.5: error.message исхода парсера — одной строкой, ≤ 1000 символов. T9.6: docstring stop() про to_thread.
T9.1: тест конкуренции без опроса со sleep.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:17:11 +04:00
Andrey Epifancev
82756b8c97 docs: D-6 — значение nats=off в healthcheck (R-17)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:15:53 +04:00
Andrey Epifancev
e2d31b894c docs: решения R-18..R-26 (воркер, задача 4.3) в design.md
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:10:59 +04:00
Andrey Epifancev
cfba21b615 docs: предложения P-1–P-3 по контракту из задачи 4.3; отметки Task 9 / 4.3
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 03:09:06 +04:00