# lawref.evaluator.document

*module*

Манифест входа [§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) и канонический документ результата [§208](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/28-part-xxvii-canonical-legal-ir.ru.md#208-canonical-serialization).

Хэш-конвенции v1 описаны в докстринге пакета: манифест хэшируется без
`semanticHash`, граф — без `proofHash`, документ — без `resultHash` и
`executionReceipt` ([§2.18](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/01-part-i-audit.ru.md#218-версия-compiler-не-должна-загрязнять-semantic-manifest)/AUDIT [§2.13](https://github.com/arxohq/law/blob/master/spec/AUDIT.ru.md#213-compiler-identity-в-semantic-hash): receipt вне semantic result).

## lawref.evaluator.document.OUTCOME_PROJECTION_FIELDS

*attribute* · *module attribute*

```python
OUTCOME_PROJECTION_FIELDS = ('schemaVersion', 'manifest', 'results', 'positions', 'conflicts', 'issues')
```

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

## lawref.evaluator.document.SCHEMA_VERSION

*attribute* · *module attribute*

```python
SCHEMA_VERSION = 'law.core.evaluation/0.1'
```

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

## lawref.evaluator.document.SCHEMA_VERSION_02

*attribute* · *module attribute*

```python
SCHEMA_VERSION_02 = 'law.core.evaluation/0.2'
```

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

## lawref.evaluator.document.VERIFICATION

*attribute* · *module attribute*

```python
VERIFICATION = 'inline'
```

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

## lawref.evaluator.document.attach_acceptance

*function*

```python
def attach_acceptance(document: dict, report: dict | None) -> dict
```

Вложить отчёт acceptance-фазы [§78.2.7](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/11-part-xi-assertions-facts-evidence.ru.md#7827-доказательство) и пересчитать `resultHash`.

Отдельной функцией, а не параметром `build_document`, по одной причине:
ветвей запроса девять, и каждая строит документ сама. Параметр пришлось бы
провести через все девять, и девятая, забытая, молча теряла бы отчёт — тот
самый класс отказов, ради которого отчёт и заводится. Здесь у поля один
владелец, а `resultHash` пересчитывается ТЕМ ЖЕ правилом ([§208](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/28-part-xxvii-canonical-legal-ir.ru.md#208-canonical-serialization): хэш
документа без `resultHash` и `executionReceipt`).

Без выбранной политики (`report is None`) документ возвращается тем же
объектом: байты запроса без политики обязаны остаться прежними ([§78.2.8](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/11-part-xi-assertions-facts-evidence.ru.md#7828-выбор-политики-идентичность-и-совместимость)).

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

## lawref.evaluator.document.build_document

*function*

```python
def build_document(manifest: dict, results: list[dict], proof_nodes: list[dict], roots: list[str], issues: list[dict], conflicts: list[dict] | None = None, positions: list[dict] | None = None, interpretation_dependent: bool | None = None) -> dict
```

`interpretation_dependent` (E-0140, [§156](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/21-part-xx-interpretations-and-theories.ru.md#156-evaluation-of-alternatives)): запрос (truth, collect,
positions) решил зависимость от неразрешённой группы САМ — `False` значит
«цель вне замыкания от голов заблокированных альтернатив», и документный
проход 0.2 не переносит INTERPRETATION_REQUIRED на такой результат.
`None` — прежнее поведение для остальных видов запросов: зависимость у
них не определена.

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

## lawref.evaluator.document.build_manifest

*function*

```python
def build_manifest(ir: dict, case: dict, effective: dict, options: dict, resolved_editions: dict[str, str] | None = None, evidence_pin: dict | None = None) -> dict
```

EvaluationInputManifest-минимум по форме примера (SPEC [§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)). Контекст
приходит материализованным ([§89.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/13-part-xiii-context-scope-applicability.ru.md#891-named-context-profiles): runtime наследования не выполняет — T041).
resolvedEditions ([§30.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/07-part-vii-source-and-document-model.ru.md#302-dynamic-reference)/T010): dynamic reference → exact edition, вход
семантики (покрыт semanticHash); резолюция — resolver до вычисления.
external snapshots ([§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)/T025): пиннятся из case.externalData — id → hash;
payload хэшируется в caseHash. ExecutionReceipt ([§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)/[§2.18](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/01-part-i-audit.ru.md#218-версия-compiler-не-должна-загрязнять-semantic-manifest)) — метаданные
ИСПОЛНЕНИЯ, не вход семантики: options['receipt'] сюда не попадает и не
влияет ни на манифест, ни на result/proof-хэши (T038).

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

## lawref.evaluator.document.due_verifications

*function*

```python
def due_verifications() -> list[dict]
```

Программы, чья плановая сверка отложена политикой; очередь очищается.

Возвращает сами IR — их сверяет `verify_program`. Порядок — тот, в
котором наступило расписание.

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

## lawref.evaluator.document.outcome_projection

*function*

```python
def outcome_projection(document: dict) -> dict
```

Исход без proof-графа (DECISION-0275): те же results, positions,
conflicts и issues, что у полного документа (адреса [§180.1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/26-part-xxv-proof-graph-and-explanations.ru.md#1801-каноническое-множество-proof-узлов) уже
переписаны), manifest и schemaVersion; proofGraph, proofHash, resultHash
и отчёт acceptance не входят. Эталон строит граф и отбрасывает его —
форма проекции задаётся здесь, экономия — дело порта.

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

## lawref.evaluator.document.program_derived

*function*

```python
def program_derived(ir: dict, name: str, compute)
```

Производное от ПРОГРАММЫ значение — чистая функция от IR, не зависящая
от дела и запроса, — в той же записи, что programHash (DECISION-0054).

Заведено 01.09.2026 для стратификации [§110](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/16-part-xv-defeasible-semantics-and-conflict-resolution.ru.md#110-stratification): `stratification_problem`
обходит предикатный граф на каждый вызов evaluate, и на
kz-administrative-code (11 482 узла) это 28 % вызова при неизменной
программе — считался не вывод, а константа программы, тот же класс, что у
хэша до 0054. Один пин объекта, одно вытеснение, один детектор: плановая
сверка хэша на вызовах-степенях двойки поднимает RuntimeError на
мутировавшем IR, и производные от него в тот же момент объявлены негодными
вместе с хэшем. Вызывающий получает кэшированный объект как есть — ему и
не мутировать (engine копирует issue перед вставкой в документ).

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

## lawref.evaluator.document.verification_pending

*function*

```python
def verification_pending() -> int
```

Сколько программ ждут отложенной сверки (для /healthz хоста).

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

## lawref.evaluator.document.verify_program

*function*

```python
def verify_program(ir: dict) -> None
```

Сверить программу с её кэшированным хэшем — то же, что делает `inline`.

Программа, которой в кэше уже нет (вытеснена LRU), сверке не подлежит:
сверять не с чем, и молчание здесь честнее выдуманного отказа.

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