Skip to main content

Episode

Struct Episode 

Source
pub struct Episode {
Show 16 fields pub session_id: String, pub path: String, pub provider: String, pub provider_session: String, pub owner: String, pub worker: String, pub worktree: String, pub branch: String, pub start_head: String, pub started_at: String, pub standing: EpisodeStanding, pub events: usize, pub last_activity: String, pub last_event: String, pub tasks: Vec<String>, pub note: String,
}
Expand description

One open episode, as its file records it and as the ledger has seen it.

Everything here is recorded rather than derived, and almost everything is optional, which is the point: an episode opened by hand has no provider, a worker that supplied no identity has none, and an episode that opened and did nothing has no ledger line and so no last_activity. Each of those is ordinary and none is a fault, so each is carried as absence — the empty fields are skipped on the wire — and a reader must handle their absence rather than expect a placeholder.

The two fields that are always there are standing and note: where the episode stands, and why it stands there in words. A standing a reader cannot act on is the failure this subsystem was corrected for, so note is never empty.

use majordomus_cli::capability::builtin::lifecycle::{Episode, EpisodeStanding};
use serde_json::json;

// the smallest true record: an episode opened by hand that has written nothing yet
let e: Episode = serde_json::from_value(json!({
    "session_id": "s-0001",
    "path": ".ai/local/state/sessions-open/by-hand.yaml",
    "standing": "open",
    "events": 0,
    "note": "open in this worktree; the pointer names another episode",
})).unwrap();

assert_eq!(e.standing, EpisodeStanding::Open);
assert!(e.provider.is_empty(), "no provider session owns a hand-opened episode");
assert!(e.last_activity.is_empty(), "it has written no ledger line");
assert!(e.tasks.is_empty(), "work outside a task is permitted");
assert!(!e.note.is_empty(), "a standing always says why");

// and absence stays absence: the empty fields are not serialised back as ""
let wire = serde_json::to_value(&e).unwrap();
assert!(wire.get("provider").is_none());
assert_eq!(wire["events"], 0, "a count of zero is a measurement, so it is kept");

Fields§

§session_id: String

The episode id the ledger stamps on every line this worker wrote.

§path: String

Repository-relative path of the open record. The body is at the path.

§provider: String

The provider whose event opened it, when one did. Empty for an episode opened by hand, which is the one episode no provider session owns.

§provider_session: String

That provider’s own session identity: the file’s stem, and the string the prompt archive stamps on the same worker’s records.

§owner: String

Who opened it.

§worker: String

The worker identity, when one was supplied. Never inferred.

§worktree: String

The worktree it opened in, absolute, as recorded.

§branch: String

The branch it opened on.

§start_head: String

The commit it opened at.

§started_at: String

When it opened, as recorded.

§standing: EpisodeStanding

Where it stands.

§events: usize

How many ledger lines carry this episode id. Zero for an episode that opened and did nothing, which is ordinary and not a fault.

§last_activity: String

The timestamp of the newest ledger line carrying this episode id, as recorded. Empty when it has written none.

§last_event: String

That line’s event name.

§tasks: Vec<String>

The tasks this episode’s ledger lines name, in the order it first touched each.

A relation, not a container. An episode may touch three tasks or none, and a task may span three episodes; the two are joined here by what the ledger recorded rather than by either one owning the other. An episode with no task is ordinary — work outside a task is permitted — and it is emphatically not a reason for the episode’s own records to go unwritten, which is the premise ADR 0052 removes.

§note: String

Why it stands where it does, in words. Never empty: a standing a reader cannot act on is the failure this subsystem is being corrected for.

Trait Implementations§

Source§

impl Clone for Episode

Source§

fn clone(&self) -> Episode

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Episode

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Episode

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for Episode

Source§

impl JsonSchema for Episode

Source§

fn schema_name() -> Cow<'static, str>

The name of the generated JSON Schema. Read more
Source§

fn schema_id() -> Cow<'static, str>

Returns a string that uniquely identifies the schema produced by this type. Read more
Source§

fn json_schema(generator: &mut SchemaGenerator) -> Schema

Generates a JSON Schema for this type. Read more
Source§

fn inline_schema() -> bool

Whether JSON Schemas generated for this type should be included directly in parent schemas, rather than being re-used where possible using the $ref keyword. Read more
Source§

impl PartialEq for Episode

Source§

fn eq(&self, other: &Episode) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for Episode

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for Episode

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more