Skip to main content

tokmd_analysis_effort/
request.rs

1//! Request and control types for effort estimation.
2//!
3//! These types form the boundary between CLI/config plumbing and the effort
4//! engine. They are intentionally small and serializable in spirit:
5//!
6//! - `EffortModelKind` chooses the estimation strategy,
7//! - `EffortLayer` controls how much of the estimate is intended for presentation,
8//! - `DeltaInput` describes a base/head comparison window,
9//! - `EffortRequest` bundles the knobs needed by `build_effort_report`.
10//!
11//! The request surface is allowed to be ahead of the implementation surface.
12//! In other words, callers may be able to request models or uncertainty modes
13//! that are parsed and validated before every variant is fully implemented.
14
15use std::fmt::{Display, Formatter};
16
17/// Request object passed into the effort engine.
18///
19/// This is the computation-facing version of the CLI/config surface. It is
20/// intentionally explicit so the builder can remain deterministic and avoid
21/// reaching back into argument parsing layers.
22///
23/// Notes:
24/// - `model` selects the requested estimate family,
25/// - `layer` is presentation-oriented metadata,
26/// - `base_ref` / `head_ref` enable delta output,
27/// - Monte Carlo fields are carried here even if the current engine chooses to
28///   reject or ignore them while only deterministic paths are implemented.
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct EffortRequest {
31    /// Estimation model requested by the caller.
32    pub model: EffortModelKind,
33    /// Requested presentation depth for effort output.
34    pub layer: EffortLayer,
35    /// Optional base reference for change-window estimation.
36    pub base_ref: Option<String>,
37    /// Optional head reference for change-window estimation.
38    pub head_ref: Option<String>,
39    /// Enable Monte Carlo uncertainty estimation.
40    pub monte_carlo: bool,
41    /// Monte Carlo sample count when uncertainty estimation is enabled.
42    pub mc_iterations: usize,
43    /// Optional deterministic seed for Monte Carlo.
44    pub mc_seed: Option<u64>,
45}
46
47impl Default for EffortRequest {
48    fn default() -> Self {
49        Self {
50            model: EffortModelKind::Cocomo81Basic,
51            layer: EffortLayer::Full,
52            base_ref: None,
53            head_ref: None,
54            monte_carlo: false,
55            mc_iterations: 10_000,
56            mc_seed: None,
57        }
58    }
59}
60
61/// Effort-estimation model requested by the caller.
62///
63/// `Cocomo81Basic` is the deterministic baseline.
64/// Other variants may be accepted by the request layer before the underlying
65/// engine fully implements them; those cases should fail clearly rather than
66/// silently degrading.
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum EffortModelKind {
69    Cocomo81Basic,
70    Cocomo2Early,
71    Ensemble,
72}
73
74impl EffortModelKind {
75    pub fn as_str(self) -> &'static str {
76        match self {
77            Self::Cocomo81Basic => "cocomo81-basic",
78            Self::Cocomo2Early => "cocomo2-early",
79            Self::Ensemble => "ensemble",
80        }
81    }
82}
83
84impl Display for EffortModelKind {
85    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
86        write!(f, "{}", self.as_str())
87    }
88}
89
90/// Requested presentation depth for effort output.
91///
92/// This is primarily a rendering hint:
93/// - `Headline` focuses on summary numbers,
94/// - `Why` adds explanatory context,
95/// - `Full` includes assumptions and optional delta details.
96///
97/// The engine may still compute richer data than the selected layer displays.
98#[derive(Debug, Clone, Copy, PartialEq, Eq)]
99pub enum EffortLayer {
100    Headline,
101    Why,
102    Full,
103}
104
105impl EffortLayer {
106    pub fn as_str(self) -> &'static str {
107        match self {
108            Self::Headline => "headline",
109            Self::Why => "why",
110            Self::Full => "full",
111        }
112    }
113}
114
115impl Display for EffortLayer {
116    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
117        write!(f, "{}", self.as_str())
118    }
119}
120
121/// Optional base/head comparison input for delta estimation.
122///
123/// When present, the effort engine may attach a delta section describing the
124/// blast radius and estimated effort impact of the change window.
125#[derive(Debug, Clone)]
126pub struct DeltaInput {
127    pub base_ref: String,
128    pub head_ref: String,
129}