Skip to content
Cockpit0.29.0
A snapshot: read at commit 707a04c7ce8 on 2026-10-18T00:06:01Z by majordomus 0.29.0. Nothing on this page is read again. See it live

mesh.peers

Who cooperates, machine by machine

What it is

Machine → runtime → session → claim: every runtime this one is linked to or has heard through the journal, grouped by machine, local first; each runtime with its liveness, the milliseconds since its beat rose, its link and its newest live claim. The default `summary` view lists only the active sessions, each with its live claims counted and its intent cut; `view=full` lists every session with every claim. `session` and `runtime` narrow either. Remote and local runtimes share one shape, and the whole fold's digest closes the answer: equal digests, equal state.

Descriptor

Canonical id
mesh.peers
Module
mesh
Kind
query
Stability
experimental
Provenance
declared
Source
apps/majordomus-cli/src/capability/builtin/mesh.rs
Cache
disabled
Benchmark
required
Tags
meshcoordinationcooperation

Run

query
A query. It reads and changes nothing.

`summary` (the default) or `full`.

`all` (the default) or `live`: whether ended claims are kept.

Only sessions, claims and handovers whose latest Lamport stamp is above this. Reviews and overlaps carry no stamp of their own and are kept or dropped with their sessions.

Only what belongs to this session: its key (`<stream>/<session>`) or its bare id.

Only what belongs to this runtime: `<node>-<runtime>`, or a node id for every runtime of that machine.

Only this collection; the others are answered empty.

At most this many of each collection: the newest by Lamport stamp where it has one, kept in the fold's own order.

Only what is still open: active sessions, live claims, review requests nobody has answered and handovers nobody has taken.

Only what mentions this text, ignoring case: a path, a branch, an issue, a pull request, a word of an intent or a subject.

GET /api/v1/mesh/peers

Projections

InterfaceAsWhere
MCP toolmajordomus_mesh_peers-
MCP resourcenot exposed-
HTTPGET /api/v1/mesh/peersSwagger
Command linenot exposed-

Schemas

