# lawref.context

*module*

Evaluation context и named profiles (WP-30; SPEC [§89](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/13-part-xiii-context-scope-applicability.ru.md#89-evaluation-context), [§89.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/13-part-xiii-context-scope-applicability.ru.md#891-named-context-profiles)).

Интерим-представление профилей до surface-синтаксиса M3 (JSON в case):

    {"contextProfiles": {"KZ2026": {"extends": null, "fields": {...}},
                         "KZ_COMPLIANCE": {"extends": "KZ2026", "fields": {...}}},
     "context": {"extends": "KZ_COMPLIANCE", "legalTime": "...", ...}}

Семантика [§89.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/13-part-xiii-context-scope-applicability.ru.md#891-named-context-profiles): наследование single, acyclic, field-wise; child переопределяет;
контекст материализуется ДО evaluation — runtime наследования не выполняет
(T041: манифест из профильного контекста байтово равен манифесту из
эквивалентного развёрнутого). Для каждого поля хранится origin и полная
override-цепочка — `show_expanded` обязана их печатать ([§89.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/13-part-xiii-context-scope-applicability.ru.md#891-named-context-profiles)).

No hidden defaults ([§5.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/02-part-ii-goals-and-scope.ru.md#51-no-hidden-defaults)): в 0.1 `legalTime` обязателен; в 0.2+ оценщик
разрешает его отсутствие до обращения потребителя ([§89.3](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/13-part-xiii-context-scope-applicability.ru.md#893-вычисление-без-временного-контекста-02)). Технические поля
дозаполняются С ПРЕДУПРЕЖДЕНИЕМ только при заданном `legalTime`.

Полей [§89](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/13-part-xiii-context-scope-applicability.ru.md#89-evaluation-context) здесь ШЕСТЬ из восемнадцати, и это правило, а не отставание
(DECISION-0034): **поле заводится вместе со своим потребителем, а не раньше**.
Причина не стилистическая — манифест [§170](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/24-part-xxiii-cases-snapshots-evaluation.ru.md#170-evaluation-input-manifest-и-execution-receipt) есть фиксированный набор ключей, чей
`semanticHash` считается по всему словарю, поэтому у поля два исхода: либо
потребитель проецирует его в манифест и сдвигает байты КАЖДОГО
evaluation-документа, либо поле навсегда остаётся вне semantic hash, то есть
входом семантики, не покрытым хэшем входа. Заведённое вхолостую поле оплачивает
первое дважды. Четыре отсутствующих (`territory`, `source_resolver`,
`evidence_policy`, `fact_snapshot`) имеют адреса в том же решении.

## lawref.context.DATE_PATTERN

*attribute* · *module attribute*

```python
DATE_PATTERN = '^\\d{4}-\\d{2}-\\d{2}$'
```

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L50-L50)

## lawref.context.INSTANT_PATTERN

*attribute* · *module attribute*

```python
INSTANT_PATTERN = '^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$'
```

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L51-L52)

## lawref.context.SILENT_DEFAULTS

*attribute* · *module attribute*

```python
SILENT_DEFAULTS = {'mode': 'audit'}
```

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L78-L78)

## lawref.context.TECHNICAL_DEFAULTS

*attribute* · *module attribute*

```python
TECHNICAL_DEFAULTS = {'timezone': 'UTC', 'decisionTime': '2026-01-01T00:00:00Z', 'knowledgeTime': '2026-01-01T00:00:00Z'}
```

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L37-L41)

## lawref.context.TIMEZONE_PATTERN

*attribute* · *module attribute*

```python
TIMEZONE_PATTERN = '^[A-Za-z][A-Za-z0-9_+-]*(?:/[A-Za-z0-9_+-]+){0,2}$'
```

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L71-L71)

## lawref.context.TIME_FIELDS

*attribute* · *module attribute*

```python
TIME_FIELDS: tuple[tuple[str, str], ...] = (('legalTime', 'LegalTime = Date | Instant'), ('decisionTime', 'Instant'), ('knowledgeTime', 'Instant'))
```

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L60-L64)

## lawref.context.ContextError

*class*

```python
class ContextError(Exception)
```

Bases: `Exception`

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L81-L85)

### lawref.context.ContextError.code

*attribute* · *instance attribute*

```python
code = code
```

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L84-L84)

### lawref.context.ContextError.message

*attribute* · *instance attribute*

```python
message = message
```

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L85-L85)

## lawref.context.check_temporal_nodes

*function*

```python
def check_temporal_nodes(nodes: list[dict], legal_time: str) -> None
```

Check temporal selection before any node can be silently filtered out.

Called after interpretation selection, and separately for case assertions.
Literal dates, event times and source publication metadata do not by
themselves depend on the evaluation clock.

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L282-L315)

## lawref.context.check_time_axes

*function*

```python
def check_time_axes(effective: dict[str, Any]) -> None
```

Отказ, если ось контекста несёт значение вне своего вида ([§2.15](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/01-part-i-audit.ru.md#215-legal_time-date-было-слишком-узким)/[§82](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#82-temporal-axes)).

Ось времени правопорядка сравнивается с границами lifecycle [§31](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/07-part-vii-source-and-document-model.ru.md#31-lifecycle) и с окнами
`effective` [§87](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#87-rule-temporal-qualifiers) ЛЕКСИКОГРАФИЧЕСКИ — это законно ровно потому, что обе
стороны суть ISO-записи одной granularity. Границы приходят из CLIR и
проверены схемой (`legal-ir.schema.json`, `DateString`/`InstantString`);
ось приходила из дела и не проверялась ничем, то есть у сравнения был
проверен ровно один операнд из двух. Строка вне ISO не отвергалась, а
молча занимала место в порядке: `не-дата` (кириллица выше цифр) читалась
как далёкое будущее, пустая строка и `--scenarios` — как далёкое прошлое.

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L131-L162)

## lawref.context.expand

*function*

```python
def expand(case: dict, *, allow_timeless: bool = False) -> tuple[dict[str, Any], dict[str, list[str]], list[dict]]
```

Материализация контекста: (effective, override-цепочки, issues).

origins[field] — цепочка записавших уровней от корня к финальному
(последний — действующий): ["profile:KZ2026", "profile:KZ_COMPLIANCE",
"case"] либо ["default"].

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L182-L230)

## lawref.context.require_time

*function*

```python
def require_time(value: str, field: str, consumer: str) -> None
```

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L276-L279)

## lawref.context.show_expanded

*function*

```python
def show_expanded(case: dict) -> str
```

`context show --expanded` ([§89.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/13-part-xiii-context-scope-applicability.ru.md#891-named-context-profiles)): effective value, origin и override chain.

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L318-L325)

## lawref.context.status_moment

*function*

```python
def status_moment(effective: dict[str, Any], origins: dict[str, list[str]], semantic_version: str) -> str
```

Момент «по состоянию на» для статусов позиций [§134](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/19-part-xviii-norm-lifecycle-fulfillment-violation.ru.md#134-positioninstance-statuses)–[§138](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/19-part-xviii-norm-lifecycle-fulfillment-violation.ru.md#138-deadline) (errata E-0212).

`legal_time` выбирает ДЕЙСТВУЮЩЕЕ ПРАВО — редакции [§92](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/13-part-xiii-context-scope-applicability.ru.md#92-edition-applicability), окна `effective`
[§87](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#87-rule-temporal-qualifiers), значения параметров во времени. «Сейчас» статуса позиции — наступил
ли срок, истёк ли он, исполнено ли обязательство — есть другой вопрос, и
отвечает на него `decision_time` [§82](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#82-temporal-axes) («момент вынесения результата»).
До errata обе величины были одной: спросить «право на дату L, а статус —
на дату решения D» было нельзя.

Правила выбора:

- семантика 0.1 заморожена (инвариант 9) — момент прежний, `legal_time`;
- `decision_time`, ДОЗАПОЛНЕННЫЙ техническим дефолтом ([§5.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/02-part-ii-goals-and-scope.ru.md#51-no-hidden-defaults),
  `CONTEXT_FIELD_DEFAULTED`), решением не является и момента не даёт:
  дело о нём ничего не сказало, а константа `2026-01-01T00:00:00Z`
  отвечала бы за него;
- ГРАНУЛЯРНОСТЬ момента остаётся гранулярностью `legal_time`: дело,
  записавшее дату, заявило, что внутри суток ничего не менялось ([§135.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/19-part-xviii-norm-lifecycle-fulfillment-violation.ru.md#1351-активация-событием-decision-0156)),
  и менять это заявление errata не вправе. При `legal_time` типа `Date`
  берётся ДАТА `decision_time`, при `Instant` — сам момент;
- совпадение (`decision_time` той же даты либо отсутствие оси) даёт ту же
  строку, что и прежде, — документ байтово прежний.

Дата `decision_time` читается ПОЛЕМ ЗАПИСИ, в том смещении, в котором ось
записана делом, а политика [§82.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#821-политика-темпорального-разрешения-decision-0156) не спрашивается: здесь не сравниваются
дата с мгновением (единственная потребность, поднимающая отказ [§82.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#821-политика-темпорального-разрешения-decision-0156)), а
читается календарная дата вынесения решения. Цена названа: дело,
записавшее решение органа из `+05:00` в `Z`, получит дату UTC — и пишет
то смещение, которое имеет в виду.

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L233-L273)

## lawref.context.time_value_kind

*function*

```python
def time_value_kind(value: Any) -> str | None
```

Вид временного значения [§2.15](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/01-part-i-audit.ru.md#215-legal_time-date-было-слишком-узким): `"date"` | `"instant"`; `None` — ни то, ни другое.

Проверяются ОБЕ стороны, и вторая из первой не следует: форма записи —
паттернами нормативной схемы, календарная состоятельность — разбором.
`2026-13-45` форму проходит и датой не является; `20260101`, наоборот,
разбирается (`date.fromisoformat` принимает базовый формат с Python 3.11),
но записью ISO 8601 в смысле схемы не является.

Разбор мгновения ДОСЛОВНО повторяет `values._instant_moment` (E-0048: две
разные процедуры чтения одного вида — тот же дефект под другим именем).
Согласие обеих сторожат ворота `verify/ci/gates/compiler/check_context_time_format.py`, а не
договорённость.

[View source](https://github.com-arxohq/arxo-io/law/blob/2edc2b92ce22b52e03f4081d2769a58229684379/engines/lawref/lawref/context.py#L88-L116)
