pub struct FlowStack { /* private fields */ }Expand description
The main flow plus its digressions, with push-on-trigger and resume-on-completion.
While a digression is active, governance — tool admission, postures and
grounds, explain() — delegates to the active layer, and the main
flow’s marking is untouched, so Resume::Previous resumes exactly where
it left off. Driven by State and guards: model-free and deterministic.
A digression stays the active layer through the turn on which it
completes, so that turn’s projection carries its closing instruction (the
terminal stage’s posture — “hand off to a human now”), and its
Resume policy applies at the next turn boundary. Without that, a
digression that completes on its entry turn would never be seen at all.
Implementations§
Source§impl FlowStack
impl FlowStack
Sourcepub fn new(main: CompiledFlow, mode: Enforcement) -> Self
pub fn new(main: CompiledFlow, mode: Enforcement) -> Self
A stack over a compiled main flow with no digressions yet.
Sourcepub fn from_monitor(main: FlowMonitor) -> Self
pub fn from_monitor(main: FlowMonitor) -> Self
A stack whose main layer is an existing monitor (keeps its on_enter
actions and mode). This is how a bare governed flow becomes the one
governance object the control plane drives.
Sourcepub fn with_overlay(self, overlay: Overlay) -> Self
pub fn with_overlay(self, overlay: Overlay) -> Self
Add a digression.
Sourcepub fn with_overlays(self, overlays: impl IntoIterator<Item = Overlay>) -> Self
pub fn with_overlays(self, overlays: impl IntoIterator<Item = Overlay>) -> Self
Add several digressions, in trigger-priority order.
Sourcepub fn with_repair(self, step: impl Into<String>, policy: RepairPolicy) -> Self
pub fn with_repair(self, step: impl Into<String>, policy: RepairPolicy) -> Self
Attach a repair policy to a main-flow step.
Sourcepub fn with_repairs(
self,
policies: impl IntoIterator<Item = (String, RepairPolicy)>,
) -> Self
pub fn with_repairs( self, policies: impl IntoIterator<Item = (String, RepairPolicy)>, ) -> Self
Attach repair policies keyed by main-flow step.
Sourcepub fn with_correction(
self,
slot: impl Into<String>,
clear: impl IntoIterator<Item = String>,
) -> Self
pub fn with_correction( self, slot: impl Into<String>, clear: impl IntoIterator<Item = String>, ) -> Self
Watch slot for corrections: when its value changes from one captured
value to another, correction_flag(slot) is raised for that turn
and clear keys are removed from state.
Raising the flag does nothing by itself. The main flow reacts through
a Constraint::Reset gated on it, which
un-latches the stages downstream of the slot so they run again with
the corrected value. A Conversation lowers exactly that for every
collected slot, clearing the confirmation of any commit stage it
re-opens.
Sourcepub fn with_corrections(
self,
corrections: impl IntoIterator<Item = (String, Vec<String>)>,
) -> Self
pub fn with_corrections( self, corrections: impl IntoIterator<Item = (String, Vec<String>)>, ) -> Self
Watch several slots; see with_correction.
Sourcepub fn correction_policies(&self) -> &BTreeMap<String, Vec<String>>
pub fn correction_policies(&self) -> &BTreeMap<String, Vec<String>>
The watched slots and the keys each correction clears.
Sourcepub fn with_verbatim(
self,
step: impl Into<String>,
text: impl Into<String>,
) -> Self
pub fn with_verbatim( self, step: impl Into<String>, text: impl Into<String>, ) -> Self
Require step to say text word for word; see
verbatim. The stack publishes the requirement
while the step is active. Its completion guard must also require
verbatim_flag(step), which a
Conversation lowers for you.
Sourcepub fn with_verbatims(
self,
texts: impl IntoIterator<Item = (String, String)>,
) -> Self
pub fn with_verbatims( self, texts: impl IntoIterator<Item = (String, String)>, ) -> Self
Verbatim requirements keyed by step.
Sourcepub fn verbatim_policies(&self) -> &BTreeMap<String, String>
pub fn verbatim_policies(&self) -> &BTreeMap<String, String>
The verbatim requirements keyed by step.
Sourcepub fn with_timing(self, step: impl Into<String>, timing: VoiceTiming) -> Self
pub fn with_timing(self, step: impl Into<String>, timing: VoiceTiming) -> Self
Attach voice timing to a step (main flow or digression).
Sourcepub fn with_timings(
self,
timings: impl IntoIterator<Item = (String, VoiceTiming)>,
) -> Self
pub fn with_timings( self, timings: impl IntoIterator<Item = (String, VoiceTiming)>, ) -> Self
Attach voice timing keyed by step.
Sourcepub fn timing_policies(&self) -> &BTreeMap<String, VoiceTiming>
pub fn timing_policies(&self) -> &BTreeMap<String, VoiceTiming>
The voice timing keyed by step.
Sourcepub fn active_timing(&self, state: &State) -> VoiceTiming
pub fn active_timing(&self, state: &State) -> VoiceTiming
The merged timing of the steps active right now in the driving layer (empty when none of them has timing, or the conversation is over).
Sourcepub fn publish_timing(&self, state: &State)
pub fn publish_timing(&self, state: &State)
Publish active_timing to
VOICE_TIMING_KEY in state, where the runtime’s audio path, timers
and turn lifecycle read it. Writes only on change; removes the key
when no timing applies. The stack calls this itself after every turn
and tool call; call it once when installing the stack.
Wrap in a SharedFlowStack for shared ownership between the control
lane (which advances it) and runtime accessors (which snapshot it).
Sourcepub fn mode(&self) -> Enforcement
pub fn mode(&self) -> Enforcement
The enforcement mode (shared by every layer).
Sourcepub fn overlays(&self) -> &[Overlay]
pub fn overlays(&self) -> &[Overlay]
The digressions this stack can enter, in trigger-priority order.
Sourcepub fn overlays_mut(&mut self) -> &mut [Overlay]
pub fn overlays_mut(&mut self) -> &mut [Overlay]
Mutable access to the digressions, for connect-time merges.
Sourcepub fn repair_policies(&self) -> &BTreeMap<String, RepairPolicy>
pub fn repair_policies(&self) -> &BTreeMap<String, RepairPolicy>
The repair policies keyed by main-flow step.
Sourcepub fn main(&self) -> &FlowMonitor
pub fn main(&self) -> &FlowMonitor
The main flow’s monitor, whether or not it is currently driving.
Sourcepub fn current(&self) -> &FlowMonitor
pub fn current(&self) -> &FlowMonitor
The monitor currently driving — the active digression if any, else the main flow.
Sourcepub fn active_overlay(&self) -> Option<&str>
pub fn active_overlay(&self) -> Option<&str>
The name of the driving digression, if one is suspending the main flow.
Sourcepub fn overlay_path(&self) -> Vec<&str>
pub fn overlay_path(&self) -> Vec<&str>
Every active digression, outermost first: a digression can itself be interrupted by another, which then drives until it completes.
Sourcepub fn is_complete(&self) -> bool
pub fn is_complete(&self) -> bool
Whether the conversation is finished (main complete, or a Terminate
digression ran).
Sourcepub fn is_terminated(&self) -> bool
pub fn is_terminated(&self) -> bool
Whether a Terminate digression ended the conversation. From then on
the stack governs nothing: no active steps or postures, every tool
denied. The runtime does not close the session by itself; the
application reads this (or TERMINATED_STATE_KEY) and hangs up.
Sourcepub fn on_interrupted(&mut self, state: &State)
pub fn on_interrupted(&mut self, state: &State)
Count a barge-in against every active main step and escalate those
whose policy’s escalate_after_interruptions is reached. Called by
the control plane when the user interrupts the model.
Sourcepub fn on_tool_failed(&mut self, state: &State)
pub fn on_tool_failed(&mut self, state: &State)
Count a failed (or timed-out) tool call against every active main step
and escalate those whose policy’s escalate_after_tool_failures is
reached.
Sourcepub fn on_turn(&mut self, state: &State)
pub fn on_turn(&mut self, state: &State)
Advance one turn.
A digression that completed on the previous turn has had its closing turn projected; its resume policy applies now, and the turn then proceeds as if the main flow had been driving all along (a new digression may trigger, or the main flow advances). Otherwise: advance the active digression, enter a triggered one (suspending the main flow), or advance the main flow.
Sourcepub fn on_tool_ok(&mut self, tool: &str, state: &State)
pub fn on_tool_ok(&mut self, tool: &str, state: &State)
Record a successful tool call against the active layer. A no-op once the
conversation has been terminated: nothing is governing, so there is no
marking for the call to advance. (In Enforce the call is denied before
it runs; in Observe it runs but must not move a flow that has ended.)
A tool can itself fire a reset (reset(..).when(called_ok(..))), so the
main layer sheds the repair signals of whatever that un-latches, exactly
as the main layer does at a turn boundary. Repair
is tracked for the main flow only, so a digression just delegates.
Sourcepub fn observe_tool(&mut self, tool: &str, ok: bool, state: &State)
pub fn observe_tool(&mut self, tool: &str, ok: bool, state: &State)
Observe a tool call for conformance against the active layer (see
FlowMonitor::observe_tool).
After termination nothing is advanced, but in Observe the call is
still recorded as a deviation: a tool used after the conversation ended
is exactly what that mode exists to catch, and the monitor cannot see it
for itself because the denial is the stack’s, not the flow’s.
Sourcepub fn admits_tool(&self, tool: &str, state: &State) -> Result<(), String>
pub fn admits_tool(&self, tool: &str, state: &State) -> Result<(), String>
Whether tool is admitted right now (delegates to the active layer).
Every tool is denied once the conversation has been terminated.
Sourcepub fn explain(&self, state: &State) -> FlowExplanation
pub fn explain(&self, state: &State) -> FlowExplanation
Explain the active layer’s control-plane state. After termination:
nothing active, nothing admitted, every tool blocked with the reason —
the conversation is over, so it is waiting for nothing. To ask instead
what it never finished, read main(): its marking and
unmet_requirements() are kept intact for exactly that audit.
Sourcepub fn marking(&self) -> &Marking
pub fn marking(&self) -> &Marking
The active layer’s marking (the last driving layer’s, after termination — kept for audit).
Sourcepub fn active_steps(&self, state: &State) -> Vec<&Step>
pub fn active_steps(&self, state: &State) -> Vec<&Step>
Steps of the active layer that are eligible but not yet done. Empty after termination.
Sourcepub fn active_postures(&self, state: &State) -> Vec<String>
pub fn active_postures(&self, state: &State) -> Vec<String>
Postures to project this turn: the active layer’s active steps’, or —
on the turn a digression completes — its closing steps’ (see
FlowMonitor::closing_postures). Empty after termination.
Sourcepub fn active_grounds(&self, state: &State) -> Vec<String>
pub fn active_grounds(&self, state: &State) -> Vec<String>
Grounding lines to project this turn, chosen like
active_postures.
Sourcepub fn unmet_requirements(&self) -> Vec<String>
pub fn unmet_requirements(&self) -> Vec<String>
The active layer’s unmet requirements. Empty after termination.
Sourcepub fn take_newly_active(&mut self, state: &State) -> Vec<String>
pub fn take_newly_active(&mut self, state: &State) -> Vec<String>
Steps of the active layer that became active since the last call.
Sourcepub fn enter_action(&self, step: &str) -> Option<&StepAction>
pub fn enter_action(&self, step: &str) -> Option<&StepAction>
The on_enter action registered for a step of the active layer.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for FlowStack
impl !RefUnwindSafe for FlowStack
impl Send for FlowStack
impl Sync for FlowStack
impl Unpin for FlowStack
impl !UnwindSafe for FlowStack
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request§impl<L> LayerExt<L> for L
impl<L> LayerExt<L> for L
§fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
Layered].