TopologyKind describes twelve distinct intents, but the orchestrator
implements five planners and mapped the kinds onto them inside plan_steps.
So Market never auctions, StarMoe never routes to experts, Ring never cycles
and Holacratic never self-organizes -- each silently runs as whichever pattern
it collapses to, while kind::description() and the UI catalog kept promising
the distinct behaviour.
Rather than delete variants that appear in persisted rows, the collapse is now
named: ExecutionPattern + TopologyKind::execution_pattern() in cm-topology,
with plan_steps dispatching on the pattern instead of re-listing the mapping.
One source of truth, and the two cannot drift.
GET /api/topologies now reports `executes_as` and `distinct_at_execution` so a
UI can stop offering aliases as if they behaved differently.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Split execute() into a thin wrapper over new execute_resumable(), which starts
from a prior RunProgress checkpoint (completed step count + outputs + records +
metrics) and invokes an async on_step callback after each newly completed step.
The step plan is re-derived from the graph (planners are deterministic), so only
completed outputs need persisting; the callback owns persistence, keeping the
orchestrator storage-agnostic. RunProgress + the journal types (StepRecord,
RunMetrics, StepPhase, GatedAction) gain Deserialize for JSONB round-trip.
New test: resume-from-checkpoint runs only the remaining steps and reproduces
the full run's output. 14 tests pass, clippy clean.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
TurnRequest gains an optional `agent` sourced from the graph node's
attrs["agent"]. The ZeroClaw executor binds a node to that alias directly
when present, falling back to the role→alias map otherwise. This lets a
single POST /api/topologies/run specify a different model per role
(heterogeneous topologies) entirely in the graph JSON — no server
ZEROCLAW_AGENT_MAP change or recreate per configuration, which makes
quota-frugal model×role sweeps practical.
cm-orchestrator 13 + cm-api topology_exec 4 tests pass, clippy clean.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
cm-topology::build(kind, roles) instantiates a canonical graph for any of the 12
kinds from a role list (the template catalog + the search generator).
cm-orchestrator::evolve searches a (kinds × team-size) grid using the comparison
machinery as fitness: build a candidate per cell, run the task, score it, and
keep a MAP-Elites-style archive of per-cell elites + a quality/cost Pareto front
and the global best. evolve_all() covers every kind at full size. This is the
bridge toward Autonomous Organizational Evolution on a safe substrate — every
candidate still executes via safe turns (§15 invariant holds).
Demoed in topology_bench (auto-picks the best topology + Pareto kinds).
cm-topology 20 tests; cm-orchestrator 17 (--features provider); clippy clean.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Milestone-A second capability: chain whole topology runs in sequence, threading
each stage's final output into the next stage's task (e.g. swarm brainstorm →
hierarchical execute → debate review). Each stage is a full safe topology run,
so §15 holds at every step. WorkflowRecord aggregates per-stage RunRecords +
totals. Demonstrated in the benchmark example. 14 tests; clippy clean.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
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]>
`cargo run -p cm-orchestrator --example topology_bench --features provider`
runs one task across hierarchical/pipeline/swarm topologies and prints a
leaderboard + quality/cost Pareto front. Offline-deterministic via the scripted
provider; set ANTHROPIC_API_KEY to run against a real model. Demonstrates
milestone B end-to-end and seeds the reproducible paper harness.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Make Scorer async and add JudgeScorer (behind the `provider` feature): asks a
cm-llm model to rate a run's output 0-100 vs the task and normalizes to [0,1],
giving the comparison harness real quality numbers. Robust integer parsing
(handles "Score: 92/100", clamps >100); provider errors score 0.0.
11 tests with --features provider (judge incl. parse + scripted-provider score);
core stays 7. Clippy clean.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
compare(graphs, task, executor, scorer) runs the same task across a set of
topologies on the same executor, scores each, and returns a Comparison:
- per-topology results (quality, tokens, turns, blocked approvals, output),
- a leaderboard (quality desc),
- a quality/cost Pareto front (on_pareto flags),
- best_quality and best_value (quality-per-token) picks.
This is the "which patterns yield better results" engine and the structured
output the paper's benchmark tables consume. Generic over TurnExecutor +
Scorer (pluggable LLM-judge later); pure core, no new deps. 9 tests, clippy clean.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Add a real TurnExecutor (behind the `provider` feature) that runs each
topology turn as a single tool-free LLM call via any cm-llm provider
(Anthropic / OpenAI-compat / scripted). Topologies now execute real model
calls and produce real metrics (tokens), feeding the comparison harness.
- ProviderExecutor builds a per-role system prompt + threads upstream context
into the user message; collects TextDelta → output, Usage → tokens.
- Tool-free reasoning turns take no sandbox-leaving actions (gated = []); §15
remains satisfied. Tool-using turns will route through a cm-runtime adapter.
- Core crate stays dependency-light; cm-llm/futures are optional (feature).
- Tests: pipeline + hierarchical run over the deterministic scripted provider
(7 tests with --features provider). Clippy clean.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
A pure async control-flow engine that executes a task across a TopologyGraph
by sequencing safe agent turns. Safety by construction: the engine can only
invoke turns via a generic TurnExecutor — it performs no side effects itself,
so §15 gating (inside each turn) is inherited and switching topology cannot
escalate authority.
- TurnExecutor trait + TurnRequest/TurnOutcome (real impl will wrap
cm-runtime::Runtime; tests use a scripted Echo executor).
- Pure planners (plan.rs): hierarchical (delegate down / synthesize up),
pipeline (topo-ordered threading), swarm (parallel attempts + aggregate).
- RunRecord journal (per-step + RunMetrics: tokens, gated actions, approvals
granted/blocked, turns) — feeds the Phase 4 comparison harness/paper.
- Unsupported kinds return an error (no panic). 5 tests, clippy clean.
Next (Phase 2b): a real TurnExecutor adapter over cm-runtime::send_message.
Co-Authored-By: Claude Opus 4.8 <[email protected]>