collet 0.1.0

Relentless agentic coding orchestrator with zero-drop agent loops
Documentation
//! EvolutionEngine — the single abstraction for pluggable evolution algorithms.
//!
//! Implement [`EvolutionEngine::step`] to create a new evolution strategy.
//! The loop provides shared primitives (workspace, observations, history,
//! trial runner); your algorithm decides what to do with them.

use anyhow::Result;
use async_trait::async_trait;

use super::history::EvolutionHistory;
use super::trial::TrialRunner;
use super::types::{Observation, StepResult};
use super::workspace::AgentWorkspace;

/// Base trait for all evolution algorithms.
///
/// Subclasses implement `step()` — one evolution cycle.  The method receives
/// the current workspace, this cycle's observations, a history query facade,
/// and a trial runner for optional live validation.
///
/// The engine is free to mutate the workspace however it sees fit.
#[async_trait]
pub trait EvolutionEngine: Send + Sync {
    /// Run one evolution step.  Mutate `workspace` as needed.
    ///
    /// # Arguments
    /// - `workspace`: The agent's filesystem workspace (read/write).
    /// - `observations`: Results from the current solve batch.
    /// - `history`: Query interface over past observations and workspace versions.
    /// - `trial`: Runner for live agent evaluation (use sparingly — expensive).
    async fn step(
        &mut self,
        workspace: &AgentWorkspace,
        observations: &[Observation],
        history: &EvolutionHistory,
        trial: &TrialRunner,
    ) -> Result<StepResult>;

    /// Optional callback invoked after each cycle completes.
    ///
    /// Override to track accept/reject signals or adjust internal state.
    fn on_cycle_end(&mut self, _accepted: bool, _score: f64) {}

    /// Human-readable engine name for logging and cycle records.
    fn name(&self) -> &str;
}