Files
clawmates/crates/cm-topology/src/heuristics.rs
T
Omar SobhandClaude Opus 4.8 817d8c712c
ci / gates (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / sandbox-k8s (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / e2e (push) Has been cancelled
feat(topology): cm-topology crate + architecture doc (Phases 0–1)
Foundation for the dynamic agentic-topologies platform (see
docs/topology-platform.md), porting agentorg's topology modeling into pure Rust:

- TopologyKind: curated 12-kind taxonomy (hierarchical, flat, pipeline, swarm,
  mesh, hub_spoke, ring, star_moe, market, blackboard, debate, holacratic).
- TopologyGraph: role-slot nodes + typed edges, with validation.
- adapter: normalize a loose JSON spec → validated graph (fills edge kinds).
- classifier: structural metrics (density, hub dominance, clustering, diameter,
  hierarchy score) → inferred kind + confidence (tree→hierarchical, line→pipeline,
  cycle→ring, star→hub_spoke, complete→mesh, empty→flat).
- heuristics: per-kind role distributions (ported from topology_manager.py).

Pure, offline, dependency-light (serde/thiserror). 17 unit tests, clippy clean.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-15 20:05:06 -07:00

164 lines
5.6 KiB
Rust

//! Per-topology heuristics: a default role mix + a short rationale.
//!
//! Ported/adapted from agentorg's `topology_manager.py` role distributions.
//! These guide how the orchestrator (Phase 2) staffs a topology and how the
//! evolution layer (Phase 5) biases search; they are advisory, not hard rules.
use crate::kind::TopologyKind;
/// Advisory staffing/optimization hints for a topology.
#[derive(Debug, Clone, Copy)]
pub struct Heuristics {
/// Suggested fraction of agents per role (sums to ~1.0).
pub role_distribution: &'static [(&'static str, f32)],
/// Why this mix suits the topology.
pub notes: &'static str,
}
/// Heuristics for a given topology kind. Every kind is covered.
pub fn heuristics(kind: TopologyKind) -> Heuristics {
use TopologyKind::*;
match kind {
Hierarchical => Heuristics {
role_distribution: &[
("coordinator", 0.15),
("executor", 0.60),
("analyst", 0.15),
("innovator", 0.05),
("validator", 0.05),
],
notes: "few coordinators, many executors; optimize span of control and depth",
},
Flat => Heuristics {
role_distribution: &[
("coordinator", 0.05),
("executor", 0.30),
("analyst", 0.25),
("innovator", 0.25),
("validator", 0.15),
],
notes: "high autonomy; reward peer collaboration, penalize consensus drag",
},
Pipeline => Heuristics {
role_distribution: &[
("coordinator", 0.10),
("executor", 0.55),
("analyst", 0.15),
("innovator", 0.05),
("validator", 0.15),
],
notes: "stage specialists in sequence; validators between stages",
},
Swarm => Heuristics {
role_distribution: &[
("coordinator", 0.10),
("executor", 0.25),
("analyst", 0.25),
("innovator", 0.25),
("validator", 0.15),
],
notes: "value diversity, reward emergent behavior, penalize redundancy",
},
Mesh => Heuristics {
role_distribution: &[
("coordinator", 0.05),
("executor", 0.30),
("analyst", 0.30),
("innovator", 0.20),
("validator", 0.15),
],
notes: "dense peer exchange; analysts dominate to converge information",
},
HubSpoke => Heuristics {
role_distribution: &[
("coordinator", 0.30),
("executor", 0.50),
("analyst", 0.10),
("innovator", 0.05),
("validator", 0.05),
],
notes: "central hub coordinates; cap hub fan-out, reward routing efficiency",
},
Ring => Heuristics {
role_distribution: &[
("coordinator", 0.10),
("executor", 0.40),
("analyst", 0.20),
("innovator", 0.15),
("validator", 0.15),
],
notes: "sequential cycles; reward cycle completion and bidirectional flow",
},
StarMoe => Heuristics {
role_distribution: &[
("coordinator", 0.15),
("executor", 0.55),
("analyst", 0.20),
("innovator", 0.05),
("validator", 0.05),
],
notes: "a router dispatches to specialist experts; reward routing accuracy",
},
Market => Heuristics {
role_distribution: &[
("coordinator", 0.10),
("executor", 0.55),
("analyst", 0.20),
("innovator", 0.05),
("validator", 0.10),
],
notes: "agents bid on tasks by fit/cost; reward allocative efficiency",
},
Blackboard => Heuristics {
role_distribution: &[
("coordinator", 0.10),
("executor", 0.35),
("analyst", 0.30),
("innovator", 0.15),
("validator", 0.10),
],
notes: "shared workspace; analysts synthesize contributions opportunistically",
},
Debate => Heuristics {
role_distribution: &[
("coordinator", 0.10),
("executor", 0.35),
("analyst", 0.20),
("innovator", 0.20),
("validator", 0.15),
],
notes: "proposer vs critic with a judge; reward decisive, well-argued outcomes",
},
Holacratic => Heuristics {
role_distribution: &[
("coordinator", 0.20),
("executor", 0.30),
("analyst", 0.20),
("innovator", 0.20),
("validator", 0.10),
],
notes: "self-organizing circles; reward clear roles and tension resolution",
},
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn every_kind_has_valid_distribution() {
for k in TopologyKind::ALL {
let h = heuristics(k);
assert!(!h.role_distribution.is_empty(), "{} empty", k.as_str());
assert!(!h.notes.is_empty());
let sum: f32 = h.role_distribution.iter().map(|(_, w)| *w).sum();
assert!(
(sum - 1.0).abs() < 0.01,
"{} role distribution sums to {sum}, expected ~1.0",
k.as_str()
);
}
}
}