Skip to content

Set up a project reference

Register actors, then move a project reference between revisions under a policy you choose.

A project reference names a line of revisions. It moves only under its active policy, and only when an actor the store’s operator registered asks.

Before you start

  • A store whose objects are accepted and named by aliases (Move an alias safely).
  • The server stopped, for step 1.
  • In the commands, $STORE is the store directory, $CONFIG your runtime configuration and $SOCK the server’s socket.

1. Register the actors

Register one operator, who may create references, and one actor for everyday publication. These commands open the store directly, so the server must be stopped:

Shell
lema actor add --store $STORE --id steward --operator
lema actor add --store $STORE --id agent

Each command prints the actor, whether it is an operator, and a new random token. The token is shown once: actors.json keeps only its SHA-256. Save each token in a file that only you can read, for example steward.token and agent.token. lema actor list --store $STORE, also with the server stopped, shows the IDs and operator flags but never the tokens.

An actor ID is 1 to 128 bytes of ASCII letters, digits and ._@-, starting with a letter or digit. An ID that already exists is refused: tokens are not rotated or revoked in this version. If the server is running, the command fails with the store at DIR is in use.

Tokens keep cooperating actors apart, such as an agent and a human steward. They do not stop a hostile local user: every client of a local store runs as the store’s OS user, who can also change the store’s files directly.

2. Start the server and take a snapshot

Shell
lema serve --store $STORE --runtime $CONFIG --socket $SOCK &
lema --socket $SOCK snapshot --aliases app. --assets doc=README.md

snapshot creates a binding map that exports every alias starting with app. under its alias name, hashes README.md locally, and creates a snapshot over the map. It prints bindings, snapshot and created. Keep the snapshot ID as $SNAPSHOT.

The binding map records the object IDs the aliases named when you ran the command, so later alias moves change no snapshot. Other ways to select:

FlagSelects
--roots ID,..accepted objects, as roots
--exports-file Fexports from a JSON list of {name, id, role?}
--authoring ID,..stored authoring bundles
--assets KIND=PATH,..files of kind doc, config or asset, kept as SHA-256 and size only

3. Create the first revision

Shell
lema --socket $SOCK revision create --after $SNAPSHOT --intent "Start."

It prints the revision’s id (keep it as $REV), created, and before, which is null because a first revision starts from the empty state. To cite evidence, add --evidence-file F with a JSON list of {kind, id}, where kind is accepted or guarantee. To list open obligations, add --obligations-file F.

4. Create a policy

policy.json
{"version": 1, "publish": ["agent"], "adopt": ["steward"]}
Shell
lema --socket $SOCK policy create --file policy.json

It prints the policy’s id (keep it as $POLICY) and created. publish lists who may move the reference to a following revision. adopt lists who may move it to the next version of its policy. The optional fields (reset, waive, require and others) are described in Store records.

5. Create the reference

Shell
lema --socket $SOCK ref create --name main --policy $POLICY --actor steward --token-file steward.token

The CLI reads the token from the first line of --token-file, or from LEMA_ACTOR_TOKEN, never from the command line. The new reference starts at the empty state, with revision: null, generation: 1 and policy_version: 1. Only an operator can create a reference, and only under a policy of version 1.

Refusals you may see:

  • set LEMA_ACTOR_TOKEN or give --token-file FILE: no token was given.
  • is not authenticated (unknown actor or wrong token).
  • only an operator does (lema actor add --operator).

6. Publish the revision

Shell
lema --socket $SOCK publish-revision --ref main --revision $REV \
  --expect-revision none --expect-generation 1 --expect-policy-version 1 \
  --actor agent --token-file agent.token

All three expectations are required, so a move never applies to a reference that changed after you looked. For each later move, read the current values with lema --socket $SOCK ref list, which gives every reference’s revision, policy, policy_version and generation.

The next revision must have the reference’s current revision as its first parent:

Shell
lema --socket $SOCK revision create --after $SNAPSHOT2 --intent "Add the parser." --parents $REV

The server checks a move and applies it in one call. It refuses, and writes nothing, when:

  • the active policy’s version is not the expected one (stale policy), or the revision or generation is not (stale expectation);
  • the actor is not listed under publish in the active policy;
  • the revision’s first parent is not the reference’s revision (does not follow reference main). To join two lines, use a merge revision, as in Report on a change and merge two lines;
  • the revision fails the policy’s requirements, for example an axiom outside require.axioms, or an open obligation under no_obligations.

A refused publication keeps the revision, its records and its objects stored for a later attempt. --idempotency-key K makes a retry return the first response instead of applying twice. Keys are shared across the whole store, so start them with the actor ID. --reset moves the reference back to an ancestor, for actors listed under reset.

7. Read the history

Shell
lema --socket $SOCK log --ref main
lema --socket $SOCK revision log $REV --limit 20
lema --socket $SOCK revision show $REV
  • log --ref lists the reference’s moves, newest first, each with its actor and recorded decision.
  • revision log lists a revision and its ancestors, breadth first along the parents, with the first-parent line first.
  • revision show gives the revision, its after-snapshot and the references that name it now.

To change the policy later, create one with "version": 2 and "previous" set to the active policy’s ID. Then move the reference with lema adopt-policy, which takes the same expectation flags. The active policy’s adopt list decides who may do this.

Written against lema-lang at commit 5a94951, 17 Oct 2026.