# lawref.normstatic

*module*

Статический анализ разрешимого фрагмента: поглощения и возможные конфликты.

Ступень 3 связей между актами (DECISION-0010). Рамка задана [§105.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#1051-базовые-normative-conflict-patterns): goal
incompatibility НЕ выводится по различию текста; статический анализатор
вправе сообщить `POSSIBLE_NORM_CONFLICT`, но defeat/priority-рёбер не
порождает — semantic conclusion остаётся за движком. Здесь реализован
анализатор ровно этой рамки над фрагментом, где вопросы разрешимы:

**Фрагмент** (правило вне фрагмента — не ошибка, а явная строка отчёта,
принцип «no silent caps»):

- голова — литерал с аргументами var/значение/entity_ref/const_ref;
- тело — established-литералы той же формы аргументов и сравнения
  var ⋈ const над Integer/Decimal [§57](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/09-part-ix-values-terms-expressions.ru.md#57-equality) (значения — точные рациональные,
  `fractions.Fraction`; float в семантическом коде запрещён);
- в теле нет двух литералов с одинаковым скелетом — иначе сопоставление
  пары правил перестаёт быть детерминированным;
- переменные сравнений заякорены в голове либо литералах тела.

**Предупреждения** — [§199](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/27-part-xxvi-static-semantics-and-diagnostics.ru.md#199-diagnostic-code-ranges) даёт диапазон `LDC-Wxxxx` без внутренней разметки;
здесь занимаются первые коды, зеркалящие тематику E4 (rules/defeasibility):

- `LDC-W4101` — возможный конфликт: головы противоположной полярности
  унифицируются, тела совместно выполнимы. Сертификат — свидетель:
  конкретные значения числовых переменных, при которых оба тела
  удовлетворимы; проверяется подстановкой, а не доверием анализатору;
- `LDC-W4102` — поглощение/дубликат: головы и литералы совпали с точностью
  до переименования, числовые ограничения одного правила покрывают другое —
  узкое правило не даёт заключений сверх широкого. Предупреждение, не
  ошибка: при командной поддержке [§109](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#109-team-support) и defeat [§107](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#107-defeat) узкое правило может
  быть осмысленным (отдельная мишень приоритета).

Ни при каких находках анализатор не влияет на evaluation: он не входит в
байтовый контракт evaluation-документа и не создаёт рёбер [§106](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#106-priority-relation)–107.

## lawref.normstatic.GROUND_KINDS

*attribute* · *module attribute*

```python
GROUND_KINDS = ('value', 'entity_ref', 'const_ref')
```

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

## lawref.normstatic.MIRROR

*attribute* · *module attribute*

```python
MIRROR = {'lt': 'gt', 'le': 'ge', 'gt': 'lt', 'ge': 'le', 'eq': 'eq'}
```

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

## lawref.normstatic.NUMERIC_TYPES

*attribute* · *module attribute*

```python
NUMERIC_TYPES = ('urn:law:std#Integer', 'urn:law:std#Decimal')
```

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

## lawref.normstatic.POSSIBLE_CONFLICT_CODE

*attribute* · *module attribute*

```python
POSSIBLE_CONFLICT_CODE = 'LDC-W4101'
```

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

## lawref.normstatic.SUBSUMPTION_CODE

*attribute* · *module attribute*

```python
SUBSUMPTION_CODE = 'LDC-W4102'
```

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

## lawref.normstatic.analyze_package

*function*

```python
def analyze_package(ir: dict) -> dict
```

Анализ CLIR-пакета: правила плюс покрытие конфликтов приоритетами
[§106](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#106-priority-relation) (норм-шаблоны [§127](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/18-part-xvii-normative-positions.ru.md#127-power) — вне фрагмента по построению).

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

## lawref.normstatic.analyze_rules

*function*

```python
def analyze_rules(rules: list[dict], priority_rules: list[dict] = ()) -> dict
```

Анализ набора правил одного пакета; результат детерминирован.

Возвращает {"warnings", "outside", "unsatisfiable", "checkedPairs"}:
warnings — W4101/W4102; outside — правила вне фрагмента с причинами;
unsatisfiable — правила с пустым числовым guard-ом (не применимы ни при
каких значениях — самостоятельная находка).

Возможный конфликт, пара которого покрыта объявленным priority_rule
([§106](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#106-priority-relation)), помечается `coveredByPriority`: предупреждение остаётся (защита
существует и названа), но взгляд ревьюера направляется на НЕпокрытые —
именно там движок ответит BOTH/INCOMPARABLE.

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

## lawref.normstatic.normal_form

*function*

```python
def normal_form(rule: dict) -> tuple[dict | None, str | None]
```

Нормальная форма правила во фрагменте либо (None, причина-вне).

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