openspec(#116): план 1 — resolve_relative и порядок редакций в публичном API, сверка с планом 3 (O-5)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
This commit is contained in:
Andrey Epifancev 2026-10-18 12:11:56 +04:00
parent 14dcb0fbee
commit f84e89288b

View File

@ -411,8 +411,9 @@ git -C "$R" commit -m "feat: типы шага 1 и выхода шагов 2–
auditor: tuple[re.Pattern[str], ...], legal_form: tuple[re.Pattern[str], ...])`
- `UnitRules(spellings: tuple[tuple[re.Pattern[str], str], ...], okei: Mapping[str, str], thousands: str,
fractional_share_percent: int)`
- `CodeOrders(sequences: Mapping[tuple[Edition, DocumentType, FormVariant], tuple[str, ...]])` с методом
`sequence(edition: Edition, form: DocumentType, variant: FormVariant) -> tuple[str, ...]`
- `CodeOrders(editions: tuple[Edition, ...], sequences: Mapping[tuple[Edition, DocumentType, FormVariant],
tuple[str, ...]])` с методом `sequence(edition: Edition, form: DocumentType, variant: FormVariant) ->
tuple[str, ...]`; `editions` — порядок редакций в файле (`(RAS_66N, FSBU4)`)
- `WarningRule(code: str, severity: Severity, scope: Literal["document", "file"])`
- `Rules(checks: CheckRules, periods: PeriodRules, headers: HeaderRules, units: UnitRules, code_ranges: CodeRanges,
code_orders: CodeOrders, lookalikes: Mapping[str, str], warnings: Mapping[str, WarningRule])`
@ -512,6 +513,7 @@ def test_code_orders_with_repeats(rules: Rules) -> None:
assert fsbu.count("1220") == len(("1220", "1220")) and "1120" not in fsbu
ras = rules.code_orders.sequence(Edition.RAS_66N, DocumentType.BALANCE, FormVariant.FULL)
assert "1120" in ras and ras.index("1110") < ras.index("1100")
assert rules.code_orders.editions == (Edition.RAS_66N, Edition.FSBU4)
def test_no_code_to_name_mapping_anywhere() -> None:
@ -2629,6 +2631,7 @@ PUBLIC = {
"StatementLine", "FailedRelation", "StatementChecks", "StatementDocument", "CandidateResult",
"NormalizationResult", "Rules", "RulesError", "load_rules", "default_rules", "normalize_candidate", "normalize",
"parse_header", "type_hint", "continuation_type", "sheet_joins", "parse_code", "parse_amount", "parse_date",
"resolve_relative",
"fix_lookalikes", "make_warning", "StatusInput", "StatusLine", "StatusValue", "document_status",
"envelope_status", "StoredForm", "StoredColumn", "StoredLine", "StoredValue", "StoredWarning", "RecomputeResult",
"recompute", "to_jsonable", "candidate_from_dict", "statements_version",
@ -2748,6 +2751,8 @@ parse_code(text: str | None, rules: Rules) -> CodeParse #
parse_amount(text: str | None, source: Source, rules: Rules) -> AmountParse
# AmountParse(amount: Decimal | None, string_value: str | None, is_recognized: bool, sign_form: SignForm | None)
parse_date(text: str | None, rules: Rules) -> date | None
resolve_relative(kind: PeriodKind, effective: date | None) -> date | None
# дата относительной колонки от эффективной даты (ядро — после правки даты отчёта)
fix_lookalikes(text: str, lookalikes: Mapping[str, str], *, anywhere: bool = False) -> str
make_warning(code: str, message: str, rules: Rules, *, line_refs: Sequence[str] = (), column_index: int | None = None,
field: str | None = None, locator: str | None = None) -> StatementWarning
@ -2799,8 +2804,9 @@ RecomputeResult(form_variant: FormVariant | None, edition: Edition | None, check
### Словари (`Rules`) — что нужно хостам
`Rules.headers.labels` / `auditor` / `legal_form` / `form_titles` / `okud` / `continuation` — метки шапки и заголовки
для адаптера Excel (план 3); `Rules.code_orders.sequence(edition, form, variant)` — перечень кодов редакции (ядру —
порядок и состав строк формы, план 4); `Rules.lookalikes` — буквы-двойники; `Rules.warnings` — уровни предупреждений.
для адаптера Excel; `Rules.code_orders.sequence(edition, form, variant)` и `Rules.code_orders.editions` — перечень
кодов редакции и порядок редакций (ядру — порядок и состав строк формы); `Rules.checks.tolerance` — допуск ±1 (ядру —
для межформенной проверки); `Rules.lookalikes` — буквы-двойники; `Rules.warnings` — уровни предупреждений.
---
@ -2874,3 +2880,15 @@ RecomputeResult(form_variant: FormVariant | None, edition: Edition | None, check
`pytest.ini` хоста задаёт `env` (`APP_ENV=test`) — тестам пакета он не нужен и не мешает; подтверждение — в плане 2.
- **O-4.** Dockerfile хостов должен копировать `api/arm_statements/rules/*.yaml` в образ (словари читаются с диска) —
в план 2 или планы сервисов.
- **O-5.** План 3 (arm-core, `2026-10-18-plan-3-arm-core.md`, таблица «Ожидаемые имена пакета») написан параллельно
и ждёт сверки с этим разделом (его O-8). Расхождения, которые правит адаптер `statements_engine.py` плана 3:
`recompute_stored_form` / `StoredFormResult` → `recompute` / `RecomputeResult`; `load_code_orders()`,
`CodeOrders.order`, `.editions` → `default_rules().code_orders.sequence(...)`, `.editions`; `relative_period_date` →
`resolve_relative`; `load_check_rules().tolerance` → `default_rules().checks.tolerance`; уверенности —
`float | None`, а не `Decimal`; `StoredValue.is_recognized` — `bool` (не `bool | None`); `StoredColumn.column_index`
— `int | None`; `period_kind`, `line_status`, `severity`, `document_type`, `edition`, `form_variant` — `StrEnum`
пакета (подкласс `str`, значения — строки контракта); `edition` результата — `Edition | None`;
`FailedRelation` — `column_index: int | None` плюс `column_key: str`, `expected` и `actual` — `Decimal` (не
`None`); `StatusInput` — `lines: tuple[StatusLine, ...]`, `values: tuple[StatusValue, ...]`, `hard_failures`
вместо `relations_failed`, дополнительно `needs_review_fields`. Решить, какая сторона меняется (по умолчанию —
адаптер плана 3, как он сам предусматривает).