episodes.list
Every execution episode this shared server holds, open and detached, with the connection holding each, when its client last spoke, how many connections have carried it, and what the repository's own episode command reported. In-memory: what survives the process is the repository's session record.
Every execution episode this shared server holds, open and detached, with the connection holding each, when its client last spoke, how many connections have carried it, and what the repository's own episode command reported. In-memory: what survives the process is the repository's session record.
- query
- behaviorally_verified
- module episodes
- #episodes
- #session
- #coordination
Exposure
Where this one definition is reachable. Absence is explicit: a surface not listed does not carry it.
| surface | as |
|---|---|
| MCP | tool majordomus_episodes |
| HTTP | GET /api/v1/episodes operationId episodes.list |
| 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 · Empty
No properties: the capability takes no input.
JSON Schema
{
"additionalProperties": false,
"description": "No input.",
"title": "Empty",
"type": "object"
}output · EpisodeList
episodes.list: every episode this server holds, counted by state, and the
one the caller holds. In memory only — it is the association between live connections and
the repository's records, which stops being true when the process stops.
The two counts partition the list, and mine is left out of the JSON rather than written
as null when the caller holds nothing, which is always so over plain HTTP:
use majordomus_cli::capability::builtin::episodes::EpisodeList;
let none = EpisodeList { open: 0, detached: 0, episodes: vec![], mine: None };
let json = serde_json::to_value(&none).unwrap();
assert_eq!(json, serde_json::json!({"open": 0, "detached": 0, "episodes": []}));
let back: EpisodeList = serde_json::from_value(json).unwrap();
assert_eq!(back.open + back.detached, back.episodes.len());| property | type | required | description |
|---|---|---|---|
| detached | integer | yes | How many are detached, waiting for a client to come back inside the grace. Not a fault count: this is where a crashed client's work waits to be resumed. |
| episodes | array | yes | Every episode, open and detached, in external-identity order. |
| mine | one of 2 | no | The episode the calling connection holds, when it holds one. |
| open | integer | yes | How many are open — held by a connection that is still there. |
JSON Schema
{
"$defs": {
"ConnectionEpisode": {
"description": "One episode: what the client calls itself, which connection holds it now, and what the\nrepository did about it.\n\n```\nuse majordomus_cli::episodes::{ConnectionEpisode, EpisodeBoard};\nuse majordomus_cli::peers::{PeerBoard, Transport};\nlet peer = PeerBoard::new().attach(Transport::Http);\nlet (episode, _) = EpisodeBoard::new().attach(&peer, \"conv-42\", \"generic\");\nlet episode: ConnectionEpisode = episode;\nassert_eq!((episode.external_id.as_str(), episode.provider.as_str()), (\"conv-42\", \"generic\"));\nassert_eq!(episode.peer.as_ref(), Some(&peer));\n// never empty: a board with no repository behind it says so\nassert!(episode.repository.contains(\"without a driver\"));\n```",
"properties": {
"attachments": {
"description": "How many times a connection has taken it over, the first attach included.",
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"external_id": {
"description": "The client's own durable name for this piece of work, and the key everything here is\naddressed by. Never a peer id: see the module documentation.",
"type": "string"
},
"last_activity_seconds_ago": {
"description": "Seconds since the client last spoke on it, through any connection.",
"format": "uint64",
"minimum": 0,
"type": "integer"
},
"opened_at": {
"description": "When it was first opened, RFC 3339, UTC. Unchanged by a re-attach: the episode is\nthe work, and the work did not restart because a socket did.",
"type": "string"
},
"peer": {
"anyOf": [
{
"$ref": "#/$defs/PeerId"
},
{
"type": "null"
}
],
"description": "The connection holding it, when one does. `None` while detached — which is a state\nan episode is *supposed* to reach and come back from, not a fault."
},
"provider": {
"description": "The provider id this episode is recorded under, as `share/providers.yaml` names one.",
"type": "string"
},
"repository": {
"description": "What the repository's own episode command reported, verbatim — the record it opened,\nor the reason it could not. Never interpreted here, and never empty: a subsystem\nthat silently does nothing is the failure mode this field exists to make visible.",
"type": "string"
},
"state": {
"$ref": "#/$defs/ConnectionEpisodeState",
"description": "Open, or detached and waiting for its client."
}
},
"required": [
"external_id",
"provider",
"opened_at",
"last_activity_seconds_ago",
"attachments",
"state",
"repository"
],
"type": "object"
},
"ConnectionEpisodeState": {
"description": "Where an episode stands: held by a live connection, or waiting for its client to come\nback. There is no closed state, because a closed episode leaves the board; what survives\nit is the repository's own record.\n\n```\nuse majordomus_cli::episodes::{ConnectionEpisodeState, EpisodeBoard};\nuse majordomus_cli::peers::{PeerBoard, Transport};\nlet peer = PeerBoard::new().attach(Transport::Stdio);\nlet board = EpisodeBoard::new();\nassert_eq!(board.attach(&peer, \"w\", \"generic\").0.state, ConnectionEpisodeState::Open);\nassert_eq!(board.detach(&peer)[0].state, ConnectionEpisodeState::Detached);\nassert_eq!(serde_json::to_string(&ConnectionEpisodeState::Detached).unwrap(), \"\\\"detached\\\"\");\n```",
"oneOf": [
{
"const": "open",
"description": "A connection holds it and the client is speaking.",
"type": "string"
},
{
"const": "detached",
"description": "The connection has gone; the episode is kept for `REATTACH_GRACE` so the client\ncan come back to it. This is the state a crash lands in, and the one a reconnect\nrecovers from.",
"type": "string"
}
]
},
"PeerId": {
"description": "A peer's identity for the life of the server: `p1`, `p2`, ... in attachment order.\n`p1` is the session that started the server.",
"type": "string"
}
},
"description": "The answer of `episodes.list`: every episode this server holds, counted by state, and the\none the caller holds. In memory only — it is the association between live connections and\nthe repository's records, which stops being true when the process stops.\n\nThe two counts partition the list, and `mine` is left out of the JSON rather than written\nas `null` when the caller holds nothing, which is always so over plain HTTP:\n\n```\nuse majordomus_cli::capability::builtin::episodes::EpisodeList;\nlet none = EpisodeList { open: 0, detached: 0, episodes: vec![], mine: None };\nlet json = serde_json::to_value(&none).unwrap();\nassert_eq!(json, serde_json::json!({\"open\": 0, \"detached\": 0, \"episodes\": []}));\nlet back: EpisodeList = serde_json::from_value(json).unwrap();\nassert_eq!(back.open + back.detached, back.episodes.len());\n```",
"properties": {
"detached": {
"description": "How many are detached, waiting for a client to come back inside the grace. Not a\nfault count: this is where a crashed client's work waits to be resumed.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"episodes": {
"description": "Every episode, open and detached, in external-identity order.",
"items": {
"$ref": "#/$defs/ConnectionEpisode"
},
"type": "array"
},
"mine": {
"anyOf": [
{
"$ref": "#/$defs/ConnectionEpisode"
},
{
"type": "null"
}
],
"description": "The episode the calling connection holds, when it holds one."
},
"open": {
"description": "How many are open — held by a connection that is still there.",
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"required": [
"open",
"detached",
"episodes"
],
"title": "EpisodeList",
"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.