Worked solutions
Complete records for the tour: every command with the output it produced on the pinned tool. Compare verdicts and proof shape when you repeat them; the long hashes in answer footers match whenever the inputs match.
Before you start
Section titled “Before you start”Run everything below from the extracted bundle root (corpus-lab/).
The tour materials, plus the silent scratch directory setup:
ls -d fixtures/parcels-*ls templates/*.mdmkdir -p /tmp/lab-workfixtures/parcels-appealsfixtures/parcels-appeals-0.2.0fixtures/parcels-case1fixtures/parcels-feesfixtures/parcels-fees-0.3.0fixtures/parcels-fees-0.4.0fixtures/parcels-ifacefixtures/parcels-iface-0.2.0fixtures/parcels-registryfixtures/parcels-registry-0.3.0templates/corpus-charter.mdtemplates/public-vocabulary-contract.mdtemplates/release-checklist.mdtemplates/review-checklist.mdtemplates/shared-dependency-change.mdtemplates/vocabulary-decision-record.mdThe ten parcels fixture states, the six templates the tour copies
from, and no output from the directory setup. The bundle’s
PINNED.md names the source revision these transcripts were
recorded against; the pack hashes further down pin every fixture’s
bytes behind that revision.
The tour runs on one build only — the public law-v0.1.1 release,
checked below on macOS arm64 (the Linux x64 binary hash is
sha256:be8b4fbb…; both are pinned in the bundle’s PINNED.md):
law versionlaw 0.1.1semantics: law.core/0.2std for language 0.2: 0.2.0lawql: lawql/1 (queryResult 0.1)binary hash: sha256:cfa7c17232f2dc594e665dbbf2ad3c154675797ef4be07ef7d758c9abfb80a28When two installs disagree, compare the first line first; the last
line identifies the exact bytes behind each install, so it differs
per platform. Do not substitute the checkout ./law launcher for
the tour: it builds newer source whose 0.2.6 numerals disagree with
these 0.2.4 fixtures (the fee scenario fails there). The checkout
launcher is needed only where a section says so explicitly.
The public composition is smaller than the checkout one. Structure and generator commands are absent from it:
law query --list 2>&1 | head -n 1law gen pinning 2>&1 | head -n 1law: unknown command querylaw: unknown command genThe Structure answers section and the two pinning runs below therefore carry their own checkout prerequisites; everything else runs on the public build above.
Scenario transcripts
Section titled “Scenario transcripts”Shared vocabulary, two scenarios:
law test fixtures/parcels-ifacelaw test labparcels.iface: world labparcels.iface ok [labparcels.iface#authored] tests/01-owns-ok.lawtest / urn:lab:parcels:iface:owns-ok ok [labparcels.iface#authored] tests/02-owns-unknown.lawtest / urn:lab:parcels:iface:owns-unknowntotal: 2 checked, 2 passed, 0 failed, 0 not run; code 0Registry act, four scenarios:
law test fixtures/parcels-registrylaw test labparcels.registry: world labparcels.registry, labparcels.iface ok [labparcels.registry#authored] tests/01-registered-ok.lawtest / urn:lab:parcels:registry:registered-ok ok [labparcels.registry#authored] tests/02-registered-missing-kind.lawtest / urn:lab:parcels:registry:registered-missing-kind ok [labparcels.registry#authored] tests/03-transfer-ok.lawtest / urn:lab:parcels:registry:transfer-ok ok [labparcels.registry#authored] tests/04-transfer-stranger.lawtest / urn:lab:parcels:registry:transfer-strangertotal: 4 checked, 4 passed, 0 failed, 0 not run; code 0Fees, five scenarios:
law test fixtures/parcels-feeslaw test labparcels.fees: world labparcels.fees, labparcels.iface, labparcels.registry ok [labparcels.fees#authored] tests/01-fee-residential-ok.lawtest / urn:lab:parcels:fees:residential-ok ok [labparcels.fees#authored] tests/02-fee-commercial-ok.lawtest / urn:lab:parcels:fees:commercial-ok ok [labparcels.fees#authored] tests/03-fee-garden-ok.lawtest / urn:lab:parcels:fees:garden-ok ok [labparcels.fees#authored] tests/04-fee-unregistered.lawtest / urn:lab:parcels:fees:unregistered ok [labparcels.fees#authored] tests/05-fee-wrong-amount.lawtest / urn:lab:parcels:fees:wrong-amounttotal: 5 checked, 5 passed, 0 failed, 0 not run; code 0Appeals, three scenarios:
law test fixtures/parcels-appealslaw test labparcels.appeals: world labparcels.appeals, labparcels.iface, labparcels.registry ok [labparcels.appeals#authored] tests/01-appeal-timely-ok.lawtest / urn:lab:parcels:appeals:timely-ok ok [labparcels.appeals#authored] tests/02-appeal-late.lawtest / urn:lab:parcels:appeals:late ok [labparcels.appeals#authored] tests/03-appeal-unregistered.lawtest / urn:lab:parcels:appeals:unregisteredtotal: 3 checked, 3 passed, 0 failed, 0 not run; code 0Worked case, four scenarios over the five-package world:
law test fixtures/parcels-case1law test labparcels.case1: world labparcels.case1, labparcels.appeals, labparcels.fees, labparcels.iface, labparcels.registry ok [labparcels.case1#authored] tests/01-worked-parcel.lawtest / urn:lab:parcels:case1:fee ok [labparcels.case1#authored] tests/01-worked-parcel.lawtest / urn:lab:parcels:case1:transfer ok [labparcels.case1#authored] tests/01-worked-parcel.lawtest / urn:lab:parcels:case1:appeal ok [labparcels.case1#authored] tests/01-worked-parcel.lawtest / urn:lab:parcels:case1:wrong-feetotal: 4 checked, 4 passed, 0 failed, 0 not run; code 0The rate revision, five scenarios over the original world:
law test fixtures/parcels-fees-0.3.0law test labparcels.fees: world labparcels.fees, labparcels.iface, labparcels.registry ok [labparcels.fees#authored] tests/01-fee-residential-ok.lawtest / urn:lab:parcels:fees:residential-ok ok [labparcels.fees#authored] tests/02-fee-commercial-ok.lawtest / urn:lab:parcels:fees:commercial-ok ok [labparcels.fees#authored] tests/03-fee-garden-ok.lawtest / urn:lab:parcels:fees:garden-ok ok [labparcels.fees#authored] tests/04-fee-unregistered.lawtest / urn:lab:parcels:fees:unregistered ok [labparcels.fees#authored] tests/05-fee-wrong-amount.lawtest / urn:lab:parcels:fees:wrong-amounttotal: 5 checked, 5 passed, 0 failed, 0 not run; code 0The renamed vocabulary, two scenarios:
law test fixtures/parcels-iface-0.2.0law test labparcels.iface: world labparcels.iface ok [labparcels.iface#authored] tests/01-holds-ok.lawtest / urn:lab:parcels:iface:holds-ok ok [labparcels.iface#authored] tests/02-holds-unknown.lawtest / urn:lab:parcels:iface:holds-unknowntotal: 2 checked, 2 passed, 0 failed, 0 not run; code 0The migrated act, four scenarios:
law test fixtures/parcels-registry-0.3.0law test labparcels.registry: world labparcels.registry, labparcels.iface ok [labparcels.registry#authored] tests/01-registered-ok.lawtest / urn:lab:parcels:registry:registered-ok ok [labparcels.registry#authored] tests/02-registered-missing-kind.lawtest / urn:lab:parcels:registry:registered-missing-kind ok [labparcels.registry#authored] tests/03-transfer-ok.lawtest / urn:lab:parcels:registry:transfer-ok ok [labparcels.registry#authored] tests/04-transfer-stranger.lawtest / urn:lab:parcels:registry:transfer-strangertotal: 4 checked, 4 passed, 0 failed, 0 not run; code 0The fee consumer on the renamed line, five scenarios:
law test fixtures/parcels-fees-0.4.0law test labparcels.fees: world labparcels.fees, labparcels.iface, labparcels.registry ok [labparcels.fees#authored] tests/01-fee-residential-ok.lawtest / urn:lab:parcels:fees:residential-ok ok [labparcels.fees#authored] tests/02-fee-commercial-ok.lawtest / urn:lab:parcels:fees:commercial-ok ok [labparcels.fees#authored] tests/03-fee-garden-ok.lawtest / urn:lab:parcels:fees:garden-ok ok [labparcels.fees#authored] tests/04-fee-unregistered.lawtest / urn:lab:parcels:fees:unregistered ok [labparcels.fees#authored] tests/05-fee-wrong-amount.lawtest / urn:lab:parcels:fees:wrong-amounttotal: 5 checked, 5 passed, 0 failed, 0 not run; code 0The appeal consumer on the renamed line, three scenarios:
law test fixtures/parcels-appeals-0.2.0law test labparcels.appeals: world labparcels.appeals, labparcels.iface, labparcels.registry ok [labparcels.appeals#authored] tests/01-appeal-timely-ok.lawtest / urn:lab:parcels:appeals:timely-ok ok [labparcels.appeals#authored] tests/02-appeal-late.lawtest / urn:lab:parcels:appeals:late ok [labparcels.appeals#authored] tests/03-appeal-unregistered.lawtest / urn:lab:parcels:appeals:unregisteredtotal: 3 checked, 3 passed, 0 failed, 0 not run; code 0Answers
Section titled “Answers”The answer text is printed in Russian: the public release renders answers
with the law.verb.ru verbalization pack, while the fixture names
(fee_due, parcel, p1) stay English. The phrases that recur in every
record below:
| Russian line | Meaning |
|---|---|
# Ответ по делу | Case answer (page title) |
> **Дисклеймер.** Ответ получен исполнением… | Disclaimer: the answer comes from executing a formalized model on the case data; it is neither the official text of the act nor a legal opinion |
## Вопрос / Установлено ли, что «X»? | Question / Is it established that X? |
## Ответ / Вычисление завершено. | Answer / The evaluation completed |
Установлено, что «X»; обратное не установлено. | X is established; its opposite is not |
Не установлено ни что «X», ни обратное. | Neither X nor its opposite is established (the model derives nothing either way; this is not a claim that X is false) |
## Основания | Grounds |
По правилу «R» | By rule R |
основание: фрагмент article/N издания «E» — «…» | Ground: fragment article/N of edition E, quoted |
Факт дела | Case fact |
см. шаг N | See step N (a repeated step printed once) |
сумма, собственник, день | Argument labels: amount, owner, day |
*Вопрос … · результат … · resultHash … · программа … · вербализация … · язык … · подробность: полное дерево* | Footer: question id, result id, result hash, program hash, verbalization pack, language, detail level (full tree) |
The fee question:
law ask fixtures/parcels-case1 --case ParcelTransfer --query-json fixtures/parcels-case1/queries/fee-answered.json --format text# Ответ по делу
> **Дисклеймер.** Ответ получен исполнением формализованной модели на данных дела. Это не официальный текст акта и не юридическое заключение.
## Вопрос
Установлено ли, что «fee_due» (parcel: `p1`, сумма: 100)?
## Ответ
Вычисление завершено.Установлено, что «fee_due» (parcel: `p1`, сумма: 100); обратное не установлено.
## Основания
- 1. По правилу «FeeResidential»: «fee_due» (parcel: `p1`, сумма: 100) - 2. По правилу «RegistrationComplete»: «registered» (parcel: `p1`) основание: фрагмент article/1 издания «PARCEL_REGISTRY_RULES_EN» — «1. Registration of parcels A parcel counts as registered when an owner holds it and a kind is recorded for it. A holding without a recorded kind registers nothing.» - 3. Факт дела: «owns» (собственник: `amy`, parcel: `p1`) - 4. Факт дела: «kind_of» (parcel: `p1`, kind: «residential») - см. шаг 4
---
*Вопрос `urn:law:lab:parcels:case1#case/ParcelTransfer/query/fee-answered` · результат `urn:result:case1#case/ParcelTransfer/query/fee-answered` · resultHash `sha256:dc3120593dd12d014b6fb50adb5a05403b0fbb43b6686d02ff4dcbfcf693c677` · программа `sha256:f219f1832a4945e55f3227f424ad69df7d4cab5c8691c6dd37e8ce7067eab182` · вербализация law.verb.ru@0.39.0 · язык ru-KZ · подробность: полное дерево*The transfer question:
law ask fixtures/parcels-case1 --case ParcelTransfer --query-json fixtures/parcels-case1/queries/transfer-answered.json --format text# Ответ по делу
> **Дисклеймер.** Ответ получен исполнением формализованной модели на данных дела. Это не официальный текст акта и не юридическое заключение.
## Вопрос
Установлено ли, что «transfer_granted» (parcel: `p1`, from: `amy`, to: `bob`)?
## Ответ
Вычисление завершено.Установлено, что «transfer_granted» (parcel: `p1`, from: `amy`, to: `bob`); обратное не установлено.
## Основания
- 1. По правилу «TransferGranted»: «transfer_granted» (parcel: `p1`, from: `amy`, to: `bob`) основание: фрагмент article/2 издания «PARCEL_REGISTRY_RULES_EN» — «2. Transfer of parcels A registered parcel transfers when its recorded owner asks for the transfer to a new owner. An ask from anyone else grants nothing.» - 2. По правилу «RegistrationComplete»: «registered» (parcel: `p1`) основание: фрагмент article/1 издания «PARCEL_REGISTRY_RULES_EN» — «1. Registration of parcels A parcel counts as registered when an owner holds it and a kind is recorded for it. A holding without a recorded kind registers nothing.» - 3. Факт дела: «owns» (собственник: `amy`, parcel: `p1`) - 4. Факт дела: «kind_of» (parcel: `p1`, kind: «residential») - 5. Факт дела: «transfer_request» (parcel: `p1`, from: `amy`, to: `bob`) - см. шаг 3
---
*Вопрос `urn:law:lab:parcels:case1#case/ParcelTransfer/query/transfer-answered` · результат `urn:result:case1#case/ParcelTransfer/query/transfer-answered` · resultHash `sha256:8c5deca4fb4bcf6fcbdda27f6715aba5807de7942803db573213f05b7ff000e7` · программа `sha256:f219f1832a4945e55f3227f424ad69df7d4cab5c8691c6dd37e8ce7067eab182` · вербализация law.verb.ru@0.39.0 · язык ru-KZ · подробность: полное дерево*The appeal question:
law ask fixtures/parcels-case1 --case ParcelTransfer --query-json fixtures/parcels-case1/queries/appeal-answered.json --format text# Ответ по делу
> **Дисклеймер.** Ответ получен исполнением формализованной модели на данных дела. Это не официальный текст акта и не юридическое заключение.
## Вопрос
Установлено ли, что «appeal_timely» (parcel: `p1`)?
## Ответ
Вычисление завершено.Установлено, что «appeal_timely» (parcel: `p1`); обратное не установлено.
## Основания
- 1. По правилу «AppealTimely»: «appeal_timely» (parcel: `p1`) - 2. По правилу «RegistrationComplete»: «registered» (parcel: `p1`) основание: фрагмент article/1 издания «PARCEL_REGISTRY_RULES_EN» — «1. Registration of parcels A parcel counts as registered when an owner holds it and a kind is recorded for it. A holding without a recorded kind registers nothing.» - 3. Факт дела: «owns» (собственник: `amy`, parcel: `p1`) - 4. Факт дела: «kind_of» (parcel: `p1`, kind: «residential») - 5. Факт дела: «appeal_filed» (parcel: `p1`, день: 25) - 6. Факт дела: «appeal_window» (parcel: `p1`, from_day: 10, to_day: 40)
---
*Вопрос `urn:law:lab:parcels:case1#case/ParcelTransfer/query/appeal-answered` · результат `urn:result:case1#case/ParcelTransfer/query/appeal-answered` · resultHash `sha256:eb9b1cf945f951ac18d09abb8eb6ece82566f0f37c4b8fa6da0e36becf449da1` · программа `sha256:f219f1832a4945e55f3227f424ad69df7d4cab5c8691c6dd37e8ce7067eab182` · вербализация law.verb.ru@0.39.0 · язык ru-KZ · подробность: полное дерево*How to read these records: the verdict line says the conclusion is established and its opposite is not; the grounds below it name the rule, the case facts, and — for registry steps — the pinned article each step leans on. The shared lines marked as repeated steps point back at an earlier step instead of printing it twice.
Why the fee question spells the amount the way it does: the rule head
fee_due(p, 100) compiles the literal into the shared number shape,
and the question file must use that same shape to meet it. The
compiled head, read from the pinned fees file inside the case world:
{"args": [{"kind": "var", "var": "v0"}, {"kind": "value", "type": {"name": "urn:law:std#Integer"}, "value": 250}], "kind": "literal", "polarity": "positive", "predicate": "urn:law:lab:parcels:fees#fee_due"}That row is the commercial rule; the residential rule the question
meets carries 100 in the same position. The fee question file
therefore passes the amount as an Integer 100 in the same typed
value shape, not as a bare literal. Scenario files need no such
care: they share the surface spelling with the rules, so 100
there meets 100 in the rule head.
Structure answers
Section titled “Structure answers”Prerequisites for this section only: a full repository checkout
and its ./law launcher, run from the repository root. The public
law composition has no query command (law: unknown command query), so these six runs cannot come from the bundle route.
The catalog holds twenty-two entries; the six question entries read (descriptions are printed in Russian; the English reading follows the listing):
anchors-of (node, pkg) — На какие закреплённые фрагменты опирается узел — акт, локатор и фрагмент каждого якоря.imports-of (pkg) — Что импортирует пакет — имена импортированных пакетов и их закреплённые semanticHash.links-of (node, pkg) — Все типизированные связи узла по отношению links — produces, reads, anchored, alias, subtype.producers (predicate, pkg) — Кто производит предикат в пакете — правила с этой головой, их сила, полярность и якоря.readers (predicate, pkg) — Кто читает предикат — литералы тел правил, норм и ограничений (головы исключены: их перечисляет producers); pkg может быть глобом, тогда видно чтение из других пакетов.type-step (type, pkg) — Один шаг цепочки типов субъекта — alias или subtype от названного типа к цели; следующий шаг — тот же вопрос с полученным to и пакетом цели.In English:
| Question | What it answers |
|---|---|
anchors-of (node, pkg) | Which pinned fragments a node rests on: the act, locator, and fragment of each anchor |
imports-of (pkg) | What a package imports: the imported package names and their pinned semanticHash |
links-of (node, pkg) | All typed links of a node in the links relation: produces, reads, anchored, alias, subtype |
producers (predicate, pkg) | Who produces a predicate in a package: rules with that head, their strength, polarity, and anchors |
readers (predicate, pkg) | Who reads a predicate: body literals of rules, norms, and constraints (heads are excluded; producers lists them); pkg may be a glob, which shows reads from other packages |
type-step (type, pkg) | One step of a subject’s type chain: an alias or subtype from the named type to its target; the next step is the same question with the returned to and the target’s package |
Who derives the registered flag:
./law query producers --project docs/corpus/lab/fixtures/parcels-registry --param predicate=urn:law:lab:parcels:registry#registered --param pkg=labparcels.registry1. producer: "urn:law:lab:parcels:registry#RegistrationComplete" | strength: "strict" | polarity: "positive" | anchors: [{"act":"urn:law:lab:parcels:registry#PARCEL_REGISTRY_RULES","anchor":"urn:law:lab:parcels:registry#PARCEL_RULE_1","locator":"article/1","path":"labparcels.registry.lawir.json"}] nodes: urn:law:lab:parcels:registry#PARCEL_REGISTRY_RULES, urn:law:lab:parcels:registry#PARCEL_RULE_1, urn:law:lab:parcels:registry#RegistrationComplete, urn:law:lab:parcels:registry#kind_of, urn:law:lab:parcels:registry#registered label: Parcel Registry Rules (fictional training text) file: labparcels.registry.lawir.json file: labparcels.registry.lawir.json source: article/1 — labparcels.registry.lawir.json label: recorded kind of the parcel file: labparcels.registry.lawir.json label: parcel is registered file: labparcels.registry.lawir.jsonRows: 1; packages in snapshot: 1.Who reads the holding link across the lab world:
./law query readers --project docs/corpus/lab/fixtures/parcels-case1 --param predicate=urn:law:lab:parcels:iface#owns --param pkg='labparcels.*'1. reader: "urn:law:lab:parcels:registry#RegistrationComplete" | context: "body.items[1].formula" | polarity: "positive" | package: "urn:law:lab:parcels:registry" nodes: urn:law:lab:parcels:iface#owns, urn:law:lab:parcels:registry#RegistrationComplete label: owner holds the parcel file: deps/labparcels.iface.lawir.json source: article/1 — deps/labparcels.registry.lawir.json2. reader: "urn:law:lab:parcels:registry#TransferGranted" | context: "body.items[2].formula" | polarity: "positive" | package: "urn:law:lab:parcels:registry" nodes: urn:law:lab:parcels:iface#owns, urn:law:lab:parcels:registry#TransferGranted label: owner holds the parcel file: deps/labparcels.iface.lawir.json source: article/2 — deps/labparcels.registry.lawir.jsonRows: 2; packages in snapshot: 5.What the registration rule leans on:
./law query anchors-of --project docs/corpus/lab/fixtures/parcels-registry --param node=urn:law:lab:parcels:registry#RegistrationComplete --param pkg=labparcels.registry1. fragment: "urn:law:lab:parcels:registry#PARCEL_RULE_1" | act: "urn:law:lab:parcels:registry#PARCEL_REGISTRY_RULES" | locator: "article/1" nodes: urn:law:lab:parcels:registry#PARCEL_REGISTRY_RULES, urn:law:lab:parcels:registry#PARCEL_RULE_1, urn:law:lab:parcels:registry#RegistrationComplete label: Parcel Registry Rules (fictional training text) file: labparcels.registry.lawir.json file: labparcels.registry.lawir.json source: article/1 — labparcels.registry.lawir.jsonRows: 1; packages in snapshot: 1.How the parcel type resolves:
./law query type-step --project docs/corpus/lab/fixtures/parcels-registry --param type=urn:law:lab:parcels:registry#Parcel --param pkg=labparcels.registry1. step: "alias" | to: "urn:law:lab:parcels:iface#Parcel" nodes: urn:law:lab:parcels:registry#Parcel file: labparcels.registry.lawir.jsonRows: 1; packages in snapshot: 1.What the case package pulls in:
./law query imports-of --project docs/corpus/lab/fixtures/parcels-case1 --param pkg=labparcels.case11. imported: "labparcels.appeals" | semantic_hash: "sha256:0000000000000000000000000000000000000000000000000000000000000000"2. imported: "labparcels.fees" | semantic_hash: "sha256:0000000000000000000000000000000000000000000000000000000000000000"3. imported: "labparcels.iface" | semantic_hash: "sha256:0000000000000000000000000000000000000000000000000000000000000000"4. imported: "labparcels.registry" | semantic_hash: "sha256:0000000000000000000000000000000000000000000000000000000000000000"Rows: 4; packages in snapshot: 1.Those four zero hashes need a gloss. Each semantic_hash is the pinned
digest the importing package records for one imported package in its own
compiled imports table — not a digest computed over the dependency bytes
at query time. The machine-readable form of the same question names the
snapshot the rows come from: the case package’s own compiled program,
one package:
./law query imports-of --project docs/corpus/lab/fixtures/parcels-case1 --param pkg=labparcels.case1 --format json | python3 -c "import json,sys; r=json.load(sys.stdin); print(json.dumps(r['manifest']['corpus'],indent=1))"[ { "package": "labparcels.case1", "semanticHash": "sha256:825c4816a2131db5bae1f1080363969ff9474d1f43c7f44ec6e6b3b335873c87" }]The snapshot digest (825c4816…) is the checkout toolchain’s
compilation of the case program — it differs from the public-release
program digest in the answer footers (f219f183…), because the two
compositions compile numerals differently (Integer versus Number).
The rows above come from that same checkout run over the shipped
0.2.4 dependency bytes. In these lab snapshots the per-import pins
are unset, so
every row reads zero. The pins that actually lock the world live
beside them in the case lockfile, one content digest per imported
package:
python3 -c "import json; lock=json.load(open('fixtures/parcels-case1/law.lock')); [print(p['name']+'@'+p['version'], p['contentHash']) for p in lock['packages']]"labparcels.appeals@0.1.0 sha256:92860bd5cd0ac02edbe666965d8430fb360dc5f938fcabaee4d83f1f95b7df6elabparcels.fees@0.2.0 sha256:dfe81269bfe070987ada69e4c2545e9c31a755aa1600be72a8242a00c30dbde4labparcels.iface@0.1.0 sha256:23b7a38c3f80dc22015fe983e6ae21083e4d52d9ef1309a5e36d964cf0a31ac2labparcels.registry@0.1.0 sha256:15b5bd7fe6f4260b5e2f94e9c8ba5af53150e36c55365b3d463e5bc34215368fThose four digests match the packed content digests quoted in the versions exercise, and each matches the pinned bytes the lockfile check verifies.
Read together: one rule derives the registered flag; two rules read the holding link; the registration rule leans on the first article; the registry parcel type is an alias of the shared parcel type; the case package pulls in all four lab packages. A named question without its package parameter is refused; the tool names the missing piece.
Provenance answers
Section titled “Provenance answers”The pinning check and the audit below need the checkout route:
run both from the repository root with ./law. The public
composition has neither gen nor the lint catalog the audit’s
last line reports on. The remaining checks in this section run on
the public route from the bundle root.
The pinning check, flagless form:
./law gen pinning docs/corpus/lab/fixtures/parcels-registry ✓ pinning.toml → sources.law [en-US] (2 articles)The audit over the same fixture:
./law audit docs/corpus/lab/fixtures/parcels-registrylaw audit labparcels.registry — formalization measure §33.1 (E-0249), profile staticCLIR lowered from sources (imports: deps); freshness: verifiedlevels not computed by this implementation: STRUCTURED, SEMANTIC
— urn:law:lab:parcels:registry#PARCEL_REGISTRY_RULES_TXT — unit: пункт (point), path declared; units 2, excluded 0 EXECUTABLE 2, ANCHORED 0, SOURCE_ONLY 0, without nodes 0; reading-only under §152: 0 aggregated model (detail not confirmed): none text coverage: 317 of 369 bytes (85.9 %), fragments 2
form (LawQL catalog lints on fresh snapshot, DECISION-0394): detectors 16, findings 0dangling premises: 0 (unsupplied by package 0, enum variants in body 0)one-way premises: 0 of 2 rulesBoth articles executable, both fragments covering most of the pinned bytes, sixteen structural checks with no findings. The small articles file beside the pinned text declares the denominator the measure counts against; without it the publication reports no text and the measure is not taken.
The import-block check:
law fix imports fixtures/parcels-registry --checkfixtures/parcels-registry `use self` blocks are canonicalThe manifest reading:
law engine manifest fixtures/parcels-registry/law.toml{"authoring":{"local_imports":"explicit"},"dependencies":{"labparcels.iface":"0.1.0"},"features":{"semanticLayer":"L3"},"package":{"language":"0.2","name":"labparcels.registry","namespace":"urn:law:lab:parcels:registry","version":"0.1.0"}}The lock readings, one per fixture:
law engine lock fixtures/parcels-iface --checklaw engine lock fixtures/parcels-registry --checklaw engine lock fixtures/parcels-fees --checklaw engine lock fixtures/parcels-appeals --checklaw engine lock fixtures/parcels-case1 --checklock: fixtures/parcels-iface/law.lock matches law.toml and resourceslock: fixtures/parcels-registry/law.lock matches law.toml and resourceslock: fixtures/parcels-fees/law.lock matches law.toml and resourceslock: fixtures/parcels-appeals/law.lock matches law.toml and resourceslock: fixtures/parcels-case1/law.lock matches law.toml and resourcesThe offline install:
law install --offline --project fixtures/parcels-registryall in place: deps/ and resources already match law.lockno changesStatics pass on all five fixtures as well; each law engine check
answers check OK with the fixture name.
Versions exercise
Section titled “Versions exercise”Pack the five fixtures. Each answer names the artifact directory and two hashes; the content hash pins the package bytes, the world hash pins the package with its closure:
law pack --out /tmp/lab-work/artifacts/iface --project fixtures/parcels-ifacelaw pack --out /tmp/lab-work/artifacts/registry --project fixtures/parcels-registrylaw pack --out /tmp/lab-work/artifacts/fees --project fixtures/parcels-feeslaw pack --out /tmp/lab-work/artifacts/appeals --project fixtures/parcels-appealslaw pack --out /tmp/lab-work/artifacts/case1 --project fixtures/parcels-case1labparcels.iface@0.1.0 → /tmp/lab-work/artifacts/iface: contentHash sha256:23b7a38c3f80dc22015fe983e6ae21083e4d52d9ef1309a5e36d964cf0a31ac2, worldHash sha256:23b7a38c3f80dc22015fe983e6ae21083e4d52d9ef1309a5e36d964cf0a31ac2, 3 fileslabparcels.registry@0.1.0 → /tmp/lab-work/artifacts/registry: contentHash sha256:15b5bd7fe6f4260b5e2f94e9c8ba5af53150e36c55365b3d463e5bc34215368f, worldHash sha256:13ef321e7bf4e5e44b45f2142e1f000e2ba4ffbf749cb3694041993bb6346ef2, 3 fileslabparcels.fees@0.2.0 → /tmp/lab-work/artifacts/fees: contentHash sha256:dfe81269bfe070987ada69e4c2545e9c31a755aa1600be72a8242a00c30dbde4, worldHash sha256:056a48336aba96920988682a4a72e723c35a9d177f094d549f79df1739322b7a, 3 fileslabparcels.appeals@0.1.0 → /tmp/lab-work/artifacts/appeals: contentHash sha256:92860bd5cd0ac02edbe666965d8430fb360dc5f938fcabaee4d83f1f95b7df6e, worldHash sha256:866374f2e79343b9cef623feeef6961574b32a6fce02c2533d486eb97fc1012e, 3 fileslabparcels.case1@0.1.0 → /tmp/lab-work/artifacts/case1: contentHash sha256:14ae7edbf58225f3fdf1cc7b5f21cb14ac33fb223795a2834d4c8d765b6f0cdc, worldHash sha256:59059bde677910196f9d3533e782716e9cd776e21e2b873119a3c35d191bce10, 3 filesPublish the five artifacts into one throwaway registry. The first publish creates the registry; each publish then lists the known versions and the descriptor and blob files it wrote:
law publish /tmp/lab-work/artifacts/iface --registry lab=/tmp/lab-work/registrylaw publish /tmp/lab-work/artifacts/registry --registry lab=/tmp/lab-work/registrylaw publish /tmp/lab-work/artifacts/fees --registry lab=/tmp/lab-work/registrylaw publish /tmp/lab-work/artifacts/appeals --registry lab=/tmp/lab-work/registrylaw publish /tmp/lab-work/artifacts/case1 --registry lab=/tmp/lab-work/registryregistry lab created: /tmp/lab-work/registrylabparcels.iface@0.1.0 → lab (/tmp/lab-work/registry): contentHash sha256:23b7a38c3f80dc22015fe983e6ae21083e4d52d9ef1309a5e36d964cf0a31ac2, worldHash sha256:23b7a38c3f80dc22015fe983e6ae21083e4d52d9ef1309a5e36d964cf0a31ac2versions labparcels.iface: 0.1.0changed: p/labparcels.iface/0.1.0/package.lawir.jsonchanged: p/labparcels.iface/0.1.0/world.lawir.jsonchanged: p/labparcels.iface/0.1.0.jsonlabparcels.registry@0.1.0 → lab (/tmp/lab-work/registry): contentHash sha256:15b5bd7fe6f4260b5e2f94e9c8ba5af53150e36c55365b3d463e5bc34215368f, worldHash sha256:13ef321e7bf4e5e44b45f2142e1f000e2ba4ffbf749cb3694041993bb6346ef2versions labparcels.registry: 0.1.0changed: p/labparcels.registry/0.1.0/package.lawir.jsonchanged: p/labparcels.registry/0.1.0/world.lawir.jsonchanged: p/labparcels.registry/0.1.0.jsonlabparcels.fees@0.2.0 → lab (/tmp/lab-work/registry): contentHash sha256:dfe81269bfe070987ada69e4c2545e9c31a755aa1600be72a8242a00c30dbde4, worldHash sha256:056a48336aba96920988682a4a72e723c35a9d177f094d549f79df1739322b7aversions labparcels.fees: 0.2.0changed: p/labparcels.fees/0.2.0/package.lawir.jsonchanged: p/labparcels.fees/0.2.0/world.lawir.jsonchanged: p/labparcels.fees/0.2.0.jsonlabparcels.appeals@0.1.0 → lab (/tmp/lab-work/registry): contentHash sha256:92860bd5cd0ac02edbe666965d8430fb360dc5f938fcabaee4d83f1f95b7df6e, worldHash sha256:866374f2e79343b9cef623feeef6961574b32a6fce02c2533d486eb97fc1012eversions labparcels.appeals: 0.1.0changed: p/labparcels.appeals/0.1.0/package.lawir.jsonchanged: p/labparcels.appeals/0.1.0/world.lawir.jsonchanged: p/labparcels.appeals/0.1.0.jsonlabparcels.case1@0.1.0 → lab (/tmp/lab-work/registry): contentHash sha256:14ae7edbf58225f3fdf1cc7b5f21cb14ac33fb223795a2834d4c8d765b6f0cdc, worldHash sha256:59059bde677910196f9d3533e782716e9cd776e21e2b873119a3c35d191bce10versions labparcels.case1: 0.1.0changed: p/labparcels.case1/0.1.0/package.lawir.jsonchanged: p/labparcels.case1/0.1.0/world.lawir.jsonchanged: p/labparcels.case1/0.1.0.jsonCurrency against that registry reports every pin up to date, exit 0:
law outdated --project fixtures/parcels-fees --registry lab=/tmp/lab-work/registrylaw outdated --project fixtures/parcels-case1 --registry lab=/tmp/lab-work/registrylab ← /tmp/lab-work/registry (--registry)labparcels.iface@0.1.0 [lab]: up to datelabparcels.registry@0.1.0 [lab]: up to datelab ← /tmp/lab-work/registry (--registry)labparcels.appeals@0.1.0 [lab]: up to datelabparcels.fees@0.2.0 [lab]: up to datelabparcels.iface@0.1.0 [lab]: up to datelabparcels.registry@0.1.0 [lab]: up to dateAuthor revision 0.2.0 of the registry package on a scratch copy.
The in-place rewrites use perl, which behaves the same on both
supported platforms; the appended block is the only addition to the
rules file:
cp -r fixtures/parcels-registry /tmp/lab-work/reg02perl -pi -e 's/^version = "0.1.0"/version = "0.2.0"/' /tmp/lab-work/reg02/law.tomlperl -pi -e 's/package labparcels.registry version "0.1.0"/package labparcels.registry version "0.2.0"/' /tmp/lab-work/reg02/package.law /tmp/lab-work/reg02/sources.law /tmp/lab-work/reg02/tests/*.lawtestcat >> /tmp/lab-work/reg02/package.law <<'EOF'
pub relation kind_recorded(parcel: Parcel) kind derived { label en unofficial "parcel has a recorded kind";}
@source(PARCEL_RULE_1)rule KindRecorded strict { for p: Parcel; for k: ParcelKind; when kind_of(p, k); then kind_recorded(p);}EOFlaw test /tmp/lab-work/reg02Bump the package headers only, not the import line, which keeps pointing at the shared vocabulary at 0.1.0. The copied pins still hold, so the four scenarios pass with no rewiring step:
law test labparcels.registry: world labparcels.registry, labparcels.iface ok [labparcels.registry#authored] tests/01-registered-ok.lawtest / urn:lab:parcels:registry:registered-ok ok [labparcels.registry#authored] tests/02-registered-missing-kind.lawtest / urn:lab:parcels:registry:registered-missing-kind ok [labparcels.registry#authored] tests/03-transfer-ok.lawtest / urn:lab:parcels:registry:transfer-ok ok [labparcels.registry#authored] tests/04-transfer-stranger.lawtest / urn:lab:parcels:registry:transfer-strangertotal: 4 checked, 4 passed, 0 failed, 0 not run; code 0Then pack and publish the revision into the same registry:
law pack --out /tmp/lab-work/artifacts/registry-0.2.0 --project /tmp/lab-work/reg02law publish /tmp/lab-work/artifacts/registry-0.2.0 --registry lab=/tmp/lab-work/registrylabparcels.registry@0.2.0 → /tmp/lab-work/artifacts/registry-0.2.0: contentHash sha256:fc69df17896dd8c60a4a4889e2313fd3228b234444bf0e36d98a94372ab96ce2, worldHash sha256:b3056c550cfaf9c58fa84befda4557d3b6c5020fdfc8c324086335343998e597, 3 fileslabparcels.registry@0.2.0 → lab (/tmp/lab-work/registry): contentHash sha256:fc69df17896dd8c60a4a4889e2313fd3228b234444bf0e36d98a94372ab96ce2, worldHash sha256:b3056c550cfaf9c58fa84befda4557d3b6c5020fdfc8c324086335343998e597versions labparcels.registry: 0.1.0, 0.2.0changed: p/labparcels.registry/0.2.0/package.lawir.jsonchanged: p/labparcels.registry/0.2.0/world.lawir.jsonchanged: p/labparcels.registry/0.2.0.jsonCurrency now flags the new revision and exits 1; the lock stays untouched:
law outdated --project fixtures/parcels-fees --registry lab=/tmp/lab-work/registrylab ← /tmp/lab-work/registry (--registry)labparcels.iface@0.1.0 [lab]: up to datelabparcels.registry@0.1.0 [lab]: published 0.2.0Move a scratch copy of the fees consumer across. Copy first, which is silent, then preview:
cp -r fixtures/parcels-fees /tmp/lab-work/fees-updlaw update 'labparcels.registry@0.2.0' --project /tmp/lab-work/fees-upd --registry lab=/tmp/lab-work/registry --dry-runlab ← /tmp/lab-work/registry (--registry)--dry-run: staged and verified, no file changed~ labparcels.registry 0.1.0 -> 0.2.0changed: .law/transport.jsonchanged: deps/labparcels.registry.lawir.jsonchanged: law.lockchanged: law.tomlchanged: package.lawThen run the same command without the preview flag:
law update 'labparcels.registry@0.2.0' --project /tmp/lab-work/fees-upd --registry lab=/tmp/lab-work/registrylab ← /tmp/lab-work/registry (--registry)~ labparcels.registry 0.1.0 -> 0.2.0changed: .law/transport.jsonchanged: deps/labparcels.registry.lawir.jsonchanged: law.lockchanged: law.tomlchanged: package.lawThe update rewrites the import line to the new version alongside the manifest, the lock, and the pinned bytes. The consumer scenarios still pass five for five, and currency reports both pins up to date with exit 0:
law test /tmp/lab-work/fees-upd | tail -n 1law outdated --project /tmp/lab-work/fees-upd --registry lab=/tmp/lab-work/registrytotal: 5 checked, 5 passed, 0 failed, 0 not run; code 0lab ← /tmp/lab-work/registry (--registry)labparcels.iface@0.1.0 [lab]: up to datelabparcels.registry@0.2.0 [lab]: up to dateTwo refusals close the exercise. Asking for a revision that was never published:
law update 'labparcels.registry@0.9.9' --project /tmp/lab-work/fees-upd --registry lab=/tmp/lab-work/registrylaw: REFUSAL: registry lab, p/labparcels.registry/0.9.9.json: No such file or directory (os error 2)And editing one fragment line by hand on another scratch copy, which
the pinning check catches. The copy and the one-word edit are
silent; the check and the diff answer. Start from the bundle root
as above; the two generator calls need the checkout (gen is not
in the public composition), so they run in a subshell there:
cp -r fixtures/parcels-registry /tmp/lab-work/regdrift: "${ARXO_CHECKOUT:?absolute path to the full checkout}"perl -pi -e 's/registers nothing\."""/registers nothing much."""/' /tmp/lab-work/regdrift/sources.law(cd "$ARXO_CHECKOUT" && ./law gen pinning /tmp/lab-work/regdrift)(cd "$ARXO_CHECKOUT" && ./law gen pinning /tmp/lab-work/regdrift --diff) ✗ pinning.toml → sources.law [en-US] (2 articles) ✗ pinning.toml → sources.law [en-US] (2 articles)--- sources.law+++ pinning.toml@@ -7,3 +7,3 @@-recorded for it. A holding without a recorded kind registers nothing much.""";+recorded for it. A holding without a recorded kind registers nothing.""";Stage A exercise
Section titled “Stage A exercise”Pack the original five states plus the fee revision into the stage directory:
mkdir -p /tmp/lab-work/stage-a/artifacts /tmp/lab-work/stage-a/answerslaw pack --out /tmp/lab-work/stage-a/artifacts/iface --project fixtures/parcels-ifacelaw pack --out /tmp/lab-work/stage-a/artifacts/registry --project fixtures/parcels-registrylaw pack --out /tmp/lab-work/stage-a/artifacts/fees --project fixtures/parcels-feeslaw pack --out /tmp/lab-work/stage-a/artifacts/appeals --project fixtures/parcels-appealslaw pack --out /tmp/lab-work/stage-a/artifacts/case1 --project fixtures/parcels-case1law pack --out /tmp/lab-work/stage-a/artifacts/fees-0.3.0 --project fixtures/parcels-fees-0.3.0labparcels.iface@0.1.0 → /tmp/lab-work/stage-a/artifacts/iface: contentHash sha256:23b7a38c3f80dc22015fe983e6ae21083e4d52d9ef1309a5e36d964cf0a31ac2, worldHash sha256:23b7a38c3f80dc22015fe983e6ae21083e4d52d9ef1309a5e36d964cf0a31ac2, 3 fileslabparcels.registry@0.1.0 → /tmp/lab-work/stage-a/artifacts/registry: contentHash sha256:15b5bd7fe6f4260b5e2f94e9c8ba5af53150e36c55365b3d463e5bc34215368f, worldHash sha256:13ef321e7bf4e5e44b45f2142e1f000e2ba4ffbf749cb3694041993bb6346ef2, 3 fileslabparcels.fees@0.2.0 → /tmp/lab-work/stage-a/artifacts/fees: contentHash sha256:dfe81269bfe070987ada69e4c2545e9c31a755aa1600be72a8242a00c30dbde4, worldHash sha256:056a48336aba96920988682a4a72e723c35a9d177f094d549f79df1739322b7a, 3 fileslabparcels.appeals@0.1.0 → /tmp/lab-work/stage-a/artifacts/appeals: contentHash sha256:92860bd5cd0ac02edbe666965d8430fb360dc5f938fcabaee4d83f1f95b7df6e, worldHash sha256:866374f2e79343b9cef623feeef6961574b32a6fce02c2533d486eb97fc1012e, 3 fileslabparcels.case1@0.1.0 → /tmp/lab-work/stage-a/artifacts/case1: contentHash sha256:14ae7edbf58225f3fdf1cc7b5f21cb14ac33fb223795a2834d4c8d765b6f0cdc, worldHash sha256:59059bde677910196f9d3533e782716e9cd776e21e2b873119a3c35d191bce10, 3 fileslabparcels.fees@0.3.0 → /tmp/lab-work/stage-a/artifacts/fees-0.3.0: contentHash sha256:a7bdcc8144572aef2a00f0d833db3007edf9c4818a79fafbf4a97576c75e06f8, worldHash sha256:3ba271665819555171ba1f980bae9f5e48548e43f4aaed8932f999d2e0749067, 3 filesPublish the six into the stage registry and copy the case aside:
law publish /tmp/lab-work/stage-a/artifacts/iface --registry lab=/tmp/lab-work/stage-a/registrylaw publish /tmp/lab-work/stage-a/artifacts/registry --registry lab=/tmp/lab-work/stage-a/registrylaw publish /tmp/lab-work/stage-a/artifacts/fees --registry lab=/tmp/lab-work/stage-a/registrylaw publish /tmp/lab-work/stage-a/artifacts/appeals --registry lab=/tmp/lab-work/stage-a/registrylaw publish /tmp/lab-work/stage-a/artifacts/case1 --registry lab=/tmp/lab-work/stage-a/registrylaw publish /tmp/lab-work/stage-a/artifacts/fees-0.3.0 --registry lab=/tmp/lab-work/stage-a/registrycp -r fixtures/parcels-case1 /tmp/lab-work/stage-a/case1registry lab created: /tmp/lab-work/stage-a/registrylabparcels.iface@0.1.0 → lab (/tmp/lab-work/stage-a/registry): contentHash sha256:23b7a38c3f80dc22015fe983e6ae21083e4d52d9ef1309a5e36d964cf0a31ac2, worldHash sha256:23b7a38c3f80dc22015fe983e6ae21083e4d52d9ef1309a5e36d964cf0a31ac2versions labparcels.iface: 0.1.0changed: p/labparcels.iface/0.1.0/package.lawir.jsonchanged: p/labparcels.iface/0.1.0/world.lawir.jsonchanged: p/labparcels.iface/0.1.0.jsonlabparcels.registry@0.1.0 → lab (/tmp/lab-work/stage-a/registry): contentHash sha256:15b5bd7fe6f4260b5e2f94e9c8ba5af53150e36c55365b3d463e5bc34215368f, worldHash sha256:13ef321e7bf4e5e44b45f2142e1f000e2ba4ffbf749cb3694041993bb6346ef2versions labparcels.registry: 0.1.0changed: p/labparcels.registry/0.1.0/package.lawir.jsonchanged: p/labparcels.registry/0.1.0/world.lawir.jsonchanged: p/labparcels.registry/0.1.0.jsonlabparcels.fees@0.2.0 → lab (/tmp/lab-work/stage-a/registry): contentHash sha256:dfe81269bfe070987ada69e4c2545e9c31a755aa1600be72a8242a00c30dbde4, worldHash sha256:056a48336aba96920988682a4a72e723c35a9d177f094d549f79df1739322b7aversions labparcels.fees: 0.2.0changed: p/labparcels.fees/0.2.0/package.lawir.jsonchanged: p/labparcels.fees/0.2.0/world.lawir.jsonchanged: p/labparcels.fees/0.2.0.jsonlabparcels.appeals@0.1.0 → lab (/tmp/lab-work/stage-a/registry): contentHash sha256:92860bd5cd0ac02edbe666965d8430fb360dc5f938fcabaee4d83f1f95b7df6e, worldHash sha256:866374f2e79343b9cef623feeef6961574b32a6fce02c2533d486eb97fc1012eversions labparcels.appeals: 0.1.0changed: p/labparcels.appeals/0.1.0/package.lawir.jsonchanged: p/labparcels.appeals/0.1.0/world.lawir.jsonchanged: p/labparcels.appeals/0.1.0.jsonlabparcels.case1@0.1.0 → lab (/tmp/lab-work/stage-a/registry): contentHash sha256:14ae7edbf58225f3fdf1cc7b5f21cb14ac33fb223795a2834d4c8d765b6f0cdc, worldHash sha256:59059bde677910196f9d3533e782716e9cd776e21e2b873119a3c35d191bce10versions labparcels.case1: 0.1.0changed: p/labparcels.case1/0.1.0/package.lawir.jsonchanged: p/labparcels.case1/0.1.0/world.lawir.jsonchanged: p/labparcels.case1/0.1.0.jsonlabparcels.fees@0.3.0 → lab (/tmp/lab-work/stage-a/registry): contentHash sha256:a7bdcc8144572aef2a00f0d833db3007edf9c4818a79fafbf4a97576c75e06f8, worldHash sha256:3ba271665819555171ba1f980bae9f5e48548e43f4aaed8932f999d2e0749067versions labparcels.fees: 0.2.0, 0.3.0changed: p/labparcels.fees/0.3.0/package.lawir.jsonchanged: p/labparcels.fees/0.3.0/world.lawir.jsonchanged: p/labparcels.fees/0.3.0.jsonSave the three old answers. The full texts match the answers recorded earlier; only the footers are shown:
law ask /tmp/lab-work/stage-a/case1 --case ParcelTransfer --query-json /tmp/lab-work/stage-a/case1/queries/fee-answered.json --format text --out /tmp/lab-work/stage-a/answers/fee-answered | tail -n 1law ask /tmp/lab-work/stage-a/case1 --case ParcelTransfer --query-json /tmp/lab-work/stage-a/case1/queries/transfer-answered.json --format text --out /tmp/lab-work/stage-a/answers/transfer-answered | tail -n 1law ask /tmp/lab-work/stage-a/case1 --case ParcelTransfer --query-json /tmp/lab-work/stage-a/case1/queries/appeal-answered.json --format text --out /tmp/lab-work/stage-a/answers/appeal-answered | tail -n 1*Вопрос `urn:law:lab:parcels:case1#case/ParcelTransfer/query/fee-answered` · результат `urn:result:case1#case/ParcelTransfer/query/fee-answered` · resultHash `sha256:dc3120593dd12d014b6fb50adb5a05403b0fbb43b6686d02ff4dcbfcf693c677` · программа `sha256:f219f1832a4945e55f3227f424ad69df7d4cab5c8691c6dd37e8ce7067eab182` · вербализация law.verb.ru@0.39.0 · язык ru-KZ · подробность: полное дерево**Вопрос `urn:law:lab:parcels:case1#case/ParcelTransfer/query/transfer-answered` · результат `urn:result:case1#case/ParcelTransfer/query/transfer-answered` · resultHash `sha256:8c5deca4fb4bcf6fcbdda27f6715aba5807de7942803db573213f05b7ff000e7` · программа `sha256:f219f1832a4945e55f3227f424ad69df7d4cab5c8691c6dd37e8ce7067eab182` · вербализация law.verb.ru@0.39.0 · язык ru-KZ · подробность: полное дерево**Вопрос `urn:law:lab:parcels:case1#case/ParcelTransfer/query/appeal-answered` · результат `urn:result:case1#case/ParcelTransfer/query/appeal-answered` · resultHash `sha256:eb9b1cf945f951ac18d09abb8eb6ece82566f0f37c4b8fa6da0e36becf449da1` · программа `sha256:f219f1832a4945e55f3227f424ad69df7d4cab5c8691c6dd37e8ce7067eab182` · вербализация law.verb.ru@0.39.0 · язык ru-KZ · подробность: полное дерево*Replay the saved fee answer on its saved inputs. The recomputed hash matches the saved footer exactly:
law eval /tmp/lab-work/stage-a/answers/fee-answered | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['resultHash'], d['results'][0]['truthStatus'], d['results'][0]['evaluationStatus'])"sha256:dc3120593dd12d014b6fb50adb5a05403b0fbb43b6686d02ff4dcbfcf693c677 TRUE_ONLY COMPUTEDRun both consumers plus the scratch case before the move. Every test passes, which fixes the baseline the predictions are written against:
law test fixtures/parcels-fees-0.3.0 | tail -n 1law test fixtures/parcels-appeals | tail -n 1law test /tmp/lab-work/stage-a/case1 | tail -n 1total: 5 checked, 5 passed, 0 failed, 0 not run; code 0total: 3 checked, 3 passed, 0 failed, 0 not run; code 0total: 4 checked, 4 passed, 0 failed, 0 not run; code 0Move the scratch case across, preview first:
law update 'labparcels.fees@0.3.0' --project /tmp/lab-work/stage-a/case1 --registry lab=/tmp/lab-work/stage-a/registry --dry-runlaw update 'labparcels.fees@0.3.0' --project /tmp/lab-work/stage-a/case1 --registry lab=/tmp/lab-work/stage-a/registrylab ← /tmp/lab-work/stage-a/registry (--registry)--dry-run: staged and verified, no file changed~ labparcels.fees 0.2.0 -> 0.3.0changed: .law/transport.jsonchanged: deps/labparcels.fees.lawir.jsonchanged: law.lockchanged: law.tomlchanged: package.lawlab ← /tmp/lab-work/stage-a/registry (--registry)~ labparcels.fees 0.2.0 -> 0.3.0changed: .law/transport.jsonchanged: deps/labparcels.fees.lawir.jsonchanged: law.lockchanged: law.tomlchanged: package.lawThe case run breaks exactly where predicted: the fee expectation still names the old amount, and the other three scenarios hold:
law test /tmp/lab-work/stage-a/case1law test labparcels.case1: world labparcels.case1, labparcels.appeals, labparcels.fees, labparcels.iface, labparcels.registry FAIL [labparcels.case1#authored] tests/01-worked-parcel.lawtest / urn:lab:parcels:case1:fee truth_status == TRUE_ONLY: in the document NEITHER ok [labparcels.case1#authored] tests/01-worked-parcel.lawtest / urn:lab:parcels:case1:transfer ok [labparcels.case1#authored] tests/01-worked-parcel.lawtest / urn:lab:parcels:case1:appeal ok [labparcels.case1#authored] tests/01-worked-parcel.lawtest / urn:lab:parcels:case1:wrong-feetotal: 4 checked, 3 passed, 1 failed, 0 not run; code 1The four verdicts after the move. The old amount goes silent. The
grep pattern keeps the Russian lines Установлено (established),
Не установлено (not established), and Вычисление (evaluation), plus
the hash line; the table under Answers translates the rest:
law ask /tmp/lab-work/stage-a/case1 --case ParcelTransfer --query-json /tmp/lab-work/stage-a/case1/queries/fee-answered.json --format text | grep -E '^(Установлено|Не установлено|Вычисление)|resultHash'Установлено ли, что «fee_due» (parcel: `p1`, сумма: 100)?Вычисление завершено.Не установлено ни что «fee_due» (parcel: `p1`, сумма: 100), ни обратное. Это не утверждение ложности и не заключение о молчании права: в модели нет вывода ни в одну сторону.*Вопрос `urn:law:lab:parcels:case1#case/ParcelTransfer/query/fee-answered` · результат `urn:result:case1#case/ParcelTransfer/query/fee-answered` · resultHash `sha256:1f964362f7df39c21f9648c79a3873a38bc1cb98647bc83d65fdba4af9f7eb92` · программа `sha256:4d39c555f907eed6d9db404a4b9e60b970cd990b1d60267cd2be60c585b3558b` · вербализация law.verb.ru@0.39.0 · язык ru-KZ · подробность: полное дерево*The new amount is established, asked in the inline form, which spells the amount as a plain integer:
law ask /tmp/lab-work/stage-a/case1 --case ParcelTransfer --query 'evaluate truth(labparcels.fees::fee_due(entity_ref("urn:lab:parcel:p1"), 120));' --query-id fee-120 --format text | grep -E '^(Установлено|Не установлено|Вычисление)|resultHash'Установлено ли, что «fee_due» (parcel: `p1`, сумма: 120)?Вычисление завершено.Установлено, что «fee_due» (parcel: `p1`, сумма: 120); обратное не установлено.*Вопрос `urn:law:lab:parcels:case1#case/ParcelTransfer/query/fee-120` · результат `urn:result:case1#case/ParcelTransfer/query/fee-120` · resultHash `sha256:f4c3cafa5b2ae77b709300d7f6f720b9e388b95b189d538b9237841c58fa3e21` · программа `sha256:4d39c555f907eed6d9db404a4b9e60b970cd990b1d60267cd2be60c585b3558b` · вербализация law.verb.ru@0.39.0 · язык ru-KZ · подробность: полное дерево*The other two verdicts stand, with new hashes behind the changed program bytes:
law ask /tmp/lab-work/stage-a/case1 --case ParcelTransfer --query-json /tmp/lab-work/stage-a/case1/queries/transfer-answered.json --format text | grep -E '^(Установлено|Не установлено)|resultHash'law ask /tmp/lab-work/stage-a/case1 --case ParcelTransfer --query-json /tmp/lab-work/stage-a/case1/queries/appeal-answered.json --format text | grep -E '^(Установлено|Не установлено)|resultHash'Установлено ли, что «transfer_granted» (parcel: `p1`, from: `amy`, to: `bob`)?Установлено, что «transfer_granted» (parcel: `p1`, from: `amy`, to: `bob`); обратное не установлено.*Вопрос `urn:law:lab:parcels:case1#case/ParcelTransfer/query/transfer-answered` · результат `urn:result:case1#case/ParcelTransfer/query/transfer-answered` · resultHash `sha256:756b93ce490b5cf69d01dffabcab1b4f1b92798b2e53a3fab7ea2039b0ecce80` · программа `sha256:4d39c555f907eed6d9db404a4b9e60b970cd990b1d60267cd2be60c585b3558b` · вербализация law.verb.ru@0.39.0 · язык ru-KZ · подробность: полное дерево*Установлено ли, что «appeal_timely» (parcel: `p1`)?Установлено, что «appeal_timely» (parcel: `p1`); обратное не установлено.*Вопрос `urn:law:lab:parcels:case1#case/ParcelTransfer/query/appeal-answered` · результат `urn:result:case1#case/ParcelTransfer/query/appeal-answered` · resultHash `sha256:2deb58533df3f1c2a59067a8e0e2e7cdc54e3ee6469df805a99b2d5dfeee3b30` · программа `sha256:4d39c555f907eed6d9db404a4b9e60b970cd990b1d60267cd2be60c585b3558b` · вербализация law.verb.ru@0.39.0 · язык ru-KZ · подробность: полное дерево*Move the stale expectation to the new amount and rerun until every test passes. The shipped fee revision already carries the same move in its own wrong-amount scenario:
language "law.core" version "0.2";package labparcels.fees version "0.3.0";namespace "urn:law:lab:parcels:fees";
// A residential parcel owes 120, so the old 100 for it is not established.
test "urn:lab:parcels:fees:wrong-amount" { given { context { legal_time @2026-01-15; } assert "holding": labparcels.iface::owns(entity_ref("urn:lab:owner:amy"), entity_ref("urn:lab:parcel:p1")) { origin case_input; } assert "kind": labparcels.registry::kind_of(entity_ref("urn:lab:parcel:p1"), labparcels.iface::residential) { origin case_input; } } evaluate truth(fee_due(entity_ref("urn:lab:parcel:p1"), 100)); expect result_kind == PROPOSITION; expect truth_status == NEITHER;}perl -pi -e 's/fee_due\(entity_ref\("urn:lab:parcel:p1"\), 100\)/fee_due(entity_ref("urn:lab:parcel:p1"), 120)/' /tmp/lab-work/stage-a/case1/tests/01-worked-parcel.lawtestgrep -n "evaluate" /tmp/lab-work/stage-a/case1/tests/01-worked-parcel.lawtestlaw test /tmp/lab-work/stage-a/case1 | tail -n 127: evaluate truth(labparcels.fees::fee_due(entity_ref("urn:lab:parcel:p1"), 120));45: evaluate truth(labparcels.registry::transfer_granted(entity_ref("urn:lab:parcel:p1"), entity_ref("urn:lab:owner:amy"), entity_ref("urn:lab:owner:bob")));66: evaluate truth(labparcels.appeals::appeal_timely(entity_ref("urn:lab:parcel:p1")));81: evaluate truth(labparcels.fees::fee_due(entity_ref("urn:lab:parcel:p1"), 250));total: 4 checked, 4 passed, 0 failed, 0 not run; code 0Close the loop after the update: replay the saved old answer and ask the fresh question side by side. History is preserved exactly when the replay reproduces the old hash while the live world answers the new amount:
law eval /tmp/lab-work/stage-a/answers/fee-answered | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['resultHash'], d['results'][0]['truthStatus'], d['results'][0]['evaluationStatus'])"law ask /tmp/lab-work/stage-a/case1 --case ParcelTransfer --query 'evaluate truth(labparcels.fees::fee_due(entity_ref("urn:lab:parcel:p1"), 120));' --query-id fee-120 --format text | tail -n 1sha256:dc3120593dd12d014b6fb50adb5a05403b0fbb43b6686d02ff4dcbfcf693c677 TRUE_ONLY COMPUTED*Вопрос `urn:law:lab:parcels:case1#case/ParcelTransfer/query/fee-120` · результат `urn:result:case1#case/ParcelTransfer/query/fee-120` · resultHash `sha256:f4c3cafa5b2ae77b709300d7f6f720b9e388b95b189d538b9237841c58fa3e21` · программа `sha256:4d39c555f907eed6d9db404a4b9e60b970cd990b1d60267cd2be60c585b3558b` · вербализация law.verb.ru@0.39.0 · язык ru-KZ · подробность: полное дерево*The replayed dc312059… equals the pre-update footer byte for
byte; the fresh f4c3cafa… answers the updated world. One
command proves the past is intact, the other that the present
moved.
Stage B exercise
Section titled “Stage B exercise”Pack the original five states plus the four renamed revisions:
mkdir -p /tmp/lab-work/stage-b/artifactslaw pack --out /tmp/lab-work/stage-b/artifacts/iface --project fixtures/parcels-ifacelaw pack --out /tmp/lab-work/stage-b/artifacts/registry --project fixtures/parcels-registrylaw pack --out /tmp/lab-work/stage-b/artifacts/fees --project fixtures/parcels-feeslaw pack --out /tmp/lab-work/stage-b/artifacts/appeals --project fixtures/parcels-appealslaw pack --out /tmp/lab-work/stage-b/artifacts/case1 --project fixtures/parcels-case1law pack --out /tmp/lab-work/stage-b/artifacts/iface-0.2.0 --project fixtures/parcels-iface-0.2.0law pack --out /tmp/lab-work/stage-b/artifacts/registry-0.3.0 --project fixtures/parcels-registry-0.3.0law pack --out /tmp/lab-work/stage-b/artifacts/fees-0.4.0 --project fixtures/parcels-fees-0.4.0law pack --out /tmp/lab-work/stage-b/artifacts/appeals-0.2.0 --project fixtures/parcels-appeals-0.2.0labparcels.iface@0.1.0 → /tmp/lab-work/stage-b/artifacts/iface: contentHash sha256:23b7a38c3f80dc22015fe983e6ae21083e4d52d9ef1309a5e36d964cf0a31ac2, worldHash sha256:23b7a38c3f80dc22015fe983e6ae21083e4d52d9ef1309a5e36d964cf0a31ac2, 3 fileslabparcels.registry@0.1.0 → /tmp/lab-work/stage-b/artifacts/registry: contentHash sha256:15b5bd7fe6f4260b5e2f94e9c8ba5af53150e36c55365b3d463e5bc34215368f, worldHash sha256:13ef321e7bf4e5e44b45f2142e1f000e2ba4ffbf749cb3694041993bb6346ef2, 3 fileslabparcels.fees@0.2.0 → /tmp/lab-work/stage-b/artifacts/fees: contentHash sha256:dfe81269bfe070987ada69e4c2545e9c31a755aa1600be72a8242a00c30dbde4, worldHash sha256:056a48336aba96920988682a4a72e723c35a9d177f094d549f79df1739322b7a, 3 fileslabparcels.appeals@0.1.0 → /tmp/lab-work/stage-b/artifacts/appeals: contentHash sha256:92860bd5cd0ac02edbe666965d8430fb360dc5f938fcabaee4d83f1f95b7df6e, worldHash sha256:866374f2e79343b9cef623feeef6961574b32a6fce02c2533d486eb97fc1012e, 3 fileslabparcels.case1@0.1.0 → /tmp/lab-work/stage-b/artifacts/case1: contentHash sha256:14ae7edbf58225f3fdf1cc7b5f21cb14ac33fb223795a2834d4c8d765b6f0cdc, worldHash sha256:59059bde677910196f9d3533e782716e9cd776e21e2b873119a3c35d191bce10, 3 fileslabparcels.iface@0.2.0 → /tmp/lab-work/stage-b/artifacts/iface-0.2.0: contentHash sha256:1c5f687074bd1fbf9424aff0cbd114fa6fac030e6c452c30a9a0d6a33c06f7fe, worldHash sha256:1c5f687074bd1fbf9424aff0cbd114fa6fac030e6c452c30a9a0d6a33c06f7fe, 3 fileslabparcels.registry@0.3.0 → /tmp/lab-work/stage-b/artifacts/registry-0.3.0: contentHash sha256:a0e9dfd1127f95659d921c49b53f04b78b0aea80aee74ee03f9e6141ca2824b5, worldHash sha256:ab2e0837c94bb2f8dd526e8251fafea3df241b09517433eb2c5b4e6bbbf5410a, 3 fileslabparcels.fees@0.4.0 → /tmp/lab-work/stage-b/artifacts/fees-0.4.0: contentHash sha256:2e3998a465a47d6dadfcc1a440443d3fd13c49ade4fcdb09e95930aa1e493d3f, worldHash sha256:5fb87994153eb7af496c6fe86e18f4ccc0df1fa6f613f0e4cb5c4d49d5dadb9e, 3 fileslabparcels.appeals@0.2.0 → /tmp/lab-work/stage-b/artifacts/appeals-0.2.0: contentHash sha256:674f43e0462c2e2637c1a7c0e6855133b4dab24a1d522754f028057d49502e22, worldHash sha256:d268b848eff7519bb4a37700e6bdd99c5117c998b4cc93f6a5153cfbac025073, 3 filesPublish the nine into the stage registry and copy the work areas aside. The copies are silent:
law publish /tmp/lab-work/stage-b/artifacts/iface --registry lab=/tmp/lab-work/stage-b/registrylaw publish /tmp/lab-work/stage-b/artifacts/registry --registry lab=/tmp/lab-work/stage-b/registrylaw publish /tmp/lab-work/stage-b/artifacts/fees --registry lab=/tmp/lab-work/stage-b/registrylaw publish /tmp/lab-work/stage-b/artifacts/appeals --registry lab=/tmp/lab-work/stage-b/registrylaw publish /tmp/lab-work/stage-b/artifacts/case1 --registry lab=/tmp/lab-work/stage-b/registrylaw publish /tmp/lab-work/stage-b/artifacts/iface-0.2.0 --registry lab=/tmp/lab-work/stage-b/registrylaw publish /tmp/lab-work/stage-b/artifacts/registry-0.3.0 --registry lab=/tmp/lab-work/stage-b/registrylaw publish /tmp/lab-work/stage-b/artifacts/fees-0.4.0 --registry lab=/tmp/lab-work/stage-b/registrylaw publish /tmp/lab-work/stage-b/artifacts/appeals-0.2.0 --registry lab=/tmp/lab-work/stage-b/registrycp -r fixtures/parcels-registry /tmp/lab-work/stage-b/reg-oldcp -r fixtures/parcels-case1 /tmp/lab-work/stage-b/case1-holdscp -r fixtures/parcels-fees /tmp/lab-work/stage-b/fees-conflictregistry lab created: /tmp/lab-work/stage-b/registrylabparcels.iface@0.1.0 → lab (/tmp/lab-work/stage-b/registry): contentHash sha256:23b7a38c3f80dc22015fe983e6ae21083e4d52d9ef1309a5e36d964cf0a31ac2, worldHash sha256:23b7a38c3f80dc22015fe983e6ae21083e4d52d9ef1309a5e36d964cf0a31ac2versions labparcels.iface: 0.1.0changed: p/labparcels.iface/0.1.0/package.lawir.jsonchanged: p/labparcels.iface/0.1.0/world.lawir.jsonchanged: p/labparcels.iface/0.1.0.jsonlabparcels.registry@0.1.0 → lab (/tmp/lab-work/stage-b/registry): contentHash sha256:15b5bd7fe6f4260b5e2f94e9c8ba5af53150e36c55365b3d463e5bc34215368f, worldHash sha256:13ef321e7bf4e5e44b45f2142e1f000e2ba4ffbf749cb3694041993bb6346ef2versions labparcels.registry: 0.1.0changed: p/labparcels.registry/0.1.0/package.lawir.jsonchanged: p/labparcels.registry/0.1.0/world.lawir.jsonchanged: p/labparcels.registry/0.1.0.jsonlabparcels.fees@0.2.0 → lab (/tmp/lab-work/stage-b/registry): contentHash sha256:dfe81269bfe070987ada69e4c2545e9c31a755aa1600be72a8242a00c30dbde4, worldHash sha256:056a48336aba96920988682a4a72e723c35a9d177f094d549f79df1739322b7aversions labparcels.fees: 0.2.0changed: p/labparcels.fees/0.2.0/package.lawir.jsonchanged: p/labparcels.fees/0.2.0/world.lawir.jsonchanged: p/labparcels.fees/0.2.0.jsonlabparcels.appeals@0.1.0 → lab (/tmp/lab-work/stage-b/registry): contentHash sha256:92860bd5cd0ac02edbe666965d8430fb360dc5f938fcabaee4d83f1f95b7df6e, worldHash sha256:866374f2e79343b9cef623feeef6961574b32a6fce02c2533d486eb97fc1012eversions labparcels.appeals: 0.1.0changed: p/labparcels.appeals/0.1.0/package.lawir.jsonchanged: p/labparcels.appeals/0.1.0/world.lawir.jsonchanged: p/labparcels.appeals/0.1.0.jsonlabparcels.case1@0.1.0 → lab (/tmp/lab-work/stage-b/registry): contentHash sha256:14ae7edbf58225f3fdf1cc7b5f21cb14ac33fb223795a2834d4c8d765b6f0cdc, worldHash sha256:59059bde677910196f9d3533e782716e9cd776e21e2b873119a3c35d191bce10versions labparcels.case1: 0.1.0changed: p/labparcels.case1/0.1.0/package.lawir.jsonchanged: p/labparcels.case1/0.1.0/world.lawir.jsonchanged: p/labparcels.case1/0.1.0.jsonlabparcels.iface@0.2.0 → lab (/tmp/lab-work/stage-b/registry): contentHash sha256:1c5f687074bd1fbf9424aff0cbd114fa6fac030e6c452c30a9a0d6a33c06f7fe, worldHash sha256:1c5f687074bd1fbf9424aff0cbd114fa6fac030e6c452c30a9a0d6a33c06f7feversions labparcels.iface: 0.1.0, 0.2.0changed: p/labparcels.iface/0.2.0/package.lawir.jsonchanged: p/labparcels.iface/0.2.0/world.lawir.jsonchanged: p/labparcels.iface/0.2.0.jsonlabparcels.registry@0.3.0 → lab (/tmp/lab-work/stage-b/registry): contentHash sha256:a0e9dfd1127f95659d921c49b53f04b78b0aea80aee74ee03f9e6141ca2824b5, worldHash sha256:ab2e0837c94bb2f8dd526e8251fafea3df241b09517433eb2c5b4e6bbbf5410aversions labparcels.registry: 0.1.0, 0.3.0changed: p/labparcels.registry/0.3.0/package.lawir.jsonchanged: p/labparcels.registry/0.3.0/world.lawir.jsonchanged: p/labparcels.registry/0.3.0.jsonlabparcels.fees@0.4.0 → lab (/tmp/lab-work/stage-b/registry): contentHash sha256:2e3998a465a47d6dadfcc1a440443d3fd13c49ade4fcdb09e95930aa1e493d3f, worldHash sha256:5fb87994153eb7af496c6fe86e18f4ccc0df1fa6f613f0e4cb5c4d49d5dadb9eversions labparcels.fees: 0.2.0, 0.4.0changed: p/labparcels.fees/0.4.0/package.lawir.jsonchanged: p/labparcels.fees/0.4.0/world.lawir.jsonchanged: p/labparcels.fees/0.4.0.jsonlabparcels.appeals@0.2.0 → lab (/tmp/lab-work/stage-b/registry): contentHash sha256:674f43e0462c2e2637c1a7c0e6855133b4dab24a1d522754f028057d49502e22, worldHash sha256:d268b848eff7519bb4a37700e6bdd99c5117c998b4cc93f6a5153cfbac025073versions labparcels.appeals: 0.1.0, 0.2.0changed: p/labparcels.appeals/0.2.0/package.lawir.jsonchanged: p/labparcels.appeals/0.2.0/world.lawir.jsonchanged: p/labparcels.appeals/0.2.0.jsonThe break. Moving the unmigrated act under the renamed vocabulary is refused with a nonzero exit, and the pins stay untouched. The refusal names the missing word at both rules that read it and lists the new word among the exports:
law update 'labparcels.iface@0.2.0' --project /tmp/lab-work/stage-b/reg-old --registry lab=/tmp/lab-work/stage-b/registry --dry-rungrep -n "labparcels.iface" /tmp/lab-work/stage-b/reg-old/law.tomllaw: REFUSAL: prepared package fails check:/tmp/lab-work/stage-b/reg-old/.law/verify/package.law:38:10: error LDC-E1105: labparcels.iface::owns: symbol is not exported by the package (§24: cross-package references target only `pub` declarations; exported: Owner, Parcel, ParcelKind, commercial, garden, holds, residential)/tmp/lab-work/stage-b/reg-old/.law/verify/package.law:47:28: error LDC-E1105: labparcels.iface::owns: symbol is not exported by the package (§24: cross-package references target only `pub` declarations; exported: Owner, Parcel, ParcelKind, commercial, garden, holds, residential)19:world = ["labparcels.registry", "labparcels.iface"]25:"labparcels.iface" = "0.1.0"The second refusal: moving one of two coupled pins alone is a version conflict, so the migration below rewires pins together:
law update 'labparcels.iface@0.2.0' --project /tmp/lab-work/stage-b/fees-conflict --registry lab=/tmp/lab-work/stage-b/registry --dry-runlaw: REFUSAL LPK-E0401: package labparcels.iface version conflict: 0.1.0 vs 0.2.0 — consumers: labparcels.registry → labparcels.iface@0.1.0; labparcels.fees → labparcels.iface@0.2.0 → update one consumer with `law update NAME` to a shared versionThe migration. Rename the holding link in the scratch case file and its scenarios. The shipped act revision shows the same move in its own rules:
@source(PARCEL_RULE_1)rule RegistrationComplete strict { for p: Parcel; for o: Owner; for k: ParcelKind; when labparcels.iface::holds(o, p) and kind_of(p, k); then registered(p);}perl -pi -e 's/labparcels\.iface::owns\(/labparcels.iface::holds(/g' /tmp/lab-work/stage-b/case1-holds/cases/parcel-transfer.lawcase /tmp/lab-work/stage-b/case1-holds/tests/01-worked-parcel.lawtestgrep -c "holds" /tmp/lab-work/stage-b/case1-holds/cases/parcel-transfer.lawcase /tmp/lab-work/stage-b/case1-holds/tests/01-worked-parcel.lawtest/tmp/lab-work/stage-b/case1-holds/cases/parcel-transfer.lawcase:1/tmp/lab-work/stage-b/case1-holds/tests/01-worked-parcel.lawtest:4Strip the four pins to a bare header, keeping the saved body aside. The strip commands are silent; the two readings confirm the bare state:
cp /tmp/lab-work/stage-b/case1-holds/package.law /tmp/lab-work/stage-b/case1-body.lawpython3 -c "t=open('/tmp/lab-work/stage-b/case1-holds/law.toml').read(); t=t.split('[dependencies]')[0].rstrip()+'\n'; open('/tmp/lab-work/stage-b/case1-holds/law.toml','w').write(t); h=open('/tmp/lab-work/stage-b/case1-holds/package.law').read().split('\n'); open('/tmp/lab-work/stage-b/case1-holds/package.law','w').write('\n'.join(h[:3])+'\n')"rm -rf /tmp/lab-work/stage-b/case1-holds/deps /tmp/lab-work/stage-b/case1-holds/law.lock /tmp/lab-work/stage-b/case1-holds/.lawcat /tmp/lab-work/stage-b/case1-holds/package.lawtail -n 3 /tmp/lab-work/stage-b/case1-holds/law.tomllanguage "law.core" version "0.2";package labparcels.case1 version "0.1.0";namespace "urn:law:lab:parcels:case1";
[authoring]local_imports = "explicit"Re-pin against the renamed revisions. The first wire carries no addition line; each later wire names its addition. The exports of the first wire already speak the new word:
law add 'labparcels.iface@0.2.0' --project /tmp/lab-work/stage-b/case1-holds --registry lab=/tmp/lab-work/stage-b/registry --from lablaw add 'labparcels.registry@0.3.0' --project /tmp/lab-work/stage-b/case1-holds --registry lab=/tmp/lab-work/stage-b/registry --from lablaw add 'labparcels.fees@0.4.0' --project /tmp/lab-work/stage-b/case1-holds --registry lab=/tmp/lab-work/stage-b/registry --from lablaw add 'labparcels.appeals@0.2.0' --project /tmp/lab-work/stage-b/case1-holds --registry lab=/tmp/lab-work/stage-b/registry --from lablab ← /tmp/lab-work/stage-b/registry (--registry)exports (7): Owner, Parcel, ParcelKind, commercial, garden, holds, residentialchanged: .law/transport.jsonchanged: deps/labparcels.iface.lawir.jsonchanged: law.lockchanged: law.tomlchanged: package.lawlab ← /tmp/lab-work/stage-b/registry (--registry)+ labparcels.registry 0.3.0exports (7): Owner, Parcel, ParcelKind, kind_of, registered, transfer_granted, transfer_requestchanged: deps/labparcels.registry.lawir.jsonchanged: law.lockchanged: law.tomlchanged: package.lawlab ← /tmp/lab-work/stage-b/registry (--registry)+ labparcels.fees 0.4.0exports (3): Parcel, ParcelKind, fee_duechanged: deps/labparcels.fees.lawir.jsonchanged: law.lockchanged: law.tomlchanged: package.lawlab ← /tmp/lab-work/stage-b/registry (--registry)+ labparcels.appeals 0.2.0exports (4): Parcel, appeal_filed, appeal_timely, appeal_windowchanged: deps/labparcels.appeals.lawir.jsonchanged: law.lockchanged: law.tomlchanged: package.lawRestore the saved body with the new import lines and run the recomposed world. Four passing scenarios, and the pins hold:
perl -pi -e 's/import labparcels\.iface version "0.1.0"/import labparcels.iface version "0.2.0"/; s/import labparcels\.registry version "0.1.0"/import labparcels.registry version "0.3.0"/; s/import labparcels\.fees version "0.2.0"/import labparcels.fees version "0.4.0"/; s/import labparcels\.appeals version "0.1.0"/import labparcels.appeals version "0.2.0"/' /tmp/lab-work/stage-b/case1-body.lawcp /tmp/lab-work/stage-b/case1-body.law /tmp/lab-work/stage-b/case1-holds/package.lawcat /tmp/lab-work/stage-b/case1-holds/package.lawlaw test /tmp/lab-work/stage-b/case1-holdslaw engine lock /tmp/lab-work/stage-b/case1-holds --checklanguage "law.core" version "0.2";package labparcels.case1 version "0.1.0";namespace "urn:law:lab:parcels:case1";import labparcels.iface version "0.2.0";import labparcels.registry version "0.3.0";import labparcels.fees version "0.4.0";import labparcels.appeals version "0.2.0";law test labparcels.case1: world labparcels.case1, labparcels.appeals, labparcels.fees, labparcels.iface, labparcels.registry ok [labparcels.case1#authored] tests/01-worked-parcel.lawtest / urn:lab:parcels:case1:fee ok [labparcels.case1#authored] tests/01-worked-parcel.lawtest / urn:lab:parcels:case1:transfer ok [labparcels.case1#authored] tests/01-worked-parcel.lawtest / urn:lab:parcels:case1:appeal ok [labparcels.case1#authored] tests/01-worked-parcel.lawtest / urn:lab:parcels:case1:wrong-feetotal: 4 checked, 4 passed, 0 failed, 0 not run; code 0lock: /tmp/lab-work/stage-b/case1-holds/law.lock matches law.toml and resourcesAll three questions are established again on the recomposed world — including the residential fee of 100. The words changed; the meaning held:
law ask /tmp/lab-work/stage-b/case1-holds --case ParcelTransfer --query-json /tmp/lab-work/stage-b/case1-holds/queries/fee-answered.json --format text | grep -E '^(Установлено|Не установлено)|resultHash'law ask /tmp/lab-work/stage-b/case1-holds --case ParcelTransfer --query-json /tmp/lab-work/stage-b/case1-holds/queries/transfer-answered.json --format text | grep -E '^(Установлено|Не установлено)|resultHash'law ask /tmp/lab-work/stage-b/case1-holds --case ParcelTransfer --query-json /tmp/lab-work/stage-b/case1-holds/queries/appeal-answered.json --format text | grep -E '^(Установлено|Не установлено)|resultHash'Установлено ли, что «fee_due» (parcel: `p1`, сумма: 100)?Установлено, что «fee_due» (parcel: `p1`, сумма: 100); обратное не установлено.*Вопрос `urn:law:lab:parcels:case1#case/ParcelTransfer/query/fee-answered` · результат `urn:result:case1#case/ParcelTransfer/query/fee-answered` · resultHash `sha256:b1d5c0e168fcea1b73d2b866c318bca3819880bf387bde8748b4f7c0f9c2c70b` · программа `sha256:fbc0a3e0672a032b1067437836c5235699afbc2ef782fef02735a390a0206c74` · вербализация law.verb.ru@0.39.0 · язык ru-KZ · подробность: полное дерево*Установлено ли, что «transfer_granted» (parcel: `p1`, from: `amy`, to: `bob`)?Установлено, что «transfer_granted» (parcel: `p1`, from: `amy`, to: `bob`); обратное не установлено.*Вопрос `urn:law:lab:parcels:case1#case/ParcelTransfer/query/transfer-answered` · результат `urn:result:case1#case/ParcelTransfer/query/transfer-answered` · resultHash `sha256:aee6b764655df1eccb79baa34a709a806540c1e1c4f520e8bc9344f591f4aac0` · программа `sha256:fbc0a3e0672a032b1067437836c5235699afbc2ef782fef02735a390a0206c74` · вербализация law.verb.ru@0.39.0 · язык ru-KZ · подробность: полное дерево*Установлено ли, что «appeal_timely» (parcel: `p1`)?Установлено, что «appeal_timely» (parcel: `p1`); обратное не установлено.*Вопрос `urn:law:lab:parcels:case1#case/ParcelTransfer/query/appeal-answered` · результат `urn:result:case1#case/ParcelTransfer/query/appeal-answered` · resultHash `sha256:72843c5f667bb1cee91445862cbcd68143f69fc51ac69f1420012cebd897b621` · программа `sha256:fbc0a3e0672a032b1067437836c5235699afbc2ef782fef02735a390a0206c74` · вербализация law.verb.ru@0.39.0 · язык ru-KZ · подробность: полное дерево*How the fixtures were wired
Section titled “How the fixtures were wired”Each fixture started from the scaffolder. A norm package:
law init /tmp/lab-work/init-pkg --name demo.shape --template package/tmp/lab-work/init-pkg: law.toml, source.lawA case package:
law init /tmp/lab-work/init-case --name demo.matter --template case/tmp/lab-work/init-case: case package demo.matter, law.core language 0.2created: law.toml, package.law, main.lawcase, law.lockcase Main declared in main.lawcase and registered in law.toml; set the time axis by explicit inputnext: law add <package> → law install → law askThe rest of this section replays the wiring on scratch copies, so
the fixtures stay untouched. Start from the extracted bundle root
(corpus-lab/), and keep both roots explicit: the generator below
exists only in the checkout composition, so it runs in a subshell
there while every other command stays in the bundle root. Set
ARXO_CHECKOUT to the absolute path of a full repository checkout
before you begin:
mkdir -p /tmp/lab-work/wirecp -r fixtures/parcels-registry /tmp/lab-work/wire/regcp -r fixtures/parcels-iface /tmp/lab-work/wire/ifaceBUNDLE_ROOT="$(pwd)": "${ARXO_CHECKOUT:?absolute path to the full checkout}"Empty the generated fragment block on the copy and regrow it with the writing form; the check form confirms it, and the diff proves the regrown bytes match the shipped file:
python3 -c "import re; p='/tmp/lab-work/wire/reg/sources.law'; t=open(p).read(); open(p,'w').write(re.sub(r'// BEGIN GENERATED.*?// END GENERATED PARCEL RULE FRAGMENTS', '// BEGIN GENERATED PARCEL RULE FRAGMENTS\n\n// END GENERATED PARCEL RULE FRAGMENTS', t, flags=re.S))"( cd "$ARXO_CHECKOUT" || exit 1 ./law gen pinning /tmp/lab-work/wire/reg --write && ./law gen pinning /tmp/lab-work/wire/reg) &&diff /tmp/lab-work/wire/reg/sources.law \ "$BUNDLE_ROOT/fixtures/parcels-registry/sources.law" && echo SOURCES-IDENTICAL ✎ pinning.toml → sources.law [en-US] (2 articles) — block rewritten ✓ pinning.toml → sources.law [en-US] (2 articles)SOURCES-IDENTICALThe pinned bytes live beside the pinning file under resources rather than sources, because the dependency commands stage that directory — and not the other — into the copy they verify. Empty the import block in the rules file and unwire the copy, then regrow the block with the per-package form:
python3 -c "import re; p='/tmp/lab-work/wire/reg/package.law'; t=open(p).read(); open(p,'w').write(re.sub(r'\nuse self::\{[^}]*\};\n', '\n', t))"rm -rf /tmp/lab-work/wire/reg/depslaw fix imports /tmp/lab-work/wire/reg/tmp/lab-work/wire/reg package.law +PARCEL_RULE_1 +PARCEL_RULE_2 incomplete analysis (entries are not removed): the package has `import`, but no context was presented: neither `deps/` nor `corpus/clir` (`--imports <context.json>`)The note about the missing import context is expected at that
point — deps/ was just removed — and the run exits 1, but the
block is still written. Now pin the dependency through the
registry built in the versions exercise. A package with one dependency wires in a single
call on complete sources:
python3 -c "p='/tmp/lab-work/wire/reg/law.toml'; t=open(p).read(); open(p,'w').write(t.split('[dependencies]')[0].rstrip()+'\n')"rm -f /tmp/lab-work/wire/reg/law.locklaw add 'labparcels.iface@0.1.0' --project /tmp/lab-work/wire/reg --registry lab=/tmp/lab-work/registry --from lablaw fix imports /tmp/lab-work/wire/reg --checklaw test /tmp/lab-work/wire/reg | tail -n 1lab ← /tmp/lab-work/registry (--registry)exports (7): Owner, Parcel, ParcelKind, commercial, garden, owns, residentialchanged: .law/transport.jsonchanged: deps/labparcels.iface.lawir.jsonchanged: law.lockchanged: law.toml/tmp/lab-work/wire/reg `use self` blocks are canonicaltotal: 4 checked, 4 passed, 0 failed, 0 not run; code 0With the dependency pinned, the check form reports the blocks canonical and the four scenarios pass.
The shared vocabulary package has no dependencies, so its lock came straight from the lock writer. The writer names the file it rewrote; the diff and the scenarios confirm the rewritten bytes:
rm -f /tmp/lab-work/wire/iface/law.locklaw engine lock /tmp/lab-work/wire/iface --writediff /tmp/lab-work/wire/iface/law.lock \ "$BUNDLE_ROOT/fixtures/parcels-iface/law.lock" && echo IFACE-LOCK-IDENTICALlaw test /tmp/lab-work/wire/iface | tail -n 1written /tmp/lab-work/wire/iface/law.lockIFACE-LOCK-IDENTICALtotal: 2 checked, 2 passed, 0 failed, 0 not run; code 0Each call verifies the package against the pins it would leave behind, so a package that names two dependencies cannot wire both in one call: the first call would face references the second has not pinned yet. Grow such a package one dependency at a time — pin, write the references the pin unlocks, pin again — or wire a bare header first and restore the body after the last pin. The fees, appeals, and case fixtures were completed the second way; the tool writes the import lines itself, and the restored bodies kept the new lines. The renamed revisions in the later stages were wired the same way. The service directory the calls leave behind is local state and ships with no fixture.
Why each silence holds
Section titled “Why each silence holds”| scenario | why the answer stays silent |
|---|---|
| a stranger’s holding | no holding for that owner is asserted anywhere |
| a holding without a recorded kind | the registration rule needs both halves |
| a transfer asked by a non-owner | the asker must equal the recorded owner |
| a kind without a holding | without a holding nothing is registered, and fees need registration |
| the wrong amount for a kind | each kind carries exactly one amount |
| a filing past the window end | the filing day must sit inside the window bounds |
| a filing without registration | timeliness needs a registered parcel first |
| the case mirror of the wrong amount | same single-amount reason, over the full world |
| the old amount under the new rate | same single-amount reason, one revision later |
| a stranger’s holding on the renamed link | same silence as before, under the new word |
Back to the tour.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.