> ## Documentation Index
> Fetch the complete documentation index at: https://docs.canary.effectiveai.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Versions

> A rater meets three version numbers and one computed identity: the RSL language version, the compiler release, its own version and its bundle identity.

Each number answers a different question, so each one changes at its own pace.

| Number | Example | Who sets it | The question it answers |
| - | - | - | - |
| RSL language version | `0.4.1` | You, as `rsl` in `spec` | Which language is this file written in? |
| Release | `0.7.2` | The installed packages | Which compiler checks and rates this file? |
| Rater version | `"1.2.0"` | You, as `version` in `spec` | Which edition of the rating plan is this? |
| Bundle identity | 64 hexadecimal characters | The compiler, from the files | Which exact source and tables gave this premium? |

The examples use a small synthetic rater. Save it as `versions/rater.rsl`:

> [accordion] Complete example: versions/rater.rsl
>
> ```rsl versions/rater.rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
> spec {
>     rsl: "0.4.1",
>     carrier: "Example Mutual",
>     state: AZ,
>     product: "Staffing Liability",
>     version: "1.2.0",
>     effective_date: 2026-01-01
> }
>
> Sources = {
>     manual: Source = {
>         artifact: artifact("00000000-0000-4000-8000-000000000000"),
>         kind: pdf
>     }
> }
>
> Constants = {
>     rate_per_1000 [cite: manual:p3] = 2
> }
>
> Records = {
>     Policy = {
>         inputs {
>             payroll: Num {precision: int} where self in [0, 100000000]
>         },
>         step rating {
>             premium: Premium [cite: manual:p3] = round(self.payroll / 1000 * rate_per_1000, 2, half_up)
>         }
>     }
> }
>
> RatingOutcomes = {
>     premium: Policy.premium
> }
> ```

## The language version says how to read the file

```rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
spec {
    rsl: "0.4.1",
    carrier: "Example Mutual",
    state: AZ,
    product: "Staffing Liability",
    version: "1.2.0",
    effective_date: 2026-01-01
}
```

`rsl` names the version of RSL that the file is written in. `rslc fmt` keeps it as the first field of `spec`.
This compiler reads RSL 0.4 and 0.4.1.

The version has a line, 0.4, and a patch, 1. A patch only adds to its line.
A rater that declares `"0.4"` passes the check of this compiler and rates the same premiums.
A rater that uses an addition of 0.4.1 declares `"0.4.1"`, and
[`E-RSL-PATCH`](https://docs.canary.effectiveai.app/rsl/reference/check-messages/header#e-rsl-patch) names the addition otherwise.

The entry point declares the version for each file it imports.
[Split a rater into files](https://docs.canary.effectiveai.app/rsl/how-to/split-a-rater-into-files.md) describes the entry point.

### One message for another version

The compiler reads the declaration before the rest of the file.
A file that declares another version gets one message, and the check stops there:

```rsl later/rater.rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
spec {
    rsl: "0.5"
}
```

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc check later/rater.rsl
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
FAIL later/rater.rsl (strict)
error: E-RSL-VERSION later/rater.rsl:2:10: RSL's latest version is 0.4.1. This rater is written for RSL 0.5. Update rslc to a release that implements RSL 0.5, then rerun.
```

A file written for another version may use syntax that this compiler reads differently.
A page of syntax messages would hide the cause, so the compiler reports the version alone.

The message says what to do. For a later version, update `rslc`.
For an earlier version, or a `spec` that lacks `rsl`, rewrite the rater in the current version.
[`E-RSL-VERSION`](https://docs.canary.effectiveai.app/rsl/reference/check-messages/header#e-rsl-version) shows an example.

## The release says which compiler you run

`rslc` is the compiler and the rating engine. `relativities` is the Python library that rates with it.
Each release of `relativities` requires one exact release of `rslc`, so one install fixes both.

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc --version
```

The command prints the release number, such as `0.7.2`.

`rslc docs` names the language version that the release reads:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc docs
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
RSL 0.4.1 reference. Run `rslc docs TOPIC`:
...
```

Python reads the same numbers from the installed packages:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
from importlib.metadata import version

import rslc

print(version("relativities"), version("rslc"), rslc.compiler_version())
# 0.7.2 0.7.2 0.7.2
```

The release and the language version move separately.
A release can fix a check, add a command or rate faster while the language stays 0.4.1.
Each rater's `rsl` declaration then stays valid, and its source stays as it is.

## The rater version is a label you set

`version` is an optional field of `spec`. Give it the edition of the rating plan, in the form your team uses.
The compiler keeps it with the other `spec` fields, and each program that loads the rater reads it there:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
from relativities import Rater

rater = Rater.build("versions/rater.rsl")
print(rater.metadata["catalog"]["spec"])
# {'carrier': 'Example Mutual', 'effective_date': '2026-01-01', 'product': 'Staffing Liability', 'rsl': '0.4.1', 'state': 'AZ', 'version': '1.2.0'}
```

The label is the author's statement. The compiler keeps it as text and leaves its meaning to you.

## The bundle identity pins a result

A bundle is the rater in the form that rates: its source files, its tables and a manifest of their hashes.
The bundle identity, `bundle_id`, is a hash over the bundle.
The compiler computes it, so the same files give the same identity:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
again = Rater.build("versions/rater.rsl")
print(len(rater.bundle_id), again.bundle_id == rater.bundle_id)
# 64 True
```

An edit to a source file or a table gives a new identity, even when the `version` label stays the same.
Change the rate in a copy of the rater, and keep the label:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
from pathlib import Path

source = Path("versions/rater.rsl").read_text()
Path("revised").mkdir(exist_ok=True)
Path("revised/rater.rsl").write_text(source.replace("= 2\n", "= 2.5\n"))
revised = Rater.build("revised/rater.rsl")

print(revised.metadata["catalog"]["spec"]["version"], revised.bundle_id == rater.bundle_id)
# 1.2.0 False
request = {"payroll": 250000}
print(rater.rate(request).to_pandas()["premium"].item(), revised.rate(request).to_pandas()["premium"].item())
# 500 625
```

Both raters carry the label 1.2.0, and they give different premiums. The bundle identity tells them apart.
A person sets a label and may forget to raise it. The identity follows the files.

Record the `bundle_id` beside each premium you keep. It names the exact source and tables behind the premium.
[Bundles and exact rating](https://docs.canary.effectiveai.app/relativities/explanation/bundles-and-exact-rating.md) shows how to load a bundle by its identity.

A bundle that `rslc export` writes also holds its rating engine and a program layer, and its identity covers them.
Compare identities between bundles made the same way.

## What stays stable for a rater in use

* With one release installed, the same source and tables give the same bundle identity and the same premiums.
* The folder and the time of the build leave the identity as it is.
* A saved bundle keeps its identity. `Rater.load` checks each file against the manifest before it rates.
* A rater that declares `"0.4"` stays valid under 0.4.1, the later patch of its line.

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rater.save("versions.zip")
print(Rater.load("versions.zip").bundle_id == rater.bundle_id)
# True
```

After you install a new release, check the rater and rate your examples again.
Compare the premiums and the `bundle_id` with the values you recorded.

## Related

* [Bundles and exact rating](https://docs.canary.effectiveai.app/relativities/explanation/bundles-and-exact-rating.md) explains how a bundle is verified.
* [Use the rslc commands](https://docs.canary.effectiveai.app/rsl/commands.md) covers `rslc check`, `rslc export` and `rslc docs`.
* [Install Relativities](https://docs.canary.effectiveai.app/relativities/setup.md) installs both packages.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.