lawref.loophole
Bounded-поиск лазеек — L8.2 плана LAYERS-NEXT (горизонт §5, заведён поручением владельца; см. spec/decisions/0035-loophole-and-amend.ru.md).
Лазейка — последовательность шагов (дата, утверждение), после которой цель
достигнута, а НИ НА ОДНОМ шаге не возникло позиции VIOLATED (§136–§137) или
CONFLICTED (§134 публикует и violated-сторону). Право на каждом шаге — своё:
документ проецируется на дату шага машиной применимости D1
(impact.edition_projection, §31), rule-окна effective §87 движок читает
сам. Факты аккумулируются: шаг добавляет одно положительное утверждение, и
каждый следующий шаг переоценивает ВЕСЬ накопленный мир на своей дате.
Оркестрация без семантики (инвариант CLAUDE.md №5): модуль только строит
входы (alphabet — по машинерии фаззера О-4), зовёт evaluate через
impact.run_scenario и читает витрину — статусы позиций из ответа на
positions-запрос и truth status цели. Ни одно правило права здесь не
интерпретируется; сравниваются выходы движка.
Поиск детерминирован БЕЗ PRNG: bounded model checking — исчерпывающий обход
в ширину (кратчайшие последовательности первыми) по отсортированным датам и
атомам, с капами и бюджетом вызовов evaluate; каждое усечение названо в
манифесте (правило «no silent caps»). Даты кандидатов добываются механически
из самого документа (границы effective, lifecycle редакций §31, Date-термы)
плюс день после каждой границы — ради «после окна».
Классификация находки — двумя контрольными прогонами, тоже через движок:
orderSensitive: те же утверждения одним пакетом на финальной дате НЕ проходят (значит существенна последовательность, не набор);timingSensitive: тот же пакет на ПОЗДНЕЙШЕЙ дате кандидатов не проходит (значит существенно окно — классическая лазейка «успеть до/переждать»).
Обход по проекции даёт и свою слепую зону, поэтому отчёт называет её сам:
если проекция сняла правила пакета, манифест несёт маркер
NORMS_NOT_IN_PROJECTION (то же имя, что у process-run, DECISION-0052 §8), а
снятые ВСЕ правила на всех датах поднимают projectionVoid — «ноль находок»
там сказано о пустом праве, а не об отсутствии лазеек. См.
projection_report.
Пространство поиска усекается ДО обхода двумя капами — атомов alphabet и
дат-кандидатов, — и оба управляются вызывающим (alphabet_cap, dates_cap;
флаги --alphabet-cap, --dates-cap). Усечение не молчит вдвойне: манифест
называет предикаты, у которых в alphabet не осталось НИ ОДНОГО действия
(alphabetOmittedPredicates — измерено 01.09.2026 на
doctrine/aba/equivalence-instruction: все 24 атома ушли на groundings журнала, и
целевое действие в алфавит не попало ни разу), а «не найдено» при усечённом
пространстве получает СВОЙ вердикт SPACE-TRUNCATED и код выхода 4 — по
тому же доводу, что PARAM-AXIS у impact-editions: конвейер не должен
читать «лазеек нет» там, где искали не во всём пространстве. Тот же код 4
у BUDGET-EXHAUSTED — обход, оборванный бюджетом посреди заданной глубины.
Положительная находка стоит и при усечении; см. verdict.
Не входит: генерация отрицательных утверждений и скалярных значений (alphabet — положительные атомы по пулам О-4); adjudicated-события §73; оценка «хорошо/плохо» — отчёт называет пути, судить о дыре — нормотворцу.
Attributes
| Name | Description |
|---|---|
ALPHABET_CAP | No description. |
DATES_CAP | No description. |
DEFAULT_BUDGET | No description. |
DEFAULT_DEPTH | No description. |
FINDINGS_CAP | No description. |
POSITIONS_QUERY | No description. |
PROJECTION_LOSS_KIND | No description. |
SCHEMA_VERSION | No description. |
SHRINK_BUDGET | No description. |
VERDICT_ALREADY | No description. |
VERDICT_BUDGET_EXHAUSTED | No description. |
VERDICT_EXIT | No description. |
VERDICT_FOUND | No description. |
VERDICT_NOT_FOUND | No description. |
VERDICT_PROJECTION_VOID | No description. |
VERDICT_SPACE_TRUNCATED | No description. |
VIOLATING_STATUSES | No description. |
Functions
| Name | Description |
|---|---|
emit_scenarios | Каждая находка — цепочка воспроизводимых сценариев формата О-1: |
exit_code | Код выхода CLI: 1 — найдено, 0 — не найдено во всём пространстве (или |
mine_dates | Даты-кандидаты из документа: (даты, было_ли_усечение). |
projection_report | Что проекция §31/D1 сняла с дат обхода: (маркеры, датируемого_не_осталось). |
render_text | No description. |
report_bytes | No description. |
run_search | Обход; отчёт детерминирован кортежем (документ, цель, depth, budget, |
truncation_lines | Строки об усечении пространства — одни на текстовый вид и на MCP. |
verdict | Вердикт отчёта — одна политика на текст, MCP и код выхода. |
verdict_hint | Пояснение к вердикту, общее для текстового вида и MCP. |
ALPHABET_CAPattributemodule attribute#
ALPHABET_CAP = 24DATES_CAPattributemodule attribute#
DATES_CAP = 6DEFAULT_BUDGETattributemodule attribute#
DEFAULT_BUDGET = 400DEFAULT_DEPTHattributemodule attribute#
DEFAULT_DEPTH = 3FINDINGS_CAPattributemodule attribute#
FINDINGS_CAP = 5POSITIONS_QUERYattributemodule attribute#
POSITIONS_QUERY = {'queryId': 'urn:query:loophole:positions', 'kind': 'positions'}PROJECTION_LOSS_KINDattributemodule attribute#
PROJECTION_LOSS_KIND = 'NORMS_NOT_IN_PROJECTION'SCHEMA_VERSIONattributemodule attribute#
SCHEMA_VERSION = 'law.loophole/0.1'SHRINK_BUDGETattributemodule attribute#
SHRINK_BUDGET = 120VERDICT_ALREADYattributemodule attribute#
VERDICT_ALREADY = 'ALREADY-REACHABLE'VERDICT_BUDGET_EXHAUSTEDattributemodule attribute#
VERDICT_BUDGET_EXHAUSTED = 'BUDGET-EXHAUSTED'VERDICT_EXITattributemodule attribute#
VERDICT_EXIT = {
VERDICT_FOUND: 1,
VERDICT_NOT_FOUND: 0,
VERDICT_ALREADY: 0,
VERDICT_PROJECTION_VOID: 3,
VERDICT_SPACE_TRUNCATED: 4,
VERDICT_BUDGET_EXHAUSTED: 4
}VERDICT_FOUNDattributemodule attribute#
VERDICT_FOUND = 'FOUND'VERDICT_NOT_FOUNDattributemodule attribute#
VERDICT_NOT_FOUND = 'NOT-FOUND'VERDICT_PROJECTION_VOIDattributemodule attribute#
VERDICT_PROJECTION_VOID = 'PROJECTION-VOID'VERDICT_SPACE_TRUNCATEDattributemodule attribute#
VERDICT_SPACE_TRUNCATED = 'SPACE-TRUNCATED'VIOLATING_STATUSESattributemodule attribute#
VIOLATING_STATUSES = ('VIOLATED', 'CONFLICTED')emit_scenariosfunction#
def emit_scenarios(report: dict, goal_scenario: dict, out_dir) -> intКаждая находка — цепочка воспроизводимых сценариев формата О-1: step-NN.json (positions-запрос на дате шага, факты накоплены) и goal.json (запрос цели на финальной дате).
exit_codefunction#
def exit_code(report: dict) -> intКод выхода CLI: 1 — найдено, 0 — не найдено во всём пространстве (или
цель достижима фоном), 3 — обход по пустому праву, 4 — обошли не всё:
пространство усечено капом либо бюджет кончился (см. summary.verdict).
mine_datesfunction#
def mine_dates(document: dict, extra: list[str], cap: int = DATES_CAP) -> tuple[list[str], bool]Даты-кандидаты из документа: (даты, было_ли_усечение).
Каждая найденная граница даёт и день ПОСЛЕ себя: включительность краёв различна (§87), и «сразу после окна» — отдельная точка поведения.
projection_reportfunction#
def projection_report(search: _Search, dates: list[str]) -> tuple[list[dict], bool]Что проекция §31/D1 сняла с дат обхода: (маркеры, датируемого_не_осталось).
ЗАЧЕМ ЭТО ЗДЕСЬ. Право каждого шага — проекция акта на дату шага, и это ровно то, чем ловятся лазейки «успеть до вступления» и «переждать». Но у пакета, чьи редакции не несут lifecycle-дат (обычай, доктрина, реставрация текста — их не «вводили в действие» датой, и это ВЕРНО про них), проекция снимает все заякоренные правила на ЛЮБУЮ дату: обход честно исполняет пустое право и честно не находит путей. «Findings: 0» при этом неотличимо от «лазеек нет» — тот же класс, что у process-run, закрытый находкой NORMS_NOT_IN_PROJECTION (DECISION-0052 §8).
Замерено 30.08.2026 на vory.corpus.ponyatiya: цель gnutyi достижима
одним шагом при обычном evaluate (TRUE_ONLY), а поиск возвращал ноль
находок и alreadyReachable: false — все 28 правил сняты на каждой из
дат-кандидатов, потому что ни одна из семи редакций lifecycle не
объявляет.
Оркестрация, не семантика (инвариант CLAUDE.md №5): сравнивается ЧИСЛО правил в проекции с числом правил документа, состояния редакций берутся из меты как есть. Ни одно правило права здесь не интерпретируется.
Даты с одинаковой подписью потери сливаются в один маркер: шесть одинаковых строк на шести датах — шум, а не диагноз.
render_textfunction#
def render_text(report: dict) -> strreport_bytesfunction#
def report_bytes(report: dict) -> bytesrun_searchfunction#
def run_search(document: dict, goal_scenario: dict, depth: int = DEFAULT_DEPTH, budget: int = DEFAULT_BUDGET, extra_dates: list[str] | None = None, alphabet_cap: int = ALPHABET_CAP, dates_cap: int = DATES_CAP) -> dict[str, Any]Обход; отчёт детерминирован кортежем (документ, цель, depth, budget, alphabet_cap, dates_cap).
goal_scenario — {“case”?: {…}, “query”: {…}, “expect”?: {…}}:
query — ground truth-запрос §168; case.assertions, если даны, — неизменный
фон каждого шага; expect.truthStatus — целевой статус (TRUE_ONLY).
truncation_linesfunction#
def truncation_lines(manifest: dict) -> list[str]Строки об усечении пространства — одни на текстовый вид и на MCP.
Называется не факт усечения, а его ЦЕНА: сколько атомов отброшено и какие предикаты остались без единого действия — по ним видно, искали ли там, где лежит ответ.
verdictfunction#
def verdict(report: dict) -> strВердикт отчёта — одна политика на текст, MCP и код выхода.
Порядок разбора несимметричен, как у impact.verdict: находка —
утверждение ПОЛОЖИТЕЛЬНОЕ об одном пути и стоит при любом усечении.
«Не найдено» — утверждение ОТРИЦАТЕЛЬНОЕ обо всём пространстве, и оно
печатается только когда пространство было обойдено целиком: не по пустому
праву (проекция сняла правила) и не по усечённому капом алфавиту или
списку дат. Иначе это SPACE-TRUNCATED — «в этих границах не найдено,
границы выбраны не вами».
verdict_hintfunction#
def verdict_hint(kind: str) -> strПояснение к вердикту, общее для текстового вида и MCP.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.