lawref.scenario
Shared scenario execution and edition projection (§31, §92, §168).
Independent Python implementation, also consumed by private impact tools. Historical error names are retained for compatibility with internal callers.
Classes
| Name | Description |
|---|---|
ImpactError | Отказ входа отчёта: дата проекции не есть LegalTime (§2.15/§82). |
ImpactWorldError | Отказ мира отчёта О-2 (DECISION-0193): программа предъявлена не целиком, |
Functions
| Name | Description |
|---|---|
edition_projection | Состояние корпуса as-of legal_time: (проекция, мета). |
link_presented_world | Программа отчёта О-2 (DECISION-0193): (программа, id узлов корня, состав |
projection_rule_loss | Что проекция §31/D1 сняла с даты: {lost, total, anchored, editions, |
run_scenario | Исполнить сценарий над документом: ('result', doc) | ('error', {...}). |
ImpactErrorclass#
class ImpactError(ValueError)Bases: ValueError
ImpactWorldErrorclass#
class ImpactWorldError(ImpactError)Bases: ImpactError
Отказ мира отчёта О-2 (DECISION-0193): программа предъявлена не целиком,
с лишним пакетом или на байтах, разошедшихся с закреплёнными. Код хоста
(FFI) — IMPACT_WORLD; текст отказа у CLI и FFI один.
codeattributeclass attributeinstance attribute#
code = 'IMPACT_WORLD'edition_projectionfunction#
def edition_projection(document: dict, legal_time: str, scope: frozenset[str] | None = None) -> tuple[dict, dict]Состояние корпуса as-of legal_time: (проекция, мета).
scope (DECISION-0193) — id узлов, о которых говорит МЕТА; проекция
при этом снимает узлы всего документа. Связанный мир проецируется
целиком — editionsAsPresented снимает условие 3 §92 со всех узлов
программы, и неспроецированная зависимость осталась бы живой на любую
дату, — а датировка, снятые узлы, состояния редакций и повисшие ссылки
отчёта называются по корню; о зависимостях — отдельной метой того же
вида. Без scope мета — обо всём документе, как прежде.
Нормативный узел снимается, если ВСЕ его разрешившиеся якоря ведут в
редакции, неприменимые на момент (машина D1 — applicability.edition_state
по lifecycle §31); достаточно одной применимой, чтобы узел остался.
Узел без якорей — вне датировки, остаётся. Якорь, не разрешившийся ни во
фрагмент, ни в редакцию, узел не датирует и называется в мете поимённо
(unresolvedAnchors) — принцип §249: не угадываем, а сообщаем.
Заякоренный нормативный узел, у которого не разрешился НИ ОДИН якорь,
остаётся применимым на любую дату — то есть выпадает из ответа целиком.
Мета считает такие узлы отдельно (undatedNodes поимённо,
anchoredNodeCount — знаменатель): именно по ним verdict отличает
«право не менялось» от «датировать было нечем».
Повисшие ссылки проекция не ЧИНИТ, но ДИАГНОСТИРУЕТ (остаток v1 закрыт
27.08.2026): выживший priority_rule §116, чьи higher/lower ведут в
снятый узел, называется в мете поимённо (danglingReferences) — вход
движку отдаётся как есть, что с висом делать — решает читатель отчёта
(§249: не угадываем, а сообщаем). Автопочинка была бы семантикой в
инструменте: что означает приоритет без одной из сторон — вопрос §116,
а не оркестрации.
link_presented_worldfunction#
def link_presented_world(document: dict, world: list[dict] | None, executing: bool) -> tuple[dict, frozenset[str] | None, list[dict]]Программа отчёта О-2 (DECISION-0193): (программа, id узлов корня, состав
мира). Без предъявленного мира и без исполнения — сам документ, None и
пустой состав: байты отчёта прежние.
Программа исполнения — корень и его закреплённое замыкание (§23, §24;
DECISION-0170: мир W = замыкание импортов C). До 11.09.2026 отчёт исполнял
один CLIR как программу целиком: у us-liver-status расчёт MELD §9.1.D
без unit_decl зависимости units.si (§49.2) падал в UNIT_UNKNOWN, и
отчёт печатал SEMANTIC-CHANGE с «изменившимся» контрольным делом —
утверждал изменение, которого в праве нет. Поэтому неполный мир при
исполнении сценариев — отказ, а не исход. Без сценариев исполнять нечего
(MCP law_editions спрашивает одну ось редакций корня), и один документ
остаётся допустимым входом.
Порядок отказов — от формы входа к байтам: документ без имени → дубль →
непредъявленный пакет замыкания → лишний пакет → связывание §23 (пины
E-0123, коллизии StableId §14) → версия семантики §168.4. Замыкание
строится обходом imports CLIR — ровно C §24; подтверждающих импортов
прелюдии law.std.* в imports CLIR нет (замер корпуса 11.09.2026).
projection_rule_lossfunction#
def projection_rule_loss(document: dict, meta: dict) -> dict | NoneЧто проекция §31/D1 сняла с даты: {lost, total, anchored, editions, examples} — или None, если не сняла ничего.
ЗАЧЕМ ЭТО ВООБЩЕ ЕСТЬ. Инструменты слоя О спрашивают право НА ДАТУ, то
есть считают по проекции, а не по всему пакету. Правило, снятое с даты, в
ответе неотличимо от правила, которому не хватило факта: разбор блокеров
§185 честно печатает «не закрыто: sogovor_qalyn_mal», а поиск лазеек
честно печатает «путей не найдено» — и читатель делает ровно неверный
вывод, что дело чего-то не доказало, а лазеек нет. Инструмент при этом
ЗНАЕТ причину: edition_projection возвращает вторым значением состояния
редакций и список снятых узлов.
Замерено на kz-tuystyq (process-run): из 93 правил на ЛЮБУЮ дату
остаётся 5 — те, что компилятор породил из самой procedure и потому не
заякорил; все 88 заякоренных сняты, потому что редакция TUYSTYQ_RU не
объявляет ни adopted, ни in_force (обычай не вводили в действие
датой, и пакет объясняет это в 06-sources.law). На
vory.corpus.ponyatiya (loophole) снимаются ВСЕ 28 правил — там ни одна
из семи редакций не несёт lifecycle вовсе.
Считаются ПРАВИЛА, а не узлы вообще: снятый фрагмент или symbol_decl на вывод не влияет, и мешать их в одно число значило бы пугать шумом.
anchored — знаменатель для вопроса «осталось ли ХОТЬ ЧТО-ТО, что
вообще можно датировать». Правило без якорей вне датировки по построению
(§31: узел без якорей остаётся применимым на любую дату), и его выживание
не говорит о праве акта ничего: у intl-istanbul-draft-2022 снято 136
правил из 149 — то есть ВСЕ 136 заякоренных, а уцелевшие 13 порождены
компилятором из procedure и якорей не несут. Считать такую проекцию
«частичной потерей» значило бы пропустить ровно тот случай, ради которого
счёт и заведён.
run_scenariofunction#
def run_scenario(document: dict, scenario: dict, extra_options: dict | None = None, editions_as_presented: str | None = None) -> tuple[str, dict]Исполнить сценарий над документом: (‘result’, doc) | (‘error’, {…}).
Контракт отказов — тот же, что у run_vector: pre-evaluation исключение
(календарь, лимиты) становится значением, а не падением инструмента, — Иначе
сценарий, роняющий ОДНУ из редакций, обрушил бы весь отчёт вместо того,
чтобы показать расхождение исходов.
extra_options — ВНЕШНИЕ РЕСУРСЫ вызывающего (сегодня: байты календарного
набора §85), а не вход семантики. Они кладутся мимо case, потому что
caseHash §170 канонизирует дело целиком, а байты в JSON не канонизируются
вовсе: положить их в case.options значит уронить КАЖДЫЙ вызов CanonError.
Пары «id набора» довольно, и она в деле уже есть — options.calendarSnapshot.
editions_as_presented (§92, errata E-0167) — дата, на которую состав
редакций document уже спроецирован ВЫЗЫВАЮЩИМ: при ней evaluate не
исполняет условие 3 §92 по дате права дела. Без неё сценарий над
ПРОЕКЦИЕЙ исполнялся бы по пересечению двух проекций — на дату проекции и
на дату дела; см. build_edition_report.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.