feat(topology): executors for all 12 kinds (mesh + debate; mappings)
Every TopologyKind now runs, mapped to five execution patterns: - hierarchical ← hub_spoke, star_moe, market - pipeline ← ring - swarm ← flat, holacratic - mesh (new) ← blackboard (two peer-exchange rounds + aggregate) - debate (new) (propose → critique → revise → judge) execute()'s match is now exhaustive (adding a kind upstream forces an executor), so the Unsupported error is gone. Benchmark spans all five distinct patterns. 14 tests with --features provider; clippy clean. Doc updated. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
c595cebab0
commit
e93a3cfb53
@@ -171,3 +171,63 @@ pub(crate) fn swarm(g: &TopologyGraph) -> Result<Vec<PlanStep>, OrchestratorErro
|
||||
});
|
||||
Ok(steps)
|
||||
}
|
||||
|
||||
/// Mesh / blackboard: two rounds of peer exchange (round 2 sees every round-1
|
||||
/// output), then the first peer aggregates — models iterative convergence.
|
||||
pub(crate) fn mesh(g: &TopologyGraph) -> Result<Vec<PlanStep>, OrchestratorError> {
|
||||
let n = g.nodes.len();
|
||||
if n == 0 {
|
||||
return Err(OrchestratorError::Malformed("empty topology".into()));
|
||||
}
|
||||
let mut steps = Vec::new();
|
||||
for i in 0..n {
|
||||
steps.push(PlanStep {
|
||||
node_idx: i,
|
||||
phase: StepPhase::Work,
|
||||
use_task: true,
|
||||
ctx_from: vec![],
|
||||
});
|
||||
}
|
||||
let round1: Vec<usize> = (0..n).collect();
|
||||
for i in 0..n {
|
||||
steps.push(PlanStep {
|
||||
node_idx: i,
|
||||
phase: StepPhase::Work,
|
||||
use_task: false,
|
||||
ctx_from: round1.clone(),
|
||||
});
|
||||
}
|
||||
let round2: Vec<usize> = (n..2 * n).collect();
|
||||
steps.push(PlanStep {
|
||||
node_idx: 0,
|
||||
phase: StepPhase::Aggregate,
|
||||
use_task: false,
|
||||
ctx_from: round2,
|
||||
});
|
||||
Ok(steps)
|
||||
}
|
||||
|
||||
/// Debate: proposer drafts, critic critiques, proposer revises, judge decides.
|
||||
pub(crate) fn debate(g: &TopologyGraph) -> Result<Vec<PlanStep>, OrchestratorError> {
|
||||
let n = g.nodes.len();
|
||||
if n == 0 {
|
||||
return Err(OrchestratorError::Malformed("empty topology".into()));
|
||||
}
|
||||
if n == 1 {
|
||||
return Ok(vec![PlanStep {
|
||||
node_idx: 0,
|
||||
phase: StepPhase::Work,
|
||||
use_task: true,
|
||||
ctx_from: vec![],
|
||||
}]);
|
||||
}
|
||||
let proposer = 0;
|
||||
let critic = 1;
|
||||
let judge = if n >= 3 { 2 } else { 0 };
|
||||
Ok(vec![
|
||||
PlanStep { node_idx: proposer, phase: StepPhase::Work, use_task: true, ctx_from: vec![] },
|
||||
PlanStep { node_idx: critic, phase: StepPhase::Work, use_task: true, ctx_from: vec![0] },
|
||||
PlanStep { node_idx: proposer, phase: StepPhase::Synth, use_task: false, ctx_from: vec![0, 1] },
|
||||
PlanStep { node_idx: judge, phase: StepPhase::Aggregate, use_task: false, ctx_from: vec![2, 1] },
|
||||
])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user