Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Command / RPC Message Plane

Editor and runtime integrations need to issue commandsRun Agent Doc, sync, focus, save, session operations — with a single reusable admission, dedupe, cancellation, generation-guard, progress, and reconnect story. Without one, every caller reinvents in-flight/dedupe/supersede/retry/timeout logic, and accepted / queued feedback gets mistaken for terminal success.

lazily’s command plane (command-plane-v1) is that shared substrate. It is an additive sibling to Snapshot / Delta / CrdtSync, not a replacement: command frames can ride the same transports and reflect into the normal state graph, but they carry command traffic, not cell state.

The four frames

FrameRole
CommandSubmitSubmit a command: envelope + domain payload (an IpcValue)
CommandCancelPreempt a still-non-terminal command by command_id
CommandEventsProgress/detail events (UX + diagnostics only, never proof)
CommandProjectionFolded, queryable command state; also the reconnect resync image

lazily owns the envelope; the namespace owns the payload. lazily never decodes payload. Agent-doc publishes its own payload schemas (agent-doc.editor_route.v1, agent-doc.sync_tmux_layout.v1, …) and only references lazily’s envelope.

Progress is not proof

The single hard rule: terminal authority is the causal receipt. A command is terminal only when a terminal CausalReceipt for its command_id folds in (applied, or rejected — including the cancelled / superseded / timed_out reasons). observed / accepted / started / queued-admission events are non-terminal progress. A transport ACK is never terminal.

This keeps command events from becoming a second proof system. Events may carry queue position, retry advice, or copied CLI output; the effect still folds through receipts and domain facts.

RPC is a facade

call / submit / cancel / observe / projection are implemented entirely over the four frames:

await client.call("agent-doc.editor_route", payload, {
  commandId,
  idempotencyKey: "project-root:plan.md:run",
  authorityGeneration: 42,
  deadlineMs: 120000,
  policy: { dedupe: "same_idempotency_key", supersede: false, cancelOnPreempt: true }
});

call resolves only on a terminal causal-receipt projection. A network ACK, controller admission, or accepted / queued event never resolves a unary call. submit returns the command_id for callers that manage events and projection themselves. Reconnect uses CommandProjection; a call replays only when the idempotency policy says replay is safe.

Rules

  • Generation guards — events/receipts outside the command’s current authority generation are ignored (kept only as audit data).
  • Idempotency — replaying a submit/event/receipt with a known id is a no-op.
  • Cancel before terminal only — a cancel after applied is ignored.
  • Terminal conflict fails closedapplied vs rejected at the same generation is not resolved by winner selection.
  • Reconnect equivalence — folding a CommandProjection equals folding the events and receipts it summarizes.

The normative field list and rules live in protocol.md § Command / RPC Message Plane. The schema is schemas/message-passing.json. Conformance fixtures live in conformance/message-passing/; each binding replays them through its CommandProjection reducer and RPC facade.

