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). Mirror of [`meerkat_core::InteractionStreamState`].
867#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
868pub enum InteractionStreamState {
869    #[default]
870    Reserved,
871    Attached,
872    Completed,
873    Expired,
874    ClosedEarly,
875}
876
877impl From<meerkat_core::InteractionStreamState> for InteractionStreamState {
878    #[allow(clippy::panic)]
879    fn from(s: meerkat_core::InteractionStreamState) -> Self {
880        match s {
881            meerkat_core::InteractionStreamState::Reserved => Self::Reserved,
882            meerkat_core::InteractionStreamState::Attached => Self::Attached,
883            meerkat_core::InteractionStreamState::Completed => Self::Completed,
884            meerkat_core::InteractionStreamState::Expired => Self::Expired,
885            meerkat_core::InteractionStreamState::ClosedEarly => Self::ClosedEarly,
886            _ => panic!(
887                "unsupported InteractionStreamState variant; update generated MeerkatMachine mirror"
888            ),
889        }
890    }
891}
892
893impl From<InteractionStreamState> for meerkat_core::InteractionStreamState {
894    fn from(s: InteractionStreamState) -> Self {
895        match s {
896            InteractionStreamState::Reserved => Self::Reserved,
897            InteractionStreamState::Attached => Self::Attached,
898            InteractionStreamState::Completed => Self::Completed,
899            InteractionStreamState::Expired => Self::Expired,
900            InteractionStreamState::ClosedEarly => Self::ClosedEarly,
901        }
902    }
903}
904
905/// Per-server MCP connection lifecycle state. Matches the catalog copy;
906/// unit variants only so the DSL can reason about state via map inserts.
907/// Failure detail travels on the `McpServerFailed` input and
908/// `McpServerStateChanged` effect's companion fields, not on the enum.
909#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
910pub enum McpServerState {
911    #[default]
912    PendingConnect,
913    Connected,
914    Failed,
915    Disconnected,
916}
917
918/// Stable identity of a comms runtime instance (W2-G / issue #264).
919///
920/// The runtime derives this string from the `Arc<dyn CommsRuntime>` pointer
921/// address via `CommsRuntimeId::from_runtime()`. The DSL treats it as an
922/// opaque newtype; two distinct `Arc`s produce distinct ids so the owner
923/// invariant can catch silent transport swaps.
924#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
925pub struct CommsRuntimeId(pub String);
926
927impl<T: Into<String>> From<T> for CommsRuntimeId {
928    fn from(s: T) -> Self {
929        Self(s.into())
930    }
931}
932
933impl CommsRuntimeId {
934    /// Derive a stable id from an `Arc<dyn CommsRuntime>`'s pointer address.
935    ///
936    /// Two `Arc` instances with the same pointee produce the same id; two
937    /// distinct `Arc` instances produce distinct ids even if their contents
938    /// are equivalent. This is sufficient for detecting silent transport
939    /// swaps at the DSL boundary.
940    pub fn from_runtime(runtime: &std::sync::Arc<dyn meerkat_core::agent::CommsRuntime>) -> Self {
941        let ptr = std::sync::Arc::as_ptr(runtime).cast::<()>() as usize;
942        Self(format!("comms-runtime-0x{ptr:x}"))
943    }
944}
945
946/// Mob instance identifier for peer-ingress ownership (W2-G / issue #264).
947///
948/// Bridging newtype mirroring `meerkat_mob::ids::MobId`. The DSL layer keeps
949/// this opaque because `meerkat-runtime` does not depend on `meerkat-mob`;
950/// the shell stringifies the real `MobId` before firing `AttachMobIngress`.
951#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
952pub struct MobId(pub String);
953
954impl<T: Into<String>> From<T> for MobId {
955    fn from(s: T) -> Self {
956        Self(s.into())
957    }
958}
959
960/// Parsed transport envelope class for peer ingress.
961///
962/// This is the mechanical shape comms may derive from a wire envelope before
963/// semantic admission. The DSL consumes it to own the peer-input class,
964/// auth-exemption, lifecycle, silent-routing, and response-terminal facts.
965#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
966pub enum PeerIngressEnvelopeClass {
967    #[default]
968    Message,
969    Request,
970    Lifecycle,
971    Response,
972    Ack,
973}
974
975/// DSL-owned admitted ingress kind.
976#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
977pub enum PeerIngressAdmittedKind {
978    #[default]
979    Message,
980    Request,
981    Response,
982    Ack,
983    PlainEvent,
984}
985
986/// DSL-owned peer input class.
987#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
988pub enum PeerIngressInputClass {
989    #[default]
990    ActionableMessage,
991    ActionableRequest,
992    ResponseProgress,
993    ResponseTerminal,
994    PeerLifecycleAdded,
995    PeerLifecycleRetired,
996    PeerLifecycleUnwired,
997    SilentRequest,
998    Ack,
999    PlainEvent,
1000}
1001
1002/// DSL-owned peer lifecycle classifier.
1003#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1004pub enum PeerIngressLifecycleClass {
1005    #[default]
1006    PeerAdded,
1007    PeerRetired,
1008    PeerUnwired,
1009}
1010
1011/// DSL-owned peer ingress auth classifier.
1012#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1013pub enum PeerIngressAuthClass {
1014    #[default]
1015    Required,
1016    SupervisorBridgeExempt,
1017}
1018
1019/// Parsed response status for peer ingress.
1020#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1021pub enum PeerIngressResponseStatus {
1022    #[default]
1023    Accepted,
1024    Completed,
1025    Failed,
1026}
1027
1028/// Closed classifier for peer-ingress request intents that drive fixed
1029/// lifecycle routing (mob peer add/retire/unwire) plus the supervisor-bridge
1030/// channel. The machine guards on this typed class; arbitrary user-configured
1031/// silent intents remain an open set matched against the raw `request_intent`
1032/// string via `silent_intent_overrides`, so `Other` covers everything outside
1033/// the closed routing set.
1034#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1035pub enum PeerIngressRequestClass {
1036    #[default]
1037    Other,
1038    MobPeerAdded,
1039    MobPeerRetired,
1040    MobPeerUnwired,
1041    SupervisorBridge,
1042}
1043
1044/// DSL-owned response progress/terminal classifier.
1045#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1046pub enum PeerIngressResponseTerminality {
1047    #[default]
1048    Progress,
1049    TerminalCompleted,
1050    TerminalFailed,
1051}
1052
1053/// DSL-owned public peer-ingress authority phase.
1054#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1055pub enum PeerIngressAuthorityPhaseClass {
1056    #[default]
1057    Absent,
1058    Received,
1059    Dropped,
1060    Delivered,
1061}
1062
1063impl From<PeerIngressAuthorityPhaseClass> for meerkat_core::PeerIngressAuthorityPhase {
1064    fn from(phase: PeerIngressAuthorityPhaseClass) -> Self {
1065        match phase {
1066            PeerIngressAuthorityPhaseClass::Absent => Self::Absent,
1067            PeerIngressAuthorityPhaseClass::Received => Self::Received,
1068            PeerIngressAuthorityPhaseClass::Dropped => Self::Dropped,
1069            PeerIngressAuthorityPhaseClass::Delivered => Self::Delivered,
1070        }
1071    }
1072}
1073
1074/// DSL-owned receive/admission result for classified peer ingress.
1075#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1076pub enum PeerIngressReceiveOutcomeClass {
1077    #[default]
1078    Admitted,
1079    DroppedUntrustedSender,
1080    DroppedSessionClosed,
1081    DroppedInboxFull,
1082}
1083
1084impl From<PeerIngressReceiveOutcomeClass> for meerkat_core::PeerIngressReceiveOutcome {
1085    fn from(outcome: PeerIngressReceiveOutcomeClass) -> Self {
1086        match outcome {
1087            PeerIngressReceiveOutcomeClass::Admitted => Self::Admitted,
1088            PeerIngressReceiveOutcomeClass::DroppedUntrustedSender => Self::DroppedUntrustedSender,
1089            PeerIngressReceiveOutcomeClass::DroppedSessionClosed => Self::DroppedSessionClosed,
1090            PeerIngressReceiveOutcomeClass::DroppedInboxFull => Self::DroppedInboxFull,
1091        }
1092    }
1093}
1094
1095/// DSL-owned admission diagnostic copy emitted with receive authority.
1096#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1097pub enum PeerIngressAdmissionDiagnosticClass {
1098    #[default]
1099    TrustedAtAdmission,
1100    UntrustedAtAdmission,
1101}
1102
1103impl From<PeerIngressAdmissionDiagnosticClass> for meerkat_core::PeerIngressAdmissionDiagnostic {
1104    fn from(diagnostic: PeerIngressAdmissionDiagnosticClass) -> Self {
1105        match diagnostic {
1106            PeerIngressAdmissionDiagnosticClass::TrustedAtAdmission => Self::TrustedAtAdmission,
1107            PeerIngressAdmissionDiagnosticClass::UntrustedAtAdmission => Self::UntrustedAtAdmission,
1108        }
1109    }
1110}
1111
1112/// Peer-ingress transport capability ownership kind (W2-G / issue #264).
1113///
1114/// Paired with `peer_ingress_comms_runtime_id` and `peer_ingress_mob_id` in
1115/// DSL state; `peer_ingress_owner_consistency` enforces pairing. Silent
1116/// downgrade `MobOwned` → `SessionOwned` is structurally impossible:
1117/// `AttachSessionIngress` requires `Unattached`; `AttachMobIngress` permits
1118/// `Unattached` or `SessionOwned` but never `MobOwned` → `SessionOwned`.
1119#[derive(
1120    Debug,
1121    Clone,
1122    Copy,
1123    PartialEq,
1124    Eq,
1125    PartialOrd,
1126    Ord,
1127    Hash,
1128    Default,
1129    serde::Serialize,
1130    serde::Deserialize,
1131)]
1132pub enum PeerIngressOwnerKind {
1133    #[default]
1134    Unattached,
1135    SessionOwned,
1136    MobOwned,
1137}
1138
1139/// Supervisor-bridge authorization kind (Wave 3 D Row 21).
1140///
1141/// Paired with `supervisor_bound_{name, peer_id, address, epoch}` in DSL
1142/// state; `supervisor_binding_consistency` enforces pairing. Rotation is
1143/// structural: `BindSupervisor` requires `Unbound`; `AuthorizeSupervisor`
1144/// requires `Bound`; `RevokeSupervisor` requires `Bound` and returns to
1145/// `Unbound`. Before Wave 3 D this fact lived as an `Option<AuthorizedSupervisorState>`
1146/// on the comms drain task's stack — the identity and epoch of the
1147/// authorized supervisor were helper-local while the corresponding trust
1148/// edge was router-owned. Moving the authorization discriminant + epoch
1149/// into DSL state collapses that split ownership.
1150#[derive(
1151    Debug,
1152    Clone,
1153    Copy,
1154    PartialEq,
1155    Eq,
1156    PartialOrd,
1157    Ord,
1158    Hash,
1159    Default,
1160    serde::Serialize,
1161    serde::Deserialize,
1162)]
1163pub enum SupervisorBindingKind {
1164    #[default]
1165    Unbound,
1166    Bound,
1167}
1168
1169/// Typed turn-execution phase, mirrored 1:1 by the closed set of literals the
1170/// DSL transitions assign to `turn_phase`. Replaces the prior stringly-typed
1171/// encoding so the ephemeral driver and runtime handles consume an exhaustive
1172/// enum instead of parsing folklore.
1173#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1174pub enum TurnPhase {
1175    #[default]
1176    Ready,
1177    ApplyingPrimitive,
1178    CallingLlm,
1179    WaitingForOps,
1180    DrainingBoundary,
1181    Extracting,
1182    ErrorRecovery,
1183    Cancelling,
1184    Completed,
1185    Failed,
1186    Cancelled,
1187}
1188
1189impl TurnPhase {
1190    pub const fn as_str(self) -> &'static str {
1191        match self {
1192            Self::Ready => "Ready",
1193            Self::ApplyingPrimitive => "ApplyingPrimitive",
1194            Self::CallingLlm => "CallingLlm",
1195            Self::WaitingForOps => "WaitingForOps",
1196            Self::DrainingBoundary => "DrainingBoundary",
1197            Self::Extracting => "Extracting",
1198            Self::ErrorRecovery => "ErrorRecovery",
1199            Self::Cancelling => "Cancelling",
1200            Self::Completed => "Completed",
1201            Self::Failed => "Failed",
1202            Self::Cancelled => "Cancelled",
1203        }
1204    }
1205}
1206
1207/// Typed registration substate. Closed set of literals previously assigned to
1208/// `registration_phase`.
1209#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1210pub enum RegistrationPhase {
1211    #[default]
1212    Queuing,
1213    Active,
1214    Draining,
1215}
1216
1217impl RegistrationPhase {
1218    pub const fn as_str(self) -> &'static str {
1219        match self {
1220            Self::Queuing => "Queuing",
1221            Self::Active => "Active",
1222            Self::Draining => "Draining",
1223        }
1224    }
1225}
1226
1227/// Typed comms drain substate. Mirrors the closed set of literals the DSL
1228/// transitions assign to `drain_phase`.
1229#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1230pub enum DrainPhase {
1231    #[default]
1232    Inactive,
1233    Running,
1234    Stopped,
1235    ExitedRespawnable,
1236}
1237
1238impl DrainPhase {
1239    pub const fn as_str(self) -> &'static str {
1240        match self {
1241            Self::Inactive => "Inactive",
1242            Self::Running => "Running",
1243            Self::Stopped => "Stopped",
1244            Self::ExitedRespawnable => "ExitedRespawnable",
1245        }
1246    }
1247}
1248
1249/// Typed comms drain mode. Mirrors `crate::meerkat_machine::CommsDrainMode`
1250/// (which is the shell-side enum) so the DSL can hold a closed set of typed
1251/// variants instead of a `Debug`-formatted string.
1252#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1253pub enum DrainMode {
1254    #[default]
1255    Timed,
1256    AttachedSession,
1257    PersistentHost,
1258}
1259
1260impl DrainMode {
1261    pub const fn as_str(self) -> &'static str {
1262        match self {
1263            Self::Timed => "Timed",
1264            Self::AttachedSession => "AttachedSession",
1265            Self::PersistentHost => "PersistentHost",
1266        }
1267    }
1268}
1269
1270impl From<crate::meerkat_machine::CommsDrainMode> for DrainMode {
1271    fn from(mode: crate::meerkat_machine::CommsDrainMode) -> Self {
1272        match mode {
1273            crate::meerkat_machine::CommsDrainMode::Timed => Self::Timed,
1274            crate::meerkat_machine::CommsDrainMode::AttachedSession => Self::AttachedSession,
1275            crate::meerkat_machine::CommsDrainMode::PersistentHost => Self::PersistentHost,
1276        }
1277    }
1278}
1279
1280/// Typed external-tool surface global phase. Closed set of literals previously
1281/// assigned to `surface_phase`.
1282#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1283pub enum SurfacePhase {
1284    #[default]
1285    Operating,
1286    Shutdown,
1287}
1288
1289impl SurfacePhase {
1290    pub const fn as_str(self) -> &'static str {
1291        match self {
1292            Self::Operating => "Operating",
1293            Self::Shutdown => "Shutdown",
1294        }
1295    }
1296}
1297
1298/// Typed input-lifecycle phase, mirroring the closed set of literals the DSL
1299/// transitions assign to `input_phases`. The shell projects from this onto the
1300/// richer `crate::input_state::InputLifecycleState` (which keeps an `Accepted`
1301/// pre-DSL-admission variant the DSL itself never writes).
1302#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1303pub enum InputPhase {
1304    #[default]
1305    Queued,
1306    Staged,
1307    Applied,
1308    AppliedPendingConsumption,
1309    Consumed,
1310    Superseded,
1311    Coalesced,
1312    Abandoned,
1313}
1314
1315impl InputPhase {
1316    pub const fn as_str(self) -> &'static str {
1317        match self {
1318            Self::Queued => "Queued",
1319            Self::Staged => "Staged",
1320            Self::Applied => "Applied",
1321            Self::AppliedPendingConsumption => "AppliedPendingConsumption",
1322            Self::Consumed => "Consumed",
1323            Self::Superseded => "Superseded",
1324            Self::Coalesced => "Coalesced",
1325            Self::Abandoned => "Abandoned",
1326        }
1327    }
1328}
1329
1330#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1331pub enum RecoveredInputObservedPhase {
1332    Accepted,
1333    #[default]
1334    Queued,
1335    Staged,
1336    Applied,
1337    AppliedPendingConsumption,
1338    Consumed,
1339    Superseded,
1340    Coalesced,
1341    Abandoned,
1342}
1343
1344/// Typed input terminal kind, mirroring the closed set of literals the DSL
1345/// transitions assign to `input_terminal_kind`. The companion fields
1346/// (`input_superseded_by`, `input_aggregate_id`, `input_abandon_reason`,
1347/// `input_abandon_attempt_count`) carry payload metadata for variants that
1348/// need it.
1349#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1350pub enum InputTerminalKind {
1351    #[default]
1352    Consumed,
1353    Superseded,
1354    Coalesced,
1355    Abandoned,
1356}
1357
1358impl InputTerminalKind {
1359    pub const fn as_str(self) -> &'static str {
1360        match self {
1361            Self::Consumed => "Consumed",
1362            Self::Superseded => "Superseded",
1363            Self::Coalesced => "Coalesced",
1364            Self::Abandoned => "Abandoned",
1365        }
1366    }
1367}
1368
1369/// Public lifecycle class emitted by generated authority before runtime
1370/// surfaces project input state onto their transport enums.
1371#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1372pub enum InputPublicLifecycleState {
1373    #[default]
1374    Accepted,
1375    Queued,
1376    Staged,
1377    Applied,
1378    AppliedPendingConsumption,
1379    Consumed,
1380    Superseded,
1381    Coalesced,
1382    Abandoned,
1383}
1384
1385impl InputPublicLifecycleState {
1386    pub const fn as_str(self) -> &'static str {
1387        match self {
1388            Self::Accepted => "Accepted",
1389            Self::Queued => "Queued",
1390            Self::Staged => "Staged",
1391            Self::Applied => "Applied",
1392            Self::AppliedPendingConsumption => "AppliedPendingConsumption",
1393            Self::Consumed => "Consumed",
1394            Self::Superseded => "Superseded",
1395            Self::Coalesced => "Coalesced",
1396            Self::Abandoned => "Abandoned",
1397        }
1398    }
1399}
1400
1401/// Public terminal result class emitted by generated authority before runtime
1402/// surfaces project input state onto their transport enums.
1403#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1404pub enum InputPublicTerminalOutcome {
1405    #[default]
1406    Completed,
1407    Abandoned,
1408    Superseded,
1409    Coalesced,
1410    Cancelled,
1411}
1412
1413impl InputPublicTerminalOutcome {
1414    pub const fn as_str(self) -> &'static str {
1415        match self {
1416            Self::Completed => "Completed",
1417            Self::Abandoned => "Abandoned",
1418            Self::Superseded => "Superseded",
1419            Self::Coalesced => "Coalesced",
1420            Self::Cancelled => "Cancelled",
1421        }
1422    }
1423}
1424
1425/// Typed pending external-surface op. Closed set of literals previously
1426/// assigned to `surface_pending_op`.
1427#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1428pub enum SurfacePendingOp {
1429    #[default]
1430    None,
1431    Add,
1432    Reload,
1433}
1434
1435impl SurfacePendingOp {
1436    pub const fn as_str(self) -> &'static str {
1437        match self {
1438            Self::None => "None",
1439            Self::Add => "Add",
1440            Self::Reload => "Reload",
1441        }
1442    }
1443}
1444
1445/// Typed staged external-surface op. Closed set of literals previously
1446/// assigned to `surface_staged_op`.
1447#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1448pub enum SurfaceStagedOp {
1449    #[default]
1450    None,
1451    Add,
1452    Remove,
1453    Reload,
1454}
1455
1456impl SurfaceStagedOp {
1457    pub const fn as_str(self) -> &'static str {
1458        match self {
1459            Self::None => "None",
1460            Self::Add => "Add",
1461            Self::Remove => "Remove",
1462            Self::Reload => "Reload",
1463        }
1464    }
1465}
1466
1467/// Typed turn primitive kind. Closed mirror of
1468/// [`meerkat_core::turn_execution_authority::TurnPrimitiveKind`] — replaces the
1469/// former literal-string `primitive_kind` field and `StartConversationRun`
1470/// input field.
1471#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1472pub enum TurnPrimitiveKind {
1473    #[default]
1474    None,
1475    ConversationTurn,
1476    ImmediateAppend,
1477    ImmediateContextAppend,
1478}
1479
1480impl From<meerkat_core::turn_execution_authority::TurnPrimitiveKind> for TurnPrimitiveKind {
1481    fn from(kind: meerkat_core::turn_execution_authority::TurnPrimitiveKind) -> Self {
1482        match kind {
1483            meerkat_core::turn_execution_authority::TurnPrimitiveKind::None => Self::None,
1484            meerkat_core::turn_execution_authority::TurnPrimitiveKind::ConversationTurn => {
1485                Self::ConversationTurn
1486            }
1487            meerkat_core::turn_execution_authority::TurnPrimitiveKind::ImmediateAppend => {
1488                Self::ImmediateAppend
1489            }
1490            meerkat_core::turn_execution_authority::TurnPrimitiveKind::ImmediateContextAppend => {
1491                Self::ImmediateContextAppend
1492            }
1493        }
1494    }
1495}
1496
1497impl From<TurnPrimitiveKind> for meerkat_core::turn_execution_authority::TurnPrimitiveKind {
1498    fn from(kind: TurnPrimitiveKind) -> Self {
1499        match kind {
1500            TurnPrimitiveKind::None => Self::None,
1501            TurnPrimitiveKind::ConversationTurn => Self::ConversationTurn,
1502            TurnPrimitiveKind::ImmediateAppend => Self::ImmediateAppend,
1503            TurnPrimitiveKind::ImmediateContextAppend => Self::ImmediateContextAppend,
1504        }
1505    }
1506}
1507
1508/// Typed turn primitive content shape. Closed mirror of
1509/// [`meerkat_core::turn_execution_authority::ContentShape`] so the runtime DSL
1510/// carries the same contract instead of local string labels.
1511#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1512pub enum ContentShape {
1513    #[default]
1514    Conversation,
1515    ConversationAndContext,
1516    Context,
1517    Empty,
1518    ImmediateAppend,
1519    ImmediateContext,
1520}
1521
1522impl ContentShape {
1523    pub const fn as_str(self) -> &'static str {
1524        match self {
1525            Self::Conversation => {
1526                meerkat_core::turn_execution_authority::ContentShape::Conversation.as_str()
1527            }
1528            Self::ConversationAndContext => {
1529                meerkat_core::turn_execution_authority::ContentShape::ConversationAndContext
1530                    .as_str()
1531            }
1532            Self::Context => meerkat_core::turn_execution_authority::ContentShape::Context.as_str(),
1533            Self::Empty => meerkat_core::turn_execution_authority::ContentShape::Empty.as_str(),
1534            Self::ImmediateAppend => {
1535                meerkat_core::turn_execution_authority::ContentShape::ImmediateAppend.as_str()
1536            }
1537            Self::ImmediateContext => {
1538                meerkat_core::turn_execution_authority::ContentShape::ImmediateContext.as_str()
1539            }
1540        }
1541    }
1542}
1543
1544impl std::fmt::Display for ContentShape {
1545    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1546        f.write_str(self.as_str())
1547    }
1548}
1549
1550impl From<meerkat_core::turn_execution_authority::ContentShape> for ContentShape {
1551    fn from(shape: meerkat_core::turn_execution_authority::ContentShape) -> Self {
1552        match shape {
1553            meerkat_core::turn_execution_authority::ContentShape::Conversation => {
1554                Self::Conversation
1555            }
1556            meerkat_core::turn_execution_authority::ContentShape::ConversationAndContext => {
1557                Self::ConversationAndContext
1558            }
1559            meerkat_core::turn_execution_authority::ContentShape::Context => Self::Context,
1560            meerkat_core::turn_execution_authority::ContentShape::Empty => Self::Empty,
1561            meerkat_core::turn_execution_authority::ContentShape::ImmediateAppend => {
1562                Self::ImmediateAppend
1563            }
1564            meerkat_core::turn_execution_authority::ContentShape::ImmediateContext => {
1565                Self::ImmediateContext
1566            }
1567        }
1568    }
1569}
1570
1571impl From<ContentShape> for meerkat_core::turn_execution_authority::ContentShape {
1572    fn from(shape: ContentShape) -> Self {
1573        match shape {
1574            ContentShape::Conversation => Self::Conversation,
1575            ContentShape::ConversationAndContext => Self::ConversationAndContext,
1576            ContentShape::Context => Self::Context,
1577            ContentShape::Empty => Self::Empty,
1578            ContentShape::ImmediateAppend => Self::ImmediateAppend,
1579            ContentShape::ImmediateContext => Self::ImmediateContext,
1580        }
1581    }
1582}
1583
1584/// Typed turn terminal outcome. Closed mirror of
1585/// [`meerkat_core::turn_execution_authority::TurnTerminalOutcome`] — replaces
1586/// the former literal-string `terminal_outcome` field.
1587#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1588pub enum TurnTerminalOutcome {
1589    #[default]
1590    None,
1591    Completed,
1592    Failed,
1593    Cancelled,
1594    BudgetExhausted,
1595    TimeBudgetExceeded,
1596    StructuredOutputValidationFailed,
1597}
1598
1599impl From<meerkat_core::turn_execution_authority::TurnTerminalOutcome> for TurnTerminalOutcome {
1600    fn from(outcome: meerkat_core::turn_execution_authority::TurnTerminalOutcome) -> Self {
1601        match outcome {
1602            meerkat_core::turn_execution_authority::TurnTerminalOutcome::None => Self::None,
1603            meerkat_core::turn_execution_authority::TurnTerminalOutcome::Completed => {
1604                Self::Completed
1605            }
1606            meerkat_core::turn_execution_authority::TurnTerminalOutcome::Failed => Self::Failed,
1607            meerkat_core::turn_execution_authority::TurnTerminalOutcome::Cancelled => {
1608                Self::Cancelled
1609            }
1610            meerkat_core::turn_execution_authority::TurnTerminalOutcome::BudgetExhausted => {
1611                Self::BudgetExhausted
1612            }
1613            meerkat_core::turn_execution_authority::TurnTerminalOutcome::TimeBudgetExceeded => {
1614                Self::TimeBudgetExceeded
1615            }
1616            meerkat_core::turn_execution_authority::TurnTerminalOutcome::StructuredOutputValidationFailed => {
1617                Self::StructuredOutputValidationFailed
1618            }
1619        }
1620    }
1621}
1622
1623impl From<TurnTerminalOutcome> for meerkat_core::turn_execution_authority::TurnTerminalOutcome {
1624    fn from(outcome: TurnTerminalOutcome) -> Self {
1625        match outcome {
1626            TurnTerminalOutcome::None => Self::None,
1627            TurnTerminalOutcome::Completed => Self::Completed,
1628            TurnTerminalOutcome::Failed => Self::Failed,
1629            TurnTerminalOutcome::Cancelled => Self::Cancelled,
1630            TurnTerminalOutcome::BudgetExhausted => Self::BudgetExhausted,
1631            TurnTerminalOutcome::TimeBudgetExceeded => Self::TimeBudgetExceeded,
1632            TurnTerminalOutcome::StructuredOutputValidationFailed => {
1633                Self::StructuredOutputValidationFailed
1634            }
1635        }
1636    }
1637}
1638
1639/// Typed turn terminal cause. Closed mirror of
1640/// [`meerkat_core::turn_execution_authority::TurnTerminalCauseKind`] carried by
1641/// MeerkatMachine terminal failure inputs/effects so display messages cannot
1642/// classify terminal failures.
1643#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1644pub enum TurnTerminalCauseKind {
1645    #[default]
1646    Unknown,
1647    HookDenied,
1648    HookFailure,
1649    LlmFailure,
1650    ToolFailure,
1651    StructuredOutputValidationFailed,
1652    BudgetExhausted,
1653    TimeBudgetExceeded,
1654    RetryExhausted,
1655    TurnLimitReached,
1656    RuntimeApplyFailure,
1657    FatalFailure,
1658}
1659
1660impl From<meerkat_core::turn_execution_authority::TurnTerminalCauseKind> for TurnTerminalCauseKind {
1661    fn from(kind: meerkat_core::turn_execution_authority::TurnTerminalCauseKind) -> Self {
1662        match kind {
1663            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::Unknown => {
1664                Self::Unknown
1665            }
1666            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::HookDenied => {
1667                Self::HookDenied
1668            }
1669            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::HookFailure => {
1670                Self::HookFailure
1671            }
1672            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::LlmFailure => {
1673                Self::LlmFailure
1674            }
1675            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::ToolFailure => {
1676                Self::ToolFailure
1677            }
1678            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::StructuredOutputValidationFailed => {
1679                Self::StructuredOutputValidationFailed
1680            }
1681            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::BudgetExhausted => {
1682                Self::BudgetExhausted
1683            }
1684            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::TimeBudgetExceeded => {
1685                Self::TimeBudgetExceeded
1686            }
1687            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::RetryExhausted => {
1688                Self::RetryExhausted
1689            }
1690            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::TurnLimitReached => {
1691                Self::TurnLimitReached
1692            }
1693            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::RuntimeApplyFailure => {
1694                Self::RuntimeApplyFailure
1695            }
1696            meerkat_core::turn_execution_authority::TurnTerminalCauseKind::FatalFailure => {
1697                Self::FatalFailure
1698            }
1699        }
1700    }
1701}
1702
1703impl From<TurnTerminalCauseKind> for meerkat_core::turn_execution_authority::TurnTerminalCauseKind {
1704    fn from(kind: TurnTerminalCauseKind) -> Self {
1705        match kind {
1706            TurnTerminalCauseKind::Unknown => Self::Unknown,
1707            TurnTerminalCauseKind::HookDenied => Self::HookDenied,
1708            TurnTerminalCauseKind::HookFailure => Self::HookFailure,
1709            TurnTerminalCauseKind::LlmFailure => Self::LlmFailure,
1710            TurnTerminalCauseKind::ToolFailure => Self::ToolFailure,
1711            TurnTerminalCauseKind::StructuredOutputValidationFailed => {
1712                Self::StructuredOutputValidationFailed
1713            }
1714            TurnTerminalCauseKind::BudgetExhausted => Self::BudgetExhausted,
1715            TurnTerminalCauseKind::TimeBudgetExceeded => Self::TimeBudgetExceeded,
1716            TurnTerminalCauseKind::RetryExhausted => Self::RetryExhausted,
1717            TurnTerminalCauseKind::TurnLimitReached => Self::TurnLimitReached,
1718            TurnTerminalCauseKind::RuntimeApplyFailure => Self::RuntimeApplyFailure,
1719            TurnTerminalCauseKind::FatalFailure => Self::FatalFailure,
1720        }
1721    }
1722}
1723
1724/// Normalized terminal-cause class for surface-result classification. The DSL
1725/// owns the typed mirror so the `ClassifyTurnTerminalCauseClass` /
1726/// `ResolveTurnSurfaceResult` transitions can carry it; the
1727/// `terminal_surface_mapping` codegen derives the classification table from
1728/// those transitions.
1729#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1730pub enum TerminalCauseClass {
1731    #[default]
1732    Missing,
1733    Unknown,
1734    BudgetExhausted,
1735    TimeBudgetExceeded,
1736    RetryExhausted,
1737    StructuredOutputValidationFailed,
1738    OtherFailure,
1739}
1740
1741/// Surface result classification emitted by `ResolveTurnSurfaceResult`.
1742#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1743pub enum SurfaceResultClass {
1744    #[default]
1745    Success,
1746    HardFailure,
1747    Cancelled,
1748    MissingTerminal,
1749}
1750
1751/// P0 Dogma Invariant 1: machine-owned LLM-failure recovery verdict emitted by
1752/// `ClassifyLlmFailureRecovery`. The DSL owns this typed mirror so the
1753/// classifier transitions can carry it; the agent loop mirrors the verdict
1754/// instead of unilaterally deciding fatal/exhaustion.
1755#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1756pub enum LlmFailureRecoveryKind {
1757    #[default]
1758    Fatal,
1759    Recover,
1760    Exhausted,
1761}
1762
1763/// #323: pre-selected call-timeout source carried into the machine's
1764/// `ClassifyCallTimeout` classifier. Source selection is shell-side; the
1765/// machine owns the retryable-vs-terminal verdict.
1766#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1767pub enum CallTimeoutSource {
1768    #[default]
1769    CallBudget,
1770    TurnBudget,
1771}
1772
1773/// #323: machine-owned call-timeout verdict emitted by `ClassifyCallTimeout`.
1774/// The agent loop mirrors this into the existing retry / budget-terminal paths.
1775#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1776pub enum CallTimeoutVerdict {
1777    #[default]
1778    RetryableCallTimeout,
1779    TerminalTurnBudget,
1780}
1781
1782/// Raw failure source fact carried by runtime run-failure handoff.
1783/// MeerkatMachine maps this to terminal outcome/cause before public
1784/// projection.
1785#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1786pub enum RunFailureSourceKind {
1787    #[default]
1788    Unknown,
1789    Llm,
1790    StoreError,
1791    ToolError,
1792    McpError,
1793    SessionNotFound,
1794    TokenBudgetExceeded,
1795    TimeBudgetExceeded,
1796    ToolCallBudgetExceeded,
1797    MaxTokensReached,
1798    ContentFiltered,
1799    MaxTurnsReached,
1800    Cancelled,
1801    InvalidStateTransition,
1802    OperationNotFound,
1803    DepthLimitExceeded,
1804    ConcurrencyLimitExceeded,
1805    ConfigError,
1806    InvalidToolAccess,
1807    InternalError,
1808    BuildError,
1809    AuthReauthRequired,
1810    CallbackPending,
1811    StructuredOutputValidationFailed,
1812    InvalidOutputSchema,
1813    HookDenied,
1814    HookTimeout,
1815    HookExecutionFailed,
1816    HookConfigInvalid,
1817    TerminalFailure,
1818    NoPendingBoundary,
1819    LlmRetryExhausted,
1820}
1821
1822impl From<meerkat_core::turn_execution_authority::TurnFailureSourceKind> for RunFailureSourceKind {
1823    fn from(kind: meerkat_core::turn_execution_authority::TurnFailureSourceKind) -> Self {
1824        match kind {
1825            meerkat_core::turn_execution_authority::TurnFailureSourceKind::Unknown => {
1826                Self::Unknown
1827            }
1828            meerkat_core::turn_execution_authority::TurnFailureSourceKind::Llm => Self::Llm,
1829            meerkat_core::turn_execution_authority::TurnFailureSourceKind::StoreError => {
1830                Self::StoreError
1831            }
1832            meerkat_core::turn_execution_authority::TurnFailureSourceKind::ToolError => {
1833                Self::ToolError
1834            }
1835            meerkat_core::turn_execution_authority::TurnFailureSourceKind::McpError => {
1836                Self::McpError
1837            }
1838            meerkat_core::turn_execution_authority::TurnFailureSourceKind::SessionNotFound => {
1839                Self::SessionNotFound
1840            }
1841            meerkat_core::turn_execution_authority::TurnFailureSourceKind::TokenBudgetExceeded => {
1842                Self::TokenBudgetExceeded
1843            }
1844            meerkat_core::turn_execution_authority::TurnFailureSourceKind::TimeBudgetExceeded => {
1845                Self::TimeBudgetExceeded
1846            }
1847            meerkat_core::turn_execution_authority::TurnFailureSourceKind::ToolCallBudgetExceeded => {
1848                Self::ToolCallBudgetExceeded
1849            }
1850            meerkat_core::turn_execution_authority::TurnFailureSourceKind::MaxTokensReached => {
1851                Self::MaxTokensReached
1852            }
1853            meerkat_core::turn_execution_authority::TurnFailureSourceKind::ContentFiltered => {
1854                Self::ContentFiltered
1855            }
1856            meerkat_core::turn_execution_authority::TurnFailureSourceKind::MaxTurnsReached => {
1857                Self::MaxTurnsReached
1858            }
1859            meerkat_core::turn_execution_authority::TurnFailureSourceKind::Cancelled => {
1860                Self::Cancelled
1861            }
1862            meerkat_core::turn_execution_authority::TurnFailureSourceKind::InvalidStateTransition => {
1863                Self::InvalidStateTransition
1864            }
1865            meerkat_core::turn_execution_authority::TurnFailureSourceKind::OperationNotFound => {
1866                Self::OperationNotFound
1867            }
1868            meerkat_core::turn_execution_authority::TurnFailureSourceKind::DepthLimitExceeded => {
1869                Self::DepthLimitExceeded
1870            }
1871            meerkat_core::turn_execution_authority::TurnFailureSourceKind::ConcurrencyLimitExceeded => {
1872                Self::ConcurrencyLimitExceeded
1873            }
1874            meerkat_core::turn_execution_authority::TurnFailureSourceKind::ConfigError => {
1875                Self::ConfigError
1876            }
1877            meerkat_core::turn_execution_authority::TurnFailureSourceKind::InvalidToolAccess => {
1878                Self::InvalidToolAccess
1879            }
1880            meerkat_core::turn_execution_authority::TurnFailureSourceKind::InternalError => {
1881                Self::InternalError
1882            }
1883            meerkat_core::turn_execution_authority::TurnFailureSourceKind::BuildError => {
1884                Self::BuildError
1885            }
1886            meerkat_core::turn_execution_authority::TurnFailureSourceKind::AuthReauthRequired => {
1887                Self::AuthReauthRequired
1888            }
1889            meerkat_core::turn_execution_authority::TurnFailureSourceKind::CallbackPending => {
1890                Self::CallbackPending
1891            }
1892            meerkat_core::turn_execution_authority::TurnFailureSourceKind::StructuredOutputValidationFailed => {
1893                Self::StructuredOutputValidationFailed
1894            }
1895            meerkat_core::turn_execution_authority::TurnFailureSourceKind::InvalidOutputSchema => {
1896                Self::InvalidOutputSchema
1897            }
1898            meerkat_core::turn_execution_authority::TurnFailureSourceKind::HookDenied => {
1899                Self::HookDenied
1900            }
1901            meerkat_core::turn_execution_authority::TurnFailureSourceKind::HookTimeout => {
1902                Self::HookTimeout
1903            }
1904            meerkat_core::turn_execution_authority::TurnFailureSourceKind::HookExecutionFailed => {
1905                Self::HookExecutionFailed
1906            }
1907            meerkat_core::turn_execution_authority::TurnFailureSourceKind::HookConfigInvalid => {
1908                Self::HookConfigInvalid
1909            }
1910            meerkat_core::turn_execution_authority::TurnFailureSourceKind::TerminalFailure => {
1911                Self::TerminalFailure
1912            }
1913            meerkat_core::turn_execution_authority::TurnFailureSourceKind::NoPendingBoundary => {
1914                Self::NoPendingBoundary
1915            }
1916            meerkat_core::turn_execution_authority::TurnFailureSourceKind::LlmRetryExhausted => {
1917                Self::LlmRetryExhausted
1918            }
1919        }
1920    }
1921}
1922
1923/// Typed classifier for failures surfaced by the runtime apply loop when a
1924/// `CoreExecutor::apply` call fails and terminalizes the runtime turn.
1925/// The companion `last_runtime_apply_failure_message` state field carries the
1926/// human-readable projection.
1927#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1928pub enum RuntimeApplyFailureCause {
1929    #[default]
1930    Unknown,
1931    PrimitiveRejected,
1932    RuntimeContextApply,
1933    RuntimeTurn,
1934    HookDenied,
1935    HookRuntimeFailure,
1936    ExecutorStopped,
1937    ExecutorControlFailed,
1938    ExecutorInternal,
1939}
1940
1941impl From<meerkat_core::lifecycle::CoreApplyFailureCauseKind> for RuntimeApplyFailureCause {
1942    #[allow(clippy::panic)]
1943    fn from(kind: meerkat_core::lifecycle::CoreApplyFailureCauseKind) -> Self {
1944        match kind {
1945            meerkat_core::lifecycle::CoreApplyFailureCauseKind::PrimitiveRejected => {
1946                Self::PrimitiveRejected
1947            }
1948            meerkat_core::lifecycle::CoreApplyFailureCauseKind::RuntimeContextApply => {
1949                Self::RuntimeContextApply
1950            }
1951            meerkat_core::lifecycle::CoreApplyFailureCauseKind::RuntimeTurn => Self::RuntimeTurn,
1952            meerkat_core::lifecycle::CoreApplyFailureCauseKind::HookDenied => Self::HookDenied,
1953            meerkat_core::lifecycle::CoreApplyFailureCauseKind::HookRuntimeFailure => {
1954                Self::HookRuntimeFailure
1955            }
1956            meerkat_core::lifecycle::CoreApplyFailureCauseKind::ExecutorStopped => {
1957                Self::ExecutorStopped
1958            }
1959            meerkat_core::lifecycle::CoreApplyFailureCauseKind::ExecutorControlFailed => {
1960                Self::ExecutorControlFailed
1961            }
1962            meerkat_core::lifecycle::CoreApplyFailureCauseKind::ExecutorInternal => {
1963                Self::ExecutorInternal
1964            }
1965            meerkat_core::lifecycle::CoreApplyFailureCauseKind::Unknown => Self::Unknown,
1966            _ => panic!(
1967                "unsupported CoreApplyFailureCauseKind variant; update generated MeerkatMachine mirror"
1968            ),
1969        }
1970    }
1971}
1972
1973impl From<&meerkat_core::lifecycle::CoreApplyFailureCause> for RuntimeApplyFailureCause {
1974    fn from(cause: &meerkat_core::lifecycle::CoreApplyFailureCause) -> Self {
1975        Self::from(cause.kind)
1976    }
1977}
1978
1979/// Typed pre-run phase marker. Closed set: `idle`, `attached`, `retired`.
1980/// Replaces the former literal-string `pre_run_phase` field.
1981#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1982pub enum PreRunPhase {
1983    #[default]
1984    Idle,
1985    Attached,
1986    Retired,
1987}
1988
1989/// Generated authority for deferred session materialization.
1990///
1991/// The shell keeps bulky build payloads in a registry, but phase/admission
1992/// meaning for the staged lifecycle is owned here.
1993#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1994pub enum StagedSessionPhase {
1995    #[default]
1996    NotStaged,
1997    Staged,
1998    Promoting,
1999    Closing,
2000}
2001
2002/// Explicit host/profile request class for mob operator access.
2003#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2004pub enum MobOperatorAccessRequestKind {
2005    #[default]
2006    Inherit,
2007    Enable,
2008    Disable,
2009}
2010
2011/// Typed runtime notice classifier for the `RuntimeNotice` effect. Closed set
2012/// of per-transition runtime lifecycle markers (drain exited, runtime reset,
2013/// executor stopped/exited, runtime recovered) emitted by the runtime-control
2014/// plane. Replaces the former literal-string `kind` field on `RuntimeNotice`
2015/// so the shell dispatcher matches exhaustively on a typed discriminant
2016/// instead of comparing string literals. `detail` stays `String` — it's a
2017/// free-form diagnostic message that accompanies the kind.
2018#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2019pub enum RuntimeNoticeKind {
2020    #[default]
2021    Drain,
2022    Reset,
2023    Stop,
2024    Exit,
2025    Recover,
2026}
2027
2028/// Closed top-level classifier for a published `RuntimeEvent`, mirroring the
2029/// five `RuntimeEvent` discriminants in `meerkat-runtime` (`InputLifecycle`,
2030/// `RunLifecycle`, `RuntimeStateChange`, `Topology`, `Projection`). Replaces the
2031/// former Debug-derived discriminant *string* on `PublishEvent.kind` so the DSL
2032/// carries a typed discriminant the shell maps exhaustively.
2033#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2034pub enum RuntimeEventKind {
2035    #[default]
2036    InputLifecycle,
2037    RunLifecycle,
2038    RuntimeStateChange,
2039    Topology,
2040    Projection,
2041}
2042
2043/// Closed classifier for runtime-loop executor effects emitted as neutral DSL
2044/// facts before the runtime shell converts them to sealed executable effects.
2045#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2046pub enum RuntimeEffectKind {
2047    #[default]
2048    CancelAfterBoundary,
2049    StopRuntimeExecutor,
2050}
2051
2052/// Typed runtime completion observation supplied by completion waiter plumbing.
2053/// Generated `ResolveRuntimeCompletionCleanup` authority owns whether that
2054/// observation permits runtime cleanup; surfaces must not match this enum to
2055/// decide cleanup locally.
2056#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2057pub enum RuntimeCompletionObservedOutcome {
2058    #[default]
2059    Completed,
2060    CompletedWithoutResult,
2061    CallbackPending,
2062    Cancelled,
2063    Abandoned,
2064    RuntimeApplyFailed,
2065    FinalizationFailed,
2066    RuntimeTerminated,
2067}
2068
2069/// Typed observation of the terminal payload shape produced by runtime-loop
2070/// execution. This is input evidence only; the generated
2071/// `ResolveRuntimeCompletionResult` transition owns the public waiter class.
2072#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2073pub enum RuntimeCompletionTerminalObservation {
2074    #[default]
2075    RunResult,
2076    NoResult,
2077    CallbackPending,
2078    MachineTerminal,
2079    RuntimeTerminated,
2080}
2081
2082/// Typed observation of whether runtime finalization completed after the
2083/// executor produced terminal evidence.
2084#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2085pub enum RuntimeCompletionFinalizationObservation {
2086    #[default]
2087    Succeeded,
2088    Failed,
2089}
2090
2091/// Typed observation supplied by public session-interrupt surfaces. The
2092/// generated `ResolveUserInterruptPublicResult` transition owns the app-facing
2093/// result class; REST/RPC/CLI may only map its typed effect to transport shape.
2094#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2095pub enum UserInterruptObservationKind {
2096    #[default]
2097    Accepted,
2098    IdleNoop,
2099    AttachedNoop,
2100    StagedNoop,
2101    Destroyed,
2102    NotInterruptible,
2103}
2104
2105/// Generated public result class for user interrupt requests.
2106#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2107pub enum UserInterruptPublicResultKind {
2108    #[default]
2109    Interrupted,
2110    /// #348: a staged (not-yet-promoted) session interrupt is a typed no-op
2111    /// terminal — distinct from `Interrupted` (a live run was cancelled).
2112    StagedNoop,
2113    NotFound,
2114    SessionBusy,
2115    Conflict,
2116}
2117
2118/// Generated public completion result class for runtime-loop waiters. Payloads
2119/// remain runtime data, but this closed classifier is the authority for which
2120/// public `CompletionOutcome` variant may be emitted.
2121#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2122pub enum RuntimeCompletionResultClass {
2123    #[default]
2124    Completed,
2125    CompletedWithoutResult,
2126    CallbackPending,
2127    Cancelled,
2128    AbandonedWithError,
2129    CompletedWithFinalizationFailure,
2130    RuntimeTerminated,
2131}
2132
2133/// Typed observation of the live-session projection available to generated
2134/// runtime-completion cleanup authority.
2135#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2136pub enum RuntimeCompletionLiveSessionObservation {
2137    #[default]
2138    NotObserved,
2139    Present,
2140    Absent,
2141}
2142
2143/// Generated cleanup action for runtime completion side effects.
2144#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2145pub enum RuntimeCompletionCleanupAction {
2146    #[default]
2147    RetainRuntime,
2148    CleanupRuntime,
2149}
2150
2151/// Generated authority for whether completion cleanup may release a surface
2152/// pre-admission guard.
2153#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2154pub enum RuntimeCompletionPreAdmissionAction {
2155    #[default]
2156    RetainPreAdmission,
2157    ReleasePreAdmission,
2158}
2159
2160/// Typed mechanical failure observed by completion waiter plumbing.
2161#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2162pub enum RuntimeCompletionWaitFailureObservation {
2163    #[default]
2164    ChannelClosed,
2165    AuthorityUnavailable,
2166}
2167
2168/// Generated public error class for mechanical runtime completion waiter
2169/// failures.
2170#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2171pub enum RuntimeCompletionWaitFailurePublicErrorClass {
2172    #[default]
2173    InternalError,
2174}
2175
2176/// Generated public reason classifier for mechanical runtime completion waiter
2177/// failures.
2178#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2179pub enum RuntimeCompletionWaitFailurePublicReason {
2180    #[default]
2181    CompletionChannelClosed,
2182    CompletionAuthorityUnavailable,
2183}
2184
2185/// Generated durability action for runtime-owned ops lifecycle snapshots.
2186#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2187pub enum RuntimeOpsLifecycleDurabilityAction {
2188    #[default]
2189    RetainSnapshot,
2190    DeleteSnapshot,
2191}
2192
2193/// Typed public rejection class for `live/open` admission.
2194#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2195pub enum LiveOpenAdmissionRejection {
2196    #[default]
2197    AlreadyBound,
2198    ChannelAlreadyBound,
2199}
2200
2201/// Typed public result class for `live/refresh` after the adapter command
2202/// queue accepts a refresh handoff. The RPC surface may only project this
2203/// value from a generated `LiveRefreshResultResolved` effect.
2204#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2205pub enum LiveRefreshPublicStatus {
2206    #[default]
2207    Queued,
2208}
2209
2210/// Typed public result class for `live/close` after the live host accepts a
2211/// close handoff. The RPC surface may only project this value from a generated
2212/// `LiveCloseResultResolved` effect.
2213#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2214pub enum LiveClosePublicStatus {
2215    #[default]
2216    Closed,
2217}
2218
2219/// Closed classifier for live adapter commands whose queue acceptance backs a
2220/// public RPC result.
2221#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2222pub enum LiveCommandPublicKind {
2223    #[default]
2224    SendInput,
2225    CommitInput,
2226    Interrupt,
2227    TruncateAssistantOutput,
2228}
2229
2230/// Closed classifier for live command rejection observations. The live host
2231/// can observe why an adapter command handoff failed, but public error-class
2232/// truth is generated from this typed fact.
2233#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2234pub enum LiveCommandRejectionReason {
2235    #[default]
2236    ChannelNotFound,
2237    NoAdapter,
2238    ChannelNotReady,
2239    UnsupportedCommand,
2240    AdapterError,
2241    InternalHostError,
2242}
2243
2244/// Typed public error class for live command rejections. RPC surfaces may only
2245/// project their JSON-RPC error code from a generated
2246/// `LiveCommandRejectionResolved` effect.
2247#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2248pub enum LiveCommandRejectionPublicErrorClass {
2249    #[default]
2250    InvalidParams,
2251    InternalError,
2252}
2253
2254/// Closed classifier for live channel control requests whose rejection backs a
2255/// public RPC error result.
2256#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2257pub enum LiveChannelRequestPublicKind {
2258    #[default]
2259    Status,
2260    Close,
2261    Refresh,
2262    WebrtcAnswer,
2263}
2264
2265/// Closed classifier for live channel control request rejection observations.
2266/// The live host can observe missing transport/cache pieces, but public
2267/// error-class truth is generated from this typed fact.
2268#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2269pub enum LiveChannelRequestRejectionReason {
2270    #[default]
2271    ChannelNotFound,
2272    NoAdapter,
2273    InvalidToken,
2274    InvalidPayload,
2275    WebrtcAnswerError,
2276    InternalHostError,
2277}
2278
2279/// Typed public error class for live channel control request rejections. RPC
2280/// surfaces may only project their JSON-RPC error code from a generated
2281/// `LiveChannelRequestRejectionResolved` effect.
2282#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2283pub enum LiveChannelRequestRejectionPublicErrorClass {
2284    #[default]
2285    InvalidParams,
2286    InternalError,
2287}
2288
2289/// Closed classifier for generated WebRTC answer admission rejections. The
2290/// transport can provide bearer material, but token existence, expiry,
2291/// channel binding, and single-use admission are decided by MeerkatMachine.
2292#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2293pub enum LiveWebrtcAnswerAdmissionRejection {
2294    #[default]
2295    TokenNotFound,
2296    TokenExpired,
2297    TokenChannelMismatch,
2298    TokenAlreadyConsumed,
2299    ChannelNotBound,
2300}
2301
2302/// Closed classifier for generated WebSocket token admission rejections. The
2303/// WebSocket transport can present bearer material, but token existence,
2304/// expiry, channel binding, and single-use admission are decided by
2305/// MeerkatMachine.
2306#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2307pub enum LiveWebsocketTokenAdmissionRejection {
2308    #[default]
2309    TokenNotFound,
2310    TokenExpired,
2311    TokenChannelMismatch,
2312    TokenAlreadyConsumed,
2313    ChannelNotBound,
2314}
2315
2316/// Typed public error class for live WebSocket token admission. The transport
2317/// projects its close/error code only from the generated admission effect.
2318#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2319pub enum LiveWebsocketTokenAdmissionPublicErrorClass {
2320    #[default]
2321    InvalidToken,
2322}
2323
2324/// Typed public success class for `live/webrtc/answer`. The WebRTC stack
2325/// produces SDP material, but the public success result is projected only
2326/// after a generated `LiveWebrtcAnswerResultResolved` effect.
2327#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2328pub enum LiveWebrtcAnswerPublicStatus {
2329    #[default]
2330    Answered,
2331}
2332
2333/// Typed terminal reason for RPC event streams. The router observes transport
2334/// end conditions, then submits the closed set here before projecting the
2335/// public `*/stream_end` notification.
2336#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2337pub enum RpcEventStreamTerminalReason {
2338    #[default]
2339    RemoteEnd,
2340    TerminalError,
2341    ExplicitClose,
2342}
2343
2344/// Typed transport observation for RPC event-stream termination. The router
2345/// submits this non-public observation; generated authority derives the public
2346/// terminal reason and error code.
2347#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2348pub enum RpcEventStreamTerminalObservationKind {
2349    #[default]
2350    TransportEnded,
2351    NotificationQueueOverflow,
2352    NotificationReceiverGone,
2353}
2354
2355/// Typed public error code for RPC event-stream terminal notifications. The
2356/// RPC surface may only project this value from a generated
2357/// `*EventStreamTerminalResolved` effect.
2358#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2359pub enum RpcEventStreamTerminalErrorCode {
2360    #[default]
2361    StreamQueueOverflow,
2362    StreamReceiverGone,
2363}
2364
2365/// Typed public status class for `live/status` after the live host has
2366/// observed the adapter transport state. RPC/SDK surfaces may only project
2367/// these values from generated `LiveChannelStatusResolved` effects.
2368#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2369pub enum LiveChannelPublicStatus {
2370    #[default]
2371    Idle,
2372    Opening,
2373    Ready,
2374    Degraded,
2375    Closing,
2376    Closed,
2377}
2378
2379/// Typed public degradation reason for `live/status`.
2380#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2381pub enum LiveChannelDegradationReason {
2382    #[default]
2383    Unknown,
2384    RateLimited,
2385    ProviderThrottled,
2386    NetworkUnstable,
2387    Other,
2388}
2389
2390/// #51: provider-neutral role for a staged realtime transcript item, carried on
2391/// the `RealtimeTranscriptAppended` staging effect. Mirror of
2392/// `meerkat_core::realtime_transcript::RealtimeTranscriptRole`.
2393#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2394pub enum RealtimeTranscriptRoleKind {
2395    #[default]
2396    User,
2397    Assistant,
2398}
2399
2400/// #51: output lane for a staged realtime transcript item (display text vs
2401/// spoken transcript). Mirror of `meerkat_core::realtime_transcript::TranscriptLane`.
2402#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2403pub enum RealtimeTranscriptLaneKind {
2404    #[default]
2405    Display,
2406    Spoken,
2407}
2408
2409/// Typed mirror of the public runtime lifecycle projection. The shell passes
2410/// only the observed variant; generated transitions own the semantic facts
2411/// derived from it.
2412#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2413pub enum RuntimeLifecycleObservedState {
2414    #[default]
2415    Initializing,
2416    Idle,
2417    Attached,
2418    Running,
2419    Retired,
2420    Stopped,
2421    Destroyed,
2422}
2423
2424#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2425pub enum RuntimeLifecycleTerminality {
2426    #[default]
2427    NonTerminal,
2428    Terminal,
2429}
2430
2431#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2432pub enum RuntimeInputAdmission {
2433    #[default]
2434    RejectsInput,
2435    AcceptsInput,
2436}
2437
2438#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2439pub enum RuntimeQueueAdmission {
2440    #[default]
2441    BlocksQueue,
2442    ProcessesQueue,
2443}
2444
2445#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2446pub enum RuntimePrepareAdmission {
2447    #[default]
2448    NotReady,
2449    Ready,
2450    Destroyed,
2451}
2452
2453#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2454pub enum RuntimeIngressAdmission {
2455    #[default]
2456    Open,
2457    NotReady,
2458    Destroyed,
2459}
2460
2461#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2462pub enum RuntimeLoopRunBinding {
2463    #[default]
2464    Blocked,
2465    AllocateNew,
2466    UsePrebound,
2467}
2468
2469/// Typed reason classifier for the `TurnRunCancelled` effect. Closed set of
2470/// cancellation-observation origins emitted when a turn's cancellation
2471/// request lands at an observable boundary. Replaces the former literal-
2472/// string `reason` field on `TurnRunCancelled`. Only one origin is emitted
2473/// today (`Observed`, fired by the `CancellationObserved` transition), but
2474/// this remains a closed classifier not a free-form message — future
2475/// cancellation origins extend the enum rather than reintroducing strings.
2476#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2477pub enum TurnCancellationReason {
2478    #[default]
2479    Observed,
2480}
2481
2482/// Typed recoverable LLM retry failure classifier. Closed mirror of
2483/// [`meerkat_core::retry::LlmRetryFailureKind`] so retry authority records the
2484/// retry cause as data, not as a parsed diagnostic string.
2485#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2486pub enum LlmRetryFailureKind {
2487    #[default]
2488    RateLimited,
2489    NetworkTimeout,
2490    CallTimeout,
2491    RetryableProviderError,
2492}
2493
2494impl From<meerkat_core::retry::LlmRetryFailureKind> for LlmRetryFailureKind {
2495    fn from(kind: meerkat_core::retry::LlmRetryFailureKind) -> Self {
2496        match kind {
2497            meerkat_core::retry::LlmRetryFailureKind::RateLimited => Self::RateLimited,
2498            meerkat_core::retry::LlmRetryFailureKind::NetworkTimeout => Self::NetworkTimeout,
2499            meerkat_core::retry::LlmRetryFailureKind::CallTimeout => Self::CallTimeout,
2500            meerkat_core::retry::LlmRetryFailureKind::RetryableProviderError => {
2501                Self::RetryableProviderError
2502            }
2503        }
2504    }
2505}
2506
2507/// Typed admission-signal classifier for the `PostAdmissionSignal` effect.
2508/// Closed set of post-admission wake/interrupt intents emitted by the
2509/// ingress authority so the shell dispatcher matches exhaustively on a
2510/// typed discriminant instead of comparing string literals. Mirrors the
2511/// shell-side `driver::ephemeral::PostAdmissionSignal` strength ordering
2512/// (WakeLoop < InterruptYielding < RequestImmediateProcessing); the
2513/// shell enum additionally carries a `None` bottom that the DSL never
2514/// emits, so only the three emitted variants appear here.
2515#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2516pub enum PostAdmissionSignalKind {
2517    #[default]
2518    WakeLoop,
2519    InterruptYielding,
2520    RequestImmediateProcessing,
2521}
2522
2523/// Typed base lifecycle state for an external tool surface. Closed mirror of
2524/// [`meerkat_core::tool_scope::ExternalToolSurfaceBaseState`] — replaces the
2525/// former literal-string values in `surface_base_state`.
2526#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2527pub enum ExternalToolSurfaceBaseState {
2528    #[default]
2529    Absent,
2530    Active,
2531    Removing,
2532    Removed,
2533}
2534
2535impl From<meerkat_core::tool_scope::ExternalToolSurfaceBaseState> for ExternalToolSurfaceBaseState {
2536    fn from(state: meerkat_core::tool_scope::ExternalToolSurfaceBaseState) -> Self {
2537        match state {
2538            meerkat_core::tool_scope::ExternalToolSurfaceBaseState::Absent => Self::Absent,
2539            meerkat_core::tool_scope::ExternalToolSurfaceBaseState::Active => Self::Active,
2540            meerkat_core::tool_scope::ExternalToolSurfaceBaseState::Removing => Self::Removing,
2541            meerkat_core::tool_scope::ExternalToolSurfaceBaseState::Removed => Self::Removed,
2542        }
2543    }
2544}
2545
2546impl From<ExternalToolSurfaceBaseState> for meerkat_core::tool_scope::ExternalToolSurfaceBaseState {
2547    fn from(state: ExternalToolSurfaceBaseState) -> Self {
2548        match state {
2549            ExternalToolSurfaceBaseState::Absent => Self::Absent,
2550            ExternalToolSurfaceBaseState::Active => Self::Active,
2551            ExternalToolSurfaceBaseState::Removing => Self::Removing,
2552            ExternalToolSurfaceBaseState::Removed => Self::Removed,
2553        }
2554    }
2555}
2556
2557/// Typed last-delta operation for an external tool surface. Closed mirror of
2558/// [`meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation`] — replaces
2559/// the former literal-string values in `surface_last_delta_operation`.
2560#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2561pub enum ExternalToolSurfaceDeltaOperation {
2562    #[default]
2563    None,
2564    Add,
2565    Remove,
2566    Reload,
2567}
2568
2569impl From<meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation>
2570    for ExternalToolSurfaceDeltaOperation
2571{
2572    fn from(op: meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation) -> Self {
2573        match op {
2574            meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation::None => Self::None,
2575            meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation::Add => Self::Add,
2576            meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation::Remove => Self::Remove,
2577            meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation::Reload => Self::Reload,
2578        }
2579    }
2580}
2581
2582impl From<ExternalToolSurfaceDeltaOperation>
2583    for meerkat_core::tool_scope::ExternalToolSurfaceDeltaOperation
2584{
2585    fn from(op: ExternalToolSurfaceDeltaOperation) -> Self {
2586        match op {
2587            ExternalToolSurfaceDeltaOperation::None => Self::None,
2588            ExternalToolSurfaceDeltaOperation::Add => Self::Add,
2589            ExternalToolSurfaceDeltaOperation::Remove => Self::Remove,
2590            ExternalToolSurfaceDeltaOperation::Reload => Self::Reload,
2591        }
2592    }
2593}
2594
2595/// Typed last-delta phase for an external tool surface. Closed mirror of
2596/// [`meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase`] — replaces the
2597/// former literal-string values in `surface_last_delta_phase`.
2598#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2599pub enum ExternalToolSurfaceDeltaPhase {
2600    #[default]
2601    None,
2602    Pending,
2603    Applied,
2604    Draining,
2605    Failed,
2606    Forced,
2607}
2608
2609impl From<meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase>
2610    for ExternalToolSurfaceDeltaPhase
2611{
2612    fn from(phase: meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase) -> Self {
2613        match phase {
2614            meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase::None => Self::None,
2615            meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase::Pending => Self::Pending,
2616            meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase::Applied => Self::Applied,
2617            meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase::Draining => Self::Draining,
2618            meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase::Failed => Self::Failed,
2619            meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase::Forced => Self::Forced,
2620        }
2621    }
2622}
2623
2624impl From<ExternalToolSurfaceDeltaPhase>
2625    for meerkat_core::tool_scope::ExternalToolSurfaceDeltaPhase
2626{
2627    fn from(phase: ExternalToolSurfaceDeltaPhase) -> Self {
2628        match phase {
2629            ExternalToolSurfaceDeltaPhase::None => Self::None,
2630            ExternalToolSurfaceDeltaPhase::Pending => Self::Pending,
2631            ExternalToolSurfaceDeltaPhase::Applied => Self::Applied,
2632            ExternalToolSurfaceDeltaPhase::Draining => Self::Draining,
2633            ExternalToolSurfaceDeltaPhase::Failed => Self::Failed,
2634            ExternalToolSurfaceDeltaPhase::Forced => Self::Forced,
2635        }
2636    }
2637}
2638
2639/// Typed failure cause for an external tool surface. Closed mirror of
2640/// [`meerkat_core::tool_scope::ExternalToolSurfaceFailureCause`] so pending
2641/// failure and call-rejection causes cross the DSL as data, not string codes.
2642#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2643pub enum ExternalToolSurfaceFailureCause {
2644    #[default]
2645    PendingFailed,
2646    SurfaceDraining,
2647    SurfaceUnavailable,
2648}
2649
2650impl From<meerkat_core::tool_scope::ExternalToolSurfaceFailureCause>
2651    for ExternalToolSurfaceFailureCause
2652{
2653    fn from(cause: meerkat_core::tool_scope::ExternalToolSurfaceFailureCause) -> Self {
2654        match cause {
2655            meerkat_core::tool_scope::ExternalToolSurfaceFailureCause::PendingFailed => {
2656                Self::PendingFailed
2657            }
2658            meerkat_core::tool_scope::ExternalToolSurfaceFailureCause::SurfaceDraining => {
2659                Self::SurfaceDraining
2660            }
2661            meerkat_core::tool_scope::ExternalToolSurfaceFailureCause::SurfaceUnavailable => {
2662                Self::SurfaceUnavailable
2663            }
2664        }
2665    }
2666}
2667
2668impl From<ExternalToolSurfaceFailureCause>
2669    for meerkat_core::tool_scope::ExternalToolSurfaceFailureCause
2670{
2671    fn from(cause: ExternalToolSurfaceFailureCause) -> Self {
2672        match cause {
2673            ExternalToolSurfaceFailureCause::PendingFailed => Self::PendingFailed,
2674            ExternalToolSurfaceFailureCause::SurfaceDraining => Self::SurfaceDraining,
2675            ExternalToolSurfaceFailureCause::SurfaceUnavailable => Self::SurfaceUnavailable,
2676        }
2677    }
2678}
2679
2680/// Typed drain-exit reason. Closed mirror of
2681/// [`meerkat_core::handles::DrainExitReason`] — replaces the former
2682/// literal-string `reason` field on `NotifyDrainExited`.
2683#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2684pub enum DrainExitReason {
2685    #[default]
2686    IdleTimeout,
2687    Dismissed,
2688    Failed,
2689    Aborted,
2690    SessionShutdown,
2691}
2692
2693impl From<meerkat_core::handles::DrainExitReason> for DrainExitReason {
2694    fn from(reason: meerkat_core::handles::DrainExitReason) -> Self {
2695        match reason {
2696            meerkat_core::handles::DrainExitReason::IdleTimeout => Self::IdleTimeout,
2697            meerkat_core::handles::DrainExitReason::Dismissed => Self::Dismissed,
2698            meerkat_core::handles::DrainExitReason::Failed => Self::Failed,
2699            meerkat_core::handles::DrainExitReason::Aborted => Self::Aborted,
2700            meerkat_core::handles::DrainExitReason::SessionShutdown => Self::SessionShutdown,
2701        }
2702    }
2703}
2704
2705impl From<DrainExitReason> for meerkat_core::handles::DrainExitReason {
2706    fn from(reason: DrainExitReason) -> Self {
2707        match reason {
2708            DrainExitReason::IdleTimeout => Self::IdleTimeout,
2709            DrainExitReason::Dismissed => Self::Dismissed,
2710            DrainExitReason::Failed => Self::Failed,
2711            DrainExitReason::Aborted => Self::Aborted,
2712            DrainExitReason::SessionShutdown => Self::SessionShutdown,
2713        }
2714    }
2715}
2716
2717/// Generated surface-request lifecycle phase. Surface transports may project
2718/// this value for diagnostics; mutation authority lives in MeerkatMachine
2719/// transitions.
2720#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2721pub enum SurfaceRequestPhase {
2722    #[default]
2723    Pending,
2724    Published,
2725    Cancelled,
2726    Completed,
2727}
2728
2729/// Generated terminal-publication policy recorded when a surface request is
2730/// admitted.
2731#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2732pub enum SurfaceRequestTerminalPolicy {
2733    #[default]
2734    RespondWithoutPublish,
2735    PublishOnSuccess,
2736}
2737
2738/// Typed work-lane origin for [`MeerkatMachineInput::Ingest`]. Closed set of
2739/// the work-lane labels the DSL observes on the admission seam — replaces
2740/// the former literal-string `origin` field. Structurally mirrors the
2741/// `MobMachine.RequestRuntimeIngress.origin` seam so the cross-machine
2742/// composition binds on a single typed enum instead of parallel
2743/// string-typed slots. Transport sources ([`meerkat_core::comms::InputSource`])
2744/// arriving from the shell side collapse to `External`; the
2745/// runtime-control-plane `Ingest` dispatch uses the dedicated `Ingest`
2746/// variant; mob-bridged ingress carries `External`/`Internal` matching
2747/// `meerkat-mob::ids::WorkOrigin`.
2748#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2749pub enum WorkOrigin {
2750    #[default]
2751    External,
2752    Internal,
2753    /// Canonical admission entrypoint fired by the runtime control plane
2754    /// with no surface-level transport or work-lane label.
2755    Ingest,
2756}
2757
2758impl From<meerkat_core::comms::InputSource> for WorkOrigin {
2759    fn from(src: meerkat_core::comms::InputSource) -> Self {
2760        match src {
2761            // Transport-originated inputs are `External` work-lane: they
2762            // entered the runtime via a non-mob transport (TCP/UDS/stdin/
2763            // webhook/RPC). Mob-originated work fires the DSL directly
2764            // with `External`/`Internal` instead of going through the
2765            // session-admission handle.
2766            meerkat_core::comms::InputSource::Tcp
2767            | meerkat_core::comms::InputSource::Uds
2768            | meerkat_core::comms::InputSource::Stdin
2769            | meerkat_core::comms::InputSource::Webhook
2770            | meerkat_core::comms::InputSource::Rpc => Self::External,
2771        }
2772    }
2773}
2774
2775/// Typed async-operation lifecycle status. Closed mirror of
2776/// [`meerkat_core::ops_lifecycle::OperationStatus`] — replaces the former
2777/// literal-string values in the DSL's `op_statuses` map.
2778///
2779/// The DSL writes these variants directly on each ops lifecycle transition
2780/// (`RegisterOp`, `StartOp`, `CompleteOp`, `FailOp`, `CancelOp`, `AbortOp`,
2781/// `RetireRequestedOp`, `RetireCompletedOp`, `TerminateOp`). The shell's
2782/// `ShellState::status()` reads the typed value directly and maps to the
2783/// domain enum via the `From` impl below — no string compares, no string
2784/// parsing.
2785#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2786pub enum OperationStatus {
2787    #[default]
2788    Absent,
2789    Provisioning,
2790    Running,
2791    Retiring,
2792    Completed,
2793    Failed,
2794    Aborted,
2795    Cancelled,
2796    Retired,
2797    Terminated,
2798}
2799
2800impl From<meerkat_core::ops_lifecycle::OperationStatus> for OperationStatus {
2801    fn from(status: meerkat_core::ops_lifecycle::OperationStatus) -> Self {
2802        match status {
2803            meerkat_core::ops_lifecycle::OperationStatus::Absent => Self::Absent,
2804            meerkat_core::ops_lifecycle::OperationStatus::Provisioning => Self::Provisioning,
2805            meerkat_core::ops_lifecycle::OperationStatus::Running => Self::Running,
2806            meerkat_core::ops_lifecycle::OperationStatus::Retiring => Self::Retiring,
2807            meerkat_core::ops_lifecycle::OperationStatus::Completed => Self::Completed,
2808            meerkat_core::ops_lifecycle::OperationStatus::Failed => Self::Failed,
2809            meerkat_core::ops_lifecycle::OperationStatus::Aborted => Self::Aborted,
2810            meerkat_core::ops_lifecycle::OperationStatus::Cancelled => Self::Cancelled,
2811            meerkat_core::ops_lifecycle::OperationStatus::Retired => Self::Retired,
2812            meerkat_core::ops_lifecycle::OperationStatus::Terminated => Self::Terminated,
2813        }
2814    }
2815}
2816
2817impl From<OperationStatus> for meerkat_core::ops_lifecycle::OperationStatus {
2818    fn from(status: OperationStatus) -> Self {
2819        match status {
2820            OperationStatus::Absent => Self::Absent,
2821            OperationStatus::Provisioning => Self::Provisioning,
2822            OperationStatus::Running => Self::Running,
2823            OperationStatus::Retiring => Self::Retiring,
2824            OperationStatus::Completed => Self::Completed,
2825            OperationStatus::Failed => Self::Failed,
2826            OperationStatus::Aborted => Self::Aborted,
2827            OperationStatus::Cancelled => Self::Cancelled,
2828            OperationStatus::Retired => Self::Retired,
2829            OperationStatus::Terminated => Self::Terminated,
2830        }
2831    }
2832}
2833
2834/// Typed discriminant mirror of
2835/// [`meerkat_core::ops_lifecycle::OperationTerminalOutcome`]. Unit variants
2836/// only; the full typed payload (completion result, failure error,
2837/// cancellation reason, terminated reason) is carried by the companion
2838/// `op_terminal_payload: Map<String, OpTerminalPayload>` field, keyed by the
2839/// same operation id. The machine guards that the payload variant matches
2840/// the discriminant on every terminal transition.
2841///
2842/// The DSL writes these variants directly on each terminal transition
2843/// (`CompleteOp`, `FailOp`, `CancelOp`, `AbortOp`, `RetireCompletedOp`,
2844/// `TerminateOp`); the shell reads the typed payload map directly — no JSON
2845/// codec, no string compares.
2846#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2847pub enum OperationTerminalOutcomeKind {
2848    #[default]
2849    Completed,
2850    Failed,
2851    Aborted,
2852    Cancelled,
2853    Retired,
2854    Terminated,
2855}
2856
2857/// Typed terminal payload carried by the ops-lifecycle authority. This IS the
2858/// domain type — the machine state stores
2859/// [`meerkat_core::ops_lifecycle::OperationTerminalOutcome`] directly, so the
2860/// shell needs no codec in either direction (K8b fold: the former
2861/// `Map<String, String>` opaque-JSON payload carrier is deleted).
2862pub type OpTerminalPayload = meerkat_core::ops_lifecycle::OperationTerminalOutcome;
2863
2864/// Result payload for completed operations, referenced by the
2865/// `OpTerminalPayload::Completed` structural variant binding.
2866pub type OperationResult = meerkat_core::ops::OperationResult;
2867
2868impl From<&OpTerminalPayload> for OperationTerminalOutcomeKind {
2869    fn from(payload: &OpTerminalPayload) -> Self {
2870        match payload {
2871            OpTerminalPayload::Completed(_) => Self::Completed,
2872            OpTerminalPayload::Failed { .. } => Self::Failed,
2873            OpTerminalPayload::Aborted { .. } => Self::Aborted,
2874            OpTerminalPayload::Cancelled { .. } => Self::Cancelled,
2875            OpTerminalPayload::Retired => Self::Retired,
2876            OpTerminalPayload::Terminated { .. } => Self::Terminated,
2877        }
2878    }
2879}
2880
2881/// Typed public result class for operation lifecycle projections. Shell/tool
2882/// surfaces may format these classes, but the lifecycle machine owns the
2883/// status-to-public-result classification.
2884#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2885pub enum OperationPublicResultClass {
2886    #[default]
2887    MissingAuthority,
2888    Running,
2889    Completed,
2890    Failed,
2891    Cancelled,
2892}
2893
2894#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2895pub enum OperationCompletionFeedClass {
2896    #[default]
2897    Emit,
2898    Suppress,
2899}
2900
2901#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2902pub enum OperationCompletionWakeClass {
2903    #[default]
2904    Wake,
2905    Ignore,
2906}
2907
2908#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2909pub enum OperationDurabilityClass {
2910    #[default]
2911    Retain,
2912    Discard,
2913}
2914
2915impl From<OperationPublicResultClass> for meerkat_core::ops_lifecycle::OperationPublicResultClass {
2916    fn from(value: OperationPublicResultClass) -> Self {
2917        match value {
2918            OperationPublicResultClass::MissingAuthority => Self::MissingAuthority,
2919            OperationPublicResultClass::Running => Self::Running,
2920            OperationPublicResultClass::Completed => Self::Completed,
2921            OperationPublicResultClass::Failed => Self::Failed,
2922            OperationPublicResultClass::Cancelled => Self::Cancelled,
2923        }
2924    }
2925}
2926
2927impl From<OperationCompletionWakeClass>
2928    for meerkat_core::ops_lifecycle::OperationCompletionWakeClass
2929{
2930    fn from(value: OperationCompletionWakeClass) -> Self {
2931        match value {
2932            OperationCompletionWakeClass::Wake => Self::Wake,
2933            OperationCompletionWakeClass::Ignore => Self::Ignore,
2934        }
2935    }
2936}
2937
2938#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2939pub enum OpRegistrationAdmissionResultKind {
2940    #[default]
2941    Accept,
2942    Reject,
2943}
2944
2945#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2946pub enum OpRegistrationRejectReasonKind {
2947    #[default]
2948    AlreadyRegistered,
2949    MaxConcurrentExceeded,
2950}
2951
2952#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2953pub enum OpLifecycleActionKind {
2954    #[default]
2955    Start,
2956    Fail,
2957    PeerReady,
2958    ProgressReported,
2959    Complete,
2960    Abort,
2961    Cancel,
2962    RetireRequested,
2963    RetireCompleted,
2964    Terminate,
2965}
2966
2967impl From<meerkat_core::ops_lifecycle::OperationLifecycleAction> for OpLifecycleActionKind {
2968    fn from(action: meerkat_core::ops_lifecycle::OperationLifecycleAction) -> Self {
2969        match action {
2970            meerkat_core::ops_lifecycle::OperationLifecycleAction::Start => Self::Start,
2971            meerkat_core::ops_lifecycle::OperationLifecycleAction::Fail => Self::Fail,
2972            meerkat_core::ops_lifecycle::OperationLifecycleAction::PeerReady => Self::PeerReady,
2973            meerkat_core::ops_lifecycle::OperationLifecycleAction::ProgressReported => {
2974                Self::ProgressReported
2975            }
2976            meerkat_core::ops_lifecycle::OperationLifecycleAction::Complete => Self::Complete,
2977            meerkat_core::ops_lifecycle::OperationLifecycleAction::Abort => Self::Abort,
2978            meerkat_core::ops_lifecycle::OperationLifecycleAction::Cancel => Self::Cancel,
2979            meerkat_core::ops_lifecycle::OperationLifecycleAction::RetireRequested => {
2980                Self::RetireRequested
2981            }
2982            meerkat_core::ops_lifecycle::OperationLifecycleAction::RetireCompleted => {
2983                Self::RetireCompleted
2984            }
2985            meerkat_core::ops_lifecycle::OperationLifecycleAction::Terminate => Self::Terminate,
2986        }
2987    }
2988}
2989
2990#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
2991pub enum OpLifecycleRejectReasonKind {
2992    #[default]
2993    OperationNotFound,
2994    InvalidTransition,
2995    PeerNotExpected,
2996    AlreadyPeerReady,
2997}
2998
2999/// Typed input-abandonment reason. Closed mirror of the discriminant set of
3000/// [`crate::input_state::InputAbandonReason`] — replaces the former
3001/// `format!("{reason:?}")` Debug round-trip in the DSL's
3002/// `input_abandon_reason` map.
3003///
3004/// The `MaxAttemptsExhausted` variant's `attempts` payload rides on the
3005/// companion `input_abandon_attempt_count: Map<String, u64>` field of the
3006/// DSL state; this enum only carries the discriminant. The domain
3007/// `InputAbandonReason::MaxAttemptsExhausted { attempts }` is reconstructed
3008/// in the driver by pairing the typed discriminant with that companion map.
3009#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3010pub enum InputAbandonReason {
3011    #[default]
3012    Retired,
3013    Reset,
3014    Stopped,
3015    Destroyed,
3016    Cancelled,
3017    MaxAttemptsExhausted,
3018}
3019
3020impl From<&crate::input_state::InputAbandonReason> for InputAbandonReason {
3021    fn from(reason: &crate::input_state::InputAbandonReason) -> Self {
3022        match reason {
3023            crate::input_state::InputAbandonReason::Retired => Self::Retired,
3024            crate::input_state::InputAbandonReason::Reset => Self::Reset,
3025            crate::input_state::InputAbandonReason::Stopped => Self::Stopped,
3026            crate::input_state::InputAbandonReason::Destroyed => Self::Destroyed,
3027            crate::input_state::InputAbandonReason::Cancelled => Self::Cancelled,
3028            crate::input_state::InputAbandonReason::MaxAttemptsExhausted { .. } => {
3029                Self::MaxAttemptsExhausted
3030            }
3031        }
3032    }
3033}
3034
3035impl InputAbandonReason {
3036    /// Stable lowercase label for event wire formats. Mirrors the
3037    /// snake-case serde representation of the domain enum for consistency
3038    /// with existing consumers.
3039    pub const fn as_str(self) -> &'static str {
3040        match self {
3041            Self::Retired => "retired",
3042            Self::Reset => "reset",
3043            Self::Stopped => "stopped",
3044            Self::Destroyed => "destroyed",
3045            Self::Cancelled => "cancelled",
3046            Self::MaxAttemptsExhausted => "max_attempts_exhausted",
3047        }
3048    }
3049}
3050
3051/// Typed work-lane assignment for admitted inputs. Replaces the former
3052/// parallel `queue_lane` / `steer_lane` sets with a single map
3053/// (`input_lane: Map<String, Enum<InputLane>>`) so mutual exclusion is
3054/// structural — an admitted input is in exactly one lane by construction.
3055///
3056/// DSL-side mirror of the shell's `meerkat_core::types::HandlingMode`; the
3057/// DSL owns the typed mirror so transitions can carry it without depending
3058/// on the shell's domain enum.
3059#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3060pub enum InputLane {
3061    #[default]
3062    Queue,
3063    Steer,
3064}
3065
3066impl From<crate::HandlingMode> for InputLane {
3067    fn from(mode: crate::HandlingMode) -> Self {
3068        match mode {
3069            crate::HandlingMode::Queue => Self::Queue,
3070            crate::HandlingMode::Steer => Self::Steer,
3071        }
3072    }
3073}
3074
3075/// Typed live-admission input kind carried by `ResolveAdmissionPlan`.
3076#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3077pub enum AdmissionInputKind {
3078    #[default]
3079    Prompt,
3080    PeerMessage,
3081    PeerRequest,
3082    PeerResponseProgress,
3083    PeerResponseTerminal,
3084    FlowStep,
3085    ExternalEvent,
3086    Continuation,
3087    Operation,
3088}
3089
3090/// Typed continuation discriminant carried by `ResolveAdmissionPlan`. The DSL
3091/// owns the typed mirror of the shell's `ContinuationKind` so the lane and
3092/// run-apply semantics for WorkGraph attention re-entry are machine-emitted.
3093#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3094pub enum AdmissionContinuationKind {
3095    #[default]
3096    Ordinary,
3097    WorkgraphAttention,
3098}
3099
3100impl From<crate::input::ContinuationKind> for AdmissionContinuationKind {
3101    fn from(kind: crate::input::ContinuationKind) -> Self {
3102        match kind {
3103            crate::input::ContinuationKind::Ordinary => Self::Ordinary,
3104            crate::input::ContinuationKind::WorkgraphAttention => Self::WorkgraphAttention,
3105        }
3106    }
3107}
3108
3109/// Typed durability class observed on an input.
3110#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3111pub enum InputDurabilityKind {
3112    #[default]
3113    Durable,
3114    Ephemeral,
3115    Derived,
3116    Missing,
3117}
3118
3119impl From<crate::input::InputDurability> for InputDurabilityKind {
3120    fn from(durability: crate::input::InputDurability) -> Self {
3121        match durability {
3122            crate::input::InputDurability::Durable => Self::Durable,
3123            crate::input::InputDurability::Ephemeral => Self::Ephemeral,
3124            crate::input::InputDurability::Derived => Self::Derived,
3125        }
3126    }
3127}
3128
3129impl From<Option<crate::input::InputDurability>> for InputDurabilityKind {
3130    fn from(durability: Option<crate::input::InputDurability>) -> Self {
3131        durability.map(Self::from).unwrap_or(Self::Missing)
3132    }
3133}
3134
3135/// Typed input-origin class observed at live admission.
3136#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3137pub enum AdmissionInputOriginKind {
3138    #[default]
3139    Operator,
3140    Peer,
3141    Flow,
3142    System,
3143    External,
3144}
3145
3146impl From<&crate::input::InputOrigin> for AdmissionInputOriginKind {
3147    fn from(origin: &crate::input::InputOrigin) -> Self {
3148        match origin {
3149            crate::input::InputOrigin::Operator => Self::Operator,
3150            crate::input::InputOrigin::Peer { .. } => Self::Peer,
3151            crate::input::InputOrigin::Flow { .. } => Self::Flow,
3152            crate::input::InputOrigin::System => Self::System,
3153            crate::input::InputOrigin::External { .. } => Self::External,
3154        }
3155    }
3156}
3157
3158impl From<crate::identifiers::InputKind> for AdmissionInputKind {
3159    fn from(kind: crate::identifiers::InputKind) -> Self {
3160        match kind {
3161            crate::identifiers::InputKind::Prompt => Self::Prompt,
3162            crate::identifiers::InputKind::PeerMessage => Self::PeerMessage,
3163            crate::identifiers::InputKind::PeerRequest => Self::PeerRequest,
3164            crate::identifiers::InputKind::PeerResponseProgress => Self::PeerResponseProgress,
3165            crate::identifiers::InputKind::PeerResponseTerminal => Self::PeerResponseTerminal,
3166            crate::identifiers::InputKind::FlowStep => Self::FlowStep,
3167            crate::identifiers::InputKind::ExternalEvent => Self::ExternalEvent,
3168            crate::identifiers::InputKind::Continuation => Self::Continuation,
3169            crate::identifiers::InputKind::Operation => Self::Operation,
3170        }
3171    }
3172}
3173
3174#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3175pub enum AdmissionPolicyApplyMode {
3176    #[default]
3177    StageRunStart,
3178    StageRunBoundary,
3179    InjectNow,
3180    Ignore,
3181}
3182
3183impl From<AdmissionPolicyApplyMode> for crate::policy::ApplyMode {
3184    fn from(mode: AdmissionPolicyApplyMode) -> Self {
3185        match mode {
3186            AdmissionPolicyApplyMode::StageRunStart => Self::StageRunStart,
3187            AdmissionPolicyApplyMode::StageRunBoundary => Self::StageRunBoundary,
3188            AdmissionPolicyApplyMode::InjectNow => Self::InjectNow,
3189            AdmissionPolicyApplyMode::Ignore => Self::Ignore,
3190        }
3191    }
3192}
3193
3194impl From<crate::policy::ApplyMode> for AdmissionPolicyApplyMode {
3195    fn from(mode: crate::policy::ApplyMode) -> Self {
3196        match mode {
3197            crate::policy::ApplyMode::StageRunStart => Self::StageRunStart,
3198            crate::policy::ApplyMode::StageRunBoundary => Self::StageRunBoundary,
3199            crate::policy::ApplyMode::InjectNow => Self::InjectNow,
3200            crate::policy::ApplyMode::Ignore => Self::Ignore,
3201        }
3202    }
3203}
3204
3205#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3206pub enum AdmissionPolicyWakeMode {
3207    #[default]
3208    WakeIfIdle,
3209    InterruptYielding,
3210    None,
3211}
3212
3213impl From<AdmissionPolicyWakeMode> for crate::policy::WakeMode {
3214    fn from(mode: AdmissionPolicyWakeMode) -> Self {
3215        match mode {
3216            AdmissionPolicyWakeMode::WakeIfIdle => Self::WakeIfIdle,
3217            AdmissionPolicyWakeMode::InterruptYielding => Self::InterruptYielding,
3218            AdmissionPolicyWakeMode::None => Self::None,
3219        }
3220    }
3221}
3222
3223#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3224pub enum AdmissionPolicyQueueMode {
3225    None,
3226    #[default]
3227    Fifo,
3228    Coalesce,
3229    Supersede,
3230    Priority,
3231}
3232
3233impl From<AdmissionPolicyQueueMode> for crate::policy::QueueMode {
3234    fn from(mode: AdmissionPolicyQueueMode) -> Self {
3235        match mode {
3236            AdmissionPolicyQueueMode::None => Self::None,
3237            AdmissionPolicyQueueMode::Fifo => Self::Fifo,
3238            AdmissionPolicyQueueMode::Coalesce => Self::Coalesce,
3239            AdmissionPolicyQueueMode::Supersede => Self::Supersede,
3240            AdmissionPolicyQueueMode::Priority => Self::Priority,
3241        }
3242    }
3243}
3244
3245#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3246pub enum AdmissionPolicyConsumePoint {
3247    OnAccept,
3248    OnApply,
3249    OnRunStart,
3250    #[default]
3251    OnRunComplete,
3252    ExplicitAck,
3253}
3254
3255impl From<AdmissionPolicyConsumePoint> for crate::policy::ConsumePoint {
3256    fn from(point: AdmissionPolicyConsumePoint) -> Self {
3257        match point {
3258            AdmissionPolicyConsumePoint::OnAccept => Self::OnAccept,
3259            AdmissionPolicyConsumePoint::OnApply => Self::OnApply,
3260            AdmissionPolicyConsumePoint::OnRunStart => Self::OnRunStart,
3261            AdmissionPolicyConsumePoint::OnRunComplete => Self::OnRunComplete,
3262            AdmissionPolicyConsumePoint::ExplicitAck => Self::ExplicitAck,
3263        }
3264    }
3265}
3266
3267#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3268pub enum AdmissionPolicyDrainPolicy {
3269    #[default]
3270    QueueNextTurn,
3271    SteerBatch,
3272    Immediate,
3273    Ignore,
3274}
3275
3276impl From<AdmissionPolicyDrainPolicy> for crate::policy::DrainPolicy {
3277    fn from(policy: AdmissionPolicyDrainPolicy) -> Self {
3278        match policy {
3279            AdmissionPolicyDrainPolicy::QueueNextTurn => Self::QueueNextTurn,
3280            AdmissionPolicyDrainPolicy::SteerBatch => Self::SteerBatch,
3281            AdmissionPolicyDrainPolicy::Immediate => Self::Immediate,
3282            AdmissionPolicyDrainPolicy::Ignore => Self::Ignore,
3283        }
3284    }
3285}
3286
3287#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3288pub enum AdmissionRoutingDisposition {
3289    #[default]
3290    Queue,
3291    Steer,
3292    Immediate,
3293    Drop,
3294}
3295
3296impl From<AdmissionRoutingDisposition> for crate::policy::RoutingDisposition {
3297    fn from(disposition: AdmissionRoutingDisposition) -> Self {
3298        match disposition {
3299            AdmissionRoutingDisposition::Queue => Self::Queue,
3300            AdmissionRoutingDisposition::Steer => Self::Steer,
3301            AdmissionRoutingDisposition::Immediate => Self::Immediate,
3302            AdmissionRoutingDisposition::Drop => Self::Drop,
3303        }
3304    }
3305}
3306
3307#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3308pub enum AdmissionRunApplyBoundary {
3309    #[default]
3310    RunStart,
3311    RunCheckpoint,
3312    Immediate,
3313}
3314
3315impl From<AdmissionRunApplyBoundary> for meerkat_core::lifecycle::run_primitive::RunApplyBoundary {
3316    fn from(boundary: AdmissionRunApplyBoundary) -> Self {
3317        match boundary {
3318            AdmissionRunApplyBoundary::RunStart => Self::RunStart,
3319            AdmissionRunApplyBoundary::RunCheckpoint => Self::RunCheckpoint,
3320            AdmissionRunApplyBoundary::Immediate => Self::Immediate,
3321        }
3322    }
3323}
3324
3325#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3326pub enum AdmissionRuntimeExecutionKind {
3327    #[default]
3328    ContentTurn,
3329    ResumePending,
3330}
3331
3332impl From<AdmissionRuntimeExecutionKind> for meerkat_core::lifecycle::RuntimeExecutionKind {
3333    fn from(kind: AdmissionRuntimeExecutionKind) -> Self {
3334        match kind {
3335            AdmissionRuntimeExecutionKind::ContentTurn => Self::ContentTurn,
3336            AdmissionRuntimeExecutionKind::ResumePending => Self::ResumePending,
3337        }
3338    }
3339}
3340
3341#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3342pub enum AdmissionPeerResponseTerminalApplyIntent {
3343    #[default]
3344    AppendContextAndRun,
3345}
3346
3347impl From<AdmissionPeerResponseTerminalApplyIntent>
3348    for meerkat_core::lifecycle::run_primitive::PeerResponseTerminalApplyIntent
3349{
3350    fn from(intent: AdmissionPeerResponseTerminalApplyIntent) -> Self {
3351        match intent {
3352            AdmissionPeerResponseTerminalApplyIntent::AppendContextAndRun => {
3353                Self::AppendContextAndRun
3354            }
3355        }
3356    }
3357}
3358
3359#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3360pub enum AdmissionPlanKind {
3361    ConsumedOnAccept,
3362    #[default]
3363    Queued,
3364}
3365
3366#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3367pub enum AdmissionIdempotencyResultKind {
3368    #[default]
3369    Accept,
3370    Deduplicated,
3371}
3372
3373#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3374pub enum AdmissionValidationResultKind {
3375    #[default]
3376    Accept,
3377    Reject,
3378}
3379
3380#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3381pub enum PeerResponseTerminalObservedStatus {
3382    #[default]
3383    NotPeerTerminal,
3384    Completed,
3385    Failed,
3386    Cancelled,
3387}
3388
3389/// Typed admission-validation rejection reason emitted on
3390/// `AdmissionValidationResolved`. The machine names which validation rule
3391/// fired; shells render display text from this fact instead of mirroring the
3392/// guard rules.
3393#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3394pub enum AdmissionRejectReasonKind {
3395    #[default]
3396    DurabilityMissing,
3397    ExternalDerivedDurabilityForbidden,
3398    DerivedDurabilityForbiddenForInputKind,
3399    PeerHandlingModeInvalid,
3400    PeerResponseTerminalInvalid,
3401}
3402
3403#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3404pub enum WaitAllAdmissionResultKind {
3405    #[default]
3406    Accept,
3407    Reject,
3408}
3409
3410#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3411pub enum WaitAllRejectReasonKind {
3412    #[default]
3413    DuplicateOperation,
3414    WaitAlreadyActive,
3415    OperationNotFound,
3416}
3417
3418#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3419pub enum RecoveredInputNormalizationReasonKind {
3420    #[default]
3421    QueueAccepted,
3422    RollbackStaged,
3423    BoundaryReceiptCommitted,
3424    MissingBoundaryReceipt,
3425}
3426
3427#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3428pub enum AdmissionQueueActionKind {
3429    #[default]
3430    None,
3431    EnqueueTo,
3432    EnqueueFront,
3433}
3434
3435#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3436pub enum AdmissionExistingQueuedActionKind {
3437    #[default]
3438    None,
3439    Coalesce,
3440    Supersede,
3441}
3442
3443/// Typed persisted input kind carried by recovered-admission witnesses.
3444#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3445pub enum RecoveredInputKind {
3446    #[default]
3447    Prompt,
3448    PeerMessage,
3449    PeerRequest,
3450    PeerResponseProgress,
3451    PeerResponseTerminal,
3452    FlowStep,
3453    ExternalEvent,
3454    Continuation,
3455    Operation,
3456}
3457
3458/// Generated recovery disposition for a persisted input row.
3459#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3460pub enum RecoveredInputRecoveryDisposition {
3461    #[default]
3462    Retain,
3463    Discard,
3464}
3465
3466impl From<crate::identifiers::InputKind> for RecoveredInputKind {
3467    fn from(kind: crate::identifiers::InputKind) -> Self {
3468        match kind {
3469            crate::identifiers::InputKind::Prompt => Self::Prompt,
3470            crate::identifiers::InputKind::PeerMessage => Self::PeerMessage,
3471            crate::identifiers::InputKind::PeerRequest => Self::PeerRequest,
3472            crate::identifiers::InputKind::PeerResponseProgress => Self::PeerResponseProgress,
3473            crate::identifiers::InputKind::PeerResponseTerminal => Self::PeerResponseTerminal,
3474            crate::identifiers::InputKind::FlowStep => Self::FlowStep,
3475            crate::identifiers::InputKind::ExternalEvent => Self::ExternalEvent,
3476            crate::identifiers::InputKind::Continuation => Self::Continuation,
3477            crate::identifiers::InputKind::Operation => Self::Operation,
3478        }
3479    }
3480}
3481
3482/// Typed persisted runtime apply boundary carried by recovered-admission
3483/// witnesses.
3484#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3485pub enum RecoveredRunApplyBoundary {
3486    #[default]
3487    RunStart,
3488    RunCheckpoint,
3489    Immediate,
3490}
3491
3492impl TryFrom<meerkat_core::lifecycle::run_primitive::RunApplyBoundary>
3493    for RecoveredRunApplyBoundary
3494{
3495    type Error = &'static str;
3496
3497    fn try_from(
3498        boundary: meerkat_core::lifecycle::run_primitive::RunApplyBoundary,
3499    ) -> Result<Self, Self::Error> {
3500        match boundary {
3501            meerkat_core::lifecycle::run_primitive::RunApplyBoundary::RunStart => {
3502                Ok(Self::RunStart)
3503            }
3504            meerkat_core::lifecycle::run_primitive::RunApplyBoundary::RunCheckpoint => {
3505                Ok(Self::RunCheckpoint)
3506            }
3507            meerkat_core::lifecycle::run_primitive::RunApplyBoundary::Immediate => {
3508                Ok(Self::Immediate)
3509            }
3510            _ => Err("unknown recovered runtime boundary"),
3511        }
3512    }
3513}
3514
3515/// Typed persisted runtime execution class carried by recovered-admission
3516/// witnesses.
3517#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3518pub enum RecoveredRuntimeExecutionKind {
3519    #[default]
3520    ContentTurn,
3521    ResumePending,
3522}
3523
3524impl From<meerkat_core::lifecycle::RuntimeExecutionKind> for RecoveredRuntimeExecutionKind {
3525    fn from(kind: meerkat_core::lifecycle::RuntimeExecutionKind) -> Self {
3526        match kind {
3527            meerkat_core::lifecycle::RuntimeExecutionKind::ContentTurn => Self::ContentTurn,
3528            meerkat_core::lifecycle::RuntimeExecutionKind::ResumePending => Self::ResumePending,
3529        }
3530    }
3531}
3532
3533/// Typed recovered terminal peer-response apply intent.
3534#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3535pub enum RecoveredPeerResponseTerminalApplyIntent {
3536    #[default]
3537    AppendContextAndRun,
3538}
3539
3540impl From<meerkat_core::lifecycle::run_primitive::PeerResponseTerminalApplyIntent>
3541    for RecoveredPeerResponseTerminalApplyIntent
3542{
3543    fn from(
3544        intent: meerkat_core::lifecycle::run_primitive::PeerResponseTerminalApplyIntent,
3545    ) -> Self {
3546        match intent {
3547            meerkat_core::lifecycle::run_primitive::PeerResponseTerminalApplyIntent::AppendContextAndRun => {
3548                Self::AppendContextAndRun
3549            }
3550        }
3551    }
3552}
3553
3554#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3555pub enum RoutingSwitchTurnPhase {
3556    #[default]
3557    Requested,
3558    PendingForBoundary,
3559    ActiveFiniteOverride,
3560    ApplyingPersistentReconfigure,
3561    Terminal,
3562}
3563
3564#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3565pub enum RoutingSwitchTurnTerminal {
3566    #[default]
3567    Denied,
3568    ConsumedAndRestored,
3569    PersistentReconfigureApplied,
3570}
3571
3572#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3573pub enum RoutingDenialReason {
3574    #[default]
3575    CapabilityPolicy,
3576    ApprovalRequiredButUnavailable,
3577    DeniedDuringApproval,
3578    ScopedOverrideConflict,
3579    RealtimeTransportConflict,
3580}
3581
3582#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3583pub enum RoutingSwitchApprovalReason {
3584    #[default]
3585    CrossProvider,
3586    CostExceedsThreshold,
3587    SafetyHold,
3588    UntilChangedFromModelOrigin,
3589    RealtimeDetachRequired,
3590}
3591
3592#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3593pub enum RoutingImageApprovalReason {
3594    #[default]
3595    CrossProvider,
3596    CostExceedsThreshold,
3597    SafetyHold,
3598    RealtimeDetachRequired,
3599}
3600
3601#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3602pub enum RoutingImagePlanDenialReason {
3603    #[default]
3604    UnsupportedTarget,
3605    UnsupportedCount,
3606    CapabilityPolicy,
3607    CostPolicy,
3608    SafetyPolicy,
3609    ApprovalRequiredButUnavailable,
3610    DeniedDuringApproval,
3611    ScopedOverrideConflict,
3612    RealtimeTransportConflict,
3613    ProjectionUnsupported,
3614}
3615
3616#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3617pub enum RoutingApprovalPhase {
3618    #[default]
3619    Pending,
3620    PresentedToUser,
3621    Approved,
3622    Denied,
3623    SurfaceDetached,
3624}
3625
3626#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3627pub enum RoutingApprovalParentKind {
3628    #[default]
3629    SwitchTurn,
3630    ImageOperation,
3631}
3632
3633#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3634pub enum RoutingImageOperationPhase {
3635    #[default]
3636    Requested,
3637    PlanResolved,
3638    ScopedOverrideActive,
3639    ProviderCallInFlight,
3640    ResultCommitted,
3641    RestoringScopedOverride,
3642    Terminal,
3643}
3644
3645#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3646pub enum RoutingImageTerminal {
3647    #[default]
3648    Generated,
3649    Denied,
3650    EmptyResult,
3651    RefusedByProvider,
3652    SafetyFiltered,
3653    Failed,
3654    Cancelled,
3655    Timeout,
3656    ScopedRestoreFailed,
3657}
3658
3659#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3660pub enum RoutingImageTerminalObservation {
3661    #[default]
3662    Generated,
3663    EmptyResult,
3664    ProviderHttpError,
3665    ProviderNativeError,
3666    ExecutionFailed,
3667    BlobCommitFailed,
3668}
3669
3670#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3671pub enum RoutingImageProviderErrorCode {
3672    #[default]
3673    Unknown,
3674    OpenAiContentFilter,
3675    OpenAiModelRefusal,
3676    GeminiSafety,
3677    GeminiModelRefusal,
3678    GeminiDeadlineExceeded,
3679}
3680
3681#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3682pub enum RoutingProviderTextDisposition {
3683    #[default]
3684    NotEmitted,
3685    Captured,
3686    EmittedButNotStored,
3687}
3688
3689/// Typed bridge command class for supervisor-authorized mob peer overlay
3690/// observations. The runtime submits this as part of the generated
3691/// MeerkatMachine overlay authorization input so the bridge surface does not
3692/// decide whether the command peer should be present or absent.
3693#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3694pub enum MobPeerOverlayCommandKind {
3695    #[default]
3696    Wire,
3697    Unwire,
3698}
3699
3700/// Generated admission result for supervisor bridge commands that require an
3701/// already-bound supervisor. The bridge shell may project this result to the
3702/// wire response, but it must not classify binding/epoch/sender admission from
3703/// snapshots on its own.
3704#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3705pub enum SupervisorBridgeCommandAdmissionResultKind {
3706    #[default]
3707    Accept,
3708    Reject,
3709}
3710
3711/// Generated public rejection class for supervisor bridge command admission.
3712#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3713pub enum SupervisorBridgeCommandRejectionKind {
3714    #[default]
3715    NotBound,
3716    StaleSupervisor,
3717    SenderMismatch,
3718}
3719
3720/// Generated admission result for `BindMember`, before bootstrap transport
3721/// checks or supervisor binding mutation.
3722#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3723pub enum SupervisorBindAdmissionResultKind {
3724    #[default]
3725    Bootstrap,
3726    IdempotentAck,
3727    Reject,
3728}
3729
3730/// Generated public rejection class for `BindMember` admission.
3731#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3732pub enum SupervisorBindRejectionKind {
3733    #[default]
3734    AlreadyBound,
3735    SenderMismatch,
3736}
3737
3738/// Generated material-admission verdict for `BindMember`. Owns the
3739/// transport/identity equality checks the shell previously decided inline:
3740/// advertised-address match, raw supervisor-peer sender match, expected
3741/// runtime peer-id match, and bootstrap-token match. The shell extracts the
3742/// four pure boolean observations and mirrors this verdict in the precedence
3743/// order address → sender → peer-id → token, else accept.
3744#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3745pub enum SupervisorBindMaterialAdmissionKind {
3746    #[default]
3747    Accept,
3748    AddressMismatch,
3749    SenderMismatch,
3750    InvalidPeerSpec,
3751    InvalidBootstrapToken,
3752}
3753
3754/// Generated session-liveness verdict for an attempted transcript edit (fork /
3755/// rewrite / restore). Owns the `SESSION_BUSY` disjunction the shell previously
3756/// decided inline: a session is busy iff its runtime is running OR it holds any
3757/// active inputs. The shell extracts the two pure boolean observations
3758/// (`runtime_running`, `has_active_inputs`) and mirrors this verdict.
3759#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3760pub enum TranscriptEditAdmissionKind {
3761    #[default]
3762    Admissible,
3763    DeniedBusy,
3764}
3765
3766/// Generated admission result for `AuthorizeSupervisor`.
3767#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3768pub enum SupervisorAuthorizeAdmissionResultKind {
3769    #[default]
3770    Proceed,
3771    IdempotentAck,
3772    Reject,
3773}
3774
3775/// Generated public rejection class for `AuthorizeSupervisor` admission.
3776#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3777pub enum SupervisorAuthorizeRejectionKind {
3778    #[default]
3779    NotBound,
3780    StaleSupervisor,
3781    SenderMismatch,
3782}
3783
3784// Track-B (R5): declarative peer endpoint descriptor for the runtime
3785// DSL. Shape mirrors `meerkat_core::comms::TrustedPeerDescriptor`.
3786// The catalog DSL holds an identical type; the two are structurally
3787// equivalent so the schema validator sees consistent opaque struct
3788// shapes.
3789#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3790pub struct PeerEndpoint {
3791    pub name: PeerName,
3792    pub peer_id: PeerId,
3793    pub address: PeerAddress,
3794    pub signing_key: PeerSigningKey,
3795}
3796
3797impl PeerEndpoint {
3798    pub fn new(
3799        name: impl Into<PeerName>,
3800        peer_id: impl Into<PeerId>,
3801        address: impl Into<PeerAddress>,
3802        signing_key: impl Into<PeerSigningKey>,
3803    ) -> Self {
3804        Self {
3805            name: name.into(),
3806            peer_id: peer_id.into(),
3807            address: address.into(),
3808            signing_key: signing_key.into(),
3809        }
3810    }
3811}
3812
3813impl From<&meerkat_core::comms::TrustedPeerDescriptor> for PeerEndpoint {
3814    fn from(spec: &meerkat_core::comms::TrustedPeerDescriptor) -> Self {
3815        Self {
3816            name: PeerName(spec.name.as_str().to_owned()),
3817            peer_id: PeerId(spec.peer_id.to_string()),
3818            address: PeerAddress(spec.address.to_string()),
3819            signing_key: PeerSigningKey(spec.pubkey),
3820        }
3821    }
3822}
3823
3824/// DSL-local carrier for the Ed25519 public signing key associated with a
3825/// peer endpoint. The MeerkatMachine owns this projection alongside the
3826/// endpoint identity atoms so trust reconciliation can install the exact
3827/// key into the comms trust store without shell-side defaults.
3828#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3829pub struct PeerSigningKey(pub [u8; 32]);
3830
3831impl From<[u8; 32]> for PeerSigningKey {
3832    fn from(key: [u8; 32]) -> Self {
3833        Self(key)
3834    }
3835}
3836
3837/// DSL-local newtype for a peer display name. Wraps the slug string
3838/// so the schema validator sees a stable opaque shape; mirrors
3839/// `meerkat_core::comms::PeerName` but avoids dragging the core
3840/// comms types into the DSL grammar.
3841#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3842pub struct PeerName(pub String);
3843
3844impl<T: Into<String>> From<T> for PeerName {
3845    fn from(s: T) -> Self {
3846        Self(s.into())
3847    }
3848}
3849
3850impl PeerName {
3851    pub fn as_str(&self) -> &str {
3852        &self.0
3853    }
3854}
3855
3856/// DSL-local newtype for the canonical peer routing id.
3857#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3858pub struct PeerId(pub String);
3859
3860impl<T: Into<String>> From<T> for PeerId {
3861    fn from(s: T) -> Self {
3862        Self(s.into())
3863    }
3864}
3865
3866impl PeerId {
3867    pub fn as_str(&self) -> &str {
3868        &self.0
3869    }
3870}
3871
3872/// DSL-local newtype for a peer transport endpoint URL.
3873#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
3874pub struct PeerAddress(pub String);
3875
3876impl<T: Into<String>> From<T> for PeerAddress {
3877    fn from(s: T) -> Self {
3878        Self(s.into())
3879    }
3880}
3881
3882impl PeerAddress {
3883    pub fn as_str(&self) -> &str {
3884        &self.0
3885    }
3886}
3887
3888// Ensure we keep the exact generated schema DSL body from the catalog source.
3889
3890// MeerkatMachine production body is catalog-owned. Keep bridge/runtime mechanics
3891// outside this macro invocation; canonical semantics live in the catalog DSL.
3892meerkat_machine_schema::meerkat_catalog_machine_dsl!("meerkat-runtime", "meerkat_machine::dsl");
3893
3894pub type MobToolCallerProvenance = meerkat_core::service::MobToolCallerProvenance;
3895pub type OpaquePrincipalToken = meerkat_core::service::OpaquePrincipalToken;
3896
3897// =====================================================================