Skip to main content

lean_ctx/core/config/
solution.rs

1use serde::{Deserialize, Serialize};
2
3/// Controls how strongly solution-efficiency guidance is applied.
4#[derive(Default, Serialize, Deserialize, Clone, Debug)]
5#[serde(rename_all = "lowercase")]
6pub enum SolutionIntensity {
7    #[serde(alias = "Off")]
8    Off,
9    #[serde(alias = "Minimal")]
10    Minimal,
11    #[default]
12    #[serde(alias = "Balanced")]
13    Balanced,
14    #[serde(alias = "Aggressive")]
15    Aggressive,
16}
17
18impl SolutionIntensity {
19    pub fn label(&self) -> &'static str {
20        match self {
21            Self::Off => "off",
22            Self::Minimal => "minimal",
23            Self::Balanced => "balanced",
24            Self::Aggressive => "aggressive",
25        }
26    }
27}
28
29static OFF_INTENSITY: SolutionIntensity = SolutionIntensity::Off;
30
31/// Configuration for solution-efficiency guidance.
32#[derive(Serialize, Deserialize, Clone, Debug)]
33#[serde(default)]
34pub struct SolutionConfig {
35    #[serde(default = "default_true")]
36    pub enabled: bool,
37    pub intensity: SolutionIntensity,
38    /// Inject the efficiency ladder into the per-turn channels (MCP
39    /// instructions and the rules files). Off by default since A3: it is
40    /// coding advice, not context routing, and it rode every turn (pilot P6:
41    /// part of the ~8% instructions share). The on-demand `LEAN-CTX.md` keeps it.
42    #[serde(default)]
43    pub inject_in_instructions: bool,
44    #[serde(default = "default_true")]
45    pub inject_in_compose: bool,
46    /// Same as `inject_in_instructions`, for sub-agent sessions. Off by default.
47    #[serde(default)]
48    pub inject_in_subagents: bool,
49    #[serde(default = "default_true")]
50    pub track_decisions: bool,
51    #[serde(default = "default_true")]
52    pub track_loc: bool,
53    #[serde(default = "default_true")]
54    pub platform_hints: bool,
55}
56
57const fn default_true() -> bool {
58    true
59}
60
61impl Default for SolutionConfig {
62    fn default() -> Self {
63        Self {
64            enabled: true,
65            intensity: SolutionIntensity::Balanced,
66            inject_in_instructions: false,
67            inject_in_compose: true,
68            inject_in_subagents: false,
69            track_decisions: true,
70            track_loc: true,
71            platform_hints: true,
72        }
73    }
74}
75
76impl SolutionConfig {
77    pub fn effective_intensity(&self) -> &SolutionIntensity {
78        if self.enabled {
79            &self.intensity
80        } else {
81            &OFF_INTENSITY
82        }
83    }
84
85    pub fn ladder_text(&self) -> &'static str {
86        const BALANCED: &str = "Solution efficiency ladder:\n\
871. YAGNI: is this needed at all?\n\
882. Reuse: does this codebase already provide it?\n\
893. Stdlib: can the standard library handle it?\n\
904. Native: use the platform's built-in capability.\n\
915. Dependency: use an already-installed dependency before adding one.\n\
926. One-line: can the correct solution be one line?\n\
937. Minimum: otherwise implement the minimum working code.\n\
94Preserve validation, security, and error-handling.";
95        const AGGRESSIVE: &str = "challenge every requirement, prefer deletion.\n\n\
96Solution efficiency ladder:\n\
971. YAGNI: is this needed at all?\n\
982. Reuse: does this codebase already provide it?\n\
993. Stdlib: can the standard library handle it?\n\
1004. Native: use the platform's built-in capability.\n\
1015. Dependency: use an already-installed dependency before adding one.\n\
1026. One-line: can the correct solution be one line?\n\
1037. Minimum: otherwise implement the minimum working code.\n\
104Preserve validation, security, and error-handling.";
105
106        match self.effective_intensity() {
107            SolutionIntensity::Off => "",
108            SolutionIntensity::Minimal => {
109                "Prefer stdlib and native platform alternatives before adding code or dependencies."
110            }
111            SolutionIntensity::Balanced => BALANCED,
112            SolutionIntensity::Aggressive => AGGRESSIVE,
113        }
114    }
115}