docs← Back to article

Markdown for LLMs

Arxo Change Protocol

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

Download this articlePlain text ↗
# Arxo Change Protocol

The Arxo Change Protocol turns a change of the rules into an object: the
states before and after, the world the change applies to, the mode of
entry into force, and the dossier assembled from them. Where the
[Arxo Fact Protocol](https://github.com/arxohq/law/blob/master/docs/protocols/01-fact-protocol) and the
[Arxo Decision Protocol](https://github.com/arxohq/law/blob/master/docs/protocols/02-decision-protocol) answer what follows from
the rules for these facts, the Change Protocol answers what would change
if the rules changed.

## The change set

A [change-set](/protocols/schemas/change-set/) names one normative
change. Its load bearing parts are:

- the [`units`](/protocols/schemas/change-set/): one or more pairs of
  states — `before` and `after` — each a dated edition of a package, a
  draft model over it, or a release of a case package;
- the [`world`](/protocols/schemas/change-set/): the dependency closure
  the change is read against, plus a `boundary` statement saying what the
  world does not contain — anything outside the closure is outside the
  dossier by construction;
- the [`intent`](/protocols/schemas/change-set/): the expected changes
  stated before measuring, the protected goals and the protected scope;
- the [`commencement`](/protocols/schemas/change-set/): the mode of entry
  into force;
- the [`producers`](/protocols/schemas/change-set/): the artifacts the
  dossier is assembled from, each with the tool that made it, its path and
  the hash of its bytes. The dossier builder reads them and never
  re-executes anything.

A small change set — one package, two dated editions, one producer
artifact — looks like this:

<!-- schema: change-set -->
```json
{
  "schemaVersion": "law.change-set/0.1",
  "id": "urn:change:demo-parking-fine-2026",
  "kind": "edition-change",
  "title": {
    "en": "City parking fines, 2025 edition against 2026 edition"
  },
  "legalStatus": "draft",
  "units": [
    {
      "subject": "package",
      "package": "demo.parking",
      "before": {
        "kind": "edition",
        "label": "2025 edition",
        "edition": "PARKING_2025",
        "editionDate": "2025-01-01"
      },
      "after": {
        "kind": "edition",
        "label": "2026 edition",
        "edition": "PARKING_2026",
        "editionDate": "2026-01-01"
      }
    }
  ],
  "world": {
    "root": "demo.parking",
    "closure": [
      {
        "name": "demo.parking",
        "version": "1.0.0"
      }
    ],
    "boundary": "Only the city parking package; the national traffic rules it references are pinned and unchanged."
  },
  "producers": [
    {
      "tool": "scenarios",
      "path": "analysis/scenarios.json",
      "sha256": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
      "role": "end-to-end"
    }
  ]
}
```

The `legalStatus` names the status of the after state, not of the model:
a draft is not law.

## The dossier

A [change-dossier](/protocols/schemas/change-dossier/) is the case for or
against the change, assembled from the producers' artifacts: what was
measured, which goals held, which objections were raised and answered,
which computations were re-run under the old program, and what remains
unverified. Its deterministic core carries its own hash, so a reader can
tell whether the dossier in front of them is the one the builder built.

Three invariants hold for every dossier. It proves only what is
formalized — the measure and the world boundary are printed always.
Statistics over a sample are not a legal answer for a case. And accepting
a scenario into the bank, objections included, gives it no legal force.