lawref.resolver
Package resolution — инкременты WP-31/WP-35 (SPEC §10–§11, §22–§24, §209).
Реализовано: разбор law.toml (tomllib) в parsed-манифест формы
package-manifest.schema.json; каноничность имён пакетов (§22, T044: единый
код LDC-E1101 у manifest-/lockfile-ног здесь и source-ноги в lawc
law-hir/resolve.rs); проверка покрытия зависимостей lockfile-ом (§11:
нормативен разрешённый lock); dynamic reference §30.2 → exact resolved
edition в manifest.resolvedEditions §170 (T010); resolve-контекст WP-35 —
content-addressed загрузка зависимостей по lock (dev-layout deps/),
exports/pkg::Symbol (§22/§24, v1-конвенция публичности), envelope.imports
с хэшами пакетов в semantic hash (§209), линковка замкнутого мира для
межпакетного вывода (ворота — verify/ci/gates/compiler/check_package_resolve.py).
Отложено (перенесено в WP-35 решением DECISION-0030): команда lawc lock с
dependency/source diff поверх этого же контекста, registry-протокол вместо
dev-layout, offline-режим сборки (§243). Rust-нога резолюции в law-hir
доехала не вся: LDC-E1101–E1105 и E1108 там есть, отложены ДВА кода —
E1106 (транзитивная зависимость вне lock, §23) и E1107 (коллизия StableId
между пакетами, §14).
Attributes
| Name | Description |
|---|---|
DEP_PIN_CODE | No description. |
DEV_REGISTRY_ID | No description. |
DOCUMENTS_DIR | No description. |
EXPANSION_PIN_CODE | No description. |
EXPORTABLE_KINDS | No description. |
ID_COLLISION_CODE | No description. |
LAYER_DEPENDENCY_CODE | No description. |
LAYER_ORDER | No description. |
PACKAGE_NAME_CODE | No description. |
PACKAGE_NAME_RE | No description. |
SNAPSHOTS_DIR | No description. |
SYMBOL_RESOLVE_CODE | No description. |
TRANSITIVE_CODE | No description. |
VERSION_CONFLICT_CODE | No description. |
Classes
| Name | Description |
|---|---|
CalendarResourceError | Отказ оркестрации календарного ресурса DECISION-0110 §2.1. |
DependencySpec | Развёрнутая запись [dependencies] §10 (errata E-0160). |
Functions
| Name | Description |
|---|---|
canonical_package_name | No description. |
check_lock_coverage | §11: canonical build использует exact versions из lock — каждая зависимость |
check_locked_resources | PAR-007: semantic source edit без lock update останавливает build. |
check_names | T044 (часть manifest+lock): неканоничные имена отклоняются согласованно. |
clir_index | Имя пакета → файл *.lawir.json каталога CLIR (сканер верхнего уровня, |
content_descriptor | Registry-дескриптор из реальных байтов пакета (замена placeholder-а |
declared_layer | Объявленный слой пакета — [features] semanticLayer (§10). |
dependency_spec | Значение записи [dependencies] → развёрнутая запись (§10, E-0160). |
dev_descriptor | No description. |
diff_lock | Dependency diff (§11: обновление lock сопровождается diff-ом). |
discover_documents | Документы дела: каждый файл в resources/documents/** при корне пакета |
discover_resources | Детерминированно найти ресурсы пакета и построить записи law.lock 0.2: |
discover_snapshots | export.json каждого снимка при корне пакета, в порядке имён. |
effective_layer | Эффективный слой сборки для lockfile: максимум по корню и зависимостям. |
envelope_imports | LockedImport-ы для envelope.imports корневого CLIR (§209: semantic hash |
expansion_context | Контекст --expansions для компилятора: записи lock с абсолютным root. |
expansion_pins | Записи секции expansions law.lock по [expansions] манифеста: пакет |
export_bases | Надтипы публичных сущностей пакета: local name → StableId базы (§42). |
export_constants | E-0162: объявленные типы публичных констант из закреплённого CLIR. |
export_entity_types | E-0162: номинальные типы для контекстного entity_ref в value<T>. |
export_kinds | Public local name → CLIR node kind for a pinned dependency. |
export_relation_parameter_names | DECISION-0186: source parameter names, separate from E-0162 types. |
export_relation_parameters | E-0162: сигнатуры публичных отношений, принимающих value-позиции. |
export_source_fragments | Закреплённое evidence для публичного fragment в импортированном @source. |
exports | Публичные символы пакета: local name → StableId (§22 pkg::Symbol). |
fact_groups | Публичные факт-группы пакета (§23.1, DECISION-0069): имя группы → |
find_package_root | Ближайший вверх каталог с law.toml; файл начинает поиск с родителя. |
generate_lock | Разрешение манифеста в канонический law.lock (§11): exact versions, |
import_closure | Транзитивное замыкание импортов корня по загруженным снимкам зависимостей |
layer_diagnostics | LDC-E8102: зависимость объявляет слой выше собственного пакета. |
link_world | Замкнутый мир программы для evaluation: узлы корня + узлы зависимостей |
load_package_context | Загрузка и проверка resolve-контекста корня пакета (dev-layout выше). |
load_registry | No description. |
locked_dependencies | Зависимости манифеста, которые закрепляет law.lock (§11). |
lowering_imports | Resolve context consumed by lawc lower --imports. |
name_diagnostics | T044: диагностики неканоничных имён с каноническим кодом (§22/§199). |
package_content_hash | Content-хэш пакета: sha256 канонических байтов CLIR-документа (§208). |
package_root_for_locked_resource | Найти детерминированный package-root потребителя закреплённого ресурса. |
package_root_for_namespace | Найти package-root по нормативному namespace манифеста §10. |
parse_manifest | law.toml → parsed manifest (§10); валидность — по package-manifest.schema. |
plain_descriptor | Плоская запись пакета в локе (без registryId/resolverUri): имя, |
registry_for_library | Реестр и карта импортов для ВСЕЙ развёртки профиля B (DECISION-0170 |
registry_from_clir | Реестр и карта импортов для generate_lock из каталога CLIR: прямые |
resolve | Полная проверка пары manifest+lock; возвращает parsed manifest либо ValueError. |
resolve_calendar_resource | Прочитать календарь по law.lock и сверить оба digest-а (§85). |
resolve_dynamic_references | §30.2: каждый узел kind=reference разрешается в ровно одно source_edition, |
resolve_symbol | pkg::Symbol → StableId по exports контекста (§22/§24). |
schemas_load_and_validate_lock | No description. |
selected_calendar_snapshot | Тот же выбор §85, что у движков; неоднозначность оставляется движку. |
world_pin_diagnostics | Пины ВНУТРИ собранного мира (errata E-0123). |
DEP_PIN_CODEattributemodule attribute#
DEP_PIN_CODE = 'LDC-E1104'DEV_REGISTRY_IDattributemodule attribute#
DEV_REGISTRY_ID = 'law-dsl-dev'DOCUMENTS_DIRattributemodule attribute#
DOCUMENTS_DIR = 'resources/documents'EXPANSION_PIN_CODEattributemodule attribute#
EXPANSION_PIN_CODE = 'LDC-E1340'EXPORTABLE_KINDSattributemodule attribute#
EXPORTABLE_KINDS = (
'function_decl',
'symbol_decl',
'type_decl',
'fragment',
'rule',
'interpretation',
'deadline_policy',
'temporal_resolution_policy',
'evidence_policy'
)ID_COLLISION_CODEattributemodule attribute#
ID_COLLISION_CODE = 'LDC-E1107'LAYER_DEPENDENCY_CODEattributemodule attribute#
LAYER_DEPENDENCY_CODE = 'LDC-E8102'LAYER_ORDERattributemodule attribute#
LAYER_ORDER = {'L0': 0, 'L1': 1, 'L2': 2, 'L3': 3}PACKAGE_NAME_CODEattributemodule attribute#
PACKAGE_NAME_CODE = 'LDC-E1101'PACKAGE_NAME_REattributemodule attribute#
PACKAGE_NAME_RE = re.compile('^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*$')SNAPSHOTS_DIRattributemodule attribute#
SNAPSHOTS_DIR = 'resources/snapshots'SYMBOL_RESOLVE_CODEattributemodule attribute#
SYMBOL_RESOLVE_CODE = 'LDC-E1105'TRANSITIVE_CODEattributemodule attribute#
TRANSITIVE_CODE = 'LDC-E1106'VERSION_CONFLICT_CODEattributemodule attribute#
VERSION_CONFLICT_CODE = 'LDC-E1112'CalendarResourceErrorclass#
class CalendarResourceError(ValueError)Bases: ValueError
Отказ оркестрации календарного ресурса DECISION-0110 §2.1.
DependencySpecclass#
class DependencySpec(NamedTuple)Bases: NamedTuple
Развёрнутая запись [dependencies] §10 (errata E-0160).
Значение строки — либо версия-строка, либо таблица
{version, registry?, features?, optional?}; обе формы нормативны по
package-manifest.schema.json (§0.1 п. 5), и строковая есть сокращение
таблицы с одним version. Развёртка здесь одна на всех потребителей:
до E-0160 каждый читал значение записи как версию, и табличная форма
сравнивалась с закреплённой версией целым объектом.
canonical_package_namefunction#
def canonical_package_name(name: str) -> boolcheck_lock_coveragefunction#
def check_lock_coverage(manifest: dict, lock: dict) -> list[str]§11: canonical build использует exact versions из lock — каждая зависимость манифеста обязана быть закреплена (имя и точная версия).
Табличная запись §10 добавляет три сверки (errata E-0160): названный
издатель против registryId закреплённого пакета — только когда lock его
называет (молчание лока об издателе не есть утверждение об ином);
запрошенные возможности против его feature set; optional = true
освобождает зависимость от обязательного закрепления, но не от сверок,
если она всё-таки закреплена.
check_locked_resourcesfunction#
def check_locked_resources(root: Path, lock: dict) -> list[str]PAR-007: semantic source edit без lock update останавливает build.
check_namesfunction#
def check_names(manifest: dict, lock: dict) -> list[str]T044 (часть manifest+lock): неканоничные имена отклоняются согласованно.
clir_indexfunction#
def clir_index(clir_dir: Path) -> dict[str, Path]Имя пакета → файл *.lawir.json каталога CLIR (сканер верхнего уровня,
зеркало law-cli::imports_context::clir_index). Канонический JSON держит
package после nodes, поэтому имя читается с хвоста файла; полный
разбор — только при промахе.
content_descriptorfunction#
def content_descriptor(ir: dict) -> dictRegistry-дескриптор из реальных байтов пакета (замена placeholder-а dev_descriptor: contentHash — хэш канонических байтов CLIR).
declared_layerfunction#
def declared_layer(manifest: dict) -> str | NoneОбъявленный слой пакета — [features] semanticLayer (§10).
dependency_specfunction#
def dependency_spec(value) -> DependencySpecЗначение записи [dependencies] → развёрнутая запись (§10, E-0160).
Типы полей берутся ПО ФОРМЕ, а не приведением: registry — только
строка, optional — только true. Схема манифеста требует ровно этого,
но check_lock_coverage зовут и на несхемных словарях (векторы, ворота),
а приведение здесь разошлось бы с портом, где as_str/as_bool тоже
отвергают чужой тип. Байтовый контракт держится формой, не догадкой.
dev_descriptorfunction#
def dev_descriptor(name: str, version: str, namespace: str) -> dictdiff_lockfunction#
def diff_lock(old: dict, new: dict) -> list[str]Dependency diff (§11: обновление lock сопровождается diff-ом).
discover_documentsfunction#
def discover_documents(root: Path) -> list[Path]Документы дела: каждый файл в resources/documents/** при корне пакета
(DECISION-0165 §1.12). Скрытые файлы (.DS_Store, .gitkeep) — не
документы: они попадают в каталог помимо автора и ломали бы лок у каждого,
кто открыл папку. Порядок — по пути.
discover_resourcesfunction#
def discover_resources(root: Path) -> list[dict]Детерминированно найти ресурсы пакета и построить записи law.lock 0.2:
A3 sources (compile_time), оверлеи меток §218 (presentation,
DECISION-0069) и документы дела §168.4 (evidence, DECISION-0165 §1.12:
id — document:<путь внутри resources/documents/>, contentHash —
sha256 точных байтов). Оверлеи ищутся ТОЛЬКО в i18n/ при корне пакета — rglob
здесь ловил бы одноимённые каталоги внутри закреплённых байтов
sources/, которые пакету не принадлежат.
discover_snapshotsfunction#
def discover_snapshots(root: Path) -> list[Path]export.json каждого снимка при корне пакета, в порядке имён.
effective_layerfunction#
def effective_layer(manifest: dict, registry: dict[tuple[str, str], dict]) -> str | NoneЭффективный слой сборки для lockfile: максимум по корню и зависимостям.
None — если слой не объявлен ни у корня, ни у одной зависимости: пустое
поле честнее выдуманного L0.
envelope_importsfunction#
def envelope_imports(context: dict) -> list[dict]LockedImport-ы для envelope.imports корневого CLIR (§209: semantic hash покрывает хэши импортированных пакетов). Порядок — по имени пакета.
expansion_contextfunction#
def expansion_context(root: Path) -> tuple[list[dict], list[dict]]Контекст --expansions для компилятора: записи lock с абсолютным root.
Возвращает (контекст, диагностики). Алиас манифеста без записи в lock,
запись lock без алиаса, расхождение name/version/contentHash с байтами
каталога — LDC-E1340 (§279.1.8); «ближайшая версия» не выбирается.
expansion_pinsfunction#
def expansion_pins(root: Path, manifest: dict) -> list[dict]Записи секции expansions law.lock по [expansions] манифеста: пакет
определения читается по path (от корня потребителя), contentHash —
digest значимых файлов (lawref.expansion.pack_content_hash).
export_basesfunction#
def export_bases(ir: dict) -> dict[str, str]Надтипы публичных сущностей пакета: local name → StableId базы (§42).
Errata E-0121: lawc check ведёт цепь подтипов §42 через границу пакета
только по тому, что предъявил резолвер, — иначе два разных чужих имени
(должник закона о банкротстве, лицо ГК) для статики несравнимы. Считает,
как и exports, только оракул; в envelope.imports (§11/§209) не
переносится — это checking aid resolve-контекста, не семантика
потребителя. Сущность без базы записи не имеет: у компилятора «предъявлен
пакет, записи нет» и означает «надтипа нет».
export_constantsfunction#
def export_constants(ir: dict) -> dict[str, dict]E-0162: объявленные типы публичных констант из закреплённого CLIR.
export_entity_typesfunction#
def export_entity_types(ir: dict) -> list[str]E-0162: номинальные типы для контекстного entity_ref в value
export_kindsfunction#
def export_kinds(ir: dict) -> dict[str, str]Public local name → CLIR node kind for a pinned dependency.
Ordinary pkg::Symbol needs only the public export table. A qualified
@source(pkg::Fragment) has a stronger contract: a relation or function
with the same public spelling must never be accepted as a source-text
anchor. This map is therefore passed to the compiler as non-semantic
resolve-context evidence alongside exports; it is reconstructed from
the same pinned CLIR bytes and never travels in envelope.imports.
Enum variants have no own node. They remain ordinary exports for the
expression resolver and are marked enum_variant here so they cannot
masquerade as fragments.
export_relation_parameter_namesfunction#
def export_relation_parameter_names(ir: dict) -> dict[str, list[str]]DECISION-0186: source parameter names, separate from E-0162 types.
export_relation_parametersfunction#
def export_relation_parameters(ir: dict) -> dict[str, list[dict]]E-0162: сигнатуры публичных отношений, принимающих value-позиции.
export_source_fragmentsfunction#
def export_source_fragments(ir: dict) -> dict[str, dict]Закреплённое evidence для публичного fragment в импортированном @source.
Запись возникает только у public fragment со структурной связью с source_edition и собственным documentHash. Повреждённый text-record отбрасывает весь fragment. package contentHash отсутствует намеренно: он не заменяет хэш редакции или текста.
exportsfunction#
def exports(ir: dict) -> dict[str, str]Публичные символы пакета: local name → StableId (§22 pkg::Symbol).
§24: по умолчанию declaration является internal, и межпакетная ссылка на
него запрещена. В CLIR это поле visibility: "public" (пишется только для
pub-деклараций — умолчание не пишется, чтобы поле было аддитивным §209).
До DECISION-0011 здесь действовала конвенция «экспортируется всё, у чего
есть #»: pub не доезжал до CLIR, и различать было нечего.
Local name — часть StableId после #; узлы без # не адресуемы извне.
Член публичного перечисления экспортируется ВМЕСТЕ СО СВОИМ ТИПОМ (§24,
errata E-0065). Собственного узла у члена нет — type_decl несёт их
списком имён в variants (§55.1), — поэтому запись синтезируется:
{namespace}#{Член}, ровно тот StableId, каким лоуверится локальная
ссылка на член. До E-0065 экспортировался только тип, и pub enum был
декларацией без употребления: check ссылку на член принимал, lower
отвергал её LDC-E1105.
Порядок двухпроходный, и это не вкус: имя члена, совпавшее с именем
публичной ДЕКЛАРАЦИИ того же пакета, не вправе её вытеснить. У узла id
может быть переопределён @id(...) (§14) и тогда отличается от
{namespace}#{имя}; синтезированная запись назвала бы StableId, которого
в мире нет.
fact_groupsfunction#
def fact_groups(ir: dict) -> dict[str, list[dict]]Публичные факт-группы пакета (§23.1, DECISION-0069): имя группы → её assertion-узлы, отсортированные по id.
Носитель членства — provenance узла (factGroup, visibility), а не
поле visibility: у Assertion в схеме его нет, и это тот же род носителя,
каким A3 метит свои узлы (a3Kind). Считает состав ТОЛЬКО оракул — как
exports §24 (E-0065): компилятор потребителя материализует то, что ему
предъявили, и своего мнения о составе не имеет. Непубличные группы
наружу не выдаются: включение facts pkg::Группа; на них падает.
find_package_rootfunction#
def find_package_root(start: Path) -> Path | NoneБлижайший вверх каталог с law.toml; файл начинает поиск с родителя.
generate_lockfunction#
def generate_lock(manifest: dict, registry: dict[tuple[str, str], dict], resources: list[dict] | None = None, expansions: list[dict] | None = None, imports: dict[str, list[tuple[str, str]]] | None = None, *, library=None, profile_block: dict | None = None, root_imports: list[tuple[str, str]] | None = None) -> dictРазрешение манифеста в канонический law.lock (§11): exact versions, packages отсортированы по canonical identity, resolutionHash — derived-хэш без самого себя; generated-at/compiler build не включаются (§11).
imports — известные импорты закреплённых пакетов (имя → [(имя, версия)…], из envelope imports их CLIR): лок закрепляет ТРАНЗИТИВНОЕ
замыкание импортов корня, как того требует мир ask (DECISION-0165 §1.2,
LDC-E1358/LDC-E1106), с ребром от импортёра к импортируемому.
Транзитивная зависимость обязательна: реестр без неё — отказ. Без
imports (реестр без сведений об импортах) закрепляются прямые
зависимости — прежние байты.
import_closurefunction#
def import_closure(manifest: dict, packages: dict[str, dict]) -> set[str]Транзитивное замыкание импортов корня по загруженным снимкам зависимостей
(старт — строки [dependencies] манифеста; зеркало
law_resolver::context::import_closure). Достигнутое, но не загруженное
имя в замыкание входит — так подготовка ask видит нематериализованное C.
layer_diagnosticsfunction#
def layer_diagnostics(manifest: dict, registry: dict[tuple[str, str], dict]) -> list[dict]LDC-E8102: зависимость объявляет слой выше собственного пакета.
Зависимость без объявленного слоя пропускается молча: её слой неизвестен, а выдумывать «L0 по умолчанию» значило бы утверждать то, чего никто не проверял. Отсутствие объявления у КОРНЯ тоже не диагностируется — слой необязателен (LS §2.5), проверяется только заявленное.
link_worldfunction#
def link_world(root_ir: dict, context: dict) -> tuple[list[dict], list[dict]]load_package_contextfunction#
def load_package_context(root: Path) -> dictЗагрузка и проверка resolve-контекста корня пакета (dev-layout выше).
Возвращает {“manifest”, “lock”, “packages”: {name: ir}, “exports”: {name: {local: StableId}}, “exportKinds”: {name: {local: kind}}, “diagnostics”: […]}; диагностики — ошибки контекста (пиннинг/замкнутость), содержимое пакетов с ошибками не считается загруженным.
load_registryfunction#
def load_registry(registry_dir: Path) -> dict[tuple[str, str], dict]locked_dependenciesfunction#
def locked_dependencies(manifest: dict) -> list[tuple[str, DependencySpec]]Зависимости манифеста, которые закрепляет law.lock (§11).
Пакеты прелюдии law.std.* (errata E-0154, DECISION-0166 §4.3) сюда не
входят: словарь std приходит с версией семантики языка, реестра и
content-адреса у него нет, и строка [dependencies] с ним — только
подтверждение пина (сверяется компилятором с import, LDC-E1111), а не
зависимость для закрепления. Имена и слои (name_diagnostics,
layer_diagnostics) читают манифест целиком — там std остаётся
обычной строкой.
Значение записи отдаётся РАЗВЁРНУТЫМ (DependencySpec, errata E-0160):
закрепляется версия, а не форма, которой её записал автор.
lowering_importsfunction#
def lowering_imports(context: dict) -> list[dict]Resolve context consumed by lawc lower --imports.
envelope_imports intentionally contains only normative LockedImport
data, because it becomes part of the consumer’s semantic hash. The
compiler additionally needs resolver evidence to enforce §24 and the
fragment-only contract of cross-package @source; exports and kinds are
derived from the already hash-pinned dependency bytes and are omitted when
CLIR is emitted again.
name_diagnosticsfunction#
def name_diagnostics(manifest: dict | None, lock: dict | None) -> list[dict]T044: диагностики неканоничных имён с каноническим кодом (§22/§199).
Возвращает [{code, severity, surface, message}]; surface — какая нога валидации отклонила (manifest | lockfile); None пропускает ногу. Source-нога живёт в lawc (law-hir/resolve.rs) и эмитит ТОТ ЖЕ код — согласованность трёх ног проверяет вектор T044 (режим resolve).
package_content_hashfunction#
def package_content_hash(ir: dict) -> strContent-хэш пакета: sha256 канонических байтов CLIR-документа (§208). Именно он пиннится в law.lock и в envelope.imports потребителей.
package_root_for_locked_resourcefunction#
def package_root_for_locked_resource(laws_root: Path, resource_id: str, content_hash: str | None = None) -> Path | NoneНайти детерминированный package-root потребителя закреплённого ресурса.
Порождаемый официальный календарь KZ не имеет собственного source-пакета:
его runtime-байты закрепляют локи использующих календарь актов. Поэтому
MCP deadline ищет один из таких локов по id (и ожидаемому datasetHash), а
окончательную schema/type/hash-проверку всё равно делает
:func:resolve_calendar_resource.
package_root_for_namespacefunction#
def package_root_for_namespace(laws_root: Path, namespace: str) -> Path | NoneНайти package-root по нормативному namespace манифеста §10.
parse_manifestfunction#
def parse_manifest(law_toml_bytes: bytes) -> dictlaw.toml → parsed manifest (§10); валидность — по package-manifest.schema.
plain_descriptorfunction#
def plain_descriptor(desc: dict) -> dictПлоская запись пакета в локе (без registryId/resolverUri): имя,
версия, namespace, contentHash, отсортированные features — форма
sync_calendar_locks и локов пакетов-дел (зеркало lawc --plain-descriptors).
registry_for_libraryfunction#
def registry_for_library(library, clir_dir: Path, *, plain: bool = True) -> tuple[dict[tuple[str, str], dict], dict[str, list[tuple[str, str]]]]registry_from_clirfunction#
def registry_from_clir(manifest: dict, clir_dir: Path, *, plain: bool = True) -> tuple[dict[tuple[str, str], dict], dict[str, list[tuple[str, str]]]]Реестр и карта импортов для generate_lock из каталога CLIR: прямые
зависимости манифеста и — транзитивно — импорты их CLIR (envelope
imports[].package). Зеркало lawc lock --clir (DECISION-0165 §1.2).
resolvefunction#
def resolve(law_toml_path: Path, lock_path: Path) -> dictПолная проверка пары manifest+lock; возвращает parsed manifest либо ValueError.
resolve_calendar_resourcefunction#
def resolve_calendar_resource(root: Path, ir: dict, case: dict) -> bytes | NoneПрочитать календарь по law.lock и сверить оба digest-а (§85).
root — package-root либо любой путь внутри пакета. Относительный path
лока может выходить к общему corpus/clir (DECISION-0110, В1), но байты
всё равно принимаются только при совпадении contentHash строки лока и
datasetHash выбранного узла.
resolve_dynamic_referencesfunction#
def resolve_dynamic_references(nodes: list[dict], legal_time: str) -> tuple[dict[str, str], list[dict], list[dict]]§30.2: каждый узел kind=reference разрешается в ровно одно source_edition,
применимое на legal_time; результат — {reference.id: edition.id} для
manifest.resolvedEditions (§170), плюс записи резолюции для proof-узлов
source_resolution §182. Ошибки — fatal issues ДО вычисления:
- SOURCE_RESOLUTION_FAILED — ни одного применимого edition (§30.2: dynamic reference ДОЛЖНА разрешиться в static);
- SOURCE_RESOLUTION_AMBIGUOUS — несколько distinguishable source states на выбранный момент (§198-prose), либо granularity legal_time и lifecycle-границ различаются без TemporalResolutionPolicy (§82/§2.15).
Отвергнутые кандидаты собираются, а не выбрасываются (§182): без них
proof резолюции говорит «взята эта редакция» и молчит о том, какие ещё
рассматривались и почему не подошли, — а именно этот вопрос задаёт
why-not («источник не действовал»). Причина отклонения — состояние
редакции на момент (closed | not_yet | suspended), то же, что считает
edition_state; выдумывать здесь нечего.
Детерминизм: узлы и кандидаты обходятся в порядке ir.nodes.
resolve_symbolfunction#
def resolve_symbol(context: dict, package: str, local_name: str) -> tuple[str | None, list[dict]]schemas_load_and_validate_lockfunction#
def schemas_load_and_validate_lock(lock_path: Path) -> dictselected_calendar_snapshotfunction#
def selected_calendar_snapshot(ir: dict, case: dict) -> dict | NoneТот же выбор §85, что у движков; неоднозначность оставляется движку.
world_pin_diagnosticsfunction#
def world_pin_diagnostics(parts: list[tuple[str, dict]]) -> list[dict]Пины ВНУТРИ собранного мира (errata E-0123).
link_deps сверяет contentHash только тех зависимостей, которые ей
передали аргументами, — то есть прямых. Пин между двумя ЗАВИСИМОСТЯМИ не
сверял никто: мир, где акт B понижен против std@0.2.0, а узлы в мире от
std@0.1.0, исполнялся молча и давал вывод по чужой версии (проба ромба
DECISION-0112 §5.1, 04.09.2026).
Проверяется НЕ замкнутость: мир корпуса намеренно неполон — потребитель, который читает у соседа только ТИПЫ (алиасы хаба лиц), не обязан тащить его узлы. Проверяется совпадение: если импортируемый пакет в мире ЕСТЬ, его байты обязаны быть теми, на которых потребитель понижен.
Вторая проверка — две версии одного пакета в одном мире: сегодня их ловит коллизия StableId §14, но сообщение говорит об id, а не о причине.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.