Input · MeshQuery
{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "view": {
      "anyOf": [
        {
          "$ref": "#/$defs/MeshView"
        },
        {
          "type": "null"
        }
      ],
      "description": "`summary` (the default) or `full`."
    },
    "claims": {
      "anyOf": [
        {
          "$ref": "#/$defs/MeshClaimFilter"
        },
        {
          "type": "null"
        }
      ],
      "description": "`all` (the default) or `live`: whether ended claims are kept."
    },
    "after": {
      "type": [
        "integer",
        "null"
      ],
      "format": "uint64",
      "minimum": 0,
      "description": "Only sessions, claims and handovers whose latest Lamport stamp is above this. Reviews\nand overlaps carry no stamp of their own and are kept or dropped with their sessions."
    },
    "session": {
      "type": [
        "string",
        "null"
      ],
      "description": "Only what belongs to this session: its key (`<stream>/<session>`) or its bare id."
    },
    "runtime": {
      "type": [
        "string",
        "null"
      ],
      "description": "Only what belongs to this runtime: `<node>-<runtime>`, or a node id for every runtime\nof that machine."
    },
    "kind": {
      "anyOf": [
        {
          "$ref": "#/$defs/MeshKind"
        },
        {
          "type": "null"
        }
      ],
      "description": "Only this collection; the others are answered empty."
    },
    "limit": {
      "type": [
        "integer",
        "null"
      ],
      "format": "uint",
      "minimum": 0,
      "description": "At most this many of each collection: the newest by Lamport stamp where it has one,\nkept in the fold's own order."
    },
    "open": {
      "type": [
        "boolean",
        "null"
      ],
      "description": "Only what is still open: active sessions, live claims, review requests nobody has\nanswered and handovers nobody has taken."
    },
    "matching": {
      "type": [
        "string",
        "null"
      ],
      "description": "Only what mentions this text, ignoring case: a path, a branch, an issue, a pull\nrequest, a word of an intent or a subject."
    }
  },
  "description": "What a reader asks of the folded state. Every filter narrows; none changes a shape, and\nan input it does not know is refused rather than ignored.\n\n```\nuse majordomus_cli::mesh::page::{ClaimFilter, Query, View};\n\nlet q: Query = serde_json::from_str(r#\"{\"view\":\"full\",\"claims\":\"live\",\"limit\":5}\"#).unwrap();\nassert_eq!(q.view(), View::Full);\nassert_eq!((q.claims, q.limit), (Some(ClaimFilter::Live), Some(5)));\nassert!(serde_json::from_str::<Query>(r#\"{\"views\":\"full\"}\"#).is_err());\n```",
  "title": "MeshQuery",
  "$defs": {
    "MeshView": {
      "oneOf": [
        {
          "type": "string",
          "const": "summary",
          "description": "Counts, each runtime's newest live claim, the open reviews and the untaken handovers:\nbounded, whatever the history."
        },
        {
          "type": "string",
          "const": "full",
          "description": "Everything, narrowed only by the filters."
        }
      ],
      "description": "How much an answer about the mesh carries. The summary is the default because it is the\nanswer a worker can read whole whatever the mesh's history; the full fold is one word\naway when a reader needs every record.\n\n```\nuse majordomus_cli::mesh::page::View;\n\nassert_eq!(View::default(), View::Summary);\nassert_eq!(serde_json::to_value(View::Full).unwrap(), \"full\");\n```"
    },
    "MeshClaimFilter": {
      "oneOf": [
        {
          "type": "string",
          "const": "all",
          "description": "Every claim, ended ones included."
        },
        {
          "type": "string",
          "const": "live",
          "description": "Only claims that are still live: held, or conflicted and still held."
        }
      ],
      "description": "Which claims a full answer keeps: all of them, the ended ones included, or only those\nstill live — the question an executor asks before it takes a lease.\n\n```\nuse majordomus_cli::mesh::page::ClaimFilter;\n\nassert_eq!(ClaimFilter::default(), ClaimFilter::All);\nassert_eq!(serde_json::from_str::<ClaimFilter>(r#\"\"live\"\"#).unwrap(), ClaimFilter::Live);\n```"
    },
    "MeshKind": {
      "oneOf": [
        {
          "type": "string",
          "const": "sessions",
          "description": "The sessions."
        },
        {
          "type": "string",
          "const": "claims",
          "description": "The claims."
        },
        {
          "type": "string",
          "const": "overlaps",
          "description": "The advisory overlaps."
        },
        {
          "type": "string",
          "const": "handovers",
          "description": "The handovers."
        },
        {
          "type": "string",
          "const": "reviews",
          "description": "The review requests."
        }
      ],
      "description": "One collection of the folded state, as `kind` names it: a reader that wants only the\nreviews is not sent the claims.\n\n```\nuse majordomus_cli::mesh::page::Kind;\n\nassert_eq!(serde_json::from_str::<Kind>(r#\"\"reviews\"\"#).unwrap(), Kind::Reviews);\nassert!(serde_json::from_str::<Kind>(r#\"\"everything\"\"#).is_err());\n```"
    }
  }
}
Output · PeerTree
{
  "type": "object",
  "properties": {
    "active": {
      "type": "boolean",
      "description": "Whether cooperation runs."
    },
    "view": {
      "$ref": "#/$defs/MeshView",
      "description": "What the answer carries: `summary` or `full`."
    },
    "reason": {
      "type": [
        "string",
        "null"
      ],
      "description": "Why not."
    },
    "runtime": {
      "type": [
        "string",
        "null"
      ],
      "description": "This runtime."
    },
    "repository": {
      "type": [
        "string",
        "null"
      ],
      "description": "The mesh repository id."
    },
    "machines": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/MachineNode"
      },
      "description": "The machines, local first."
    },
    "refused": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/RefusedView"
      },
      "description": "Candidates refused, with the rule."
    },
    "digest": {
      "type": [
        "string",
        "null"
      ],
      "description": "The digest of the cooperation state: equal digests, equal state."
    }
  },
  "required": [
    "active",
    "view",
    "machines",
    "refused"
  ],
  "description": "The answer of `mesh.peers`: machine → runtime → session → claim, every level from the\none journal and the one link table.",
  "title": "PeerTree",
  "$defs": {
    "MeshView": {
      "oneOf": [
        {
          "type": "string",
          "const": "summary",
          "description": "Counts, each runtime's newest live claim, the open reviews and the untaken handovers:\nbounded, whatever the history."
        },
        {
          "type": "string",
          "const": "full",
          "description": "Everything, narrowed only by the filters."
        }
      ],
      "description": "How much an answer about the mesh carries. The summary is the default because it is the\nanswer a worker can read whole whatever the mesh's history; the full fold is one word\naway when a reader needs every record.\n\n```\nuse majordomus_cli::mesh::page::View;\n\nassert_eq!(View::default(), View::Summary);\nassert_eq!(serde_json::to_value(View::Full).unwrap(), \"full\");\n```"
    },
    "MachineNode": {
      "type": "object",
      "properties": {
        "node": {
          "type": "string",
          "description": "The node id."
        },
        "name": {
          "type": "string",
          "description": "Its display name, when a card or this node said."
        },
        "local": {
          "type": "boolean",
          "description": "Whether it is this machine."
        },
        "runtimes": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/RuntimeNode"
          },
          "description": "Its runtimes."
        }
      },
      "required": [
        "node",
        "name",
        "local",
        "runtimes"
      ],
      "description": "One machine in the peer tree."
    },
    "RuntimeNode": {
      "type": "object",
      "properties": {
        "runtime": {
          "type": "string",
          "description": "`<node>-<runtime>`."
        },
        "this_runtime": {
          "type": "boolean",
          "description": "Whether this is the runtime answering."
        },
        "liveness": {
          "$ref": "#/$defs/StreamLiveness",
          "description": "Whether its stream beats: own, live, or expired."
        },
        "last_beat_ms": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "description": "Milliseconds since its beat last rose, on this runtime's clock."
        },
        "link": {
          "anyOf": [
            {
              "$ref": "#/$defs/PeerView"
            },
            {
              "type": "null"
            }
          ],
          "description": "This runtime's link to it, when there is one."
        },
        "newest_claim": {
          "anyOf": [
            {
              "$ref": "#/$defs/MeshClaimBrief"
            },
            {
              "type": "null"
            }
          ],
          "description": "Its newest live claim, told briefly."
        },
        "sessions": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/SessionNode"
          },
          "description": "Its sessions; in the summary view only the active ones."
        }
      },
      "required": [
        "runtime",
        "this_runtime",
        "liveness",
        "sessions"
      ],
      "description": "One runtime in the peer tree."
    },
    "StreamLiveness": {
      "oneOf": [
        {
          "type": "string",
          "const": "own",
          "description": "This runtime's own current stream."
        },
        {
          "type": "string",
          "const": "live",
          "description": "Its beat rose within the expiry."
        },
        {
          "type": "string",
          "const": "expired",
          "description": "Its beat has not risen within the expiry, or was never heard."
        }
      ],
      "description": "Whether a stream is speaking now, on this runtime's clock. It is a verdict about a\nstream and not about a link: a runtime reachable only through a relay is alive, and a\nruntime that crashed stops beating for everyone at once. `Own` is kept apart from `Live`\nbecause a runtime's own stream needs no evidence — it is the thing doing the beating.\n\n```\nuse majordomus_cli::mesh::journal::StreamLiveness;\n\nassert!(StreamLiveness::Own.is_alive() && StreamLiveness::Live.is_alive());\nassert!(!StreamLiveness::Expired.is_alive());\nassert_eq!(\n    serde_json::to_value(StreamLiveness::Expired).unwrap(),\n    serde_json::json!(\"expired\"),\n);\n```"
    },
    "PeerView": {
      "type": "object",
      "properties": {
        "runtime": {
          "type": "string",
          "description": "`<node>-<runtime>`: the peer's durable identity."
        },
        "node": {
          "type": "string",
          "description": "The node (machine key digest)."
        },
        "instance": {
          "type": "string",
          "description": "The current instance."
        },
        "name": {
          "type": "string",
          "description": "The node's display name."
        },
        "version": {
          "type": "string",
          "description": "The executable version."
        },
        "local": {
          "type": "boolean",
          "description": "Whether the peer runs on this machine (the same node key)."
        },
        "trust": {
          "$ref": "#/$defs/TrustState",
          "description": "The trust verdict the link was admitted under."
        },
        "protocol": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "description": "The negotiated link protocol."
        },
        "features": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "The link features the peer carries."
        },
        "endpoints": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Where the peer answers."
        },
        "state": {
          "$ref": "#/$defs/LinkState",
          "description": "The link's standing."
        },
        "outbound": {
          "type": "boolean",
          "description": "Whether this runtime dials the peer."
        },
        "inbound": {
          "type": "boolean",
          "description": "Whether the peer dials this runtime."
        },
        "endpoint": {
          "type": [
            "string",
            "null"
          ],
          "description": "The endpoint this runtime dials, when it does."
        },
        "last_exchange_ms": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "description": "Milliseconds since the last successful exchange in either direction."
        },
        "rtt_ms": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "description": "The last round trip, milliseconds."
        },
        "failures": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "description": "Consecutive failed rounds."
        },
        "last_error": {
          "type": [
            "string",
            "null"
          ],
          "description": "The last failure, in words."
        },
        "handshakes": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "description": "Handshakes completed with this peer."
        },
        "reconnects": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "description": "Handshakes after an expiry or a dropped link."
        },
        "restarts": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "description": "New instances of the peer seen (its process restarted)."
        },
        "linked_at": {
          "type": "string",
          "description": "When the current link was established, RFC 3339."
        }
      },
      "required": [
        "runtime",
        "node",
        "instance",
        "name",
        "version",
        "local",
        "trust",
        "protocol",
        "features",
        "endpoints",
        "state",
        "outbound",
        "inbound",
        "failures",
        "handshakes",
        "reconnects",
        "restarts",
        "linked_at"
      ],
      "description": "One peer as every surface shows it: who it is, how this runtime reaches it, and what\nthe link has been through. The counters are carried per peer rather than only in the\ntotals because the question a person asks of a flapping mesh is which peer is flapping,\nand `restarts` answers a different one from `reconnects` — a peer whose process keeps\ndying, against a link that keeps dropping under a process that never did.\n\n```\n# use std::collections::BTreeMap;\n# use std::sync::{Arc, Mutex, Weak};\n# use majordomus_cli::mesh::config::{CooperationConfig, TrustConfig};\n# use majordomus_cli::mesh::cooperation::*;\n# use majordomus_cli::mesh::identity::NodeIdentity;\n# use majordomus_cli::mesh::link::{LinkReply, LinkTransport, Signed, HELLO_PATH};\n# use majordomus_cli::mesh::registry::MeshRegistry;\n# use majordomus_cli::mesh::repository::{of_root_commits, runtime_id};\n# use majordomus_cli::mesh::trust::TrustPolicy;\n# #[derive(Default)] struct Net(Mutex<BTreeMap<String, Weak<Cooperation>>>);\n# impl LinkTransport for Net {\n#   fn post(&self, e: &str, p: &str, m: &Signed) -> Result<LinkReply, String> {\n#     let peer = (self.0.lock().unwrap().get(e).and_then(Weak::upgrade))\n#         .ok_or_else(|| format!(\"{e}: nobody there\"))?;\n#     Ok(if p == HELLO_PATH { peer.accept_hello(m) } else { peer.accept_sync(m) }) } }\n# let net = Arc::new(Net::default());\n# let runtime = |endpoint: &str| { let c = Cooperation::new(CooperationSetup {\n#     identity: Arc::new(NodeIdentity::ephemeral().unwrap()), runtime: runtime_id(endpoint),\n#     repository: of_root_commits(&[\"root\".into()]), endpoints: vec![endpoint.into()],\n#     version: \"doc\".into(), config: CooperationConfig::default(),\n#     trust: TrustConfig { policy: TrustPolicy::Tofu, allow: vec![] }, journal_path: None,\n#     registry: Arc::new(MeshRegistry::new()),\n#     transport: Arc::clone(&net) as Arc<dyn LinkTransport>, board: None,\n#     checkout: CheckoutFacts::default() }).unwrap();\n#   net.0.lock().unwrap().insert(endpoint.into(), Arc::downgrade(&c)); c };\n# let (a, b) = (runtime(\"a:1\"), runtime(\"b:1\"));\na.dial(&[\"b:1\".into()]).unwrap();\n\nlet peer: &PeerView = &a.peers()[0];\nassert_eq!(peer.runtime, b.runtime_key(), \"the durable identity, not the endpoint\");\nassert!(peer.outbound, \"this runtime dials it\");\nassert_eq!(peer.handshakes, 1);\nassert_eq!(peer.restarts, 0, \"the peer's process has not died under the link\");\n```"
    },
    "TrustState": {
      "oneOf": [
        {
          "type": "object",
          "properties": {
            "state": {
              "type": "string",
              "const": "observed"
            }
          },
          "required": [
            "state"
          ],
          "description": "Valid, recorded, trusted for nothing. The resting state of an unknown node."
        },
        {
          "type": "object",
          "properties": {
            "state": {
              "type": "string",
              "const": "trusted"
            },
            "detail": {
              "type": "string"
            }
          },
          "required": [
            "state",
            "detail"
          ],
          "description": "The policy trusts this key; `detail` says which rule did (`allowlist`, `tofu`)."
        },
        {
          "type": "object",
          "properties": {
            "state": {
              "type": "string",
              "const": "rejected"
            },
            "detail": {
              "type": "string"
            }
          },
          "required": [
            "state",
            "detail"
          ],
          "description": "The policy rejected this node; `detail` says why (for instance a TOFU key\nchange). A rejected node stays listed — an operator debugging a mesh needs to\nsee what was refused, not wonder about silence."
        }
      ],
      "description": "What the policy decided about one node."
    },
    "LinkState": {
      "oneOf": [
        {
          "type": "string",
          "const": "connecting",
          "description": "Handshaking, or never yet exchanged."
        },
        {
          "type": "string",
          "const": "connected",
          "description": "An exchange within two heartbeats."
        },
        {
          "type": "string",
          "const": "degraded",
          "description": "Rounds are failing; the last exchange is under half the expiry old."
        },
        {
          "type": "string",
          "const": "unreachable",
          "description": "The last exchange is over half the expiry old; the link is about to expire."
        },
        {
          "type": "string",
          "const": "expired",
          "description": "No exchange within the expiry: the link is dropped and will be re-dialed."
        }
      ],
      "description": "A link's standing, from this runtime's side. It is a statement about a connection and\nnever about the peer: a runtime reachable only through a third party is `Expired` here\nwhile its streams beat on everywhere, which is why claims follow streams and not this.\n\nThe variants are ordered by how far the link has fallen, so the worst link in a table\nis the maximum and a reader never has to rank them by hand.\n\n```\nuse majordomus_cli::mesh::cooperation::LinkState;\n\nlet table = [LinkState::Connected, LinkState::Unreachable, LinkState::Degraded];\nassert_eq!(table.iter().max(), Some(&LinkState::Unreachable), \"the worst link shows\");\nassert_eq!(serde_json::to_value(LinkState::Connected).unwrap(), \"connected\");\n```"
    },
    "MeshClaimBrief": {
      "type": "object",
      "properties": {
        "key": {
          "type": "string",
          "description": "`<stream>/<claim>`."
        },
        "session": {
          "type": "string",
          "description": "The holding session's key."
        },
        "issue": {
          "type": [
            "string",
            "null"
          ],
          "description": "The issue it is for."
        },
        "intent": {
          "type": [
            "string",
            "null"
          ],
          "description": "What it is for, cut to `SUMMARY_TEXT` characters."
        },
        "paths": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "description": "How many paths it claims."
        },
        "mode": {
          "$ref": "#/$defs/ClaimMode",
          "description": "Exclusive or advisory."
        },
        "acquired_lamport": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "description": "The Lamport stamp of the acquisition."
        }
      },
      "required": [
        "key",
        "session",
        "paths",
        "mode",
        "acquired_lamport"
      ],
      "description": "One live claim, told briefly: whose it is, what it is for and how many paths it holds,\nwith its intent cut to `SUMMARY_TEXT` characters — enough to know whom to ask.\n\n```\nuse std::sync::Arc;\nuse majordomus_cli::mesh::identity::NodeIdentity;\nuse majordomus_cli::mesh::journal::{ClaimMode, EventBody, Journal, SessionInfo, StreamLiveness};\nuse majordomus_cli::mesh::state::fold;\n\nlet j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), \"0000000000000001\",\n    \"repo\".into(), None).unwrap();\nj.append_own(EventBody::SessionOpened { info: SessionInfo::named(\"s1\", \"claude-code\") })\n    .unwrap();\nfor (claim, path) in [(\"c1\", \"apps/a\"), (\"c2\", \"apps/b\")] {\n    j.append_own(EventBody::ClaimAcquired { claim: claim.into(), session: \"s1\".into(),\n        scope: vec![path.into()], intent: Some(\"work\".into()), mode: ClaimMode::Exclusive,\n        issue: Some(\"#1\".into()) }).unwrap();\n}\nj.append_own(EventBody::ClaimReleased { claim: \"c1\".into() }).unwrap();\nlet state = fold(&j.events(), &|_| StreamLiveness::Own);\nuse majordomus_cli::mesh::page::{summarize, ClaimBrief};\n\nlet summary = summarize(&state, &[]);\nlet newest: &ClaimBrief = summary.runtimes[0].newest_claim.as_ref().unwrap();\nassert_eq!((newest.issue.as_deref(), newest.paths), (Some(\"#1\"), 1));\n```"
    },
    "ClaimMode": {
      "oneOf": [
        {
          "type": "string",
          "const": "exclusive",
          "description": "Exclusive: a second exclusive claim meeting this scope is refused while this one\nlives, on every runtime that knows of it."
        },
        {
          "type": "string",
          "const": "advisory",
          "description": "Advisory: an announcement, like the peer board's. Overlaps are reported, never\nrefused."
        }
      ],
      "description": "Whether a claim excludes others or only tells them. Both are useful and they answer\ndifferent questions: an exclusive claim is a worker saying \"do not edit this while I\nam\", an advisory one is saying \"I am here\". Exclusive is the default because a claim\ntaken without a thought about the mode is a claim somebody expects to be respected.\n\n```\nuse majordomus_cli::mesh::journal::ClaimMode;\n\nassert_eq!(ClaimMode::default(), ClaimMode::Exclusive);\nassert_eq!(serde_json::to_value(ClaimMode::Advisory).unwrap(), serde_json::json!(\"advisory\"));\n```"
    },
    "SessionNode": {
      "type": "object",
      "properties": {
        "key": {
          "type": "string",
          "description": "`<stream>/<session>`."
        },
        "info": {
          "$ref": "#/$defs/SessionInfo",
          "description": "What the session last said about itself."
        },
        "state": {
          "$ref": "#/$defs/SessionState",
          "description": "Its standing."
        },
        "claims": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ClaimView"
          },
          "description": "The claims it holds or held; empty in the summary view, which counts them instead."
        },
        "claims_held": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "description": "How many of its claims are live."
        },
        "reviews": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "The review requests it opened, by key."
        }
      },
      "required": [
        "key",
        "info",
        "state",
        "claims",
        "claims_held",
        "reviews"
      ],
      "description": "One session in the peer tree."
    },
    "SessionInfo": {
      "type": "object",
      "properties": {
        "session": {
          "type": "string",
          "description": "The session's id within its stream."
        },
        "client": {
          "type": "string",
          "description": "The client: `claude-code`, `codex`, `cli`, ..."
        },
        "worker": {
          "type": [
            "string",
            "null"
          ],
          "description": "The worker's own name for itself, when it gave one."
        },
        "intent": {
          "type": [
            "string",
            "null"
          ],
          "description": "What the session says it is doing."
        },
        "task": {
          "type": [
            "string",
            "null"
          ],
          "description": "The task id (`t-...`) the session works under."
        },
        "issue": {
          "type": [
            "string",
            "null"
          ],
          "description": "The issue (`I0001`, `#184`) the work belongs to."
        },
        "milestone": {
          "type": [
            "string",
            "null"
          ],
          "description": "The milestone the work belongs to."
        },
        "checkout": {
          "type": [
            "string",
            "null"
          ],
          "description": "The checkout id (a digest, never a path)."
        },
        "branch": {
          "type": [
            "string",
            "null"
          ],
          "description": "The branch checked out."
        },
        "head": {
          "type": [
            "string",
            "null"
          ],
          "description": "The commit checked out."
        },
        "dirty": {
          "type": [
            "boolean",
            "null"
          ],
          "description": "Whether the working tree had uncommitted changes when this was said."
        },
        "context": {
          "type": [
            "string",
            "null"
          ],
          "description": "The context revision the session works from (a digest the context compiler names)."
        }
      },
      "required": [
        "session",
        "client"
      ],
      "description": "What a session tells the mesh about itself. Every field is a public fact about work in\nprogress; none is a path on the author's disk, a secret or a credential.\n\nAlmost everything here is optional, and that is the design: a session says what it\nknows, and a field it leaves out is omitted rather than carried empty, so a reader can\ntell \"no task\" from \"a task called nothing\". Opening the same session id again replaces\nthis record, which is how a session that learns its branch later tells the mesh.\n\n```\nuse majordomus_cli::mesh::journal::SessionInfo;\n\nlet mut info = SessionInfo::named(\"s1\", \"claude-code\");\nassert_eq!(info.task, None);\nassert!(serde_json::to_value(&info).unwrap().get(\"task\").is_none(), \"unsaid, not empty\");\n\ninfo.branch = Some(\"feature/mesh-cooperation\".into());\nassert_eq!(serde_json::to_value(&info).unwrap()[\"branch\"], \"feature/mesh-cooperation\");\n```"
    },
    "SessionState": {
      "oneOf": [
        {
          "type": "string",
          "const": "active",
          "description": "Open, and its runtime is alive."
        },
        {
          "type": "string",
          "const": "closed",
          "description": "Closed by its own runtime."
        },
        {
          "type": "string",
          "const": "expired",
          "description": "Never closed, but its runtime stopped beating: gone, as far as anyone can tell."
        }
      ],
      "description": "A session's standing, as every runtime of the mesh reads it. The distinction that\nmatters is between `Closed` and `Expired`: the first is a session that said it was\nfinished, the second one whose runtime stopped beating and can no longer say anything.\nBoth end the session's claims, but only the second is a machine nobody should expect an\nanswer from.\n\n```\nuse std::sync::Arc;\nuse majordomus_cli::mesh::identity::NodeIdentity;\nuse majordomus_cli::mesh::journal::{EventBody, Journal, SessionInfo, StreamLiveness};\nuse majordomus_cli::mesh::state::{fold, SessionState};\n\nlet j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), \"0000000000000001\",\n    \"repo\".into(), None).unwrap();\nj.append_own(EventBody::SessionOpened { info: SessionInfo::named(\"s1\", \"cli\") }).unwrap();\nassert_eq!(fold(&j.events(), &|_| StreamLiveness::Own).sessions[0].state, SessionState::Active);\n\n// the same events, read on a runtime that no longer hears the writer\nlet gone = fold(&j.events(), &|_| StreamLiveness::Expired);\nassert_eq!(gone.sessions[0].state, SessionState::Expired);\n```"
    },
    "ClaimView": {
      "type": "object",
      "properties": {
        "key": {
          "type": "string",
          "description": "`<stream>/<claim>`."
        },
        "stream": {
          "$ref": "#/$defs/StreamId",
          "description": "The writing stream."
        },
        "runtime": {
          "type": "string",
          "description": "`<node>-<runtime>`."
        },
        "session": {
          "type": "string",
          "description": "The holding session's key."
        },
        "scope": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "The claimed paths."
        },
        "intent": {
          "type": [
            "string",
            "null"
          ],
          "description": "What it is for."
        },
        "mode": {
          "$ref": "#/$defs/ClaimMode",
          "description": "Exclusive or advisory."
        },
        "issue": {
          "type": [
            "string",
            "null"
          ],
          "description": "The issue it is for."
        },
        "acquired_lamport": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "description": "The Lamport stamp of the acquisition."
        },
        "acquired_seq": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "description": "The sequence of the acquisition within its stream: with the stamp and the stream,\nthe total order in which exclusivity is decided."
        },
        "state": {
          "$ref": "#/$defs/ClaimState",
          "description": "Its standing."
        }
      },
      "required": [
        "key",
        "stream",
        "runtime",
        "session",
        "scope",
        "mode",
        "acquired_lamport",
        "acquired_seq",
        "state"
      ],
      "description": "One claim anywhere in the mesh: who took what, for what, and where it stands. The\nacquisition's Lamport stamp and sequence are carried rather than derived on demand,\nbecause they are what exclusivity is decided by — every runtime ranks two competing\nclaims by the same triple and so names the same winner, with no message passing and no\n\"last packet wins\".\n\n```\nuse std::sync::Arc;\nuse majordomus_cli::mesh::identity::NodeIdentity;\nuse majordomus_cli::mesh::journal::{ClaimMode, EventBody, Journal, StreamLiveness};\nuse majordomus_cli::mesh::state::{fold, ClaimState, ClaimView};\n\nlet j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), \"0000000000000001\",\n    \"repo\".into(), None).unwrap();\nj.append_own(EventBody::ClaimAcquired { claim: \"c1\".into(), session: \"s1\".into(),\n    scope: vec![\"apps/majordomus-cli\".into()], intent: Some(\"document the mesh\".into()),\n    mode: ClaimMode::Exclusive, issue: Some(\"#184\".into()) }).unwrap();\n\nlet state = fold(&j.events(), &|_| StreamLiveness::Own);\nlet claim: &ClaimView = &state.claims[0];\nassert_eq!(claim.scope, [\"apps/majordomus-cli\"]);\nassert_eq!(claim.state, ClaimState::Held);\nassert!(claim.acquired_lamport > 0, \"the order exclusivity is decided in\");\n```"
    },
    "StreamId": {
      "type": "string",
      "description": "One stream: a run of one runtime of one node. `<node 32 hex>-<runtime 16 hex>-<instance\n16 hex>`. The node is the machine's key, the runtime is one checkout's server on that\nmachine, the instance is one process run of that server — so two worktrees on one\nmachine are two streams, and a restart is a new stream of the same runtime.\n\nNumbering events within a stream rather than globally is what makes replication cheap\nand unambiguous: a gap in one stream is visible without coordinating with anyone, and\n`(stream, seq)` identifies an event on every machine that holds it.\n\n```\nuse majordomus_cli::mesh::journal::StreamId;\n\nlet id = StreamId::new(&\"a\".repeat(32), &\"b\".repeat(16), &\"c\".repeat(16)).unwrap();\nassert_eq!(id.node(), \"a\".repeat(32));\nassert_eq!(id.runtime(), \"b\".repeat(16));\n\n// a restart is a new stream, and the same runtime\nlet after = StreamId::new(&\"a\".repeat(32), &\"b\".repeat(16), &\"d\".repeat(16)).unwrap();\nassert_ne!(after, id);\nassert_eq!(after.runtime_key(), id.runtime_key());\n```"
    },
    "ClaimState": {
      "oneOf": [
        {
          "type": "object",
          "properties": {
            "state": {
              "type": "string",
              "const": "held"
            }
          },
          "required": [
            "state"
          ],
          "description": "Live; for an exclusive claim, the winner of its scope."
        },
        {
          "type": "object",
          "properties": {
            "state": {
              "type": "string",
              "const": "released"
            }
          },
          "required": [
            "state"
          ],
          "description": "Released by its holder."
        },
        {
          "type": "object",
          "properties": {
            "state": {
              "type": "string",
              "const": "expired"
            },
            "detail": {
              "type": "string"
            }
          },
          "required": [
            "state",
            "detail"
          ],
          "description": "Ended without a release: the holder's session closed or its runtime expired."
        },
        {
          "type": "object",
          "properties": {
            "state": {
              "type": "string",
              "const": "conflicted"
            },
            "detail": {
              "type": "string"
            }
          },
          "required": [
            "state",
            "detail"
          ],
          "description": "Live, exclusive, and beaten to its scope by the claim whose key this names."
        }
      ],
      "description": "A claim's standing, and — where it ended or lost — what ended it. The two variants that\ncarry a string exist because the bare verdict is not actionable: a worker told its claim\nexpired needs to know whether its session closed or its runtime stopped beating, and one\ntold its claim is conflicted needs the key of the claim that beat it, which is the same\nkey on every runtime.\n\n```\nuse majordomus_cli::mesh::state::ClaimState;\n\nassert!(ClaimState::Held.is_live());\nassert!(ClaimState::Conflicted(\"s/c1\".into()).is_live(), \"still held, and not the winner\");\nassert!(!ClaimState::Released.is_live());\n\n// the detail travels with the verdict, so a reader is never left asking who won\nlet value = serde_json::to_value(ClaimState::Conflicted(\"s/c1\".into())).unwrap();\nassert_eq!(value[\"state\"], \"conflicted\");\nassert_eq!(value[\"detail\"], \"s/c1\");\n```"
    },
    "RefusedView": {
      "type": "object",
      "properties": {
        "endpoint": {
          "type": "string",
          "description": "The endpoint dialed, or `inbound:<runtime>` for a refused hello."
        },
        "direction": {
          "type": "string",
          "description": "`outbound` (this runtime refused the peer's welcome, or the peer refused this\nhello) or `inbound` (this runtime refused the peer's hello)."
        },
        "runtime": {
          "type": [
            "string",
            "null"
          ],
          "description": "The peer's runtime key, when its card said."
        },
        "refusal": {
          "$ref": "#/$defs/LinkRefusal",
          "description": "The refusal."
        },
        "at": {
          "type": "string",
          "description": "When, RFC 3339."
        }
      },
      "required": [
        "endpoint",
        "direction",
        "refusal",
        "at"
      ],
      "description": "A candidate that was refused, with the rule that refused it. A refusal is kept and\nshown rather than logged and dropped, because the commonest mesh failure is a link that\nnever forms: a person who declared a seed and sees no peer needs the decision that was\nmade about it — the wrong repository, a key nobody allowed, a clock too far out — and\nthe direction says which side made it.\n\n```\n# use std::collections::BTreeMap;\n# use std::sync::{Arc, Mutex, Weak};\n# use majordomus_cli::mesh::config::{CooperationConfig, TrustConfig};\n# use majordomus_cli::mesh::cooperation::*;\n# use majordomus_cli::mesh::identity::NodeIdentity;\n# use majordomus_cli::mesh::link::{LinkReply, LinkTransport, RefusalCode, Signed, HELLO_PATH};\n# use majordomus_cli::mesh::registry::MeshRegistry;\n# use majordomus_cli::mesh::repository::{of_root_commits, runtime_id};\n# use majordomus_cli::mesh::trust::TrustPolicy;\n# #[derive(Default)] struct Net(Mutex<BTreeMap<String, Weak<Cooperation>>>);\n# impl LinkTransport for Net {\n#   fn post(&self, e: &str, p: &str, m: &Signed) -> Result<LinkReply, String> {\n#     let peer = (self.0.lock().unwrap().get(e).and_then(Weak::upgrade))\n#         .ok_or_else(|| format!(\"{e}: nobody there\"))?;\n#     Ok(if p == HELLO_PATH { peer.accept_hello(m) } else { peer.accept_sync(m) }) } }\n# let net = Arc::new(Net::default());\n# let runtime = |endpoint: &str, policy: TrustPolicy| {\n#   let c = Cooperation::new(CooperationSetup {\n#     identity: Arc::new(NodeIdentity::ephemeral().unwrap()), runtime: runtime_id(endpoint),\n#     repository: of_root_commits(&[\"root\".into()]), endpoints: vec![endpoint.into()],\n#     version: \"doc\".into(), config: CooperationConfig::default(),\n#     trust: TrustConfig { policy, allow: vec![] }, journal_path: None,\n#     registry: Arc::new(MeshRegistry::new()),\n#     transport: Arc::clone(&net) as Arc<dyn LinkTransport>, board: None,\n#     checkout: CheckoutFacts::default() }).unwrap();\n#   net.0.lock().unwrap().insert(endpoint.into(), Arc::downgrade(&c)); c };\n# let a = runtime(\"a:1\", TrustPolicy::Tofu);\n# let strict = runtime(\"s:1\", TrustPolicy::DenyUnknown);\na.dial(&[\"s:1\".into()]).expect_err(\"reachable, and not trusted\");\n\nlet refused: &RefusedView = &strict.status().refused[0];\nassert_eq!(refused.refusal.code, RefusalCode::Untrusted);\nassert_eq!(refused.direction, \"inbound\", \"this runtime refused the hello\");\nassert_eq!(refused.runtime.as_deref(), Some(a.runtime_key()));\n```"
    },
    "LinkRefusal": {
      "type": "object",
      "properties": {
        "code": {
          "$ref": "#/$defs/RefusalCode",
          "description": "The rule that refused."
        },
        "detail": {
          "type": "string",
          "description": "Why, in words."
        },
        "proto_min": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "description": "The refuser's oldest protocol."
        },
        "proto_max": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "description": "The refuser's newest protocol."
        }
      },
      "required": [
        "code",
        "detail",
        "proto_min",
        "proto_max"
      ],
      "description": "A refusal: the code, the reason in words, and the protocol range of the refuser so a\nversion mismatch is diagnosable from either end.\n\nCarrying the refuser's protocol range in every refusal, not only in the one about\nprotocols, is what makes a version problem visible from the side that has the log: the\ndialer sees what the answerer speaks without anyone having to read the other machine.\n\n```\nuse majordomus_cli::mesh::link::{LinkRefusal, RefusalCode, LINK_PROTOCOL_MAX};\n\nlet refusal = LinkRefusal::new(RefusalCode::Untrusted, \"the key is not in the allowlist\");\nassert_eq!(refusal.code, RefusalCode::Untrusted);\nassert_eq!(refusal.proto_max, LINK_PROTOCOL_MAX);\nassert_eq!(refusal.to_string(), \"untrusted: the key is not in the allowlist\");\n```"
    },
    "RefusalCode": {
      "oneOf": [
        {
          "type": "string",
          "const": "malformed",
          "description": "Not the shape of the message."
        },
        {
          "type": "string",
          "const": "oversized",
          "description": "Over `MAX_LINK_MESSAGE`."
        },
        {
          "type": "string",
          "const": "protocol_unsupported",
          "description": "The protocol ranges do not meet."
        },
        {
          "type": "string",
          "const": "signature",
          "description": "The signature does not verify."
        },
        {
          "type": "string",
          "const": "stale",
          "description": "The timestamp is outside the skew window."
        },
        {
          "type": "string",
          "const": "replay",
          "description": "A nonce or a counter already seen."
        },
        {
          "type": "string",
          "const": "repository_mismatch",
          "description": "The peer serves another repository: the isolation rule."
        },
        {
          "type": "string",
          "const": "untrusted",
          "description": "The peer's key is not trusted by this runtime's policy: discovery is not trust."
        },
        {
          "type": "string",
          "const": "self_link",
          "description": "The peer is this very runtime."
        },
        {
          "type": "string",
          "const": "not_active",
          "description": "This runtime's cooperation is not active."
        },
        {
          "type": "string",
          "const": "unknown_link",
          "description": "The link id is unknown here: the answerer restarted or expired the link; say hello."
        },
        {
          "type": "string",
          "const": "capacity",
          "description": "A bound of this runtime is full."
        },
        {
          "type": "string",
          "const": "feature_unsupported",
          "description": "The peer lacks a feature the operation needs."
        },
        {
          "type": "string",
          "const": "misaddressed",
          "description": "A hello addressed to another runtime: captured on its way there and replayed here."
        }
      ],
      "description": "Why a link message was turned down. Every refusal is typed, counted and shown: a mesh\nthat refuses a peer says which rule did, instead of dropping a socket.\n\nThe codes are the diagnosis a person needs when two runtimes will not link, and they\nare deliberately distinct where the remedies differ: `Untrusted` is a key to add,\n`RepositoryMismatch` is two different repositories, `SelfLink` is a configuration that\ndials its own endpoint, and `UnknownLink` is not a failure at all but an instruction to\nsay hello again.\n\n```\nuse majordomus_cli::mesh::link::RefusalCode;\n\n// the wire word is the code's identity across surfaces, and it is stable\nassert_eq!(RefusalCode::RepositoryMismatch.as_str(), \"repository_mismatch\");\nassert_eq!(\n    serde_json::to_value(RefusalCode::Untrusted).unwrap(),\n    serde_json::json!(\"untrusted\"),\n);\nassert_ne!(RefusalCode::Untrusted, RefusalCode::RepositoryMismatch);\n```"
    }
  }
}

Examples

These are the capability's own benchmark cases: the same inputs the benchmark runs and the OpenAPI document shows.

summary
{}
full
{
  "view": "full"
}