Markdown for LLMs
Publishing a release
The source Markdown for this article. Copy it into your assistant or download it as a text file.
# Publishing a release A release moves a package from a working directory to an installable, content-hashed artifact that other packages can pin. The registry is a directory layout, an address and not an authority: descriptors promise bytes, and after download the bytes prove the promise by hash. Environment: the public `law-v0.1.1` release, run from the root of the [lab bundle](/corpus/lab/#before-you-start). The example continues the lab's [versions exercise](/corpus/lab/solutions/#versions-exercise), which has already published the five lab packages to `/tmp/lab-work/registry` and authored revision `0.2.0` of `labparcels.registry` in `/tmp/lab-work/reg02`. Status letters follow the [legend on the topic index](/corpus/#how-this-topic-marks-confidence). ## Example: pack, publish, and pin one revision One package, three steps. All commands and outputs below are verbatim from the [versions exercise](/corpus/lab/solutions/#versions-exercise). **1. Pack and 2. publish** revision `0.2.0` of `labparcels.registry` into the existing lab registry: ```shell law pack --out /tmp/lab-work/artifacts/registry-0.2.0 --project /tmp/lab-work/reg02 law publish /tmp/lab-work/artifacts/registry-0.2.0 --registry lab=/tmp/lab-work/registry ``` ```text labparcels.registry@0.2.0 → /tmp/lab-work/artifacts/registry-0.2.0: contentHash sha256:fc69df17896dd8c60a4a4889e2313fd3228b234444bf0e36d98a94372ab96ce2, worldHash sha256:b3056c550cfaf9c58fa84befda4557d3b6c5020fdfc8c324086335343998e597, 3 files labparcels.registry@0.2.0 → lab (/tmp/lab-work/registry): contentHash sha256:fc69df17896dd8c60a4a4889e2313fd3228b234444bf0e36d98a94372ab96ce2, worldHash sha256:b3056c550cfaf9c58fa84befda4557d3b6c5020fdfc8c324086335343998e597 versions labparcels.registry: 0.1.0, 0.2.0 changed: p/labparcels.registry/0.2.0/package.lawir.json changed: p/labparcels.registry/0.2.0/world.lawir.json changed: p/labparcels.registry/0.2.0.json ``` The first line is `pack`: it names the artifact directory and two hashes. The content hash pins the package bytes; the world hash pins the package together with its closure. The remaining lines are `publish`: the same two hashes now stand in the registry, the registry lists both known versions, and the `changed:` lines name the descriptor (`0.2.0.json`) and the two blobs it wrote. What this result means: any project that can read the `lab` registry can now pin `labparcels.registry@0.2.0`, and the install will verify the downloaded bytes against `sha256:fc69df17…`. Nothing in an existing consumer changed yet. **3. Pin** the new revision from a consumer, here a scratch copy of the fees package at `/tmp/lab-work/fees-upd`: ```shell law update 'labparcels.registry@0.2.0' --project /tmp/lab-work/fees-upd --registry lab=/tmp/lab-work/registry ``` ```text lab ← /tmp/lab-work/registry (--registry) ~ labparcels.registry 0.1.0 -> 0.2.0 changed: .law/transport.json changed: deps/labparcels.registry.lawir.json changed: law.lock changed: law.toml changed: package.law ``` The consumer's manifest, lock, pinned bytes, and import line now name `0.2.0`. In the lab run its five scenarios still pass after the move, so the consumer can commit the new pin. Previewing the move first and checking currency afterwards are covered on [**Upgrades and replay**](/corpus/releases/replay-and-upgrades/). ## The three steps in general First `pack` builds the release artifact: a directory or a portable `.arxo` container. Then `publish` places it into a registry directory, or prepares a signed candidate from a manifest plus a bytes directory. Downstream packages then pin the exact version with `add` or `update`. The directory flow is **available in the public release** (S). The command catalog records these usage strings for the first two steps: ```text law pack --out <dir|file.arxo> | --answers … | --runs … [--project <dir>] [--json] law publish <artifact> (--registry <ID>=<dir> | --candidate <manifest.json> --bytes <dir>) [--json] ``` `publish` refuses to run without a pack artifact, as a bare run shows: ```text $ law publish law: REFUSAL: law publish: needs a `law pack` artifact directory ``` The refusal writes nothing. Run `law pack` first and pass its output directory to `publish`. A hosted registry service beyond the directory layout is **unconfirmed** (U): this guide cannot promise one, so treat any such endpoint as unconfirmed until it is announced. ## What an artifact directory contains Each published release keeps its lockfile, its compiled package bytes, its release record, and its linked world bytes together. The observed layout for the release `calc.tiers` at `0.1.0`, a law pack artifact in format `law.package-release/0.1`: ```text $ ls dist/artifacts/calc.tiers-0.1.0/ law.lock package.lawir.json release.json world.lawir.json ``` The linked world bytes are produced by new-root linking at pack time. Downstream, fixed-world-artifact execution verifies and runs them but never links again. The descriptor hash check after download is what makes the publisher's promise verifiable. (S) ## Two formats, not one The example above is the left column below: those four files are exactly what `law pack --out <dir>` produces, and `publish` then places such a directory into a registry. The right column, the standalone release, adds a passport and a report store: | | Law pack artifact | Standalone release | |---|---|---| | Format id | `law.package-release/0.1` | `law.package-build/0.3` and later | | Passport | none: no passport file inside | required: without one it is not a release | | Checks at build | lockfile, compiled bytes, and linked world packed together | compiles, runs scenarios, replays the saved evaluations, then writes the passport; any failure stops the build | | Downstream artifacts | registry placement; `.arxo` container for offline moves | the passport travels with the release; quality, replay, and performance reports attach later | | Report location | the hash check at install time; no separate report store | hash-addressed reports stored beside the release, never inside it | ## Offline transfer with containers The `.arxo` container carries pins plus bytes for offline moves. `add` takes a container file in place of a package name, and `install` restores from one through its transfer flag. Neither form reads any registry, so a container copied on removable media moves a closure with no network at all. The transfer re-verifies content hashes on arrival, so the carried bytes are as trustworthy as a registry download. (S) Canon profiles publish through the same channel: the registry carries a signed profile descriptor, so installers can check the pinned graph before downloading any package bytes. (S) ## What to read next - [Versions protocol](/protocols/versions/) for version selection rules. - [Schema catalog](/protocols/schemas/) for descriptor, lockfile, and profile formats. - [Command-line reference](/cli/) for the pack, publish, add, and install commands.