Refs #26 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EAKRDNzXtRrwmWz9z6PZu3
5.9 KiB
Design: Срез 2b (сквозное) — контракт v1.2, §12, OQ
Context
Контракт recognition-result.schema.json v1.1: statementDocument рассчитан на OCR (поля *_confidence,
is_recognized), document_type ∈ {BALANCE, INCOME, OTHER}, результатов проверок у форм нет (у osvDocument есть
checks); osvDocument.header описывает период текстом, годом и кварталом, границы диапазона месяцев выразить нельзя
(OQ-131). Правило версионирования: MINOR — необязательные поля и новые значения enum; потребители обновляют копии раньше
производителя. Потребители копий: tabular-parser (тест идентичности в make check), arm-core (тест идентичности,
pydantic-модели результата в services/result_mapping.py), scan-gateway (копия и модели).
Decisions
D-1. Состав v1.2
$defs.statementDocument.properties.document_type.enum:["BALANCE", "INCOME", "DISCLOSURE", "OTHER"].$defs.statementDocument.properties.checks(object, необязательное):relations_failedиsoft_relations_failed— массивы объектов{column_index: integer, relation: string, expected: money, actual: money}(все четыре обязательны);duplicate_line_codes— массив строк. Описание: отсутствие объекта — «не проверялось» (OCR-путь), пустые массивы — «проверено, сошлось».$defs.osvDocument.properties.header.properties:period_start,period_end—["string", "null"],format: date;is_from_year_start—["boolean", "null"]. Описание: границы периода по шапке; для квартала/года — первое и последнее число; для диапазона месяцев — его границы;is_from_year_start=period_start— 1 января.title,descriptionсхемы иschema_version.description— «1.2».$commentо версионировании не меняется.recognition-request.schema.jsonиrecognition-result-message.schema.jsonне меняются;result_schema_versionв сообщении — строка, новых значений не требует.
D-2. Примеры
result-statement-minimal.json получает checks: {relations_failed: [], soft_relations_failed: [], duplicate_line_codes: []}
и schema_version: "1.2". Новый result-statement-excel.json: service.name = tabular-parser, три документа —
BALANCE с locator = "sheet:Бухгалтерский баланс. Лист 1,Бухгалтерский баланс. Лист 2", тремя колонками, строками
1110/11101/1100/1600 и checks с одним нарушением в soft_relations_failed; INCOME на одном листе; DISCLOSURE без
columns/lines; status = needs_check с предупреждением о единицах. result-osv-minimal.json — period_start,
period_end, is_from_year_start. Все примеры валидируются тестами контракта в трёх сервисах.
D-3. §12 — текст решений владельца
§12 переписывается по пунктам 1–8 с сохранением нумерации и добавлением п. 9 «Склейка листов и страниц», п. 10 «Статус документа и книги», п. 11 «Что отложено» (запасной путь по именам, нормализация единиц, признак продолжения). Формулы §7 остаются в §7; в §12 п. 7 — ссылка и правило «жёсткие/мягкие, допуск ±1, двойной расчёт знаков». Текст решений — из brainstorming 06.10.2026 (вопросы 2–6) и design дочернего change (D-2…D-8).
D-4. Порядок раскатки
docs (этот change) → bounded-PR в arm-core и scan-gateway «копия схемы v1.2 + модели, без логики» → tabular-parser (производитель 1.2) → fixtures (golden). Тест идентичности в сервисах пропускается только при недоступном docs, поэтому между мержем docs и мержем копий тесты сервисов на main падают; окно минимизируется одновременным открытием PR.
Decisions made without discussion
| № | Дата | Решение | Обоснование | Цена ошибки |
|---|---|---|---|---|
| 1 | 2026-10-06 | checks форм — отдельная структура, не переиспользование osvDocument.checks |
у форм нарушения по колонкам и соотношениям, у ОСВ — по строкам | поле остаётся необязательным |
| 2 | 2026-10-06 | expected/actual в нарушении — money (строка с двумя знаками), не число |
единый тип денег контракта | смена типа — MAJOR, поэтому сразу строка |
| 3 | 2026-10-06 | is_from_year_start — отдельное поле, is_cumulative не переопределяется |
is_cumulative ядро уже трактует по OQ-02/124; новое поле не ломает семантику |
два похожих поля |
| 4 | 2026-10-06 | Пример result-statement-excel.json со статусом needs_check и DISCLOSURE |
иллюстрирует все новые элементы одним файлом | нет |