# lawref.evaluator.procedures

*module*

Свёртка истории процедур — SPEC [§160.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1601-on-e--условие-валидности-перехода-decision-0156)–[§164.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1642-current_state-и-state_before), [§180.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/26-part-xxv-proof-graph-and-explanations.ru.md#1802-proof-узлы-свёртки-процедур-decision-0156), [§201.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/28-part-xxvii-canonical-legal-ir.ru.md#2011-узел-procedure-decision-0156) (DECISION-0156).

Фаза стоит ОДНОЙ стратой [§111](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#111-порядок-evaluation-strata) между strict-замыканием входных фактов и
правилами-потребителями [§164](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#164-invalid-transitions): автомат перестал быть записью правил и стал
данными узла `procedure` [§201.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/28-part-xxvii-canonical-legal-ir.ru.md#2011-узел-procedure-decision-0156), а порядок по времени со «строго более
ранними» событиями [§110.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#110-stratification) правилами не выражается.

Свёртка ОДНА на документ ([§161.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1612-что-видит-гард-и-почему-свёртка-стратифицируется)): все процедуры программы и все их
экземпляры лежат в одном глобальном порядке по началу канонического `time`
носителей [§79.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#791-исполнимая-форма-экземпляра-decision-0156). Носители с равным началом образуют ГРУППУ и каждый читает
состояние ДО группы — отсюда требование [§161.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1612-что-видит-гард-и-почему-свёртка-стратифицируется), которое эта реализация
держит по построению: порядок обхода внутри группы не влияет ни на один
опубликованный факт и ни на один узел proof-графа.

Программа без узла `procedure` через модуль не проходит вовсе: байты её
документов обязаны остаться прежними (инвариант 3 CLAUDE.md).

## lawref.evaluator.procedures.CARRIER_REUSED

*attribute* · *module attribute*

```python
CARRIER_REUSED = _fatal('CARRIER_REUSED', 'одно событие предъявлено носителем двух переходов одной области либо вложенных областей одного экземпляра; такие переходы не образуют одного шага истории, и состояние после события не определено, свёртка не выполнялась (§161.1, §162.1)')
```

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

## lawref.evaluator.procedures.INVALID_JOIN

*attribute* · *module attribute*

```python
INVALID_JOIN = _fatal('INVALID_JOIN_POLICY', 'политика соединения области недостижима: quorum(n) при n вне 1..m либо соединение без областей; автомат не исполняется (§162.2)')
```

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

## lawref.evaluator.procedures.NORM_STATUS_PREDICATES

*attribute* · *module attribute*

```python
NORM_STATUS_PREDICATES = ('urn:law:std#active', 'urn:law:std#bearer_of', 'urn:law:std#beneficiary_of', 'urn:law:std#conflicts', 'urn:law:std#created', 'urn:law:std#instance_of', 'urn:law:std#rule_of', 'urn:law:std#satisfied', 'urn:law:std#undetermined', 'urn:law:std#violated')
```

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

## lawref.evaluator.procedures.REASONS

*attribute* · *module attribute*

```python
REASONS = ('from', 'on', 'guard', 'requires', 'join')
```

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

## lawref.evaluator.procedures.SIMULTANEOUS

*attribute* · *module attribute*

```python
SIMULTANEOUS = _fatal('SIMULTANEOUS_EVENTS', 'два события экземпляра процедуры имеют равное начало канонического интервала; порядок истории не определён, свёртка не выполнялась (§79.1, §161.1)')
```

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

## lawref.evaluator.procedures.Automaton

*class*

```python
class Automaton
```

Разбор узла `procedure` в таблицы, которыми пользуется свёртка.

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

### lawref.evaluator.procedures.Automaton.constants

*attribute* · *instance attribute*

```python
constants: dict[str, dict] = {}
```

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

### lawref.evaluator.procedures.Automaton.id

*attribute* · *instance attribute*

```python
id = str(node['id'])
```

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

### lawref.evaluator.procedures.Automaton.lattice

*attribute* · *instance attribute*

```python
lattice = lattice
```

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

### lawref.evaluator.procedures.Automaton.node

*attribute* · *instance attribute*

```python
node = node
```

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

### lawref.evaluator.procedures.Automaton.regions

*attribute* · *instance attribute*

```python
regions: dict[str, dict] = {}
```

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

### lawref.evaluator.procedures.Automaton.state_path

*attribute* · *instance attribute*

```python
state_path: dict[str, tuple[str, ...]] = {}
```

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

### lawref.evaluator.procedures.Automaton.states

*attribute* · *instance attribute*

```python
states: dict[str, dict] = {}
```

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

### lawref.evaluator.procedures.Automaton.transition_path

*attribute* · *instance attribute*

```python
transition_path: dict[str, tuple[str, ...]] = {}
```

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

### lawref.evaluator.procedures.Automaton.transitions

*attribute* · *instance attribute*

```python
transitions: dict[str, dict] = {}
```

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

### lawref.evaluator.procedures.Automaton.active_states

*method* · *staticmethod*

```python
def active_states(config: dict | None) -> list[str]
```

Все активные состояния конфигурации — рекурсивно по областям.

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

### lawref.evaluator.procedures.Automaton.enter

*method*

```python
def enter(state_id: str) -> dict
```

Конфигурация после входа в `state_id`: у составного состояния
токены ставятся в `initial` КАЖДОЙ области ([§162.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1621-регионы-и-токены-decision-0156)).

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

### lawref.evaluator.procedures.Automaton.initial_config

*method*

```python
def initial_config() -> dict | None
```

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

### lawref.evaluator.procedures.Automaton.initial_state_id

*method*

```python
def initial_state_id() -> str | None
```

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

### lawref.evaluator.procedures.Automaton.is_terminal_in_region

*method*

```python
def is_terminal_in_region(state_id: str) -> bool
```

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

### lawref.evaluator.procedures.Automaton.join_of

*method*

```python
def join_of(state_id: str) -> dict | None
```

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

### lawref.evaluator.procedures.Automaton.navigate

*method*

```python
def navigate(config: dict | None, path: tuple[str, ...]) -> dict | None
```

Под-конфигурация области по пути; None — область не активна.

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

### lawref.evaluator.procedures.Automaton.predicate

*method*

```python
def predicate(field: str) -> str
```

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

### lawref.evaluator.procedures.Automaton.region_of_state

*method*

```python
def region_of_state(state_id: str) -> tuple[str, ...]
```

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

### lawref.evaluator.procedures.Automaton.regions_of

*method*

```python
def regions_of(state_id: str) -> list[dict]
```

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

### lawref.evaluator.procedures.Automaton.replace

*method*

```python
def replace(config: dict, path: tuple[str, ...], new_sub: dict) -> dict
```

Копия конфигурации с заменённой под-конфигурацией по пути.

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

### lawref.evaluator.procedures.Automaton.term

*method*

```python
def term(name: str) -> dict
```

Терм имени профиля [§164.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1641-носитель-у-трёх-предикатов-decision-0156) (состояние, переход, сама процедура) в
форме ПОСЛЕ предпрохода [§54.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/09-part-ix-values-terms-expressions.ru.md#541-разыменование-предшествует-вычислению-errata-e-0049). Имя без декларации константы остаётся
`const_ref` — так устроены и корпусная конвенция, и ручные векторы;
имя, объявленное `const S: PState = …`, публикуется значением.

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

## lawref.evaluator.procedures.FoldRefusal

*class*

```python
class FoldRefusal(Exception)
```

Bases: `Exception`

Отказ свёртки [§161.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1611-свёртка-истории-decision-0156): документ не вычисляется целиком ([§181.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/26-part-xxv-proof-graph-and-explanations.ru.md#1812-total-outcome-при-блокирующей-диагностике)).

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

### lawref.evaluator.procedures.FoldRefusal.issue

*attribute* · *instance attribute*

```python
issue = issue
```

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

## lawref.evaluator.procedures.above_rules

*function*

```python
def above_rules(nodes: list[dict]) -> dict[str, list[str]]
```

Предикат → правила НАД свёрткой, его производящие ([§161.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1612-что-видит-гард-и-почему-свёртка-стратифицируется)).

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

## lawref.evaluator.procedures.automaton_subtype

*function*

```python
def automaton_subtype(automaton: Automaton, carrier_type: str, on: str) -> bool
```

[§160.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1601-on-e--условие-валидности-перехода-decision-0156): тип носителя есть `on E` либо его подтип [§79](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#79-event-declaration).

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

## lawref.evaluator.procedures.check_guard_stratification

*function*

```python
def check_guard_stratification(nodes: list[dict], plan: dict | None = None) -> None
```

[§161.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1612-что-видит-гард-и-почему-свёртка-стратифицируется): гард перехода не может читать вывод, произведённый ВЫШЕ свёртки.

Статически это `LDC-E1348` у компилятора; у оракула, которому CLIR подан
собранным вручную, тот же случай есть fatal до исполнения. Переносить
такое правило вниз нельзя: оно само (либо его группа [§111](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#111-порядок-evaluation-strata)) зависит от
свёртки, и перенос означал бы чтение невычисленного вывода ([§110](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#110-stratification)).

Отказ предъявляется по ПОТЕНЦИАЛЬНОМУ графу: дефитер, неприменимый в
ЭТОМ деле, положения группы не меняет — положение фазы есть свойство
программы, а не дела.

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

## lawref.evaluator.procedures.effect_predicates

*function*

```python
def effect_predicates(nodes: list[dict]) -> dict[str, str]
```

Предикат → ЧТО его производит выше свёртки, кроме правил ([§161.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1612-что-видит-гард-и-почему-свёртка-стратифицируется)).

Два класса сверх правил: эффект полномочия [§127](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/18-part-xvii-normative-positions.ru.md#127-power) (`payload.effect.after`) и
статус-атом [§140](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/19-part-xviii-norm-lifecycle-fulfillment-violation.ru.md#140-violation). Оба производятся фазами L2/L3, которые стоят выше свёртки
ЦЕЛИКОМ, а не «выше по зависимости»: норм-цикл [§143](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/19-part-xviii-norm-lifecycle-fulfillment-violation.ru.md#143-chains) и defeasible [§104](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#104-defeasible-candidate) на
страты не разделимы, и гард, читающий такой предикат, не увидит его ни при
каком порядке фаз (E-0148, сверка №4 п. 8).

Значение — id шаблона полномочия; у статус-атома [§140](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/19-part-xviii-norm-lifecycle-fulfillment-violation.ru.md#140-violation) его нет, и значение
пусто: производитель там — сам движок.

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

## lawref.evaluator.procedures.fold

*function*

```python
def fold(store: SupportStore, nodes: list[dict], registry: ProofRegistry, issues: list[dict], world: EventWorld, env: Any = None, plan: dict | None = None) -> None
```

Одна глобальная свёртка [§161.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1611-свёртка-истории-decision-0156)–[§164.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1642-current_state-и-state_before) над всеми процедурами документа.

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

## lawref.evaluator.procedures.fold_plan

*function*

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

[§161.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1612-что-видит-гард-и-почему-свёртка-стратифицируется)/[§111](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#111-порядок-evaluation-strata): план страт относительно свёртки истории.

«Ниже свёртки» — не «строгое правило». Вход внешних по отношению к
префиксу предикатов замораживается после завершения ВСЕХ их
производителей, включая defeasible-кандидатов, их оппозицию, дефитеры и
применимые приоритеты; сила правила сама по себе положения не определяет.
Независимые завершённые ГРУППЫ L1 [§111](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#111-порядок-evaluation-strata) идут ниже свёртки; группа,
зависящая от свёртки либо от закреплённых выше производителей, идёт выше
ЦЕЛИКОМ — часть кандидатов внизу, а часть наверху означала бы разрешение
конфликта по недособранному множеству, то есть нарушение predicate
completion barrier [§111](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#111-порядок-evaluation-strata).

Расчёт — одна неподвижная точка по четырём правилам:

1. правило (любой силы), читающее предикат из `above`, — выше;
2. группа L1 предиката, у которого ХОТЬ ОДИН производитель выше (своё
   поражаемое правило, strict-оппозиция, атакующий дефитер), — выше
   целиком;
3. условие приоритета [§120](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/17-part-xvi-priority-declarations.ru.md#120-lex-posterior), читающее предикат из `above`, поднимает
   правила, которых касается ребро;
4. подъём добавляет ГОЛОВУ правила в `above`, и расчёт повторяется —
   подъём группы поднимает её потребителей.

Безусловный транзитивный путь приоритета [§106](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#106-priority-relation) планом не трогается вовсе:
замыкание считается по ПОЛНОЙ программе (`prepare_defeasible`), и ребро
`A > C` через правило `B` выше свёртки действует в нижней части, не
требуя исполнения `B`.

`None` — узла `procedure` в программе нет: план не строится, порядок фаз
прежний, байты прежних документов целы (инвариант 3 CLAUDE.md).

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

## lawref.evaluator.procedures.fold_predicates

*function*

```python
def fold_predicates(nodes: list[dict]) -> set[str]
```

Предикаты [§164.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1641-носитель-у-трёх-предикатов-decision-0156), ПРОИЗВОДИМЫЕ свёрткой (не читаемые ею).

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

## lawref.evaluator.procedures.needs_event_world

*function*

```python
def needs_event_world(nodes: list[dict]) -> bool
```

Нужен ли документу мир событий [§79.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/12-part-xii-events-actions-temporal-model.ru.md#791-исполнимая-форма-экземпляра-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), без типа-события и без
расписания `recurring` его не строит вовсе — и остаётся байтово той же,
какой была до DECISION-0156 (инвариант 3 CLAUDE.md).

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

## lawref.evaluator.procedures.rule_reads

*function*

```python
def rule_reads(rule: dict) -> set[str]
```

ВСЕ предикаты, читаемые правилом ([§161.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1612-что-видит-гард-и-почему-свёртка-стратифицируется), барьер свёртки).

«Читает» здесь — не «стоит положительным конъюнктом тела». Барьер [§161.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1612-что-видит-гард-и-почему-свёртка-стратифицируется)
строится по ПОЛНОМУ графу чтений, иначе он пропускает ровно те формы, в
которых чтение и прячется: `not_known` [§113](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#113-default-negation), агрегат [§59](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/09-part-ix-values-terms-expressions.ru.md#59-aggregates) и квантор [§52](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/08-part-viii-type-system.ru.md#52-finite-domains)
внутри гарда, сравнение [§57](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/09-part-ix-values-terms-expressions.ru.md#57-equality), `scope` [§92](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/13-part-xiii-context-scope-applicability.ru.md#92-edition-applicability) и — главное — термы САМОЙ ГОЛОВЫ
(`count { s | current_state(x, s) }` в аргументе вывода читает свёртку,
а конъюнктом тела не является).

Собственный предикат головы в чтения не входит: он производится, а не
читается; но аргументы головы обходятся наравне с телом.

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

## lawref.evaluator.procedures.split_closure_groups

*function*

```python
def split_closure_groups(level_groups, nodes: list[dict], plan: dict | None = None)
```

Замыкания [§70](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/10-part-x-propositions-and-four-valued-support.ru.md#70-closed-world-declarations) НИЖЕ и ВЫШЕ свёртки ([§161.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1612-что-видит-гард-и-почему-свёртка-стратифицируется), [§231.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/31-part-xxx-scalability.ru.md#2311-lazy-closure-и-comprehensions)).

Замыкание над предикатом свёртки материализуется ПОСЛЕ неё: закрытый
`current_state` [§164.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1642-current_state-и-state_before) иначе получил бы explicit negative на каждый
кандидат раньше, чем свёртка опубликовала бы положительную опору, и
текущее состояние дела стало бы `BOTH` — то есть спорным — на ровном
месте. Правила, замыкания и свёртка стратифицируются ВМЕСТЕ ([§111](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#111-порядок-evaluation-strata):
«strict-замыкания и замыкания [§70](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/10-part-x-propositions-and-four-valued-support.ru.md#70-closed-world-declarations) согласуются с тем же планом»), поэтому
подъём группы L1 поднимает и замыкание над её предикатом.

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

## lawref.evaluator.procedures.split_defeasible

*function*

```python
def split_defeasible(prepared: dict, plan: dict | None)
```

Слой L1 [§104](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#104-defeasible-candidate)–[§115](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#115-конфликтный-результат) НИЖЕ и ВЫШЕ свёртки ([§161.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1612-что-видит-гард-и-почему-свёртка-стратифицируется), [§111](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#111-порядок-evaluation-strata)).

Возвращает пару установок с ТЕМИ ЖЕ замыканием приоритетов [§106](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#106-priority-relation), рангами
[§110](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#110-stratification) и статическими issues, что и полная: подготовка считается по ПОЛНОЙ
программе, а планом отбираются лишь ИСПОЛНЯЕМЫЕ кандидаты. Иначе
транзитивное ребро приоритета, проходящее через правило выше свёртки,
исчезло бы в нижней части, и положение фазы изменило бы решётку [§106](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#106-priority-relation) —
свойство программы, а не порядка вычисления.

Нижняя часть пуста — возвращается `(None, prepared)`: прежний единственный
вызов, прежние байты.

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

## lawref.evaluator.procedures.split_strict

*function*

```python
def split_strict(prepared, nodes: list[dict], plan: dict | None = None)
```

Строгий слой НИЖЕ свёртки ([§161.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1612-что-видит-гард-и-почему-свёртка-стратифицируется)): правила, чьи головы транзитивно не
зависят ни от предикатов [§164.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1641-носитель-у-трёх-предикатов-decision-0156), ни от групп L1, закреплённых выше.

Свёртка есть одна страта [§111](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#111-порядок-evaluation-strata), и её вход заморожен на входе: правила,
читающие `valid_transition` / `entered_state` / `left_state` /
`current_state`, стоят СТРОГО ВЫШЕ и до свёртки не применяются — иначе
`not_known(valid_transition(…))` [§113](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#113-default-negation) у потребителя [§164](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#164-invalid-transitions) сработал бы на
НЕВЫЧИСЛЕННОМ выводе ([§161.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1611-свёртка-истории-decision-0156)). Программа без узла `procedure` этой
функции не видит и идёт прежним порядком байт в байт.

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

## lawref.evaluator.procedures.validate_joins

*function*

```python
def validate_joins(automata: list[Automaton]) -> None
```

[§162.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/22-part-xxi-procedures.ru.md#1622-политики-соединения): соединение, которое не сработает никогда, есть тупик.

Тот же класс, что статический `LDC-E1345`, предъявленный собранным
вручную CLIR, — fatal `INVALID_JOIN_POLICY` до вывода. `LDC-E1345` называет
ЧЕТЫРЕ формы, а не одну: `quorum(n)` вне диапазона, `join` без областей и
— обе проверялись раньше — область без `initial` либо без терминального
состояния. Область без начального состояния не получает токена вовсе, а
область без терминала не завершается ни при какой истории: и то, и другое
делает соединение недостижимым ровно так же, как `quorum(0)`.

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