pub struct TransitionGate {
pub require_modifications: bool,
pub message: Option<String>,
pub region: Option<String>,
pub tools: Vec<String>,
pub max_attempts: Option<usize>,
pub require_region_updated: Option<String>,
pub require_regions: Vec<String>,
pub require_no_open_items: Option<String>,
}Expand description
Preconditions an edge imposes on the stage it leaves, checked once the edge
has been chosen but before its transform runs. A gate that isn’t satisfied
re-runs the stage with a [System] nudge instead of transitioning.
The motivating case: an agent that reads and reasons about the
codebase entirely through shell and reaches the review stage without ever
having called a file-writing tool, producing a run with no output at all.
Fields§
§require_modifications: boolRequire at least one successful file-modifying tool call in the stage being left.
message: Option<String>Nudge injected when the gate blocks. A default explaining the framework’s change tracking is generated when absent.
region: Option<String>Region whose non-emptiness also satisfies the gate. Per-stage tool-call counters reset on stage entry and are not restored when a run resumes after a daemon restart, but context regions are - so pointing the gate at the region the write tools are routed into keeps a resumed run honest.
tools: Vec<String>Tool names counted as modifying beyond the built-in write_file /
edit_file - for agents whose writes go through MCP or script tools.
max_attempts: Option<usize>How many times the stage is re-run before the gate gives up and lets the
transition through (with a warning). Defaults to
DEFAULT_GATE_ATTEMPTS.
require_region_updated: Option<String>Region that must have changed during this stage, not merely be present.
Every other gate asks whether something exists. That cannot express a revise loop: a stage sent back to redo its work satisfies a presence check by re-emitting what it already wrote, so a reviewer’s rejection can be answered with the same plan and the loop spins until it runs out of revisits. Measured, a plan that overrode a documented definition was re-confirmed by a verify stage and the run ended confidently wrong.
Compared against the region’s content as it stood when the stage was entered, so “changed” means changed by this pass.
require_regions: Vec<String>Regions that must all hold content before this edge may be taken.
Conjunctive, and that is the point. Self::region reads as though it
says this and does not: it is one of several alternative ways to
satisfy Self::require_modifications, so
{ require_modifications = true, region = "plan" } is met by writing
any file anywhere while plan stays empty (#371). That is the right
shape for what region is for - a restart-durable stand-in for
per-stage counters, which do not survive a daemon restart - and the
wrong shape for “this stage does not leave without writing X”. This key
is the second thing, ANDed with every other condition on the gate.
A name the window does not hold passes with a warning rather than
blocking: lev validate refuses a gate naming a region no stage
declares, so reaching that at runtime means a layout moved underneath
the edge, and stranding a run over it would be worse than the missing
check. Saying nothing is what made the old behaviour hard to find.
require_no_open_items: Option<String>Checklist region that must have no open items before this edge is taken.
The other gates ask whether a region has content, which cannot tell a list of three unfinished items from a list of three finished ones. This is the gate a checklist exists for: it makes “did you actually finish” a mechanical question rather than one the model answers about itself.
Trait Implementations§
Source§impl Clone for TransitionGate
impl Clone for TransitionGate
Source§fn clone(&self) -> TransitionGate
fn clone(&self) -> TransitionGate
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for TransitionGate
impl Debug for TransitionGate
Source§impl Default for TransitionGate
impl Default for TransitionGate
Source§fn default() -> TransitionGate
fn default() -> TransitionGate
Source§impl<'de> Deserialize<'de> for TransitionGate
impl<'de> Deserialize<'de> for TransitionGate
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for TransitionGate
Source§impl PartialEq for TransitionGate
impl PartialEq for TransitionGate
Source§impl Serialize for TransitionGate
impl Serialize for TransitionGate
impl StructuralPartialEq for TransitionGate
Auto Trait Implementations§
impl Freeze for TransitionGate
impl RefUnwindSafe for TransitionGate
impl Send for TransitionGate
impl Sync for TransitionGate
impl Unpin for TransitionGate
impl UnsafeUnpin for TransitionGate
impl UnwindSafe for TransitionGate
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.