Bump package, Rust workspace, bridge helper cache, and contract fixture versions together so the remote helper path and release metadata stay in sync for the v0.3.6 cut. Made-with: Cursor
Protocol contract fixtures
This directory holds static JSON (and one multi-line text) fixtures for the Sessions wire contract between the local bridge (Rust local_bridge, driven by Python in sublime/sessions/ssh_file_transport.py) and the remote session helper (session_helper, Rust). They are intended for shared parsing tests and documentation; they are not wired into any test runner by themselves.
Transport
- Framing is NDJSON: one UTF-8 line per logical message, each line a single JSON object.
- Every helper-visible line uses the serde externally tagged shape: a top-level
message_typefield (handshake,request,response,error,cancel,shutdowninsnake_case) with the remaining fields flattened from the inner struct (session_protocol::ProtocolMessage).
Two request shapes
-
Python → bridge (stdin, persistent mode)
One JSON object per line withoutmessage_type:id,method,params,timeout_ms,trace(stringoff|error|info|debug). This matchesRequestEnvelopeJSON as consumed bylocal_bridgewhen--persistentis used. -
Bridge → helper (remote stdio)
The same logical request is wrapped as{"message_type":"request",...}viasession_protocol::encode_messagebefore it reaches the helper. Fixtures that describe helper traffic use this shape only where noted.
Fixtures named *.request.json use the Python → bridge envelope and follow ssh_file_transport._execute_rust_bridge_request: methods tree/list, file/read, file/stat, and file/write are sent as method: "channel/dispatch" with params.v = "sessions.channel.v1", channel: "file", kind: "request", and the real method in params.body. exec/once is sent with method: "exec/once" directly (no channel wrapper).
Responses and errors
- Fixtures named
*.response*.jsonand helper-side errors usemessage_type: "response"ormessage_type: "error"with flattened fields:responsecarriesidandresult;errorcarries optionalid,code,message,retryable. file_write.error.*.jsonare stillresponsemessages: structured write failures are carried inresultasfile/write’sFileWriteResult(ok: false,error_code,error_message), which matches howsession_helperreports most write failures instead of a top-level protocolerror.
Bridge → Python (stdout)
The bridge prints one JSON object per line shaped as { "ok": bool, "id"?: string, "result"?: any, "error"?: { "id"?, "code", "message", "retryable" } } (local_bridge::BridgeCliOutput). Fixtures prefixed with bridge_stdout.* capture this envelope explicitly so both Python parser tests and Rust output-model tests can verify the contract independently.
File reference
| File | Role |
|---|---|
handshake.valid.json |
Valid handshake line from the helper after startup. |
handshake.missing_required_fields.json |
Invalid handshake JSON (omits protocol_version and remote_home) for negative decoding tests. |
tree_list.request.json |
Python-style channel/dispatch wrapping tree/list. |
tree_list.response.json |
Helper response with mixed TreeListEntry values (directory, regular_file, symlink + is_symlink_loop: true). |
file_read.request.json |
Python-style dispatch for file/read. |
file_read.response.regular_file.json |
Helper response; body_b64 is standard Base64 of hello\n (aGVsbG8K). |
file_read.response.directory.json |
Helper response for a non-regular path: metadata.kind is directory and body_b64 is empty (matches session_helper today). Callers should treat this as “not readable as file bytes”. |
file_stat.response.exists.json |
Helper response with exists: true and metadata. |
file_stat.response.not_exists.json |
Helper response with exists: false (no metadata). |
file_write.request.json |
Dispatch for file/write including expected_metadata. |
file_write.response.success.json |
FileWriteResult success payload inside result. |
file_write.error.permission_denied.json |
Structured failure with error_code: "permission_denied". |
file_write.error.metadata_changed.json |
Structured failure with error_code: "remote_metadata_changed". |
exec_once.request.json |
Direct exec/once Python-style request. |
exec_once.response.success.json |
Successful ExecOnceResult. |
exec_once.response.timeout.json |
Timed-out ExecOnceResult (timed_out: true, exit_code: 124, stderr suffix style from the helper). |
error.session_scoped.json |
Protocol-level error with id: null (session-scoped). |
protocol.malformed_stdout.txt |
Sample stdout with non-JSON noise lines mixed with valid NDJSON frames (decoder tolerance / diagnostics). |
bridge_stdout.success.handshake.json |
Bridge CLI handshake output (persistent mode first line): ok: true, result.handshake with remote_home, arch, helper_version, etc. |
bridge_stdout.success.file_read.json |
Bridge success envelope wrapping a file/read result (ok: true, id, result with metadata + body_b64). |
bridge_stdout.success.tree_list.json |
Bridge success envelope wrapping a tree/list result. |
bridge_stdout.error.permission_denied.json |
Bridge error envelope for a file/write permission-denied failure (ok: false, structured error). |
bridge_stdout.error.session_scoped.json |
Bridge error envelope with id: null (session-scoped abort). |
bridge_stdout.malformed.non_json.txt |
Mixed valid and non-JSON lines as they could appear on bridge stdout (tolerance test). |
bridge_stdout.malformed.ok_missing.json |
JSON object missing the required ok field — Python must reject or handle gracefully. |
bridge_stdout.malformed.result_missing.json |
ok: true but no result field — tests incomplete success envelope handling. |
bridge_stdout.malformed.id_mismatch.json |
Valid bridge output with an id that does not match any pending request — tests response routing. |
Shared vocabulary
- RemoteFileKind (JSON string):
regular_file,directory,symlink,other. - FileWriteErrorCode (JSON string, snake_case):
permission_denied,path_is_directory,remote_file_missing,remote_metadata_changed,transport_error. - ShutdownNotice.reason:
stdin_closed,ssh_disconnected,bridge_requested.
Base64
Example used in file_read.response.regular_file.json: plaintext hello\n → aGVsbG8K (standard Base64, RFC 4648).