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.
What a corpus scenario is
Section titled “What a corpus scenario is”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 isclient(written to the host’s stdin) orserver(read from its stdout), andraw, which holds the exact wire bytes of one frame without the trailing line feed. Recover the wire by writingrawplus a line feed per line. Client lines may end with a carriage return insideraw— 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.frameLimitBytesat minimum — replay always starts the host with it), the id and clock seeds, and the declarednormalizelist 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"}Validating your client
Section titled “Validating your client”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:
muse-conformance serve-fixture --transcript transcripts/session-startWrite 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.
Matching semantics
Section titled “Matching semantics”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
clientline as parsed JSON — key order and whitespace are free. - Id unification for the values you mint. Exactly two declared paths are
yours: the
idon your own requests andparams.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, butparams.clientInfo.nameandparams.clientInfo.versionon yourinitializeare unified exactly like your ids, and the optionaltitledisplay 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
idyou 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.