124 Commits

Author SHA1 Message Date
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
Andrey Epifancev
e3353242bd fix(emulator): единственный refresh индекса за проход, реальный тест появления каталога, dot-файл в skip-тесте (round 3)
- T14.1: процесс_once() без refresh если индекс передан; run() refresh перед вызовом, не после
- T14.2a: спай на build_index — не вызывается повторно при неизменных фикстурах
- T14.2b: реальный тест файла, появляющегося на проходе 2: ровно 2 build_index всего
- T14.2c: добавлен dot-файл `.{uuid}.pdf.part` в skip-тест
- Мутационные тесты падают при удалении проверок (не коммичены)
- Typo: «фиксутрах» → «фикстурах»
- 915 тестов проходят, make check зелёный

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 02:21:42 +04:00
Andrey Epifancev
793516fa61 fix(emulator): тесты неперестроения индекса, единственный refresh за проход, различающий тест skip-списка и верхний регистр (T14.2, T14.4)
T14.2(a): Добавлен тест с шпионом на build_index, проверяющий что индекс не пересчитывается повторно на каждом проходе при неизменных фикстурах. 5 проходов — ровно 1 вызов build_index (при инициализации run), остальные используют refresh.

T14.2(b): Добавлен тест корректной обработки появления каталога фикстур после стартапа — run не выбрасывает исключение и может использовать фикстуры после их создания.

T14.1 remainder (double refresh): Исправлено поведение process_once: если index=None, то build_index один раз; если index передан, то только refresh. Обновлена docstring процесса.

T14.2(c): Добавлен мутационный тест test_skip_suffixes_not_logged_as_regex_mismatch, проверяющий что файлы с _SKIP_SUFFIXES пропускаются молча и НЕ логируются как не совпадающие с шаблоном.

T14.4: Переписан test_uppercase_extension_accepted — теперь пишет файл напрямую .PDF и проверяет нормализацию в .pdf.done, вместо использования _drop которая нормализует расширение.

Дополнительно:
- Обновлена docstring run() — точное описание: один refresh в конце каждого прохода
- Удалено "(Review Focus 5)" из docstring test_ignores_part_tmp_done
- Добавлен @pytest.mark.skipif для chmod теста при запуске от root

915 тестов пройдено, 10 деселектировано (10 избранных тестов требуют fixtures).
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 02:13:23 +04:00
Andrey Epifancev
31e05955ae fix(emulator): индекс не пересчитывается на каждом проходе, устойчивость к нечитаемому файлу, тесты (T14.1–T14.4)
T14.1: run() ВСЕГДА строит индекс один раз (даже если fixtures_dir отсутствует → пустой индекс), обновляет через refresh() на каждом проходе. process_once() больше не пересчитывает при None, берёт переданный индекс.

T14.3: OSError при чтении входящего файла логируется одной строкой, проход продолжается со следующего файла.

T14.4: Лог сообщений об ошибке использует "по умолчанию" вместо `default`; исправлена опечатка "фиксутрах" → "фикстурах"; удалено "(Review Focus 5)" из docstring модуля.

Новые тесты: test_upload_file_read_error_continues (T14.3), test_uppercase_extension_accepted (M-4), test_ignores_part_tmp_done_robust (T14.2c).

Все 912 тестов зелёные.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 02:02:55 +04:00
Andrey Epifancev
bb56226177 feat(emulator): пара фикстур по sha256 содержимого, SCAN_EMULATOR_DEFAULT, входящий <uuid>.<ext> (D-3)
- Добавлена FixtureIndex с индексированием по sha256 содержимого файлов (не-JSON)
- build_index() строит индекс один раз, refresh() обновляет только при изменении списка файлов
- resolve_stem() находит основу имени по хешу, при промахе возвращает default или (None, "none")
- process_once() принимает параметр index и default, работает с файлами <uuid>.<ext>
- Пропускаются dot-файлы, *.part, *.tmp, *.done (Review Focus 5)
- Сообщение об ошибке: "{sha256[:12]}: нет пары по содержимому в фикстурах"
- EmulatorSettings.default = "" для SCAN_EMULATOR_DEFAULT
- Логирование источника пары: hash / default / none
- Все 909 тестов зелёные, включая 54 новых и переписанных тестов эмулятора

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 01:53:22 +04:00
Andrey Epifancev
a12a603657 docs(openspec): решение №27 — при выключенной очистке сирот .part не логируем
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 01:45:41 +04:00
Andrey Epifancev
c1782b9524 feat(worker): очистка горячей папки под SCAN_CLEANUP, RECOGNITION_FAILED без расширения, OcrNormalizer в lifespan (D-2, D-4)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 01:36:28 +04:00
Andrey Epifancev
c00823c673 feat(hotfolder): SMB — rename без замены и cleanup под флагом (D-1, D-2) 2026-10-07 01:21:51 +04:00
Andrey Epifancev
5c2d89bef3 fix(hotfolder): пустой тест, неоспоримая публикация при сбое удаления .part, validate_name в cleanup (T11.1, T11.2, T11.4)
- T11.1: добавлен test_keeps_part_file_on_failure_when_cleanup_disabled (cleanup=False);
  переименован test_cleanup_failure_does_not_mask_original_error (cleanup=True).
- T11.2 (R-8): завершающий part.unlink после успешного link обёрнут в contextlib.suppress(OSError);
  файл уже доставлен, ошибка удаления .part её не отменяет.
  Добавлен test_successful_put_despite_final_unlink_failure: успешный link,
  затем PermissionError в unlink → put НЕ падает, целевой файл на месте.
- T11.4: cleanup вызывает validate_name(name) перед удалениями (защита от выхода за пределы).
  Добавлен test_rejects_unsafe_names в TestCleanup.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 01:09:29 +04:00
Andrey Epifancev
6b2087f57f docs(openspec): решение №26 — снятие .part при публикации не зависит от SCAN_CLEANUP
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 01:08:40 +04:00
Andrey Epifancev
f7ce9f4cdc feat(hotfolder): имя <job_id>.<ext>, запись без замены, cleanup под SCAN_CLEANUP (D-1, D-2)
- inbox_name: возвращает <job_id>.<ext> (суффикс в нижнем регистре, 1–16 символов [0-9a-z])
- put: атомарная запись через os.link (без замены), запасной путь os.replace при EPERM/EXDEV/ENOTSUP
- cleanup: удаляет ответ, входящий файл, временные файлы при флаге cleanup_enabled
- LocalHotFolder: параметр cleanup: bool = False, атрибут cleanup_enabled
- SmbHotFolder: параметр cleanup: bool = False (заглушка, логика в Task 12)
- create_hotfolder: передаёт cleanup=settings.SCAN_CLEANUP обоим конструкторам
- SpyHotFolder: метод cleanup для шпионажа за очисткой
- Удалены: MAX_PART_NAME_BYTES, _fit_name, _MAX_EXTENSION_CHARS, _utf8_len (имя всегда короткое)
- Тесты: TestInboxName с новым форматом, TestPutWithoutReplace (без замены),
  TestCleanup (включена/выключена), cleanup_enabled в фабрике
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 01:01:09 +04:00
Andrey Epifancev
ebbeff58bd test(normalizer): golden на реальных ответах ИС, make golden-update (D-8)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 00:47:42 +04:00
Andrey Epifancev
2a7ceca334 feat(normalizer): OcrNormalizer — документы из успешных файлов, статусы done/needs_check/error (D-6)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 00:42:44 +04:00
Andrey Epifancev
8ebf572a22 fix(normalizer): values по числу колонок, предупреждения редакций и колонок (T8.1–T8.6)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 00:37:30 +04:00
Andrey Epifancev
37b36047fe docs(openspec): решения №21–25 (Task 8: values по колонкам, лукалайки только для дат, пустая редакция, form_name)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 00:36:20 +04:00
Andrey Epifancev
80622ed331 feat(normalizer): сборка statementDocument из таблицы OCR — тип, колонки, строки, редакции (D-6, D-7)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 00:30:22 +04:00
Andrey Epifancev
6882493d98 feat(normalizer): шапка документа из data_ocr — ИНН, единицы, дата отчёта (§11.1 п. 8)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 00:25:48 +04:00
Andrey Epifancev
462ea9ee32 feat(normalizer): строки таблицы OCR — шапки, классы строк, тип по кодам (§11.1 п. 3–5)
Перенос _classify_row, _parse_table_rows, _synthetic_header_cells, _resolve_table_type
из reference-old-arm с адаптацией к новой архитектуре:
- Cell dataclass вместо dict
- ParsedTable вместо list возврата
- Fallback для row_index если не int
- Безопасная обработка пустых кодов в table_type_by_codes

14 тестов пройдено (2 на реальных данных fixtures).

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 00:21:20 +04:00
Andrey Epifancev
81081a90c7 docs(openspec): решения №17–20 без обсуждения (Срез 3a, Task 1–5)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 00:16:38 +04:00
Andrey Epifancev
0123dc0067 feat(normalizer): раскладка колонок OCR — шапка «Код» и вывод по данным (§11.1 п. 3)
Перенос `_build_layout`, `_infer_layout`, `_cells_by_index`, `_cell_value` из старого ядра.
- Cell dataclass (frozen): значение и уверенность из ячейки OCR
- build_layout: раскладка из строки с ячейкой «Код…» (заголовок)
- infer_layout: раскладка из строк данных по кодам (когда заголовка нет)
- Справочник кодов приходит параметром, ячейки — Cell вместо словарей

R-1 (design #18): тест test_aep3_like_rows_without_header исправлен:
- столбец 5 содержит только мусор (пусто, ':', '+ :') → не входит в value_idxs
- столбец 4 содержит суммы ('3', '5 678') не реже мусора ('--') → входит
- замена assertion на layout.value_idxs == (2, 4) вместо ошибочного условия

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 00:15:13 +04:00
Andrey Epifancev
60092b8293 feat(normalizer): разбор сумм OCR — перенос _parse_amount (§11.1 п. 7)
Переносим функции парсинга сумм и проверки пустоты из старого ядра:
замена запятой, удаление пробелов, извлечение круглых скобок (отрицательное),
множественные точки как разделители тысяч. Отличие: verified вычисляется
ДО постановки минуса (решение №13 design.md), чтобы не отмечать суммы
в скобках как неверифицированные.
2026-10-07 00:10:20 +04:00
Andrey Epifancev
5f56f62dbb feat(normalizer): разбор дат из OCR — дословный перенос date_utils старого ядра (§11.1 п. 2)
Портирован модуль date_utils.py из DKB_ARMKA с перечисленными в §11.1 правками:
- удалены _LOOKALIKES, _LOOKALIKE_CHARS, _NEAR_DIGIT, _normalize (перенесены в text.fix_lookalikes)
- переименована _parse_date в parse_date с новой сигнатурой (value: object -> date | None)
- обновлены аннотации типов: Optional[...] -> ... | None
- добавлена аннотация для _PATTERNS: list[tuple[re.Pattern[str], Callable[[re.Match[str]], date | None]]]
- добавлены noqa/type: ignore комментарии для прохода линтеров

Тесты: 35 тестов пройдены (парсинг дат в текстовых и числовых формах, отклонение названий организаций).

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 00:06:14 +04:00
Andrey Epifancev
746d993077 fix(normalizer): замена неразрывного пробела в fix_lookalikes, тест
Исправлена строка 26 в fix_lookalikes: текст.replace("\xa0", " ") для
корректной замены неразрывного пробела (U+00A0) на обычный пробел (U+0020),
как в источнике date_utils._normalize.

Добавлен тест test_nbsp_replacement для проверки замены NBSP с таблицей
двойников и без неё.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-07 00:00:31 +04:00
Andrey Epifancev
cea8dfe485 feat(normalizer): очистка OCR-текста — двойники, разделитель клеток, clean_value (§11.1 п. 1, 6)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-06 23:56:16 +04:00
Andrey Epifancev
ecdf9a4e13 fix(normalizer): опечатка кода 1220 в справочнике 66n, тест данных редакции
I-1: Исправлена опечатка в api/rules/statement_lines.yaml код 1220:
- было: 'ценностями' (неправильный падеж)
- стало: 'ценностям' (правильный падеж, соответствует брифу)

I-2: Добавлен тест test_66n_edition_data_integrity() в TestRealRules:
- проверяет точное количество кодов в редакции 66n (63)
- валидирует специфические коды из брифа: 1220 (опечатка), 1105, 2411, 2412
- тест фиксирует данные редакции 66n, предотвращает проскальзывание опечаток

Результат: 760 тестов пройдено (749 + 11 новых), lint чист.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-06 23:44:44 +04:00
Andrey Epifancev
393d65208f feat(normalizer): справочники yaml с редакциями форм, загрузчик правил, SCAN_CLEANUP/SCAN_RULES_DIR (D-7)
Справочники нормализатора OCR:
- api/rules/statement_lines.yaml: редакции форм ББ/ОФР (66n до 2024-12-31, fsbu4 с 2025-01-01)
- api/rules/ocr_lookalikes.yaml: замены букв на цифры (из date_utils._LOOKALIKES)
- api/rules/statement_labels.yaml: подстроки label → тип документа (BALANCE/INCOME)

Модуль rules.py:
- Edition: редакция с интервалом дат и таблицей кодов → наименований
- OcrRules: все справочники + методы edition_for(), edition_by_codes(), known_codes(), editions_with()
- load_rules(): загрузчик с валидацией (коды 4–5 цифр, двойники 1→1, файлы обязательны)

Настройки:
- SCAN_CLEANUP: удаление файлов из горячей папки (по умолчанию false)
- SCAN_RULES_DIR: путь к справочникам (по умолчанию 'rules')

TDD: 10 тестов (TestRealRules, TestEditionChoice, TestValidation, test_settings_defaults)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-06 23:33:54 +04:00
Andrey Epifancev
533e5a2a4a Merge remote-tracking branch 'origin/main' into feat/6-slice-3a-ocr-normalizer 2026-10-06 23:27:43 +04:00
Andrey Epifancev
86fa779c0c openspec/plan: Срез 3a приведён к DBML и 2b — повтор кода (№15), string_value только для нечисла (№16)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-06 23:27:42 +04:00
aep
7653860bb2 Merge pull request 'chore(contract): копия docs/contracts после M-12 ($comment, примеры)' (#7) from fix/contract-v1-2-examples into main
Reviewed-on: #7
2026-10-06 22:21:40 +03:00
Andrey Epifancev
55c017e819 chore(contract): копия docs/contracts — $comment без «1.1», пример Excel done, OCR-пример без checks, описание мягких нарушений (M-12, OQ-138)
Refs RSHB/arm-tabular-parser#20

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EAKRDNzXtRrwmWz9z6PZu3
2026-10-06 23:17:33 +04:00
Andrey Epifancev
b1da9b8774 plan: Срез 3a — Task 0 выполнена (main с v1.2 влит, 749 passed), OQ с 144, CONTRACT_VERSION 1.0 (решение №14)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-06 22:48:40 +04:00
Andrey Epifancev
3bc01e5e23 Merge remote-tracking branch 'origin/main' into feat/6-slice-3a-ocr-normalizer 2026-10-06 22:46:47 +04:00
aep
d13c65d172 Merge pull request 'chore(contract): копия схемы v1.2 (без логики)' (#5) from chore/contract-v1-2 into main
Reviewed-on: #5
2026-10-06 21:43:48 +03:00
Andrey Epifancev
ec916aee3f plan: Срез 3a — план реализации (18 задач), решение №13 в design.md
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-06 19:19:24 +04:00
Andrey Epifancev
0894d2b89b openspec: решение №12 (скобка как }) — в открытые вопросы, follow-up в docs OQ (решение владельца)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-06 18:59:07 +04:00
Andrey Epifancev
a15fe65d52 openspec: спека Среза 3a — горячие папки как у armka_file_worker, нормализатор OCR → statementDocument v1.2 (#6)
proposal, design (D-1…D-9, решения без обсуждения №1–12), дельты спек image-recognition-gateway
(папки, очистка под флагом, нормализация, справочники с редакциями, статусы) и scan-emulator (пара по sha256,
набор по умолчанию). tasks.md заполняется планом.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-06 18:39:52 +04:00
Andrey Epifancev
e2f1bb5f4a chore(contract): копия схемы v1.2 и модели (DISCLOSURE, checks, границы периода), без изменения логики
Refs RSHB/arm-tabular-parser#14

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
2026-10-06 14:30:44 +04:00
aep
dffc18a2f1 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:43 +03:00
Andrey Epifancev
7cec4596d9 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:47 +04:00
aep
8bb10949ec Merge pull request 'Срез 0: скелет scan-gateway — без фронта и БД, горячие папки local/smb, воркер NATS без JetStream, эмулятор ИС Сканирование' (#3) from feat/1-slice-0-skeleton into main
Reviewed-on: #3
2026-10-04 18:41:18 +03:00