Пакет общего кода нормализации ББ/ОФР arm_statements (#116 docs) #2

Merged
aep merged 28 commits from feat/1-arm-statements-package into main 2026-10-18 17:11:55 +03:00
Owner

Closes #1

Пакет общего кода arm_statements — план 1 волны 1 единой нормализации ББ/ОФР (RSHB/arm-ka-docs#116). План: openspec/changes/unified-statement-normalization/plans/2026-10-18-plan-1-arm-statements.md (ветка feat/116-unified-normalization в arm-ka-docs, PR #117).

Что внутри

Чистые функции над frozen-dataclass (stdlib + PyYAML): шаги 2–8 нормализации (раскладка и колонки, строки и разлепление, суммы, §7, подтверждение кодов структурой, needs_review, статус), normalize_candidate / normalize, recompute для ядра, to_contract / warning_to_contract / status_input_from_contract (форма контракта v2.0), словари rules/*.yaml, golden на обезличенных входах (Review Focus 1–5). Публичный API совпадает с разделом «Публичный API пакета» плана (проверено финальным ревью через inspect); сверх раздела в __all__ добавлены Rules и RulesError (R-8).

make check: ruff, ruff format, mypy strict — чисто; 272 passed. Схема v2.0: to_contract проверен по recognition-result.schema.json (0 ошибок, разовая проверка вне репозитория).

Rules I made

  • R-1 дорожка — фоновый SDD-контроллер sonnet, исполнители sonnet, финальное ревью opus.
  • R-2 Р-34 (подтверждение кода — code_fixed, уверенность не меняется) и Р-43 (workspace-таблица) учтены.
  • R-3 parse_code: краевая | как в спеке («1220|» → 12201, «|1220» → 11220 с fixed=True, подсвечивается). Цена: код с краевой чертой OCR становится пятизначным; вопрос владельцу спеки.
  • R-4 тест плана test_sublines исправлен по спеке (допуск ±1). Цена: если подстроки хотели строже — допуск 0.
  • R-5 неуверенный код вне перечня редакции структурой не подтверждается. Цена: лишняя подсветка (безопасная сторона).
  • R-6 история ветки переписана git filter-branch --msg-filter (трейлер одного коммита); ветка не публиковалась.
  • R-7 решения исполнителей при пробелах спеки (T6.2, T10.1–T10.4, T11.2, T14.3–T14.4, T15.2) — все прошли ревью задач, со спекой не расходятся.
  • R-8 Rules и RulesError в __all__.
    Решения автора плана P1-1…P1-31 перенесены в design.md (arm-ka-docs, коммит bb1b761 ветки feat/116).

Findings

Все Critical/Important закрыты (fixed): I-1 (T3, abs_kind), I-1/I-2 (T6, огромный Decimal, «(-5)»), T20.1 (квантование догадки), финальное ревью: I-1 двухстрочная шапка с «Код» сверху, I-2 line_refs = ref строки, I-3 recompute для DISCLOSURE, I-4 трейлер, M-1…M-4. Полная таблица — в ledger SDD (## Findings).

Deferred (в follow-up при закрытии)

  • M-5 смешанные разделители суммы дают «лучшую догадку» ×100 (решение владельца).
  • M-6 длинная подпись колонки проходит относительные шаблоны.
  • M-7 спека statement-normalization/spec.md:13 («конвертацию делает хост») ��асходится с P1-26 — правка в docs PR #117.
  • M-8 MappingProxyType вместо изменяемых dict в Rules (T3.8); M-9 «1 234, 56» → 1234.56 recognized (T6.9).
  • R-3: «1220|» → 12201 — вопрос владельцу спеки.
  • O-2 arm-statements/CLAUDE.md — незаполненный шаблон, нет .claude/code-paths (из adopt-project).
  • Для планов 4–5: предупреждения адаптера (candidate.warnings) при отсутствии документа хост обрабатывает сам (README); сегмент без «Код» в верхней строке повторной шапки — см. тесты test_segments.
  • Тестовые пробелы T1–T20 (minor, перечень в ledger): границы порогов, DETAIL/строка правки, REL-ветки и т. п.

🤖 Generated with Claude Code

Closes #1 Пакет общего кода `arm_statements` — план 1 волны 1 единой нормализации ББ/ОФР (RSHB/arm-ka-docs#116). План: `openspec/changes/unified-statement-normalization/plans/2026-10-18-plan-1-arm-statements.md` (ветка `feat/116-unified-normalization` в arm-ka-docs, PR #117). ## Что внутри Чистые функции над frozen-dataclass (stdlib + PyYAML): шаги 2–8 нормализации (раскладка и колонки, строки и разлепление, суммы, §7, подтверждение кодов структурой, `needs_review`, статус), `normalize_candidate` / `normalize`, `recompute` для ядра, `to_contract` / `warning_to_contract` / `status_input_from_contract` (форма контракта v2.0), словари `rules/*.yaml`, golden на обезличенных входах (Review Focus 1–5). Публичный API совпадает с разделом «Публичный API пакета» плана (проверено финальным ревью через inspect); сверх раздела в `__all__` добавлены `Rules` и `RulesError` (R-8). `make check`: ruff, ruff format, mypy strict — чисто; 272 passed. Схема v2.0: `to_contract` проверен по `recognition-result.schema.json` (0 ошибок, разовая проверка вне репозитория). ## Rules I made - R-1 дорожка — фоновый SDD-контроллер sonnet, исполнители sonnet, финальное ревью opus. - R-2 Р-34 (подтверждение кода — `code_fixed`, уверенность не меняется) и Р-43 (workspace-таблица) учтены. - R-3 `parse_code`: краевая `|` как в спеке («1220|» → 12201, «|1220» → 11220 с `fixed=True`, подсвечивается). Цена: код с краевой чертой OCR становится пятизначным; вопрос владельцу спеки. - R-4 тест плана `test_sublines` исправлен по спеке (допуск ±1). Цена: если подстроки хотели строже — допуск 0. - R-5 неуверенный код вне перечня редакции структурой не подтверждается. Цена: лишняя подсветка (безопасная сторона). - R-6 история ветки переписана `git filter-branch --msg-filter` (трейлер одного коммита); ветка не публиковалась. - R-7 решения исполнителей при пробелах спеки (T6.2, T10.1–T10.4, T11.2, T14.3–T14.4, T15.2) — все прошли ревью задач, со спекой не расходятся. - R-8 `Rules` и `RulesError` в `__all__`. Решения автора плана P1-1…P1-31 перенесены в `design.md` (arm-ka-docs, коммит bb1b761 ветки feat/116). ## Findings Все Critical/Important закрыты (`fixed`): I-1 (T3, abs_kind), I-1/I-2 (T6, огромный Decimal, «(-5)»), T20.1 (квантование догадки), финальное ревью: I-1 двухстрочная шапка с «Код» сверху, I-2 `line_refs` = ref строки, I-3 `recompute` для DISCLOSURE, I-4 трейлер, M-1…M-4. Полная таблица — в ledger SDD (`## Findings`). ### Deferred (в follow-up при закрытии) - M-5 смешанные разделители суммы дают «лучшую догадку» ×100 (решение владельца). - M-6 длинная подпись колонки проходит относительные шаблоны. - M-7 спека `statement-normalization/spec.md:13` («конвертацию делает хост») ��асходится с P1-26 — правка в docs PR #117. - M-8 `MappingProxyType` вместо изменяемых dict в `Rules` (T3.8); M-9 «1 234, 56» → 1234.56 recognized (T6.9). - R-3: «1220|» → 12201 — вопрос владельцу спеки. - O-2 `arm-statements/CLAUDE.md` — незаполненный шаблон, нет `.claude/code-paths` (из adopt-project). - Для планов 4–5: предупреждения адаптера (`candidate.warnings`) при отсутствии документа хост обрабатывает сам (README); сегмент без «Код» в верхней строке повторной шапки — см. тесты `test_segments`. - Тестовые пробелы T1–T20 (minor, перечень в ledger): границы порогов, DETAIL/строка правки, REL-ветки и т. п. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 28 commits 2026-10-18 15:02:34 +03:00
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
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
Добавлены evaluation.py (EvalLine/EvalValue/is_check_line) и checks.py
(form_variant, subline_parents, evaluate_relations, checks_from).

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
normalize_candidate / normalize; __init__ экспортирует уже реализованный публичный API.
DISCLOSURE: шапка не проверяется, предупреждений шапки нет, статус done (P1-6).

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
Пять golden-входов по Review Focus 1–5, эталоны, свойство status_input_from_contract(to_contract(d)) == status_input(d)
на golden и граничных кейсах (DISCLOSURE, без строк, абсолютная колонка без даты), test_public_api, RulesError в __all__,
README: публичный API, словари, golden-update.

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
После выбора строки по подписи кода проверяется и нижняя строка (годы):
если подпись шапки отдельно не период, а вместе с нижней — период,
строки склеиваются. Тесты: Excel, OCR, повторная шапка в два ряда.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
Адрес ячейки остаётся в message. Добавлен инвариант-тест по golden:
line_refs предупреждений документа входят в ref строк, locator нет,
column_index есть среди колонок.

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
M-2: README и docstring normalize_candidate — при отсутствии документа
candidate.warnings хост обрабатывает сам. M-3: тесты сопоставления
по дате (переставленные даты) и по порядку (дубль даты).
M-4: «Косарев» заменён на «Иванов» в тестах и docstring.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
aep merged commit 6bce80be4e into main 2026-10-18 17:11:55 +03:00
This repo is archived. You cannot comment on pull requests.
No Reviewers
No Label
1 Participants
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RSHB/arm-statements#2
No description provided.