#![allow(clippy::too_many_arguments)]
use meerkat_machine_dsl::machine;
use super::OptionValueExt;
#[derive(
Debug,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Default,
serde::Serialize,
serde::Deserialize,
)]
pub struct SessionId(pub String);
impl<T: Into<String>> From<T> for SessionId {
fn from(value: T) -> Self {
Self(value.into())
}
}
impl SessionId {
pub fn as_str(&self) -> &str {
&self.0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum SessionFirstTurnPhase {
#[default]
Inactive,
Pending,
Consumed,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum SessionInitialPromptStageDecision {
#[default]
Clear,
Store,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum SystemContextAppendDecision {
#[default]
Staged,
Duplicate,
RejectEmpty,
RejectConflict,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum SystemContextPersistAppendAdmission {
#[default]
Reject,
Admit,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum SystemContextSource {
#[default]
Normal,
RuntimeSteer,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum RealtimeTranscriptRoleKind {
#[default]
User,
Assistant,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum RealtimeTranscriptLaneKind {
#[default]
Display,
Spoken,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum RealtimeTranscriptStopReasonKind {
Cancelled,
ToolUse,
#[default]
Other,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum RealtimeTranscriptMaterializeDecision {
#[default]
Wait,
MarkSkipped,
MaterializeUser,
MaterializeAssistant,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum SessionSystemPromptSource {
#[default]
DirectMutation,
ExplicitBuild,
DefaultBuild,
WasmDefaultBuild,
RuntimeContextAppend,
RuntimeSteerCleanup,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum ObservedSessionTailKind {
#[default]
Empty,
System,
SystemNotice,
User,
BlockAssistant,
ToolResults,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum PendingContinuationDisposition {
RunPending,
#[default]
NoPendingBoundary,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum PendingContinuationPublicTerminal {
#[default]
NoPendingBoundary,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum ResumeOverrideRejection {
#[default]
ProviderRequiresModel,
BuildOnlyAfterFirstTurn,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum ResumeProviderSelection {
#[default]
RecomputeFromModel,
UseOverride,
UseStored,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum ResumeSelfHostedSelection {
#[default]
Clear,
Retain,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum LiveSessionAuthorityKind {
#[default]
LiveAuthoritative,
DurableAuthoritative,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum LiveSessionAuthorityReason {
#[default]
StoredArchived,
LiveUncommittedTranscript,
RuntimeSystemContextDiverged,
StoredTranscriptRevisionDiverged,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum RuntimeProjectionRollbackDisposition {
#[default]
RejectDivergent,
RebuildToAuthority,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum SessionDocumentLifecycle {
#[default]
Active,
Archived,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum SessionArchiveDisposition {
#[default]
Archive,
AlreadyArchived,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum TranscriptEditKind {
#[default]
Fork,
Rewrite,
}
machine! {
machine SessionDocumentMachine {
version: 1,
rust: "self" / "catalog::dsl::session_document",
state {
lifecycle_phase: SessionDocumentPhase,
session_first_turn_phase: Map<SessionId, Enum<SessionFirstTurnPhase>>,
session_pending_initial_prompt_present: Map<SessionId, bool>,
session_pending_tool_results_count: Map<SessionId, u64>,
session_lifecycle_terminal: Map<SessionId, Enum<SessionDocumentLifecycle>>,
}
init(Ready) {
session_first_turn_phase = EmptyMap,
session_pending_initial_prompt_present = EmptyMap,
session_pending_tool_results_count = EmptyMap,
session_lifecycle_terminal = EmptyMap,
}
terminal []
phase SessionDocumentPhase {
Ready,
}
input SessionDocumentInput {
MarkSessionInitialTurnPending { session_id: SessionId },
StartSessionInitialTurn { session_id: SessionId },
StageSessionInitialPrompt { session_id: SessionId, prompt_has_content: bool },
StageSessionToolResults { session_id: SessionId, result_count: u64 },
ConsumeSessionDeferredInputs { session_id: SessionId },
RestoreSessionConsumedInputs {
session_id: SessionId,
restore_first_turn_pending: bool,
pending_initial_prompt_present: bool,
pending_tool_result_message_count: u64,
},
RecoverSessionFirstTurnPhase {
session_id: SessionId,
phase: Enum<SessionFirstTurnPhase>,
pending_initial_prompt_present: bool,
pending_tool_result_message_count: u64,
},
ResolveSessionFirstTurnOverridesAllowed { session_id: SessionId },
ResolveSystemContextAppend {
trimmed_text_byte_count: u64,
idempotency_key_present: bool,
existing_key_matches: bool,
existing_key_conflicts: bool,
active_turn_scoped: bool,
},
ResolveSystemContextPendingApplyItem {
source_kind: Enum<SystemContextSource>,
},
ResolveSystemContextSteerCleanupItem {
source_kind: Enum<SystemContextSource>,
},
RestoreSystemContextSnapshot {
active_keys_have_known_pending_or_seen: bool,
seen_keys_match_known_appends: bool,
},
ResolveSystemContextPersistAppendAdmission {
has_previous: bool,
content_identical: bool,
content_extends_previous: bool,
appended_starts_with_separator: bool,
incoming_is_runtime_context_append: bool,
},
ResolveRealtimeItemObserved {
role: Enum<RealtimeTranscriptRoleKind>,
response_discarded: bool,
},
ResolveRealtimeItemSkipped,
ResolveRealtimeUserTranscriptFinal {
text_present: bool,
segment_empty: bool,
segment_matches: bool,
},
ResolveRealtimeAssistantDelta {
response_id_valid: bool,
response_discarded: bool,
delta_id_present: bool,
delta_id_seen: bool,
item_has_text: bool,
current_lane: Enum<RealtimeTranscriptLaneKind>,
requested_lane: Enum<RealtimeTranscriptLaneKind>,
response_completed: bool,
text_after_write_present: bool,
},
ResolveRealtimeAssistantTextReplacement {
response_id_valid: bool,
response_discarded: bool,
item_materialized: bool,
item_has_text: bool,
current_lane: Enum<RealtimeTranscriptLaneKind>,
requested_lane: Enum<RealtimeTranscriptLaneKind>,
response_completed: bool,
text_after_replace_present: bool,
},
ResolveRealtimeAssistantTurnCompleted {
response_id_valid: bool,
response_discarded: bool,
stop_reason: Enum<RealtimeTranscriptStopReasonKind>,
},
ResolveRealtimeAssistantTurnInterrupted {
response_id_valid: bool,
},
ResolveRealtimeMaterializeCandidate {
item_materialized: bool,
predecessor_materialized: bool,
item_skipped: bool,
item_ready: bool,
item_text_present: bool,
role: Enum<RealtimeTranscriptRoleKind>,
response_id_present: bool,
completion_present: bool,
completion_usage_consumed: bool,
},
RestoreRealtimeTranscriptState {
item_count: u64,
first_seen_count: u64,
first_seen_unique_count: u64,
every_item_has_order_entry: bool,
every_order_entry_has_item: bool,
all_identity_fields_valid: bool,
all_delta_ids_valid: bool,
all_completion_response_ids_valid: bool,
all_discarded_response_ids_valid: bool,
all_materialized_items_were_ready_or_skipped: bool,
all_assistant_items_have_response_unless_skipped: bool,
all_ready_assistant_items_have_completion_or_are_skipped: bool,
all_materialized_assistant_completions_consumed: bool,
all_completed_assistant_text_items_are_ready_or_materialized_or_skipped: bool,
all_discarded_assistant_items_are_skipped_or_materialized: bool,
},
AuthorizeSessionMetadataPersist {
schema_version: u64,
model_present: bool,
},
AuthorizeSessionBuildStatePersist {
mob_tool_authority_context_present: bool,
mob_tool_authority_context_generated: bool,
},
RestoreSessionBuildState,
AuthorizeSystemPromptMutation {
source: Enum<SessionSystemPromptSource>,
prompt_present: bool,
prompt_byte_count: u64,
replacing_existing: bool,
},
ResolvePendingContinuation {
session_tail: Enum<ObservedSessionTailKind>,
staged_tool_result_count: u64,
},
AuthorizeSessionResumeOverrides {
provider_override_present: bool,
model_override_present: bool,
has_build_only_overrides: bool,
first_turn_phase: Enum<SessionFirstTurnPhase>,
},
ClassifyLiveSessionAuthority {
stored_transcript_diverged: bool,
live_has_uncommitted_transcript: bool,
runtime_system_context_diverged: bool,
stored_is_archived: bool,
},
RecoverSessionFromStore {
session_id: SessionId,
has_metadata: bool,
has_build_state: bool,
runtime_projection_quarantined: bool,
},
ResolveRuntimeProjectionRollback {
session_id: SessionId,
row_continues_authority: bool,
row_is_runtime_checkpoint: bool,
},
ApplyPendingToolResults {
session_id: SessionId,
result_count: u64,
},
TranscriptEdit {
session_id: SessionId,
fork_or_rewrite_directive: Enum<TranscriptEditKind>,
},
RecoverSessionLifecycleTerminal {
session_id: SessionId,
terminal: Enum<SessionDocumentLifecycle>,
},
ArchiveSessionDocument {
session_id: SessionId,
runtime_backed: bool,
durable_snapshot_present: bool,
runtime_session_registered: bool,
},
}
effect SessionDocumentEffect {
SessionFirstTurnPhaseResolved {
phase: Enum<SessionFirstTurnPhase>,
was_pending: bool,
},
SessionFirstTurnOverridesResolved { allowed: bool },
SessionInitialPromptStageResolved { decision: Enum<SessionInitialPromptStageDecision> },
SessionToolResultsStageResolved { accepted_count: u64 },
SessionConsumedInputsRestoreResolved {
restore_first_turn_pending: bool,
restore_initial_prompt: bool,
restore_tool_results: bool,
},
SessionFirstTurnPhaseRecovered,
SystemContextAppendResolved {
decision: Enum<SystemContextAppendDecision>,
active_turn_scoped: bool,
},
SystemContextPendingApplyItemResolved {
promote_to_applied: bool,
mark_seen_applied: bool,
remove_seen: bool,
},
SystemContextSteerCleanupItemResolved {
discard: bool,
},
SystemContextSnapshotRestoreAuthorized,
SystemContextPersistAppendAdmissionResolved {
admission: Enum<SystemContextPersistAppendAdmission>,
},
RealtimeTranscriptEventResolved {
observe_item: bool,
observe_skipped: bool,
write_user_segment: bool,
append_assistant_segment: bool,
replace_assistant_segment: bool,
promote_lane: bool,
mark_item_ready: bool,
record_delta_id: bool,
remove_completion: bool,
record_completion: bool,
discard_response: bool,
discard_response_by_lane: bool,
mark_response_ready: bool,
materialize_ready_items: bool,
},
RealtimeMaterializeCandidateResolved {
decision: Enum<RealtimeTranscriptMaterializeDecision>,
consume_usage: bool,
},
RealtimeTranscriptSnapshotRestoreAuthorized,
SessionMetadataPersistAuthorized,
SessionBuildStatePersistAuthorized,
SessionBuildStateRestoreAuthorized,
SystemPromptMutationAuthorized,
PendingContinuationResolved { disposition: Enum<PendingContinuationDisposition> },
PendingContinuationPublicTerminalResolved { terminal: Enum<PendingContinuationPublicTerminal> },
SessionResumeOverridesAuthorized {
provider_selection: Enum<ResumeProviderSelection>,
self_hosted_selection: Enum<ResumeSelfHostedSelection>,
provider_overridden: bool,
},
SessionResumeOverridesRejected { reason: Enum<ResumeOverrideRejection> },
LiveSessionAuthorityClassified {
authority: Enum<LiveSessionAuthorityKind>,
reason: Enum<LiveSessionAuthorityReason>,
},
SessionStoreRecoverySourceResolved { recoverable: bool },
RuntimeProjectionRollbackResolved {
disposition: Enum<RuntimeProjectionRollbackDisposition>,
},
SessionToolResultsApplied {
session_id: SessionId,
applied_count: u64,
},
TranscriptRewriteCommitted {
kind: Enum<TranscriptEditKind>,
success: bool,
},
SessionLifecycleTerminalRecovered,
SessionArchiveResolved {
disposition: Enum<SessionArchiveDisposition>,
write_document: bool,
retire_runtime: bool,
},
}
helper phase_allows_initial_turn_overrides(phase: Enum<SessionFirstTurnPhase>) -> bool {
phase == SessionFirstTurnPhase::Pending
}
helper should_store_initial_prompt(
phase: Enum<SessionFirstTurnPhase>,
prompt_has_content: bool
) -> bool {
phase == SessionFirstTurnPhase::Pending && prompt_has_content
}
helper append_is_empty(trimmed_text_byte_count: u64) -> bool {
trimmed_text_byte_count == 0
}
helper append_is_conflict(
idempotency_key_present: bool,
existing_key_conflicts: bool
) -> bool {
idempotency_key_present && existing_key_conflicts
}
helper append_is_duplicate(
idempotency_key_present: bool,
existing_key_matches: bool,
existing_key_conflicts: bool
) -> bool {
idempotency_key_present && existing_key_matches && existing_key_conflicts == false
}
helper append_is_new(
idempotency_key_present: bool,
existing_key_matches: bool,
existing_key_conflicts: bool
) -> bool {
idempotency_key_present == false
|| (existing_key_matches == false && existing_key_conflicts == false)
}
helper persist_append_is_admissible(
has_previous: bool,
content_identical: bool,
content_extends_previous: bool,
appended_starts_with_separator: bool,
incoming_is_runtime_context_append: bool
) -> bool {
(has_previous && content_identical)
|| (has_previous
&& content_extends_previous
&& appended_starts_with_separator
&& incoming_is_runtime_context_append)
|| (has_previous == false && incoming_is_runtime_context_append)
}
helper realtime_delta_is_duplicate(delta_id_present: bool, delta_id_seen: bool) -> bool {
delta_id_present && delta_id_seen
}
helper realtime_lane_accepts(
item_has_text: bool,
current_lane: Enum<RealtimeTranscriptLaneKind>,
requested_lane: Enum<RealtimeTranscriptLaneKind>
) -> bool {
current_lane == requested_lane || item_has_text == false
}
helper realtime_should_mark_ready_after_write(
response_completed: bool,
text_after_write_present: bool
) -> bool {
response_completed && text_after_write_present
}
helper realtime_stop_reason_discards(
stop_reason: Enum<RealtimeTranscriptStopReasonKind>
) -> bool {
stop_reason == RealtimeTranscriptStopReasonKind::Cancelled
}
helper realtime_stop_reason_removes_completion(
stop_reason: Enum<RealtimeTranscriptStopReasonKind>
) -> bool {
stop_reason == RealtimeTranscriptStopReasonKind::ToolUse
}
helper realtime_stop_reason_records_completion(
stop_reason: Enum<RealtimeTranscriptStopReasonKind>
) -> bool {
stop_reason == RealtimeTranscriptStopReasonKind::Other
}
helper tail_has_pending_boundary(session_tail: Enum<ObservedSessionTailKind>) -> bool {
session_tail == ObservedSessionTailKind::User
|| session_tail == ObservedSessionTailKind::ToolResults
}
helper has_effective_pending_boundary(
session_tail: Enum<ObservedSessionTailKind>,
staged_tool_result_count: u64
) -> bool {
tail_has_pending_boundary(session_tail) || staged_tool_result_count > 0
}
helper resume_reject_provider_requires_model(
provider_override_present: bool,
model_override_present: bool
) -> bool {
provider_override_present && model_override_present == false
}
helper resume_reject_build_only_after_first_turn(
has_build_only_overrides: bool,
first_turn_phase: Enum<SessionFirstTurnPhase>
) -> bool {
has_build_only_overrides
&& phase_allows_initial_turn_overrides(first_turn_phase) == false
}
helper resume_overrides_admissible(
provider_override_present: bool,
model_override_present: bool,
has_build_only_overrides: bool,
first_turn_phase: Enum<SessionFirstTurnPhase>
) -> bool {
resume_reject_provider_requires_model(
provider_override_present,
model_override_present
) == false
&& resume_reject_build_only_after_first_turn(
has_build_only_overrides,
first_turn_phase
) == false
}
helper resume_provider_recompute_from_model(
model_override_present: bool,
provider_override_present: bool
) -> bool {
model_override_present && provider_override_present == false
}
helper store_projection_can_recover_authority(
has_metadata: bool,
has_build_state: bool,
runtime_projection_quarantined: bool
) -> bool {
has_metadata || has_build_state || runtime_projection_quarantined
}
helper archive_should_retire_runtime(
runtime_backed: bool,
durable_snapshot_present: bool,
runtime_session_registered: bool
) -> bool {
runtime_backed && (durable_snapshot_present || runtime_session_registered)
}
disposition SessionFirstTurnPhaseResolved => local seam NoOwnerRealization,
disposition SessionFirstTurnOverridesResolved => local seam NoOwnerRealization,
disposition SessionInitialPromptStageResolved => local seam NoOwnerRealization,
disposition SessionToolResultsStageResolved => local seam NoOwnerRealization,
disposition SessionConsumedInputsRestoreResolved => local seam NoOwnerRealization,
disposition SessionFirstTurnPhaseRecovered => local seam NoOwnerRealization,
disposition SystemContextAppendResolved => local seam NoOwnerRealization,
disposition SystemContextPendingApplyItemResolved => local seam NoOwnerRealization,
disposition SystemContextSteerCleanupItemResolved => local seam NoOwnerRealization,
disposition SystemContextSnapshotRestoreAuthorized => local seam NoOwnerRealization,
disposition SystemContextPersistAppendAdmissionResolved => local seam NoOwnerRealization,
disposition RealtimeTranscriptEventResolved => local seam NoOwnerRealization,
disposition RealtimeMaterializeCandidateResolved => local seam NoOwnerRealization,
disposition RealtimeTranscriptSnapshotRestoreAuthorized => local seam NoOwnerRealization,
disposition SessionMetadataPersistAuthorized => local seam NoOwnerRealization,
disposition SessionBuildStatePersistAuthorized => local seam NoOwnerRealization,
disposition SessionBuildStateRestoreAuthorized => local seam NoOwnerRealization,
disposition SystemPromptMutationAuthorized => local seam NoOwnerRealization,
disposition PendingContinuationResolved => local seam NoOwnerRealization,
disposition PendingContinuationPublicTerminalResolved => local seam NoOwnerRealization,
disposition SessionResumeOverridesAuthorized => local seam NoOwnerRealization,
disposition SessionResumeOverridesRejected => local seam NoOwnerRealization,
disposition LiveSessionAuthorityClassified => local seam NoOwnerRealization,
disposition SessionStoreRecoverySourceResolved => local seam NoOwnerRealization,
disposition RuntimeProjectionRollbackResolved => local seam NoOwnerRealization,
disposition SessionToolResultsApplied => local seam NoOwnerRealization,
disposition TranscriptRewriteCommitted => local seam NoOwnerRealization,
disposition SessionLifecycleTerminalRecovered => local seam NoOwnerRealization,
disposition SessionArchiveResolved => local seam NoOwnerRealization,
transition MarkSessionInitialTurnPendingInactiveOrPending {
on input MarkSessionInitialTurnPending { session_id }
guard {
self.lifecycle_phase == Phase::Ready
&& (self.session_first_turn_phase.get_cloned(session_id).get("value")
== SessionFirstTurnPhase::Inactive
|| self.session_first_turn_phase.get_cloned(session_id).get("value")
== SessionFirstTurnPhase::Pending)
}
update {
self.session_first_turn_phase.insert(session_id, SessionFirstTurnPhase::Pending);
}
to Ready
emit SessionFirstTurnPhaseResolved {
phase: SessionFirstTurnPhase::Pending,
was_pending: false
}
}
transition MarkSessionInitialTurnPendingConsumed {
on input MarkSessionInitialTurnPending { session_id }
guard {
self.lifecycle_phase == Phase::Ready
&& self.session_first_turn_phase.get_cloned(session_id).get("value")
== SessionFirstTurnPhase::Consumed
}
update {}
to Ready
emit SessionFirstTurnPhaseResolved {
phase: SessionFirstTurnPhase::Consumed,
was_pending: false
}
}
transition StartSessionInitialTurnPending {
on input StartSessionInitialTurn { session_id }
guard {
self.lifecycle_phase == Phase::Ready
&& self.session_first_turn_phase.get_cloned(session_id).get("value")
== SessionFirstTurnPhase::Pending
}
update {
self.session_first_turn_phase.insert(session_id, SessionFirstTurnPhase::Consumed);
}
to Ready
emit SessionFirstTurnPhaseResolved {
phase: SessionFirstTurnPhase::Consumed,
was_pending: true
}
}
transition StartSessionInitialTurnInactive {
on input StartSessionInitialTurn { session_id }
guard {
self.lifecycle_phase == Phase::Ready
&& self.session_first_turn_phase.get_cloned(session_id).get("value")
== SessionFirstTurnPhase::Inactive
}
update {}
to Ready
emit SessionFirstTurnPhaseResolved {
phase: SessionFirstTurnPhase::Inactive,
was_pending: false
}
}
transition StartSessionInitialTurnConsumed {
on input StartSessionInitialTurn { session_id }
guard {
self.lifecycle_phase == Phase::Ready
&& self.session_first_turn_phase.get_cloned(session_id).get("value")
== SessionFirstTurnPhase::Consumed
}
update {}
to Ready
emit SessionFirstTurnPhaseResolved {
phase: SessionFirstTurnPhase::Consumed,
was_pending: false
}
}
transition ResolveSessionFirstTurnOverridesAllowed {
on input ResolveSessionFirstTurnOverridesAllowed { session_id }
guard {
self.lifecycle_phase == Phase::Ready
&& phase_allows_initial_turn_overrides(
self.session_first_turn_phase.get_cloned(session_id).get("value")
)
}
update {}
to Ready
emit SessionFirstTurnOverridesResolved { allowed: true }
}
transition ResolveSessionFirstTurnOverridesDenied {
on input ResolveSessionFirstTurnOverridesAllowed { session_id }
guard {
self.lifecycle_phase == Phase::Ready
&& phase_allows_initial_turn_overrides(
self.session_first_turn_phase.get_cloned(session_id).get("value")
) == false
}
update {}
to Ready
emit SessionFirstTurnOverridesResolved { allowed: false }
}
transition StageSessionInitialPromptStore {
on input StageSessionInitialPrompt { session_id, prompt_has_content }
guard {
self.lifecycle_phase == Phase::Ready
&& should_store_initial_prompt(
self.session_first_turn_phase.get_cloned(session_id).get("value"),
prompt_has_content
)
}
update {
self.session_pending_initial_prompt_present.insert(session_id, true);
}
to Ready
emit SessionInitialPromptStageResolved {
decision: SessionInitialPromptStageDecision::Store
}
}
transition StageSessionInitialPromptClear {
on input StageSessionInitialPrompt { session_id, prompt_has_content }
guard {
self.lifecycle_phase == Phase::Ready
&& should_store_initial_prompt(
self.session_first_turn_phase.get_cloned(session_id).get("value"),
prompt_has_content
) == false
}
update {
self.session_pending_initial_prompt_present.insert(session_id, false);
}
to Ready
emit SessionInitialPromptStageResolved {
decision: SessionInitialPromptStageDecision::Clear
}
}
transition StageSessionToolResults {
on input StageSessionToolResults { session_id, result_count }
guard {
self.lifecycle_phase == Phase::Ready
&& (self.session_first_turn_phase.get_cloned(session_id).get("value")
== SessionFirstTurnPhase::Inactive
|| self.session_first_turn_phase.get_cloned(session_id).get("value")
== SessionFirstTurnPhase::Pending
|| self.session_first_turn_phase.get_cloned(session_id).get("value")
== SessionFirstTurnPhase::Consumed)
}
update {
self.session_pending_tool_results_count.insert(session_id, result_count);
}
to Ready
emit SessionToolResultsStageResolved { accepted_count: result_count }
}
transition ConsumeSessionDeferredInputsPending {
on input ConsumeSessionDeferredInputs { session_id }
guard {
self.lifecycle_phase == Phase::Ready
&& self.session_first_turn_phase.get_cloned(session_id).get("value")
== SessionFirstTurnPhase::Pending
}
update {
self.session_first_turn_phase.insert(session_id, SessionFirstTurnPhase::Consumed);
self.session_pending_initial_prompt_present.insert(session_id, false);
self.session_pending_tool_results_count.insert(session_id, 0);
}
to Ready
emit SessionFirstTurnPhaseResolved {
phase: SessionFirstTurnPhase::Consumed,
was_pending: true
}
}
transition ConsumeSessionDeferredInputsInactive {
on input ConsumeSessionDeferredInputs { session_id }
guard {
self.lifecycle_phase == Phase::Ready
&& self.session_first_turn_phase.get_cloned(session_id).get("value")
== SessionFirstTurnPhase::Inactive
}
update {
self.session_pending_initial_prompt_present.insert(session_id, false);
self.session_pending_tool_results_count.insert(session_id, 0);
}
to Ready
emit SessionFirstTurnPhaseResolved {
phase: SessionFirstTurnPhase::Inactive,
was_pending: false
}
}
transition ConsumeSessionDeferredInputsConsumed {
on input ConsumeSessionDeferredInputs { session_id }
guard {
self.lifecycle_phase == Phase::Ready
&& self.session_first_turn_phase.get_cloned(session_id).get("value")
== SessionFirstTurnPhase::Consumed
}
update {
self.session_pending_initial_prompt_present.insert(session_id, false);
self.session_pending_tool_results_count.insert(session_id, 0);
}
to Ready
emit SessionFirstTurnPhaseResolved {
phase: SessionFirstTurnPhase::Consumed,
was_pending: false
}
}
transition RestoreSessionConsumedInputs {
on input RestoreSessionConsumedInputs {
session_id,
restore_first_turn_pending,
pending_initial_prompt_present,
pending_tool_result_message_count
}
guard { self.lifecycle_phase == Phase::Ready && restore_first_turn_pending }
update {
self.session_first_turn_phase.insert(session_id, SessionFirstTurnPhase::Pending);
self.session_pending_initial_prompt_present
.insert(session_id, pending_initial_prompt_present);
self.session_pending_tool_results_count
.insert(session_id, pending_tool_result_message_count);
}
to Ready
emit SessionConsumedInputsRestoreResolved {
restore_first_turn_pending: restore_first_turn_pending,
restore_initial_prompt: pending_initial_prompt_present,
restore_tool_results: pending_tool_result_message_count > 0
}
}
transition RestoreSessionConsumedInputsNoPhaseRollback {
on input RestoreSessionConsumedInputs {
session_id,
restore_first_turn_pending,
pending_initial_prompt_present,
pending_tool_result_message_count
}
guard { self.lifecycle_phase == Phase::Ready && restore_first_turn_pending == false }
update {
self.session_pending_initial_prompt_present
.insert(session_id, pending_initial_prompt_present);
self.session_pending_tool_results_count
.insert(session_id, pending_tool_result_message_count);
}
to Ready
emit SessionConsumedInputsRestoreResolved {
restore_first_turn_pending: restore_first_turn_pending,
restore_initial_prompt: pending_initial_prompt_present,
restore_tool_results: pending_tool_result_message_count > 0
}
}
transition RecoverSessionFirstTurnPhase {
on input RecoverSessionFirstTurnPhase {
session_id,
phase,
pending_initial_prompt_present,
pending_tool_result_message_count
}
guard {
self.lifecycle_phase == Phase::Ready
&& (phase == SessionFirstTurnPhase::Inactive
|| phase == SessionFirstTurnPhase::Pending
|| phase == SessionFirstTurnPhase::Consumed)
}
update {
self.session_first_turn_phase.insert(session_id, phase);
self.session_pending_initial_prompt_present
.insert(session_id, pending_initial_prompt_present);
self.session_pending_tool_results_count
.insert(session_id, pending_tool_result_message_count);
}
to Ready
emit SessionFirstTurnPhaseRecovered
}
transition ResolveSystemContextAppendEmpty {
on input ResolveSystemContextAppend {
trimmed_text_byte_count,
idempotency_key_present,
existing_key_matches,
existing_key_conflicts,
active_turn_scoped
}
guard {
self.lifecycle_phase == Phase::Ready
&& append_is_empty(trimmed_text_byte_count)
}
update {}
to Ready
emit SystemContextAppendResolved {
decision: SystemContextAppendDecision::RejectEmpty,
active_turn_scoped: active_turn_scoped
}
}
transition ResolveSystemContextAppendConflict {
on input ResolveSystemContextAppend {
trimmed_text_byte_count,
idempotency_key_present,
existing_key_matches,
existing_key_conflicts,
active_turn_scoped
}
guard {
self.lifecycle_phase == Phase::Ready
&& append_is_empty(trimmed_text_byte_count) == false
&& append_is_conflict(idempotency_key_present, existing_key_conflicts)
}
update {}
to Ready
emit SystemContextAppendResolved {
decision: SystemContextAppendDecision::RejectConflict,
active_turn_scoped: active_turn_scoped
}
}
transition ResolveSystemContextAppendDuplicate {
on input ResolveSystemContextAppend {
trimmed_text_byte_count,
idempotency_key_present,
existing_key_matches,
existing_key_conflicts,
active_turn_scoped
}
guard {
self.lifecycle_phase == Phase::Ready
&& append_is_empty(trimmed_text_byte_count) == false
&& append_is_duplicate(
idempotency_key_present,
existing_key_matches,
existing_key_conflicts)
}
update {}
to Ready
emit SystemContextAppendResolved {
decision: SystemContextAppendDecision::Duplicate,
active_turn_scoped: active_turn_scoped
}
}
transition ResolveSystemContextAppendNew {
on input ResolveSystemContextAppend {
trimmed_text_byte_count,
idempotency_key_present,
existing_key_matches,
existing_key_conflicts,
active_turn_scoped
}
guard {
self.lifecycle_phase == Phase::Ready
&& append_is_empty(trimmed_text_byte_count) == false
&& append_is_new(
idempotency_key_present,
existing_key_matches,
existing_key_conflicts)
}
update {}
to Ready
emit SystemContextAppendResolved {
decision: SystemContextAppendDecision::Staged,
active_turn_scoped: active_turn_scoped
}
}
transition ResolveSystemContextPersistAppendAdmissionAdmit {
on input ResolveSystemContextPersistAppendAdmission {
has_previous,
content_identical,
content_extends_previous,
appended_starts_with_separator,
incoming_is_runtime_context_append
}
guard {
self.lifecycle_phase == Phase::Ready
&& persist_append_is_admissible(
has_previous,
content_identical,
content_extends_previous,
appended_starts_with_separator,
incoming_is_runtime_context_append)
}
update {}
to Ready
emit SystemContextPersistAppendAdmissionResolved {
admission: SystemContextPersistAppendAdmission::Admit
}
}
transition ResolveSystemContextPersistAppendAdmissionReject {
on input ResolveSystemContextPersistAppendAdmission {
has_previous,
content_identical,
content_extends_previous,
appended_starts_with_separator,
incoming_is_runtime_context_append
}
guard {
self.lifecycle_phase == Phase::Ready
&& persist_append_is_admissible(
has_previous,
content_identical,
content_extends_previous,
appended_starts_with_separator,
incoming_is_runtime_context_append) == false
}
update {}
to Ready
emit SystemContextPersistAppendAdmissionResolved {
admission: SystemContextPersistAppendAdmission::Reject
}
}
transition ResolveSystemContextPendingApplyItemRuntimeSteer {
on input ResolveSystemContextPendingApplyItem { source_kind }
guard {
self.lifecycle_phase == Phase::Ready
&& source_kind == SystemContextSource::RuntimeSteer
}
update {}
to Ready
emit SystemContextPendingApplyItemResolved {
promote_to_applied: false,
mark_seen_applied: false,
remove_seen: true
}
}
transition ResolveSystemContextPendingApplyItemNormal {
on input ResolveSystemContextPendingApplyItem { source_kind }
guard {
self.lifecycle_phase == Phase::Ready
&& source_kind == SystemContextSource::Normal
}
update {}
to Ready
emit SystemContextPendingApplyItemResolved {
promote_to_applied: true,
mark_seen_applied: true,
remove_seen: false
}
}
transition ResolveSystemContextSteerCleanupItemRuntimeSteer {
on input ResolveSystemContextSteerCleanupItem { source_kind }
guard {
self.lifecycle_phase == Phase::Ready
&& source_kind == SystemContextSource::RuntimeSteer
}
update {}
to Ready
emit SystemContextSteerCleanupItemResolved { discard: true }
}
transition ResolveSystemContextSteerCleanupItemNormal {
on input ResolveSystemContextSteerCleanupItem { source_kind }
guard {
self.lifecycle_phase == Phase::Ready
&& source_kind == SystemContextSource::Normal
}
update {}
to Ready
emit SystemContextSteerCleanupItemResolved { discard: false }
}
transition RestoreSystemContextSnapshot {
on input RestoreSystemContextSnapshot {
active_keys_have_known_pending_or_seen,
seen_keys_match_known_appends
}
guard {
self.lifecycle_phase == Phase::Ready
&& active_keys_have_known_pending_or_seen
&& seen_keys_match_known_appends
}
update {}
to Ready
emit SystemContextSnapshotRestoreAuthorized
}
transition ResolveRealtimeItemObservedDiscardedAssistant {
on input ResolveRealtimeItemObserved { role, response_discarded }
guard {
self.lifecycle_phase == Phase::Ready
&& role == RealtimeTranscriptRoleKind::Assistant
&& response_discarded
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: false,
observe_skipped: true,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeItemObservedPresent {
on input ResolveRealtimeItemObserved { role, response_discarded }
guard {
self.lifecycle_phase == Phase::Ready
&& (role != RealtimeTranscriptRoleKind::Assistant || response_discarded == false)
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: true,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeItemSkipped {
on input ResolveRealtimeItemSkipped
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: false,
observe_skipped: true,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeUserTranscriptFinalEmpty {
on input ResolveRealtimeUserTranscriptFinal { text_present, segment_empty, segment_matches }
guard {
self.lifecycle_phase == Phase::Ready
&& text_present == false
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: true,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: true,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeUserTranscriptFinalStore {
on input ResolveRealtimeUserTranscriptFinal { text_present, segment_empty, segment_matches }
guard {
self.lifecycle_phase == Phase::Ready
&& text_present
&& segment_empty
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: true,
observe_skipped: false,
write_user_segment: true,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: true,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeUserTranscriptFinalReplayOrConflict {
on input ResolveRealtimeUserTranscriptFinal { text_present, segment_empty, segment_matches }
guard {
self.lifecycle_phase == Phase::Ready
&& text_present
&& segment_empty == false
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: true,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: true,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeAssistantDeltaInvalidOrDuplicate {
on input ResolveRealtimeAssistantDelta {
response_id_valid,
response_discarded,
delta_id_present,
delta_id_seen,
item_has_text,
current_lane,
requested_lane,
response_completed,
text_after_write_present
}
guard {
self.lifecycle_phase == Phase::Ready
&& (response_id_valid == false
|| realtime_delta_is_duplicate(delta_id_present, delta_id_seen))
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: false,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: false
}
}
transition ResolveRealtimeAssistantDeltaDiscarded {
on input ResolveRealtimeAssistantDelta {
response_id_valid,
response_discarded,
delta_id_present,
delta_id_seen,
item_has_text,
current_lane,
requested_lane,
response_completed,
text_after_write_present
}
guard {
self.lifecycle_phase == Phase::Ready
&& response_id_valid
&& response_discarded
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: false,
observe_skipped: true,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeAssistantDeltaLaneConflict {
on input ResolveRealtimeAssistantDelta {
response_id_valid,
response_discarded,
delta_id_present,
delta_id_seen,
item_has_text,
current_lane,
requested_lane,
response_completed,
text_after_write_present
}
guard {
self.lifecycle_phase == Phase::Ready
&& response_id_valid
&& response_discarded == false
&& realtime_delta_is_duplicate(delta_id_present, delta_id_seen) == false
&& realtime_lane_accepts(item_has_text, current_lane, requested_lane) == false
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: true,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: delta_id_present,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeAssistantDeltaAccepted {
on input ResolveRealtimeAssistantDelta {
response_id_valid,
response_discarded,
delta_id_present,
delta_id_seen,
item_has_text,
current_lane,
requested_lane,
response_completed,
text_after_write_present
}
guard {
self.lifecycle_phase == Phase::Ready
&& response_id_valid
&& response_discarded == false
&& realtime_delta_is_duplicate(delta_id_present, delta_id_seen) == false
&& realtime_lane_accepts(item_has_text, current_lane, requested_lane)
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: true,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: true,
replace_assistant_segment: false,
promote_lane: true,
mark_item_ready: realtime_should_mark_ready_after_write(response_completed, text_after_write_present),
record_delta_id: delta_id_present,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeAssistantReplacementInvalid {
on input ResolveRealtimeAssistantTextReplacement {
response_id_valid,
response_discarded,
item_materialized,
item_has_text,
current_lane,
requested_lane,
response_completed,
text_after_replace_present
}
guard {
self.lifecycle_phase == Phase::Ready
&& response_id_valid == false
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: false,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: false
}
}
transition ResolveRealtimeAssistantReplacementDiscarded {
on input ResolveRealtimeAssistantTextReplacement {
response_id_valid,
response_discarded,
item_materialized,
item_has_text,
current_lane,
requested_lane,
response_completed,
text_after_replace_present
}
guard {
self.lifecycle_phase == Phase::Ready
&& response_id_valid
&& response_discarded
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: false,
observe_skipped: true,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeAssistantReplacementLocked {
on input ResolveRealtimeAssistantTextReplacement {
response_id_valid,
response_discarded,
item_materialized,
item_has_text,
current_lane,
requested_lane,
response_completed,
text_after_replace_present
}
guard {
self.lifecycle_phase == Phase::Ready
&& response_id_valid
&& response_discarded == false
&& item_materialized
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: true,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeAssistantReplacementLaneConflict {
on input ResolveRealtimeAssistantTextReplacement {
response_id_valid,
response_discarded,
item_materialized,
item_has_text,
current_lane,
requested_lane,
response_completed,
text_after_replace_present
}
guard {
self.lifecycle_phase == Phase::Ready
&& response_id_valid
&& response_discarded == false
&& item_materialized == false
&& realtime_lane_accepts(item_has_text, current_lane, requested_lane) == false
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: true,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeAssistantReplacementAccepted {
on input ResolveRealtimeAssistantTextReplacement {
response_id_valid,
response_discarded,
item_materialized,
item_has_text,
current_lane,
requested_lane,
response_completed,
text_after_replace_present
}
guard {
self.lifecycle_phase == Phase::Ready
&& response_id_valid
&& response_discarded == false
&& item_materialized == false
&& realtime_lane_accepts(item_has_text, current_lane, requested_lane)
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: true,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: true,
promote_lane: true,
mark_item_ready: realtime_should_mark_ready_after_write(response_completed, text_after_replace_present),
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeAssistantTurnCompletedInvalid {
on input ResolveRealtimeAssistantTurnCompleted { response_id_valid, response_discarded, stop_reason }
guard {
self.lifecycle_phase == Phase::Ready
&& response_id_valid == false
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: false,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: false
}
}
transition ResolveRealtimeAssistantTurnCompletedDiscard {
on input ResolveRealtimeAssistantTurnCompleted { response_id_valid, response_discarded, stop_reason }
guard {
self.lifecycle_phase == Phase::Ready
&& response_id_valid
&& (response_discarded || realtime_stop_reason_discards(stop_reason))
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: false,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: true,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeAssistantTurnCompletedToolUse {
on input ResolveRealtimeAssistantTurnCompleted { response_id_valid, response_discarded, stop_reason }
guard {
self.lifecycle_phase == Phase::Ready
&& response_id_valid
&& response_discarded == false
&& realtime_stop_reason_removes_completion(stop_reason)
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: false,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: true,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: true
}
}
transition ResolveRealtimeAssistantTurnCompletedRecord {
on input ResolveRealtimeAssistantTurnCompleted { response_id_valid, response_discarded, stop_reason }
guard {
self.lifecycle_phase == Phase::Ready
&& response_id_valid
&& response_discarded == false
&& realtime_stop_reason_records_completion(stop_reason)
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: false,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: false,
record_completion: true,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: true,
materialize_ready_items: true
}
}
transition ResolveRealtimeAssistantTurnInterruptedInvalid {
on input ResolveRealtimeAssistantTurnInterrupted { response_id_valid }
guard {
self.lifecycle_phase == Phase::Ready
&& response_id_valid == false
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: false,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: false,
record_completion: false,
discard_response: false,
discard_response_by_lane: false,
mark_response_ready: false,
materialize_ready_items: false
}
}
transition ResolveRealtimeAssistantTurnInterruptedValid {
on input ResolveRealtimeAssistantTurnInterrupted { response_id_valid }
guard {
self.lifecycle_phase == Phase::Ready
&& response_id_valid
}
update {}
to Ready
emit RealtimeTranscriptEventResolved {
observe_item: false,
observe_skipped: false,
write_user_segment: false,
append_assistant_segment: false,
replace_assistant_segment: false,
promote_lane: false,
mark_item_ready: false,
record_delta_id: false,
remove_completion: false,
record_completion: true,
discard_response: false,
discard_response_by_lane: true,
mark_response_ready: true,
materialize_ready_items: true
}
}
transition ResolveRealtimeMaterializeAlreadyDone {
on input ResolveRealtimeMaterializeCandidate {
item_materialized,
predecessor_materialized,
item_skipped,
item_ready,
item_text_present,
role,
response_id_present,
completion_present,
completion_usage_consumed
}
guard {
self.lifecycle_phase == Phase::Ready
&& item_materialized
}
update {}
to Ready
emit RealtimeMaterializeCandidateResolved {
decision: RealtimeTranscriptMaterializeDecision::Wait,
consume_usage: false
}
}
transition ResolveRealtimeMaterializeWaitForPredecessor {
on input ResolveRealtimeMaterializeCandidate {
item_materialized,
predecessor_materialized,
item_skipped,
item_ready,
item_text_present,
role,
response_id_present,
completion_present,
completion_usage_consumed
}
guard {
self.lifecycle_phase == Phase::Ready
&& item_materialized == false
&& predecessor_materialized == false
}
update {}
to Ready
emit RealtimeMaterializeCandidateResolved {
decision: RealtimeTranscriptMaterializeDecision::Wait,
consume_usage: false
}
}
transition ResolveRealtimeMaterializeSkipped {
on input ResolveRealtimeMaterializeCandidate {
item_materialized,
predecessor_materialized,
item_skipped,
item_ready,
item_text_present,
role,
response_id_present,
completion_present,
completion_usage_consumed
}
guard {
self.lifecycle_phase == Phase::Ready
&& item_materialized == false
&& predecessor_materialized
&& item_skipped
}
update {}
to Ready
emit RealtimeMaterializeCandidateResolved {
decision: RealtimeTranscriptMaterializeDecision::MarkSkipped,
consume_usage: false
}
}
transition ResolveRealtimeMaterializeWaitForReadyText {
on input ResolveRealtimeMaterializeCandidate {
item_materialized,
predecessor_materialized,
item_skipped,
item_ready,
item_text_present,
role,
response_id_present,
completion_present,
completion_usage_consumed
}
guard {
self.lifecycle_phase == Phase::Ready
&& item_materialized == false
&& predecessor_materialized
&& item_skipped == false
&& (item_ready == false || item_text_present == false)
}
update {}
to Ready
emit RealtimeMaterializeCandidateResolved {
decision: RealtimeTranscriptMaterializeDecision::Wait,
consume_usage: false
}
}
transition ResolveRealtimeMaterializeUser {
on input ResolveRealtimeMaterializeCandidate {
item_materialized,
predecessor_materialized,
item_skipped,
item_ready,
item_text_present,
role,
response_id_present,
completion_present,
completion_usage_consumed
}
guard {
self.lifecycle_phase == Phase::Ready
&& item_materialized == false
&& predecessor_materialized
&& item_skipped == false
&& item_ready
&& item_text_present
&& role == RealtimeTranscriptRoleKind::User
}
update {}
to Ready
emit RealtimeMaterializeCandidateResolved {
decision: RealtimeTranscriptMaterializeDecision::MaterializeUser,
consume_usage: false
}
}
transition ResolveRealtimeMaterializeAssistant {
on input ResolveRealtimeMaterializeCandidate {
item_materialized,
predecessor_materialized,
item_skipped,
item_ready,
item_text_present,
role,
response_id_present,
completion_present,
completion_usage_consumed
}
guard {
self.lifecycle_phase == Phase::Ready
&& item_materialized == false
&& predecessor_materialized
&& item_skipped == false
&& item_ready
&& item_text_present
&& role == RealtimeTranscriptRoleKind::Assistant
&& response_id_present
&& completion_present
}
update {}
to Ready
emit RealtimeMaterializeCandidateResolved {
decision: RealtimeTranscriptMaterializeDecision::MaterializeAssistant,
consume_usage: completion_usage_consumed == false
}
}
transition ResolveRealtimeMaterializeAssistantMissingCompletion {
on input ResolveRealtimeMaterializeCandidate {
item_materialized,
predecessor_materialized,
item_skipped,
item_ready,
item_text_present,
role,
response_id_present,
completion_present,
completion_usage_consumed
}
guard {
self.lifecycle_phase == Phase::Ready
&& item_materialized == false
&& predecessor_materialized
&& item_skipped == false
&& item_ready
&& item_text_present
&& role == RealtimeTranscriptRoleKind::Assistant
&& (response_id_present == false || completion_present == false)
}
update {}
to Ready
emit RealtimeMaterializeCandidateResolved {
decision: RealtimeTranscriptMaterializeDecision::Wait,
consume_usage: false
}
}
transition AuthorizeRestoreRealtimeTranscriptState {
on input RestoreRealtimeTranscriptState {
item_count,
first_seen_count,
first_seen_unique_count,
every_item_has_order_entry,
every_order_entry_has_item,
all_identity_fields_valid,
all_delta_ids_valid,
all_completion_response_ids_valid,
all_discarded_response_ids_valid,
all_materialized_items_were_ready_or_skipped,
all_assistant_items_have_response_unless_skipped,
all_ready_assistant_items_have_completion_or_are_skipped,
all_materialized_assistant_completions_consumed,
all_completed_assistant_text_items_are_ready_or_materialized_or_skipped,
all_discarded_assistant_items_are_skipped_or_materialized
}
guard {
self.lifecycle_phase == Phase::Ready
&& item_count == first_seen_count
&& first_seen_count == first_seen_unique_count
&& every_item_has_order_entry
&& every_order_entry_has_item
&& all_identity_fields_valid
&& all_delta_ids_valid
&& all_completion_response_ids_valid
&& all_discarded_response_ids_valid
&& all_materialized_items_were_ready_or_skipped
&& all_assistant_items_have_response_unless_skipped
&& all_ready_assistant_items_have_completion_or_are_skipped
&& all_materialized_assistant_completions_consumed
&& all_completed_assistant_text_items_are_ready_or_materialized_or_skipped
&& all_discarded_assistant_items_are_skipped_or_materialized
}
update {}
to Ready
emit RealtimeTranscriptSnapshotRestoreAuthorized
}
transition AuthorizeSessionMetadataPersist {
on input AuthorizeSessionMetadataPersist {
schema_version,
model_present,
}
guard {
self.lifecycle_phase == Phase::Ready
&& schema_version > 0
&& model_present == true
}
update {}
to Ready
emit SessionMetadataPersistAuthorized
}
transition AuthorizeSessionBuildStatePersist {
on input AuthorizeSessionBuildStatePersist {
mob_tool_authority_context_present,
mob_tool_authority_context_generated,
}
guard {
self.lifecycle_phase == Phase::Ready
&& (
mob_tool_authority_context_present == false
|| mob_tool_authority_context_generated == true
)
}
update {}
to Ready
emit SessionBuildStatePersistAuthorized
}
transition RestoreSessionBuildState {
on input RestoreSessionBuildState
guard { self.lifecycle_phase == Phase::Ready }
update {}
to Ready
emit SessionBuildStateRestoreAuthorized
}
transition AuthorizeSystemPromptMutation {
on input AuthorizeSystemPromptMutation {
source,
prompt_present,
prompt_byte_count,
replacing_existing,
}
guard {
self.lifecycle_phase == Phase::Ready
&& (prompt_present == true || prompt_byte_count == 0)
}
update {}
to Ready
emit SystemPromptMutationAuthorized
}
transition ResolvePendingContinuationWithBoundary {
on input ResolvePendingContinuation {
session_tail,
staged_tool_result_count
}
guard {
self.lifecycle_phase == Phase::Ready
&& has_effective_pending_boundary(session_tail, staged_tool_result_count)
}
update {}
to Ready
emit PendingContinuationResolved {
disposition: PendingContinuationDisposition::RunPending
}
}
transition ResolvePendingContinuationWithoutBoundary {
on input ResolvePendingContinuation {
session_tail,
staged_tool_result_count
}
guard {
self.lifecycle_phase == Phase::Ready
&& has_effective_pending_boundary(session_tail, staged_tool_result_count) == false
}
update {}
to Ready
emit PendingContinuationResolved {
disposition: PendingContinuationDisposition::NoPendingBoundary
}
emit PendingContinuationPublicTerminalResolved {
terminal: PendingContinuationPublicTerminal::NoPendingBoundary
}
}
transition AuthorizeSessionResumeOverridesRejectProviderRequiresModel {
on input AuthorizeSessionResumeOverrides {
provider_override_present,
model_override_present,
has_build_only_overrides,
first_turn_phase
}
guard {
self.lifecycle_phase == Phase::Ready
&& resume_reject_provider_requires_model(
provider_override_present,
model_override_present
)
}
update {}
to Ready
emit SessionResumeOverridesRejected {
reason: ResumeOverrideRejection::ProviderRequiresModel
}
}
transition AuthorizeSessionResumeOverridesRejectBuildOnlyAfterFirstTurn {
on input AuthorizeSessionResumeOverrides {
provider_override_present,
model_override_present,
has_build_only_overrides,
first_turn_phase
}
guard {
self.lifecycle_phase == Phase::Ready
&& resume_reject_provider_requires_model(
provider_override_present,
model_override_present
) == false
&& resume_reject_build_only_after_first_turn(
has_build_only_overrides,
first_turn_phase
)
}
update {}
to Ready
emit SessionResumeOverridesRejected {
reason: ResumeOverrideRejection::BuildOnlyAfterFirstTurn
}
}
transition AuthorizeSessionResumeOverridesAcceptRecomputeProvider {
on input AuthorizeSessionResumeOverrides {
provider_override_present,
model_override_present,
has_build_only_overrides,
first_turn_phase
}
guard {
self.lifecycle_phase == Phase::Ready
&& resume_overrides_admissible(
provider_override_present,
model_override_present,
has_build_only_overrides,
first_turn_phase
)
&& resume_provider_recompute_from_model(
model_override_present,
provider_override_present
)
}
update {}
to Ready
emit SessionResumeOverridesAuthorized {
provider_selection: ResumeProviderSelection::RecomputeFromModel,
self_hosted_selection: ResumeSelfHostedSelection::Clear,
provider_overridden: true
}
}
transition AuthorizeSessionResumeOverridesAcceptUseOverride {
on input AuthorizeSessionResumeOverrides {
provider_override_present,
model_override_present,
has_build_only_overrides,
first_turn_phase
}
guard {
self.lifecycle_phase == Phase::Ready
&& resume_overrides_admissible(
provider_override_present,
model_override_present,
has_build_only_overrides,
first_turn_phase
)
&& resume_provider_recompute_from_model(
model_override_present,
provider_override_present
) == false
&& provider_override_present
}
update {}
to Ready
emit SessionResumeOverridesAuthorized {
provider_selection: ResumeProviderSelection::UseOverride,
self_hosted_selection: ResumeSelfHostedSelection::Clear,
provider_overridden: true
}
}
transition AuthorizeSessionResumeOverridesAcceptRetainStored {
on input AuthorizeSessionResumeOverrides {
provider_override_present,
model_override_present,
has_build_only_overrides,
first_turn_phase
}
guard {
self.lifecycle_phase == Phase::Ready
&& resume_overrides_admissible(
provider_override_present,
model_override_present,
has_build_only_overrides,
first_turn_phase
)
&& resume_provider_recompute_from_model(
model_override_present,
provider_override_present
) == false
&& provider_override_present == false
}
update {}
to Ready
emit SessionResumeOverridesAuthorized {
provider_selection: ResumeProviderSelection::UseStored,
self_hosted_selection: ResumeSelfHostedSelection::Retain,
provider_overridden: false
}
}
transition ClassifyLiveSessionAuthorityLive {
on input ClassifyLiveSessionAuthority {
stored_transcript_diverged,
live_has_uncommitted_transcript,
runtime_system_context_diverged,
stored_is_archived
}
guard {
self.lifecycle_phase == Phase::Ready
&& stored_transcript_diverged == false
&& live_has_uncommitted_transcript == false
&& runtime_system_context_diverged == false
&& stored_is_archived == false
}
update {}
to Ready
emit LiveSessionAuthorityClassified {
authority: LiveSessionAuthorityKind::LiveAuthoritative,
reason: LiveSessionAuthorityReason::StoredArchived
}
}
transition ClassifyLiveSessionAuthorityDurableArchived {
on input ClassifyLiveSessionAuthority {
stored_transcript_diverged,
live_has_uncommitted_transcript,
runtime_system_context_diverged,
stored_is_archived
}
guard {
self.lifecycle_phase == Phase::Ready
&& stored_is_archived == true
}
update {}
to Ready
emit LiveSessionAuthorityClassified {
authority: LiveSessionAuthorityKind::DurableAuthoritative,
reason: LiveSessionAuthorityReason::StoredArchived
}
}
transition ClassifyLiveSessionAuthorityDurableUncommitted {
on input ClassifyLiveSessionAuthority {
stored_transcript_diverged,
live_has_uncommitted_transcript,
runtime_system_context_diverged,
stored_is_archived
}
guard {
self.lifecycle_phase == Phase::Ready
&& stored_is_archived == false
&& live_has_uncommitted_transcript == true
}
update {}
to Ready
emit LiveSessionAuthorityClassified {
authority: LiveSessionAuthorityKind::DurableAuthoritative,
reason: LiveSessionAuthorityReason::LiveUncommittedTranscript
}
}
transition ClassifyLiveSessionAuthorityDurableSystemContext {
on input ClassifyLiveSessionAuthority {
stored_transcript_diverged,
live_has_uncommitted_transcript,
runtime_system_context_diverged,
stored_is_archived
}
guard {
self.lifecycle_phase == Phase::Ready
&& stored_is_archived == false
&& live_has_uncommitted_transcript == false
&& runtime_system_context_diverged == true
}
update {}
to Ready
emit LiveSessionAuthorityClassified {
authority: LiveSessionAuthorityKind::DurableAuthoritative,
reason: LiveSessionAuthorityReason::RuntimeSystemContextDiverged
}
}
transition ClassifyLiveSessionAuthorityDurableRevision {
on input ClassifyLiveSessionAuthority {
stored_transcript_diverged,
live_has_uncommitted_transcript,
runtime_system_context_diverged,
stored_is_archived
}
guard {
self.lifecycle_phase == Phase::Ready
&& stored_is_archived == false
&& live_has_uncommitted_transcript == false
&& runtime_system_context_diverged == false
&& stored_transcript_diverged == true
}
update {}
to Ready
emit LiveSessionAuthorityClassified {
authority: LiveSessionAuthorityKind::DurableAuthoritative,
reason: LiveSessionAuthorityReason::StoredTranscriptRevisionDiverged
}
}
transition RecoverSessionFromStoreAuthorized {
on input RecoverSessionFromStore {
session_id,
has_metadata,
has_build_state,
runtime_projection_quarantined
}
guard {
self.lifecycle_phase == Phase::Ready
&& store_projection_can_recover_authority(
has_metadata,
has_build_state,
runtime_projection_quarantined
)
}
update {}
to Ready
emit SessionStoreRecoverySourceResolved { recoverable: true }
}
transition RecoverSessionFromStoreUnrecoverable {
on input RecoverSessionFromStore {
session_id,
has_metadata,
has_build_state,
runtime_projection_quarantined
}
guard {
self.lifecycle_phase == Phase::Ready
&& store_projection_can_recover_authority(
has_metadata,
has_build_state,
runtime_projection_quarantined
) == false
}
update {}
to Ready
emit SessionStoreRecoverySourceResolved { recoverable: false }
}
transition ResolveRuntimeProjectionRollbackRebuild {
on input ResolveRuntimeProjectionRollback {
session_id,
row_continues_authority,
row_is_runtime_checkpoint
}
guard {
self.lifecycle_phase == Phase::Ready
&& row_continues_authority == true
&& row_is_runtime_checkpoint == true
}
update {}
to Ready
emit RuntimeProjectionRollbackResolved {
disposition: RuntimeProjectionRollbackDisposition::RebuildToAuthority
}
}
transition ResolveRuntimeProjectionRollbackReject {
on input ResolveRuntimeProjectionRollback {
session_id,
row_continues_authority,
row_is_runtime_checkpoint
}
guard {
self.lifecycle_phase == Phase::Ready
&& (row_continues_authority == false
|| row_is_runtime_checkpoint == false)
}
update {}
to Ready
emit RuntimeProjectionRollbackResolved {
disposition: RuntimeProjectionRollbackDisposition::RejectDivergent
}
}
transition ApplyPendingToolResults {
on input ApplyPendingToolResults {
session_id,
result_count
}
guard { self.lifecycle_phase == Phase::Ready }
update {}
to Ready
emit SessionToolResultsApplied {
session_id: session_id,
applied_count: result_count
}
}
transition TranscriptEditFork {
on input TranscriptEdit {
session_id,
fork_or_rewrite_directive
}
guard {
self.lifecycle_phase == Phase::Ready
&& fork_or_rewrite_directive == TranscriptEditKind::Fork
}
update {}
to Ready
emit TranscriptRewriteCommitted {
kind: TranscriptEditKind::Fork,
success: true
}
}
transition TranscriptEditRewrite {
on input TranscriptEdit {
session_id,
fork_or_rewrite_directive
}
guard {
self.lifecycle_phase == Phase::Ready
&& fork_or_rewrite_directive == TranscriptEditKind::Rewrite
}
update {}
to Ready
emit TranscriptRewriteCommitted {
kind: TranscriptEditKind::Rewrite,
success: true
}
}
transition RecoverSessionLifecycleTerminal {
on input RecoverSessionLifecycleTerminal { session_id, terminal }
guard {
self.lifecycle_phase == Phase::Ready
&& (terminal == SessionDocumentLifecycle::Active
|| terminal == SessionDocumentLifecycle::Archived)
}
update {
self.session_lifecycle_terminal.insert(session_id, terminal);
}
to Ready
emit SessionLifecycleTerminalRecovered
}
transition ArchiveSessionDocumentActive {
on input ArchiveSessionDocument {
session_id,
runtime_backed,
durable_snapshot_present,
runtime_session_registered
}
guard {
self.lifecycle_phase == Phase::Ready
&& self.session_lifecycle_terminal.get_cloned(session_id).get("value")
== SessionDocumentLifecycle::Active
}
update {
self.session_lifecycle_terminal
.insert(session_id, SessionDocumentLifecycle::Archived);
}
to Ready
emit SessionArchiveResolved {
disposition: SessionArchiveDisposition::Archive,
write_document: durable_snapshot_present,
retire_runtime: archive_should_retire_runtime(
runtime_backed,
durable_snapshot_present,
runtime_session_registered)
}
}
transition ArchiveSessionDocumentAlreadyArchived {
on input ArchiveSessionDocument {
session_id,
runtime_backed,
durable_snapshot_present,
runtime_session_registered
}
guard {
self.lifecycle_phase == Phase::Ready
&& self.session_lifecycle_terminal.get_cloned(session_id).get("value")
== SessionDocumentLifecycle::Archived
}
update {}
to Ready
emit SessionArchiveResolved {
disposition: SessionArchiveDisposition::AlreadyArchived,
write_document: false,
retire_runtime: false
}
}
}
}