Skip to content
Developer Preview

Conformance

You do not prove an MSP client correct by reading — you prove it by replaying the golden transcript corpus. The conformance testkit makes the wire contract executable: fixtures are recordings of full connections, produced by running the real server against deterministic fake tools and a seeded id and clock source, one fixture per contract scenario. The corpus lives beside the schema bundle in the source tree that produces the server; a packaged distribution for client developers has not shipped yet. Its README.md is the operating manual this page summarizes, so everything below also tells you what to expect when you receive a copy.

Each scenario is a directory named by its scenario id, containing:

  • transcript.ndjson — the wire session, pure NDJSON. Every line is one standalone JSON object with two members: dir, which is client (written to the host’s stdin) or server (read from its stdout), and raw, which holds the exact wire bytes of one frame without the trailing line feed. Recover the wire by writing raw plus a line feed per line. Client lines may end with a carriage return inside raw — tolerated on input, never emitted by the server.
  • manifest.json — provenance and pins: the scenario id, the schema fingerprint the transcript was authored under, the recorded server configuration (serverConfig.frameLimitBytes at minimum — replay always starts the host with it), the id and clock seeds, and the declared normalize list of nondeterministic paths.
  • records.jsonl (optional) — harness-internal input to the reconciliation check; its shapes carry no cross-language stability promise, and clients must not parse it.

Here is the shortest possible sample — the first line of the framing-tolerance-cr-input scenario, whose whole point is the trailing carriage return tolerated inside the client frame:

{"dir":"client","raw":"{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"clientInfo\":{\"name\":\"conformance\",\"version\":\"0.0.0\"}}}\r"}

The corpus works with no special tooling in any language: read transcript.ndjson line by line with any JSON parser, drive your client’s fold with the server lines, and compare what your client would send against the client lines under the manifest’s normalize list.

The line-by-line replay above is the supported validation path today: the corpus format needs nothing beyond a JSON parser, in any language.

There is also an interactive harness, muse-conformance, which plays the server side as a canned host — but like the corpus itself it is not yet distributed to client developers. When you have a build of it, spawn it exactly as you will spawn muse serve:

Terminal window
muse-conformance serve-fixture --transcript transcripts/session-start

Write your frames to its stdin, read recorded server frames from its stdout, and it fails closed with a machine-readable divergence report on the first frame that does not match.

These are the rules the harness applies, and the mental model your own comparator should copy:

  • Your frames are matched structurally. Each of your frames is compared against the transcript’s next client line as parsed JSON — key order and whitespace are free.
  • Id unification for the values you mint. Exactly two declared paths are yours: the id on your own requests and params.commandId. Your values need not reproduce the recorded ones — the first sighting pairs your value with the recorded value, and the pairing is held one-to-one for the run, so reusing one of your ids against two different recorded ids is a mismatch.
  • Your identity is yours. The corpus was recorded by a client that named itself conformance, but params.clientInfo.name and params.clientInfo.version on your initialize are unified exactly like your ids, and the optional title display member may be present or absent regardless of the recording — send your client’s real identity; it is never matched against the recording client’s.
  • Values learned from the wire are matched exactly. The id you echo when answering a server-initiated request, params.turnId, params.itemId — each was delivered to you byte-exactly, so your echo has no freedom; answering the wrong request is a correlation bug and fails the run.
  • Server frames are byte-exact. Recorded server lines are emitted verbatim and never rewritten to your ids — byte-identity is the point of the corpus.
  • Off-transcript frames are never improvised. A harness that invented replies would be a second server implementation, which the corpus contract forbids; an unexpected frame stops the run with a typed failure.

One fixture class is deliberately hand-authored and exempt from real-server replay: the SDK-tolerance fixtures, which carry shapes a real server cannot emit (an unknown item kind, an unknown session-state method) so that your client’s must-ignore and render-generically duties are executable too. Open-enum tolerance also applies during validation: an unknown string value on an enum the bundle marks open validates as conformant with a warning, never a failure.

The corpus scripts exact dialogues; it is not a template for the frames your client must send in production. In particular, some recorded client frames carry a futureOptionalField member: that is the ignore-unknown-members fixture — a conforming server ignores unknown members on stable-surface requests — so a scripted serve-fixture run reproduces it, but it is not a member real clients send, and a preflight must not treat recorded client frames as required request shapes.