mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-07 08:27:12 +00:00
Rename ManagerLoopHandler to SubWorkflowHandler
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f45c1b1e2d
commit
7002f0638a
5 changed files with 19 additions and 19 deletions
|
|
@ -7,7 +7,7 @@ A DOT-based pipeline runner for multi-stage AI workflows. Define workflows as Gr
|
|||
- **Graph** -- A directed graph parsed from DOT syntax containing nodes, edges, and attributes. The graph carries a `goal` describing the pipeline's purpose.
|
||||
- **Node** -- A workflow step. Graphviz shapes map to handler types (e.g., `Mdiamond` = start, `Msquare` = exit, `box` = codergen/LLM, `diamond` = conditional, `hexagon` = human gate, `component` = parallel).
|
||||
- **Edge** -- A connection between nodes with optional `condition`, `label`, `weight`, and `fidelity` attributes that control routing.
|
||||
- **Handler** -- An async trait implementation that executes a node and returns an `Outcome`. Built-in handlers include `StartHandler`, `ExitHandler`, `CodergenHandler`, `ConditionalHandler`, `WaitHumanHandler`, `ParallelHandler`, `FanInHandler`, `ScriptHandler`, and `ManagerLoopHandler`.
|
||||
- **Handler** -- An async trait implementation that executes a node and returns an `Outcome`. Built-in handlers include `StartHandler`, `ExitHandler`, `CodergenHandler`, `ConditionalHandler`, `WaitHumanHandler`, `ParallelHandler`, `FanInHandler`, `ScriptHandler`, and `SubWorkflowHandler`.
|
||||
- **Outcome** -- The result of executing a handler, carrying a `StageStatus` (Success, Fail, PartialSuccess, Retry, Skipped), optional routing hints (`preferred_label`, `suggested_next_ids`), and context updates.
|
||||
- **Context** -- A thread-safe key-value store shared across pipeline stages, supporting snapshots and isolated cloning for parallel branches.
|
||||
- **Interviewer** -- A trait for human-in-the-loop interactions. Implementations include `AutoApproveInterviewer`, `QueueInterviewer`, `CallbackInterviewer`, `ConsoleInterviewer`, and `RecordingInterviewer`.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use crate::pipeline::prepare_pipeline;
|
|||
use super::{EngineServices, Handler};
|
||||
|
||||
/// Orchestrates a child pipeline engine, polling for completion or stop conditions.
|
||||
pub struct ManagerLoopHandler;
|
||||
pub struct SubWorkflowHandler;
|
||||
|
||||
/// Parse a duration string like "45s", "200ms", "5m" into a Duration.
|
||||
/// Falls back to 45 seconds on parse failure.
|
||||
|
|
@ -69,7 +69,7 @@ fn context_diff(
|
|||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Handler for ManagerLoopHandler {
|
||||
impl Handler for SubWorkflowHandler {
|
||||
async fn execute(
|
||||
&self,
|
||||
node: &Node,
|
||||
|
|
@ -247,7 +247,7 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
async fn child_pipeline_succeeds() {
|
||||
let handler = ManagerLoopHandler;
|
||||
let handler = SubWorkflowHandler;
|
||||
let mut node = Node::new("manager");
|
||||
node.attrs.insert(
|
||||
"stack.child_dot_source".to_string(),
|
||||
|
|
@ -274,7 +274,7 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
async fn no_dot_source_fails() {
|
||||
let handler = ManagerLoopHandler;
|
||||
let handler = SubWorkflowHandler;
|
||||
let mut node = Node::new("manager");
|
||||
node.attrs
|
||||
.insert("manager.max_cycles".to_string(), AttrValue::Integer(10));
|
||||
|
|
@ -301,7 +301,7 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
async fn invalid_dot_source_fails() {
|
||||
let handler = ManagerLoopHandler;
|
||||
let handler = SubWorkflowHandler;
|
||||
let mut node = Node::new("manager");
|
||||
node.attrs.insert(
|
||||
"stack.child_dot_source".to_string(),
|
||||
|
|
@ -370,7 +370,7 @@ mod tests {
|
|||
git_state: std::sync::RwLock::new(None),
|
||||
};
|
||||
|
||||
let handler = ManagerLoopHandler;
|
||||
let handler = SubWorkflowHandler;
|
||||
let mut node = Node::new("manager");
|
||||
// Child pipeline with a "work" node (default handler = ContextEchoHandler)
|
||||
node.attrs.insert(
|
||||
|
|
@ -415,7 +415,7 @@ mod tests {
|
|||
let dot_path = dir.path().join("child.dot");
|
||||
std::fs::write(&dot_path, child_dot_succeeds()).unwrap();
|
||||
|
||||
let handler = ManagerLoopHandler;
|
||||
let handler = SubWorkflowHandler;
|
||||
let mut node = Node::new("manager");
|
||||
node.attrs.insert(
|
||||
"stack.child_dotfile".to_string(),
|
||||
|
|
@ -477,7 +477,7 @@ mod tests {
|
|||
git_state: std::sync::RwLock::new(None),
|
||||
};
|
||||
|
||||
let handler = ManagerLoopHandler;
|
||||
let handler = SubWorkflowHandler;
|
||||
let mut node = Node::new("manager");
|
||||
node.attrs.insert(
|
||||
"stack.child_dot_source".to_string(),
|
||||
|
|
@ -540,7 +540,7 @@ mod tests {
|
|||
git_state: std::sync::RwLock::new(None),
|
||||
};
|
||||
|
||||
let handler = ManagerLoopHandler;
|
||||
let handler = SubWorkflowHandler;
|
||||
let mut node = Node::new("manager");
|
||||
node.attrs.insert(
|
||||
"stack.child_dot_source".to_string(),
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ pub fn default_registry(
|
|||
);
|
||||
registry.register(
|
||||
"stack.manager_loop",
|
||||
Box::new(manager_loop::ManagerLoopHandler),
|
||||
Box::new(manager_loop::SubWorkflowHandler),
|
||||
);
|
||||
registry
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use arc_workflows::handler::codergen::{CodergenBackend, CodergenHandler, Coderge
|
|||
use arc_workflows::handler::conditional::ConditionalHandler;
|
||||
use arc_workflows::handler::default_registry;
|
||||
use arc_workflows::handler::exit::ExitHandler;
|
||||
use arc_workflows::handler::manager_loop::ManagerLoopHandler;
|
||||
use arc_workflows::handler::manager_loop::SubWorkflowHandler;
|
||||
use arc_workflows::handler::script::ScriptHandler;
|
||||
use arc_workflows::handler::start::StartHandler;
|
||||
use arc_workflows::handler::wait_human::WaitHumanHandler;
|
||||
|
|
@ -1255,7 +1255,7 @@ fn make_full_registry(interviewer: Arc<dyn Interviewer>) -> HandlerRegistry {
|
|||
registry.register("wait.human", Box::new(WaitHumanHandler::new(interviewer)));
|
||||
registry.register(
|
||||
"stack.manager_loop",
|
||||
Box::new(ManagerLoopHandler),
|
||||
Box::new(SubWorkflowHandler),
|
||||
);
|
||||
registry
|
||||
}
|
||||
|
|
@ -2668,7 +2668,7 @@ async fn manager_loop_stop_condition_satisfied_e2e() {
|
|||
registry.register("start", Box::new(StartHandler));
|
||||
registry.register("exit", Box::new(ExitHandler));
|
||||
registry.register("done_setter", Box::new(DoneSetterHandler));
|
||||
registry.register("stack.manager_loop", Box::new(ManagerLoopHandler));
|
||||
registry.register("stack.manager_loop", Box::new(SubWorkflowHandler));
|
||||
let engine = PipelineEngine::new(registry, Arc::new(EventEmitter::new()), local_env());
|
||||
let config = RunConfig {
|
||||
logs_root: dir.path().to_path_buf(),
|
||||
|
|
@ -2742,7 +2742,7 @@ async fn manager_loop_max_cycles_exceeded_e2e() {
|
|||
let mut registry = HandlerRegistry::new(Box::new(SlowHandler));
|
||||
registry.register("start", Box::new(StartHandler));
|
||||
registry.register("exit", Box::new(ExitHandler));
|
||||
registry.register("stack.manager_loop", Box::new(ManagerLoopHandler));
|
||||
registry.register("stack.manager_loop", Box::new(SubWorkflowHandler));
|
||||
let engine = PipelineEngine::new(registry, Arc::new(EventEmitter::new()), local_env());
|
||||
let config = RunConfig {
|
||||
logs_root: dir.path().to_path_buf(),
|
||||
|
|
@ -3323,7 +3323,7 @@ async fn manager_loop_runs_child_engine_e2e() {
|
|||
let mut registry = HandlerRegistry::new(Box::new(StartHandler));
|
||||
registry.register("start", Box::new(StartHandler));
|
||||
registry.register("exit", Box::new(ExitHandler));
|
||||
registry.register("stack.manager_loop", Box::new(ManagerLoopHandler));
|
||||
registry.register("stack.manager_loop", Box::new(SubWorkflowHandler));
|
||||
|
||||
let engine = PipelineEngine::new(registry, Arc::new(EventEmitter::new()), local_env());
|
||||
let config = RunConfig {
|
||||
|
|
@ -3456,7 +3456,7 @@ async fn manager_loop_context_flows_e2e() {
|
|||
registry.register("start", Box::new(StartHandler));
|
||||
registry.register("exit", Box::new(ExitHandler));
|
||||
registry.register("setter", Box::new(SetterHandler));
|
||||
registry.register("stack.manager_loop", Box::new(ManagerLoopHandler));
|
||||
registry.register("stack.manager_loop", Box::new(SubWorkflowHandler));
|
||||
|
||||
let engine = PipelineEngine::new(registry, Arc::new(EventEmitter::new()), local_env());
|
||||
let config = RunConfig {
|
||||
|
|
@ -3527,7 +3527,7 @@ async fn manager_loop_child_dotfile_e2e() {
|
|||
let mut registry = HandlerRegistry::new(Box::new(StartHandler));
|
||||
registry.register("start", Box::new(StartHandler));
|
||||
registry.register("exit", Box::new(ExitHandler));
|
||||
registry.register("stack.manager_loop", Box::new(ManagerLoopHandler));
|
||||
registry.register("stack.manager_loop", Box::new(SubWorkflowHandler));
|
||||
|
||||
let engine = PipelineEngine::new(registry, Arc::new(EventEmitter::new()), local_env());
|
||||
let config = RunConfig {
|
||||
|
|
|
|||
|
|
@ -955,7 +955,7 @@ ScriptHandler:
|
|||
Orchestrates sprint-based iteration by supervising a child pipeline. The manager observes the child's telemetry, evaluates progress via a guard function, and optionally steers the child through intervention.
|
||||
|
||||
```
|
||||
ManagerLoopHandler:
|
||||
SubWorkflowHandler:
|
||||
FUNCTION execute(node, context, graph, logs_root) -> Outcome:
|
||||
child_dotfile = graph.attrs.get("stack.child_dotfile")
|
||||
poll_interval = parse_duration(node.attrs.get("manager.poll_interval", "45s"))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue