Единая нормализация ББ/ОФР, ядро — часть А: DBML v5.19, очистка форм, агрегат по коду, правка формы, контракт 2.0 (arm-ka-docs#116) #129

Merged
aep merged 20 commits from feat/126-normalization-core-a into main 2026-10-18 18:44:13 +03:00
Owner

Закрывает часть А плана 3 единой нормализации ББ/ОФР (arm-ka-docs#116). Closes #126.

Слить после docs #117. На контур — только вместе с частью Б и фронтом (план 6). До части Б ядро не принимает результаты 2.0 на маппинг и не пишет document_issue §7. Change unified-normalization-core-a архивировать только вместе с core-b (R-7).

Что сделано

  • A0: change OpenSpec unified-normalization-core-a.
  • A1–A2: схема DBML v5.19, миграция 0007_dbml_v5_19 (upgrade с заполнением, downgrade с отказами и журналом потерь).
  • A3: crm_id ГСК/ГСЗ (409 CRM_ID_EXISTS, аудит GROUP_CHANGE).
  • A4: api/scripts/purge_statements.py (очистка форм перед выкладкой; отказ только при VERIFIED/ARCHIVED со снимком ЕХ).
  • A5: копии контракта обоих MAJOR, модели v2.0, приём конвертов 1.x/2.0, JobBrief.warnings структурами.
  • A6–A7: словарь имён с синонимами, совпадение наименований, агрегат формы по коду.
  • A8: ответ GET …/statement и DocumentOut.issues по v5.19.
  • A9: маппер 1.x с полями v5.19, file_ordinal, вторая форма, MAPPING_WARNING.
  • A10: чистые функции условия RECOGNIZED для 2.0 (подключаются в части Б).
  • A11: порядок 409 при подтверждении формы.
  • A12–A13: PATCH …/statement (ячейки, колонки, шапка, строки).

make check-full

Exit 0: ruff и mypy чистые; unit 1530 passed; integration 1043 passed; e2e пропущен/зелёный (профиль services не поднят); docker-build и web-check (biome, tsc, build) зелёные. Полный вывод — в ledger дорожки.

Известные ограничения / решения владельцу

  • Вторая форма ББ теперь хранится и участвует в автозамене: файл с ББ на 30.09.2025 и ББ на 31.12.2024 может заменить старый файл за 4 кв. 2024, а его ОФР выпадет с предупреждением OQ-154 (по спеке; раньше вторая форма пропускалась).
  • Несовместимые изменения API: line_code может быть null, новые поля, JobBrief.warnings — объекты, header.organization_name: null → 422. Фронт и гайд — по плану 6.
  • needs_review значений строки, выведенной из detail назначением кода, не восстанавливается (T13.3 → часть Б, B2); проверки ядра info после смены кода не пересчитываются (T13.4, часть Б).
  • Отложены: см. таблицу ниже.

Rulings I made

R-1 порядок A0–A4, A6–A13, затем A5 (цена: конфликты слияния); R-2 исполнители/ревьюеры sonnet, финал opus; R-3 тесты на scratch-БД в compose-Postgres; R-4 A0 без отдельного ревью; R-5 ревью A1+A2 парой; R-6 ревью малых задач парами; R-7 архив change А только вместе с Б; R-8 одна волна правок и один re-review. Решения исполнителей A1-1…A5-6 и открытые вопросы — в openspec/changes/unified-normalization-core-a/design.md.

Находки (маркер — статус)

fixed: T1.1, T7.5, T8.1, T2.1, T4.2, T4.4, T4.5, T10.1, T11.1, T13.2, I-1, I-2, M-1…M-5, M-7, M-9…M-12, T5.3.
deferred: T1.2, T4.1, T7.1–T7.3, T8.2–T8.5, T13.3, T13.4, T5.1, T5.2, M-6, M-8, R2.1, R2.2, R2.3, O-3 (statement-code-orders.yaml в Б), O-4 (гайд фронта).
rejected: T1.3, T4.3, T4.6, T7.4, T8.6, T13.1, T13.5, T13.6, T5.4, M-13, I-3 (R-7), O-2.

🤖 Generated with Claude Code

Закрывает часть А плана 3 единой нормализации ББ/ОФР (arm-ka-docs#116). Closes #126. **Слить после docs #117. На контур — только вместе с частью Б и фронтом (план 6).** До части Б ядро не принимает результаты `2.0` на маппинг и не пишет `document_issue` §7. Change `unified-normalization-core-a` архивировать только вместе с `core-b` (R-7). ## Что сделано - A0: change OpenSpec `unified-normalization-core-a`. - A1–A2: схема DBML v5.19, миграция `0007_dbml_v5_19` (upgrade с заполнением, downgrade с отказами и журналом потерь). - A3: `crm_id` ГСК/ГСЗ (409 `CRM_ID_EXISTS`, аудит `GROUP_CHANGE`). - A4: `api/scripts/purge_statements.py` (очистка форм перед выкладкой; отказ только при `VERIFIED`/`ARCHIVED` со снимком ЕХ). - A5: копии контракта обоих MAJOR, модели v2.0, приём конвертов 1.x/2.0, `JobBrief.warnings` структурами. - A6–A7: словарь имён с синонимами, совпадение наименований, агрегат формы по коду. - A8: ответ `GET …/statement` и `DocumentOut.issues` по v5.19. - A9: маппер 1.x с полями v5.19, `file_ordinal`, вторая форма, `MAPPING_WARNING`. - A10: чистые функции условия `RECOGNIZED` для 2.0 (подключаются в части Б). - A11: порядок 409 при подтверждении формы. - A12–A13: `PATCH …/statement` (ячейки, колонки, шапка, строки). ## `make check-full` Exit 0: ruff и mypy чистые; unit 1530 passed; integration 1043 passed; e2e пропущен/зелёный (профиль services не поднят); docker-build и web-check (biome, tsc, build) зелёные. Полный вывод — в ledger дорожки. ## Известные ограничения / решения владельцу - Вторая форма ББ теперь хранится и участвует в автозамене: файл с ББ на 30.09.2025 и ББ на 31.12.2024 может заменить старый файл за 4 кв. 2024, а его ОФР выпадет с предупреждением OQ-154 (по спеке; раньше вторая форма пропускалась). - Несовместимые изменения API: `line_code` может быть `null`, новые поля, `JobBrief.warnings` — объекты, `header.organization_name: null` → 422. Фронт и гайд — по плану 6. - `needs_review` значений строки, выведенной из `detail` назначением кода, не восстанавливается (T13.3 → часть Б, B2); проверки ядра `info` после смены кода не пересчитываются (T13.4, часть Б). - Отложены: см. таблицу ниже. ## Rulings I made R-1 порядок A0–A4, A6–A13, затем A5 (цена: конфликты слияния); R-2 исполнители/ревьюеры sonnet, финал opus; R-3 тесты на scratch-БД в compose-Postgres; R-4 A0 без отдельного ревью; R-5 ревью A1+A2 парой; R-6 ревью малых задач парами; R-7 архив change А только вместе с Б; R-8 одна волна правок и один re-review. Решения исполнителей A1-1…A5-6 и открытые вопросы — в `openspec/changes/unified-normalization-core-a/design.md`. ## Находки (маркер — статус) fixed: T1.1, T7.5, T8.1, T2.1, T4.2, T4.4, T4.5, T10.1, T11.1, T13.2, I-1, I-2, M-1…M-5, M-7, M-9…M-12, T5.3. deferred: T1.2, T4.1, T7.1–T7.3, T8.2–T8.5, T13.3, T13.4, T5.1, T5.2, M-6, M-8, R2.1, R2.2, R2.3, O-3 (statement-code-orders.yaml в Б), O-4 (гайд фронта). rejected: T1.3, T4.3, T4.6, T7.4, T8.6, T13.1, T13.5, T13.6, T5.4, M-13, I-3 (R-7), O-2. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 20 commits 2026-10-18 18:40:28 +03:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Модели и upgrade ревизии 0007_dbml_v5_19: пять enum'ов, колонки строк/значений/колонок/шапок форм,
document.file_ordinal (уникален в файле, уникальность типа только для не-форм), recognition_job.statements_version,
related_group.crm_id, таблица document_issue; заполнение по умолчанию (row_index, needs_review, header_source и др.).
delete_file_statements удаляет document_issue; make_document берёт следующий file_ordinal; маппер пока нумерует
документы по порядку создания. downgrade — заглушка (задача A2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
crm_id пишется в колонку related_group.crm_id (v5.19), попадает в ответы и в
payload аудита; занятый значением другой ГСК/ГСЗ даёт 409 CRM_ID_EXISTS
(pre-check и uq_related_group_crm_id на гонку). Смена crm_id пишется как
GROUP_CHANGE с before/after всех изменённых полей (Р-41, P3-18).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
form_confirmable заменён на form_blocker: PERIOD_REQUIRED -> LINES_UNRESOLVED -> DUPLICATE_FORM -> CHECKS_NOT_PASSED.
Ручное и автоподтверждение используют одну функцию.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Копии api/contracts/ побайтно равны docs/contracts/ (тест идентичности плана 0): схемы v2.0 основные, .v1 рядом,
examples/ — v2.0, examples/v1/ — v1.0. Модели result_v2.py и RecognitionResultMessageV2, versions.py выбирает модель
по MAJOR. Приём конвертов принимает оба MAJOR; metrics.warnings в recognition_job пишется структурами (строки 1.x
оборачиваются в LEGACY_WARNING). JobBrief.warnings отдаёт структуры, мусор пропускается, БД не переписывается.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
aep merged commit 938e9fac87 into main 2026-10-18 18:44:13 +03:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RSHB/arm-core#129
No description provided.