163 Commits

Author SHA1 Message Date
aep
18842e0796 Merge pull request 'feat(normalizer): запятая — разделитель тысяч в суммах OCR (AURORA-1405, #35)' (#36) from feat/35-ocr-thousands into main 2026-10-15 17:37:17 +03:00
Andrey Epifancev
9dd568ce44 fix(normalizer): правило тысяч только при скобках на всю строку, спека и README (AURORA-1405, #35)
I-1: «(4,200) руб», «1,234(5,678)» и т. п. разбираются как прежде; I-2/I-3: спека и README;
M-1..M-3: docstring, комментарий регулярки, тесты крайних случаев.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 16:59:32 +04:00
Andrey Epifancev
1f308ddfe3 feat(normalizer): запятая-разделитель тысяч в суммах OCR (AURORA-1405, #35)
«4,200» в PDF — это 4200: запятые вида [+-]?[1-9]\d{0,2}(,\d{3})+ (полное совпадение, с учётом скобок)
удаляются до замены запятой на точку, verified сохраняется. Решение владельца 15.10.2026.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 16:56:58 +04:00
aep
97a910f641 Merge pull request 'openspec: архив nats-env-config (#32)' (#34) from chore/32-archive-nats-env-config into main
Reviewed-on: #34
2026-10-13 12:59:37 +03:00
Andrey Epifancev
7235669fc6 openspec: архив nats-env-config (#32)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 13:57:09 +04:00
aep
e8ae691bdf Merge pull request 'NATS: subject'ы и JWT по окружению из OpenBao (OPENBAO__NATS__*) (#32)' (#33) from feat/32-nats-env-config into main
Reviewed-on: #33
2026-10-13 12:54:55 +03:00
Andrey Epifancev
c10f927730 Правки финального ревью: умолчания subject'ов не названы фактическими
M-3: докстринги worker.py не называют умолчание фактическим subject'ом.
T7.1: выровнены переносы докстринга core/nats.py.
M-5: CLAUDE.md помечает files.tabular_parsed как умолчание.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 13:26:44 +04:00
Andrey Epifancev
0ef4a8a6bc openspec: nats-env-config — check-full зелёный, пункт 3.2 отмечен (#32)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 13:18:15 +04:00
Andrey Epifancev
cd5409be6e Тесты NATS-настроек: все ключи и пары subject, утечка секретов, strip seed, JWT в /healthcheck, лог старта (#32)
Фикс-волна minor-находок ревью (T6.1, T6.3, T2.2-аналог); tasks.md отмечен, кроме make check-full.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 12:56:27 +04:00
Andrey Epifancev
192500e9f9 NATS: подписка, публикация и /healthcheck.subjects по настройкам; интеграционные тесты на своих subject'ах (#32)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 12:19:11 +04:00
Andrey Epifancev
f1f7d784a5 NATS: subject'ы и JWT из OPENBAO__NATS__*, SecretStr, скрытие входа в ошибках (#32)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 12:06:11 +04:00
Andrey Epifancev
1579295961 openspec: change nats-env-config — subject'ы и JWT NATS по окружению из OpenBao
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:40:35 +04:00
aep
d49fa63e55 Merge pull request 'Нормализатор OCR: при конфликте label и единодушных кодов строк тип документа — по кодам (#30)' (#31) from feat/30-type-by-codes into main
Reviewed-on: #31
2026-10-09 19:08:42 +03:00
Andrey Epifancev
0847e6786c fix(normalizer): при конфликте label с единодушными кодами строк тип документа — по кодам (#30)
ИС Сканирование вернула ОФР с label «Бухгалтерский баланс» при кодах 2110…2910;
по прежнему правилу побеждал label, и документ уходил в ядро как BALANCE.
Теперь: все коды данных одной группы и противоречат label — тип по кодам,
предупреждение «тип по label (…) не совпал с кодами: взят …», needs_check;
смешанные коды — по-прежнему label. header.form_name не меняется.
Спека image-recognition-gateway, README и CLAUDE.md обновлены.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-09 20:07:25 +04:00
aep
c2a1de6a8d Merge pull request 'openspec: архив hotfolder-direct-write (#26)' (#28) from chore/26-archive-hotfolder-direct-write into main
Reviewed-on: #28
2026-10-09 16:46:09 +03:00
Andrey Epifancev
94ab9e90d1 openspec: архив hotfolder-direct-write (#26)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 17:23:21 +04:00
aep
f37a3cd706 Merge pull request 'Горячая папка: запись прямо в Input, как в старом АРМ; таймаут 20 мин (#26)' (#27) from feat/26-hotfolder-direct-write into main
Reviewed-on: #27
2026-10-09 16:22:05 +03:00
Andrey Epifancev
7d8a506f4d fix(hotfolder): ошибка открытия входящего файла не удаляет файл прошлой доставки (#26, I-1)
Открытие вынесено из блока снятия недописанного файла: при SCAN_CLEANUP=true
удаляется только файл, сбойнувший после открытия. Решения R-5…R-8 — в design.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 16:54:54 +04:00
Andrey Epifancev
3413328f02 docs: прямая запись в Input, SCAN_TMP_DIR только у эмулятора, таймаут 1200 с (#26)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 16:41:32 +04:00
Andrey Epifancev
7dc0317b99 feat(hotfolder): local тоже пишет прямо в Input; без SCAN_TMP_DIR; таймаут 1200 с (#26)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 16:34:39 +04:00
Andrey Epifancev
6870ca799a feat(smb): запись прямо в Input с перезаписью, как в старом АРМ (#26)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 16:30:31 +04:00
Andrey Epifancev
7ec3dd49fd plan: hotfolder-direct-write (#26)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 16:28:31 +04:00
Andrey Epifancev
85f4e9c847 openspec: change hotfolder-direct-write — запись прямо в Input, как в старом АРМ (#26)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 16:22:07 +04:00
aep
6da4114bde Merge pull request 'openspec: архив nats-files-subjects (#22)' (#24) from chore/22-archive-nats-files-subjects into main 2026-10-08 22:50:56 +03:00
Andrey Epifancev
89c14542bc openspec: архив nats-files-subjects (#22)
Change слит PR #23; спеки обновлены (subject'ы files.tabular_uploaded,
files.img_uploaded, files.tabular_parsed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-08 23:50:30 +04:00
aep
f69ff83d69 Merge pull request 'NATS: subject'ы как в старом АРМ — files.*_uploaded, files.tabular_parsed (#22)' (#23) from feat/22-nats-files-subjects into main
Reviewed-on: #23
2026-10-08 22:48:31 +03:00
Andrey Epifancev
6c287ef4bc nats: subject'ы как в старом АРМ — files.*_uploaded, files.tabular_parsed (#22)
Решение владельца 08.10.2026: recognition.tabular.request → files.tabular_uploaded,
recognition.image.request → files.img_uploaded, recognition.result →
files.tabular_parsed (общий subject ack и результатов; files.img_parsed не
используется). Тела сообщений, Nats-Msg-Id, queue group'ы и schema_version не
меняются. Константы api/src/contract/subjects.py, докстринги, тесты, README,
CLAUDE.md; копии схем api/contracts/ из docs/contracts/ побайтно; change
nats-files-subjects с дельтой спеки. Сквозной change — RSHB/arm-ka-docs#74.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-08 23:46:19 +04:00
aep
1e7027ba73 Merge pull request 'Логгер: вызывать setup_logger при импорте приложения (#18)' (#20) from feat/18-logger-diagnose into main
Reviewed-on: #20
2026-10-08 15:47:49 +03:00
Andrey Epifancev
3a4b8cc723 fix(logger): вызывать setup_logger при импорте приложения (#18)
setup_logger() с diagnose=False существовал, но не вызывался: работал
обработчик loguru по умолчанию (diagnose=True), и трейсбек любого
залогированного исключения содержал значения локальных переменных.
Теперь src/app.py вызывает setup_logger при импорте, как tabular-parser.

Регрессионный тест в отдельном процессе: исключение с локальной
переменной логируется с трейсбеком, но без её значения.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-08 16:41:40 +04:00
aep
e67aab35d8 Merge pull request 'Нормализатор: разлеплять склеенные строки ИС «1500\n1700» (#16, OQ-156)' (#17) from feat/16-split-merged-codes into main
Reviewed-on: #17
2026-10-08 13:54:41 +03:00
Andrey Epifancev
c81ec9a66c feat(normalizer): разлеплять склеенные строки ИС «1500\n1700» (#16, OQ-156)
ИС возвращает соседние строки формы одной строкой: в ячейке кода несколько
целых кодов через перевод строки, суммы — тоже. Раньше строка пропускалась как
нечисловой код, и в ББ РБ и Счастливочной за 1 кв. 2025 не было 1500 и 1700.

- rows.split_merged_row: N ≥ 2 целых кодов и ровно N частей в каждой непустой
  ячейке значений → N строк до классификации; наименование делится так же или
  остаётся целым; уверенность — исходной ячейки. Иначе — поведение прежнее.
- Предупреждение таблицы «строк с несколькими кодами разлеплено: N».
- Решение №36 в design.md Среза 3a (отклонение от источника), README.

Эталоны нормализатора — отдельный PR в arm-ka-fixtures; правило — §11.1 п. 4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 12:59:22 +04:00
aep
110d13121d Merge pull request 'openspec/config.yaml: источник истины DBML v5.13 → v5.17 (#13)' (#14) from feat/13-config-v517 into main
Reviewed-on: #14
2026-10-07 22:44:02 +03:00
Andrey Epifancev
f5cd47870d openspec/config.yaml: источник истины DBML v5.13 → v5.17 (#13)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 23:42:03 +04:00
aep
536dd31536 Merge pull request 'feat(config): несекретные настройки из OpenBao через OPENBAO__APP__<ИМЯ> (#11)' (#12) from feat/11-openbao-app-settings into main
Reviewed-on: #12
2026-10-07 17:42:19 +03:00
Andrey Epifancev
0ad8858d6f feat(config): несекретные настройки из OpenBao через OPENBAO__APP__<ИМЯ> (#11)
Тот же источник настроек, что в arm-core#44: приоритет обычный env -> OPENBAO__APP__* -> .env -> умолчание;
неизвестное имя — ошибка при старте; ключ APP не ломает OpenBAOSettings. Режим smb из OPENBAO__APP__
включает проверку обязательных OPENBAO__SMB__*.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EAKRDNzXtRrwmWz9z6PZu3
2026-10-07 18:35:39 +04:00
aep
6d195207d5 Merge pull request 'openspec: архив change slice-3a-ocr-normalizer' (#10) from chore/archive-slice-3a-ocr-normalizer into main
Reviewed-on: #10
2026-10-07 04:07:37 +03:00
Andrey Epifancev
98f21297bb openspec: архив change slice-3a-ocr-normalizer (2026-10-07), спеки image-recognition-gateway и scan-emulator
Ссылки README и CLAUDE.md переведены на архив.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 05:07:07 +04:00
aep
477816225b Merge pull request 'Срез 3a: горячие папки как у armka_file_worker, нормализатор OCR → statementDocument v1.2' (#8) from feat/6-slice-3a-ocr-normalizer into main
Reviewed-on: #8
2026-10-07 04:04:58 +03:00
Andrey Epifancev
1c39ca1b73 docs(scan-gateway): README и спека — запись .part по №32/№35
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 04:05:35 +04:00
Andrey Epifancev
cb8c71fc26 fix(hotfolder): повтор задания при существующем назначении не трогает .part (R-17)
LocalHotFolder.put сначала проверяет назначение: если файл во входящем каталоге уже есть, он считается доставленным,
ничего не пишется, а .part снимается только при включённой очистке. Иначе удаление старого .part подавляется (остаток
прерванной записи не роняет задание); если он остался, усечение разрешено только при st_nlink == 1, ссылка на чужой файл
не трогается и исключение поднимается как есть.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 03:44:41 +04:00
Andrey Epifancev
b411b7e128 docs(openspec): решение №35 — повтор put при существующем назначении
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 03:43:35 +04:00
Andrey Epifancev
576ce2c205 docs(scan-gateway): README и CLAUDE.md по итогам финального ревью Среза 3a
Статус при ошибочном файле набора (№28), новые предупреждения (№29, формулировка ИНН), правило Money (№30), длина дат (№31),
дубли yaml (№33), очистка удаляет всё содержимое Output/<job_id>/, процедура заполнения fsbu4 со списком тестов с пустой
редакцией; SCAN_CLEANUP и SCAN_RULES_DIR в .env.example.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 03:35:11 +04:00
Andrey Epifancev
a65ff8cf40 test: SMB-очистка и коллизии rename, проверки очистки в воркере, точные докстринги
- F-D: фейк rename бросает SMBOSError(STATUS_OBJECT_NAME_COLLISION) (и обычный FileExistsError), rmdir — STATUS_DIRECTORY_NOT_EMPTY;
  тесты validate_name, сирот .part/.done, access-denied scandir, подкаталога в Output, .part при существующем назначении,
  учётных данных во всех вызовах очистки; докстринг SmbHotFolder.put больше не противоречит сам себе (T12.5)
- F-E: тест ошибки очистки проверяет вызов очистки и ровно одну строку WARNING
- T9.4: докстринг протокола Normalizer; T13.4: устаревшие ссылки на «Task 14»; мёртвый noqa BLE001 в worker.py

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 03:35:10 +04:00
Andrey Epifancev
b956d5746f fix(hotfolder): .part создаётся заново (O_EXCL), fallback os.replace только вокруг os.link (№32)
Старый .part, оставшийся жёсткой ссылкой на опубликованный файл, больше не перезаписывается на месте; ошибка записи
поднимается как есть, а не как FileNotFoundError от os.replace; EOPNOTSUPP добавлен к списку ФС без жёстких ссылок.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 03:35:10 +04:00
Andrey Epifancev
c1288d08fb fix(normalizer): итоги финального ревью — Money, статус при ошибочном файле, пропущенные строки, длина дат, дубли yaml
- C-1 (№30): сумма с более чем двумя знаками после запятой не принимается (amount=null, string_value, is_recognized=false);
  confidence ячеек и шапки приводится к [0, 100], NaN и бесконечность дают 0
- F-A (№28): ошибочный файл набора при успешном понижает статус до needs_check
- F-B: «ИНН не распознан» только когда ИНН не извлечён, иначе «ИНН распознан неуверенно»
- №29: предупреждения «строк с нечисловым кодом пропущено: N» и «строк без кода с суммами пропущено: N»
- I-3 (№31): тексты дат длиннее 200 символов не разбираются и не проходят fix_lookalikes
- T1.3 (№33): загрузчик yaml отклоняет повторяющиеся ключи; тавтологичный тест дублей заменён настоящим
- гигиена: докстринг amounts.py описывает фактическое поведение (все точки удаляются), мёртвые noqa в ocr/__init__.py

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 03:35:10 +04:00
Andrey Epifancev
22025ecabe docs(openspec): решения №30–34 по итогам финального ревью (Money, длина дат, .part, дубли yaml, дубли кодов), уточнение №29
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 03:24:56 +04:00
Andrey Epifancev
02c6bc8762 docs(openspec): решения №28–29 — статус при ошибочном файле набора, предупреждение о пропущенных строках
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 03:06:52 +04:00
Andrey Epifancev
140ec5b713 docs(openspec): спека — schema_version результата 1.0 (№14), cleanup удаляет всё содержимое Output/<job_id>/
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 02:51:53 +04:00
Andrey Epifancev
bef8441ca8 docs(scan-gateway): README/CLAUDE.md под Срез 3a, roundtrip с документами, tasks.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 02:42:49 +04:00
Andrey Epifancev
13bd2885e5 fix(emulator): тест dot-файла различает проверку префикса, честные докстринги, сценарий появления файла (round 4)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 02:28:16 +04:00