# lawref.semdiff

*module*

Semantic diff [§215](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/29-part-xxviii-compiler-pipeline.ru.md#215-semantic-diff) и его вербализованный вид (WP-23-срез + WP-25 (c)).

Две функции, разделённые намеренно:

- `diff_documents` отвечает на вопрос «что изменилось в семантике» и работает
  с хэшами узлов ([§209](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/28-part-xxvii-canonical-legal-ir.ru.md#209-theory-hash-и-artifact-hash)-фильтр, применённый к узлу): переименование локального
  имени при явном `@id` семантикой не является, правка метки — тоже (errata
  E-0010), а изменение тела правила — является;
- `render_diff` отвечает на вопрос «как это прочитает юрист» и печатает тот же
  результат как **diff вербализаций** (LS [§3.6](https://github.com/arxohq/law/blob/master/spec/LAYERS-SURFACES.ru.md#36-привязка-утверждения): основной формат ревью
  изменений). Юрист сверяет тексты, а не хэши.

Сопоставление узлов идёт по StableId; узлы, пропавшие в одном документе и
появившиеся в другом с ТЕМ ЖЕ semantic hash, показываются переименованием, а
не парой «удалено/добавлено»: без этого рефакторинг имени выглядел бы как
удаление нормы.

## lawref.semdiff.ADDED

*attribute* · *module attribute*

```python
ADDED = 'added'
```

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

## lawref.semdiff.CHANGED

*attribute* · *module attribute*

```python
CHANGED = 'changed'
```

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

## lawref.semdiff.PRESENTATION

*attribute* · *module attribute*

```python
PRESENTATION = 'presentation'
```

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

## lawref.semdiff.REMOVED

*attribute* · *module attribute*

```python
REMOVED = 'removed'
```

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

## lawref.semdiff.RENAMED

*attribute* · *module attribute*

```python
RENAMED = 'renamed'
```

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

## lawref.semdiff.diff_documents

*function*

```python
def diff_documents(before: dict, after: dict) -> dict[str, Any]
```

Semantic diff двух CLIR-документов ([§215](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/29-part-xxviii-compiler-pipeline.ru.md#215-semantic-diff), уровни declaration и rule).

Возвращает `{"entries": [...], "semanticChange": bool}`. `entries` —
отсортированный по id список записей вида
`{"kind", "id", "newId"?, "hashBefore"?, "hashAfter"?}`.

`semanticChange` отвечает про **содержание** норм: добавлено, удалено или
изменено. Переименование содержания не меняет и потому его не поднимает —
но [§209](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/28-part-xxvii-canonical-legal-ir.ru.md#209-theory-hash-и-artifact-hash) включает id узла в хэш, поэтому программа всё равно получает другой
semantic hash, а утверждения по прежнему адресу становятся беспредметными;
об этом сказано прямо в вербализованном diff-е.

`presentation` — узел с тем же semantic hash, но изменившимся content hash:
правка метки или морфологической формы. Семантикой это не является, но
вербализация меняется, поэтому запись выдаётся отдельным видом, а не
молча пропускается — иначе ревьюер не узнал бы, что текст под его
утверждением изменился (LS [§3.6](https://github.com/arxohq/law/blob/master/spec/LAYERS-SURFACES.ru.md#36-привязка-утверждения)).

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

## lawref.semdiff.render_diff

*function*

```python
def render_diff(result: dict, before_verb: dict, after_verb: dict, pack: dict) -> str
```

Diff вербализаций (LS [§3.6](https://github.com/arxohq/law/blob/master/spec/LAYERS-SURFACES.ru.md#36-привязка-утверждения)) — Markdown для ревьюера.

Для каждой записи печатается блок «было/стало» в построчном diff-виде;
для добавленного и удалённого — текст целиком. Хэши остаются в документе,
но подписью под текстом: юрист сверяет формулировки, а не digest-ы.

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