Skip to main content

klieo_spec/
lib.rs

1#![deny(missing_docs)]
2#![deny(rust_2018_idioms)]
3#![deny(rustdoc::broken_intra_doc_links)]
4
5//! Generic decompose / critique / refine traits and a quality loop runner.
6//!
7//! `klieo-spec` lifts the pattern from the legacy
8//! `klieo-domain` aggregates (`goal`, `epic`, `spec`, `refinement`,
9//! `quality`) into a domain-agnostic agent toolkit. Any agent author
10//! can plug in their own [`Decomposer<I, O>`], [`Critic<T>`], and
11//! [`Refiner<T>`] implementations and reuse the production-grade
12//! quality loop semantics.
13//!
14//! # Worked example
15//!
16//! ```
17//! # tokio_test::block_on(async {
18//! use klieo_spec::*;
19//! use async_trait::async_trait;
20//!
21//! /// Toy critic: pass when the input contains "OK".
22//! struct LenCheck { min: usize }
23//! #[async_trait]
24//! impl Critic<String> for LenCheck {
25//!     async fn evaluate(&self, t: &String, _iter: u8)
26//!         -> Result<Critique, SpecError>
27//!     {
28//!         if t.len() >= self.min {
29//!             Ok(Critique::pass(format!("ok: {} chars", t.len())))
30//!         } else {
31//!             Ok(Critique::fail(format!("too short: {} < {}", t.len(), self.min)))
32//!         }
33//!     }
34//! }
35//!
36//! /// Toy refiner: pad the input until it satisfies the critic.
37//! struct Pad;
38//! #[async_trait]
39//! impl Refiner<String> for Pad {
40//!     async fn refine(&self, t: String, _c: &Critique, _iter: u8)
41//!         -> Result<String, SpecError>
42//!     {
43//!         Ok(format!("{t}-x"))
44//!     }
45//! }
46//!
47//! let loop_runner = QualityLoop::new(LenCheck { min: 5 }, Pad)
48//!     .with_max_iterations(10);
49//! let (out, meta) = loop_runner.run("a".to_string()).await.unwrap();
50//! assert!(meta.passed);
51//! assert!(out.len() >= 5);
52//! # });
53//! ```
54//!
55//! # Why a separate crate?
56//!
57//! The legacy `klieo-domain` decomposition / refinement code is
58//! tightly coupled to `Spec`, `GraphContext`, and `NodeRef` — usable
59//! only by a single product. `klieo-spec` is intentionally domain-
60//! free so that:
61//!
62//! - **Agent authors** can build on the same loop semantics for any
63//!   decomposable / refinable type (a request body, a code patch, a
64//!   plan-of-tasks, …).
65//! - **The legacy code** keeps running untouched. Plan #30 owns the
66//!   cutover that re-bases `klieo-domain` on this crate.
67
68pub mod quality;
69pub use quality::{Critique, QualityMetadata};
70
71pub mod decompose;
72pub use decompose::Decomposer;
73
74pub mod critique;
75pub use critique::Critic;
76
77pub mod refine;
78pub use refine::Refiner;
79
80pub mod loops;
81pub use loops::QualityLoop;
82
83mod error;
84pub use error::SpecError;