{
  "protocol_version": 1,
  "kind": "Command",
  "model": "CommandProjection",
  "description": "observed/accepted events are progress only; the command becomes terminal ONLY when the applied CausalReceipt folds in.",
  "frames": [
    {
      "schema": "message-passing",
      "wire": {
        "CommandSubmit": {
          "command_id": "cmd-run-1",
          "causation_id": "cmd-run-1",
          "source": "vscode-plugin",
          "target": "project-controller",
          "namespace": "agent-doc",
          "name": "editor_route",
          "authority_generation": 42,
          "idempotency_key": "project-root:plan.md:run",
          "deadline_ms": 120000,
          "policy": {
            "dedupe": "same_idempotency_key",
            "supersede": false,
            "cancel_on_preempt": true
          },
          "payload_type": "agent-doc.editor_route.v1",
          "payload_hash": "sha256:f753816ec570dcaa98e80dafcf975b020a5ccc9db551c69e121567a48ee16346",
          "payload": {
            "Inline": [
              123,
              34,
              102,
              105,
              108,
              101,
              34,
              58,
              34,
              47,
              104,
              111,
              109,
              101,
              47,
              117,
              115,
              101,
              114,
              47,
              112,
              114,
              111,
              106,
              101,
              99,
              116,
              47,
              112,
              108,
              97,
              110,
              46,
              109,
              100,
              34,
              44,
              34,
              114,
              101,
              108,
              97,
              116,
              105,
              118,
              101,
              95,
              112,
              97,
              116,
              104,
              34,
              58,
              34,
              112,
              108,
              97,
              110,
              46,
              109,
              100,
              34,
              44,
              34,
              100,
              105,
              115,
              112,
              97,
              116,
              99,
              104,
              95,
              111,
              110,
              108,
              121,
              34,
              58,
              102,
              97,
              108,
              115,
              101,
              44,
              34,
              112,
              108,
              97,
              105,
              110,
              95,
              116,
              114,
              105,
              103,
              103,
              101,
              114,
              34,
              58,
              102,
              97,
              108,
              115,
              101,
              44,
              34,
              119,
              97,
              105,
              116,
              95,
              98,
              117,
              100,
              103,
              101,
              116,
              95,
              109,
              115,
              34,
              58,
              49,
              50,
              48,
              48,
              48,
              48,
              44,
              34,
              108,
              97,
              121,
              111,
              117,
              116,
              95,
              97,
              114,
              103,
              115,
              34,
              58,
              123,
              34,
              99,
              111,
              108,
              117,
              109,
              110,
              115,
              34,
              58,
              50,
              44,
              34,
              102,
              111,
              99,
              117,
              115,
              34,
              58,
              116,
              114,
              117,
              101,
              125,
              44,
              34,
              114,
              111,
              117,
              116,
              101,
              95,
              107,
              101,
              121,
              34,
              58,
              34,
              112,
              114,
              111,
              106,
              101,
              99,
              116,
              45,
              114,
              111,
              111,
              116,
              58,
              112,
              108,
              97,
              110,
              46,
              109,
              100,
              58,
              114,
              117,
              110,
              34,
              44,
              34,
              101,
              100,
              105,
              116,
              111,
              114,
              95,
              97,
              116,
              116,
              101,
              109,
              112,
              116,
              95,
              105,
              100,
              34,
              58,
              34,
              97,
              116,
              116,
              101,
              109,
              112,
              116,
              45,
              55,
              34,
              125
            ]
          },
          "required_features": [
            "causal-receipts",
            "command-events"
          ]
        }
      }
    },
    {
      "schema": "message-passing",
      "wire": {
        "CommandEvents": {
          "events": [
            {
              "event_id": "ev-1",
              "command_id": "cmd-run-1",
              "kind": "observed",
              "generation": 42,
              "detail": null
            },
            {
              "event_id": "ev-2",
              "command_id": "cmd-run-1",
              "kind": "accepted",
              "generation": 42,
              "detail": "queued at position 1"
            },
            {
              "event_id": "ev-3",
              "command_id": "cmd-run-1",
              "kind": "started",
              "generation": 42,
              "detail": null
            }
          ]
        }
      }
    },
    {
      "schema": "receipts",
      "wire": {
        "CausalReceipts": {
          "receipts": [
            {
              "receipt_id": "rcpt-1",
              "causation_id": "cmd-run-1",
              "observer": "project-controller",
              "generation": 42,
              "outcome": "applied",
              "reason": null,
              "payload_hash": "sha256:f753816ec570dcaa98e80dafcf975b020a5ccc9db551c69e121567a48ee16346"
            }
          ]
        }
      }
    }
  ],
  "expect": {
    "projection": {
      "generation": 42,
      "commands": [
        {
          "command_id": "cmd-run-1",
          "status": "applied",
          "terminal": true,
          "generation": 42,
          "reason": null,
          "terminal_receipt_id": "rcpt-1",
          "last_event_id": "ev-3"
        }
      ]
    },
    "terminal_after_frame_index": 2
  }
}