Skip to main content

meerkat_runtime/meerkat_machine/
dsl.rs

1//! MeerkatMachine DSL definition with real bridging types.
2#![allow(clippy::too_many_arguments)]
3
4use meerkat_machine_dsl::machine;
5use meerkat_machine_schema::catalog::dsl::OptionValueExt;
6
7// ---------------------------------------------------------------------------
8// Bridging types
9// ---------------------------------------------------------------------------
10
11#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
12pub struct SessionId(pub String);
13
14impl<T: Into<String>> From<T> for SessionId {
15    fn from(s: T) -> Self {
16        Self(s.into())
17    }
18}
19
20impl SessionId {
21    pub fn from_domain(id: &meerkat_core::types::SessionId) -> Self {
22        Self(id.to_string())
23    }
24}
25
26#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
27pub struct AgentRuntimeId(pub String);
28
29impl<T: Into<String>> From<T> for AgentRuntimeId {
30    fn from(s: T) -> Self {
31        Self(s.into())
32    }
33}
34
35impl AgentRuntimeId {
36    pub fn from_domain(id: &crate::identifiers::LogicalRuntimeId) -> Self {
37        Self(id.to_string())
38    }
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
42pub struct FenceToken(pub u64);
43
44impl From<u64> for FenceToken {
45    fn from(v: u64) -> Self {
46        Self(v)
47    }
48}
49
50impl FenceToken {
51    pub fn from_domain(value: u64) -> Self {
52        Self(value)
53    }
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
57pub struct Generation(pub u64);
58
59impl From<u64> for Generation {
60    fn from(v: u64) -> Self {
61        Self(v)
62    }
63}
64
65impl Generation {
66    pub fn from_domain(value: u64) -> Self {
67        Self(value)
68    }
69}
70
71#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
72pub struct RuntimeEpochId(pub String);
73
74impl<T: Into<String>> From<T> for RuntimeEpochId {
75    fn from(s: T) -> Self {
76        Self(s.into())
77    }
78}
79
80impl RuntimeEpochId {
81    pub fn from_domain(id: &meerkat_core::runtime_epoch::RuntimeEpochId) -> Self {
82        Self(id.to_string())
83    }
84}
85
86#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
87pub struct RunId(pub String);
88
89impl<T: Into<String>> From<T> for RunId {
90    fn from(s: T) -> Self {
91        Self(s.into())
92    }
93}
94
95impl RunId {
96    pub fn from_domain(id: &meerkat_core::lifecycle::RunId) -> Self {
97        Self(id.to_string())
98    }
99}
100
101#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
102pub struct InputId(pub String);
103
104impl<T: Into<String>> From<T> for InputId {
105    fn from(s: T) -> Self {
106        Self(s.into())
107    }
108}
109
110impl InputId {
111    pub fn from_domain(id: &meerkat_core::lifecycle::InputId) -> Self {
112        Self(id.to_string())
113    }
114}
115
116#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
117pub struct WorkId(pub String);
118
119impl<T: Into<String>> From<T> for WorkId {
120    fn from(s: T) -> Self {
121        Self(s.into())
122    }
123}
124
125impl WorkId {
126    pub fn from_domain(id: &meerkat_core::lifecycle::InputId) -> Self {
127        Self(id.to_string())
128    }
129}
130
131#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
132pub struct OperationId(pub String);
133
134impl<T: Into<String>> From<T> for OperationId {
135    fn from(s: T) -> Self {
136        Self(s.into())
137    }
138}
139
140impl OperationId {
141    pub fn from_domain(id: &meerkat_core::ops::OperationId) -> Self {
142        Self::from(serde_json::to_string(id).unwrap_or_else(|_| "\"unknown\"".to_string()))
143    }
144}
145
146#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
147pub struct WaitRequestId(pub String);
148
149impl<T: Into<String>> From<T> for WaitRequestId {
150    fn from(s: T) -> Self {
151        Self(s.into())
152    }
153}
154
155impl WaitRequestId {
156    pub fn from_domain(id: &meerkat_core::lifecycle::WaitRequestId) -> Self {
157        Self(id.to_string())
158    }
159}
160
161/// Typed async-operation kind. Closed mirror of
162/// [`meerkat_core::ops_lifecycle::OperationKind`] — replaces the former
163/// newtype wrapper around an opaque JSON-encoded string. The DSL writes this
164/// variant directly on `RegisterOp` so guards on `PeerReadyOp`
165/// (`kind_is_mob_member_child`) can reason about the closed set without
166/// string parsing. `BackgroundToolCapacitySlot` is a generated shell admission
167/// reservation, not a background job, so completion-feed publication can
168/// distinguish it from `BackgroundToolOp`.
169#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
170pub enum OperationKind {
171    #[default]
172    MobMemberChild,
173    BackgroundToolOp,
174    BackgroundToolCapacitySlot,
175}
176
177#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
178pub enum OperationSourceKind {
179    #[default]
180    SessionChild,
181    BackendPeer,
182}
183
184/// Typed source identity for an async operation. The lifecycle machine stores
185/// this on `RegisterOp` so peer-only operation identity is not reconstructed
186/// from display strings or shell-side labels.
187#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
188pub struct OperationSource {
189    pub kind: OperationSourceKind,
190    pub session_id: Option<SessionId>,
191    pub peer_id: Option<PeerId>,
192    pub address: Option<PeerAddress>,
193}
194
195impl OperationSource {
196    pub fn from_domain(source: &meerkat_core::ops_lifecycle::OperationSource) -> Self {
197        match source {
198            meerkat_core::ops_lifecycle::OperationSource::SessionChild { session_id } => Self {
199                kind: OperationSourceKind::SessionChild,
200                session_id: Some(SessionId::from_domain(session_id)),
201                peer_id: None,
202                address: None,
203            },
204            meerkat_core::ops_lifecycle::OperationSource::BackendPeer { peer_id, address } => {
205                Self {
206                    kind: OperationSourceKind::BackendPeer,
207                    session_id: None,
208                    peer_id: Some(PeerId(peer_id.to_string())),
209                    address: Some(PeerAddress(address.to_string())),
210                }
211            }
212        }
213    }
214
215    pub fn to_domain(&self) -> Result<meerkat_core::ops_lifecycle::OperationSource, String> {
216        match self.kind {
217            OperationSourceKind::SessionChild => {
218                let session_id = self
219                    .session_id
220                    .as_ref()
221                    .ok_or_else(|| "session operation source missing session_id".to_string())?;
222                let session_id = meerkat_core::types::SessionId::parse(&session_id.0)
223                    .map_err(|error| format!("invalid session operation source id: {error}"))?;
224                Ok(meerkat_core::ops_lifecycle::OperationSource::session_child(
225                    session_id,
226                ))
227            }
228            OperationSourceKind::BackendPeer => {
229                let peer_id = self
230                    .peer_id
231                    .as_ref()
232                    .ok_or_else(|| "backend peer operation source missing peer_id".to_string())?;
233                let address = self
234                    .address
235                    .as_ref()
236                    .ok_or_else(|| "backend peer operation source missing address".to_string())?;
237                let peer_id = meerkat_core::comms::PeerId::parse(&peer_id.0).map_err(|error| {
238                    format!("invalid backend peer operation source id: {error}")
239                })?;
240                let address =
241                    meerkat_core::comms::PeerAddress::parse(&address.0).map_err(|error| {
242                        format!("invalid backend peer operation source address: {error}")
243                    })?;
244                Ok(meerkat_core::ops_lifecycle::OperationSource::backend_peer(
245                    peer_id, address,
246                ))
247            }
248        }
249    }
250}
251
252impl From<meerkat_core::ops_lifecycle::OperationKind> for OperationKind {
253    fn from(kind: meerkat_core::ops_lifecycle::OperationKind) -> Self {
254        match kind {
255            meerkat_core::ops_lifecycle::OperationKind::MobMemberChild => Self::MobMemberChild,
256            meerkat_core::ops_lifecycle::OperationKind::BackgroundToolOp => Self::BackgroundToolOp,
257            meerkat_core::ops_lifecycle::OperationKind::BackgroundToolCapacitySlot => {
258                Self::BackgroundToolCapacitySlot
259            }
260        }
261    }
262}
263
264impl From<OperationKind> for meerkat_core::ops_lifecycle::OperationKind {
265    fn from(kind: OperationKind) -> Self {
266        match kind {
267            OperationKind::MobMemberChild => Self::MobMemberChild,
268            OperationKind::BackgroundToolOp => Self::BackgroundToolOp,
269            OperationKind::BackgroundToolCapacitySlot => Self::BackgroundToolCapacitySlot,
270        }
271    }
272}
273
274impl OperationKind {
275    pub fn from_domain(kind: &meerkat_core::ops_lifecycle::OperationKind) -> Self {
276        Self::from(*kind)
277    }
278}
279
280/// Typed mirror of [`meerkat_core::Provider`] for use inside DSL bridging
281/// types. Closed 5-variant enum; the seam carries the discriminant directly
282/// rather than a JSON-encoded string.
283#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
284pub enum Provider {
285    #[default]
286    Anthropic,
287    OpenAI,
288    Gemini,
289    SelfHosted,
290    Other,
291}
292
293impl From<meerkat_core::provider::Provider> for Provider {
294    fn from(p: meerkat_core::provider::Provider) -> Self {
295        match p {
296            meerkat_core::provider::Provider::Anthropic => Self::Anthropic,
297            meerkat_core::provider::Provider::OpenAI => Self::OpenAI,
298            meerkat_core::provider::Provider::Gemini => Self::Gemini,
299            meerkat_core::provider::Provider::SelfHosted => Self::SelfHosted,
300            meerkat_core::provider::Provider::Other => Self::Other,
301        }
302    }
303}
304
305impl From<Provider> for meerkat_core::provider::Provider {
306    fn from(p: Provider) -> Self {
307        match p {
308            Provider::Anthropic => Self::Anthropic,
309            Provider::OpenAI => Self::OpenAI,
310            Provider::Gemini => Self::Gemini,
311            Provider::SelfHosted => Self::SelfHosted,
312            Provider::Other => Self::Other,
313        }
314    }
315}
316
317/// Typed mirror of [`meerkat_core::AuthBindingRef`] — structural string
318/// projection carrying the flat forms of `realm` / `binding` / `profile`
319/// with bidirectional `From`.
320///
321/// The DSL layer keeps string fields because this mirror is the
322/// DSL-layer identity carrier (used inside runtime-owned guards /
323/// transitions where slug validation has already happened at the
324/// boundary). Domain-side `AuthBindingRef` carries the typed atoms
325/// (`RealmId` / `BindingId` / `ProfileId`).
326#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
327pub struct AuthBindingRef {
328    pub realm_id: String,
329    pub binding_id: String,
330    pub profile_id: Option<String>,
331}
332
333impl From<&meerkat_core::AuthBindingRef> for AuthBindingRef {
334    fn from(r: &meerkat_core::AuthBindingRef) -> Self {
335        Self {
336            realm_id: r.realm.as_str().to_owned(),
337            binding_id: r.binding.as_str().to_owned(),
338            profile_id: r.profile.as_ref().map(|p| p.as_str().to_owned()),
339        }
340    }
341}
342
343/// Fallible conversion — DSL-layer flat strings may be slug-invalid
344/// (the DSL mirror intentionally accepts opaque strings to survive
345/// deserialization drift across schema versions), so lifting back to
346/// the typed-atom domain form may reject.
347impl TryFrom<AuthBindingRef> for meerkat_core::AuthBindingRef {
348    type Error = meerkat_core::IdentityError;
349
350    fn try_from(r: AuthBindingRef) -> Result<Self, Self::Error> {
351        Ok(Self {
352            realm: meerkat_core::RealmId::parse(&r.realm_id)?,
353            binding: meerkat_core::BindingId::parse(&r.binding_id)?,
354            profile: r
355                .profile_id
356                .as_deref()
357                .map(meerkat_core::ProfileId::parse)
358                .transpose()?,
359            origin: meerkat_core::connection::BindingOrigin::Configured,
360        })
361    }
362}
363
364/// Typed mirror of [`meerkat_core::SessionLlmIdentity`] — structural field
365/// projection with typed `Provider` and `AuthBindingRef` mirrors. The
366/// `provider_params` payload is a legitimately open-set `serde_json::Value`
367/// at the persistence boundary (arbitrary provider-specific options), so it
368/// rides on a stable JSON-serialization field inside the DSL — never parsed
369/// back as a discriminant inside any guard or transition.
370#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
371pub struct SessionLlmIdentity {
372    pub model: String,
373    pub provider: Provider,
374    pub self_hosted_server_id: Option<String>,
375    /// Stable JSON serialization of the open-set `provider_params` payload.
376    /// Carried as an opaque identity token; DSL guards never inspect its
377    /// content. Boundary-legitimate per the dogma round-4 brief's
378    /// "variable JSON payload" carve-out applied at field granularity.
379    pub provider_params_repr: Option<String>,
380    pub auth_binding: Option<AuthBindingRef>,
381}
382
383impl SessionLlmIdentity {
384    pub fn from_domain(id: &meerkat_core::SessionLlmIdentity) -> Self {
385        Self {
386            model: id.model.clone(),
387            provider: Provider::from(id.provider),
388            self_hosted_server_id: id.self_hosted_server_id.clone(),
389            provider_params_repr: id
390                .provider_params
391                .as_ref()
392                .map(|v| serde_json::to_string(v).unwrap_or_default()),
393            auth_binding: id.auth_binding.as_ref().map(AuthBindingRef::from),
394        }
395    }
396}
397
398impl TryFrom<SessionLlmIdentity> for meerkat_core::SessionLlmIdentity {
399    type Error = String;
400
401    fn try_from(id: SessionLlmIdentity) -> Result<Self, Self::Error> {
402        Ok(Self {
403            model: id.model,
404            provider: id.provider.into(),
405            self_hosted_server_id: id.self_hosted_server_id,
406            provider_params: id
407                .provider_params_repr
408                .as_deref()
409                .map(serde_json::from_str)
410                .transpose()
411                .map_err(|err| format!("invalid generated provider_params identity: {err}"))?,
412            auth_binding: id
413                .auth_binding
414                .map(meerkat_core::AuthBindingRef::try_from)
415                .transpose()
416                .map_err(|err| format!("invalid generated auth binding identity: {err}"))?,
417        })
418    }
419}
420
421/// Typed mirror of [`meerkat_core::SessionToolVisibilityState`] —
422/// structural projection using typed `ToolFilter` / `ToolVisibilityWitness`
423/// mirrors plus ordered name sets for deterministic Ord/Hash.
424#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
425pub struct SessionToolVisibilityState {
426    pub capability_base_filter: ToolFilter,
427    pub inherited_base_filter: ToolFilter,
428    pub active_filter: ToolFilter,
429    pub staged_filter: ToolFilter,
430    pub active_requested_deferred_names: std::collections::BTreeSet<ToolName>,
431    pub staged_requested_deferred_names: std::collections::BTreeSet<ToolName>,
432    pub active_revision: u64,
433    pub staged_revision: u64,
434    pub requested_witnesses: std::collections::BTreeMap<ToolName, ToolVisibilityWitness>,
435    pub filter_witnesses: std::collections::BTreeMap<ToolName, ToolVisibilityWitness>,
436}
437
438impl SessionToolVisibilityState {
439    pub fn from_domain(id: &meerkat_core::SessionToolVisibilityState) -> Self {
440        Self {
441            capability_base_filter: ToolFilter::from(&id.capability_base_filter),
442            inherited_base_filter: ToolFilter::from(&id.inherited_base_filter),
443            active_filter: ToolFilter::from(&id.active_filter),
444            staged_filter: ToolFilter::from(&id.staged_filter),
445            active_requested_deferred_names: id.active_requested_deferred_names.clone(),
446            staged_requested_deferred_names: id.staged_requested_deferred_names.clone(),
447            active_revision: id.active_revision,
448            staged_revision: id.staged_revision,
449            requested_witnesses: id
450                .requested_witnesses
451                .iter()
452                .map(|(k, w)| (k.clone(), ToolVisibilityWitness::from(w)))
453                .collect(),
454            filter_witnesses: id
455                .filter_witnesses
456                .iter()
457                .map(|(k, w)| (k.clone(), ToolVisibilityWitness::from(w)))
458                .collect(),
459        }
460    }
461}
462
463/// Typed mirror of
464/// [`crate::meerkat_machine_types::SessionLlmCapabilitySurface`] — structural
465/// projection of the boolean capability matrix plus optional call timeout.
466#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
467pub struct SessionLlmCapabilitySurface {
468    pub supports_temperature: bool,
469    pub supports_thinking: bool,
470    pub supports_reasoning: bool,
471    pub inline_video: bool,
472    pub vision: bool,
473    pub image_input: bool,
474    pub image_tool_results: bool,
475    pub supports_web_search: bool,
476    pub image_generation: bool,
477    pub realtime: bool,
478    pub call_timeout_secs: Option<u64>,
479}
480
481impl From<&crate::meerkat_machine_types::SessionLlmCapabilitySurface>
482    for SessionLlmCapabilitySurface
483{
484    fn from(s: &crate::meerkat_machine_types::SessionLlmCapabilitySurface) -> Self {
485        Self {
486            supports_temperature: s.supports_temperature,
487            supports_thinking: s.supports_thinking,
488            supports_reasoning: s.supports_reasoning,
489            inline_video: s.inline_video,
490            vision: s.vision,
491            image_input: s.image_input,
492            image_tool_results: s.image_tool_results,
493            supports_web_search: s.supports_web_search,
494            image_generation: s.image_generation,
495            realtime: s.realtime,
496            call_timeout_secs: s.call_timeout_secs,
497        }
498    }
499}
500
501impl From<SessionLlmCapabilitySurface>
502    for crate::meerkat_machine_types::SessionLlmCapabilitySurface
503{
504    fn from(s: SessionLlmCapabilitySurface) -> Self {
505        Self {
506            supports_temperature: s.supports_temperature,
507            supports_thinking: s.supports_thinking,
508            supports_reasoning: s.supports_reasoning,
509            inline_video: s.inline_video,
510            vision: s.vision,
511            image_input: s.image_input,
512            image_tool_results: s.image_tool_results,
513            supports_web_search: s.supports_web_search,
514            image_generation: s.image_generation,
515            realtime: s.realtime,
516            call_timeout_secs: s.call_timeout_secs,
517        }
518    }
519}
520
521impl SessionLlmCapabilitySurface {
522    pub fn from_domain(id: &crate::meerkat_machine_types::SessionLlmCapabilitySurface) -> Self {
523        Self::from(id)
524    }
525}
526
527/// Typed capability-surface resolution status. Closed mirror of
528/// [`crate::meerkat_machine_types::SessionLlmCapabilitySurfaceStatus`] —
529/// replaces the former JSON-stringified wrapper the DSL used to carry the
530/// two-state discriminant across the seam.
531///
532/// The DSL stores the variant directly on `ReconfigureSessionLlmIdentity`
533/// flow state; the shell maps to/from the domain enum via the `From` impls
534/// below — no `serde_json::to_string`, no string compares.
535#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
536pub enum SessionLlmCapabilitySurfaceStatus {
537    Resolved,
538    #[default]
539    Unresolved,
540}
541
542impl From<crate::meerkat_machine_types::SessionLlmCapabilitySurfaceStatus>
543    for SessionLlmCapabilitySurfaceStatus
544{
545    fn from(status: crate::meerkat_machine_types::SessionLlmCapabilitySurfaceStatus) -> Self {
546        match status {
547            crate::meerkat_machine_types::SessionLlmCapabilitySurfaceStatus::Resolved => {
548                Self::Resolved
549            }
550            crate::meerkat_machine_types::SessionLlmCapabilitySurfaceStatus::Unresolved => {
551                Self::Unresolved
552            }
553        }
554    }
555}
556
557impl From<SessionLlmCapabilitySurfaceStatus>
558    for crate::meerkat_machine_types::SessionLlmCapabilitySurfaceStatus
559{
560    fn from(status: SessionLlmCapabilitySurfaceStatus) -> Self {
561        match status {
562            SessionLlmCapabilitySurfaceStatus::Resolved => Self::Resolved,
563            SessionLlmCapabilitySurfaceStatus::Unresolved => Self::Unresolved,
564        }
565    }
566}
567
568impl SessionLlmCapabilitySurfaceStatus {
569    pub fn from_domain(
570        id: &crate::meerkat_machine_types::SessionLlmCapabilitySurfaceStatus,
571    ) -> Self {
572        Self::from(*id)
573    }
574}
575
576/// Typed mirror of
577/// [`crate::meerkat_machine_types::SessionToolVisibilityDelta`] — structural
578/// projection using typed `ToolFilter` mirrors plus the two boolean change
579/// flags. Replaces the former `format!("{id:?}")` Debug-stringified wrapper.
580#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
581pub struct SessionToolVisibilityDelta {
582    pub previous_capability_base_filter: ToolFilter,
583    pub current_capability_base_filter: ToolFilter,
584    pub committed_visible_set_changed: bool,
585    pub revision_bumped: bool,
586}
587
588impl SessionToolVisibilityDelta {
589    pub fn from_domain(id: &crate::meerkat_machine_types::SessionToolVisibilityDelta) -> Self {
590        Self {
591            previous_capability_base_filter: ToolFilter::from(&id.previous_capability_base_filter),
592            current_capability_base_filter: ToolFilter::from(&id.current_capability_base_filter),
593            committed_visible_set_changed: id.committed_visible_set_changed,
594            revision_bumped: id.revision_bumped,
595        }
596    }
597}
598
599/// Canonical typed tool identity. This IS the domain type —
600/// [`meerkat_core::types::ToolName`] — carried directly through the machine
601/// (K8a fold: the tool-visibility name domain is `ToolName`-keyed end to end;
602/// no stringly bridge inside the machine).
603pub type ToolName = meerkat_core::types::ToolName;
604
605/// Typed mirror of [`meerkat_core::ToolFilter`] — closed 3-variant
606/// discriminant with a `BTreeSet<ToolName>` name payload for
607/// `Allow`/`Deny` so the value is `Ord + Hash` and deterministic across
608/// iteration, matching the R3 `InputAbandonReason::MaxAttemptsExhausted {
609/// attempts }` pattern of carrying the discriminant's companion data in a
610/// field with stable ordering.
611#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
612pub enum ToolFilter {
613    #[default]
614    All,
615    Allow(std::collections::BTreeSet<ToolName>),
616    Deny(std::collections::BTreeSet<ToolName>),
617}
618
619impl From<&meerkat_core::ToolFilter> for ToolFilter {
620    fn from(f: &meerkat_core::ToolFilter) -> Self {
621        match f {
622            meerkat_core::ToolFilter::All => Self::All,
623            meerkat_core::ToolFilter::Allow(names) => Self::Allow(names.iter().cloned().collect()),
624            meerkat_core::ToolFilter::Deny(names) => Self::Deny(names.iter().cloned().collect()),
625        }
626    }
627}
628
629impl From<ToolFilter> for meerkat_core::ToolFilter {
630    fn from(f: ToolFilter) -> Self {
631        match f {
632            ToolFilter::All => Self::All,
633            ToolFilter::Allow(names) => Self::Allow(names.into_iter().collect()),
634            ToolFilter::Deny(names) => Self::Deny(names.into_iter().collect()),
635        }
636    }
637}
638
639impl ToolFilter {
640    pub fn from_domain(id: &meerkat_core::ToolFilter) -> Self {
641        Self::from(id)
642    }
643}
644
645/// Typed mirror of [`meerkat_core::types::ToolSourceKind`] — closed
646/// Closed discriminant for tool provenance classification.
647#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
648pub enum ToolSourceKind {
649    #[default]
650    Builtin,
651    Shell,
652    Comms,
653    Memory,
654    Schedule,
655    WorkGraph,
656    Mob,
657    Callback,
658    Mcp,
659    RustBundle,
660}
661
662impl From<&meerkat_core::types::ToolSourceKind> for ToolSourceKind {
663    fn from(k: &meerkat_core::types::ToolSourceKind) -> Self {
664        match k {
665            meerkat_core::types::ToolSourceKind::Builtin => Self::Builtin,
666            meerkat_core::types::ToolSourceKind::Shell => Self::Shell,
667            meerkat_core::types::ToolSourceKind::Comms => Self::Comms,
668            meerkat_core::types::ToolSourceKind::Memory => Self::Memory,
669            meerkat_core::types::ToolSourceKind::Schedule => Self::Schedule,
670            meerkat_core::types::ToolSourceKind::WorkGraph => Self::WorkGraph,
671            meerkat_core::types::ToolSourceKind::Mob => Self::Mob,
672            meerkat_core::types::ToolSourceKind::Callback => Self::Callback,
673            meerkat_core::types::ToolSourceKind::Mcp => Self::Mcp,
674            meerkat_core::types::ToolSourceKind::RustBundle => Self::RustBundle,
675        }
676    }
677}
678
679/// Typed mirror of [`meerkat_core::types::ToolProvenance`] — structural
680/// projection carried inside [`ToolVisibilityWitness`], using the typed
681/// `ToolSourceKind` discriminant mirror.
682#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
683pub struct ToolProvenance {
684    pub kind: ToolSourceKind,
685    pub source_id: String,
686}
687
688impl From<&meerkat_core::types::ToolProvenance> for ToolProvenance {
689    fn from(p: &meerkat_core::types::ToolProvenance) -> Self {
690        Self {
691            kind: ToolSourceKind::from(&p.kind),
692            source_id: p.source_id.to_string(),
693        }
694    }
695}
696
697/// Typed mirror of [`meerkat_core::ToolVisibilityWitness`] — structural
698/// projection of the two optional witness fields.
699#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
700pub struct ToolVisibilityWitness {
701    pub last_seen_provenance: Option<ToolProvenance>,
702}
703
704impl From<&meerkat_core::ToolVisibilityWitness> for ToolVisibilityWitness {
705    fn from(w: &meerkat_core::ToolVisibilityWitness) -> Self {
706        Self {
707            last_seen_provenance: w.last_seen_provenance.as_ref().map(ToolProvenance::from),
708        }
709    }
710}
711
712impl ToolVisibilityWitness {
713    pub fn from_domain(id: &meerkat_core::ToolVisibilityWitness) -> Self {
714        Self::from(id)
715    }
716
717    fn len(&self) -> u64 {
718        u64::from(self.last_seen_provenance.is_some())
719    }
720}
721
722/// Bridging type for an MCP server identifier, matching the catalog type.
723/// Used as the key in `mcp_server_states` and carried on MCP lifecycle
724/// inputs and effects.
725#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
726pub struct McpServerId(pub String);
727
728impl<T: Into<String>> From<T> for McpServerId {
729    fn from(s: T) -> Self {
730        Self(s.into())
731    }
732}
733
734/// Bridging wrapper mapping [`meerkat_core::PeerCorrelationId`] into the DSL
735/// macro's type system. Keyed map values for `pending_peer_requests` and
736/// `inbound_peer_requests`; carried on every W1-A peer-lifecycle input and
737/// effect.
738#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
739pub struct PeerCorrelationId(pub String);
740
741impl From<meerkat_core::PeerCorrelationId> for PeerCorrelationId {
742    fn from(id: meerkat_core::PeerCorrelationId) -> Self {
743        Self(id.0.to_string())
744    }
745}
746
747impl From<uuid::Uuid> for PeerCorrelationId {
748    fn from(id: uuid::Uuid) -> Self {
749        Self(id.to_string())
750    }
751}
752
753impl From<String> for PeerCorrelationId {
754    fn from(s: String) -> Self {
755        Self(s)
756    }
757}
758
759impl From<&str> for PeerCorrelationId {
760    fn from(s: &str) -> Self {
761        Self(s.to_string())
762    }
763}
764
765/// Typed outbound peer-request state, mirroring
766/// [`meerkat_core::OutboundPeerRequestState`]. Unit variants only; failure
767/// reason travels on the `PeerResponseTerminalArrived` input's companion
768/// fields, not in the enum.
769#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
770pub enum OutboundPeerRequestState {
771    #[default]
772    Sent,
773    AcceptedProgress,
774    Completed,
775    Failed,
776    TimedOut,
777}
778
779impl From<meerkat_core::OutboundPeerRequestState> for OutboundPeerRequestState {
780    #[allow(clippy::panic)]
781    fn from(s: meerkat_core::OutboundPeerRequestState) -> Self {
782        match s {
783            meerkat_core::OutboundPeerRequestState::Sent => Self::Sent,
784            meerkat_core::OutboundPeerRequestState::AcceptedProgress => Self::AcceptedProgress,
785            meerkat_core::OutboundPeerRequestState::Completed => Self::Completed,
786            meerkat_core::OutboundPeerRequestState::Failed => Self::Failed,
787            meerkat_core::OutboundPeerRequestState::TimedOut => Self::TimedOut,
788            _ => panic!(
789                "unsupported OutboundPeerRequestState variant; update generated MeerkatMachine mirror"
790            ),
791        }
792    }
793}
794
795impl From<OutboundPeerRequestState> for meerkat_core::OutboundPeerRequestState {
796    fn from(s: OutboundPeerRequestState) -> Self {
797        match s {
798            OutboundPeerRequestState::Sent => Self::Sent,
799            OutboundPeerRequestState::AcceptedProgress => Self::AcceptedProgress,
800            OutboundPeerRequestState::Completed => Self::Completed,
801            OutboundPeerRequestState::Failed => Self::Failed,
802            OutboundPeerRequestState::TimedOut => Self::TimedOut,
803        }
804    }
805}
806
807/// Typed inbound peer-request state, mirroring
808/// [`meerkat_core::InboundPeerRequestState`].
809#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
810pub enum InboundPeerRequestState {
811    #[default]
812    Received,
813    Replied,
814}
815
816impl From<meerkat_core::InboundPeerRequestState> for InboundPeerRequestState {
817    #[allow(clippy::panic)]
818    fn from(s: meerkat_core::InboundPeerRequestState) -> Self {
819        match s {
820            meerkat_core::InboundPeerRequestState::Received => Self::Received,
821            meerkat_core::InboundPeerRequestState::Replied => Self::Replied,
822            _ => panic!(
823                "unsupported InboundPeerRequestState variant; update generated MeerkatMachine mirror"
824            ),
825        }
826    }
827}
828
829impl From<InboundPeerRequestState> for meerkat_core::InboundPeerRequestState {
830    fn from(s: InboundPeerRequestState) -> Self {
831        match s {
832            InboundPeerRequestState::Received => Self::Received,
833            InboundPeerRequestState::Replied => Self::Replied,
834        }
835    }
836}
837
838/// Typed terminal disposition carried on `PeerResponseTerminalArrived`.
839/// Mirror of [`meerkat_core::handles::PeerTerminalDisposition`].
840#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
841pub enum PeerTerminalDisposition {
842    #[default]
843    Completed,
844    Failed,
845}
846
847impl From<meerkat_core::handles::PeerTerminalDisposition> for PeerTerminalDisposition {
848    #[allow(clippy::panic)]
849    fn from(d: meerkat_core::handles::PeerTerminalDisposition) -> Self {
850        match d {
851            meerkat_core::handles::PeerTerminalDisposition::Completed => Self::Completed,
852            meerkat_core::handles::PeerTerminalDisposition::Failed => Self::Failed,
853            _ => panic!(
854                "unsupported PeerTerminalDisposition variant; update generated MeerkatMachine mirror"
855            ),
856        }
857    }
858}
859
860/// Typed lifecycle state of an interaction stream reservation (U6 / dogma #5).
861///
862/// Owns whether a reserved subscriber/stream channel is still claimable
863/// (`Reserved`), live with an attached consumer (`Attached`), or terminal
864/// (`Completed` after a terminal event won, `Expired` after the TTL elapsed
865/// without an attach, `ClosedEarly` after the consumer dropped the stream
866/// before terminal, `Abandoned` after an explicit typed failure). Mirror of
867/// [`meerkat_core::InteractionStreamState`].
868#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
869pub enum InteractionStreamState {
870    #[default]
871    Reserved,
872    Attached,
873    Completed,
874    Expired,
875    ClosedEarly,
876    Abandoned,
877}
878
879impl From<meerkat_core::InteractionStreamState> for InteractionStreamState {
880    #[allow(clippy::panic)]
881    fn from(s: meerkat_core::InteractionStreamState) -> Self {
882        match s {
883            meerkat_core::InteractionStreamState::Reserved => Self::Reserved,
884            meerkat_core::InteractionStreamState::Attached => Self::Attached,
885            meerkat_core::InteractionStreamState::Completed => Self::Completed,
886            meerkat_core::InteractionStreamState::Expired => Self::Expired,
887            meerkat_core::InteractionStreamState::ClosedEarly => Self::ClosedEarly,
888            meerkat_core::InteractionStreamState::Abandoned => Self::Abandoned,
889            _ => panic!(
890                "unsupported InteractionStreamState variant; update generated MeerkatMachine mirror"
891            ),
892        }
893    }
894}
895
896impl From<InteractionStreamState> for meerkat_core::InteractionStreamState {
897    fn from(s: InteractionStreamState) -> Self {
898        match s {
899            InteractionStreamState::Reserved => Self::Reserved,
900            InteractionStreamState::Attached => Self::Attached,
901            InteractionStreamState::Completed => Self::Completed,
902            InteractionStreamState::Expired => Self::Expired,
903            InteractionStreamState::ClosedEarly => Self::ClosedEarly,
904            InteractionStreamState::Abandoned => Self::Abandoned,
905        }
906    }
907}
908
909/// Typed reason carried by `InteractionStreamAbandoned`.
910#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
911pub enum InteractionStreamAbandonReason {
912    #[default]
913    SendFailed,
914    AdmissionRejected,
915    ResponseRejected,
916    TerminalDeliveryFailed,
917}
918
919impl From<meerkat_core::InteractionStreamAbandonReason> for InteractionStreamAbandonReason {
920    #[allow(clippy::panic)]
921    fn from(reason: meerkat_core::InteractionStreamAbandonReason) -> Self {
922        match reason {
923            meerkat_core::InteractionStreamAbandonReason::SendFailed => Self::SendFailed,
924            meerkat_core::InteractionStreamAbandonReason::AdmissionRejected => {
925                Self::AdmissionRejected
926            }
927            meerkat_core::InteractionStreamAbandonReason::ResponseRejected => {
928                Self::ResponseRejected
929            }
930            meerkat_core::InteractionStreamAbandonReason::TerminalDeliveryFailed => {
931                Self::TerminalDeliveryFailed
932            }
933            _ => panic!(
934                "unsupported InteractionStreamAbandonReason variant; update generated MeerkatMachine mirror"
935            ),
936        }
937    }
938}
939
940impl From<InteractionStreamAbandonReason> for meerkat_core::InteractionStreamAbandonReason {
941    fn from(reason: InteractionStreamAbandonReason) -> Self {
942        match reason {
943            InteractionStreamAbandonReason::SendFailed => Self::SendFailed,
944            InteractionStreamAbandonReason::AdmissionRejected => Self::AdmissionRejected,
945            InteractionStreamAbandonReason::ResponseRejected => Self::ResponseRejected,
946            InteractionStreamAbandonReason::TerminalDeliveryFailed => Self::TerminalDeliveryFailed,
947        }
948    }
949}
950
951/// Per-server MCP connection lifecycle state. Matches the catalog copy;
952/// unit variants only so the DSL can reason about state via map inserts.
953/// Failure detail travels on the `McpServerFailed` input and
954/// `McpServerStateChanged` effect's companion fields, not on the enum.
955#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
956pub enum McpServerState {
957    #[default]
958    PendingConnect,
959    Connected,
960    Failed,
961    Disconnected,
962}
963
964/// Stable identity of a comms runtime instance (W2-G / issue #264).
965///
966/// The runtime derives this string from the `Arc<dyn CommsRuntime>` pointer
967/// address via `CommsRuntimeId::from_runtime()`. The DSL treats it as an
968/// opaque newtype; two distinct `Arc`s produce distinct ids so the owner
969/// invariant can catch silent transport swaps.
970#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
971pub struct CommsRuntimeId(pub String);
972
973impl<T: Into<String>> From<T> for CommsRuntimeId {
974    fn from(s: T) -> Self {
975        Self(s.into())
976    }
977}
978
979impl CommsRuntimeId {
980    /// Derive a stable id from an `Arc<dyn CommsRuntime>`'s pointer address.
981    ///
982    /// Two `Arc` instances with the same pointee produce the same id; two
983    /// distinct `Arc` instances produce distinct ids even if their contents
984    /// are equivalent. This is sufficient for detecting silent transport
985    /// swaps at the DSL boundary.
986    pub fn from_runtime(runtime: &std::sync::Arc<dyn meerkat_core::agent::CommsRuntime>) -> Self {
987        let ptr = std::sync::Arc::as_ptr(runtime).cast::<()>() as usize;
988        Self(format!("comms-runtime-0x{ptr:x}"))
989    }
990}
991
992/// Mob instance identifier for peer-ingress ownership (W2-G / issue #264).
993///
994/// Bridging newtype mirroring `meerkat_mob::ids::MobId`. The DSL layer keeps
995/// this opaque because `meerkat-runtime` does not depend on `meerkat-mob`;
996/// the shell stringifies the real `MobId` before firing `AttachMobIngress`.
997#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
998pub struct MobId(pub String);
999
1000impl<T: Into<String>> From<T> for MobId {
1001    fn from(s: T) -> Self {
1002        Self(s.into())
1003    }
1004}
1005
1006/// Parsed transport envelope class for peer ingress.
1007///
1008/// This is the mechanical shape comms may derive from a wire envelope before
1009/// semantic admission. The DSL consumes it to own the peer-input class,
1010/// auth-exemption, lifecycle, silent-routing, and response-terminal facts.
1011#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1012pub enum PeerIngressEnvelopeClass {
1013    #[default]
1014    Message,
1015    Request,
1016    Lifecycle,
1017    Response,
1018    Ack,
1019}
1020
1021/// DSL-owned admitted ingress kind.
1022#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1023pub enum PeerIngressAdmittedKind {
1024    #[default]
1025    Message,
1026    Request,
1027    Response,
1028    Ack,
1029    PlainEvent,
1030}
1031
1032/// DSL-owned peer input class.
1033#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1034pub enum PeerIngressInputClass {
1035    #[default]
1036    ActionableMessage,
1037    ActionableRequest,
1038    ResponseProgress,
1039    ResponseTerminal,
1040    PeerLifecycleAdded,
1041    PeerLifecycleRetired,
1042    PeerLifecycleUnwired,
1043    SilentRequest,
1044    Ack,
1045    PlainEvent,
1046}
1047
1048/// DSL-owned peer lifecycle classifier.
1049#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1050pub enum PeerIngressLifecycleClass {
1051    #[default]
1052    PeerAdded,
1053    PeerRetired,
1054    PeerUnwired,
1055}
1056
1057/// DSL-owned peer ingress auth classifier.
1058#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1059pub enum PeerIngressAuthClass {
1060    #[default]
1061    Required,
1062    SupervisorBridgeExempt,
1063}
1064
1065/// Parsed response status for peer ingress.
1066#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1067pub enum PeerIngressResponseStatus {
1068    #[default]
1069    Accepted,
1070    Completed,
1071    Failed,
1072}
1073
1074/// Closed classifier for peer-ingress request intents that drive fixed
1075/// lifecycle routing (mob peer add/retire/unwire) plus the supervisor-bridge
1076/// channel. The machine guards on this typed class; arbitrary user-configured
1077/// silent intents remain an open set matched against the raw `request_intent`
1078/// string via `silent_intent_overrides`, so `Other` covers everything outside
1079/// the closed routing set.
1080#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1081pub enum PeerIngressRequestClass {
1082    #[default]
1083    Other,
1084    MobPeerAdded,
1085    MobPeerRetired,
1086    MobPeerUnwired,
1087    SupervisorBridge,
1088}
1089
1090/// DSL-owned response progress/terminal classifier.
1091#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1092pub enum PeerIngressResponseTerminality {
1093    #[default]
1094    Progress,
1095    TerminalCompleted,
1096    TerminalFailed,
1097}
1098
1099/// DSL-owned public peer-ingress authority phase.
1100#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1101pub enum PeerIngressAuthorityPhaseClass {
1102    #[default]
1103    Absent,
1104    Received,
1105    Dropped,
1106    Delivered,
1107}
1108
1109impl From<PeerIngressAuthorityPhaseClass> for meerkat_core::PeerIngressAuthorityPhase {
1110    fn from(phase: PeerIngressAuthorityPhaseClass) -> Self {
1111        match phase {
1112            PeerIngressAuthorityPhaseClass::Absent => Self::Absent,
1113            PeerIngressAuthorityPhaseClass::Received => Self::Received,
1114            PeerIngressAuthorityPhaseClass::Dropped => Self::Dropped,
1115            PeerIngressAuthorityPhaseClass::Delivered => Self::Delivered,
1116        }
1117    }
1118}
1119
1120/// DSL-owned receive/admission result for classified peer ingress.
1121#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1122pub enum PeerIngressReceiveOutcomeClass {
1123    #[default]
1124    Admitted,
1125    DroppedUntrustedSender,
1126    DroppedSessionClosed,
1127    DroppedInboxFull,
1128}
1129
1130impl From<PeerIngressReceiveOutcomeClass> for meerkat_core::PeerIngressReceiveOutcome {
1131    fn from(outcome: PeerIngressReceiveOutcomeClass) -> Self {
1132        match outcome {
1133            PeerIngressReceiveOutcomeClass::Admitted => Self::Admitted,
1134            PeerIngressReceiveOutcomeClass::DroppedUntrustedSender => Self::DroppedUntrustedSender,
1135            PeerIngressReceiveOutcomeClass::DroppedSessionClosed => Self::DroppedSessionClosed,
1136            PeerIngressReceiveOutcomeClass::DroppedInboxFull => Self::DroppedInboxFull,
1137        }
1138    }
1139}
1140
1141/// DSL-owned admission diagnostic copy emitted with receive authority.
1142#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1143pub enum PeerIngressAdmissionDiagnosticClass {
1144    #[default]
1145    TrustedAtAdmission,
1146    UntrustedAtAdmission,
1147}
1148
1149impl From<PeerIngressAdmissionDiagnosticClass> for meerkat_core::PeerIngressAdmissionDiagnostic {
1150    fn from(diagnostic: PeerIngressAdmissionDiagnosticClass) -> Self {
1151        match diagnostic {
1152            PeerIngressAdmissionDiagnosticClass::TrustedAtAdmission => Self::TrustedAtAdmission,
1153            PeerIngressAdmissionDiagnosticClass::UntrustedAtAdmission => Self::UntrustedAtAdmission,
1154        }
1155    }
1156}
1157
1158/// Peer-ingress transport capability ownership kind (W2-G / issue #264).
1159///
1160/// Paired with `peer_ingress_comms_runtime_id` and `peer_ingress_mob_id` in
1161/// DSL state; `peer_ingress_owner_consistency` enforces pairing. Silent
1162/// downgrade `MobOwned` → `SessionOwned` is structurally impossible:
1163/// `AttachSessionIngress` requires `Unattached`; `AttachMobIngress` permits
1164/// `Unattached` or `SessionOwned` but never `MobOwned` → `SessionOwned`.
1165#[derive(
1166    Debug,
1167    Clone,
1168    Copy,
1169    PartialEq,
1170    Eq,
1171    PartialOrd,
1172    Ord,
1173    Hash,
1174    Default,
1175    serde::Serialize,
1176    serde::Deserialize,
1177)]
1178pub enum PeerIngressOwnerKind {
1179    #[default]
1180    Unattached,
1181    SessionOwned,
1182    MobOwned,
1183}
1184
1185/// Supervisor-bridge authorization kind (Wave 3 D Row 21).
1186///
1187/// Paired with `supervisor_bound_{name, peer_id, address, epoch}` in DSL
1188/// state; `supervisor_binding_consistency` enforces pairing. Rotation is
1189/// structural: `BindSupervisor` requires `Unbound`; `AuthorizeSupervisor`
1190/// requires `Bound`; `RevokeSupervisor` requires `Bound` and returns to
1191/// `Unbound`. Before Wave 3 D this fact lived as an `Option<AuthorizedSupervisorState>`
1192/// on the comms drain task's stack — the identity and epoch of the
1193/// authorized supervisor were helper-local while the corresponding trust
1194/// edge was router-owned. Moving the authorization discriminant + epoch
1195/// into DSL state collapses that split ownership.
1196#[derive(
1197    Debug,
1198    Clone,
1199    Copy,
1200    PartialEq,
1201    Eq,
1202    PartialOrd,
1203    Ord,
1204    Hash,
1205    Default,
1206    serde::Serialize,
1207    serde::Deserialize,
1208)]
1209pub enum SupervisorBindingKind {
1210    #[default]
1211    Unbound,
1212    Bound,
1213}
1214
1215/// Typed turn-execution phase, mirrored 1:1 by the closed set of literals the
1216/// DSL transitions assign to `turn_phase`. Replaces the prior stringly-typed
1217/// encoding so the ephemeral driver and runtime handles consume an exhaustive
1218/// enum instead of parsing folklore.
1219#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1220pub enum TurnPhase {
1221    #[default]
1222    Ready,
1223    ApplyingPrimitive,
1224    CallingLlm,
1225    WaitingForOps,
1226    DrainingBoundary,
1227    Extracting,
1228    ErrorRecovery,
1229    Cancelling,
1230    Completed,
1231    Failed,
1232    Cancelled,
1233}
1234
1235impl TurnPhase {
1236    pub const fn as_str(self) -> &'static str {
1237        match self {
1238            Self::Ready => "Ready",
1239            Self::ApplyingPrimitive => "ApplyingPrimitive",
1240            Self::CallingLlm => "CallingLlm",
1241            Self::WaitingForOps => "WaitingForOps",
1242            Self::DrainingBoundary => "DrainingBoundary",
1243            Self::Extracting => "Extracting",
1244            Self::ErrorRecovery => "ErrorRecovery",
1245            Self::Cancelling => "Cancelling",
1246            Self::Completed => "Completed",
1247            Self::Failed => "Failed",
1248            Self::Cancelled => "Cancelled",
1249        }
1250    }
1251}
1252
1253/// Typed registration substate. Closed set of literals previously assigned to
1254/// `registration_phase`.
1255#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1256pub enum RegistrationPhase {
1257    #[default]
1258    Queuing,
1259    Active,
1260    Draining,
1261}
1262
1263impl RegistrationPhase {
1264    pub const fn as_str(self) -> &'static str {
1265        match self {
1266            Self::Queuing => "Queuing",
1267            Self::Active => "Active",
1268            Self::Draining => "Draining",
1269        }
1270    }
1271}
1272
1273/// Typed comms drain substate. Mirrors the closed set of literals the DSL
1274/// transitions assign to `drain_phase`.
1275#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1276pub enum DrainPhase {
1277    #[default]
1278    Inactive,
1279    Running,
1280    Stopped,
1281    ExitedRespawnable,
1282}
1283
1284impl DrainPhase {
1285    pub const fn as_str(self) -> &'static str {
1286        match self {
1287            Self::Inactive => "Inactive",
1288            Self::Running => "Running",
1289            Self::Stopped => "Stopped",
1290            Self::ExitedRespawnable => "ExitedRespawnable",
1291        }
1292    }
1293}
1294
1295/// Typed comms drain mode. Mirrors `crate::meerkat_machine::CommsDrainMode`
1296/// (which is the shell-side enum) so the DSL can hold a closed set of typed
1297/// variants instead of a `Debug`-formatted string.
1298#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1299pub enum DrainMode {
1300    #[default]
1301    Timed,
1302    AttachedSession,
1303    PersistentHost,
1304}
1305
1306impl DrainMode {
1307    pub const fn as_str(self) -> &'static str {
1308        match self {
1309            Self::Timed => "Timed",
1310            Self::AttachedSession => "AttachedSession",
1311            Self::PersistentHost => "PersistentHost",
1312        }
1313    }
1314}
1315
1316impl From<crate::meerkat_machine::CommsDrainMode> for DrainMode {
1317    fn from(mode: crate::meerkat_machine::CommsDrainMode) -> Self {
1318        match mode {
1319            crate::meerkat_machine::CommsDrainMode::Timed => Self::Timed,
1320            crate::meerkat_machine::CommsDrainMode::AttachedSession => Self::AttachedSession,
1321            crate::meerkat_machine::CommsDrainMode::PersistentHost => Self::PersistentHost,
1322        }
1323    }
1324}
1325
1326/// Typed external-tool surface global phase. Closed set of literals previously
1327/// assigned to `surface_phase`.
1328#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1329pub enum SurfacePhase {
1330    #[default]
1331    Operating,
1332    Shutdown,
1333}
1334
1335impl SurfacePhase {
1336    pub const fn as_str(self) -> &'static str {
1337        match self {
1338            Self::Operating => "Operating",
1339            Self::Shutdown => "Shutdown",
1340        }
1341    }
1342}
1343
1344/// Typed input-lifecycle phase, mirroring the closed set of literals the DSL
1345/// transitions assign to `input_phases`. The shell projects from this onto the
1346/// richer `crate::input_state::InputLifecycleState` (which keeps an `Accepted`
1347/// pre-DSL-admission variant the DSL itself never writes).
1348#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1349pub enum InputPhase {
1350    #[default]
1351    Queued,
1352    Staged,
1353    Applied,
1354    AppliedPendingConsumption,
1355    Consumed,
1356    Superseded,
1357    Coalesced,
1358    Abandoned,
1359}
1360
1361impl InputPhase {
1362    pub const fn as_str(self) -> &'static str {
1363        match self {
1364            Self::Queued => "Queued",
1365            Self::Staged => "Staged",
1366            Self::Applied => "Applied",
1367            Self::AppliedPendingConsumption => "AppliedPendingConsumption",
1368            Self::Consumed => "Consumed",
1369            Self::Superseded => "Superseded",
1370            Self::Coalesced => "Coalesced",
1371            Self::Abandoned => "Abandoned",
1372        }
1373    }
1374}
1375
1376#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1377pub enum RecoveredInputObservedPhase {
1378    Accepted,
1379    #[default]
1380    Queued,
1381    Staged,
1382    Applied,
1383    AppliedPendingConsumption,
1384    Consumed,
1385    Superseded,
1386    Coalesced,
1387    Abandoned,
1388}
1389
1390/// Typed input terminal kind, mirroring the closed set of literals the DSL
1391/// transitions assign to `input_terminal_kind`. The companion fields
1392/// (`input_superseded_by`, `input_aggregate_id`, `input_abandon_reason`,
1393/// `input_abandon_attempt_count`) carry payload metadata for variants that
1394/// need it.
1395#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1396pub enum InputTerminalKind {
1397    #[default]
1398    Consumed,
1399    Superseded,
1400    Coalesced,
1401    Abandoned,
1402}
1403
1404impl InputTerminalKind {
1405    pub const fn as_str(self) -> &'static str {
1406        match self {
1407            Self::Consumed => "Consumed",
1408            Self::Superseded => "Superseded",
1409            Self::Coalesced => "Coalesced",
1410            Self::Abandoned => "Abandoned",
1411        }
1412    }
1413}
1414
1415/// Public lifecycle class emitted by generated authority before runtime
1416/// surfaces project input state onto their transport enums.
1417#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1418pub enum InputPublicLifecycleState {
1419    #[default]
1420    Accepted,
1421    Queued,
1422    Staged,
1423    Applied,
1424    AppliedPendingConsumption,
1425    Consumed,
1426    Superseded,
1427    Coalesced,
1428    Abandoned,
1429}
1430
1431impl InputPublicLifecycleState {
1432    pub const fn as_str(self) -> &'static str {
1433        match self {
1434            Self::Accepted => "Accepted",
1435            Self::Queued => "Queued",
1436            Self::Staged => "Staged",
1437            Self::Applied => "Applied",
1438            Self::AppliedPendingConsumption => "AppliedPendingConsumption",
1439            Self::Consumed => "Consumed",
1440            Self::Superseded => "Superseded",
1441            Self::Coalesced => "Coalesced",
1442            Self::Abandoned => "Abandoned",
1443        }
1444    }
1445}
1446
1447/// Public terminal result class emitted by generated authority before runtime
1448/// surfaces project input state onto their transport enums.
1449#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1450pub enum InputPublicTerminalOutcome {
1451    #[default]
1452    Completed,
1453    Abandoned,
1454    Superseded,
1455    Coalesced,
1456    Cancelled,
1457}
1458
1459impl InputPublicTerminalOutcome {
1460    pub const fn as_str(self) -> &'static str {
1461        match self {
1462            Self::Completed => "Completed",
1463            Self::Abandoned => "Abandoned",
1464            Self::Superseded => "Superseded",
1465            Self::Coalesced => "Coalesced",
1466            Self::Cancelled => "Cancelled",
1467        }
1468    }
1469}
1470
1471/// Typed pending external-surface op. Closed set of literals previously
1472/// assigned to `surface_pending_op`.
1473#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1474pub enum SurfacePendingOp {
1475    #[default]
1476    None,
1477    Add,
1478    Reload,
1479}
1480
1481impl SurfacePendingOp {
1482    pub const fn as_str(self) -> &'static str {
1483        match self {
1484            Self::None => "None",
1485            Self::Add => "Add",
1486            Self::Reload => "Reload",
1487        }
1488    }
1489}
1490
1491/// Typed staged external-surface op. Closed set of literals previously
1492/// assigned to `surface_staged_op`.
1493#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1494pub enum SurfaceStagedOp {
1495    #[default]
1496    None,
1497    Add,
1498    Remove,
1499    Reload,
1500}
1501
1502impl SurfaceStagedOp {
1503    pub const fn as_str(self) -> &'static str {
1504        match self {
1505            Self::None => "None",
1506            Self::Add => "Add",
1507            Self::Remove => "Remove",
1508            Self::Reload => "Reload",
1509        }
1510    }
1511}
1512
1513/// Typed turn primitive kind. Closed mirror of
1514/// [`meerkat_core::turn_execution_authority::TurnPrimitiveKind`] — replaces the
1515/// former literal-string `primitive_kind` field and `StartConversationRun`
1516/// input field.
1517#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1518pub enum TurnPrimitiveKind {
1519    #[default]
1520    None,
1521    ConversationTurn,
1522    ImmediateAppend,
1523    ImmediateContextAppend,
1524}
1525
1526impl From<meerkat_core::turn_execution_authority::TurnPrimitiveKind> for TurnPrimitiveKind {
1527    fn from(kind: meerkat_core::turn_execution_authority::TurnPrimitiveKind) -> Self {
1528        match kind {
1529            meerkat_core::turn_execution_authority::TurnPrimitiveKind::None => Self::None,
1530            meerkat_core::turn_execution_authority::TurnPrimitiveKind::ConversationTurn => {
1531                Self::ConversationTurn
1532            }
1533            meerkat_core::turn_execution_authority::TurnPrimitiveKind::ImmediateAppend => {
1534                Self::ImmediateAppend
1535            }
1536            meerkat_core::turn_execution_authority::TurnPrimitiveKind::ImmediateContextAppend => {
1537                Self::ImmediateContextAppend
1538            }
1539        }
1540    }
1541}
1542
1543impl From<TurnPrimitiveKind> for meerkat_core::turn_execution_authority::TurnPrimitiveKind {
1544    fn from(kind: TurnPrimitiveKind) -> Self {
1545        match kind {
1546            TurnPrimitiveKind::None => Self::None,
1547            TurnPrimitiveKind::ConversationTurn => Self::ConversationTurn,
1548            TurnPrimitiveKind::ImmediateAppend => Self::ImmediateAppend,
1549            TurnPrimitiveKind::ImmediateContextAppend => Self::ImmediateContextAppend,
1550        }
1551    }
1552}
1553
1554/// Typed turn primitive content shape. Closed mirror of
1555/// [`meerkat_core::turn_execution_authority::ContentShape`] so the runtime DSL
1556/// carries the same contract instead of local string labels.
1557#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1558pub enum ContentShape {
1559    #[default]
1560    Conversation,
1561    ConversationAndContext,
1562    Context,
1563    Empty,
1564    ImmediateAppend,
1565    ImmediateContext,
1566}
1567
1568impl ContentShape {
1569    pub const fn as_str(self) -> &'static str {
1570        match self {
1571            Self::Conversation => {
1572                meerkat_core::turn_execution_authority::ContentShape::Conversation.as_str()
1573            }
1574            Self::ConversationAndContext => {
1575                meerkat_core::turn_execution_authority::ContentShape::ConversationAndContext
1576                    .as_str()
1577            }
1578            Self::Context => meerkat_core::turn_execution_authority::ContentShape::Context.as_str(),
1579            Self::Empty => meerkat_core::turn_execution_authority::ContentShape::Empty.as_str(),
1580            Self::ImmediateAppend => {
1581                meerkat_core::turn_execution_authority::ContentShape::ImmediateAppend.as_str()
1582            }
1583            Self::ImmediateContext => {
1584                meerkat_core::turn_execution_authority::ContentShape::ImmediateContext.as_str()
1585            }
1586        }
1587    }
1588}
1589
1590impl std::fmt::Display for ContentShape {
1591    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1592        f.write_str(self.as_str())
1593    }
1594}
1595
1596impl From<meerkat_core::turn_execution_authority::ContentShape> for ContentShape {
1597    fn from(shape: meerkat_core::turn_execution_authority::ContentShape) -> Self {
1598        match shape {
1599            meerkat_core::turn_execution_authority::ContentShape::Conversation => {
1600                Self::Conversation
1601            }
1602            meerkat_core::turn_execution_authority::ContentShape::ConversationAndContext => {
1603                Self::ConversationAndContext
1604            }
1605            meerkat_core::turn_execution_authority::ContentShape::Context => Self::Context,
1606            meerkat_core::turn_execution_authority::ContentShape::Empty => Self::Empty,
1607            meerkat_core::turn_execution_authority::ContentShape::ImmediateAppend => {
1608                Self::ImmediateAppend
1609            }
1610            meerkat_core::turn_execution_authority::ContentShape::ImmediateContext => {
1611                Self::ImmediateContext
1612            }
1613        }
1614    }
1615}
1616
1617impl From<ContentShape> for meerkat_core::turn_execution_authority::ContentShape {
1618    fn from(shape: ContentShape) -> Self {
1619        match shape {
1620            ContentShape::Conversation => Self::Conversation,
1621            ContentShape::ConversationAndContext => Self::ConversationAndContext,
1622            ContentShape::Context => Self::Context,
1623            ContentShape::Empty => Self::Empty,
1624            ContentShape::ImmediateAppend => Self::ImmediateAppend,
1625            ContentShape::ImmediateContext => Self::ImmediateContext,
1626        }
1627    }
1628}
1629
1630/// Typed turn terminal outcome. Closed mirror of
1631/// [`meerkat_core::turn_execution_authority::TurnTerminalOutcome`] — replaces
1632/// the former literal-string `terminal_outcome` field.
1633#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1634pub enum TurnTerminalOutcome {
1635    #[default]
1636    None,
1637    Completed,
1638    Failed,
1639    Cancelled,
1640    BudgetExhausted,
1641    TimeBudgetExceeded,
1642    StructuredOutputValidationFailed,
1643}
1644
1645impl From<meerkat_core::turn_execution_authority::TurnTerminalOutcome> for TurnTerminalOutcome {
1646    fn from(outcome: meerkat_core::turn_execution_authority::TurnTerminalOutcome) -> Self {
1647        match outcome {
1648            meerkat_core::turn_execution_authority::TurnTerminalOutcome::None => Self::None,
1649            meerkat_core::turn_execution_authority::TurnTerminalOutcome::Completed => {
1650                Self::Completed
1651            }
1652            meerkat_core::turn_execution_authority::TurnTerminalOutcome::Failed => Self::Failed,
1653            meerkat_core::turn_execution_authority::TurnTerminalOutcome::Cancelled => {
1654                Self::Cancelled
1655            }
1656            meerkat_core::turn_execution_authority::TurnTerminalOutcome::BudgetExhausted => {
1657                Self::BudgetExhausted
1658            }
1659            meerkat_core::turn_execution_authority::TurnTerminalOutcome::TimeBudgetExceeded => {
1660                Self::TimeBudgetExceeded
1661            }
1662            meerkat_core::turn_execution_authority::TurnTerminalOutcome::StructuredOutputValidationFailed => {
1663                Self::StructuredOutputValidationFailed
1664            }
1665        }
1666    }
1667}
1668
1669impl From<TurnTerminalOutcome> for meerkat_core::turn_execution_authority::TurnTerminalOutcome {
1670    fn from(outcome: TurnTerminalOutcome) -> Self {
1671        match outcome {
1672            TurnTerminalOutcome::None => Self::None,
1673            TurnTerminalOutcome::Completed => Self::Completed,
1674            TurnTerminalOutcome::Failed => Self::Failed,
1675            TurnTerminalOutcome::Cancelled => Self::Cancelled,
1676            TurnTerminalOutcome::BudgetExhausted => Self::BudgetExhausted,
1677            TurnTerminalOutcome::TimeBudgetExceeded => Self::TimeBudgetExceeded,
1678            TurnTerminalOutcome::StructuredOutputValidationFailed => {
1679                Self::StructuredOutputValidationFailed
1680            }
1681        }
1682    }
1683}
1684
1685/// Typed turn terminal cause. Closed mirror of
1686/// [`meerkat_core::turn_execution_authority::TurnTerminalCauseKind`] carried by
1687/// MeerkatMachine terminal failure inputs/effects so display messages cannot
1688/// classify terminal failures.
1689#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1690pub enum TurnTerminalCauseKind {
1691    #[default]
1692    Unknown,
1693    HookDenied,
1694    HookFailure,
1695    LlmFailure,
1696    ToolFailure,
1697    StructuredOutputValidationFailed,
1698    BudgetExhausted,
1699    TimeBudgetExceeded,
1700    RetryExhausted,
1701    TurnLimitReached,
1702    RuntimeApplyFailure,
1703    FatalFailure,
1704}
1705
1706impl From<meerkat_core::turn_execution_authority::TurnTerminalCauseKind> for TurnTerminalCauseKind {
1707    fn from(kind: meerkat_core::turn_execution_authority::TurnTerminalCauseKind) -> Self {
1708        match kind {
1709            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::Unknown => {
1710                Self::Unknown
1711            }
1712            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::HookDenied => {
1713                Self::HookDenied
1714            }
1715            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::HookFailure => {
1716                Self::HookFailure
1717            }
1718            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::LlmFailure => {
1719                Self::LlmFailure
1720            }
1721            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::ToolFailure => {
1722                Self::ToolFailure
1723            }
1724            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::StructuredOutputValidationFailed => {
1725                Self::StructuredOutputValidationFailed
1726            }
1727            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::BudgetExhausted => {
1728                Self::BudgetExhausted
1729            }
1730            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::TimeBudgetExceeded => {
1731                Self::TimeBudgetExceeded
1732            }
1733            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::RetryExhausted => {
1734                Self::RetryExhausted
1735            }
1736            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::TurnLimitReached => {
1737                Self::TurnLimitReached
1738            }
1739            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::RuntimeApplyFailure => {
1740                Self::RuntimeApplyFailure
1741            }
1742            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::FatalFailure => {
1743                Self::FatalFailure
1744            }
1745        }
1746    }
1747}
1748
1749impl From<TurnTerminalCauseKind> for meerkat_core::turn_execution_authority::TurnTerminalCauseKind {
1750    fn from(kind: TurnTerminalCauseKind) -> Self {
1751        match kind {
1752            TurnTerminalCauseKind::Unknown => Self::Unknown,
1753            TurnTerminalCauseKind::HookDenied => Self::HookDenied,
1754            TurnTerminalCauseKind::HookFailure => Self::HookFailure,
1755            TurnTerminalCauseKind::LlmFailure => Self::LlmFailure,
1756            TurnTerminalCauseKind::ToolFailure => Self::ToolFailure,
1757            TurnTerminalCauseKind::StructuredOutputValidationFailed => {
1758                Self::StructuredOutputValidationFailed
1759            }
1760            TurnTerminalCauseKind::BudgetExhausted => Self::BudgetExhausted,
1761            TurnTerminalCauseKind::TimeBudgetExceeded => Self::TimeBudgetExceeded,
1762            TurnTerminalCauseKind::RetryExhausted => Self::RetryExhausted,
1763            TurnTerminalCauseKind::TurnLimitReached => Self::TurnLimitReached,
1764            TurnTerminalCauseKind::RuntimeApplyFailure => Self::RuntimeApplyFailure,
1765            TurnTerminalCauseKind::FatalFailure => Self::FatalFailure,
1766        }
1767    }
1768}
1769
1770/// Normalized terminal-cause class for surface-result classification. The DSL
1771/// owns the typed mirror so the `ClassifyTurnTerminalCauseClass` /
1772/// `ResolveTurnSurfaceResult` transitions can carry it; the
1773/// `terminal_surface_mapping` codegen derives the classification table from
1774/// those transitions.
1775#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1776pub enum TerminalCauseClass {
1777    #[default]
1778    Missing,
1779    Unknown,
1780    BudgetExhausted,
1781    TimeBudgetExceeded,
1782    RetryExhausted,
1783    StructuredOutputValidationFailed,
1784    OtherFailure,
1785}
1786
1787/// Surface result classification emitted by `ResolveTurnSurfaceResult`.
1788#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1789pub enum SurfaceResultClass {
1790    #[default]
1791    Success,
1792    HardFailure,
1793    Cancelled,
1794    MissingTerminal,
1795}
1796
1797/// P0 Dogma Invariant 1: machine-owned LLM-failure recovery verdict emitted by
1798/// `ClassifyLlmFailureRecovery`. The DSL owns this typed mirror so the
1799/// classifier transitions can carry it; the agent loop mirrors the verdict
1800/// instead of unilaterally deciding fatal/exhaustion.
1801#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1802pub enum LlmFailureRecoveryKind {
1803    #[default]
1804    Fatal,
1805    Recover,
1806    Exhausted,
1807}
1808
1809/// #323: pre-selected call-timeout source carried into the machine's
1810/// `ClassifyCallTimeout` classifier. Source selection is shell-side; the
1811/// machine owns the retryable-vs-terminal verdict.
1812#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1813pub enum CallTimeoutSource {
1814    #[default]
1815    CallBudget,
1816    TurnBudget,
1817}
1818
1819/// #323: machine-owned call-timeout verdict emitted by `ClassifyCallTimeout`.
1820/// The agent loop mirrors this into the existing retry / budget-terminal paths.
1821#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1822pub enum CallTimeoutVerdict {
1823    #[default]
1824    RetryableCallTimeout,
1825    TerminalTurnBudget,
1826}
1827
1828/// Raw failure source fact carried by runtime run-failure handoff.
1829/// MeerkatMachine maps this to terminal outcome/cause before public
1830/// projection.
1831#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1832pub enum RunFailureSourceKind {
1833    #[default]
1834    Unknown,
1835    Llm,
1836    StoreError,
1837    ToolError,
1838    McpError,
1839    SessionNotFound,
1840    TokenBudgetExceeded,
1841    TimeBudgetExceeded,
1842    ToolCallBudgetExceeded,
1843    MaxTokensReached,
1844    ContentFiltered,
1845    MaxTurnsReached,
1846    Cancelled,
1847    InvalidStateTransition,
1848    OperationNotFound,
1849    DepthLimitExceeded,
1850    ConcurrencyLimitExceeded,
1851    ConfigError,
1852    InvalidToolAccess,
1853    SkillResolutionFailed,
1854    InternalError,
1855    BuildError,
1856    AuthReauthRequired,
1857    CallbackPending,
1858    StructuredOutputValidationFailed,
1859    InvalidOutputSchema,
1860    HookDenied,
1861    HookTimeout,
1862    HookExecutionFailed,
1863    HookConfigInvalid,
1864    TerminalFailure,
1865    NoPendingBoundary,
1866    LlmRetryExhausted,
1867}
1868
1869impl From<meerkat_core::turn_execution_authority::TurnFailureSourceKind> for RunFailureSourceKind {
1870    fn from(kind: meerkat_core::turn_execution_authority::TurnFailureSourceKind) -> Self {
1871        match kind {
1872            meerkat_core::turn_execution_authority::TurnFailureSourceKind::Unknown => {
1873                Self::Unknown
1874            }
1875            meerkat_core::turn_execution_authority::TurnFailureSourceKind::Llm => Self::Llm,
1876            meerkat_core::turn_execution_authority::TurnFailureSourceKind::StoreError => {
1877                Self::StoreError
1878            }
1879            meerkat_core::turn_execution_authority::TurnFailureSourceKind::ToolError => {
1880                Self::ToolError
1881            }
1882            meerkat_core::turn_execution_authority::TurnFailureSourceKind::McpError => {
1883                Self::McpError
1884            }
1885            meerkat_core::turn_execution_authority::TurnFailureSourceKind::SessionNotFound => {
1886                Self::SessionNotFound
1887            }
1888            meerkat_core::turn_execution_authority::TurnFailureSourceKind::TokenBudgetExceeded => {
1889                Self::TokenBudgetExceeded
1890            }
1891            meerkat_core::turn_execution_authority::TurnFailureSourceKind::TimeBudgetExceeded => {
1892                Self::TimeBudgetExceeded
1893            }
1894            meerkat_core::turn_execution_authority::TurnFailureSourceKind::ToolCallBudgetExceeded => {
1895                Self::ToolCallBudgetExceeded
1896            }
1897            meerkat_core::turn_execution_authority::TurnFailureSourceKind::MaxTokensReached => {
1898                Self::MaxTokensReached
1899            }
1900            meerkat_core::turn_execution_authority::TurnFailureSourceKind::ContentFiltered => {
1901                Self::ContentFiltered
1902            }
1903            meerkat_core::turn_execution_authority::TurnFailureSourceKind::MaxTurnsReached => {
1904                Self::MaxTurnsReached
1905            }
1906            meerkat_core::turn_execution_authority::TurnFailureSourceKind::Cancelled => {
1907                Self::Cancelled
1908            }
1909            meerkat_core::turn_execution_authority::TurnFailureSourceKind::InvalidStateTransition => {
1910                Self::InvalidStateTransition
1911            }
1912            meerkat_core::turn_execution_authority::TurnFailureSourceKind::OperationNotFound => {
1913                Self::OperationNotFound
1914            }
1915            meerkat_core::turn_execution_authority::TurnFailureSourceKind::DepthLimitExceeded => {
1916                Self::DepthLimitExceeded
1917            }
1918            meerkat_core::turn_execution_authority::TurnFailureSourceKind::ConcurrencyLimitExceeded => {
1919                Self::ConcurrencyLimitExceeded
1920            }
1921            meerkat_core::turn_execution_authority::TurnFailureSourceKind::ConfigError => {
1922                Self::ConfigError
1923            }
1924            meerkat_core::turn_execution_authority::TurnFailureSourceKind::InvalidToolAccess => {
1925                Self::InvalidToolAccess
1926            }
1927            meerkat_core::turn_execution_authority::TurnFailureSourceKind::SkillResolutionFailed => {
1928                Self::SkillResolutionFailed
1929            }
1930            meerkat_core::turn_execution_authority::TurnFailureSourceKind::InternalError => {
1931                Self::InternalError
1932            }
1933            meerkat_core::turn_execution_authority::TurnFailureSourceKind::BuildError => {
1934                Self::BuildError
1935            }
1936            meerkat_core::turn_execution_authority::TurnFailureSourceKind::AuthReauthRequired => {
1937                Self::AuthReauthRequired
1938            }
1939            meerkat_core::turn_execution_authority::TurnFailureSourceKind::CallbackPending => {
1940                Self::CallbackPending
1941            }
1942            meerkat_core::turn_execution_authority::TurnFailureSourceKind::StructuredOutputValidationFailed => {
1943                Self::StructuredOutputValidationFailed
1944            }
1945            meerkat_core::turn_execution_authority::TurnFailureSourceKind::InvalidOutputSchema => {
1946                Self::InvalidOutputSchema
1947            }
1948            meerkat_core::turn_execution_authority::TurnFailureSourceKind::HookDenied => {
1949                Self::HookDenied
1950            }
1951            meerkat_core::turn_execution_authority::TurnFailureSourceKind::HookTimeout => {
1952                Self::HookTimeout
1953            }
1954            meerkat_core::turn_execution_authority::TurnFailureSourceKind::HookExecutionFailed => {
1955                Self::HookExecutionFailed
1956            }
1957            meerkat_core::turn_execution_authority::TurnFailureSourceKind::HookConfigInvalid => {
1958                Self::HookConfigInvalid
1959            }
1960            meerkat_core::turn_execution_authority::TurnFailureSourceKind::TerminalFailure => {
1961                Self::TerminalFailure
1962            }
1963            meerkat_core::turn_execution_authority::TurnFailureSourceKind::NoPendingBoundary => {
1964                Self::NoPendingBoundary
1965            }
1966            meerkat_core::turn_execution_authority::TurnFailureSourceKind::LlmRetryExhausted => {
1967                Self::LlmRetryExhausted
1968            }
1969        }
1970    }
1971}
1972
1973/// Typed classifier for failures surfaced by the runtime apply loop when a
1974/// `CoreExecutor::apply` call fails and terminalizes the runtime turn.
1975/// The companion `last_runtime_apply_failure_message` state field carries the
1976/// human-readable projection.
1977#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1978pub enum RuntimeApplyFailureCause {
1979    #[default]
1980    Unknown,
1981    PrimitiveRejected,
1982    RuntimeContextApply,
1983    RuntimeTurn,
1984    HookDenied,
1985    HookRuntimeFailure,
1986    ExecutorStopped,
1987    ExecutorControlFailed,
1988    ExecutorInternal,
1989}
1990
1991impl From<meerkat_core::lifecycle::CoreApplyFailureCauseKind> for RuntimeApplyFailureCause {
1992    #[allow(clippy::panic)]
1993    fn from(kind: meerkat_core::lifecycle::CoreApplyFailureCauseKind) -> Self {
1994        match kind {
1995            meerkat_core::lifecycle::CoreApplyFailureCauseKind::PrimitiveRejected => {
1996                Self::PrimitiveRejected
1997            }
1998            meerkat_core::lifecycle::CoreApplyFailureCauseKind::RuntimeContextApply => {
1999                Self::RuntimeContextApply
2000            }
2001            meerkat_core::lifecycle::CoreApplyFailureCauseKind::RuntimeTurn => Self::RuntimeTurn,
2002            meerkat_core::lifecycle::CoreApplyFailureCauseKind::HookDenied => Self::HookDenied,
2003            meerkat_core::lifecycle::CoreApplyFailureCauseKind::HookRuntimeFailure => {
2004                Self::HookRuntimeFailure
2005            }
2006            meerkat_core::lifecycle::CoreApplyFailureCauseKind::ExecutorStopped => {
2007                Self::ExecutorStopped
2008            }
2009            meerkat_core::lifecycle::CoreApplyFailureCauseKind::ExecutorControlFailed => {
2010                Self::ExecutorControlFailed
2011            }
2012            meerkat_core::lifecycle::CoreApplyFailureCauseKind::ExecutorInternal => {
2013                Self::ExecutorInternal
2014            }
2015            meerkat_core::lifecycle::CoreApplyFailureCauseKind::Unknown => Self::Unknown,
2016            _ => panic!(
2017                "unsupported CoreApplyFailureCauseKind variant; update generated MeerkatMachine mirror"
2018            ),
2019        }
2020    }
2021}
2022
2023impl From<&meerkat_core::lifecycle::CoreApplyFailureCause> for RuntimeApplyFailureCause {
2024    fn from(cause: &meerkat_core::lifecycle::CoreApplyFailureCause) -> Self {
2025        Self::from(cause.kind)
2026    }
2027}
2028
2029/// Typed pre-run phase marker. Closed set: `idle`, `attached`, `retired`.
2030/// Replaces the former literal-string `pre_run_phase` field.
2031#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2032pub enum PreRunPhase {
2033    #[default]
2034    Idle,
2035    Attached,
2036    Retired,
2037}
2038
2039/// Generated authority for deferred session materialization.
2040///
2041/// The shell keeps bulky build payloads in a registry, but phase/admission
2042/// meaning for the staged lifecycle is owned here.
2043#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2044pub enum StagedSessionPhase {
2045    #[default]
2046    NotStaged,
2047    Staged,
2048    Promoting,
2049    Closing,
2050}
2051
2052/// Explicit host/profile request class for mob operator access.
2053#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2054pub enum MobOperatorAccessRequestKind {
2055    #[default]
2056    Inherit,
2057    Enable,
2058    Disable,
2059}
2060
2061/// Typed runtime notice classifier for the `RuntimeNotice` effect. Closed set
2062/// of per-transition runtime lifecycle markers (drain exited, runtime reset,
2063/// executor stopped/exited, runtime recovered) emitted by the runtime-control
2064/// plane. Replaces the former literal-string `kind` field on `RuntimeNotice`
2065/// so the shell dispatcher matches exhaustively on a typed discriminant
2066/// instead of comparing string literals. `detail` stays `String` — it's a
2067/// free-form diagnostic message that accompanies the kind.
2068#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2069pub enum RuntimeNoticeKind {
2070    #[default]
2071    Drain,
2072    Reset,
2073    Stop,
2074    Exit,
2075    Recover,
2076}
2077
2078/// Closed top-level classifier for a published `RuntimeEvent`, mirroring the
2079/// five `RuntimeEvent` discriminants in `meerkat-runtime` (`InputLifecycle`,
2080/// `RunLifecycle`, `RuntimeStateChange`, `Topology`, `Projection`). Replaces the
2081/// former Debug-derived discriminant *string* on `PublishEvent.kind` so the DSL
2082/// carries a typed discriminant the shell maps exhaustively.
2083#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2084pub enum RuntimeEventKind {
2085    #[default]
2086    InputLifecycle,
2087    RunLifecycle,
2088    RuntimeStateChange,
2089    Topology,
2090    Projection,
2091}
2092
2093/// Closed classifier for runtime-loop executor effects emitted as neutral DSL
2094/// facts before the runtime shell converts them to sealed executable effects.
2095#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2096pub enum RuntimeEffectKind {
2097    #[default]
2098    CancelAfterBoundary,
2099    StopRuntimeExecutor,
2100}
2101
2102/// Typed runtime completion observation supplied by completion waiter plumbing.
2103/// Generated `ResolveRuntimeCompletionCleanup` authority owns whether that
2104/// observation permits runtime cleanup; surfaces must not match this enum to
2105/// decide cleanup locally.
2106#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2107pub enum RuntimeCompletionObservedOutcome {
2108    #[default]
2109    Completed,
2110    CompletedWithoutResult,
2111    CallbackPending,
2112    Cancelled,
2113    Abandoned,
2114    RuntimeApplyFailed,
2115    FinalizationFailed,
2116    RuntimeTerminated,
2117}
2118
2119/// Typed observation of the terminal payload shape produced by runtime-loop
2120/// execution. This is input evidence only; the generated
2121/// `ResolveRuntimeCompletionResult` transition owns the public waiter class.
2122#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2123pub enum RuntimeCompletionTerminalObservation {
2124    #[default]
2125    RunResult,
2126    NoResult,
2127    CallbackPending,
2128    MachineTerminal,
2129    RuntimeTerminated,
2130}
2131
2132/// Typed observation of whether runtime finalization completed after the
2133/// executor produced terminal evidence.
2134#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2135pub enum RuntimeCompletionFinalizationObservation {
2136    #[default]
2137    Succeeded,
2138    Failed,
2139}
2140
2141/// Typed observation supplied by public session-interrupt surfaces. The
2142/// generated `ResolveUserInterruptPublicResult` transition owns the app-facing
2143/// result class; REST/RPC/CLI may only map its typed effect to transport shape.
2144#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2145pub enum UserInterruptObservationKind {
2146    #[default]
2147    Accepted,
2148    IdleNoop,
2149    AttachedNoop,
2150    StagedNoop,
2151    Destroyed,
2152    NotInterruptible,
2153}
2154
2155/// Generated public result class for user interrupt requests.
2156#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2157pub enum UserInterruptPublicResultKind {
2158    #[default]
2159    Interrupted,
2160    /// #348: a staged (not-yet-promoted) session interrupt is a typed no-op
2161    /// terminal — distinct from `Interrupted` (a live run was cancelled).
2162    StagedNoop,
2163    NotFound,
2164    SessionBusy,
2165    Conflict,
2166}
2167
2168/// Generated public completion result class for runtime-loop waiters. Payloads
2169/// remain runtime data, but this closed classifier is the authority for which
2170/// public `CompletionOutcome` variant may be emitted.
2171#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2172pub enum RuntimeCompletionResultClass {
2173    #[default]
2174    Completed,
2175    CompletedWithoutResult,
2176    CallbackPending,
2177    Cancelled,
2178    AbandonedWithError,
2179    CompletedWithFinalizationFailure,
2180    RuntimeTerminated,
2181}
2182
2183/// Typed observation of the live-session projection available to generated
2184/// runtime-completion cleanup authority.
2185#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2186pub enum RuntimeCompletionLiveSessionObservation {
2187    #[default]
2188    NotObserved,
2189    Present,
2190    Absent,
2191}
2192
2193/// Generated cleanup action for runtime completion side effects.
2194#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2195pub enum RuntimeCompletionCleanupAction {
2196    #[default]
2197    RetainRuntime,
2198    CleanupRuntime,
2199}
2200
2201/// Generated authority for whether completion cleanup may release a surface
2202/// pre-admission guard.
2203#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2204pub enum RuntimeCompletionPreAdmissionAction {
2205    #[default]
2206    RetainPreAdmission,
2207    ReleasePreAdmission,
2208}
2209
2210/// Typed mechanical failure observed by completion waiter plumbing.
2211#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2212pub enum RuntimeCompletionWaitFailureObservation {
2213    #[default]
2214    ChannelClosed,
2215    AuthorityUnavailable,
2216}
2217
2218/// Generated public error class for mechanical runtime completion waiter
2219/// failures.
2220#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2221pub enum RuntimeCompletionWaitFailurePublicErrorClass {
2222    #[default]
2223    InternalError,
2224}
2225
2226/// Generated public reason classifier for mechanical runtime completion waiter
2227/// failures.
2228#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2229pub enum RuntimeCompletionWaitFailurePublicReason {
2230    #[default]
2231    CompletionChannelClosed,
2232    CompletionAuthorityUnavailable,
2233}
2234
2235/// Generated durability action for runtime-owned ops lifecycle snapshots.
2236#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2237pub enum RuntimeOpsLifecycleDurabilityAction {
2238    #[default]
2239    RetainSnapshot,
2240    DeleteSnapshot,
2241}
2242
2243/// Typed public rejection class for `live/open` admission.
2244#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2245pub enum LiveOpenAdmissionRejection {
2246    #[default]
2247    AlreadyBound,
2248    ChannelAlreadyBound,
2249    LifecycleClosed,
2250}
2251
2252/// Typed public result class for `live/refresh` after the adapter command
2253/// queue accepts a refresh handoff. The RPC surface may only project this
2254/// value from a generated `LiveRefreshResultResolved` effect.
2255#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2256pub enum LiveRefreshPublicStatus {
2257    #[default]
2258    Queued,
2259}
2260
2261/// Typed public result class for `live/close` after the live host accepts a
2262/// close handoff. The RPC surface may only project this value from a generated
2263/// `LiveCloseResultResolved` effect.
2264#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2265pub enum LiveClosePublicStatus {
2266    #[default]
2267    Closed,
2268}
2269
2270/// Closed classifier for live adapter commands whose queue acceptance backs a
2271/// public RPC result.
2272#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2273pub enum LiveCommandPublicKind {
2274    #[default]
2275    SendInput,
2276    CommitInput,
2277    Interrupt,
2278    TruncateAssistantOutput,
2279}
2280
2281/// Closed classifier for live command rejection observations. The live host
2282/// can observe why an adapter command handoff failed, but public error-class
2283/// truth is generated from this typed fact.
2284#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2285pub enum LiveCommandRejectionReason {
2286    #[default]
2287    ChannelNotFound,
2288    NoAdapter,
2289    ChannelNotReady,
2290    UnsupportedCommand,
2291    AdapterError,
2292    InternalHostError,
2293}
2294
2295/// Typed public error class for live command rejections. RPC surfaces may only
2296/// project their JSON-RPC error code from a generated
2297/// `LiveCommandRejectionResolved` effect.
2298#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2299pub enum LiveCommandRejectionPublicErrorClass {
2300    #[default]
2301    InvalidParams,
2302    InternalError,
2303}
2304
2305/// Closed classifier for live channel control requests whose rejection backs a
2306/// public RPC error result.
2307#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2308pub enum LiveChannelRequestPublicKind {
2309    #[default]
2310    Status,
2311    Close,
2312    Refresh,
2313    WebrtcAnswer,
2314}
2315
2316/// Closed classifier for live channel control request rejection observations.
2317/// The live host can observe missing transport/cache pieces, but public
2318/// error-class truth is generated from this typed fact.
2319#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2320pub enum LiveChannelRequestRejectionReason {
2321    #[default]
2322    ChannelNotFound,
2323    NoAdapter,
2324    InvalidToken,
2325    InvalidPayload,
2326    WebrtcAnswerError,
2327    InternalHostError,
2328}
2329
2330/// Typed public error class for live channel control request rejections. RPC
2331/// surfaces may only project their JSON-RPC error code from a generated
2332/// `LiveChannelRequestRejectionResolved` effect.
2333#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2334pub enum LiveChannelRequestRejectionPublicErrorClass {
2335    #[default]
2336    InvalidParams,
2337    InternalError,
2338}
2339
2340/// Closed classifier for generated WebRTC answer admission rejections. The
2341/// transport can provide bearer material, but token existence, expiry,
2342/// channel binding, and single-use admission are decided by MeerkatMachine.
2343#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2344pub enum LiveWebrtcAnswerAdmissionRejection {
2345    #[default]
2346    TokenNotFound,
2347    TokenExpired,
2348    TokenChannelMismatch,
2349    TokenAlreadyConsumed,
2350    ChannelNotBound,
2351}
2352
2353/// Closed classifier for generated WebSocket token admission rejections. The
2354/// WebSocket transport can present bearer material, but token existence,
2355/// expiry, channel binding, and single-use admission are decided by
2356/// MeerkatMachine.
2357#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2358pub enum LiveWebsocketTokenAdmissionRejection {
2359    #[default]
2360    TokenNotFound,
2361    TokenExpired,
2362    TokenChannelMismatch,
2363    TokenAlreadyConsumed,
2364    ChannelNotBound,
2365}
2366
2367/// Typed public error class for live WebSocket token admission. The transport
2368/// projects its close/error code only from the generated admission effect.
2369#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2370pub enum LiveWebsocketTokenAdmissionPublicErrorClass {
2371    #[default]
2372    InvalidToken,
2373}
2374
2375/// Typed public success class for `live/webrtc/answer`. The WebRTC stack
2376/// produces SDP material, but the public success result is projected only
2377/// after a generated `LiveWebrtcAnswerResultResolved` effect.
2378#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2379pub enum LiveWebrtcAnswerPublicStatus {
2380    #[default]
2381    Answered,
2382}
2383
2384/// Typed terminal reason for RPC event streams. The router observes transport
2385/// end conditions, then submits the closed set here before projecting the
2386/// public `*/stream_end` notification.
2387#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2388pub enum RpcEventStreamTerminalReason {
2389    #[default]
2390    RemoteEnd,
2391    TerminalError,
2392    ExplicitClose,
2393}
2394
2395/// Typed transport observation for RPC event-stream termination. The router
2396/// submits this non-public observation; generated authority derives the public
2397/// terminal reason and error code.
2398#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2399pub enum RpcEventStreamTerminalObservationKind {
2400    #[default]
2401    TransportEnded,
2402    NotificationQueueOverflow,
2403    NotificationReceiverGone,
2404}
2405
2406/// Typed public error code for RPC event-stream terminal notifications. The
2407/// RPC surface may only project this value from a generated
2408/// `*EventStreamTerminalResolved` effect.
2409#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2410pub enum RpcEventStreamTerminalErrorCode {
2411    #[default]
2412    StreamQueueOverflow,
2413    StreamReceiverGone,
2414}
2415
2416/// Typed public status class for `live/status` after the live host has
2417/// observed the adapter transport state. RPC/SDK surfaces may only project
2418/// these values from generated `LiveChannelStatusResolved` effects.
2419#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2420pub enum LiveChannelPublicStatus {
2421    #[default]
2422    Idle,
2423    Opening,
2424    Ready,
2425    Degraded,
2426    Closing,
2427    Closed,
2428}
2429
2430/// Typed public degradation reason for `live/status`.
2431#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2432pub enum LiveChannelDegradationReason {
2433    #[default]
2434    Unknown,
2435    RateLimited,
2436    ProviderThrottled,
2437    NetworkUnstable,
2438    Other,
2439}
2440
2441/// #51: provider-neutral role for a staged realtime transcript item, carried on
2442/// the `RealtimeTranscriptAppended` staging effect. Mirror of
2443/// `meerkat_core::realtime_transcript::RealtimeTranscriptRole`.
2444#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2445pub enum RealtimeTranscriptRoleKind {
2446    #[default]
2447    User,
2448    Assistant,
2449}
2450
2451/// #51: output lane for a staged realtime transcript item (display text vs
2452/// spoken transcript). Mirror of `meerkat_core::realtime_transcript::TranscriptLane`.
2453#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2454pub enum RealtimeTranscriptLaneKind {
2455    #[default]
2456    Display,
2457    Spoken,
2458}
2459
2460/// Typed mirror of the public runtime lifecycle projection. The shell passes
2461/// only the observed variant; generated transitions own the semantic facts
2462/// derived from it.
2463#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2464pub enum RuntimeLifecycleObservedState {
2465    #[default]
2466    Initializing,
2467    Idle,
2468    Attached,
2469    Running,
2470    Retired,
2471    Stopped,
2472    Destroyed,
2473}
2474
2475/// Physical observation class for the durable runtime-authority projection.
2476/// Missing, unsupported, malformed, and unavailable rows remain first-class
2477/// inputs to the generated level-triggered classifier.
2478#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2479pub enum RuntimeAuthorityObservationKind {
2480    #[default]
2481    Missing,
2482    Decoded,
2483    Unsupported,
2484    Malformed,
2485    Unavailable,
2486}
2487
2488/// Output-only next obligation selected by the generated runtime-authority
2489/// classifier. This enum grants no write authority by itself.
2490#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2491pub enum RuntimeAuthorityReconcileDecision {
2492    #[default]
2493    RepairBlocked,
2494    Converged,
2495    NormalizeOrReplace,
2496    Quarantine,
2497    Backoff,
2498}
2499
2500#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2501pub enum RuntimeLifecycleTerminality {
2502    #[default]
2503    NonTerminal,
2504    Terminal,
2505}
2506
2507#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2508pub enum RuntimeInputAdmission {
2509    #[default]
2510    RejectsInput,
2511    AcceptsInput,
2512}
2513
2514#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2515pub enum RuntimeQueueAdmission {
2516    #[default]
2517    BlocksQueue,
2518    ProcessesQueue,
2519}
2520
2521#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2522pub enum RuntimePrepareAdmission {
2523    #[default]
2524    NotReady,
2525    Ready,
2526    Destroyed,
2527}
2528
2529#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2530pub enum RuntimeIngressAdmission {
2531    #[default]
2532    Open,
2533    NotReady,
2534    Destroyed,
2535}
2536
2537#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2538pub enum RuntimeLoopRunBinding {
2539    #[default]
2540    Blocked,
2541    AllocateNew,
2542    UsePrebound,
2543}
2544
2545/// Typed reason classifier for the `TurnRunCancelled` effect. Closed set of
2546/// cancellation-observation origins emitted when a turn's cancellation
2547/// request lands at an observable boundary. Replaces the former literal-
2548/// string `reason` field on `TurnRunCancelled`. Only one origin is emitted
2549/// today (`Observed`, fired by the `CancellationObserved` transition), but
2550/// this remains a closed classifier not a free-form message — future
2551/// cancellation origins extend the enum rather than reintroducing strings.
2552#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2553pub enum TurnCancellationReason {
2554    #[default]
2555    Observed,
2556}
2557
2558/// Typed recoverable LLM retry failure classifier. Closed mirror of
2559/// [`meerkat_core::retry::LlmRetryFailureKind`] so retry authority records the
2560/// retry cause as data, not as a parsed diagnostic string.
2561#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2562pub enum LlmRetryFailureKind {
2563    #[default]
2564    RateLimited,
2565    NetworkTimeout,
2566    CallTimeout,
2567    RetryableProviderError,
2568}
2569
2570impl From<meerkat_core::retry::LlmRetryFailureKind> for LlmRetryFailureKind {
2571    fn from(kind: meerkat_core::retry::LlmRetryFailureKind) -> Self {
2572        match kind {
2573            meerkat_core::retry::LlmRetryFailureKind::RateLimited => Self::RateLimited,
2574            meerkat_core::retry::LlmRetryFailureKind::NetworkTimeout => Self::NetworkTimeout,
2575            meerkat_core::retry::LlmRetryFailureKind::CallTimeout => Self::CallTimeout,
2576            meerkat_core::retry::LlmRetryFailureKind::RetryableProviderError => {
2577                Self::RetryableProviderError
2578            }
2579        }
2580    }
2581}
2582
2583/// Typed admission-signal classifier for the `PostAdmissionSignal` effect.
2584/// Closed set of post-admission wake/interrupt intents emitted by the
2585/// ingress authority so the shell dispatcher matches exhaustively on a
2586/// typed discriminant instead of comparing string literals. Mirrors the
2587/// shell-side `driver::ephemeral::PostAdmissionSignal` strength ordering
2588/// (WakeLoop < InterruptYielding < RequestImmediateProcessing); the
2589/// shell enum additionally carries a `None` bottom that the DSL never
2590/// emits, so only the three emitted variants appear here.
2591#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2592pub enum PostAdmissionSignalKind {
2593    #[default]
2594    WakeLoop,
2595    InterruptYielding,
2596    RequestImmediateProcessing,
2597}
2598
2599/// Typed base lifecycle state for an external tool surface. Closed mirror of
2600/// [`meerkat_core::tool_scope::ExternalToolSurfaceBaseState`] — replaces the
2601/// former literal-string values in `surface_base_state`.
2602#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2603pub enum ExternalToolSurfaceBaseState {
2604    #[default]
2605    Absent,
2606    Active,
2607    Removing,
2608    Removed,
2609}
2610
2611impl From<meerkat_core::tool_scope::ExternalToolSurfaceBaseState> for ExternalToolSurfaceBaseState {
2612    fn from(state: meerkat_core::tool_scope::ExternalToolSurfaceBaseState) -> Self {
2613        match state {
2614            meerkat_core::tool_scope::ExternalToolSurfaceBaseState::Absent => Self::Absent,
2615            meerkat_core::tool_scope::ExternalToolSurfaceBaseState::Active => Self::Active,
2616            meerkat_core::tool_scope::ExternalToolSurfaceBaseState::Removing => Self::Removing,
2617            meerkat_core::tool_scope::ExternalToolSurfaceBaseState::Removed => Self::Removed,
2618        }
2619    }
2620}
2621
2622impl From<ExternalToolSurfaceBaseState> for meerkat_core::tool_scope::ExternalToolSurfaceBaseState {
2623    fn from(state: ExternalToolSurfaceBaseState) -> Self {
2624        match state {
2625            ExternalToolSurfaceBaseState::Absent => Self::Absent,
2626            ExternalToolSurfaceBaseState::Active => Self::Active,
2627            ExternalToolSurfaceBaseState::Removing => Self::Removing,
2628            ExternalToolSurfaceBaseState::Removed => Self::Removed,
2629        }
2630    }
2631}
2632
2633/// Typed last-delta operation for an external tool surface. Closed mirror of
2634/// [`meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation`] — replaces
2635/// the former literal-string values in `surface_last_delta_operation`.
2636#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2637pub enum ExternalToolSurfaceDeltaOperation {
2638    #[default]
2639    None,
2640    Add,
2641    Remove,
2642    Reload,
2643}
2644
2645impl From<meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation>
2646    for ExternalToolSurfaceDeltaOperation
2647{
2648    fn from(op: meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation) -> Self {
2649        match op {
2650            meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation::None => Self::None,
2651            meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation::Add => Self::Add,
2652            meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation::Remove => Self::Remove,
2653            meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation::Reload => Self::Reload,
2654        }
2655    }
2656}
2657
2658impl From<ExternalToolSurfaceDeltaOperation>
2659    for meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation
2660{
2661    fn from(op: ExternalToolSurfaceDeltaOperation) -> Self {
2662        match op {
2663            ExternalToolSurfaceDeltaOperation::None => Self::None,
2664            ExternalToolSurfaceDeltaOperation::Add => Self::Add,
2665            ExternalToolSurfaceDeltaOperation::Remove => Self::Remove,
2666            ExternalToolSurfaceDeltaOperation::Reload => Self::Reload,
2667        }
2668    }
2669}
2670
2671/// Typed last-delta phase for an external tool surface. Closed mirror of
2672/// [`meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase`] — replaces the
2673/// former literal-string values in `surface_last_delta_phase`.
2674#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2675pub enum ExternalToolSurfaceDeltaPhase {
2676    #[default]
2677    None,
2678    Pending,
2679    Applied,
2680    Draining,
2681    Failed,
2682    Forced,
2683}
2684
2685impl From<meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase>
2686    for ExternalToolSurfaceDeltaPhase
2687{
2688    fn from(phase: meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase) -> Self {
2689        match phase {
2690            meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase::None => Self::None,
2691            meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase::Pending => Self::Pending,
2692            meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase::Applied => Self::Applied,
2693            meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase::Draining => Self::Draining,
2694            meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase::Failed => Self::Failed,
2695            meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase::Forced => Self::Forced,
2696        }
2697    }
2698}
2699
2700impl From<ExternalToolSurfaceDeltaPhase>
2701    for meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase
2702{
2703    fn from(phase: ExternalToolSurfaceDeltaPhase) -> Self {
2704        match phase {
2705            ExternalToolSurfaceDeltaPhase::None => Self::None,
2706            ExternalToolSurfaceDeltaPhase::Pending => Self::Pending,
2707            ExternalToolSurfaceDeltaPhase::Applied => Self::Applied,
2708            ExternalToolSurfaceDeltaPhase::Draining => Self::Draining,
2709            ExternalToolSurfaceDeltaPhase::Failed => Self::Failed,
2710            ExternalToolSurfaceDeltaPhase::Forced => Self::Forced,
2711        }
2712    }
2713}
2714
2715/// Typed failure cause for an external tool surface. Closed mirror of
2716/// [`meerkat_core::tool_scope::ExternalToolSurfaceFailureCause`] so pending
2717/// failure and call-rejection causes cross the DSL as data, not string codes.
2718#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2719pub enum ExternalToolSurfaceFailureCause {
2720    #[default]
2721    PendingFailed,
2722    SurfaceDraining,
2723    SurfaceUnavailable,
2724}
2725
2726impl From<meerkat_core::tool_scope::ExternalToolSurfaceFailureCause>
2727    for ExternalToolSurfaceFailureCause
2728{
2729    fn from(cause: meerkat_core::tool_scope::ExternalToolSurfaceFailureCause) -> Self {
2730        match cause {
2731            meerkat_core::tool_scope::ExternalToolSurfaceFailureCause::PendingFailed => {
2732                Self::PendingFailed
2733            }
2734            meerkat_core::tool_scope::ExternalToolSurfaceFailureCause::SurfaceDraining => {
2735                Self::SurfaceDraining
2736            }
2737            meerkat_core::tool_scope::ExternalToolSurfaceFailureCause::SurfaceUnavailable => {
2738                Self::SurfaceUnavailable
2739            }
2740        }
2741    }
2742}
2743
2744impl From<ExternalToolSurfaceFailureCause>
2745    for meerkat_core::tool_scope::ExternalToolSurfaceFailureCause
2746{
2747    fn from(cause: ExternalToolSurfaceFailureCause) -> Self {
2748        match cause {
2749            ExternalToolSurfaceFailureCause::PendingFailed => Self::PendingFailed,
2750            ExternalToolSurfaceFailureCause::SurfaceDraining => Self::SurfaceDraining,
2751            ExternalToolSurfaceFailureCause::SurfaceUnavailable => Self::SurfaceUnavailable,
2752        }
2753    }
2754}
2755
2756/// Typed drain-exit reason. Closed mirror of
2757/// [`meerkat_core::handles::DrainExitReason`] — replaces the former
2758/// literal-string `reason` field on `NotifyDrainExited`.
2759#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2760pub enum DrainExitReason {
2761    #[default]
2762    IdleTimeout,
2763    Dismissed,
2764    Failed,
2765    Aborted,
2766    SessionShutdown,
2767}
2768
2769impl From<meerkat_core::handles::DrainExitReason> for DrainExitReason {
2770    fn from(reason: meerkat_core::handles::DrainExitReason) -> Self {
2771        match reason {
2772            meerkat_core::handles::DrainExitReason::IdleTimeout => Self::IdleTimeout,
2773            meerkat_core::handles::DrainExitReason::Dismissed => Self::Dismissed,
2774            meerkat_core::handles::DrainExitReason::Failed => Self::Failed,
2775            meerkat_core::handles::DrainExitReason::Aborted => Self::Aborted,
2776            meerkat_core::handles::DrainExitReason::SessionShutdown => Self::SessionShutdown,
2777        }
2778    }
2779}
2780
2781impl From<DrainExitReason> for meerkat_core::handles::DrainExitReason {
2782    fn from(reason: DrainExitReason) -> Self {
2783        match reason {
2784            DrainExitReason::IdleTimeout => Self::IdleTimeout,
2785            DrainExitReason::Dismissed => Self::Dismissed,
2786            DrainExitReason::Failed => Self::Failed,
2787            DrainExitReason::Aborted => Self::Aborted,
2788            DrainExitReason::SessionShutdown => Self::SessionShutdown,
2789        }
2790    }
2791}
2792
2793/// Generated surface-request lifecycle phase. Surface transports may project
2794/// this value for diagnostics; mutation authority lives in MeerkatMachine
2795/// transitions.
2796#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2797pub enum SurfaceRequestPhase {
2798    #[default]
2799    Pending,
2800    Published,
2801    Cancelled,
2802    Completed,
2803}
2804
2805/// Generated terminal-publication policy recorded when a surface request is
2806/// admitted.
2807#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2808pub enum SurfaceRequestTerminalPolicy {
2809    #[default]
2810    RespondWithoutPublish,
2811    PublishOnSuccess,
2812}
2813
2814/// Typed work-lane origin for [`MeerkatMachineInput::Ingest`]. Closed set of
2815/// the work-lane labels the DSL observes on the admission seam — replaces
2816/// the former literal-string `origin` field. Structurally mirrors the
2817/// `MobMachine.RequestRuntimeIngress.origin` seam so the cross-machine
2818/// composition binds on a single typed enum instead of parallel
2819/// string-typed slots. Transport sources ([`meerkat_core::comms::InputSource`])
2820/// arriving from the shell side collapse to `External`; the
2821/// runtime-control-plane `Ingest` dispatch uses the dedicated `Ingest`
2822/// variant; mob-bridged ingress carries `External`/`Internal` matching
2823/// `meerkat-mob::ids::WorkOrigin`.
2824#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2825pub enum WorkOrigin {
2826    #[default]
2827    External,
2828    Internal,
2829    /// Canonical admission entrypoint fired by the runtime control plane
2830    /// with no surface-level transport or work-lane label.
2831    Ingest,
2832}
2833
2834impl From<meerkat_core::comms::InputSource> for WorkOrigin {
2835    fn from(src: meerkat_core::comms::InputSource) -> Self {
2836        match src {
2837            // Transport-originated inputs are `External` work-lane: they
2838            // entered the runtime via a non-mob transport (TCP/UDS/stdin/
2839            // webhook/RPC). Mob-originated work fires the DSL directly
2840            // with `External`/`Internal` instead of going through the
2841            // session-admission handle.
2842            meerkat_core::comms::InputSource::Tcp
2843            | meerkat_core::comms::InputSource::Uds
2844            | meerkat_core::comms::InputSource::Stdin
2845            | meerkat_core::comms::InputSource::Webhook
2846            | meerkat_core::comms::InputSource::Rpc => Self::External,
2847        }
2848    }
2849}
2850
2851/// Typed async-operation lifecycle status. Closed mirror of
2852/// [`meerkat_core::ops_lifecycle::OperationStatus`] — replaces the former
2853/// literal-string values in the DSL's `op_statuses` map.
2854///
2855/// The DSL writes these variants directly on each ops lifecycle transition
2856/// (`RegisterOp`, `StartOp`, `CompleteOp`, `FailOp`, `CancelOp`, `AbortOp`,
2857/// `RetireRequestedOp`, `RetireCompletedOp`, `TerminateOp`). The shell's
2858/// `ShellState::status()` reads the typed value directly and maps to the
2859/// domain enum via the `From` impl below — no string compares, no string
2860/// parsing.
2861#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2862pub enum OperationStatus {
2863    #[default]
2864    Absent,
2865    Provisioning,
2866    Running,
2867    Retiring,
2868    Completed,
2869    Failed,
2870    Aborted,
2871    Cancelled,
2872    Retired,
2873    Terminated,
2874}
2875
2876impl From<meerkat_core::ops_lifecycle::OperationStatus> for OperationStatus {
2877    fn from(status: meerkat_core::ops_lifecycle::OperationStatus) -> Self {
2878        match status {
2879            meerkat_core::ops_lifecycle::OperationStatus::Absent => Self::Absent,
2880            meerkat_core::ops_lifecycle::OperationStatus::Provisioning => Self::Provisioning,
2881            meerkat_core::ops_lifecycle::OperationStatus::Running => Self::Running,
2882            meerkat_core::ops_lifecycle::OperationStatus::Retiring => Self::Retiring,
2883            meerkat_core::ops_lifecycle::OperationStatus::Completed => Self::Completed,
2884            meerkat_core::ops_lifecycle::OperationStatus::Failed => Self::Failed,
2885            meerkat_core::ops_lifecycle::OperationStatus::Aborted => Self::Aborted,
2886            meerkat_core::ops_lifecycle::OperationStatus::Cancelled => Self::Cancelled,
2887            meerkat_core::ops_lifecycle::OperationStatus::Retired => Self::Retired,
2888            meerkat_core::ops_lifecycle::OperationStatus::Terminated => Self::Terminated,
2889        }
2890    }
2891}
2892
2893impl From<OperationStatus> for meerkat_core::ops_lifecycle::OperationStatus {
2894    fn from(status: OperationStatus) -> Self {
2895        match status {
2896            OperationStatus::Absent => Self::Absent,
2897            OperationStatus::Provisioning => Self::Provisioning,
2898            OperationStatus::Running => Self::Running,
2899            OperationStatus::Retiring => Self::Retiring,
2900            OperationStatus::Completed => Self::Completed,
2901            OperationStatus::Failed => Self::Failed,
2902            OperationStatus::Aborted => Self::Aborted,
2903            OperationStatus::Cancelled => Self::Cancelled,
2904            OperationStatus::Retired => Self::Retired,
2905            OperationStatus::Terminated => Self::Terminated,
2906        }
2907    }
2908}
2909
2910/// Typed discriminant mirror of
2911/// [`meerkat_core::ops_lifecycle::OperationTerminalOutcome`]. Unit variants
2912/// only; the full typed payload (completion result, failure error,
2913/// cancellation reason, terminated reason) is carried by the companion
2914/// `op_terminal_payload: Map<String, OpTerminalPayload>` field, keyed by the
2915/// same operation id. The machine guards that the payload variant matches
2916/// the discriminant on every terminal transition.
2917///
2918/// The DSL writes these variants directly on each terminal transition
2919/// (`CompleteOp`, `FailOp`, `CancelOp`, `AbortOp`, `RetireCompletedOp`,
2920/// `TerminateOp`); the shell reads the typed payload map directly — no JSON
2921/// codec, no string compares.
2922#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2923pub enum OperationTerminalOutcomeKind {
2924    #[default]
2925    Completed,
2926    Failed,
2927    Aborted,
2928    Cancelled,
2929    Retired,
2930    Terminated,
2931}
2932
2933/// Typed terminal payload carried by the ops-lifecycle authority. This IS the
2934/// domain type — the machine state stores
2935/// [`meerkat_core::ops_lifecycle::OperationTerminalOutcome`] directly, so the
2936/// shell needs no codec in either direction (K8b fold: the former
2937/// `Map<String, String>` opaque-JSON payload carrier is deleted).
2938pub type OpTerminalPayload = meerkat_core::ops_lifecycle::OperationTerminalOutcome;
2939
2940/// Result payload for completed operations, referenced by the
2941/// `OpTerminalPayload::Completed` structural variant binding.
2942pub type OperationResult = meerkat_core::ops::OperationResult;
2943
2944impl From<&OpTerminalPayload> for OperationTerminalOutcomeKind {
2945    fn from(payload: &OpTerminalPayload) -> Self {
2946        match payload {
2947            OpTerminalPayload::Completed(_) => Self::Completed,
2948            OpTerminalPayload::Failed { .. } => Self::Failed,
2949            OpTerminalPayload::Aborted { .. } => Self::Aborted,
2950            OpTerminalPayload::Cancelled { .. } => Self::Cancelled,
2951            OpTerminalPayload::Retired => Self::Retired,
2952            OpTerminalPayload::Terminated { .. } => Self::Terminated,
2953        }
2954    }
2955}
2956
2957/// Typed public result class for operation lifecycle projections. Shell/tool
2958/// surfaces may format these classes, but the lifecycle machine owns the
2959/// status-to-public-result classification.
2960#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2961pub enum OperationPublicResultClass {
2962    #[default]
2963    MissingAuthority,
2964    Running,
2965    Completed,
2966    Failed,
2967    Cancelled,
2968}
2969
2970#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2971pub enum OperationCompletionFeedClass {
2972    #[default]
2973    Emit,
2974    Suppress,
2975}
2976
2977#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2978pub enum OperationCompletionWakeClass {
2979    #[default]
2980    Wake,
2981    Ignore,
2982}
2983
2984#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2985pub enum OperationDurabilityClass {
2986    #[default]
2987    Retain,
2988    Discard,
2989}
2990
2991impl From<OperationPublicResultClass> for meerkat_core::ops_lifecycle::OperationPublicResultClass {
2992    fn from(value: OperationPublicResultClass) -> Self {
2993        match value {
2994            OperationPublicResultClass::MissingAuthority => Self::MissingAuthority,
2995            OperationPublicResultClass::Running => Self::Running,
2996            OperationPublicResultClass::Completed => Self::Completed,
2997            OperationPublicResultClass::Failed => Self::Failed,
2998            OperationPublicResultClass::Cancelled => Self::Cancelled,
2999        }
3000    }
3001}
3002
3003impl From<OperationCompletionWakeClass>
3004    for meerkat_core::ops_lifecycle::OperationCompletionWakeClass
3005{
3006    fn from(value: OperationCompletionWakeClass) -> Self {
3007        match value {
3008            OperationCompletionWakeClass::Wake => Self::Wake,
3009            OperationCompletionWakeClass::Ignore => Self::Ignore,
3010        }
3011    }
3012}
3013
3014#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3015pub enum OpRegistrationAdmissionResultKind {
3016    #[default]
3017    Accept,
3018    Reject,
3019}
3020
3021#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3022pub enum OpRegistrationRejectReasonKind {
3023    #[default]
3024    AlreadyRegistered,
3025    MaxConcurrentExceeded,
3026}
3027
3028#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3029pub enum OpLifecycleActionKind {
3030    #[default]
3031    Start,
3032    Fail,
3033    PeerReady,
3034    ProgressReported,
3035    Complete,
3036    Abort,
3037    Cancel,
3038    RetireRequested,
3039    RetireCompleted,
3040    Terminate,
3041}
3042
3043impl From<meerkat_core::ops_lifecycle::OperationLifecycleAction> for OpLifecycleActionKind {
3044    fn from(action: meerkat_core::ops_lifecycle::OperationLifecycleAction) -> Self {
3045        match action {
3046            meerkat_core::ops_lifecycle::OperationLifecycleAction::Start => Self::Start,
3047            meerkat_core::ops_lifecycle::OperationLifecycleAction::Fail => Self::Fail,
3048            meerkat_core::ops_lifecycle::OperationLifecycleAction::PeerReady => Self::PeerReady,
3049            meerkat_core::ops_lifecycle::OperationLifecycleAction::ProgressReported => {
3050                Self::ProgressReported
3051            }
3052            meerkat_core::ops_lifecycle::OperationLifecycleAction::Complete => Self::Complete,
3053            meerkat_core::ops_lifecycle::OperationLifecycleAction::Abort => Self::Abort,
3054            meerkat_core::ops_lifecycle::OperationLifecycleAction::Cancel => Self::Cancel,
3055            meerkat_core::ops_lifecycle::OperationLifecycleAction::RetireRequested => {
3056                Self::RetireRequested
3057            }
3058            meerkat_core::ops_lifecycle::OperationLifecycleAction::RetireCompleted => {
3059                Self::RetireCompleted
3060            }
3061            meerkat_core::ops_lifecycle::OperationLifecycleAction::Terminate => Self::Terminate,
3062        }
3063    }
3064}
3065
3066#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3067pub enum OpLifecycleRejectReasonKind {
3068    #[default]
3069    OperationNotFound,
3070    InvalidTransition,
3071    PeerNotExpected,
3072    AlreadyPeerReady,
3073}
3074
3075/// Typed input-abandonment reason. Closed mirror of the discriminant set of
3076/// [`crate::input_state::InputAbandonReason`] — replaces the former
3077/// `format!("{reason:?}")` Debug round-trip in the DSL's
3078/// `input_abandon_reason` map.
3079///
3080/// The `MaxAttemptsExhausted` variant's `attempts` payload rides on the
3081/// companion `input_abandon_attempt_count: Map<String, u64>` field of the
3082/// DSL state; this enum only carries the discriminant. The domain
3083/// `InputAbandonReason::MaxAttemptsExhausted { attempts }` is reconstructed
3084/// in the driver by pairing the typed discriminant with that companion map.
3085#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3086pub enum InputAbandonReason {
3087    #[default]
3088    Retired,
3089    Reset,
3090    Stopped,
3091    Destroyed,
3092    Cancelled,
3093    MaxAttemptsExhausted,
3094}
3095
3096impl From<&crate::input_state::InputAbandonReason> for InputAbandonReason {
3097    fn from(reason: &crate::input_state::InputAbandonReason) -> Self {
3098        match reason {
3099            crate::input_state::InputAbandonReason::Retired => Self::Retired,
3100            crate::input_state::InputAbandonReason::Reset => Self::Reset,
3101            crate::input_state::InputAbandonReason::Stopped => Self::Stopped,
3102            crate::input_state::InputAbandonReason::Destroyed => Self::Destroyed,
3103            crate::input_state::InputAbandonReason::Cancelled => Self::Cancelled,
3104            crate::input_state::InputAbandonReason::MaxAttemptsExhausted { .. } => {
3105                Self::MaxAttemptsExhausted
3106            }
3107        }
3108    }
3109}
3110
3111impl InputAbandonReason {
3112    /// Stable lowercase label for event wire formats. Mirrors the
3113    /// snake-case serde representation of the domain enum for consistency
3114    /// with existing consumers.
3115    pub const fn as_str(self) -> &'static str {
3116        match self {
3117            Self::Retired => "retired",
3118            Self::Reset => "reset",
3119            Self::Stopped => "stopped",
3120            Self::Destroyed => "destroyed",
3121            Self::Cancelled => "cancelled",
3122            Self::MaxAttemptsExhausted => "max_attempts_exhausted",
3123        }
3124    }
3125}
3126
3127/// Typed work-lane assignment for admitted inputs. Replaces the former
3128/// parallel `queue_lane` / `steer_lane` sets with a single map
3129/// (`input_lane: Map<String, Enum<InputLane>>`) so mutual exclusion is
3130/// structural — an admitted input is in exactly one lane by construction.
3131///
3132/// DSL-side mirror of the shell's `meerkat_core::types::HandlingMode`; the
3133/// DSL owns the typed mirror so transitions can carry it without depending
3134/// on the shell's domain enum.
3135#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3136pub enum InputLane {
3137    #[default]
3138    Queue,
3139    Steer,
3140}
3141
3142impl From<crate::HandlingMode> for InputLane {
3143    fn from(mode: crate::HandlingMode) -> Self {
3144        match mode {
3145            crate::HandlingMode::Queue => Self::Queue,
3146            crate::HandlingMode::Steer => Self::Steer,
3147        }
3148    }
3149}
3150
3151/// Typed live-admission input kind carried by `ResolveAdmissionPlan`.
3152#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3153pub enum AdmissionInputKind {
3154    #[default]
3155    Prompt,
3156    PeerMessage,
3157    PeerRequest,
3158    PeerResponseProgress,
3159    PeerResponseTerminal,
3160    FlowStep,
3161    ExternalEvent,
3162    Continuation,
3163    Operation,
3164}
3165
3166/// Typed continuation discriminant carried by `ResolveAdmissionPlan`. The DSL
3167/// owns the typed mirror of the shell's `ContinuationKind` so the lane and
3168/// run-apply semantics for WorkGraph attention re-entry are machine-emitted.
3169#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3170pub enum AdmissionContinuationKind {
3171    #[default]
3172    Ordinary,
3173    WorkgraphAttention,
3174}
3175
3176impl From<crate::input::ContinuationKind> for AdmissionContinuationKind {
3177    fn from(kind: crate::input::ContinuationKind) -> Self {
3178        match kind {
3179            crate::input::ContinuationKind::Ordinary => Self::Ordinary,
3180            crate::input::ContinuationKind::WorkgraphAttention => Self::WorkgraphAttention,
3181        }
3182    }
3183}
3184
3185/// Typed durability class observed on an input.
3186#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3187pub enum InputDurabilityKind {
3188    #[default]
3189    Durable,
3190    Ephemeral,
3191    Derived,
3192    Missing,
3193}
3194
3195impl From<crate::input::InputDurability> for InputDurabilityKind {
3196    fn from(durability: crate::input::InputDurability) -> Self {
3197        match durability {
3198            crate::input::InputDurability::Durable => Self::Durable,
3199            crate::input::InputDurability::Ephemeral => Self::Ephemeral,
3200            crate::input::InputDurability::Derived => Self::Derived,
3201        }
3202    }
3203}
3204
3205impl From<Option<crate::input::InputDurability>> for InputDurabilityKind {
3206    fn from(durability: Option<crate::input::InputDurability>) -> Self {
3207        durability.map(Self::from).unwrap_or(Self::Missing)
3208    }
3209}
3210
3211/// Typed input-origin class observed at live admission.
3212#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3213pub enum AdmissionInputOriginKind {
3214    #[default]
3215    Operator,
3216    Peer,
3217    Flow,
3218    System,
3219    External,
3220}
3221
3222impl From<&crate::input::InputOrigin> for AdmissionInputOriginKind {
3223    fn from(origin: &crate::input::InputOrigin) -> Self {
3224        match origin {
3225            crate::input::InputOrigin::Operator => Self::Operator,
3226            crate::input::InputOrigin::Peer { .. } => Self::Peer,
3227            crate::input::InputOrigin::Flow { .. } => Self::Flow,
3228            crate::input::InputOrigin::System => Self::System,
3229            crate::input::InputOrigin::External { .. } => Self::External,
3230        }
3231    }
3232}
3233
3234impl From<crate::identifiers::InputKind> for AdmissionInputKind {
3235    fn from(kind: crate::identifiers::InputKind) -> Self {
3236        match kind {
3237            crate::identifiers::InputKind::Prompt => Self::Prompt,
3238            crate::identifiers::InputKind::PeerMessage => Self::PeerMessage,
3239            crate::identifiers::InputKind::PeerRequest => Self::PeerRequest,
3240            crate::identifiers::InputKind::PeerResponseProgress => Self::PeerResponseProgress,
3241            crate::identifiers::InputKind::PeerResponseTerminal => Self::PeerResponseTerminal,
3242            crate::identifiers::InputKind::FlowStep => Self::FlowStep,
3243            crate::identifiers::InputKind::ExternalEvent => Self::ExternalEvent,
3244            crate::identifiers::InputKind::Continuation => Self::Continuation,
3245            crate::identifiers::InputKind::Operation => Self::Operation,
3246        }
3247    }
3248}
3249
3250#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3251pub enum AdmissionPolicyApplyMode {
3252    #[default]
3253    StageRunStart,
3254    StageRunBoundary,
3255    InjectNow,
3256    Ignore,
3257}
3258
3259impl From<AdmissionPolicyApplyMode> for crate::policy::ApplyMode {
3260    fn from(mode: AdmissionPolicyApplyMode) -> Self {
3261        match mode {
3262            AdmissionPolicyApplyMode::StageRunStart => Self::StageRunStart,
3263            AdmissionPolicyApplyMode::StageRunBoundary => Self::StageRunBoundary,
3264            AdmissionPolicyApplyMode::InjectNow => Self::InjectNow,
3265            AdmissionPolicyApplyMode::Ignore => Self::Ignore,
3266        }
3267    }
3268}
3269
3270impl From<crate::policy::ApplyMode> for AdmissionPolicyApplyMode {
3271    fn from(mode: crate::policy::ApplyMode) -> Self {
3272        match mode {
3273            crate::policy::ApplyMode::StageRunStart => Self::StageRunStart,
3274            crate::policy::ApplyMode::StageRunBoundary => Self::StageRunBoundary,
3275            crate::policy::ApplyMode::InjectNow => Self::InjectNow,
3276            crate::policy::ApplyMode::Ignore => Self::Ignore,
3277        }
3278    }
3279}
3280
3281#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3282pub enum AdmissionPolicyWakeMode {
3283    #[default]
3284    WakeIfIdle,
3285    InterruptYielding,
3286    None,
3287}
3288
3289impl From<AdmissionPolicyWakeMode> for crate::policy::WakeMode {
3290    fn from(mode: AdmissionPolicyWakeMode) -> Self {
3291        match mode {
3292            AdmissionPolicyWakeMode::WakeIfIdle => Self::WakeIfIdle,
3293            AdmissionPolicyWakeMode::InterruptYielding => Self::InterruptYielding,
3294            AdmissionPolicyWakeMode::None => Self::None,
3295        }
3296    }
3297}
3298
3299#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3300pub enum AdmissionPolicyQueueMode {
3301    None,
3302    #[default]
3303    Fifo,
3304    Coalesce,
3305    Supersede,
3306    Priority,
3307}
3308
3309impl From<AdmissionPolicyQueueMode> for crate::policy::QueueMode {
3310    fn from(mode: AdmissionPolicyQueueMode) -> Self {
3311        match mode {
3312            AdmissionPolicyQueueMode::None => Self::None,
3313            AdmissionPolicyQueueMode::Fifo => Self::Fifo,
3314            AdmissionPolicyQueueMode::Coalesce => Self::Coalesce,
3315            AdmissionPolicyQueueMode::Supersede => Self::Supersede,
3316            AdmissionPolicyQueueMode::Priority => Self::Priority,
3317        }
3318    }
3319}
3320
3321#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3322pub enum AdmissionPolicyConsumePoint {
3323    OnAccept,
3324    OnApply,
3325    OnRunStart,
3326    #[default]
3327    OnRunComplete,
3328    ExplicitAck,
3329}
3330
3331impl From<AdmissionPolicyConsumePoint> for crate::policy::ConsumePoint {
3332    fn from(point: AdmissionPolicyConsumePoint) -> Self {
3333        match point {
3334            AdmissionPolicyConsumePoint::OnAccept => Self::OnAccept,
3335            AdmissionPolicyConsumePoint::OnApply => Self::OnApply,
3336            AdmissionPolicyConsumePoint::OnRunStart => Self::OnRunStart,
3337            AdmissionPolicyConsumePoint::OnRunComplete => Self::OnRunComplete,
3338            AdmissionPolicyConsumePoint::ExplicitAck => Self::ExplicitAck,
3339        }
3340    }
3341}
3342
3343#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3344pub enum AdmissionPolicyDrainPolicy {
3345    #[default]
3346    QueueNextTurn,
3347    SteerBatch,
3348    Immediate,
3349    Ignore,
3350}
3351
3352impl From<AdmissionPolicyDrainPolicy> for crate::policy::DrainPolicy {
3353    fn from(policy: AdmissionPolicyDrainPolicy) -> Self {
3354        match policy {
3355            AdmissionPolicyDrainPolicy::QueueNextTurn => Self::QueueNextTurn,
3356            AdmissionPolicyDrainPolicy::SteerBatch => Self::SteerBatch,
3357            AdmissionPolicyDrainPolicy::Immediate => Self::Immediate,
3358            AdmissionPolicyDrainPolicy::Ignore => Self::Ignore,
3359        }
3360    }
3361}
3362
3363#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3364pub enum AdmissionRoutingDisposition {
3365    #[default]
3366    Queue,
3367    Steer,
3368    Immediate,
3369    Drop,
3370}
3371
3372impl From<AdmissionRoutingDisposition> for crate::policy::RoutingDisposition {
3373    fn from(disposition: AdmissionRoutingDisposition) -> Self {
3374        match disposition {
3375            AdmissionRoutingDisposition::Queue => Self::Queue,
3376            AdmissionRoutingDisposition::Steer => Self::Steer,
3377            AdmissionRoutingDisposition::Immediate => Self::Immediate,
3378            AdmissionRoutingDisposition::Drop => Self::Drop,
3379        }
3380    }
3381}
3382
3383#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3384pub enum AdmissionRunApplyBoundary {
3385    #[default]
3386    RunStart,
3387    RunCheckpoint,
3388    Immediate,
3389}
3390
3391impl From<AdmissionRunApplyBoundary> for meerkat_core::lifecycle::run_primitive::RunApplyBoundary {
3392    fn from(boundary: AdmissionRunApplyBoundary) -> Self {
3393        match boundary {
3394            AdmissionRunApplyBoundary::RunStart => Self::RunStart,
3395            AdmissionRunApplyBoundary::RunCheckpoint => Self::RunCheckpoint,
3396            AdmissionRunApplyBoundary::Immediate => Self::Immediate,
3397        }
3398    }
3399}
3400
3401#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3402pub enum AdmissionRuntimeExecutionKind {
3403    #[default]
3404    ContentTurn,
3405    ResumePending,
3406}
3407
3408impl From<AdmissionRuntimeExecutionKind> for meerkat_core::lifecycle::RuntimeExecutionKind {
3409    fn from(kind: AdmissionRuntimeExecutionKind) -> Self {
3410        match kind {
3411            AdmissionRuntimeExecutionKind::ContentTurn => Self::ContentTurn,
3412            AdmissionRuntimeExecutionKind::ResumePending => Self::ResumePending,
3413        }
3414    }
3415}
3416
3417#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3418pub enum AdmissionPeerResponseTerminalApplyIntent {
3419    #[default]
3420    AppendContextAndRun,
3421}
3422
3423impl From<AdmissionPeerResponseTerminalApplyIntent>
3424    for meerkat_core::lifecycle::run_primitive::PeerResponseTerminalApplyIntent
3425{
3426    fn from(intent: AdmissionPeerResponseTerminalApplyIntent) -> Self {
3427        match intent {
3428            AdmissionPeerResponseTerminalApplyIntent::AppendContextAndRun => {
3429                Self::AppendContextAndRun
3430            }
3431        }
3432    }
3433}
3434
3435#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3436pub enum AdmissionPlanKind {
3437    ConsumedOnAccept,
3438    #[default]
3439    Queued,
3440}
3441
3442#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3443pub enum AdmissionIdempotencyResultKind {
3444    #[default]
3445    Accept,
3446    Deduplicated,
3447}
3448
3449#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3450pub enum AdmissionValidationResultKind {
3451    #[default]
3452    Accept,
3453    Reject,
3454}
3455
3456#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3457pub enum PeerResponseTerminalObservedStatus {
3458    #[default]
3459    NotPeerTerminal,
3460    Completed,
3461    Failed,
3462    Cancelled,
3463}
3464
3465/// Typed admission-validation rejection reason emitted on
3466/// `AdmissionValidationResolved`. The machine names which validation rule
3467/// fired; shells render display text from this fact instead of mirroring the
3468/// guard rules.
3469#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3470pub enum AdmissionRejectReasonKind {
3471    #[default]
3472    DurabilityMissing,
3473    ExternalDerivedDurabilityForbidden,
3474    DerivedDurabilityForbiddenForInputKind,
3475    PeerHandlingModeInvalid,
3476    PeerResponseTerminalInvalid,
3477}
3478
3479#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3480pub enum WaitAllAdmissionResultKind {
3481    #[default]
3482    Accept,
3483    Reject,
3484}
3485
3486#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3487pub enum WaitAllRejectReasonKind {
3488    #[default]
3489    DuplicateOperation,
3490    WaitAlreadyActive,
3491    OperationNotFound,
3492}
3493
3494#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3495pub enum RecoveredInputNormalizationReasonKind {
3496    #[default]
3497    QueueAccepted,
3498    RollbackStaged,
3499    BoundaryReceiptCommitted,
3500    MissingBoundaryReceipt,
3501}
3502
3503#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3504pub enum AdmissionQueueActionKind {
3505    #[default]
3506    None,
3507    EnqueueTo,
3508    EnqueueFront,
3509}
3510
3511#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3512pub enum AdmissionExistingQueuedActionKind {
3513    #[default]
3514    None,
3515    Coalesce,
3516    Supersede,
3517}
3518
3519/// Typed persisted input kind carried by recovered-admission witnesses.
3520#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3521pub enum RecoveredInputKind {
3522    #[default]
3523    Prompt,
3524    PeerMessage,
3525    PeerRequest,
3526    PeerResponseProgress,
3527    PeerResponseTerminal,
3528    FlowStep,
3529    ExternalEvent,
3530    Continuation,
3531    Operation,
3532}
3533
3534/// Generated recovery disposition for a persisted input row.
3535#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3536pub enum RecoveredInputRecoveryDisposition {
3537    #[default]
3538    Retain,
3539    Discard,
3540}
3541
3542impl From<crate::identifiers::InputKind> for RecoveredInputKind {
3543    fn from(kind: crate::identifiers::InputKind) -> Self {
3544        match kind {
3545            crate::identifiers::InputKind::Prompt => Self::Prompt,
3546            crate::identifiers::InputKind::PeerMessage => Self::PeerMessage,
3547            crate::identifiers::InputKind::PeerRequest => Self::PeerRequest,
3548            crate::identifiers::InputKind::PeerResponseProgress => Self::PeerResponseProgress,
3549            crate::identifiers::InputKind::PeerResponseTerminal => Self::PeerResponseTerminal,
3550            crate::identifiers::InputKind::FlowStep => Self::FlowStep,
3551            crate::identifiers::InputKind::ExternalEvent => Self::ExternalEvent,
3552            crate::identifiers::InputKind::Continuation => Self::Continuation,
3553            crate::identifiers::InputKind::Operation => Self::Operation,
3554        }
3555    }
3556}
3557
3558/// Typed persisted runtime apply boundary carried by recovered-admission
3559/// witnesses.
3560#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3561pub enum RecoveredRunApplyBoundary {
3562    #[default]
3563    RunStart,
3564    RunCheckpoint,
3565    Immediate,
3566}
3567
3568impl TryFrom<meerkat_core::lifecycle::run_primitive::RunApplyBoundary>
3569    for RecoveredRunApplyBoundary
3570{
3571    type Error = &'static str;
3572
3573    fn try_from(
3574        boundary: meerkat_core::lifecycle::run_primitive::RunApplyBoundary,
3575    ) -> Result<Self, Self::Error> {
3576        match boundary {
3577            meerkat_core::lifecycle::run_primitive::RunApplyBoundary::RunStart => {
3578                Ok(Self::RunStart)
3579            }
3580            meerkat_core::lifecycle::run_primitive::RunApplyBoundary::RunCheckpoint => {
3581                Ok(Self::RunCheckpoint)
3582            }
3583            meerkat_core::lifecycle::run_primitive::RunApplyBoundary::Immediate => {
3584                Ok(Self::Immediate)
3585            }
3586            _ => Err("unknown recovered runtime boundary"),
3587        }
3588    }
3589}
3590
3591/// Typed persisted runtime execution class carried by recovered-admission
3592/// witnesses.
3593#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3594pub enum RecoveredRuntimeExecutionKind {
3595    #[default]
3596    ContentTurn,
3597    ResumePending,
3598}
3599
3600impl From<meerkat_core::lifecycle::RuntimeExecutionKind> for RecoveredRuntimeExecutionKind {
3601    fn from(kind: meerkat_core::lifecycle::RuntimeExecutionKind) -> Self {
3602        match kind {
3603            meerkat_core::lifecycle::RuntimeExecutionKind::ContentTurn => Self::ContentTurn,
3604            meerkat_core::lifecycle::RuntimeExecutionKind::ResumePending => Self::ResumePending,
3605        }
3606    }
3607}
3608
3609/// Typed recovered terminal peer-response apply intent.
3610#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3611pub enum RecoveredPeerResponseTerminalApplyIntent {
3612    #[default]
3613    AppendContextAndRun,
3614}
3615
3616impl From<meerkat_core::lifecycle::run_primitive::PeerResponseTerminalApplyIntent>
3617    for RecoveredPeerResponseTerminalApplyIntent
3618{
3619    fn from(
3620        intent: meerkat_core::lifecycle::run_primitive::PeerResponseTerminalApplyIntent,
3621    ) -> Self {
3622        match intent {
3623            meerkat_core::lifecycle::run_primitive::PeerResponseTerminalApplyIntent::AppendContextAndRun => {
3624                Self::AppendContextAndRun
3625            }
3626        }
3627    }
3628}
3629
3630#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3631pub enum RoutingSwitchTurnPhase {
3632    #[default]
3633    Requested,
3634    PendingForBoundary,
3635    ActiveFiniteOverride,
3636    ApplyingPersistentReconfigure,
3637    Terminal,
3638}
3639
3640#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3641pub enum RoutingSwitchTurnTerminal {
3642    #[default]
3643    Denied,
3644    ConsumedAndRestored,
3645    PersistentReconfigureApplied,
3646}
3647
3648#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3649pub enum RoutingDenialReason {
3650    #[default]
3651    CapabilityPolicy,
3652    ApprovalRequiredButUnavailable,
3653    DeniedDuringApproval,
3654    ScopedOverrideConflict,
3655    RealtimeTransportConflict,
3656}
3657
3658#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3659pub enum RoutingSwitchApprovalReason {
3660    #[default]
3661    CrossProvider,
3662    CostExceedsThreshold,
3663    SafetyHold,
3664    UntilChangedFromModelOrigin,
3665    RealtimeDetachRequired,
3666}
3667
3668#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3669pub enum RoutingImageApprovalReason {
3670    #[default]
3671    CrossProvider,
3672    CostExceedsThreshold,
3673    SafetyHold,
3674    RealtimeDetachRequired,
3675}
3676
3677#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3678pub enum RoutingImagePlanDenialReason {
3679    #[default]
3680    UnsupportedTarget,
3681    UnsupportedCount,
3682    CapabilityPolicy,
3683    CostPolicy,
3684    SafetyPolicy,
3685    ApprovalRequiredButUnavailable,
3686    DeniedDuringApproval,
3687    ScopedOverrideConflict,
3688    RealtimeTransportConflict,
3689    ProjectionUnsupported,
3690}
3691
3692#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3693pub enum RoutingApprovalPhase {
3694    #[default]
3695    Pending,
3696    PresentedToUser,
3697    Approved,
3698    Denied,
3699    SurfaceDetached,
3700}
3701
3702#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3703pub enum RoutingApprovalParentKind {
3704    #[default]
3705    SwitchTurn,
3706    ImageOperation,
3707}
3708
3709#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3710pub enum RoutingImageOperationPhase {
3711    #[default]
3712    Requested,
3713    PlanResolved,
3714    ScopedOverrideActive,
3715    ProviderCallInFlight,
3716    ResultCommitted,
3717    RestoringScopedOverride,
3718    Terminal,
3719}
3720
3721#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3722pub enum RoutingImageTerminal {
3723    #[default]
3724    Generated,
3725    Denied,
3726    EmptyResult,
3727    RefusedByProvider,
3728    SafetyFiltered,
3729    Failed,
3730    Cancelled,
3731    Timeout,
3732    ScopedRestoreFailed,
3733}
3734
3735#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3736pub enum RoutingImageTerminalObservation {
3737    #[default]
3738    Generated,
3739    EmptyResult,
3740    ProviderHttpError,
3741    ProviderNativeError,
3742    ExecutionFailed,
3743    BlobCommitFailed,
3744}
3745
3746#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3747pub enum RoutingImageProviderErrorCode {
3748    #[default]
3749    Unknown,
3750    OpenAiContentFilter,
3751    OpenAiModelRefusal,
3752    GeminiSafety,
3753    GeminiModelRefusal,
3754    GeminiDeadlineExceeded,
3755}
3756
3757#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3758pub enum RoutingProviderTextDisposition {
3759    #[default]
3760    NotEmitted,
3761    Captured,
3762    EmittedButNotStored,
3763}
3764
3765/// Typed bridge command class for supervisor-authorized mob peer overlay
3766/// observations. The runtime submits this as part of the generated
3767/// MeerkatMachine overlay authorization input so the bridge surface does not
3768/// decide whether the command peer should be present or absent.
3769#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3770pub enum MobPeerOverlayCommandKind {
3771    #[default]
3772    Wire,
3773    Unwire,
3774}
3775
3776/// Generated admission result for supervisor bridge commands that require an
3777/// already-bound supervisor. The bridge shell may project this result to the
3778/// wire response, but it must not classify binding/epoch/sender admission from
3779/// snapshots on its own.
3780#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3781pub enum SupervisorBridgeCommandAdmissionResultKind {
3782    #[default]
3783    Accept,
3784    ResumePendingRevoke,
3785    Reject,
3786}
3787
3788/// Generated public rejection class for supervisor bridge command admission.
3789#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3790pub enum SupervisorBridgeCommandRejectionKind {
3791    #[default]
3792    NotBound,
3793    StaleSupervisor,
3794    SenderMismatch,
3795    CommandNotAllowed,
3796}
3797
3798/// Closed supervisor cleanup command class. These commands retain narrowly
3799/// modeled access after ordinary runtime work has closed.
3800#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3801pub enum SupervisorCleanupCommandKind {
3802    #[default]
3803    Retire,
3804    Observe,
3805    Destroy,
3806    Revoke,
3807}
3808
3809/// Generated admission result for `BindMember`, before bootstrap transport
3810/// checks or supervisor binding mutation.
3811#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3812pub enum SupervisorBindAdmissionResultKind {
3813    #[default]
3814    Bootstrap,
3815    IdempotentAck,
3816    Reject,
3817}
3818
3819/// Generated public rejection class for `BindMember` admission.
3820#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3821pub enum SupervisorBindRejectionKind {
3822    #[default]
3823    AlreadyBound,
3824    SenderMismatch,
3825    RevocationPending,
3826}
3827
3828/// Generated material-admission verdict for `BindMember`. Owns the
3829/// transport/identity equality checks the shell previously decided inline:
3830/// advertised-address match, raw supervisor-peer sender match, expected
3831/// runtime peer-id match, and bootstrap-token match. The shell extracts the
3832/// four pure boolean observations and mirrors this verdict in the precedence
3833/// order address → sender → peer-id → token, else accept.
3834#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3835pub enum SupervisorBindMaterialAdmissionKind {
3836    #[default]
3837    Accept,
3838    AddressMismatch,
3839    SenderMismatch,
3840    InvalidPeerSpec,
3841    InvalidBootstrapToken,
3842}
3843
3844/// Generated session-liveness verdict for an attempted transcript edit (fork /
3845/// rewrite / restore). Owns the `SESSION_BUSY` disjunction the shell previously
3846/// decided inline: a session is busy iff its runtime is running OR it holds any
3847/// active inputs. The shell extracts the two pure boolean observations
3848/// (`runtime_running`, `has_active_inputs`) and mirrors this verdict.
3849#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3850pub enum TranscriptEditAdmissionKind {
3851    #[default]
3852    Admissible,
3853    DeniedBusy,
3854}
3855
3856/// Generated admission result for `AuthorizeSupervisor`.
3857#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3858pub enum SupervisorAuthorizeAdmissionResultKind {
3859    #[default]
3860    Proceed,
3861    IdempotentAck,
3862    Reject,
3863}
3864
3865#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3866pub enum SupervisorRotationPhase {
3867    #[default]
3868    PreviousRevokePending,
3869    NextPublishPending,
3870    Completed,
3871    Rejected,
3872}
3873
3874#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3875pub enum SupervisorRotationSubmissionResultKind {
3876    #[default]
3877    New,
3878    ExistingPending,
3879    ExistingTerminal,
3880    Rejected,
3881    Conflict,
3882}
3883
3884#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3885pub enum SupervisorRotationObservationStatusKind {
3886    #[default]
3887    NotFound,
3888    PreviousRevokePending,
3889    NextPublishPending,
3890    Completed,
3891    Rejected,
3892}
3893
3894#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3895pub enum SupervisorRotationRejectionKind {
3896    #[default]
3897    OperationConflict,
3898    NotBound,
3899    SenderMismatch,
3900    TargetEpochNotAdvanced,
3901    InvalidTarget,
3902    UnsupportedProtocolVersion,
3903}
3904
3905/// Generated public rejection class for `AuthorizeSupervisor` admission.
3906#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3907pub enum SupervisorAuthorizeRejectionKind {
3908    #[default]
3909    NotBound,
3910    StaleSupervisor,
3911    SenderMismatch,
3912    RotationNotAllowed,
3913}
3914
3915// Track-B (R5): declarative peer endpoint descriptor for the runtime
3916// DSL. Shape mirrors `meerkat_core::comms::TrustedPeerDescriptor`.
3917// The catalog DSL holds an identical type; the two are structurally
3918// equivalent so the schema validator sees consistent opaque struct
3919// shapes.
3920#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3921pub struct PeerEndpoint {
3922    pub name: PeerName,
3923    pub peer_id: PeerId,
3924    pub address: PeerAddress,
3925    pub signing_key: PeerSigningKey,
3926}
3927
3928impl PeerEndpoint {
3929    pub fn new(
3930        name: impl Into<PeerName>,
3931        peer_id: impl Into<PeerId>,
3932        address: impl Into<PeerAddress>,
3933        signing_key: impl Into<PeerSigningKey>,
3934    ) -> Self {
3935        Self {
3936            name: name.into(),
3937            peer_id: peer_id.into(),
3938            address: address.into(),
3939            signing_key: signing_key.into(),
3940        }
3941    }
3942}
3943
3944impl From<&meerkat_core::comms::TrustedPeerDescriptor> for PeerEndpoint {
3945    fn from(spec: &meerkat_core::comms::TrustedPeerDescriptor) -> Self {
3946        Self {
3947            name: PeerName(spec.name.as_str().to_owned()),
3948            peer_id: PeerId(spec.peer_id.to_string()),
3949            address: PeerAddress(spec.address.to_string()),
3950            signing_key: PeerSigningKey(spec.pubkey),
3951        }
3952    }
3953}
3954
3955/// DSL-local carrier for the Ed25519 public signing key associated with a
3956/// peer endpoint. The MeerkatMachine owns this projection alongside the
3957/// endpoint identity atoms so trust reconciliation can install the exact
3958/// key into the comms trust store without shell-side defaults.
3959#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3960pub struct PeerSigningKey(pub [u8; 32]);
3961
3962impl From<[u8; 32]> for PeerSigningKey {
3963    fn from(key: [u8; 32]) -> Self {
3964        Self(key)
3965    }
3966}
3967
3968/// DSL-local newtype for a peer display name. Wraps the slug string
3969/// so the schema validator sees a stable opaque shape; mirrors
3970/// `meerkat_core::comms::PeerName` but avoids dragging the core
3971/// comms types into the DSL grammar.
3972#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3973pub struct PeerName(pub String);
3974
3975impl<T: Into<String>> From<T> for PeerName {
3976    fn from(s: T) -> Self {
3977        Self(s.into())
3978    }
3979}
3980
3981impl PeerName {
3982    pub fn as_str(&self) -> &str {
3983        &self.0
3984    }
3985}
3986
3987/// DSL-local newtype for the canonical peer routing id.
3988#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3989pub struct PeerId(pub String);
3990
3991impl<T: Into<String>> From<T> for PeerId {
3992    fn from(s: T) -> Self {
3993        Self(s.into())
3994    }
3995}
3996
3997impl PeerId {
3998    pub fn as_str(&self) -> &str {
3999        &self.0
4000    }
4001}
4002
4003/// DSL-local newtype for a peer transport endpoint URL.
4004#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
4005pub struct PeerAddress(pub String);
4006
4007impl<T: Into<String>> From<T> for PeerAddress {
4008    fn from(s: T) -> Self {
4009        Self(s.into())
4010    }
4011}
4012
4013impl PeerAddress {
4014    pub fn as_str(&self) -> &str {
4015        &self.0
4016    }
4017}
4018
4019// Ensure we keep the exact generated schema DSL body from the catalog source.
4020
4021// MeerkatMachine production body is catalog-owned. Keep bridge/runtime mechanics
4022// outside this macro invocation; canonical semantics live in the catalog DSL.
4023meerkat_machine_schema::meerkat_catalog_machine_dsl!("meerkat-runtime", "meerkat_machine::dsl");
4024
4025pub type MobToolCallerProvenance = meerkat_core::service::MobToolCallerProvenance;
4026pub type OpaquePrincipalToken = meerkat_core::service::OpaquePrincipalToken;
4027
4028// =====================================================================