Core documentation

Transport and lifecycle

Specification metadata
title: Transport and lifecycle
status: draft
normative: true
summary: Private JSON-RPC stdio dogfood floor, optional warm transports, the initialize handshake, and the session state machine.
updated: 2026-06-23

2026-06-23 binding decision: ADR 0025 chooses native JSON-RPC over stdio as the private dogfood binding floor. A namespaced MCP extension remains a private compatibility/status experiment; the semantic contract remains transport-neutral.

§Transport

This chapter records the private JSON-RPC 2.0 dogfood floor, newline-delimited (one JSON object per line, no embedded newlines). It is not a public deployment commitment, stable package surface, or deployment trust root.

Requests carry an id and expect a response. Notifications omit id and MUST NOT be answered. $/-prefixed methods are protocol utilities (progress, cancellation). See decision 0001.

§Session model

One stateful session per workspace root. The server holds its model warm across calls — that warmth is the reason these are servers, not CLI shells. The host owns session lifecycle: it spawns, initializes, supervises, and shuts down the server.

§State machine

spawned ──initialize──▶ initializing ──initialized──▶ active ──shutdown──▶ shuttingDown ──exit──▶ exited

The Core Profile uses only the tiny first host/provider/check path in this state machine: initialize, the host’s initialized grant, workspace/readBlob, workspace/listTree, and check/evaluate behind host/evaluateChangeset. Inspect, edit, apply, deployment surfaces, dogfood, ACE integration, and reference-engine parity remain non-Core.

§The initialize handshake

Capability negotiation, permission capping, and SnapshotRef/Baseline issuance happen here. Note that the host narrows what the server requested.

// host → server
{ "jsonrpc":"2.0", "id":1, "method":"initialize", "params":{
  "protocolVersion":"asp/1.0",
  "host":{ "name":"covibes-host", "version":"0.1.0" },
  "hostCapabilities":{ "progress":true, "pullDiagnostics":true, "readBlob":true, "putBlob":true },
  "workspace":{ "root":"/repo",
    "baseline":{ "rev":"git:tree:9f3a1c", "dirty":"sha256:ab…", "stampedAt":"2026-06-16T10:00:00Z" } },
  "assuranceMode":"advisory" } }

// server → host
{ "jsonrpc":"2.0", "id":1, "result":{
  "serverInfo":{ "name":"acme-secrets", "version":"1.2.0", "fingerprint":"sha256:dd…" },
  "capabilityFamilies":["check"],
  "roles":["judge"], // legacy compatibility metadata
  "capabilities":{
    "check":{ "diagnosticSources":["acme-secrets"], "scopes":["changeset","workspace"],
              "comparisons":["introduced","all"], "fixes":true },
    "watch":{ "push":true } },
  "requestedPermissions":{ "read":["**/*"], "write":false, "network":true },
  "provenance":{ "publisher":"acme", "signature":"…" } } }

// host → server  (notification) — read narrowed, network denied
{ "jsonrpc":"2.0", "method":"initialized", "params":{
  "grantedPermissions":{ "read":["src/**","!**/.env*"], "write":false, "network":false,
                         "resourceLimits":{ "cpuPct":50, "memoryMb":512, "wallclockMs":30000, "fd":256 } },
  "baseline":{ "rev":"git:tree:9f3a1c", "dirty":"sha256:ab…", "stampedAt":"2026-06-16T10:00:00Z" } } }

Rules:

§Protocol utilities

MethodDirectionPurpose
$/progressserver → hostStream progress / partial results for long operations
$/cancelRequesthost → serverCancel an in-flight request by id
workspace/baselineChangedhost → serverAdvance the session baseline when the tree moves
shutdown / exithost → serverEnd the session

§Host callbacks (server → host requests)

These let a server pull or upload content-addressed blobs without filesystem access. The host scope-checks every one. They are not write intent; applying a proposal is owned by the harness-facing host/applyProposal surface after explicit user, agent, or harness authorization. Server-initiated applyEdit is historical and non-conforming; the write path is superseded by ADR 0024.

MethodPurpose
workspace/listTreeEnumerate baseline entries (path → blobId), scope-filtered
workspace/readBlobFetch blob bytes by content hash (batched)
workspace/putBlobUpload bytes for a proposal-introduced blob; host adds it to the referenced set (edit/legacy act)
window/logMessageDiagnostics / telemetry to the host

See data model for the content-addressed blob protocol and host obligations for how callbacks are policed.

§Errors

A failure-to-evaluate uses the JSON-RPC error object (schemas/error.schema.json). error.data.failClass (health | contract | policy | input) is authoritative — the host keys fail-policy off it. error.code is advisory. A deny or indeterminate host decision is never an error; it is a successful result carrying diagnostics and coverage evidence. A provider assessment with findings is also never an error; it is a successful result carrying diagnostics, status, and coverage.

ASP reserves the JSON-RPC server-error range -32099..-32000. Registry:

codenamefailClass
-32010health_not_readyhealth
-32011stale_baselinehealth (retryable)
-32012scope_deniedpolicy
-32013invalid_changesetinput
-32014unsupported_versioncontract
-32015blob_unavailablehealth
-32016cancelledhealth (retryable)

§Streaming and cancellation

A server that advertised partialResults MAY stream $/progress notifications (schemas/progress.schema.json) before the terminal result: each carries an incremental diagnostics batch (kind:"diagnostics"), a report, or an end marker. The final result on the original request id is authoritative and supersedes the streamed partials for both the JSON-RPC stdio floor and any future binding adapter. Progress is advisory; it cannot allow a gate or apply a proposal. On $/cancelRequest, the server SHOULD stop and return an error with failClass:"health", retryable:true, code -32016; the host still reports the terminal cancelled/degraded coverage state for gate call-sites.