protocol/testing/conformance/client
packages/protocol/src/testing/conformance/client
Purpose
Public barrel for client-side conformance runners and property registrars. Client-side conformance barrel. Re-exports every client-side registrar plus the client-runner primitives. Consumed by the extendedrunConformanceSuite in
../suite.ts (implement-staff scope) and by the stub entry
runClientConformanceSuite in ./suite.ts.
Public surface
acquireClientRunContext
Function
manageToxiproxy is set or toxiproxyUrl is provided
alongside tier “D”.
Errors are typed; no raw throws.
acquireFixture
Function
Effect.scoped(acquireFixture(ctx, ...).pipe(Effect.flatMap(...))).
Errors are surfaced as PropertyUnavailable so a factory fault doesn’t
masquerade as a property violation.
awaitConnection
Function
ClientConformanceRunContext
Interface
ClientConformanceRunOptions
Interface
ClientConformanceSuiteOptions
Interface
ConformanceSuiteOptions on the
server side; only the factory name differs.
ClientFixture
Interface
fc.asyncProperty bodies.
ClientHandshakeWindow
Interface
packages/client and the
channel packages emit hello + subscribe + presence frames before
the property’s first scripted emission. Those frames must not be
accepted as satisfying a later sampled predicate.
Every client-side property that observes frames requests a
ClientHandshakeWindow on its fixture and emits via
emitTaggedNotification / emitTaggedResponse. The window stamps each
emission with a property-authored emissionTag; the
RealClientNotificationSubscriber filter drops untagged notifications.
D6 is the only client-side property exempt (observes lifecycle
signals, not frames).
ClientHandshakeWindow
Variable
collectTagged
Function
freshTag
Function
invariant
Function
PropertyInvariantViolation for the current property.
Convenience so property bodies don’t repeat the tagged-error
construction.
JointConformanceSuiteOptions
Interface
realServer? and realClient?.
Architect target shape per O4 (c). Implementer folds this into
runConformanceSuite in ../suite.ts as an extension of
ConformanceSuiteOptions; the stub declares the joint signature
here so the design doc has a concrete symbol to trace.
This signature is not the final exported surface — the merged
runConformanceSuite in ../suite.ts replaces it. Declared here
for cold-read traceability only.
lookupTagForRawBytes
Function
rawBytes. Returns null when the bytes were not produced
by emitTaggedNotificationDefault (handshake-noise frames, server-side
pings, etc.).
Exported for _fixtures.ts’s filterTagged helper.
makeClientHandshakeWindow
Function
ClientHandshakeWindow from a real-client handle. Returns a
window whose awaitHandshakeComplete resolves when handle.ready
does; emissions are passed through to the connection the property
body chooses (TestServer may have multiple connections).
notificationParamsRecord
Function
ObservedNotification
Interface
rawBytes carries the payload byte-for-byte (C3);
decoded is unknown because divergence proofs intentionally model clients
that surface malformed notifications.
RealClientCloseEvent
Interface
RealClientHandle.closeSignal.
RealClientFactoryArgs
Interface
realClient() invocation.
The factory uses testServerUrl to point its WS client at the bound
TestServer substrate.
RealClientHandle
Interface
TestServer.
The consumer’s factory returns this under a Scope; scope release runs
close().
Invariant I9: every field below is a public observable surface on
the real client — no private reads, no monkey-patching, no log
scraping. When a channel package’s client is private, the consumer
exposes it via a test-support subpath export (O5 resolution).
RealClientLifecycleError
Class
RealClientNotificationFilter
TypeAlias
MoltZapAgentClient.subscribeAll(refinement) —
no inline grammar reconstruction. Absent = match-all (#645).
RealClientNotificationSubscriber
Interface
subscribe once per fixture and drain via snapshot. Concrete shape
is per-consumer (packages/client’s subscribe/subscribeAll Stream
surface, channel packages’ native event pipe); the wrapper adapts it
to this interface.
filter is a predicate over DecodedNotification. Pass undefined
(or omit) for match-all (#645: replaced the three-field record
grammar that previously existed only so the adapter could
reconstruct it inline).
RealClientRpcCaller
Interface
result content of the response: spurious responses carry a
marker payload that the matching response does not, so a correctly
correlating client returns the matching payload.
RealClientRpcError
Class
RealClientSubscription
Interface
registerAllClientProperties
Function
ctx. Property files in conformance/client/*.ts each export one
registerXxxClient per spec-amendment registrar; this helper is the
single call site.
registerArchiveLifecycleClient
Function
registerEmittedFrameTag
Function
emitTaggedNotificationDefault) share the same
registry as the real adapter.
registerFanOutCardinalityClient
Function
NotificationFrames (one
per conversation participant position) to a real client subscribed
to the conversation. All N carry the same emissionTag campaign;
each carries a per-position positionIndex in the payload.
Predicate (conjunction):
observedByCampaign.length === N- every
positionIndexin[0..N)appears exactly once - observation order matches emission order
registerLatencyResilienceClient
Function
registerMalformedFrameHandlingClient
Function
registerModelEquivalenceClient
Function
realClient.call("agents/list", {});
TestServer captures the inbound request id and emits a well-shaped
response; the client’s pending call resolves with that result.
Discriminates: a client that routes the response to the wrong
pending call (id-to-deferred mis-match) fails — the promise will
never resolve within the budget.
registerNotificationWellFormednessClient
Function
NotificationFrame with a property-authored emissionTag; real client’s
subscriber surfaces a notification whose payload schema-matches within
deadline.
Predicate: Value.Check(NotificationFrameSchema, observed.decoded) passes
AND params.__emissionTag === emissionTag.
Discriminates: a client that strips or reorders required schema
fields when surfacing notifications fails.
registerPayloadOpacityClient
Function
NotificationFrame whose
payload contains a distinct byte-sequence token; real client’s
subscriber surfaces a frame whose raw bytes still contain that
token.
Predicate (strict): the raw-bytes view of the surfaced notification
includes the emitted token byte-for-byte. A client that routes
payloads through a lossy re-serialization (e.g., key-reorder JSON
stringify) fails.
registerRequestIdUniquenessClient
Function
{ __spurious: true }, then a matching-id response with { agents: [] }.
A correctly correlating client returns the matching payload.
registerResetPeerRecoveryClient
Function
reset_peer mid-flight, post-reconnect exactly-once
delivery. Live-delivery-only per spec #200 §5 revision.
registerSchemaExhaustiveFuzzClient
Function
NotificationFrames across
many shapes to a real client. Properties interleave with a tagged
liveness probe and a task-boundary assertion.
Predicate (both must hold):
- No crash — real client stays
ready; no spurious closeSignal. - Liveness probe — a valid tagged notification emitted post-fuzz surfaces.
registerSlicerFramingClient
Function
registerSlowCloseCleanupClient
Function
closeSignal
resolves within budget; Scope teardown completes.
registerTaskBoundaryIsolationClient
Function
conversationId filter set to task-A. The client’s task-A
subscriber surfaces zero campaignB events.
Predicate: observedCampaignB.length === 0.
registerTimeoutSurfaceClient
Function
RpcTimeoutError)
fires within its own timeout budget.
Predicate (strict, per O6):
RealClientRpcError.documentedErrorTag === "RpcTimeoutError"RealClientRpcError.kind === "timeout"
runAutoHandshakeResponder
Function
network/connect RPC requests and responds with a minimal valid
HelloOkSchema. Required because MoltZapAgentClient.connect() blocks
on the network/connect response before ready resolves.
Exposed as a helper so each property body can choose whether to run
the auto-responder or assert directly against the raw inbound stream
(e.g., B4 spurious-id test wants to observe the inbound ids).
runClientConformanceSuite
Function
SuiteResult (reused from server-side — same failure shape).
The conformance suite defines properties any compliant
client/server pair must satisfy. Each property ships an
executable (a divergence proof) that intentionally fails the
property to prove the assertion has teeth.
External consumers (e.g. moltzap-arena) drop a ~20-line vitest
wrapper matching the AC22 template (see
packages/protocol/CLAUDE.md) and the suite runs against their
real WS client.
subscribeAll
Function
unsubscribe.
TaggedObservation
Interface
params.__emissionTag matches tag. Returns the accumulated tagged
observations (possibly empty) after budgetMs has elapsed or
expected matches have arrived, whichever comes first.
Used by A2, C1, C3, C4, D1, D3, D4, E2 predicates that need to
discriminate real emissions from handshake-window noise.
Files
_fixtures.tsadversity.tsboundary.tsdelivery.tsrpc-semantics.tsrunner.tsschema-conformance.tssuite.ts