Skip to main content

Module state

Module state 

Source
Expand description

Where an episode is in its life, and the transitions that move it there.

§Why this is a type and not a convention

The lifecycle used to be expressed as the presence and absence of files: an episode is open because state/sessions-open/<key>.yaml exists, and closed because it does not and a record does. That representation has no state it refuses to be in. It cannot say that a closed episode may not be closed again — which is how one episode in this repository came to have four immutable records — and it cannot say that a transition is legal without also performing it, which is how every check of the form “is this allowed” ended up written separately at each call site, in shell, three times, with the task guard ADR 0052 removed embedded in one of them.

So the transitions are the contract and EpisodeState::may_move_to is the one place they are written down: the store asks before every change, and a caller that reads a terminal state never sees it move again. The same shape as crate::execution::ExecutionState, for the same reason and deliberately in the same style — a reader who has met one has met the other.

  Opening ──► Open ──┬──► Detached ──┬──► Open        (resume)
                     │               └──► Closed      (close, or recover)
                     ├──► Open                        (checkpoint, repeated start: no move)
                     └──► Closed                      (close, or recover)

§What is not in the signature

There is no task. EpisodeState::may_move_to takes a target state and nothing else; Transition carries no task field. This is the whole of ADR 0052 expressed as a type: the defect it removed was outcome != active -> skip on the path that writes an episode’s artefacts, and in this model there is nowhere to put it. A task’s outcome may change what a continuation record says — that belongs to the record’s composition, not to the state machine — and it may never decide whether one is written.

use majordomus_cli::session::{EpisodeState, Transition};

// the whole machine, asked rather than drawn
assert!(EpisodeState::Open.may_move_to(EpisodeState::Closed));
assert!(!EpisodeState::Closed.may_move_to(EpisodeState::Open));
assert_eq!(Transition::Recover.from_to(), (EpisodeState::Detached, EpisodeState::Closed));

Structs§

Machine
The state machine as data, so that every surface projects the same machine instead of drawing its own.
StateView
One state of the machine: its word, whether an episode ever leaves it, and where it may go from there.
TransitionView
One transition of the machine: its word, the states it runs between, and whether it moves the state at all.

Enums§

EpisodeState
Where an episode is: minted, open, detached from the connection that held it, or closed into the immutable record.
Transition
What moved an episode. The vocabulary the ADR 0052 audit needs: open, resume, checkpoint, detach, close, recover.