Skip to main content

stygian_plugin/reliability/
mod.rs

1//! Extraction reliability scoring
2//!
3//! Computes a 0.0–1.0 reliability score for [`ExtractionResult`] outputs so
4//! fallback chains can optimize for *data quality*, not only fetch success.
5//!
6//! # Score components
7//!
8//! The score is the weighted sum of three sub-scores, clamped to `[0.0, 1.0]`:
9//!
10//! | Sub-score              | Default weight | Source                                           |
11//! |------------------------|---------------:|--------------------------------------------------|
12//! | `schema_completeness`  |           0.70 | `successful_regions / total_regions`             |
13//! | `transformation_success`|          0.30 | `1 − transformation_failure_rate`                |
14//! | `retry_penalty`        |           0.10 | `retry_count / max_retries` (clamped)            |
15//!
16//! `retry_penalty` is **subtracted** from the weighted sum — it represents a
17//! quality discount for results that took many retries to produce.
18//!
19//! # Interpretation bands
20//!
21//! The continuous `overall` score is bucketed into three discrete bands so
22//! callers can branch on a single [`ReliabilityBand`] value:
23//!
24//! | Band    | Score range   | Interpretation                                  |
25//! |---------|---------------|-------------------------------------------------|
26//! | `High`  | `0.85..=1.00` | Production-ready; trust the result.             |
27//! | `Medium`| `0.50..0.85`  | Partial; treat as best-effort, retry if needed. |
28//! | `Low`   | `0.00..0.50`  | Unreliable; prefer an alternative fallback.     |
29//!
30//! # Selection policy
31//!
32//! The [`ScoreWeightedSelector`] helper ranks a list of `(name, score)`
33//! candidates and picks the highest-scoring one. Callers can apply a custom
34//! [`ScoringWeights`] to tune the importance of each sub-score for their
35//! target class.
36//!
37//! # Example
38//!
39//! ```
40//! use stygian_plugin::domain::{ExtractionResult, IdempotencyKey};
41//! use stygian_plugin::reliability::{ReliabilityScorer, ReliabilityBand};
42//!
43//! let result = ExtractionResult::new(IdempotencyKey::new());
44//! let score = ReliabilityScorer::new().score_extraction(&result, 0);
45//! assert_eq!(score.band, ReliabilityBand::High); // empty template -> vacuously complete
46//! assert!((score.overall - 1.0).abs() < f32::EPSILON);
47//! ```
48
49pub mod score;
50pub mod scorer;
51pub mod selector;
52
53pub use score::{ReliabilityBand, ReliabilityScore};
54pub use scorer::{ReliabilityScorer, ScoringWeights};
55pub use selector::{ScoreWeightedSelector, ScoredCandidate};