lawref.mutate
Детерминированные semantic mutations над CLIR.
Модуль намеренно работает с уже lowered Legal IR: он не переписывает
.law-исходники и не пытается угадать юридический текст. Каждый
дескриптор содержит достаточно данных, чтобы его можно было повторно
применить к тому же semantic snapshot через :func:apply_mutation.
Границы v1:
- перечисление не имеет скрытого лимита;
capдействует только когда вызывающий передал его явно и это отражено в manifest; invalidозначает, что операция дала бы невалидный CLIR либо нарушила базовую safety-проверку правила;stillbornозначает валидный результат с тем же semantic hash. Stillborn — generator-internal/non-score запись, а не mutant, который можно засчитать killed или survived;- contentHash меняется только у структурно изменённых узлов. В некоторых legacy-пакетах есть post-lowering attachments с историческим contentHash, и перерасчёт всех узлов превращал бы один mutant в шумный derived diff. Top-level semanticHash пересчитывается всегда.
Это не интерпретатор права. Он применяет только локальные структурные операторы, а корректность формы подтверждает нормативная JSON Schema.
Attributes
| Name | Description |
|---|---|
COMPARISON_SWAPS | No description. |
DEFAULT_OPERATORS | No description. |
SCHEMA_VERSION | No description. |
Classes
| Name | Description |
|---|---|
InvalidMutation | A descriptor cannot produce a schema- and safety-valid CLIR mutant. |
MutationError | Descriptor, base document, or caller contract is malformed. |
Functions
| Name | Description |
|---|---|
apply_mutation | Apply one descriptor to CLIR and return a fresh, rehashed document. |
enumerate_mutants | Enumerate valid CLIR mutants in canonical descriptor order. |
iter_mutants | Ленивый близнец enumerate_mutants: поток вместо материализации. |
report_bytes | Canonical, reproducible transport form of an enumeration result. |
COMPARISON_SWAPSattributemodule attribute#
COMPARISON_SWAPS = {
'eq': ('ne', 'ge', 'le'),
'ne': ('eq'),
'lt': ('le', 'eq'),
'le': ('lt', 'eq'),
'gt': ('ge', 'eq'),
'ge': ('gt', 'eq')
}DEFAULT_OPERATORSattributemodule attribute#
DEFAULT_OPERATORS = (
'drop_conjunct',
'swap_comparison',
'substitute_var',
'bind_entity_ref',
'freshen_var_occurrence',
'toggle_not_known',
'remove_not_known',
'drop_effective',
'remove_priority',
'remove_rule'
)SCHEMA_VERSIONattributemodule attribute#
SCHEMA_VERSION = 'law.mutate/0.1'InvalidMutationclass#
class InvalidMutation(MutationError)Bases: MutationError
A descriptor cannot produce a schema- and safety-valid CLIR mutant.
MutationErrorclass#
class MutationError(ValueError)Bases: ValueError
Descriptor, base document, or caller contract is malformed.
apply_mutationfunction#
def apply_mutation(document: dict, descriptor: dict) -> dictApply one descriptor to CLIR and return a fresh, rehashed document.
The source document is never mutated. Descriptor replay is guarded by the
semantic snapshot and each recorded before value, so applying a
descriptor to another edition fails loudly rather than drifting to a
similarly shaped location. This public entrypoint performs full document
preflight and validates the complete resulting document afterwards; bulk
enumeration uses the internal preflighted path once for throughput.
enumerate_mutantsfunction#
def enumerate_mutants(document: dict, operators: Iterable[str] | str | None = None, cap: int | None = None, nodes: Iterable[str] | None = None) -> dict[str, Any]Enumerate valid CLIR mutants in canonical descriptor order.
The return object is intentionally JSON-ready::
{"manifest": ..., "mutants": [{"descriptor": ..., "document": ...}], "invalid": [...], "stillborn": [...]}.cap=None means no cap. An explicit cap stops after that many valid
mutants in canonical order. The manifest names exactly how many later
descriptors were not examined, rather than pretending that cap is an
exhaustive result. nodes restricts candidates to the named carrier
nodes and is reflected in the manifest; existing callers without it get
byte-identical results (реализация — потребитель iter_mutants).
iter_mutantsfunction#
def iter_mutants(document: dict, operators: Iterable[str] | str | None = None, cap: int | None = None, nodes: Iterable[str] | None = None)Ленивый близнец enumerate_mutants: поток вместо материализации.
Появился из замера профайлера связывания (31.08.2026): на kz-income-tax
(16,7 МБ, 1681 правило) жадное перечисление — это 1681 deepcopy полного
документа с пересчётом semanticHash каждого, часы и гигабайты ДО первого
использования. Поток отдаёт ("valid" | "invalid" | "stillborn", запись)
в том же каноническом порядке и с теми же записями, что жадная форма,
но держит один мутант за раз; nodes сужает кандидатов по id узла.
report_bytesfunction#
def report_bytes(report: dict) -> bytesCanonical, reproducible transport form of an enumeration result.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.