session_domain.machine
Každý stav, v němž může být epizoda, zda je koncový a kam se může přesunout; každý přechod — open, resume, checkpoint, detach, close, recover — se stavy, mezi nimiž běží, a zda stav vůbec posouvá. Odvozeno z typů, takže diagram, který se rozchází s kódem, nemůže existovat. Na čem stroj záměrně nezávisí, je řečeno, ne ponecháno k dedukci: na stavu úlohy, což je ADR 0052.
Každý stav, v němž může být epizoda, zda je koncový a kam se může přesunout; každý přechod — open, resume, checkpoint, detach, close, recover — se stavy, mezi nimiž běží, a zda stav vůbec posouvá. Odvozeno z typů, takže diagram, který se rozchází s kódem, nemůže existovat. Na čem stroj záměrně nezávisí, je řečeno, ne ponecháno k dedukci: na stavu úlohy, což je ADR 0052.
- query
- behaviorally_verified
- module session_domain
- #session
- #continuity
- #lifecycle
Zpřístupnění
Kde je tato jedna definice dosažitelná. Absence je explicitní: povrch, který není uveden, ji nenese.
| povrch | jako |
|---|---|
| MCP | nástroj majordomus_session_machine zdroj majordomus://session/machine |
| HTTP | GET /api/v1/session/machine operationId session_domain.machine |
| příkazová řádka | — |
Schémata
Kanonický vstup a výstup z typů Rustu; schéma nástroje MCP a parametry a odpovědi OpenAPI se odvozují z nich.
vstup · Prázdné
Žádné vlastnosti: schopnost nebere žádný vstup.
JSON Schema
{
"additionalProperties": false,
"description": "No input.",
"title": "Empty",
"type": "object"
}výstup · MachineReport
use majordomus_cli::capability::builtin::MachineReport;
use majordomus_cli::session::Machine;
// the report is the machine plus one citation; the machine itself is derived from the
// types and carries no second list
let report = MachineReport { machine: Machine::describe(), decision: "adr-0047".into() };
assert!(report.machine.transitions.iter().any(|t| !t.moves_state), "a checkpoint is an event");
assert!(report.decision.contains("0047"));| vlastnost | typ | povinné | popis |
|---|---|---|---|
| rozhodnutí | string | ano | Rozhodnutí, jehož implementací je tento stroj, aby čtenář, který na něj v projekci narazí, mohl jít přečíst, proč má takový tvar. |
| independent_of | array | ano | Na čem stroj záměrně nezávisí, uvedeno tak, aby čtenář nemusel absenci odvozovat. Dnes jedna položka: stav úlohy. |
| stavy | array | ano | Každý stav, s významem a zda je koncový. |
| přechody | array | ano | Každý přechod, se stavy, mezi nimiž probíhá. |
JSON Schema
{
"$defs": {
"EpisodeState": {
"description": "Where an episode is: minted, open, detached from the connection that held it, or closed\ninto the immutable record.\n\n```\nuse majordomus_cli::session::EpisodeState;\n\nassert!(EpisodeState::Open.may_move_to(EpisodeState::Closed));\nassert!(!EpisodeState::Closed.may_move_to(EpisodeState::Open), \"a record is immutable\");\nassert!(EpisodeState::Open.may_move_to(EpisodeState::Open), \"a resume is not a move\");\nassert!(EpisodeState::Closed.is_final());\n```",
"oneOf": [
{
"const": "opening",
"description": "An identity has been minted and nothing durable has been written yet. It exists so\nthat a crash between minting an id and writing the open record is a state the model\ncan name rather than an episode that never happened.",
"type": "string"
},
{
"const": "open",
"description": "The open record stands. The worker is here, or was recently.",
"type": "string"
},
{
"const": "detached",
"description": "The connection that held the episode went away, and the episode did not. A dropped\nsocket is the most ordinary thing that happens to a session; an episode that closed\nitself on every disconnect would lose the work of every worker whose network\nhiccuped. It is still resumable, and it is still recoverable if nobody resumes it.",
"type": "string"
},
{
"const": "closed",
"description": "The immutable record has been published. Terminal, and terminal is the point: the\nfour records of `s-20260909152316-024f` all exist because nothing in the previous\nrepresentation could say this.",
"type": "string"
}
]
},
"StateView": {
"description": "One state of the machine: its word, whether an episode ever leaves it, and where it may\ngo from there.\n\n```\nuse majordomus_cli::session::{EpisodeState, Machine, StateView};\n\nlet m = Machine::describe();\nlet closed: &StateView =\n m.states.iter().find(|s| s.state == EpisodeState::Closed).expect(\"a state\");\nassert!(closed.terminal && closed.may_move_to.is_empty());\n```",
"properties": {
"may_move_to": {
"description": "The states an episode in this one may move to, in canonical order.",
"items": {
"$ref": "#/$defs/EpisodeState"
},
"type": "array"
},
"state": {
"$ref": "#/$defs/EpisodeState",
"description": "The state's word."
},
"terminal": {
"description": "Whether an episode ever leaves it.",
"type": "boolean"
}
},
"required": [
"state",
"terminal",
"may_move_to"
],
"type": "object"
},
"Transition": {
"description": "What moved an episode. The vocabulary the ADR 0052 audit needs: `open`, `resume`,\n`checkpoint`, `detach`, `close`, `recover`.\n\nOne of them does not change the state, and it is a transition anyway. A checkpoint\nleaves an open episode open — but it is one of the two events whose *absence* is what\nthe audit was looking for, and an event that is modelled as \"nothing happened\" cannot\nbe counted. The six days of silence were six days in which `session.started` and\n`session.closed` kept arriving and the two events that produce the records a worker\nresumes from did not. A vocabulary in which those two are not events is a vocabulary in\nwhich that outage is invisible.\n\n```\nuse majordomus_cli::session::{EpisodeState, Transition};\n\n// a checkpoint is a transition that does not move the state, and says so\nlet c = Transition::Checkpoint;\nassert_eq!(c.from_to(), (EpisodeState::Open, EpisodeState::Open));\nassert!(!c.moves_state());\n\n// a resume is canonically the return to a detached episode; a provider's start event\n// arriving at one that is already open is the same transition seen from `Open`, which\n// the machine allows without a move\nassert_eq!(Transition::Resume.from_to(), (EpisodeState::Detached, EpisodeState::Open));\nassert!(EpisodeState::Open.may_move_to(EpisodeState::Open));\n\n// and every transition's own move is one the machine allows\nfor t in Transition::ALL {\n let (from, to) = t.from_to();\n assert!(from.may_move_to(to), \"{} is not a legal move\", t.as_str());\n}\n```",
"oneOf": [
{
"const": "open",
"description": "The episode begins: an id is minted and the open record is written.",
"type": "string"
},
{
"const": "resume",
"description": "The worker came back to a detached episode. A provider's start event also fires\nagain on a resume and on a compaction against an episode that is still open; that\nis the same transition observed from `Open`, and the honest answer to \"your episode\nis already open\" is to keep it rather than to open a second one.",
"type": "string"
},
{
"const": "checkpoint",
"description": "A progress note was recorded against the episode. An artefact of the episode and\nnot of a task (ADR 0052): a checkpoint outside a task records `task: none` and is a\nnormal record, not a refusal.",
"type": "string"
},
{
"const": "detach",
"description": "The connection went away without an end event.",
"type": "string"
},
{
"const": "close",
"description": "The worker ended the episode and the immutable record was published.",
"type": "string"
},
{
"const": "recover",
"description": "Nobody ended it and its last sign of life is older than the stranded threshold, so\nmaintenance closed it. The record says so: an episode closed this way is\n`interrupted`, because a reader resuming from it needs to know it may be incomplete.",
"type": "string"
}
]
},
"TransitionView": {
"description": "One transition of the machine: its word, the states it runs between, and whether it\nmoves the state at all.\n\n```\nuse majordomus_cli::session::{Machine, Transition, TransitionView};\n\nlet m = Machine::describe();\nlet close: &TransitionView = m\n .transitions\n .iter()\n .find(|t| t.transition == Transition::Close)\n .expect(\"a transition\");\nassert!(close.moves_state);\n```",
"properties": {
"from": {
"$ref": "#/$defs/EpisodeState",
"description": "Where it starts."
},
"moves_state": {
"description": "False for `resume` and `checkpoint`, which are events inside a state.",
"type": "boolean"
},
"to": {
"$ref": "#/$defs/EpisodeState",
"description": "Where it ends."
},
"transition": {
"$ref": "#/$defs/Transition",
"description": "The transition's word."
}
},
"required": [
"transition",
"from",
"to",
"moves_state"
],
"type": "object"
}
},
"description": "The lifecycle machine, with the decision it implements, so that a reader meeting it in\na projection can go and read why it is shaped this way.\n\n```\nuse majordomus_cli::capability::builtin::MachineReport;\nuse majordomus_cli::session::Machine;\n\n// the report is the machine plus one citation; the machine itself is derived from the\n// types and carries no second list\nlet report = MachineReport { machine: Machine::describe(), decision: \"adr-0047\".into() };\nassert!(report.machine.transitions.iter().any(|t| !t.moves_state), \"a checkpoint is an event\");\nassert!(report.decision.contains(\"0047\"));\n```",
"properties": {
"decision": {
"description": "The decision this machine is the implementation of, so a reader meeting it in a\nprojection can go and read why it is shaped this way.",
"type": "string"
},
"independent_of": {
"description": "What the machine deliberately does not depend on, stated so that a reader does not\nhave to infer an absence. One entry today: task state.",
"items": {
"type": "string"
},
"type": "array"
},
"states": {
"description": "Every state, with what it means and whether it is terminal.",
"items": {
"$ref": "#/$defs/StateView"
},
"type": "array"
},
"transitions": {
"description": "Every transition, with the states it runs between.",
"items": {
"$ref": "#/$defs/TransitionView"
},
"type": "array"
}
},
"required": [
"states",
"transitions",
"independent_of",
"decision"
],
"title": "MachineReport",
"type": "object"
}Politiky
- benchmark
- povinné — cíl na každém transportu, který expozice deklaruje; případy jsou ty ze vstupního typu
- cache
- proces — až 1 položka v procesu, každá 600 s, vymezená otiskem registru
Cíle benchmarku
Odvozeno z registru pro tento repozitář: jeden požadavek na transport a případy, které poskytuje typ vstupu. Celá matice je na stránce měření výkonu.