Contracts

The movement core speaks six contracts. Each is written down here with an integer version of its own, independent of the release tag and of the others, so an embedder, an adapter vendor or a second engine can say exactly what it speaks.

contractdocumentcurrentsupporteddeprecatedon the wire
catalog-snapshotcatalog-snapshot.md11nonecontractVersion on the snapshot
park-statepark-state.md21, 2noneversion on the state
host-familieshost-families.md11nonehostFamiliesVersion on segment.open
adapter-protocoladapter-protocol.md22noneprotocolVersion on every request and the manifest
language-versionslanguage-versions.md55nonelanguageVersion beside every program
system-callersystem-caller.md11nonenone: an in-process interface

How a version moves #

The rule mirrors the language's (language-versions.md):

Each document #

Every contract document carries the same three things: its version on a line of its own at the top (Version: N), the JSON shapes as TypeScript-ish type blocks, and a "Changes" list, newest first.

Conformance kits #

A contract written down is a claim; a kit is how you check it. Each kit is data plus a runner, so it works against your implementation as well as ours.

The host kit: recorded engine runs #

A host recording is one entry into the engine as data: what it was handed, every request it made of its host in the order it made them, with the answer each got and the requests already answered when it was made, and how it ended. The format is the zod schema in packages/engine-contracts/conformance/recording.ts:

{
  kit: 'host';
  version: 2;                          // the recording format's own version
  entry: 'run' | 'resume' | 'settleRace' | 'callbackBody';
  input: RunInput | ResumeInput | SettleRaceInput | CallbackBodyInput;  // with its languageVersion
  methods: string[];                   // every host method the recorded host served
  requests: Array<
    { family: string; method: string; args: unknown; after: number[] } &
    ({ answer?: unknown } | { error: ThrownError })
  >;
  result?: unknown;                    // exactly one of result and failure
  failure?: ThrownError;
}

Replaying. An engine under replay is handed the recorded input and a host that answers from the recording. It conforms when:

A divergence over a request with no recorded counterpart also carries that request in full (unmatched on the verdict). The first divergence is named: the request with no counterpart and the nearest recorded one, the request reordered and the one it waited on, the recorded request never made, or the path where the results first differ. The rules are packages/engine-contracts/conformance/replay.ts.

Replaying a recording against your engine or host. A recording is one line of JSON, and each line replays on its own.

Recording your own host. Wrap any EngineHost with a recorder: it hands the engine and the host each other's own values, keeps JSON copies, and refuses a request or answer JSON cannot carry, and any request made after the entry ended. The recording and replay rules are packages/engine-contracts/conformance/.

What proves the host contract here. The language's proof is the engine package's shim tests (the Rust engine run through its shim against a host, packages/movement-engine), apps/cli's slot conformance (slot_conformance.test.ts, every slot module held to the same cases over the wire) and its run-host contract (run_host_contract.test.ts, the host lf itself provides). The recorded-run harness, with its corpora, its HTTP host double and its re-harvest command, is a host's own proof and belongs to the host that records them: lf-platform has one, under apps/api/src/services/movement_engine/conformance/.

The language kit: checked programs #

Every program the test suites check, with its catalog snapshot, language version and full diagnostics. The corpus and its tools are lf-platform's: in an lf-platform checkout, pnpm language:conformance <checks.json> replays a corpus against the checker, ours or your own, and pnpm checks:corpus assembles ours into target/checks/checks.json, because the repository pins each program by a hash of its text and the text lives in its test. The tools' guide is in lf-platform, packages/legacy-lang/conformance/README.md.

The adapter kit #

lf-platform's pnpm adapter:conformance runs a vendor's server through the adapter protocol and reports each check. See step 1, "Run the conformance CLI against your server", of Build your first adapter.