mesh.peer
One runtime by its key (`<node>-<runtime>`, or a node id for its first runtime): the machine it runs on, its liveness, its link from here, its sessions and claims, and any refusal recorded against it. Not found is an answer with the reason.
One runtime by its key (`<node>-<runtime>`, or a node id for its first runtime): the machine it runs on, its liveness, its link from here, its sessions and claims, and any refusal recorded against it. Not found is an answer with the reason.
- query
- experimental
- module mesh
- #mesh
- #coordination
- #cooperation
Exposure
Where this one definition is reachable. Absence is explicit: a surface not listed does not carry it.
| surface | as |
|---|---|
| MCP | tool majordomus_mesh_peer |
| HTTP | GET /api/v1/mesh/peer operationId mesh.peer |
| command line | — |
Schemas
The canonical input and output, from the Rust types; the MCP tool schema and the OpenAPI parameters and responses are derived from these.
input · PeerInput
mesh.peer.| property | type | required | description |
|---|---|---|---|
| runtime | string | yes | The runtime, <node>-<runtime> (a node id alone matches its first runtime). |
JSON Schema
{
"additionalProperties": false,
"description": "The input of `mesh.peer`.",
"properties": {
"runtime": {
"description": "The runtime, `<node>-<runtime>` (a node id alone matches its first runtime).",
"type": "string"
}
},
"required": [
"runtime"
],
"title": "PeerInput",
"type": "object"
}output · PeerDetail
mesh.peer.| property | type | required | description |
|---|---|---|---|
| found | boolean | yes | Whether the runtime is known here. |
| machine | string | null | no | The machine it runs on. |
| reason | string | null | no | Why not, when it is not. |
| refused | array | yes | Refusals recorded against it. |
| runtime | one of 2 | no | The runtime, its link and its sessions. |
JSON Schema
{
"$defs": {
"ClaimMode": {
"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```",
"oneOf": [
{
"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.",
"type": "string"
}
]
},
"ClaimState": {
"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```",
"oneOf": [
{
"description": "Live; for an exclusive claim, the winner of its scope.",
"properties": {
"state": {
"const": "held",
"type": "string"
}
},
"required": [
"state"
],
"type": "object"
},
{
"description": "Released by its holder.",
"properties": {
"state": {
"const": "released",
"type": "string"
}
},
"required": [
"state"
],
"type": "object"
},
{
"description": "Ended without a release: the holder's session closed or its runtime expired.",
"properties": {
"detail": {
"type": "string"
},
"state": {
"const": "expired",
"type": "string"
}
},
"required": [
"state",
"detail"
],
"type": "object"
},
{
"description": "Live, exclusive, and beaten to its scope by the claim whose key this names.",
"properties": {
"detail": {
"type": "string"
},
"state": {
"const": "conflicted",
"type": "string"
}
},
"required": [
"state",
"detail"
],
"type": "object"
}
]
},
"ClaimView": {
"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```",
"properties": {
"acquired_lamport": {
"description": "The Lamport stamp of the acquisition.",
"format": "uint64",
"minimum": 0,
"type": "integer"
},
"acquired_seq": {
"description": "The sequence of the acquisition within its stream: with the stamp and the stream,\nthe total order in which exclusivity is decided.",
"format": "uint64",
"minimum": 0,
"type": "integer"
},
"intent": {
"description": "What it is for.",
"type": [
"string",
"null"
]
},
"issue": {
"description": "The issue it is for.",
"type": [
"string",
"null"
]
},
"key": {
"description": "`<stream>/<claim>`.",
"type": "string"
},
"mode": {
"$ref": "#/$defs/ClaimMode",
"description": "Exclusive or advisory."
},
"runtime": {
"description": "`<node>-<runtime>`.",
"type": "string"
},
"scope": {
"description": "The claimed paths.",
"items": {
"type": "string"
},
"type": "array"
},
"session": {
"description": "The holding session's key.",
"type": "string"
},
"state": {
"$ref": "#/$defs/ClaimState",
"description": "Its standing."
},
"stream": {
"$ref": "#/$defs/StreamId",
"description": "The writing stream."
}
},
"required": [
"key",
"stream",
"runtime",
"session",
"scope",
"mode",
"acquired_lamport",
"acquired_seq",
"state"
],
"type": "object"
},
"LinkRefusal": {
"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```",
"properties": {
"code": {
"$ref": "#/$defs/RefusalCode",
"description": "The rule that refused."
},
"detail": {
"description": "Why, in words.",
"type": "string"
},
"proto_max": {
"description": "The refuser's newest protocol.",
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"proto_min": {
"description": "The refuser's oldest protocol.",
"format": "uint32",
"minimum": 0,
"type": "integer"
}
},
"required": [
"code",
"detail",
"proto_min",
"proto_max"
],
"type": "object"
},
"LinkState": {
"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```",
"oneOf": [
{
"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.",
"type": "string"
}
]
},
"MeshClaimBrief": {
"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```",
"properties": {
"acquired_lamport": {
"description": "The Lamport stamp of the acquisition.",
"format": "uint64",
"minimum": 0,
"type": "integer"
},
"intent": {
"description": "What it is for, cut to `SUMMARY_TEXT` characters.",
"type": [
"string",
"null"
]
},
"issue": {
"description": "The issue it is for.",
"type": [
"string",
"null"
]
},
"key": {
"description": "`<stream>/<claim>`.",
"type": "string"
},
"mode": {
"$ref": "#/$defs/ClaimMode",
"description": "Exclusive or advisory."
},
"paths": {
"description": "How many paths it claims.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"session": {
"description": "The holding session's key.",
"type": "string"
}
},
"required": [
"key",
"session",
"paths",
"mode",
"acquired_lamport"
],
"type": "object"
},
"PeerView": {
"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```",
"properties": {
"endpoint": {
"description": "The endpoint this runtime dials, when it does.",
"type": [
"string",
"null"
]
},
"endpoints": {
"description": "Where the peer answers.",
"items": {
"type": "string"
},
"type": "array"
},
"failures": {
"description": "Consecutive failed rounds.",
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"features": {
"description": "The link features the peer carries.",
"items": {
"type": "string"
},
"type": "array"
},
"handshakes": {
"description": "Handshakes completed with this peer.",
"format": "uint64",
"minimum": 0,
"type": "integer"
},
"inbound": {
"description": "Whether the peer dials this runtime.",
"type": "boolean"
},
"instance": {
"description": "The current instance.",
"type": "string"
},
"last_error": {
"description": "The last failure, in words.",
"type": [
"string",
"null"
]
},
"last_exchange_ms": {
"description": "Milliseconds since the last successful exchange in either direction.",
"format": "uint64",
"minimum": 0,
"type": [
"integer",
"null"
]
},
"linked_at": {
"description": "When the current link was established, RFC 3339.",
"type": "string"
},
"local": {
"description": "Whether the peer runs on this machine (the same node key).",
"type": "boolean"
},
"name": {
"description": "The node's display name.",
"type": "string"
},
"node": {
"description": "The node (machine key digest).",
"type": "string"
},
"outbound": {
"description": "Whether this runtime dials the peer.",
"type": "boolean"
},
"protocol": {
"description": "The negotiated link protocol.",
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"reconnects": {
"description": "Handshakes after an expiry or a dropped link.",
"format": "uint64",
"minimum": 0,
"type": "integer"
},
"restarts": {
"description": "New instances of the peer seen (its process restarted).",
"format": "uint64",
"minimum": 0,
"type": "integer"
},
"rtt_ms": {
"description": "The last round trip, milliseconds.",
"format": "uint64",
"minimum": 0,
"type": [
"integer",
"null"
]
},
"runtime": {
"description": "`<node>-<runtime>`: the peer's durable identity.",
"type": "string"
},
"state": {
"$ref": "#/$defs/LinkState",
"description": "The link's standing."
},
"trust": {
"$ref": "#/$defs/TrustState",
"description": "The trust verdict the link was admitted under."
},
"version": {
"description": "The executable version.",
"type": "string"
}
},
"required": [
"runtime",
"node",
"instance",
"name",
"version",
"local",
"trust",
"protocol",
"features",
"endpoints",
"state",
"outbound",
"inbound",
"failures",
"handshakes",
"reconnects",
"restarts",
"linked_at"
],
"type": "object"
},
"RefusalCode": {
"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```",
"oneOf": [
{
"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.",
"type": "string"
}
]
},
"RefusedView": {
"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```",
"properties": {
"at": {
"description": "When, RFC 3339.",
"type": "string"
},
"direction": {
"description": "`outbound` (this runtime refused the peer's welcome, or the peer refused this\nhello) or `inbound` (this runtime refused the peer's hello).",
"type": "string"
},
"endpoint": {
"description": "The endpoint dialed, or `inbound:<runtime>` for a refused hello.",
"type": "string"
},
"refusal": {
"$ref": "#/$defs/LinkRefusal",
"description": "The refusal."
},
"runtime": {
"description": "The peer's runtime key, when its card said.",
"type": [
"string",
"null"
]
}
},
"required": [
"endpoint",
"direction",
"refusal",
"at"
],
"type": "object"
},
"RuntimeNode": {
"description": "One runtime in the peer tree.",
"properties": {
"last_beat_ms": {
"description": "Milliseconds since its beat last rose, on this runtime's clock.",
"format": "uint64",
"minimum": 0,
"type": [
"integer",
"null"
]
},
"link": {
"anyOf": [
{
"$ref": "#/$defs/PeerView"
},
{
"type": "null"
}
],
"description": "This runtime's link to it, when there is one."
},
"liveness": {
"$ref": "#/$defs/StreamLiveness",
"description": "Whether its stream beats: own, live, or expired."
},
"newest_claim": {
"anyOf": [
{
"$ref": "#/$defs/MeshClaimBrief"
},
{
"type": "null"
}
],
"description": "Its newest live claim, told briefly."
},
"runtime": {
"description": "`<node>-<runtime>`.",
"type": "string"
},
"sessions": {
"description": "Its sessions; in the summary view only the active ones.",
"items": {
"$ref": "#/$defs/SessionNode"
},
"type": "array"
},
"this_runtime": {
"description": "Whether this is the runtime answering.",
"type": "boolean"
}
},
"required": [
"runtime",
"this_runtime",
"liveness",
"sessions"
],
"type": "object"
},
"SessionInfo": {
"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```",
"properties": {
"branch": {
"description": "The branch checked out.",
"type": [
"string",
"null"
]
},
"checkout": {
"description": "The checkout id (a digest, never a path).",
"type": [
"string",
"null"
]
},
"client": {
"description": "The client: `claude-code`, `codex`, `cli`, ...",
"type": "string"
},
"context": {
"description": "The context revision the session works from (a digest the context compiler names).",
"type": [
"string",
"null"
]
},
"dirty": {
"description": "Whether the working tree had uncommitted changes when this was said.",
"type": [
"boolean",
"null"
]
},
"head": {
"description": "The commit checked out.",
"type": [
"string",
"null"
]
},
"intent": {
"description": "What the session says it is doing.",
"type": [
"string",
"null"
]
},
"issue": {
"description": "The issue (`I0001`, `#184`) the work belongs to.",
"type": [
"string",
"null"
]
},
"milestone": {
"description": "The milestone the work belongs to.",
"type": [
"string",
"null"
]
},
"session": {
"description": "The session's id within its stream.",
"type": "string"
},
"task": {
"description": "The task id (`t-...`) the session works under.",
"type": [
"string",
"null"
]
},
"worker": {
"description": "The worker's own name for itself, when it gave one.",
"type": [
"string",
"null"
]
}
},
"required": [
"session",
"client"
],
"type": "object"
},
"SessionNode": {
"description": "One session in the peer tree.",
"properties": {
"claims": {
"description": "The claims it holds or held; empty in the summary view, which counts them instead.",
"items": {
"$ref": "#/$defs/ClaimView"
},
"type": "array"
},
"claims_held": {
"description": "How many of its claims are live.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"info": {
"$ref": "#/$defs/SessionInfo",
"description": "What the session last said about itself."
},
"key": {
"description": "`<stream>/<session>`.",
"type": "string"
},
"reviews": {
"description": "The review requests it opened, by key.",
"items": {
"type": "string"
},
"type": "array"
},
"state": {
"$ref": "#/$defs/SessionState",
"description": "Its standing."
}
},
"required": [
"key",
"info",
"state",
"claims",
"claims_held",
"reviews"
],
"type": "object"
},
"SessionState": {
"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```",
"oneOf": [
{
"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.",
"type": "string"
}
]
},
"StreamId": {
"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```",
"type": "string"
},
"StreamLiveness": {
"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```",
"oneOf": [
{
"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.",
"type": "string"
}
]
},
"TrustState": {
"description": "What the policy decided about one node.",
"oneOf": [
{
"description": "Valid, recorded, trusted for nothing. The resting state of an unknown node.",
"properties": {
"state": {
"const": "observed",
"type": "string"
}
},
"required": [
"state"
],
"type": "object"
},
{
"description": "The policy trusts this key; `detail` says which rule did (`allowlist`, `tofu`).",
"properties": {
"detail": {
"type": "string"
},
"state": {
"const": "trusted",
"type": "string"
}
},
"required": [
"state",
"detail"
],
"type": "object"
},
{
"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.",
"properties": {
"detail": {
"type": "string"
},
"state": {
"const": "rejected",
"type": "string"
}
},
"required": [
"state",
"detail"
],
"type": "object"
}
]
}
},
"description": "The answer of `mesh.peer`.",
"properties": {
"found": {
"description": "Whether the runtime is known here.",
"type": "boolean"
},
"machine": {
"description": "The machine it runs on.",
"type": [
"string",
"null"
]
},
"reason": {
"description": "Why not, when it is not.",
"type": [
"string",
"null"
]
},
"refused": {
"description": "Refusals recorded against it.",
"items": {
"$ref": "#/$defs/RefusedView"
},
"type": "array"
},
"runtime": {
"anyOf": [
{
"$ref": "#/$defs/RuntimeNode"
},
{
"type": "null"
}
],
"description": "The runtime, its link and its sessions."
}
},
"required": [
"found",
"refused"
],
"title": "PeerDetail",
"type": "object"
}Policies
- benchmark
- required — a target on every transport the exposure declares; the cases are the input type's
- cache
- disabled — every call runs the handler
Benchmark targets
Derived from the registry for this repository: one requirement per transport, and the cases the input type provides. The whole matrix is on the benchmarks page.