docs← Back to article

Markdown for LLMs

Compatibility: versions and language lines

The source Markdown for this article. Copy it into your assistant or download it as a text file.

Download this articlePlain text ↗
# Compatibility: versions and language lines

Compatibility in this corpus has three independent dimensions: the package
version, the language line the package is written against, and the canon
profile that pins a releasable set. This page explains each one and how they
combine.

Environment: the observed transcript below comes from the public
`law-v0.1.1` release run over the [lab bundle](/corpus/lab/#before-you-start).
Status letters follow the
[legend on the topic index](/corpus/#how-this-topic-marks-confidence).

## Version grammar is wide; selection is narrow

Example first. Four version strings and what happens to each:

| Version string | Legal? | Selected automatically as "latest"? |
|---|---|---|
| `0.2.0` | yes | yes: a structured stable number |
| `0.3.0-rc.1` | yes | no: a pre-release |
| `2026-09` | yes | no: not structured numbering; install it by exact pin |
| `-1` | no: a version must start with a letter or digit | — |

The lab shows selection at work. After revision `0.2.0` of
`labparcels.registry` is published next to `0.1.0`, the currency check
over the fees package reports the newer stable version. Verbatim, from
the lab's [versions exercise](/corpus/lab/solutions/#versions-exercise):

```text
lab ← /tmp/lab-work/registry (--registry)
labparcels.iface@0.1.0 [lab]: up to date
labparcels.registry@0.1.0 [lab]: published 0.2.0
```

What this result means: `0.2.0` is the version a dependency command
would pick for `labparcels.registry` when no version is named. The pin
in the lock still says `0.1.0`, and nothing changes until someone moves
it with `law update`. The number alone does not justify the move; the
consumer's scenarios do.

The rule behind the table: a package version must start with a letter
or digit, followed by letters, digits, dots, underscores, pluses, or
hyphens. Structured `major.minor.patch` numbers with optional
pre-release and build parts are only a selection convenience on top of
that grammar. A version outside structured numbering is therefore a
legal state, not a manifest error; such a release simply takes no part
in automatic latest-version selection. The source comment that states
this rule:

```text
/// A package version §10 admits a wider shape (`^[0-9A-Za-z][0-9A-Za-z._+-]*$`),
/// so "not semver" is a legal state, not a manifest error: such a
/// release simply takes no part in automatic latest-version selection.
```

Consequences for upgrades:

- A version that is not structured numbering is legal and stays installable
  by exact pin. It is never auto-selected as "latest".
- Pre-releases are excluded from latest-stable selection.
- Structured numbering is not a promise of compatible behavior. Exact
  pins in the manifest and lockfile decide what you get; the number
  never does. **Available in the public release** (S).

The [Versions protocol](/protocols/versions/) is the normative reference for
this behavior.

## Language lines: 0.1 versus 0.2

The `0.2` language line is frozen: only additive revisions extend it. A
world links exactly one semantics line, and closures that mix lines are
refused at resolution time. The lockfile records the line of the linked
world, so a later run still evaluates under the same semantics. (S)

The semantics line alone replays nothing. Repeating a saved result
years later needs three more things beside it:

- the saved toolchain: the exact build tools, pinned by hash;
- the input artifacts: the release bytes plus the saved evaluations;
- the replay mechanism, which re-runs those evaluations and compares
  the result bytes.

Lose any of the four and the outcome is a fresh computation, not a
replay. When you record a result, record the full `law version` output
with it; the block this page was written against is under
[Reproduction details](#reproduction-details).

## Canon profiles pin a releasable set

A canon profile (`law.profile/0.1`) pins a named set of packages with exact
versions, content hashes, calendars, and the required semantics revision.
It is one reviewable unit: a manifest adopts it through its profile slot,
and the lockfile then carries it under its resolution hash. The observed
top-level fields are:

```text
Arxo canon profile 0.1 | schemaVersion, id, version, kind, title, asOf,
language, semanticsRevision, packages, calendars, contentHash
```

`calendars` appears only where a calendar is pinned; the remaining
fields are present on every observed profile.

The `kind` value (`jurisdiction`, `discipline`, `tradition`, or `custom`)
is descriptive only. Profiles nest transitively. Registry descriptors
carry a signed profile form, so graphs can be checked before any bytes
download. (S)

A worked example over the lab fixtures (`labparcels.iface`,
`labparcels.registry`, `labparcels.fees`, `labparcels.appeals`,
`labparcels.case1`) shows how a locked world keeps every member on one
line; the [lab tour](/corpus/lab/) walks through it.

## Reproduction details

<details>
<summary>Toolchain, hashes, and full transcripts</summary>

The pinned toolchain at the time of writing reports itself as follows
(stdout of the version command; build warnings on standard error omitted):

```text
$ law version
law 0.1.1
semantics: law.core/0.2
std for language 0.2: 0.2.0
lawql: lawql/1 (queryResult 0.1)
binary hash: sha256:cfa7c17232f2dc594e665dbbf2ad3c154675797ef4be07ef7d758c9abfb80a28
```

Quote these five lines when recording what a result was computed with.

</details>

## What to read next

- [Versions protocol](/protocols/versions/) for the normative rules.
- [Schema catalog](/protocols/schemas/) for the lockfile and profile formats.
- [Command-line reference](/cli/) for the package and world commands.