Books / Constructions / Chapter 16
Part V · Chapter 16
Reusing a Package
Contents of Constructions
In the previous chapter the work rule used the newton, the metre, and the joule. Their definitions lived in a separate package. The acid chapter split things the same way: one package set the chemical vocabulary, another built definitions on it. Time to work out how these parts join.
Start by identifying what the package provides: its public names, the inputs it requires, and the result it promises. A package used by another package is a dependency; the package that uses it is the consumer. We will use chemistry to examine the names, then mechanics to check a pinned dependency and repeat the familiar calculation.
The package name and the names inside it
The chemical vocabulary opens with three lines:
language "law.core" version "0.2";
package openstax.chemistry_acids version "0.1.0";
namespace "urn:openstax:clir:chemistry-acids";
The first line names the language and its version; the second, the package and its version. The third sets the namespace, the shared beginning from which the declarations’ addresses are built.
In an explanation a rule’s address may look like this:
urn:openstax:clir:chemistry-acids#AmphiproticDonatesAndAccepts.
In this address the namespace comes before # and the rule’s
name after it. A label helps us recognize the rule; the full
address identifies the declaration that took part, without
guessing from a similar name.
We have often met pub before declarations.
It marks a name as available to other packages.
A declaration without pub may take part in the work
of its own package, but other packages cannot
refer to it as a public name[^chapter-16-public].
A public name does not establish that its definition is sound
or fits the case at hand. pub is about availability. We still
need to read the declaration’s meaning and constraints.
What an import means
The acid-definitions package connects the vocabulary with the line:
import openstax.chemistry_acids version "0.1.0";
After that it may refer to the vocabulary’s public declarations.
For example, the general question about acids uses
the type Species from the connected package:
pub relation is_acid(s: openstax.chemistry_acids::Species) kind institutional {
label ru unofficial "частица признаётся кислотой по выбранному прочтению";
label en unofficial "the species is an acid under the selected reading";
}
In the name openstax.chemistry_acids::Species, the package stands
to the left of the double colon, the declaration to the right.
The consumer refers to the vocabulary’s own Species type;
it does not declare a second type with a similar name and
assume the two will be treated as one.
But an import line by itself runs nothing. To read the
consumer’s declarations, names must be resolved against the
dependency’s public declarations. To compute with them, its
definitions and rules must also be present in the assembled
program. The law test command prepares both when it builds the pinned world.
Recognizing names and computing with their definitions are separate steps,
even when one command handles them.
Mechanics has a similar line connecting units.si.
Here the dependency provides the unit definitions
the calculation’s operations use. Recognizing the symbol N
and computing a quantity with a known dimension are
two different requirements on the assembled set.
What the package provides—and assumes
Take the work calculation from the last chapter. Before use, it helps to write down its conditions in a few lines:
| What to establish | For this calculation |
|---|---|
| Which inputs are needed | Force and displacement for one calculation |
| Which units are admissible | Units of force and length convertible to N and m |
| Which answer results | Work, written in J |
| What is assumed | Constant force, displacement in its direction |
| What the calculation does not check | Whether these conditions hold; measurement errors |
This table summarizes the package’s contract with its user in ordinary language; it is not part of the program. The relation’s signature gives the inputs’ types and order, and the conversion operations check their dimensions. Neither establishes that the force in the real experiment was constant or directed along the displacement. The person applying the model must check that.
Try writing the same summary for the chemical vocabulary:
what comes in, what follows, and what remains unchecked? A
donates_proton message counts as input information.
The definitions package builds its conclusion on that message
but does not investigate the substance on its own.
A dependency carries these applicability conditions
together with its capabilities.
Why a fingerprint is needed next to the version
An import names a version, but repeatability requires pinning
the dependency’s exact contents. The
law.lock file does this job.
It records the chosen packages, their versions, and content
fingerprints. The version names the intended release;
artifactHash identifies the compiled dependency, while sourceHash
identifies its source snapshot. Both belong to the current lock format. resolutionHash fingerprints the
outcome of resolving the dependencies together, rather than
one package alone[^chapter-16-lock].
These values follow the package format’s rules. Do not replace them with an arbitrary hash of the printed text or a hand-shortened string. An explanation may show the fingerprint’s start; checking needs the full fingerprint in the file.
The recipient must receive both the pinning and the
dependencies themselves. The law.lock file tells what to look for
but does not contain the dependency’s program itself.
Given the dependency files, the recipient can prepare the calculation
without asking the author for the right version.
When a dependency file and its recorded fingerprint disagree, first investigate the cause. Overwriting law.lock to fit whatever is at hand means accepting a new set, not restoring the earlier calculation.
Run the calculation with its dependency
The companion already contains mechanics, its unit definitions, and the lock
that pins their contents. First make a working copy. Start in reader/ and
choose a directory name that does not already exist:
mkdir mechanics-study
cp -R packs/primitives/natural-sciences/mechanics/. mechanics-study
mechanics-study is now your copy of the package. It contains the rule files,
scenarios, law.lock, and deps/. Check that its dependency files agree with
the received lock:
law install --project mechanics-study --offline
--project names the package. --offline uses the files already received.
A successful check confirms that the pinned dependencies are available;
it does not run the work calculation or choose a newer version.
Now run the scenarios:
law test mechanics-study
The ten scenarios should pass, including the 300-joule work calculation.
law test reads the package’s manifest, builds the program with its pinned
dependencies, and compares each answer with the scenario’s expectations.
For tasks 1 and 2 from Chapter 15, edit the work scenario in
mechanics-study/tests/calc-mechanics.lawtest, then run law test mechanics-study
again. Begin each exercise with an unchanged copy of that file.
Replacing 50 m with 5000 cm keeps the result. After replacing 6 N with
6 J, use the dimension-error expectations specified in Chapter 15,
including removal of the rule-application expectation.
Check the pinning separately
Make a second copy for the deliberate error:
cp -R mechanics-study mechanics-bad-pin
In mechanics-bad-pin/law.lock, find the dependency record named units.si.
Change only its artifactHash to sha256: followed by 64 zeros. The dependency
files themselves stay unchanged. Try the same installation check:
law install --project mechanics-bad-pin --offline
The command refuses the altered lock. The recorded fingerprint no longer agrees with the received set. Read the refusal before changing anything else. Restore the lock from the untouched copy and check again:
cp mechanics-study/law.lock mechanics-bad-pin/law.lock
law install --project mechanics-bad-pin --offline
law test mechanics-bad-pin
The installation check should succeed and the ten scenarios should pass again. The mechanics rules needed no repair: the deliberate error was in the pinning[^chapter-16-restore].
The chemical vocabulary allows the same check. The refusal reason stays the same: the pinned fingerprint and the dependency copy in hand disagree.
What to hand over together
This is the dependency part of the handover; Chapter 18 returns
to the full transfer. With the rule files, enclose the manifest
law.toml, which names the package and declares its dependencies,
the dependency pinning, the dependencies themselves, and sample
questions. If the model rests on a text, the saved source materials
and their bindings will be needed too.

Equally important are brief instructions: which file to run, which question is asked, what is expected, and which conditions the user must check before calculating. The prepared set must let anyone repeat the answer without remembering how the author assembled it on their own machine.
Now we can connect a package, check its pinned copy, and examine its role in the computation. The fingerprint check establishes agreement with the pinning; the scenarios check particular answers. Neither establishes that every rule is right. A wrong rule can pass tests that never expose its difference from the intended rule. The next chapter builds checks that do.
[^chapter-16-public]: §§23–24 of the Arxo specification tell apart import, declaration visibility, and a dependency’s participation in execution. A name’s publicness does not replace connecting the needed program contents. [^chapter-16-lock]: §11: law.lock sets the pinned information and separates updating dependencies from execution. The mechanics manifest declares the units.si dependency. [^chapter-16-restore]: This edition’s experiment changes only the dependency’s artifactHash in a copied lock; the dependency files stay unchanged. The npm CLI refuses the altered lock. Returning the saved lock restores installation and all ten mechanics scenarios. The historical specification link above describes the earlier contentHash format; the companion’s migration note records the current sourceHash/artifactHash format.
Contents · PDF · EPUB · Original text under CC BY 4.0 · Source-material terms