1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//! 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 use ;
pub use Decomposer;
pub use Critic;
pub use Refiner;
pub use QualityLoop;
pub use SpecError;