I-1: ветка повторной публикации в _process_one записывает request_subject
(как первая публикация); тест test_republish_updates_request_subject.
M-1: примеры /healthcheck в README (ядро: три subject'а; tabular-parser: два).
M-3: docstring'и и логи не выдают умолчание за фактический subject.
M-5: CLAUDE.md — subject'ы задаются OPENBAO__NATS__NATS_*_SUBJECT.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Решение владельца 09.10.2026. Парсер — по-прежнему 5 мин. Note DBML
«OCR — 5 мин» не меняется до следующей версии модели (OQ-159).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
T4.1: публикатор, переводя задание в финальный error/INVALID_REQUEST, теперь в той же транзакции (под тем же
FOR UPDATE) ставит файлу текущего задания ERROR (spec primary-files «Жизненный цикл статуса файла»); файл
чужого задания не меняется. Тест test_invalid_request_marks_job_error_and_pass_continues[current|non_current];
CommittedJobs.make_file_job принимает original_name.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
- services/file_status.py: set_file_status_for_job(session, job, status, *, now, only_from=None) и пакетный
set_file_status_for_jobs для вахтёра; переход только при current_recognition_job_id = job.id, PROCESSED и
SUPERSEDED не перезаписываются (D-5, R-5).
- inbox: ack -> файл UPLOADED->PROCESSING; error -> ERROR; done/needs_check -> UPLOADED->PROCESSING (R-4: ack мог
потеряться), из PROCESSING файл ждёт цикла маппинга; inbox не читает S3 и не создаёт документы.
- вахтёр: UPDATE recognition_job ... RETURNING id и UPDATE stored_file -> ERROR в той же транзакции;
публикатор при dlq -> файл ERROR.
- удалены ResultMapper, NoopMapper, _map_result, _MapperError и параметр mapper у handle_message; app.py без mapper.
- тесты: статусы файла (ack/error/done/needs_check/без ack/timeout/dlq), чужое задание файл не трогает (Review
Focus 1), откат статуса файла вместе с транзакцией сообщения; CommittedJobs.make_file_job/add_job/file.
- tasks.md 2.2, шаги Task 4 в плане.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
Все nullable jsonb-колонки ORM (audit_event.before_value/after_value,
ex_snapshot_item.payload, recognition_job.group_schema/metrics,
osv_entry.original_values) объявлены через nullable_jsonb() =
JSONB(none_as_null=True): Python None сохраняется как SQL NULL, IS NULL
находит строку. DDL не меняется; сверка с DBML и миграции зелёные.
Обходы для не-объекта в metrics (CASE по jsonb_typeof в публикаторе,
merge_metrics в inbox) оставлены: строки до исправления и сырой SQL
могут содержать jsonb null. Тесты: SQL NULL после AuditService.record
без before/after, metrics фабрики None -> SQL NULL, повтор публикации и
слияние метрик для SQL NULL и jsonb null, перечень колонок с флагом.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- services/recognition_exchange.py: publish_pending — одно задание на короткую транзакцию
(SELECT … LIMIT 1 FOR UPDATE OF recognition_job SKIP LOCKED → публикация → UPDATE → COMMIT):
queued → published (request_msg_id = <job_id>:<attempt>, request_subject, published_at, reply_deadline —
5 мин по умолчанию, requested_at); published без ack дольше ACK_TIMEOUT → повтор с тем же Nats-Msg-Id и
attempt, metrics.republish_count (jsonb ||, прочие ключи сохраняются); после OUTBOX_MAX_REPUBLISH → dlq/NO_ACK;
запрос не собирается по контракту → error/INVALID_REQUEST; первая NatsPublishError откатывает задание и
прерывает проход; нет соединения — проход пропускается. published с прошедшим reply_deadline оставлен вахтёру.
- expire_deadlines — один UPDATE processing/published с reply_deadline < now → timeout/TIMEOUT.
- run_publisher_loop / run_watchdog_loop (30 с), ExchangeTasks: запуск в lifespan вместе с NatsConnection,
остановка до nats.stop(). audit_event не пишется (R-7).
- Тесты: интеграционные против PostgreSQL и NATS (схема запроса, повторы и dlq на инжектируемых часах, ack после
первого повтора, вахтёр, ошибка публикации, два конкурентных прохода, циклы), lifespan; фабрика CommittedJobs.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>