# lawref.calendar

*module*

Business-календарь: снапшот и операции (WP-06; SPEC [§85](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#85-calendar-snapshot), [§85.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#851-lawcalendar01-dataset), [§86](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#86-deadline-policy) — подмножество).

Реализовано: проверка datasetHash до вычисления ([§85](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#85-calendar-snapshot): «несовпадение content_hash —
ошибки до вычисления»; T039), покрытие valid-интервала с `CALENDAR_OUT_OF_RANGE`
([§85.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#851-lawcalendar01-dataset); T040), is_working_day / add_business_days / previous_working_day по
weeklySchedule + overrides; DeadlinePolicy [§86](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#86-deadline-policy) — compute_deadline (start_count /
include_end / roll / cutoff; отсутствие policy — `MISSING_POLICY`, неявных
вариантов нет). Отложено (по вехам): working_intervals c granularity ([§85.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#851-lawcalendar01-dataset)
`CALENDAR_GRANULARITY_UNAVAILABLE`), timezone-переходы ([§86](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#86-deadline-policy): политики
несуществующего/неоднозначного local time — потребуют tzdb-снапшота).

Детерминизм: никакого системного времени/таймзоны — только pinned dataset (FND [§7.4](https://github.com/arxohq/law/blob/master/spec/FOUNDATION.ru.md#74-данные)).

## lawref.calendar.WEEKDAYS

*attribute* · *module attribute*

```python
WEEKDAYS = ('monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday')
```

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

## lawref.calendar.Calendar

*class* · *dataclass*

```python
class Calendar
```

Загруженный immutable снапшот ([§85](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#85-calendar-snapshot)).

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

### lawref.calendar.Calendar.end_exclusive

*attribute* · *instance attribute*

```python
end_exclusive: _dt.date
```

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

### lawref.calendar.Calendar.overrides

*attribute* · *instance attribute*

```python
overrides: dict[_dt.date, bool]
```

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

### lawref.calendar.Calendar.snapshot_id

*attribute* · *instance attribute*

```python
snapshot_id: str
```

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

### lawref.calendar.Calendar.start

*attribute* · *instance attribute*

```python
start: _dt.date
```

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

### lawref.calendar.Calendar.weekly_working

*attribute* · *instance attribute*

```python
weekly_working: dict[str, bool]
```

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

### lawref.calendar.Calendar.add_business_days

*method*

```python
def add_business_days(day: _dt.date, days: int) -> _dt.date
```

[§85.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#851-lawcalendar01-dataset): обязательная операция add_business_period для business_day ([§84.3](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#843-businessperiod)).

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

### lawref.calendar.Calendar.is_working_day

*method*

```python
def is_working_day(day: _dt.date) -> bool
```

[§85.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#851-lawcalendar01-dataset): обязательный запрос is_working_day; overrides сильнее weeklySchedule.

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

### lawref.calendar.Calendar.previous_working_day

*method*

```python
def previous_working_day(day: _dt.date) -> _dt.date
```

Ближайший рабочий день строго раньше `day` (перенос «накануне»).

[§86](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#86-deadline-policy): значение `roll = previous_working_day` политики срока; рабочесть дня
берётся из `is_working_day` [§85.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#851-lawcalendar01-dataset), а не из ambient-календаря.

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

## lawref.calendar.CalendarError

*class*

```python
class CalendarError(Exception)
```

Bases: `Exception`

Ошибка календарного контракта; code — из [§85](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#85-calendar-snapshot)/[§85.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#851-lawcalendar01-dataset).

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

### lawref.calendar.CalendarError.code

*attribute* · *instance attribute*

```python
code = code
```

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

### lawref.calendar.CalendarError.message

*attribute* · *instance attribute*

```python
message = message
```

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

## lawref.calendar.TermEnv

*class*

```python
class TermEnv
```

Окружение вычисления термов: всё pinned-окружение одного evaluation.

Помимо календаря и DeadlinePolicy здесь находится immutable-индекс чистых
``FunctionDecl``. Это НЕ второй интерпретатор: тела функций остаются
обычными CLIR Term и исполняются ``values.eval_term``. Индекс лишь связывает
``CallTerm.function`` с декларацией и собирает детерминированный trace для
proof graph (§A3.2/§A3.6).

Существует ровно потому, что `add_business_days` [§86](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#86-deadline-policy) — не чистая функция
аргументов: календарь и политика приходят из окружения (`calendar =
context.calendar`, `policy = context.deadline_policy` в нормативном примере
[§86](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#86-deadline-policy)). Глобала здесь быть не может: окружение живёт одно evaluation и
входит в манифест через снапшот и контекст, а не через состояние модуля.

Загрузка календаря ЛЕНИВАЯ: пакет без единого календарного терма не обязан
иметь валидный датасет, а [§85](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#85-calendar-snapshot) «ошибки до вычисления» остаются за
calendar_op-запросом (T039) — иначе hash mismatch менял бы момент отказа.

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

### lawref.calendar.TermEnv.semantic_version

*attribute* · *instance attribute*

```python
semantic_version = semantic_version
```

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

### lawref.calendar.TermEnv.legal_time

*property*

```python
legal_time: str
```

`legalTime` контекста [§5.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/02-part-ii-goals-and-scope.ru.md#51-no-hidden-defaults) — обязательная ось, не системные часы.

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

### lawref.calendar.TermEnv.snapshot_id

*property*

```python
snapshot_id: str | None
```

Id снапшота — для relatedNodes в issue ([§85.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#851-lawcalendar01-dataset)).

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

### lawref.calendar.TermEnv.calendar

*method*

```python
def calendar() -> Calendar
```

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

### lawref.calendar.TermEnv.calendar_period

*method*

```python
def calendar_period(after: _dt.date, count: int, unit: str) -> tuple[_dt.date, dict[str, Any]]
```

[§84.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#842-calendarperiod)/[§86](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#86-deadline-policy) `add_calendar_period(after, count, policy)` — errata E-0029.

Календарь [§85](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#85-calendar-snapshot) не запрашивается вовсе: у этого терма пути к нему нет.
До E-0029 та же операция шла через `deadline()` с предикатом
`needs_calendar`, то есть требование снимка зависело от политики и не
читалось в норме; на этой условности реализации молча разошлись.

`roll` и `cutoff` здесь отвергаются, а не игнорируются: допустить их
значило бы вернуть снимок через политику. `include_end` обязан быть
`true` по той же причине — при `false` итог зависит от рабочести дня.

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

### lawref.calendar.TermEnv.deadline

*method*

```python
def deadline(after: _dt.date, count: int, unit: str, after_time: str | None) -> tuple[_dt.date, dict[str, Any]]
```

[§86](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#86-deadline-policy) `add_business_days(after, count, calendar, policy)`: policy — из
материализованного контекста [§89](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/13-part-xiii-context-scope-applicability.ru.md#89-evaluation-context); её отсутствие — `MISSING_POLICY`.

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

### lawref.calendar.TermEnv.enum_member_type

*method*

```python
def enum_member_type(symbol: str) -> str | None
```

StableId перечисления, объявившего член `symbol`, либо None (E-0067).

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

### lawref.calendar.TermEnv.external_opaque

*method*

```python
def external_opaque(symbol: str) -> dict[str, Any] | None
```

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

### lawref.calendar.TermEnv.external_snapshot

*method*

```python
def external_snapshot(symbol: str) -> dict[str, Any] | None
```

Граница [§47.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/08-part-viii-type-system.ru.md#472-snapshot) для честного adapter-required отказа без I/O.

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

### lawref.calendar.TermEnv.function

*method*

```python
def function(symbol: str) -> dict[str, Any] | None
```

Разрешить pure FunctionDecl [§46](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/08-part-viii-type-system.ru.md#46-functions) по StableId символа [§14](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/05-part-v-lexis-and-basic-syntax.ru.md#14-идентификаторы).

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

### lawref.calendar.TermEnv.function_symbol

*method*

```python
def function_symbol(symbol: str) -> dict[str, Any] | None
```

Вернуть SymbolDecl для проверки return type [§46](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/08-part-viii-type-system.ru.md#46-functions).

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

### lawref.calendar.TermEnv.function_trace

*method*

```python
def function_trace() -> list[dict[str, Any]]
```

Копия trace [§179](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/26-part-xxv-proof-graph-and-explanations.ru.md#179-proof-graph): вызывающий не может изменить состояние evaluation.

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

### lawref.calendar.TermEnv.is_a3_parameter

*method*

```python
def is_a3_parameter(symbol: str) -> bool
```

Функция объявлена параметром-датасетом A3 §A3.2, а не телом [§46](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/08-part-viii-type-system.ru.md#46-functions).

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

### lawref.calendar.TermEnv.note

*method*

```python
def note(issue: dict[str, Any]) -> None
```

Записать информационный issue вывода ([§64.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/10-part-x-propositions-and-four-valued-support.ru.md#642-отношение-округления-над-сертифицированными-границами-errata-e-0136)) без дубликатов.

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

### lawref.calendar.TermEnv.notes

*method*

```python
def notes() -> list[dict[str, Any]]
```

Информационные issue, накопленные за evaluation — в порядке первого
появления, дальше их сортирует канон документа [§208](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/28-part-xxvii-canonical-legal-ir.ru.md#208-canonical-serialization).

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

### lawref.calendar.TermEnv.read_external_snapshot

*method*

```python
def read_external_snapshot(symbol: str, args: list[Any], where: str)
```

Read exactly one typed call from a supplied pinned dataset ([§60](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/09-part-ix-values-terms-expressions.ru.md#60-external-data-access)).

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

### lawref.calendar.TermEnv.record_function_call

*method*

```python
def record_function_call(entry: dict[str, Any]) -> None
```

Записать вызов [§46](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/08-part-viii-type-system.ru.md#46-functions) в trace — посылка узла `function_evaluation` [§179](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/26-part-xxv-proof-graph-and-explanations.ru.md#179-proof-graph).

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

### lawref.calendar.TermEnv.reset_function_trace

*method*

```python
def reset_function_trace() -> None
```

Начать trace одного терм-запроса (узлы `function_evaluation` [§179](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/26-part-xxv-proof-graph-and-explanations.ru.md#179-proof-graph)).

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

### lawref.calendar.TermEnv.tables_of

*method* · *staticmethod*

```python
def tables_of(nodes: list[dict[str, Any]] | None) -> dict[str, dict]
```

Таблицы символов по узлам — то, что вид программы кэширует.

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

### lawref.calendar.TermEnv.unit_table

*method*

```python
def unit_table() -> dict[str, dict[str, Any]]
```

Реестр объявлений единиц [§49.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/08-part-viii-type-system.ru.md#492-объявление-единиц-errata-e-0136-e-0150) закреплённого CLIR (errata E-0136).

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

## lawref.calendar.compute_deadline

*function*

```python
def compute_deadline(cal: Calendar | None, after: _dt.date, count: int, policy: dict[str, Any] | None, after_time: str | None = None, unit: str = 'business_day', suspensions: Any = None, calendar_day_step: bool = False) -> tuple[_dt.date, dict[str, Any]]
```

Deadline [§86](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#86-deadline-policy) по DeadlinePolicy; возвращает (due, trace для proof-атрибутов).

Policy обязательна: «если policy не задана явно или profile-ом,
compilation/evaluation завершается MISSING_POLICY» — никакого неявного
варианта. V1-конвенции семантики (уточнение — normative examples WP-09):
  1. cutoff: если задан и время подачи after_time позже cutoff, старт
     сдвигается на следующий календарный день;
  2. start_count = next_day: отсчёт со следующего календарного дня;
  3. count > 0: день 1 = первый рабочий день >= старта, due = день N;
     count = 0: due = старт (без счёта);
  4. include_end = false: действие должно быть совершено до дня окончания —
     due сдвигается на предыдущий рабочий день;
  5. roll: применяется к итоговой дате, если она нерабочая (достижимо при
     count = 0 или пустом счёте); no_roll оставляет дату как есть;
  6. unit: business_day (по умолчанию) — счёт по рабочим дням; calendar_day —
     счёт календарными днями (ГК РК ст. 173–175: день N = старт + N-1,
     затем include_end и roll — здесь roll реально достижим);
  7. suspensions (D2, DECISION-0008 [§3.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/02-part-ii-goals-and-scope.ru.md#3-цели-law-dsl-core-01)): окна приостановления течения
     срока. День внутри окна НЕ является днём течения ни в какой единице:
     due — N-й СЧИТАЮЩИЙСЯ день, начиная со старта, где считающийся —
     рабочий (business_day) либо любой (calendar_day) день вне окон.
     Без окон обе ветви дают ровно прежний результат, поэтому байты
     существующих голденов не двигаются; поля suspension* появляются в
     trace ТОЛЬКО при непустых окнах — по той же причине.

Приостановление применяется к СЧЁТУ, а не к границам: include_end и roll
работают поверх полученной даты как раньше (окно на итоговой дате её не
сдвигает — сдвигают только нерабочесть и include_end).

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

## lawref.calendar.load_calendar

*function*

```python
def load_calendar(snapshot_node: dict[str, Any], resource_bytes: bytes) -> Calendar
```

Загрузка снапшота: digest над байтами ресурса ([§85](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#85-calendar-snapshot); errata-редакция addendum),
schema-валидация датасета и инварианты [§85.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#851-lawcalendar01-dataset) — всё ДО первого вычисления (T039).

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

## lawref.calendar.needs_calendar

*function*

```python
def needs_calendar(unit: str, policy: dict[str, Any] | None) -> bool
```

Спрашивает ли ЭТОТ срок рабочий календарь [§85](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#85-calendar-snapshot).

Календарный шаг [§84.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#842-calendarperiod) с `no_roll` и `include_end` не обращается к
календарю ни разу: месяцы и годы считаются по датам, а не по рабочим
дням. Требовать при этом закреплённый снимок праздников значило бы делать
норму неисполнимой из-за данных, которых она не читает, — срок полномочий
«семь лет» истекает в 2033 году, и календарь на 2033-й ему не нужен.
Дневные единицы календарь спрашивают ВСЕГДА: даже при `no_roll`
`is_working_day` вызывается (левый операнд `and` в проверке ниже), и
менять это errata E-0026 не вправе — она про новые единицы.

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

## lawref.calendar.symbol_tables

*function*

```python
def symbol_tables(nodes: list[dict[str, Any]] | None) -> dict[str, dict]
```

Таблицы символов TermEnv по узлам программы — чистая функция от узлов,
которую вид программы (`evaluator.prepared`) считает один раз: функции [§46](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/08-part-viii-type-system.ru.md#46-functions),
их символы, внешние снимки и непрозрачные границы [§47.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/08-part-viii-type-system.ru.md#472-snapshot), члены
перечислений [§38](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/08-part-viii-type-system.ru.md#38-enums)/[§57](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/09-part-ix-values-terms-expressions.ru.md#57-equality) (errata E-0067: StableId члена `{namespace}#{Член}`
→ StableId объявившего перечисления; индекс питает ветку const_ref
`eval_term` — член есть значение-идентичность, а не мёртвая ссылка).

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