#![deny(missing_docs)]
#![deny(rust_2018_idioms)]

//! Generic decompose / critique / refine traits and a quality loop runner.
//!
//! `klieo-spec` lifts the pattern from the legacy
//! `klieo-domain` aggregates (`goal`, `epic`, `spec`, `refinement`,
//! `quality`) into a domain-agnostic agent toolkit. Any agent author
//! can plug in their own [`Decomposer<I, O>`], [`Critic<T>`], and
//! [`Refiner<T>`] implementations and reuse the production-grade
//! quality loop semantics.
//!
//! # Worked example
//!
//! ```
//! # tokio_test::block_on(async {
//! use klieo_spec::*;
//! use async_trait::async_trait;
//!
//! /// Toy critic: pass when the input contains "OK".
//! struct LenCheck { min: usize }
//! #[async_trait]
//! impl Critic<String> for LenCheck {
//!     async fn evaluate(&self, t: &String, _iter: u8)
//!         -> Result<Critique, SpecError>
//!     {
//!         if t.len() >= self.min {
//!             Ok(Critique::pass(format!("ok: {} chars", t.len())))
//!         } else {
//!             Ok(Critique::fail(format!("too short: {} < {}", t.len(), self.min)))
//!         }
//!     }
//! }
//!
//! /// Toy refiner: pad the input until it satisfies the critic.
//! struct Pad;
//! #[async_trait]
//! impl Refiner<String> for Pad {
//!     async fn refine(&self, t: String, _c: &Critique, _iter: u8)
//!         -> Result<String, SpecError>
//!     {
//!         Ok(format!("{t}-x"))
//!     }
//! }
//!
//! let loop_runner = QualityLoop::new(LenCheck { min: 5 }, Pad)
//!     .with_max_iterations(10);
//! let (out, meta) = loop_runner.run("a".to_string()).await.unwrap();
//! assert!(meta.passed);
//! assert!(out.len() >= 5);
//! # });
//! ```
//!
//! # Why a separate crate?
//!
//! The legacy `klieo-domain` decomposition / refinement code is
//! tightly coupled to `Spec`, `GraphContext`, and `NodeRef` — usable
//! only by a single product. `klieo-spec` is intentionally domain-
//! free so that:
//!
//! - **Agent authors** can build on the same loop semantics for any
//!   decomposable / refinable type (a request body, a code patch, a
//!   plan-of-tasks, …).
//! - **The legacy code** keeps running untouched. Plan #30 owns the
//!   cutover that re-bases `klieo-domain` on this crate.

pub mod quality;
pub use quality::{Critique, QualityMetadata};

pub mod decompose;
pub use decompose::Decomposer;

pub mod critique;
pub use critique::Critic;

pub mod refine;
pub use refine::Refiner;

pub mod loops;
pub use loops::QualityLoop;

mod error;
pub use error::SpecError;
