# lawref.ask

*module*

Эталонная подготовка операции `ask` [§168.4](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/24-part-xxiii-cases-snapshots-evaluation.ru.md#1684-пакет-дело-и-операция-ask-decision-0165) (DECISION-0165 [§1.10](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/01-part-i-audit.ru.md#1-что-сохраняется-без-изменений)–[§1.11](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/01-part-i-audit.ru.md#1-что-сохраняется-без-изменений)).

Оракул раньше движка (инвариант 6): здесь — независимая от `law-cli`
подготовка полного `EvaluationRequest` из пакета-дела:

    пакет + выбранное дело + вопрос + явные ресурсы
      → регистрация дел ([[cases]], `lawref.cases`)
      → resolve-контекст и пины (`lawref.resolver.load_package_context`)
      → замыкание лока == замыкание импортов (LDC-E1358)
      → корень: закрытый состав (LDC-E1355), imports == лок
      → связывание мира (`link_world`)
      → дело и вопрос, пониженные ПОД ТЕМ ЖЕ контекстом
      → документы дела ↔ ресурсы лока (LDC-E8704)
      → queryId (LDC-E1356)
      → EvaluationRequest (semanticVersion — из корневого CLIR)
      → evaluate.

Понижение исходников (`.law`, `.lawcase`, строка `evaluate …;`) — работа
компилятора (общий Rust frontend, как у `.lawtest`): модуль принимает УЖЕ
пониженные документы, а вызов `lawc` живёт только в CLI `python -m lawref ask`
(прецедент `_goals_documents` в `__main__`). Хост ничего не вычисляет и не
фильтрует (инвариант 5) и ничего не дописывает в `case.options`: всё, что
входит в `caseHash`, пишет понижение дела ([§168.4](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/24-part-xxiii-cases-snapshots-evaluation.ru.md#1684-пакет-дело-и-операция-ask-decision-0165)).

## lawref.ask.ALLOWED_ROOT_KINDS

*attribute* · *module attribute*

```python
ALLOWED_ROOT_KINDS = frozenset({'deadline_policy', 'temporal_resolution_policy', 'evidence_policy', 'calendar_snapshot'})
```

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

## lawref.ask.DOCUMENT_CAPABILITY

*attribute* · *module attribute*

```python
DOCUMENT_CAPABILITY = 'evidence'
```

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

## lawref.ask.DOCUMENT_CODE

*attribute* · *module attribute*

```python
DOCUMENT_CODE = 'LDC-E8704'
```

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

## lawref.ask.DOCUMENT_KIND

*attribute* · *module attribute*

```python
DOCUMENT_KIND = 'document'
```

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

## lawref.ask.LOCK_CLOSURE_CODE

*attribute* · *module attribute*

```python
LOCK_CLOSURE_CODE = 'LDC-E1358'
```

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

## lawref.ask.QUERY_ID_CODE

*attribute* · *module attribute*

```python
QUERY_ID_CODE = 'LDC-E1356'
```

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

## lawref.ask.QUERY_INVALID_CODE

*attribute* · *module attribute*

```python
QUERY_INVALID_CODE = 'QUERY_INVALID'
```

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

## lawref.ask.QUERY_NAME

*attribute* · *module attribute*

```python
QUERY_NAME = re.compile('[A-Za-z0-9_.-]+')
```

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

## lawref.ask.ROOT_KIND_CODE

*attribute* · *module attribute*

```python
ROOT_KIND_CODE = 'LDC-E1355'
```

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

## lawref.ask.VERSION_CODE

*attribute* · *module attribute*

```python
VERSION_CODE = 'LDC-E1359'
```

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

## lawref.ask.AskError

*class*

```python
class AskError(ValueError)
```

Bases: `ValueError`

Отказ ПОДГОТОВКИ: `{"error": {"code", "message"}}`, evaluation-документа
нет (DECISION-0165 [§1.10](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/01-part-i-audit.ru.md#1-что-сохраняется-без-изменений)). Отличим от вычисленного fatal issue.

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

### lawref.ask.AskError.code

*attribute* · *instance attribute*

```python
code = code
```

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

### lawref.ask.AskError.message

*attribute* · *instance attribute*

```python
message = message
```

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

### lawref.ask.AskError.envelope

*method*

```python
def envelope() -> dict
```

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

## lawref.ask.Prepared

*class* · *dataclass*

```python
class Prepared
```

Полный запрос и конверт подготовки (пины мира — вне caseHash).

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

### lawref.ask.Prepared.envelope

*attribute* · *class attribute* · *instance attribute*

```python
envelope: dict = field(default_factory=dict)
```

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

### lawref.ask.Prepared.request

*attribute* · *instance attribute*

```python
request: EvaluationRequest
```

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

## lawref.ask.ResourcesChecked

*class* · *dataclass*

```python
class ResourcesChecked
```

Свидетельство шага «ресурсы пакета сверены с локом» (LDC-E8704, PAR-007).

Сверка — свойство дерева пакета и его лока, а не дела: `discover_resources`
обходит всё дерево, документы конкретного дела сверяет отдельно
`check_documents`. Хост, понижающий много дел одного пакета
(`population-impact`, DECISION-0255 [§1](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/01-part-i-audit.ru.md#1-что-сохраняется-без-изменений)), сверяет ресурсы один раз при
открытии стороны и подаёт свидетельство в `prepare`/`ask`: без него пакет
из N дел стоил O(N²) обходов дерева (замер Ф6, 15.09.2026). Одиночный `ask`
свидетельства не имеет и сверяет на прежнем месте — порядок отказов [§168.4](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/24-part-xxiii-cases-snapshots-evaluation.ru.md#1684-пакет-дело-и-операция-ask-decision-0165)
не меняется. Порт — `law_cli_core::ask::ResourcesChecked`.

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

### lawref.ask.ResourcesChecked.root

*attribute* · *instance attribute*

```python
root: Path
```

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

## lawref.ask.ask

*function*

```python
def ask(root: Path, *, case_name: str | None, root_ir: dict, case: dict, query: dict, query_id: str | None = None, evaluator: Callable[[EvaluationRequest], dict] | None = None, context: dict | None = None, resources: ResourcesChecked | None = None, registration: RegistrationChecked | None = None) -> tuple[dict, dict]
```

Подготовка + evaluate: (evaluation-документ, конверт подготовки).

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

## lawref.ask.check_documents

*function*

```python
def check_documents(root: Path, lock: dict, case: dict) -> None
```

Каждый evidence с `uri`, указывающим внутрь пакета, обязан быть
закреплён ресурсом лока вида `document` с тем же хэшем байтов ([§168.4](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/24-part-xxiii-cases-snapshots-evaluation.ru.md#1684-пакет-дело-и-операция-ask-decision-0165)).

Целостность байтов — отказ подготовки, а не признание evidence
подлинным: приёмка опор остаётся у EvidencePolicy [§78.2](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/11-part-xi-assertions-facts-evidence.ru.md#782-исполнимый-профиль-evidencepolicy-lawcoreevidence-policy01).

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

## lawref.ask.check_package_resources

*function*

```python
def check_package_resources(root: Path, lock: dict) -> ResourcesChecked
```

Ресурсы пакета ↔ лок: первый расход — отказ `LDC-E8704`, иначе свидетельство.

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

## lawref.ask.check_query

*function*

```python
def check_query(query: dict, namespace: str, case_name: str, explicit_id: str | None = None) -> dict
```

Форма вопроса — по `query.schema.json`; `queryId` — по [§172](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/25-part-xxiv-queries-and-results.ru.md#172-standard-queries).

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

## lawref.ask.check_root

*function*

```python
def check_root(ir: dict, context: dict) -> None
```

Закрытый состав корня (LDC-E1355) и соответствие imports локу.

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

## lawref.ask.link

*function*

```python
def link(ir: dict, context: dict) -> dict
```

Слитый мир: узлы корня + узлы зависимостей, диагностики — отказ.

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

## lawref.ask.load_context

*function*

```python
def load_context(root: Path) -> dict
```

resolve-контекст пакета-дела с проверками [§11](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/04-part-iv-project-and-files.ru.md#11-lawlock)/[§23](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/06-part-vi-package-and-module-system.ru.md#23-import) и замыкания лока.

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

## lawref.ask.lowering_imports

*function*

```python
def lowering_imports(context: dict) -> list[dict]
```

Контекст `--imports` компилятора для корня, дела и вопроса.

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

## lawref.ask.prepare

*function*

```python
def prepare(root: Path, *, case_name: str | None, root_ir: dict, case: dict, query: dict, query_id: str | None = None, registered: list[RegisteredCase] | None = None, context: dict | None = None, resources: ResourcesChecked | None = None, registration: RegistrationChecked | None = None) -> Prepared
```

Полный `EvaluationRequest` из пониженных входов пакета-дела.

`root_ir` — CLIR корня, пониженный компилятором ПОД контекстом
`lowering_imports(load_context(root))`; `case` — документ дела, пониженный
под тем же контекстом и той же программой; `query` — вопрос [§172](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/25-part-xxiv-queries-and-results.ru.md#172-standard-queries).
`context` — уже загруженный `load_context(root)` вызывающего: тот же
контекст, под которым понижены входы, не читается и не валидируется
второй раз (цена — минуты `jsonschema` на большом мире).
`resources` — свидетельство `check_package_resources` того же корня:
ресурсы пакета уже сверены открытием пакета и второй раз не обходятся.
`registration` — свидетельство `cases.check_package_registration` того же
корня: регистрация дел уже проверена открытием пакета, манифест и
`.lawcase` второй раз не читаются.

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

## lawref.ask.query_id_for

*function*

```python
def query_id_for(namespace: str, case_name: str, given: str | None) -> str
```

`queryId` [§172](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/25-part-xxiv-queries-and-results.ru.md#172-standard-queries) (DECISION-0165 [§1.6](https://github.com/arxohq/law/blob/master/spec/SPEC.ru/01-part-i-audit.ru.md#1-что-сохраняется-без-изменений)): короткое имя дополняется до URN
пространства пакета-дела, полный URN сверяется с пространством.

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