Andrey Epifancev 94846cbd4c openspec: сквозная спека Среза 2b — контракт результата v1.2, §12, OQ
Proposal, design (состав v1.2: DISCLOSURE, statementDocument.checks, границы периода ОСВ; примеры; порядок
раскатки потребители → производитель), дельта recognition-contract «Файл результата» v1.2, tasks.

Refs #26

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
2026-10-06 13:21:30 +04:00

54 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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` | иллюстрирует все новые элементы одним файлом | нет |