1use std::collections::BTreeMap;
8use std::sync::Arc;
9
10use crate::meerkat_machine::{CommsDrainMode, CommsDrainPhase, DrainExitReason, dsl};
11use indexmap::IndexSet;
12use meerkat_core::RuntimeEpochId;
13use meerkat_core::agent::CommsRuntime;
14use meerkat_core::image_generation::{
15 ImageOperationApprovalReason, ImageOperationDenialReason, ImageOperationId,
16 ImageOperationPhase, ImageOperationTerminalClass, ImageProviderTerminalObservation,
17 ProviderTextDisposition, SessionModelRoutingStatus, SwitchTurnApprovalReason,
18 SwitchTurnControlResult, SwitchTurnIntent, SwitchTurnRequestId,
19};
20use meerkat_core::lifecycle::WaitRequestId;
21use meerkat_core::lifecycle::core_executor::CoreExecutor;
22use meerkat_core::lifecycle::run_primitive::{ModelId, TurnMetadataOverride};
23use meerkat_core::lifecycle::{InputId, RunId};
24use meerkat_core::lifecycle::{RunBoundaryReceipt, RunId as LifecycleRunId};
25use meerkat_core::ops::OperationId;
26use meerkat_core::ops_lifecycle::OperationLifecycleSnapshot;
27use meerkat_core::types::HandlingMode;
28use meerkat_core::types::SessionId;
29use meerkat_machine_derive::CommandManifest;
30use meerkat_machine_schema::catalog::dsl::meerkat_machine::MeerkatMachineInputVariant;
31use serde::{Deserialize, Serialize};
32
33use crate::AcceptOutcome;
34use crate::identifiers::LogicalRuntimeId;
35use crate::ingress_types::{ContentShape, RequestId, ReservationKey};
36use crate::input::Input;
37use crate::input_state::InputLifecycleState;
38use crate::input_state::InputTerminalOutcome;
39use crate::input_state::StoredInputState;
40use crate::runtime_event::RuntimeEventEnvelope;
41use crate::runtime_state::RuntimeState;
42use crate::traits::{
43 DestroyReport, RecoveryReport, RecycleReport, ResetReport, RetireReport,
44 RuntimeControlPlaneError, RuntimeDriverError,
45};
46
47#[derive(Debug, Clone, Serialize, PartialEq)]
54#[serde(rename_all = "snake_case")]
55pub struct SessionLlmReconfigureRequest {
56 #[serde(default, skip_serializing_if = "Option::is_none")]
57 pub model: Option<String>,
58 #[serde(default, skip_serializing_if = "Option::is_none")]
59 pub provider: Option<String>,
60 #[serde(default, skip_serializing_if = "Option::is_none")]
61 pub provider_params: Option<
62 TurnMetadataOverride<meerkat_core::lifecycle::run_primitive::ProviderParamsOverride>,
63 >,
64 #[serde(default, skip_serializing_if = "Option::is_none")]
68 pub auth_binding: Option<TurnMetadataOverride<meerkat_core::AuthBindingRef>>,
69}
70
71#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
72#[serde(rename_all = "snake_case")]
73pub enum SessionLlmCapabilitySurfaceStatus {
74 Resolved,
75 #[default]
76 Unresolved,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
80#[serde(rename_all = "snake_case")]
81pub struct SessionLlmCapabilitySurface {
82 pub supports_temperature: bool,
83 pub supports_thinking: bool,
84 pub supports_reasoning: bool,
85 pub inline_video: bool,
86 pub vision: bool,
87 #[serde(default)]
88 pub image_input: bool,
89 pub image_tool_results: bool,
90 pub supports_web_search: bool,
91 #[serde(default)]
92 pub image_generation: bool,
93 #[serde(default)]
97 pub realtime: bool,
98 #[serde(default, skip_serializing_if = "Option::is_none")]
99 pub call_timeout_secs: Option<u64>,
100}
101
102impl SessionLlmCapabilitySurface {
103 #[must_use]
104 pub fn to_wire_resolved(&self) -> meerkat_contracts::WireResolvedModelCapabilities {
105 meerkat_contracts::WireResolvedModelCapabilities {
106 vision: self.vision,
107 image_input: self.image_input,
108 image_tool_results: self.image_tool_results,
109 inline_video: self.inline_video,
110 realtime: self.realtime,
111 web_search: self.supports_web_search,
112 image_generation: self.image_generation,
113 }
114 }
115}
116
117#[derive(Debug, Clone, PartialEq, Eq)]
118pub struct SessionLlmCapabilityDelta {
119 pub previous: Option<SessionLlmCapabilitySurface>,
120 pub current: Option<SessionLlmCapabilitySurface>,
121 pub changed: bool,
122}
123
124#[derive(Debug, Clone, PartialEq, Eq)]
125pub struct SessionToolVisibilityDelta {
126 pub previous_capability_base_filter: meerkat_core::ToolFilter,
127 pub current_capability_base_filter: meerkat_core::ToolFilter,
128 pub committed_visible_set_changed: bool,
129 pub revision_bumped: bool,
130}
131
132#[derive(Debug, Clone, PartialEq)]
133pub struct SessionLlmReconfigureReport {
134 pub previous_identity: meerkat_core::SessionLlmIdentity,
135 pub new_identity: meerkat_core::SessionLlmIdentity,
136 pub capability_delta: SessionLlmCapabilityDelta,
137 pub tool_visibility_delta: SessionToolVisibilityDelta,
138 pub rollback_occurred: bool,
139}
140
141#[derive(Debug, Clone)]
142pub struct HydratedSessionLlmState {
143 pub current_identity: meerkat_core::SessionLlmIdentity,
144 pub current_visibility_state: meerkat_core::SessionToolVisibilityState,
145 pub current_capability_surface: Option<SessionLlmCapabilitySurface>,
146 pub capability_surface_status: SessionLlmCapabilitySurfaceStatus,
147 pub base_tool_names: std::collections::BTreeSet<meerkat_core::ToolName>,
148}
149
150#[derive(Debug, Clone)]
151pub struct ResolvedSessionLlmReconfigure {
152 pub target_identity: meerkat_core::SessionLlmIdentity,
153 pub target_capability_surface: SessionLlmCapabilitySurface,
154}
155
156#[derive(Debug, Clone, Copy, PartialEq, Eq)]
157pub enum ModelRoutingApprovalDisposition {
158 NotRequired,
159 Approved,
160 DeniedByUser,
161 RequiredButUnavailable,
162}
163
164#[derive(Debug, Clone, Copy, PartialEq, Eq)]
165pub struct ModelRoutingRealtimePolicy {
166 pub target_realtime_capable: bool,
167 pub allow_realtime_detach: bool,
168}
169
170#[derive(Debug, Clone, PartialEq, Eq)]
171pub struct SwitchTurnRequest {
172 pub request_id: SwitchTurnRequestId,
173 pub intent: SwitchTurnIntent,
174 pub target_realtime: ModelRoutingRealtimePolicy,
175 pub approval: ModelRoutingApprovalDisposition,
176 pub approval_reason: Option<SwitchTurnApprovalReason>,
177}
178
179#[derive(Debug, Clone, PartialEq, Eq)]
180pub struct ImageOperationRoutingRequest {
181 pub operation_id: ImageOperationId,
182 pub target_model: ModelId,
183 pub target_realtime: ModelRoutingRealtimePolicy,
184 pub approval: ModelRoutingApprovalDisposition,
185 pub approval_reason: Option<ImageOperationApprovalReason>,
186 pub requires_scoped_override: bool,
187}
188
189#[derive(Debug, Clone, PartialEq, Eq)]
190pub enum ImageOperationRoutingResult {
191 Accepted {
192 operation_id: ImageOperationId,
193 phase: ImageOperationPhase,
194 },
195 Denied {
196 operation_id: ImageOperationId,
197 reason: ImageOperationDenialReason,
198 },
199}
200
201#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
202#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
203pub trait SessionLlmReconfigureHost: Send + Sync {
204 async fn hydrate_session_llm_state(
205 &self,
206 session_id: &SessionId,
207 ) -> Result<HydratedSessionLlmState, RuntimeDriverError>;
208
209 async fn resolve_target_session_llm_identity(
210 &self,
211 request: &SessionLlmReconfigureRequest,
212 current_identity: &meerkat_core::SessionLlmIdentity,
213 ) -> Result<ResolvedSessionLlmReconfigure, RuntimeDriverError>;
214
215 async fn apply_live_session_llm_identity(
216 &self,
217 session_id: &SessionId,
218 identity: &meerkat_core::SessionLlmIdentity,
219 ) -> Result<(), RuntimeDriverError>;
220
221 async fn apply_live_session_tool_visibility_state(
222 &self,
223 session_id: &SessionId,
224 visibility_state: Option<meerkat_core::SessionToolVisibilityState>,
225 ) -> Result<(), RuntimeDriverError>;
226
227 async fn persist_live_session(&self, session_id: &SessionId) -> Result<(), RuntimeDriverError>;
228
229 async fn discard_live_session(&self, session_id: &SessionId) -> Result<(), RuntimeDriverError>;
230}
231
232#[derive(Debug, thiserror::Error)]
233pub(crate) enum MeerkatMachineCommandError {
234 #[error(transparent)]
235 Driver(#[from] RuntimeDriverError),
236 #[error(transparent)]
237 Control(#[from] RuntimeControlPlaneError),
238}
239
240#[derive(CommandManifest)]
246#[allow(clippy::large_enum_variant)]
247pub(crate) enum MeerkatMachineCommand {
248 RegisterSession {
249 session_id: SessionId,
250 },
251 #[cfg_attr(not(test), allow(dead_code))]
254 UnregisterSession {
255 session_id: SessionId,
256 },
257 EnsureSessionWithExecutor {
258 session_id: SessionId,
259 executor: Box<dyn CoreExecutor>,
260 },
261 SetSilentIntents {
262 session_id: SessionId,
263 intents: Vec<String>,
264 },
265 CancelAfterBoundary {
266 session_id: SessionId,
267 },
268 StopRuntimeExecutor {
269 session_id: SessionId,
270 reason: String,
271 },
272 CommitServiceTurnTerminalReceipt {
273 session_id: SessionId,
274 },
275 #[cfg_attr(not(test), allow(dead_code))]
276 ContainsSession {
277 session_id: SessionId,
278 },
279 SessionHasExecutor {
280 session_id: SessionId,
281 },
282 SessionHasComms {
283 session_id: SessionId,
284 },
285 OpsLifecycleRegistry {
286 session_id: SessionId,
287 },
288 #[cfg_attr(not(test), allow(dead_code))]
291 PrepareBindings {
292 session_id: SessionId,
293 },
294 #[cfg_attr(not(test), allow(dead_code))]
297 PrepareLocalSessionBindings {
298 session_id: SessionId,
299 },
300 InputState {
301 session_id: SessionId,
302 input_id: InputId,
303 },
304 InputStateByIdempotencyKey {
311 session_id: SessionId,
312 idempotency_key: String,
313 },
314 InteractionTerminalStatus {
319 session_id: SessionId,
320 selector: crate::terminal_status::InteractionSelector,
321 },
322 RunTerminalStatus {
326 session_id: SessionId,
327 run_id: RunId,
328 },
329 ListActiveInputs {
330 session_id: SessionId,
331 },
332 ReconfigureSessionLlmIdentity {
333 session_id: SessionId,
334 previous_identity: Box<meerkat_core::SessionLlmIdentity>,
335 previous_visibility_state: Box<meerkat_core::SessionToolVisibilityState>,
336 previous_capability_surface: Option<SessionLlmCapabilitySurface>,
337 previous_capability_surface_status: SessionLlmCapabilitySurfaceStatus,
338 view_image_tool_available: bool,
339 previous_view_image_visible: bool,
340 next_view_image_visible: bool,
341 previous_active_visibility_revision: u64,
342 previous_staged_visibility_revision: u64,
343 target_identity: Box<meerkat_core::SessionLlmIdentity>,
344 target_capability_surface: Box<SessionLlmCapabilitySurface>,
345 next_visibility_state: Box<meerkat_core::SessionToolVisibilityState>,
346 next_capability_base_filter: meerkat_core::ToolFilter,
347 next_active_visibility_revision: u64,
348 tool_visibility_delta: Box<SessionToolVisibilityDelta>,
349 },
350 StagePersistentFilter {
351 session_id: SessionId,
352 filter: meerkat_core::ToolFilter,
353 witnesses:
354 std::collections::BTreeMap<meerkat_core::ToolName, meerkat_core::ToolVisibilityWitness>,
355 },
356 RequestDeferredTools {
357 session_id: SessionId,
358 authorities: Vec<meerkat_core::DeferredToolLoadAuthority>,
359 },
360 PublishCommittedVisibleSet {
366 session_id: SessionId,
367 visibility_state: Box<meerkat_core::SessionToolVisibilityState>,
368 },
369 SetPeerIngressContext {
370 session_id: SessionId,
371 keep_alive: bool,
372 comms_runtime: Option<Arc<dyn CommsRuntime>>,
373 mob_id: Option<crate::meerkat_machine::dsl::MobId>,
377 },
378 NotifyDrainExited {
379 session_id: SessionId,
380 reason: DrainExitReason,
381 },
382 AbortAll,
383 Abort {
384 session_id: SessionId,
385 },
386 Wait {
387 session_id: SessionId,
388 },
389 Ingest {
390 runtime_id: LogicalRuntimeId,
391 input: Input,
392 },
393 PublishEvent {
394 event: RuntimeEventEnvelope,
395 },
396 Retire {
397 runtime_id: LogicalRuntimeId,
398 },
399 Recycle {
400 runtime_id: LogicalRuntimeId,
401 },
402 Reset {
403 runtime_id: LogicalRuntimeId,
404 },
405 Recover {
406 runtime_id: LogicalRuntimeId,
407 },
408 Destroy {
409 runtime_id: LogicalRuntimeId,
410 },
411 RuntimeState {
412 runtime_id: LogicalRuntimeId,
413 },
414 ResolvedSessionLlmCapabilities {
415 session_id: SessionId,
416 },
417 ConfigureModelRoutingBaseline {
418 session_id: SessionId,
419 baseline_model: ModelId,
420 realtime_capable: bool,
421 },
422 SessionModelRoutingStatus {
423 session_id: SessionId,
424 },
425 RequestSwitchTurn {
426 session_id: SessionId,
427 request: Box<SwitchTurnRequest>,
428 },
429 AdmitModelRoutingAssistantTurn {
430 session_id: SessionId,
431 },
432 BeginImageOperation {
433 session_id: SessionId,
434 request: Box<ImageOperationRoutingRequest>,
435 },
436 DenyImageOperationPlan {
437 session_id: SessionId,
438 operation_id: ImageOperationId,
439 reason: ImageOperationDenialReason,
440 },
441 ActivateImageOperationOverride {
442 session_id: SessionId,
443 operation_id: ImageOperationId,
444 },
445 ClassifyImageOperationTerminal {
446 session_id: SessionId,
447 operation_id: ImageOperationId,
448 observation: ImageProviderTerminalObservation,
449 provider_text: ProviderTextDisposition,
450 },
451 CompleteImageOperation {
452 session_id: SessionId,
453 operation_id: ImageOperationId,
454 terminal: ImageOperationTerminalClass,
455 },
456 RestoreImageOperationOverride {
457 session_id: SessionId,
458 operation_id: ImageOperationId,
459 },
460 LoadBoundaryReceipt {
461 runtime_id: LogicalRuntimeId,
462 run_id: LifecycleRunId,
463 sequence: u64,
464 },
465 AcceptWithCompletion {
466 session_id: SessionId,
467 input: Input,
468 register_completion: bool,
469 },
470 AcceptWithoutWake {
471 session_id: SessionId,
472 input: Input,
473 },
474}
475
476#[derive(Debug, Clone)]
477pub(crate) struct MeerkatMachineRunFailure {
478 pub source: Option<dsl::RunFailureSourceKind>,
479 pub machine_terminal_failure_observed: bool,
480 pub error: String,
481}
482
483impl MeerkatMachineRunFailure {
484 pub(crate) fn from_machine_terminal_failure(error: impl Into<String>) -> Self {
485 Self {
486 source: None,
487 machine_terminal_failure_observed: true,
488 error: error.into(),
489 }
490 }
491}
492
493#[derive(Debug)]
494#[allow(clippy::large_enum_variant)]
495pub(crate) enum MeerkatMachineCommandResult {
496 AcceptOutcome(AcceptOutcome),
497 AcceptWithCompletion {
498 outcome: AcceptOutcome,
499 handle: Option<crate::completion::CompletionHandle>,
500 #[cfg_attr(not(test), allow(dead_code))]
501 admission_signal: crate::driver::ephemeral::PostAdmissionSignal,
502 },
503 Unit,
504 Bool(bool),
505 Spawned(bool),
506 OpsLifecycleRegistry(Option<Arc<crate::ops_lifecycle::RuntimeOpsLifecycleRegistry>>),
507 Bindings(meerkat_core::SessionRuntimeBindings),
508 InputState(Option<StoredInputState>),
509 InteractionTerminalStatus(
510 Option<crate::terminal_status::Sourced<crate::terminal_status::InteractionTerminalReport>>,
511 ),
512 RunTerminalStatus(crate::terminal_status::Sourced<crate::terminal_status::RunTerminalReport>),
513 ActiveInputs(Vec<InputId>),
514 LlmReconfigured(SessionLlmReconfigureReport),
515 VisibilityRevision(meerkat_core::ToolScopeRevision),
516 VisibilityPublished(meerkat_core::SessionToolVisibilityState),
517 RetireReport(RetireReport),
518 RecycleReport(RecycleReport),
519 ResetReport(ResetReport),
520 RecoveryReport(RecoveryReport),
521 DestroyReport(DestroyReport),
522 RuntimeState(RuntimeState),
523 ResolvedSessionLlmCapabilities(Option<SessionLlmCapabilitySurface>),
524 SessionModelRoutingStatus(SessionModelRoutingStatus),
525 SwitchTurnControlResult(SwitchTurnControlResult),
526 ImageOperationRoutingResult(ImageOperationRoutingResult),
527 ImageOperationPhase(ImageOperationPhase),
528 ImageOperationTerminalClass(ImageOperationTerminalClass),
529 BoundaryReceipt(Option<RunBoundaryReceipt>),
530}
531
532#[doc(hidden)]
533#[must_use]
534pub fn canonical_meerkat_machine_command_manifest() -> IndexSet<&'static str> {
535 canonical_meerkat_machine_command_input_variant_manifest()
536 .into_iter()
537 .map(|variant| variant.as_str())
538 .collect()
539}
540
541#[doc(hidden)]
542#[must_use]
543pub fn canonical_meerkat_machine_command_input_variant_manifest()
544-> IndexSet<MeerkatMachineInputVariant> {
545 canonical_meerkat_machine_command_classifications()
546 .into_iter()
547 .flat_map(|record| record.classification.catalog_input_variants())
548 .collect()
549}
550
551#[doc(hidden)]
552#[must_use]
553pub fn canonical_meerkat_machine_runtime_internal_manifest() -> IndexSet<&'static str> {
554 canonical_meerkat_machine_runtime_internal_input_variant_manifest()
555 .into_iter()
556 .map(|variant| variant.as_str())
557 .collect()
558}
559
560#[doc(hidden)]
561#[must_use]
562pub fn canonical_meerkat_machine_runtime_internal_input_variant_manifest()
563-> IndexSet<MeerkatMachineInputVariant> {
564 canonical_meerkat_machine_runtime_internal_classifications()
565 .into_iter()
566 .map(|record| record.input.input_variant())
567 .collect()
568}
569
570#[doc(hidden)]
571#[must_use]
572pub fn canonical_meerkat_machine_runtime_internal_fieldless_input_variant_manifest()
573-> IndexSet<MeerkatMachineInputVariant> {
574 MeerkatMachineFieldlessRuntimeInternalInput::ALL
575 .iter()
576 .copied()
577 .map(MeerkatMachineFieldlessRuntimeInternalInput::input_variant)
578 .collect()
579}
580
581macro_rules! meerkat_machine_runtime_internal_inputs {
582 ($($reason:ident => [$($variant:ident),+ $(,)?]),+ $(,)?) => {
583 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
584 pub enum MeerkatMachineRuntimeInternalInput {
585 $($($variant),+),+
586 }
587
588 impl MeerkatMachineRuntimeInternalInput {
589 pub const ALL: &'static [Self] = &[
590 $($(Self::$variant),+),+
591 ];
592
593 pub const CLASSIFICATIONS: &'static [MeerkatMachineRuntimeInternalClassificationRecord] = &[
594 $($(
595 MeerkatMachineRuntimeInternalClassificationRecord {
596 input: Self::$variant,
597 reason: MeerkatMachineRuntimeInternalReason::$reason,
598 },
599 )+)+
600 ];
601
602 #[must_use]
603 pub const fn input_variant(self) -> MeerkatMachineInputVariant {
604 match self {
605 $($(Self::$variant => MeerkatMachineInputVariant::$variant,)+)+
606 }
607 }
608
609 #[must_use]
610 pub const fn reason(self) -> MeerkatMachineRuntimeInternalReason {
611 match self {
612 $(
613 $(Self::$variant)|+ => MeerkatMachineRuntimeInternalReason::$reason,
614 )+
615 }
616 }
617 }
618 };
619}
620
621#[derive(Debug, Clone, Copy, PartialEq, Eq)]
622pub enum MeerkatMachineRuntimeInternalReason {
623 InputQueueLifecycle,
624 OperationLifecycle,
625 RunExecutionLifecycle,
626 CancellationLifecycle,
627 LiveTopologyReconfiguration,
628 InteractionStreamLifecycle,
629 EventStreamLifecycle,
630 CommsIngressLifecycle,
631 SupervisorTrustLifecycle,
632 MobOperatorAuthorityLifecycle,
633 PeerRequestLifecycle,
634 VisibilityAuthorityLifecycle,
635 DeferredSessionLifecycle,
636 ExtractionLifecycle,
637 McpServerLifecycle,
638 ModelRoutingLifecycle,
639 ExternalSurfaceLifecycle,
640 FailureRecoveryLifecycle,
641 UserInterruptDispatch,
642 SessionUnregisterDrainLifecycle,
643}
644
645#[derive(Debug, Clone, Copy, PartialEq, Eq)]
646pub struct MeerkatMachineRuntimeInternalClassificationRecord {
647 pub input: MeerkatMachineRuntimeInternalInput,
648 pub reason: MeerkatMachineRuntimeInternalReason,
649}
650
651meerkat_machine_runtime_internal_inputs!(
652 InputQueueLifecycle => [
653 AbandonInput,
654 AdvanceSessionContext,
655 BudgetExhausted,
656 ChangeLane,
657 CoalesceInput,
658 ConsumeInput,
659 ConsumeOnAccept,
660 MarkApplied,
661 MarkAppliedPendingConsumption,
662 DeferInputBehindBacklog,
663 PrioritizeInput,
664 QueueAccepted,
665 RecoverAdmittedInput,
666 RecoverInputLifecycle,
667 ResolveAdmissionIdempotency,
668 ResolveAdmissionPlan,
669 ResolveAdmissionValidation,
670 ResolveInputPublicLifecycle,
671 ResolveInputPublicTerminalOutcome,
672 ResolveTranscriptEditAdmission,
673 RegisterAcceptedIdempotency,
674 ResolveStagedRollback,
675 RetryRequested,
676 RollbackStaged,
677 StageForRun,
678 StartConversationRun,
679 StartImmediateAppend,
680 StartImmediateContext,
681 SteerAccepted,
682 SupersedeInput,
683 AuthorizeStoredInputStateSeed,
684 ClassifyInputTerminality,
685 ClassifyRecoveredInputDurability,
686 ClassifyRuntimeLoopQueueAdmission,
687 NormalizeRecoveredInputLifecycle,
688 ],
689 OperationLifecycle => [
690 AbortOp,
691 CancelOp,
692 CancelWaitAll,
693 ClassifyOperationCompletionFeed,
694 ClassifyOperationCompletionWake,
695 ClassifyOperationDurability,
696 ClassifyOperationPublicResult,
697 ClassifyOperationTerminality,
698 ClassifyOperationTransitionIdempotence,
699 ClassifyRecoveredOperationRecord,
700 CollectCompletedOp,
701 CompleteOp,
702 EvictCompletedOp,
703 FailOp,
704 IncrementAttemptCount,
705 OpsBarrierSatisfied,
706 PeerReadyOp,
707 ProgressReportedOp,
708 RecoverCompletionFeedEntry,
709 RegisterOp,
710 RegisterPendingOps,
711 RecoverCompletionConsumerCursors,
712 RecoverOpRecord,
713 RecoverOpsCompletionCursor,
714 ResolveOpLifecycleTransitionRejection,
715 ResolveRuntimeOpsLifecycleDurability,
716 ResolveWaitAllAdmission,
717 RequestWaitAll,
718 RetireCompletedOp,
719 RetireRequestedOp,
720 SatisfyWaitAll,
721 StartOp,
722 TerminateOp,
723 ],
724 RunExecutionLifecycle => [
725 AcknowledgeTerminal,
726 AdvanceAgentCompletionCursor,
727 AdvanceRuntimeInjectedCompletionCursor,
728 AdvanceRuntimeObservedCompletionCursor,
729 BoundaryComplete,
730 BoundaryContinue,
731 ClassifyAssistantOutput,
732 ClassifyCallTimeout,
733 ClassifyTurnTerminalCauseClass,
734 ClassifyTurnTerminality,
735 ClearSessionLlmState,
736 Commit,
737 Fail,
738 HydrateSessionLlmState,
739 LlmReturnedTerminal,
740 LlmReturnedToolCalls,
741 Prepare,
742 PrimitiveApplied,
743 RecordBoundarySeq,
744 ResolveLiveBoundaryContextReceipt,
745 ResolveRuntimeCompletionCleanup,
746 ResolveRuntimeCompletionResult,
747 ResolveRuntimeCompletionWaitFailure,
748 ResolveTurnSurfaceResult,
749 RollbackRun,
750 RunCompleted,
751 RunFailed,
752 RuntimeExecutorExited,
753 TimeBudgetExceeded,
754 ToolCallsResolved,
755 TurnLimitReached,
756 ],
757 CancellationLifecycle => [
758 CancelNow,
759 CancelRun,
760 CancellationObserved,
761 ForceCancelNoRun,
762 RequestCancelAfterBoundary,
763 RunCancelled,
764 ],
765 LiveTopologyReconfiguration => [
766 AbandonLiveOpenAdmission,
767 CompleteUntilChangedSwitchTurnReconfigure,
768 RecordLiveChannelRequestRejected,
769 RecordLiveChannelStatus,
770 RecordLiveCloseClosed,
771 RecordLiveCommandAccepted,
772 RecordLiveCommandRejected,
773 RecordLiveRefreshQueued,
774 ResolveLiveOpenAdmission,
775 ],
776 InteractionStreamLifecycle => [
777 InteractionStreamAttached,
778 InteractionStreamClosedEarly,
779 InteractionStreamCompleted,
780 InteractionStreamExpired,
781 InteractionStreamReserved,
782 ],
783 EventStreamLifecycle => [
784 RecordMobEventStreamOpened,
785 RecordMobEventStreamTerminated,
786 RecordSessionEventStreamOpened,
787 RecordSessionEventStreamTerminated,
788 ResolveMobEventStreamClose,
789 ResolveSessionEventStreamClose,
790 ],
791 CommsIngressLifecycle => [
792 AddDirectPeerEndpoint,
793 ApplyMobPeerOverlay,
794 AttachMobIngress,
795 AttachSessionIngress,
796 AuthorizeSupervisorMobPeerOverlay,
797 BindSupervisor,
798 ClearLocalEndpoint,
799 DetachIngress,
800 PeerResponseRejected,
801 PublishLocalEndpoint,
802 RemoveDirectPeerEndpoint,
803 ResolvePeerIngressDequeue,
804 ResolvePeerIngressReceive,
805 ResolveSupervisorAuthorizeAdmission,
806 ResolveSupervisorBindAdmission,
807 ResolveSupervisorBindMaterialAdmission,
808 ResolveSupervisorBridgeCommandAdmission,
809 SpawnDrain,
810 StopDrain,
811 ],
812 SupervisorTrustLifecycle => [
813 AuthorizeSupervisor,
814 PrepareTerminalSupervisorCleanupBindings,
815 RecoverRevokedSupervisorReceipt,
816 RecoverSupervisorBinding,
817 RecoverSupervisorRevocationPending,
818 RecoverSupervisorRotationOperation,
819 RecoverSupervisorRotationTerminalReceipt,
820 RefreshSupervisorBindingRoute,
821 RequestSupervisorTrustPublish,
822 ResolveSupervisorCleanupCommandAdmission,
823 ResumeSupervisorRotation,
824 RevokeSupervisor,
825 SubmitSupervisorRotation,
826 SupervisorRotationNextPublished,
827 SupervisorRotationPreviousRevoked,
828 SupervisorTrustEdgePublishFailed,
829 SupervisorTrustEdgePublished,
830 SupervisorTrustEdgeRevokeFailed,
831 SupervisorTrustEdgeRevoked,
832 ObserveSupervisorRotation,
833 ],
834 MobOperatorAuthorityLifecycle => [
835 GrantMobOperatorManageMob,
836 ResolveMobOperatorCreateAuthority,
837 RestoreMobOperatorAuthority,
838 SetMobOperatorCreateAuthority,
839 SetMobOperatorProfileMutation,
840 SetMobOperatorSpawnProfilesInMob,
841 ],
842 PeerRequestLifecycle => [
843 PeerRequestReceived,
844 PeerRequestSendFailed,
845 PeerRequestSent,
846 PeerRequestTimedOut,
847 PeerResponseProgressArrived,
848 PeerResponseReplied,
849 PeerResponseTerminalArrived,
850 ],
851 VisibilityAuthorityLifecycle => [
852 CommitDeferredNames,
853 CommitVisibilityFilter,
854 ClearTurnToolOverlay,
855 ReplaceDeferredToolAuthorityCatalog,
856 ReplaceFilterToolAuthorityCatalog,
857 SetTurnToolOverlay,
858 StageDeferredNames,
859 StageVisibilityFilter,
860 SurfaceSetRemovalTimeout,
861 ReplaceVisibilityState,
862 ],
863 DeferredSessionLifecycle => [
864 AbandonDeferredSessionPromotion,
865 AuthorizeDeferredSessionMachineArchivedResume,
866 AuthorizeDeferredSessionSystemContextAppend,
867 BeginDeferredSessionArchive,
868 BeginDeferredSessionPromotion,
869 DropDeferredSession,
870 FinishDeferredSessionArchive,
871 FinishDeferredSessionPromotion,
872 RestoreDeferredSessionArchive,
873 StageDeferredSession,
874 UpdateDeferredSessionKeepAlive,
875 UpdateDeferredSessionLlmIdentity,
876 ],
877 ExtractionLifecycle => [
878 EnterExtraction,
879 ExtractionFailed,
880 ExtractionStart,
881 ExtractionValidationFailed,
882 ExtractionValidationPassed,
883 ],
884 McpServerLifecycle => [
885 McpServerConnectPending,
886 McpServerConnected,
887 McpServerDisconnected,
888 McpServerFailed,
889 McpServerReload,
890 ],
891 ModelRoutingLifecycle => [
892 ModelRoutingStatus,
893 RequestFiniteSwitchTurn,
894 RequestUntilChangedSwitchTurn,
895 SetModelRoutingBaseline,
896 ],
897 ExternalSurfaceLifecycle => [
898 AdmitSurfaceRequest,
899 CancelSurfaceRequest,
900 ClassifySurfaceRequestTerminal,
901 FinishSurfaceRequestUnpublished,
902 PublishOrCancelSurfaceRequest,
903 PublishSurfaceRequest,
904 RecordLiveWebrtcAnswerAccepted,
905 RecordLiveWebrtcTokenIssued,
906 RecordLiveWebsocketTokenIssued,
907 ResolveLiveWebrtcAnswerAdmission,
908 ResolveLiveWebsocketTokenAdmission,
909 SurfaceApplyBoundary,
910 SurfaceCallFinished,
911 SurfaceCallStarted,
912 SurfaceFinalizeRemovalClean,
913 SurfaceFinalizeRemovalForced,
914 SurfaceMarkPendingFailed,
915 SurfaceMarkPendingSucceeded,
916 SurfaceRegister,
917 SurfaceShutdown,
918 SurfaceSnapshotAligned,
919 SurfaceStageAdd,
920 SurfaceStageReload,
921 SurfaceStageRemove,
922 ],
923 FailureRecoveryLifecycle => [
924 ClassifyLlmFailureRecovery,
925 ClassifyRuntimeLifecycleDurability,
926 ClassifyRuntimeLifecycleState,
927 FatalFailure,
928 RecoverableFailure,
929 RecoverRuntimeAuthority,
930 ResolveVisibleRuntimePhase,
931 ],
932 UserInterruptDispatch => [
933 InterruptCurrentRun,
934 ResolveUserInterruptPublicResult,
935 ],
936 SessionUnregisterDrainLifecycle => [
937 BeginUnregisterSession,
938 CommsDrainExitedForUnregister,
939 CompletionWaitersResolvedForUnregister,
940 RuntimeLoopStoppedForUnregister,
941 ],
942);
943
944macro_rules! meerkat_machine_fieldless_runtime_internal_inputs {
945 ($($authority:ident => [$($variant:ident),+ $(,)?]),+ $(,)?) => {
946 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
947 pub enum MeerkatMachineFieldlessRuntimeInternalInput {
948 $($($variant),+),+
949 }
950
951 impl MeerkatMachineFieldlessRuntimeInternalInput {
952 pub const ALL: &'static [Self] = &[
953 $($(Self::$variant),+),+
954 ];
955
956 #[must_use]
957 pub const fn runtime_internal_input(self) -> MeerkatMachineRuntimeInternalInput {
958 match self {
959 $($(Self::$variant => MeerkatMachineRuntimeInternalInput::$variant,)+)+
960 }
961 }
962
963 #[must_use]
964 pub const fn input_variant(self) -> MeerkatMachineInputVariant {
965 self.runtime_internal_input().input_variant()
966 }
967
968 #[must_use]
969 pub const fn authority(self) -> MeerkatMachineFieldlessRuntimeInternalAuthority {
970 match self {
971 $(
972 $(Self::$variant)|+ => MeerkatMachineFieldlessRuntimeInternalAuthority::$authority,
973 )+
974 }
975 }
976
977 #[must_use]
978 pub const fn requires_typed_runtime_internal_stager(self) -> bool {
979 matches!(
980 self.authority(),
981 MeerkatMachineFieldlessRuntimeInternalAuthority::UserInterruptDispatch
982 )
983 }
984
985 pub(crate) const fn dsl_input_variant(self) -> dsl::MeerkatMachineInputVariant {
986 match self {
987 $($(Self::$variant => dsl::MeerkatMachineInputVariant::$variant,)+)+
988 }
989 }
990
991 pub(crate) fn dsl_input(self) -> dsl::MeerkatMachineInput {
992 match self {
993 $($(Self::$variant => dsl::MeerkatMachineInput::$variant,)+)+
994 }
995 }
996
997 pub(crate) fn from_dsl_input_variant(
998 variant: dsl::MeerkatMachineInputVariant,
999 ) -> Option<Self> {
1000 Self::ALL
1001 .iter()
1002 .copied()
1003 .find(|input| input.dsl_input_variant() == variant)
1004 }
1005
1006 pub(crate) fn reject_raw_dsl_input(
1007 input: &dsl::MeerkatMachineInput,
1008 ) -> Result<(), String> {
1009 if let Some(fieldless) = Self::from_dsl_input_variant(input.variant())
1010 && fieldless.requires_typed_runtime_internal_stager()
1011 {
1012 let variant = fieldless.input_variant();
1013 return Err(format!(
1014 "fieldless runtime-internal input {variant:?} must use typed runtime-internal staging authority"
1015 ));
1016 }
1017 Ok(())
1018 }
1019 }
1020 };
1021}
1022
1023meerkat_machine_fieldless_runtime_internal_inputs!(
1024 RuntimeOwner => [
1025 RuntimeExecutorExited,
1026 ForceCancelNoRun,
1027 CancelWaitAll,
1028 StopDrain,
1029 SurfaceShutdown,
1030 DetachIngress,
1031 ClearLocalEndpoint,
1032 ],
1033 UserInterruptDispatch => [
1034 InterruptCurrentRun,
1035 ],
1036);
1037
1038#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1039pub enum MeerkatMachineFieldlessRuntimeInternalAuthority {
1040 RuntimeOwner,
1041 UserInterruptDispatch,
1042}
1043
1044#[doc(hidden)]
1045#[must_use]
1046pub fn canonical_meerkat_machine_runtime_internal_classifications()
1047-> Vec<MeerkatMachineRuntimeInternalClassificationRecord> {
1048 MeerkatMachineRuntimeInternalInput::CLASSIFICATIONS.to_vec()
1049}
1050
1051#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1052pub enum MeerkatMachineCommandClassification {
1053 CatalogInput(MeerkatMachineCatalogInput),
1054 CatalogInputs(&'static [MeerkatMachineCatalogInput]),
1055 ShellMechanic(MeerkatMachineShellMechanicReason),
1056}
1057
1058impl MeerkatMachineCommandClassification {
1059 #[must_use]
1060 pub fn catalog_inputs(self) -> Vec<MeerkatMachineCatalogInput> {
1061 match self {
1062 Self::CatalogInput(input) => vec![input],
1063 Self::CatalogInputs(inputs) => inputs.to_vec(),
1064 Self::ShellMechanic(_) => Vec::new(),
1065 }
1066 }
1067
1068 #[must_use]
1069 pub fn catalog_input_variants(self) -> Vec<MeerkatMachineInputVariant> {
1070 self.catalog_inputs()
1071 .into_iter()
1072 .map(MeerkatMachineCatalogInput::input_variant)
1073 .collect()
1074 }
1075}
1076
1077#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1078pub enum MeerkatMachineCatalogInput {
1079 RegisterSession,
1080 UnregisterSession,
1081 EnsureSessionWithExecutor,
1082 SetSilentIntents,
1083 CancelAfterBoundary,
1084 StopRuntimeExecutor,
1085 ServiceTurnCommitted,
1086 ContainsSession,
1087 SessionHasExecutor,
1088 SessionHasComms,
1089 OpsLifecycleRegistry,
1090 PrepareBindings,
1091 InputState,
1092 ListActiveInputs,
1093 ReconfigureSessionLlmIdentity,
1094 StagePersistentFilter,
1095 RequestDeferredTools,
1096 PublishCommittedVisibleSet,
1097 SetPeerIngressContext,
1098 NotifyDrainExited,
1099 AbortAll,
1100 Abort,
1101 Wait,
1102 Ingest,
1103 PublishEvent,
1104 Retire,
1105 Recycle,
1106 Reset,
1107 Recover,
1108 Destroy,
1109 RuntimeState,
1110 ModelRoutingStatus,
1111 SetModelRoutingBaseline,
1112 RequestFiniteSwitchTurn,
1113 RequestUntilChangedSwitchTurn,
1114 AdmitModelRoutingAssistantTurn,
1115 BeginImageOperation,
1116 DenyImageOperationPlan,
1117 ActivateImageOperationOverride,
1118 ClassifyImageOperationTerminal,
1119 CompleteImageOperation,
1120 RestoreImageOperationOverride,
1121 LoadBoundaryReceipt,
1122 AcceptWithCompletion,
1123 AcceptWithoutWake,
1124}
1125
1126impl MeerkatMachineCatalogInput {
1127 pub const ALL: &'static [Self] = &[
1128 Self::RegisterSession,
1129 Self::UnregisterSession,
1130 Self::EnsureSessionWithExecutor,
1131 Self::SetSilentIntents,
1132 Self::CancelAfterBoundary,
1133 Self::StopRuntimeExecutor,
1134 Self::ServiceTurnCommitted,
1135 Self::ContainsSession,
1136 Self::SessionHasExecutor,
1137 Self::SessionHasComms,
1138 Self::OpsLifecycleRegistry,
1139 Self::PrepareBindings,
1140 Self::InputState,
1141 Self::ListActiveInputs,
1142 Self::ReconfigureSessionLlmIdentity,
1143 Self::StagePersistentFilter,
1144 Self::RequestDeferredTools,
1145 Self::PublishCommittedVisibleSet,
1146 Self::SetPeerIngressContext,
1147 Self::NotifyDrainExited,
1148 Self::AbortAll,
1149 Self::Abort,
1150 Self::Wait,
1151 Self::Ingest,
1152 Self::PublishEvent,
1153 Self::Retire,
1154 Self::Recycle,
1155 Self::Reset,
1156 Self::Recover,
1157 Self::Destroy,
1158 Self::RuntimeState,
1159 Self::ModelRoutingStatus,
1160 Self::SetModelRoutingBaseline,
1161 Self::RequestFiniteSwitchTurn,
1162 Self::RequestUntilChangedSwitchTurn,
1163 Self::AdmitModelRoutingAssistantTurn,
1164 Self::BeginImageOperation,
1165 Self::DenyImageOperationPlan,
1166 Self::ActivateImageOperationOverride,
1167 Self::ClassifyImageOperationTerminal,
1168 Self::CompleteImageOperation,
1169 Self::RestoreImageOperationOverride,
1170 Self::LoadBoundaryReceipt,
1171 Self::AcceptWithCompletion,
1172 Self::AcceptWithoutWake,
1173 ];
1174
1175 #[must_use]
1176 pub const fn input_variant(self) -> MeerkatMachineInputVariant {
1177 match self {
1178 Self::RegisterSession => MeerkatMachineInputVariant::RegisterSession,
1179 Self::UnregisterSession => MeerkatMachineInputVariant::UnregisterSession,
1180 Self::EnsureSessionWithExecutor => {
1181 MeerkatMachineInputVariant::EnsureSessionWithExecutor
1182 }
1183 Self::SetSilentIntents => MeerkatMachineInputVariant::SetSilentIntents,
1184 Self::CancelAfterBoundary => MeerkatMachineInputVariant::CancelAfterBoundary,
1185 Self::StopRuntimeExecutor => MeerkatMachineInputVariant::StopRuntimeExecutor,
1186 Self::ServiceTurnCommitted => MeerkatMachineInputVariant::ServiceTurnCommitted,
1187 Self::ContainsSession => MeerkatMachineInputVariant::ContainsSession,
1188 Self::SessionHasExecutor => MeerkatMachineInputVariant::SessionHasExecutor,
1189 Self::SessionHasComms => MeerkatMachineInputVariant::SessionHasComms,
1190 Self::OpsLifecycleRegistry => MeerkatMachineInputVariant::OpsLifecycleRegistry,
1191 Self::PrepareBindings => MeerkatMachineInputVariant::PrepareBindings,
1192 Self::InputState => MeerkatMachineInputVariant::InputState,
1193 Self::ListActiveInputs => MeerkatMachineInputVariant::ListActiveInputs,
1194 Self::ReconfigureSessionLlmIdentity => {
1195 MeerkatMachineInputVariant::ReconfigureSessionLlmIdentity
1196 }
1197 Self::StagePersistentFilter => MeerkatMachineInputVariant::StagePersistentFilter,
1198 Self::RequestDeferredTools => MeerkatMachineInputVariant::RequestDeferredTools,
1199 Self::PublishCommittedVisibleSet => {
1200 MeerkatMachineInputVariant::PublishCommittedVisibleSet
1201 }
1202 Self::SetPeerIngressContext => MeerkatMachineInputVariant::SetPeerIngressContext,
1203 Self::NotifyDrainExited => MeerkatMachineInputVariant::NotifyDrainExited,
1204 Self::AbortAll => MeerkatMachineInputVariant::AbortAll,
1205 Self::Abort => MeerkatMachineInputVariant::Abort,
1206 Self::Wait => MeerkatMachineInputVariant::Wait,
1207 Self::Ingest => MeerkatMachineInputVariant::Ingest,
1208 Self::PublishEvent => MeerkatMachineInputVariant::PublishEvent,
1209 Self::Retire => MeerkatMachineInputVariant::Retire,
1210 Self::Recycle => MeerkatMachineInputVariant::Recycle,
1211 Self::Reset => MeerkatMachineInputVariant::Reset,
1212 Self::Recover => MeerkatMachineInputVariant::Recover,
1213 Self::Destroy => MeerkatMachineInputVariant::Destroy,
1214 Self::RuntimeState => MeerkatMachineInputVariant::RuntimeState,
1215 Self::ModelRoutingStatus => MeerkatMachineInputVariant::ModelRoutingStatus,
1216 Self::SetModelRoutingBaseline => MeerkatMachineInputVariant::SetModelRoutingBaseline,
1217 Self::RequestFiniteSwitchTurn => MeerkatMachineInputVariant::RequestFiniteSwitchTurn,
1218 Self::RequestUntilChangedSwitchTurn => {
1219 MeerkatMachineInputVariant::RequestUntilChangedSwitchTurn
1220 }
1221 Self::AdmitModelRoutingAssistantTurn => {
1222 MeerkatMachineInputVariant::AdmitModelRoutingAssistantTurn
1223 }
1224 Self::BeginImageOperation => MeerkatMachineInputVariant::BeginImageOperation,
1225 Self::DenyImageOperationPlan => MeerkatMachineInputVariant::DenyImageOperationPlan,
1226 Self::ActivateImageOperationOverride => {
1227 MeerkatMachineInputVariant::ActivateImageOperationOverride
1228 }
1229 Self::ClassifyImageOperationTerminal => {
1230 MeerkatMachineInputVariant::ClassifyImageOperationTerminal
1231 }
1232 Self::CompleteImageOperation => MeerkatMachineInputVariant::CompleteImageOperation,
1233 Self::RestoreImageOperationOverride => {
1234 MeerkatMachineInputVariant::RestoreImageOperationOverride
1235 }
1236 Self::LoadBoundaryReceipt => MeerkatMachineInputVariant::LoadBoundaryReceipt,
1237 Self::AcceptWithCompletion => MeerkatMachineInputVariant::AcceptWithCompletion,
1238 Self::AcceptWithoutWake => MeerkatMachineInputVariant::AcceptWithoutWake,
1239 }
1240 }
1241
1242 #[must_use]
1243 pub const fn as_str(self) -> &'static str {
1244 match self {
1245 Self::RegisterSession => "RegisterSession",
1246 Self::UnregisterSession => "UnregisterSession",
1247 Self::EnsureSessionWithExecutor => "EnsureSessionWithExecutor",
1248 Self::SetSilentIntents => "SetSilentIntents",
1249 Self::CancelAfterBoundary => "CancelAfterBoundary",
1250 Self::StopRuntimeExecutor => "StopRuntimeExecutor",
1251 Self::ServiceTurnCommitted => "ServiceTurnCommitted",
1252 Self::ContainsSession => "ContainsSession",
1253 Self::SessionHasExecutor => "SessionHasExecutor",
1254 Self::SessionHasComms => "SessionHasComms",
1255 Self::OpsLifecycleRegistry => "OpsLifecycleRegistry",
1256 Self::PrepareBindings => "PrepareBindings",
1257 Self::InputState => "InputState",
1258 Self::ListActiveInputs => "ListActiveInputs",
1259 Self::ReconfigureSessionLlmIdentity => "ReconfigureSessionLlmIdentity",
1260 Self::StagePersistentFilter => "StagePersistentFilter",
1261 Self::RequestDeferredTools => "RequestDeferredTools",
1262 Self::PublishCommittedVisibleSet => "PublishCommittedVisibleSet",
1263 Self::SetPeerIngressContext => "SetPeerIngressContext",
1264 Self::NotifyDrainExited => "NotifyDrainExited",
1265 Self::AbortAll => "AbortAll",
1266 Self::Abort => "Abort",
1267 Self::Wait => "Wait",
1268 Self::Ingest => "Ingest",
1269 Self::PublishEvent => "PublishEvent",
1270 Self::Retire => "Retire",
1271 Self::Recycle => "Recycle",
1272 Self::Reset => "Reset",
1273 Self::Recover => "Recover",
1274 Self::Destroy => "Destroy",
1275 Self::RuntimeState => "RuntimeState",
1276 Self::ModelRoutingStatus => "ModelRoutingStatus",
1277 Self::SetModelRoutingBaseline => "SetModelRoutingBaseline",
1278 Self::RequestFiniteSwitchTurn => "RequestFiniteSwitchTurn",
1279 Self::RequestUntilChangedSwitchTurn => "RequestUntilChangedSwitchTurn",
1280 Self::AdmitModelRoutingAssistantTurn => "AdmitModelRoutingAssistantTurn",
1281 Self::BeginImageOperation => "BeginImageOperation",
1282 Self::DenyImageOperationPlan => "DenyImageOperationPlan",
1283 Self::ActivateImageOperationOverride => "ActivateImageOperationOverride",
1284 Self::ClassifyImageOperationTerminal => "ClassifyImageOperationTerminal",
1285 Self::CompleteImageOperation => "CompleteImageOperation",
1286 Self::RestoreImageOperationOverride => "RestoreImageOperationOverride",
1287 Self::LoadBoundaryReceipt => "LoadBoundaryReceipt",
1288 Self::AcceptWithCompletion => "AcceptWithCompletion",
1289 Self::AcceptWithoutWake => "AcceptWithoutWake",
1290 }
1291 }
1292}
1293
1294impl MeerkatMachineCommandVariant {
1295 #[must_use]
1296 pub const fn catalog_input(self) -> Option<MeerkatMachineCatalogInput> {
1297 match self {
1298 Self::ConfigureModelRoutingBaseline
1299 | Self::RequestSwitchTurn
1300 | Self::ResolvedSessionLlmCapabilities
1301 | Self::SessionModelRoutingStatus
1302 | Self::PrepareLocalSessionBindings => None,
1303 Self::RegisterSession => Some(MeerkatMachineCatalogInput::RegisterSession),
1304 Self::UnregisterSession => Some(MeerkatMachineCatalogInput::UnregisterSession),
1305 Self::EnsureSessionWithExecutor => {
1306 Some(MeerkatMachineCatalogInput::EnsureSessionWithExecutor)
1307 }
1308 Self::SetSilentIntents => Some(MeerkatMachineCatalogInput::SetSilentIntents),
1309 Self::CancelAfterBoundary => Some(MeerkatMachineCatalogInput::CancelAfterBoundary),
1310 Self::StopRuntimeExecutor => Some(MeerkatMachineCatalogInput::StopRuntimeExecutor),
1311 Self::CommitServiceTurnTerminalReceipt => {
1312 Some(MeerkatMachineCatalogInput::ServiceTurnCommitted)
1313 }
1314 Self::ContainsSession => Some(MeerkatMachineCatalogInput::ContainsSession),
1315 Self::SessionHasExecutor => Some(MeerkatMachineCatalogInput::SessionHasExecutor),
1316 Self::SessionHasComms => Some(MeerkatMachineCatalogInput::SessionHasComms),
1317 Self::OpsLifecycleRegistry => Some(MeerkatMachineCatalogInput::OpsLifecycleRegistry),
1318 Self::PrepareBindings => Some(MeerkatMachineCatalogInput::PrepareBindings),
1319 Self::InputState => Some(MeerkatMachineCatalogInput::InputState),
1320 Self::InputStateByIdempotencyKey => Some(MeerkatMachineCatalogInput::InputState),
1323 Self::InteractionTerminalStatus => Some(MeerkatMachineCatalogInput::InputState),
1327 Self::RunTerminalStatus => Some(MeerkatMachineCatalogInput::InputState),
1328 Self::ListActiveInputs => Some(MeerkatMachineCatalogInput::ListActiveInputs),
1329 Self::ReconfigureSessionLlmIdentity => {
1330 Some(MeerkatMachineCatalogInput::ReconfigureSessionLlmIdentity)
1331 }
1332 Self::StagePersistentFilter => Some(MeerkatMachineCatalogInput::StagePersistentFilter),
1333 Self::RequestDeferredTools => Some(MeerkatMachineCatalogInput::RequestDeferredTools),
1334 Self::PublishCommittedVisibleSet => {
1335 Some(MeerkatMachineCatalogInput::PublishCommittedVisibleSet)
1336 }
1337 Self::SetPeerIngressContext => Some(MeerkatMachineCatalogInput::SetPeerIngressContext),
1338 Self::NotifyDrainExited => Some(MeerkatMachineCatalogInput::NotifyDrainExited),
1339 Self::AbortAll => Some(MeerkatMachineCatalogInput::AbortAll),
1340 Self::Abort => Some(MeerkatMachineCatalogInput::Abort),
1341 Self::Wait => Some(MeerkatMachineCatalogInput::Wait),
1342 Self::Ingest => Some(MeerkatMachineCatalogInput::Ingest),
1343 Self::PublishEvent => Some(MeerkatMachineCatalogInput::PublishEvent),
1344 Self::Retire => Some(MeerkatMachineCatalogInput::Retire),
1345 Self::Recycle => Some(MeerkatMachineCatalogInput::Recycle),
1346 Self::Reset => Some(MeerkatMachineCatalogInput::Reset),
1347 Self::Recover => Some(MeerkatMachineCatalogInput::Recover),
1348 Self::Destroy => Some(MeerkatMachineCatalogInput::Destroy),
1349 Self::RuntimeState => Some(MeerkatMachineCatalogInput::RuntimeState),
1350 Self::AdmitModelRoutingAssistantTurn => {
1351 Some(MeerkatMachineCatalogInput::AdmitModelRoutingAssistantTurn)
1352 }
1353 Self::BeginImageOperation => Some(MeerkatMachineCatalogInput::BeginImageOperation),
1354 Self::DenyImageOperationPlan => {
1355 Some(MeerkatMachineCatalogInput::DenyImageOperationPlan)
1356 }
1357 Self::ActivateImageOperationOverride => {
1358 Some(MeerkatMachineCatalogInput::ActivateImageOperationOverride)
1359 }
1360 Self::ClassifyImageOperationTerminal => {
1361 Some(MeerkatMachineCatalogInput::ClassifyImageOperationTerminal)
1362 }
1363 Self::CompleteImageOperation => {
1364 Some(MeerkatMachineCatalogInput::CompleteImageOperation)
1365 }
1366 Self::RestoreImageOperationOverride => {
1367 Some(MeerkatMachineCatalogInput::RestoreImageOperationOverride)
1368 }
1369 Self::LoadBoundaryReceipt => Some(MeerkatMachineCatalogInput::LoadBoundaryReceipt),
1370 Self::AcceptWithCompletion => Some(MeerkatMachineCatalogInput::AcceptWithCompletion),
1371 Self::AcceptWithoutWake => Some(MeerkatMachineCatalogInput::AcceptWithoutWake),
1372 }
1373 }
1374}
1375
1376#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1377pub enum MeerkatMachineShellMechanicReason {
1378 ModelRoutingShellConfiguration,
1379 TurnControlOverlayRequest,
1380 RealtimeTransportObservation,
1381 SessionModelRoutingObservation,
1382 LocalSessionBindingBootstrap,
1383}
1384
1385#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1386pub struct MeerkatMachineCommandClassificationRecord {
1387 pub command: MeerkatMachineCommandVariant,
1388 pub classification: MeerkatMachineCommandClassification,
1389}
1390
1391#[doc(hidden)]
1392#[must_use]
1393pub fn canonical_meerkat_machine_command_classifications()
1394-> Vec<MeerkatMachineCommandClassificationRecord> {
1395 MeerkatMachineCommand::command_variant_manifest()
1396 .iter()
1397 .copied()
1398 .map(|variant| MeerkatMachineCommandClassificationRecord {
1399 command: variant,
1400 classification: meerkat_machine_command_classification(variant),
1401 })
1402 .collect()
1403}
1404
1405const fn meerkat_machine_command_classification(
1406 variant: MeerkatMachineCommandVariant,
1407) -> MeerkatMachineCommandClassification {
1408 match variant {
1409 MeerkatMachineCommandVariant::ConfigureModelRoutingBaseline => {
1410 MeerkatMachineCommandClassification::CatalogInput(
1411 MeerkatMachineCatalogInput::SetModelRoutingBaseline,
1412 )
1413 }
1414 MeerkatMachineCommandVariant::RequestSwitchTurn => {
1415 MeerkatMachineCommandClassification::CatalogInputs(&[
1416 MeerkatMachineCatalogInput::RequestFiniteSwitchTurn,
1417 MeerkatMachineCatalogInput::RequestUntilChangedSwitchTurn,
1418 ])
1419 }
1420 MeerkatMachineCommandVariant::ResolvedSessionLlmCapabilities => {
1421 MeerkatMachineCommandClassification::ShellMechanic(
1422 MeerkatMachineShellMechanicReason::SessionModelRoutingObservation,
1423 )
1424 }
1425 MeerkatMachineCommandVariant::SessionModelRoutingStatus => {
1426 MeerkatMachineCommandClassification::CatalogInput(
1427 MeerkatMachineCatalogInput::ModelRoutingStatus,
1428 )
1429 }
1430 MeerkatMachineCommandVariant::PrepareLocalSessionBindings => {
1431 MeerkatMachineCommandClassification::ShellMechanic(
1432 MeerkatMachineShellMechanicReason::LocalSessionBindingBootstrap,
1433 )
1434 }
1435 MeerkatMachineCommandVariant::RegisterSession => {
1436 MeerkatMachineCommandClassification::CatalogInput(
1437 MeerkatMachineCatalogInput::RegisterSession,
1438 )
1439 }
1440 MeerkatMachineCommandVariant::UnregisterSession => {
1441 MeerkatMachineCommandClassification::CatalogInput(
1442 MeerkatMachineCatalogInput::UnregisterSession,
1443 )
1444 }
1445 MeerkatMachineCommandVariant::EnsureSessionWithExecutor => {
1446 MeerkatMachineCommandClassification::CatalogInput(
1447 MeerkatMachineCatalogInput::EnsureSessionWithExecutor,
1448 )
1449 }
1450 MeerkatMachineCommandVariant::SetSilentIntents => {
1451 MeerkatMachineCommandClassification::CatalogInput(
1452 MeerkatMachineCatalogInput::SetSilentIntents,
1453 )
1454 }
1455 MeerkatMachineCommandVariant::CancelAfterBoundary => {
1456 MeerkatMachineCommandClassification::CatalogInput(
1457 MeerkatMachineCatalogInput::CancelAfterBoundary,
1458 )
1459 }
1460 MeerkatMachineCommandVariant::StopRuntimeExecutor => {
1461 MeerkatMachineCommandClassification::CatalogInput(
1462 MeerkatMachineCatalogInput::StopRuntimeExecutor,
1463 )
1464 }
1465 MeerkatMachineCommandVariant::CommitServiceTurnTerminalReceipt => {
1466 MeerkatMachineCommandClassification::CatalogInput(
1467 MeerkatMachineCatalogInput::ServiceTurnCommitted,
1468 )
1469 }
1470 MeerkatMachineCommandVariant::ContainsSession => {
1471 MeerkatMachineCommandClassification::CatalogInput(
1472 MeerkatMachineCatalogInput::ContainsSession,
1473 )
1474 }
1475 MeerkatMachineCommandVariant::SessionHasExecutor => {
1476 MeerkatMachineCommandClassification::CatalogInput(
1477 MeerkatMachineCatalogInput::SessionHasExecutor,
1478 )
1479 }
1480 MeerkatMachineCommandVariant::SessionHasComms => {
1481 MeerkatMachineCommandClassification::CatalogInput(
1482 MeerkatMachineCatalogInput::SessionHasComms,
1483 )
1484 }
1485 MeerkatMachineCommandVariant::OpsLifecycleRegistry => {
1486 MeerkatMachineCommandClassification::CatalogInput(
1487 MeerkatMachineCatalogInput::OpsLifecycleRegistry,
1488 )
1489 }
1490 MeerkatMachineCommandVariant::PrepareBindings => {
1491 MeerkatMachineCommandClassification::CatalogInput(
1492 MeerkatMachineCatalogInput::PrepareBindings,
1493 )
1494 }
1495 MeerkatMachineCommandVariant::InputState => {
1496 MeerkatMachineCommandClassification::CatalogInput(
1497 MeerkatMachineCatalogInput::InputState,
1498 )
1499 }
1500 MeerkatMachineCommandVariant::InputStateByIdempotencyKey => {
1504 MeerkatMachineCommandClassification::CatalogInput(
1505 MeerkatMachineCatalogInput::InputState,
1506 )
1507 }
1508 MeerkatMachineCommandVariant::InteractionTerminalStatus
1512 | MeerkatMachineCommandVariant::RunTerminalStatus => {
1513 MeerkatMachineCommandClassification::CatalogInput(
1514 MeerkatMachineCatalogInput::InputState,
1515 )
1516 }
1517 MeerkatMachineCommandVariant::ListActiveInputs => {
1518 MeerkatMachineCommandClassification::CatalogInput(
1519 MeerkatMachineCatalogInput::ListActiveInputs,
1520 )
1521 }
1522 MeerkatMachineCommandVariant::ReconfigureSessionLlmIdentity => {
1523 MeerkatMachineCommandClassification::CatalogInput(
1524 MeerkatMachineCatalogInput::ReconfigureSessionLlmIdentity,
1525 )
1526 }
1527 MeerkatMachineCommandVariant::StagePersistentFilter => {
1528 MeerkatMachineCommandClassification::CatalogInput(
1529 MeerkatMachineCatalogInput::StagePersistentFilter,
1530 )
1531 }
1532 MeerkatMachineCommandVariant::RequestDeferredTools => {
1533 MeerkatMachineCommandClassification::CatalogInput(
1534 MeerkatMachineCatalogInput::RequestDeferredTools,
1535 )
1536 }
1537 MeerkatMachineCommandVariant::PublishCommittedVisibleSet => {
1538 MeerkatMachineCommandClassification::CatalogInput(
1539 MeerkatMachineCatalogInput::PublishCommittedVisibleSet,
1540 )
1541 }
1542 MeerkatMachineCommandVariant::SetPeerIngressContext => {
1543 MeerkatMachineCommandClassification::CatalogInput(
1544 MeerkatMachineCatalogInput::SetPeerIngressContext,
1545 )
1546 }
1547 MeerkatMachineCommandVariant::NotifyDrainExited => {
1548 MeerkatMachineCommandClassification::CatalogInput(
1549 MeerkatMachineCatalogInput::NotifyDrainExited,
1550 )
1551 }
1552 MeerkatMachineCommandVariant::AbortAll => {
1553 MeerkatMachineCommandClassification::CatalogInput(MeerkatMachineCatalogInput::AbortAll)
1554 }
1555 MeerkatMachineCommandVariant::Abort => {
1556 MeerkatMachineCommandClassification::CatalogInput(MeerkatMachineCatalogInput::Abort)
1557 }
1558 MeerkatMachineCommandVariant::Wait => {
1559 MeerkatMachineCommandClassification::CatalogInput(MeerkatMachineCatalogInput::Wait)
1560 }
1561 MeerkatMachineCommandVariant::Ingest => {
1562 MeerkatMachineCommandClassification::CatalogInput(MeerkatMachineCatalogInput::Ingest)
1563 }
1564 MeerkatMachineCommandVariant::PublishEvent => {
1565 MeerkatMachineCommandClassification::CatalogInput(
1566 MeerkatMachineCatalogInput::PublishEvent,
1567 )
1568 }
1569 MeerkatMachineCommandVariant::Retire => {
1570 MeerkatMachineCommandClassification::CatalogInput(MeerkatMachineCatalogInput::Retire)
1571 }
1572 MeerkatMachineCommandVariant::Recycle => {
1573 MeerkatMachineCommandClassification::CatalogInput(MeerkatMachineCatalogInput::Recycle)
1574 }
1575 MeerkatMachineCommandVariant::Reset => {
1576 MeerkatMachineCommandClassification::CatalogInput(MeerkatMachineCatalogInput::Reset)
1577 }
1578 MeerkatMachineCommandVariant::Recover => {
1579 MeerkatMachineCommandClassification::CatalogInput(MeerkatMachineCatalogInput::Recover)
1580 }
1581 MeerkatMachineCommandVariant::Destroy => {
1582 MeerkatMachineCommandClassification::CatalogInput(MeerkatMachineCatalogInput::Destroy)
1583 }
1584 MeerkatMachineCommandVariant::RuntimeState => {
1585 MeerkatMachineCommandClassification::CatalogInput(
1586 MeerkatMachineCatalogInput::RuntimeState,
1587 )
1588 }
1589 MeerkatMachineCommandVariant::AdmitModelRoutingAssistantTurn => {
1590 MeerkatMachineCommandClassification::CatalogInput(
1591 MeerkatMachineCatalogInput::AdmitModelRoutingAssistantTurn,
1592 )
1593 }
1594 MeerkatMachineCommandVariant::BeginImageOperation => {
1595 MeerkatMachineCommandClassification::CatalogInput(
1596 MeerkatMachineCatalogInput::BeginImageOperation,
1597 )
1598 }
1599 MeerkatMachineCommandVariant::DenyImageOperationPlan => {
1600 MeerkatMachineCommandClassification::CatalogInput(
1601 MeerkatMachineCatalogInput::DenyImageOperationPlan,
1602 )
1603 }
1604 MeerkatMachineCommandVariant::ActivateImageOperationOverride => {
1605 MeerkatMachineCommandClassification::CatalogInput(
1606 MeerkatMachineCatalogInput::ActivateImageOperationOverride,
1607 )
1608 }
1609 MeerkatMachineCommandVariant::ClassifyImageOperationTerminal => {
1610 MeerkatMachineCommandClassification::CatalogInput(
1611 MeerkatMachineCatalogInput::ClassifyImageOperationTerminal,
1612 )
1613 }
1614 MeerkatMachineCommandVariant::CompleteImageOperation => {
1615 MeerkatMachineCommandClassification::CatalogInput(
1616 MeerkatMachineCatalogInput::CompleteImageOperation,
1617 )
1618 }
1619 MeerkatMachineCommandVariant::RestoreImageOperationOverride => {
1620 MeerkatMachineCommandClassification::CatalogInput(
1621 MeerkatMachineCatalogInput::RestoreImageOperationOverride,
1622 )
1623 }
1624 MeerkatMachineCommandVariant::LoadBoundaryReceipt => {
1625 MeerkatMachineCommandClassification::CatalogInput(
1626 MeerkatMachineCatalogInput::LoadBoundaryReceipt,
1627 )
1628 }
1629 MeerkatMachineCommandVariant::AcceptWithCompletion => {
1630 MeerkatMachineCommandClassification::CatalogInput(
1631 MeerkatMachineCatalogInput::AcceptWithCompletion,
1632 )
1633 }
1634 MeerkatMachineCommandVariant::AcceptWithoutWake => {
1635 MeerkatMachineCommandClassification::CatalogInput(
1636 MeerkatMachineCatalogInput::AcceptWithoutWake,
1637 )
1638 }
1639 }
1640}
1641
1642#[derive(Debug, Clone, PartialEq, Eq)]
1646pub struct MeerkatCompletionWaiterSnapshot {
1647 pub input_id: InputId,
1648 pub waiter_count: usize,
1649}
1650
1651#[derive(Debug, Clone, PartialEq, Eq)]
1656pub struct MeerkatCompletionWaitersSnapshot {
1657 pub input_count: usize,
1658 pub waiter_count: usize,
1659 pub waiting_inputs: Vec<MeerkatCompletionWaiterSnapshot>,
1660}
1661
1662#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1664pub enum MeerkatDriverKind {
1665 Ephemeral,
1666 Persistent,
1667}
1668
1669#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1671pub struct MeerkatCursorSnapshot {
1672 pub agent_applied_cursor: u64,
1673 pub runtime_observed_seq: u64,
1674 pub runtime_last_injected_seq: u64,
1675}
1676
1677#[derive(Debug, Clone)]
1679pub struct MeerkatBindingSnapshot {
1680 pub session_id: SessionId,
1681 pub runtime_id: LogicalRuntimeId,
1682 pub driver_kind: MeerkatDriverKind,
1683 pub driver_present: bool,
1684 pub completions_present: bool,
1685 pub ops_registry_present: bool,
1686 pub epoch_id: RuntimeEpochId,
1687 pub cursor_state: MeerkatCursorSnapshot,
1688}
1689
1690#[derive(Debug, Clone)]
1692pub struct MeerkatControlSnapshot {
1693 pub phase: RuntimeState,
1694 pub current_run_id: Option<RunId>,
1695 pub pre_run_phase: Option<RuntimeState>,
1696}
1697
1698#[derive(Debug, Clone)]
1700pub struct MeerkatAdmittedInputSnapshot {
1701 pub input_id: InputId,
1702 pub content_shape: Option<ContentShape>,
1703 pub request_id: Option<RequestId>,
1704 pub reservation_key: Option<ReservationKey>,
1705 pub handling_mode: Option<HandlingMode>,
1706 pub live_interrupt_required: bool,
1710 pub lifecycle: Option<InputLifecycleState>,
1711 pub terminal_outcome: Option<InputTerminalOutcome>,
1712 pub last_run_id: Option<RunId>,
1713 pub last_boundary_sequence: Option<u64>,
1714 pub is_prompt: bool,
1715}
1716
1717#[derive(Debug, Clone)]
1719pub struct MeerkatInputsSnapshot {
1720 pub admission_order: Vec<MeerkatAdmittedInputSnapshot>,
1721 pub queue: Vec<InputId>,
1722 pub steer_queue: Vec<InputId>,
1723 pub current_run_id: Option<RunId>,
1724 pub current_run_contributors: Vec<InputId>,
1725 pub post_admission_signal: String,
1726 pub silent_intent_overrides: Vec<String>,
1727}
1728
1729#[derive(Debug, Clone)]
1735pub struct MeerkatArchiveSnapshot {
1736 pub control: MeerkatControlSnapshot,
1737 pub queue: Vec<InputId>,
1738 pub steer_queue: Vec<InputId>,
1739 pub completion_waiters: MeerkatCompletionWaitersSnapshot,
1740}
1741
1742#[derive(Debug, Clone)]
1748pub struct MeerkatLedgerSnapshot {
1749 pub input_count: usize,
1750 pub non_terminal_count: usize,
1751 pub accepted_count: usize,
1752 pub queued_count: usize,
1753 pub staged_count: usize,
1754 pub applied_count: usize,
1755 pub applied_pending_consumption_count: usize,
1756 pub consumed_count: usize,
1757 pub superseded_count: usize,
1758 pub coalesced_count: usize,
1759 pub abandoned_count: usize,
1760}
1761
1762#[derive(Debug, Clone)]
1764pub struct MeerkatOpsSnapshot {
1765 pub operation_count: usize,
1766 pub active_count: usize,
1767 pub wait_request_id: Option<WaitRequestId>,
1768 pub pending_wait_present: bool,
1769 pub pending_wait_request_id: Option<WaitRequestId>,
1770 pub wait_operation_ids: Vec<OperationId>,
1771 pub operations: Vec<OperationLifecycleSnapshot>,
1772}
1773
1774#[derive(Debug, Clone)]
1779pub struct MeerkatDrainSnapshot {
1780 pub slot_present: bool,
1781 pub phase: Option<CommsDrainPhase>,
1782 pub mode: Option<CommsDrainMode>,
1783 pub handle_present: bool,
1784}
1785
1786#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1793pub struct MeerkatFormalStateProjection {
1794 pub available_fields: BTreeMap<String, String>,
1796 pub unavailable_fields: Vec<String>,
1798}
1799
1800#[derive(Debug, Clone)]
1805pub struct MeerkatMachineSpineSnapshot {
1806 pub binding: MeerkatBindingSnapshot,
1807 pub control: MeerkatControlSnapshot,
1808 pub inputs: MeerkatInputsSnapshot,
1809 pub ledger: MeerkatLedgerSnapshot,
1810 pub completion_waiters: MeerkatCompletionWaitersSnapshot,
1811 pub ops: MeerkatOpsSnapshot,
1812 pub drain: MeerkatDrainSnapshot,
1813 pub formal_state: MeerkatFormalStateProjection,
1814}
1815
1816impl MeerkatMachineSpineSnapshot {
1817 pub fn validate_spine_invariants(&self) -> Result<(), Vec<String>> {
1823 let mut violations = Vec::new();
1824
1825 if self.control.phase == RuntimeState::Running && self.control.current_run_id.is_none() {
1829 violations
1830 .push("RunningHasActiveRunInvariant: phase is Running but no active run_id".into());
1831 }
1832
1833 if self.control.current_run_id.is_some()
1835 && !matches!(
1836 self.control.phase,
1837 RuntimeState::Running | RuntimeState::Retired
1838 )
1839 {
1840 violations.push(format!(
1841 "ActiveRunPhaseInvariant: active run_id present but phase is {:?}",
1842 self.control.phase
1843 ));
1844 }
1845
1846 if self.control.phase == RuntimeState::Destroyed {
1848 if !self.inputs.queue.is_empty() {
1849 violations.push("DestroyedShapeInvariant: Destroyed but queue is non-empty".into());
1850 }
1851 if !self.inputs.steer_queue.is_empty() {
1852 violations
1853 .push("DestroyedShapeInvariant: Destroyed but steer_queue is non-empty".into());
1854 }
1855 if self.completion_waiters.input_count > 0 {
1856 violations.push(
1857 "DestroyedShapeInvariant: Destroyed but completion waiters remain".into(),
1858 );
1859 }
1860 }
1861
1862 let queue_set: std::collections::HashSet<_> = self.inputs.queue.iter().collect();
1866 let steer_set: std::collections::HashSet<_> = self.inputs.steer_queue.iter().collect();
1867 if !queue_set.is_disjoint(&steer_set) {
1868 violations
1869 .push("QueueSteerDisjointInvariant: queue and steer_queue share entries".into());
1870 }
1871
1872 for qid in &self.inputs.queue {
1874 if let Some(snap) = self
1875 .inputs
1876 .admission_order
1877 .iter()
1878 .find(|a| &a.input_id == qid)
1879 {
1880 if snap.handling_mode != Some(HandlingMode::Queue) {
1881 violations.push(format!(
1882 "QueueHandlingInvariant: queue entry {qid} has handling_mode {:?}",
1883 snap.handling_mode
1884 ));
1885 }
1886 if snap.lifecycle != Some(InputLifecycleState::Queued) {
1887 violations.push(format!(
1888 "QueueHandlingInvariant: queue entry {qid} has lifecycle {:?}",
1889 snap.lifecycle
1890 ));
1891 }
1892 }
1893 }
1894
1895 for sid in &self.inputs.steer_queue {
1897 if let Some(snap) = self
1898 .inputs
1899 .admission_order
1900 .iter()
1901 .find(|a| &a.input_id == sid)
1902 {
1903 if snap.handling_mode != Some(HandlingMode::Steer) {
1904 violations.push(format!(
1905 "SteerHandlingInvariant: steer_queue entry {sid} has handling_mode {:?}",
1906 snap.handling_mode
1907 ));
1908 }
1909 if snap.lifecycle != Some(InputLifecycleState::Queued) {
1910 violations.push(format!(
1911 "SteerHandlingInvariant: steer_queue entry {sid} has lifecycle {:?}",
1912 snap.lifecycle
1913 ));
1914 }
1915 }
1916 }
1917
1918 for cid in &self.inputs.current_run_contributors {
1921 if let Some(snap) = self
1922 .inputs
1923 .admission_order
1924 .iter()
1925 .find(|a| &a.input_id == cid)
1926 && !matches!(
1927 snap.lifecycle,
1928 Some(
1929 InputLifecycleState::Staged
1930 | InputLifecycleState::Applied
1931 | InputLifecycleState::AppliedPendingConsumption
1932 )
1933 )
1934 {
1935 violations.push(format!(
1936 "ContributorLifecycleInvariant: contributor {cid} has lifecycle {:?}",
1937 snap.lifecycle
1938 ));
1939 }
1940 }
1941
1942 for snap in &self.inputs.admission_order {
1944 if snap.terminal_outcome.is_some() {
1945 if queue_set.contains(&snap.input_id) {
1946 violations.push(format!(
1947 "TerminalInputsNotQueuedInvariant: terminal input {} in queue",
1948 snap.input_id
1949 ));
1950 }
1951 if steer_set.contains(&snap.input_id) {
1952 violations.push(format!(
1953 "TerminalInputsNotQueuedInvariant: terminal input {} in steer_queue",
1954 snap.input_id
1955 ));
1956 }
1957 }
1958 }
1959
1960 if self.control.current_run_id.is_some() && self.inputs.current_run_contributors.is_empty()
1962 {
1963 violations
1964 .push("CurrentRunContributorsInvariant: active run but no contributors".into());
1965 }
1966
1967 if let Some(control_run_id) = &self.control.current_run_id {
1971 for cid in &self.inputs.current_run_contributors {
1972 if let Some(snap) = self
1973 .inputs
1974 .admission_order
1975 .iter()
1976 .find(|a| &a.input_id == cid)
1977 && snap.last_run_id.as_ref() != Some(control_run_id)
1978 {
1979 violations.push(format!(
1980 "ContributorRunIdentityInvariant: contributor {cid} has last_run_id {:?}, expected {:?}",
1981 snap.last_run_id, control_run_id
1982 ));
1983 }
1984 }
1985 }
1986
1987 let wait_active = self.ops.wait_request_id.is_some();
1991 if wait_active && self.ops.wait_operation_ids.is_empty() {
1992 violations
1993 .push("WaitAllAlignmentInvariant: wait_active but no wait_operation_ids".into());
1994 }
1995 if !wait_active && !self.ops.wait_operation_ids.is_empty() {
1996 violations.push(
1997 "WaitAllAlignmentInvariant: wait_operation_ids present but no wait_request_id"
1998 .into(),
1999 );
2000 }
2001
2002 if let Some(phase) = self.drain.phase
2006 && phase != CommsDrainPhase::Inactive
2007 && self.drain.mode.is_none()
2008 {
2009 violations.push("DrainModeInvariant: drain.phase is active but mode is None".into());
2010 }
2011
2012 if violations.is_empty() {
2013 Ok(())
2014 } else {
2015 Err(violations)
2016 }
2017 }
2018}