Books / Constructions / Chapter 18
Part V · Chapter 18
A Model You Can Hand Over
Contents of Constructions
Imagine sending the model to a colleague. They open the files, but no one stands beside them who remembers where the dependency lives, which case was chosen, and why this particular number or statement is expected in the answer.
A well-prepared model lets them recover all of that from the set itself. The recipient repeats the question, checks the result, then changes one ground and explains why the answer changed or stayed the same.

We assemble such a set using the water example from the start of the book. It needs no new rules. We separate the familiar input information, the question, and the test’s expectations.
Keeping the case separate from the test
In .lawtest, given, evaluate,
and expect stand side by side: inputs, question, expectation.
For handing over, keep the information in a separate
.lawcase file. Different questions can then be asked about
the same case without building an expected answer into it.
The book’s example is called kniga.voda.
Its manifest, law.toml, identifies the package and its dependencies:
[package]
name = "kniga.voda"
version = "0.1.0"
language = "0.2"
namespace = "urn:kniga:clir:voda"
[dependencies]
"openstax.chemistry_acids" = "0.1.0"
[[cases]]
name = "Voda"
path = "cases/voda.lawcase"
The [dependencies] section names the chemical vocabulary.
The [[cases]] section links the name Voda to the case file.
That is a pointer to the information the query will run on.
At the root lies package.law with the header and the import:
language "law.core" version "0.2";
package kniga.voda version "0.1.0";
namespace "urn:kniga:clir:voda";
import openstax.chemistry_acids version "0.1.0";
And the full cases/voda.lawcase file looks like this:
language "law.core" version "0.2";
package kniga.voda version "0.1.0";
namespace "urn:kniga:clir:voda";
import openstax.chemistry_acids version "0.1.0";
case Voda {
context {
legal_time @2026-09-08;
knowledge_time @2026-09-08T12:00:00Z;
decision_time @2026-09-08T12:00:00Z;
timezone "UTC";
}
assert openstax.chemistry_acids::donates_proton(entity_ref("urn:case:kniga:h2o")) {
id "voda-1";
origin case_input;
}
assert openstax.chemistry_acids::accepts_proton(entity_ref("urn:case:kniga:h2o")) {
id "voda-2";
origin case_input;
}
}
Both assertions concern one object.
The relation names are qualified because the case
belongs to one package and the vocabulary to another.
The context’s dates and each assertion’s origin are stated explicitly.
Neither assertion states that water is amphiprotic.
A rule from the imported vocabulary package must derive it.
The case also holds no expect: expectations belong
to the check, not to the inputs.[^chapter-18-case]
Prepare a copy to hand over
Install npm CLI 0.2.4 as described in the prologue. The companion provides
a complete Water package with its case, compiled dependency, source snapshot,
and lock. Start in reader/ and make a working copy:
mkdir water-study
cp -R docs/books/postroeniya-alt/examples/voda/. water-study
law install --project water-study --offline
The installation check should confirm that the received dependency files
match law.lock. Keep this lock: it records the author’s chosen set.
Generating another lock would choose a new set rather than restore this one.
The companion’s migration note records how the author prepared the package.
The small “Water” package does not define amphiproticity itself; the definition comes from the chemical vocabulary. Its dependency source snapshot includes the readable rules and saved textbook fragments. Keep those materials with the compiled dependency. The program repeats the calculation; the source text lets the recipient assess the formalization.
Ask the question
law ask water-study --case Voda \
--query 'evaluate truth(
openstax.chemistry_acids::amphiprotic(
entity_ref("urn:case:kniga:h2o")
)
);' \
--query-id amphi --out water-answer
--case selects the case. --query carries
the familiar evaluate truth(...) question.
--query-id gives the question a stable name;
--out names the output directory.
The saved evaluation includes these three files used in the chapter:
| File | What it holds |
|---|---|
ask.json |
Which package, case, and question were chosen |
request.json |
The prepared computation input |
result.json |
Answers, explanation, and the calculation manifest |
The CLI also writes bundle.json and index.json for the saved evaluation’s
package information. Keep the whole output directory when handing over a replay.
In result.json the answer to the amphiproticity question is
TRUE_ONLY, the status COMPUTED. The explanation graph
links the conclusion to the rule
AmphiproticDonatesAndAccepts from the vocabulary
and assertions voda-1, voda-2 from the case.
That is how we see the dependency’s rule truly
took part in the calculation.[^chapter-18-proof]
What the recipient checks
The document has several fingerprints:
| Field | What it helps compare |
|---|---|
manifest.programHash |
The program used in the calculation |
manifest.caseHash |
The prepared case |
resultHash |
The canonical result document |
For the full water handover, collect:
- the prepared package directory, with
law.toml,package.law, the case,law.lock, and the compiled dependency indeps/; - the readable dependency sources and saved textbook fragment;
- installation instructions for Node.js 20 or newer and
@arxo/cli@0.2.4, together with the supported platform andlaw version --jsonoutput; - the question command, its expected answer, and the original
result.jsonfor comparison; - the complete saved evaluation directory if the recipient will use
law eval.
The recipient first installs the CLI with npm install -g @arxo/cli@0.2.4
and confirms the version. They receive the package files separately from npm.
law install --offline checks the existing dependency pins and restores from
local bytes without choosing new versions; it leaves the author’s lock in place.
The local repetition below uses that same recipient route. water-recipient
is a second directory, containing the package sent to the recipient:
cp -R water-study water-recipient
law install --project water-recipient --offline
law ask water-recipient --case Voda \
--query 'evaluate truth(
openstax.chemistry_acids::amphiprotic(
entity_ref("urn:case:kniga:h2o")
)
);' \
--query-id amphi --out recipient-answer
cmp water-answer/result.json \
recipient-answer/result.json
The last command compares the two documents byte for byte and stays silent when they match. On the checked set they match. This is only a local rehearsal of handing over — not a run on someone else’s computer — but it shows the calculation can be repeated with the npm-installed CLI and the received dependency pins in a different directory.
To replay the saved evaluation directly, run:
law eval water-answer
law inspect water-answer/result.json summary
law eval repeats the saved request and checks its result. law inspect
summarizes the document without making another claim about the source text.
Hashes cover contents under canonical-form rules — a standard
representation for comparison — rather than the JSON’s outward formatting. A matching resultHash
confirms the pinned document was reproduced.
It does not establish that the inputs are true in the world
or prove that the textbook was interpreted correctly.[^chapter-18-hashes]
If the fingerprints differ, first compare
the program and the case. Then check the question, its name,
the context, and the manifest’s remaining fields.
The two fields programHash and caseHash do not exhaust
every possible reason for a differing result.
Change one ground
In the recipient’s copy, delete the accepts_proton assertion block
with its id and origin.
Keep the first assertion and the whole context.
Repeating the question yields NEITHER, COMPUTED:
donation alone does not support amphiproticity. It does not
refute it either: one of the rule’s needed premises is missing.
Now restore the original case and add one more assertion:
assert openstax.chemistry_acids::donates_proton(entity_ref("urn:case:kniga:other")) {
id "voda-other";
origin case_input;
}
It reports another object’s property.
The answer about water stays TRUE_ONLY. But the case has changed,
so the calculation document differs from the original.
The two experiments are easy to compare side by side:
| Change | Answer | programHash |
caseHash and resultHash |
|---|---|---|---|
| Repetition without changes | TRUE_ONLY |
As before | As before |
| Water’s proton acceptance removed | NEITHER |
As before | Changed |
| The above entry about another object added | TRUE_ONLY |
As before | Changed |
In all rows the status is COMPUTED.
The extra assertion did not support the conclusion about water,
but it belongs to the supplied case. Getting the same logical
answer is therefore different from reproducing the same
calculation document.
Not every file edit changes the calculation. Reindenting is not adding an assertion. Watch for substantive changes to the prepared case; do not expect a new hash after every keystroke.
Now take your own text
Return to the material chosen in the prologue. Narrow the first question so it can be checked on a small number of cases. There is no need to model the whole document or to use every construction in the book.
First name the source and the fragment on which the model rests. If there are editions, name the needed one. Then spell out the objects, the admissible inputs, and the rule leading to the answer. Mark which conditions stay assumptions and which the model establishes.
Prepare a positive case and a nearby case just beyond the applicability boundary. If the answer depends on a date, a reading, or a human judgment, the context and the explanation must show it. Justify expectations before running.
After that, assemble the set: the source, the readable model, cases, questions, checks, pinned dependencies, and repetition instructions. Enclose the original result document and name one change the recipient can make on their own.
The set is not yet ready to hand over if any of the following hold:
- the finished outcome is asserted in the case instead of derived;
- the stated fragment does not support the rule;
- missing information is treated as negation with no declared ground;
- the expectation is merely copied from the result;
- repeating the run needs files only the author has.
Different formalizations of one text are allowed. They can be compared on their merits when each shows its choices, grounds, and consequences. Handing over a model lets another person make that comparison without you. The epilogue gathers the grounds the recipient should be able to ask you to show.
[^chapter-18-case]: A standalone case and the ask operation are described in
§168.4 of the specification.
The Voda declaration and both original assertions are given in
the example file.
[^chapter-18-proof]: The conclusion links assertions voda-1, voda-2 to the rule
AmphiproticDonatesAndAccepts from
the chemical package.
The rule’s application is checked against the explanation graph in result.json,
not only against the final TRUE_ONLY.
[^chapter-18-hashes]: The manifest’s makeup is described in §170, the canonical-form rules in §208. To explain a divergence, the document’s contents are compared; one fingerprint does not tell which particular field changed.
Contents · PDF · EPUB · Original text under CC BY 4.0 · Source-material terms