Dependencies, locks, and registries
Dependencies in the corpus resolve to exact pins, never to ranges. Three commands manage the closure, a fourth previews drift, and the lockfile remembers the outcome. All of them are available in the public release (S).
Environment: the public law-v0.1.1 release, run from the root of the
lab bundle; the example needs the
throwaway registry built in the lab’s
versions exercise. Status
letters follow the legend on the topic index.
Example: pin one dependency
Section titled “Example: pin one dependency”The lab’s parcels-registry package imports the shared vocabulary
labparcels.iface. The wiring replay
works on a scratch copy of that package with its [dependencies]
section and its law.lock removed, and then pins the vocabulary again
from the lab registry:
law add 'labparcels.iface@0.1.0' --project /tmp/lab-work/wire/reg --registry lab=/tmp/lab-work/registry --from labThe law add part of the recorded output (excerpt: the first six lines;
the full block is under Reproduction details):
lab ← /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.tomlLine by line: the first line names the registry address the command
read. The second lists what the pinned package exports to the
importer. The changed: lines name every file the command wrote:
law.tomlgains the requested pin under[dependencies]:"labparcels.iface" = "0.1.0". This is the request: one exact version, no range.law.lockis written from scratch. It records the resolved package (name, version, namespace, registry idlab, the resolver addressregistry://lab/labparcels.iface/0.1.0, and the content hash of its compiled bytes), the dependency edge fromlabparcels.registrytolabparcels.ifacewith the requested and the resolved version, the semantics linelaw.core/0.2.0, the root package’s own content hash, and one resolution hash over all of it.deps/labparcels.iface.lawir.jsonholds the compiled bytes that the lock’s content hash covers..law/transport.jsonis local service state of the command. It ships with no fixture.
The shipped fixture shows the same end state; read
fixtures/parcels-registry/law.lock
next to the list above.
What this result means: the package now has one exact, hash-checked version of its dependency, and every later check resolves through the lock. In the lab run the package’s four scenarios pass right after the pin, so the pin is ready to commit. A package that names two dependencies cannot be wired in one call; the wiring replay explains the one-at-a-time order.
Adding, installing, updating, previewing
Section titled “Adding, installing, updating, previewing”addrecords a new dependency and resolves the closure over registry descriptors. It also accepts a container file in place of a package name; then it reads no registry at all.installmaterializes the pinned closure into the project. It alone offers an offline mode and a recovery mode, and it restores from a container through its transfer flag.updatemoves a pin forward. It can replay saved evaluations under the candidate version.outdatedpreviews newer stable versions of each pinned package and checks whether the pinned bytes still match. It leaves the lock untouched.
Only install runs offline. Adding and updating by name must read
registry descriptors to build the closure. Registries are local
directories, so offline here means no registry reads at all
(rebuilding from the local cache alone), not merely no network. The
container forms are the other way to move bytes without touching a
registry. Available in the public release (S).
The preview flag belongs to the commands that write: add, install,
and update accept a dry-run flag. outdated takes none, because it
never writes; passing the flag to it is refused outright. Every command
above accepts repeatable registry addresses. (S)
The usage lines below are a verbatim excerpt of the command listing:
$ law --help law add <name>[@<version>] [--project <dir>] [--from <registryId>] [--registry <ID=LOCATION>]… [--dry-run] [--json] law install [--project <dir>] [--registry <ID=LOCATION>]… [--offline] [--dry-run] [--recover] [--json] law update <name>[@<version>] [--project <dir>] [--registry <ID=LOCATION>]… [--dry-run] [--replay <dir>] [--json]Version selection: when no version is given, the newest stable dotted release wins. Prereleases and non-dotted releases are never selected automatically. The dotted grammar is a selection convenience, not a promise of compatible behavior. The full rules live on Versions.
Argument handling is strict. Called with no package, add refuses —
verbatim error-stream output, exit code 1:
$ law addlaw: REFUSAL: law add: needs exactly one argument — <name>[@<version>]The refusal changes no file. Name exactly one package, with or without
@<version>, and run the command again.
The lockfile is the memory
Section titled “The lockfile is the memory”The lockfile pins the whole closure: one exact version per package, content hashes for the compiled bytes, dependency edges, the effective semantics line, the canon profile block, and a resolution hash over all of it. Checks that run against a project resolve through the lock, not through the manifest wishes. Validation (pin coverage, hash agreement, profile agreement) is part of the same machinery. (S)
See Packages, cases, and worlds for how the locked closure becomes a linked world, and the Schema catalog for the lock format itself.
Registries are directories
Section titled “Registries are directories”A registry is an address, not an authority. It is a directory layout of descriptors and blobs that the resolver reads. Descriptors name exact versions and content hashes. The downloaded bytes are verified against the promised hash before anything trusts them. Registry identity stays separate from mirror addresses, and a project may override addresses per registry id. (S)
There is no hosted registry service behind these pages. Directory registries that the commands consume and publish are supported surface. Anything beyond that is unconfirmed (U): this guide promises nothing about it.
Moving a closure without a network
Section titled “Moving a closure without a network”A portable container carries pins plus bytes for offline transfer.
add accepts a container file in place of a package name, and
install restores from one through its transfer flag. Neither form
reads any registry. The installed result is the same pinned closure a
registry resolution would have produced. (S)
Canon profiles pin the jurisdiction set
Section titled “Canon profiles pin the jurisdiction set”A canon profile pins a named set of packages (jurisdiction, discipline, or custom scope) with versions, namespaces, content hashes, calendars, and its own content hash. Three rules govern it:
- The profile slot in the manifest is optional. A manifest that uses it names exactly one profile at the lock root.
- The lock carries the profile block under the resolution hash.
- Published profile descriptors repeat the full element list, so the graph is checkable before any download. (S)
Profiles, release lines, and upgrades are covered from the release side on Publishing a release, Compatibility: versions and language lines, and Upgrades and replay.
Reproduction details
Section titled “Reproduction details”Toolchain, hashes, and full transcripts
The example comes from the lab’s
wiring replay,
run on the public law-v0.1.1 release; the toolchain block is on the
topic index. The full recorded step,
verbatim, with the preparation commands and the two follow-up checks:
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 0Where to go next
Section titled “Where to go next”- Packages, cases, and worlds — what the closure is for: the linked world.
- Package boundaries: what the corpus answers — the import surface and the limits of a corpus question.
- Packages and cases — the command reference this page summarizes.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.