Skip to main content

lean_ctx/core/profiles/
builtins.rs

1use super::types::{
2    BudgetConfig, CompressionConfig, DegradationConfig, LayoutConfig, OutputHints, PipelineConfig,
3    Profile, ProfileAutonomy, ProfileMeta, ReadConfig, RoutingConfig, TranslationConfig,
4};
5use std::collections::HashMap;
6
7// ── Built-in Profiles ──────────────────────────────────────
8
9pub(super) fn builtin_coder() -> Profile {
10    Profile {
11        profile: ProfileMeta {
12            name: "coder".to_string(),
13            inherits: None,
14            description: "Default coding workflow with guarded autonomy drivers".to_string(),
15        },
16        read: ReadConfig {
17            default_mode: Some("auto".to_string()),
18            max_tokens_per_file: Some(50_000),
19            prefer_cache: Some(true),
20        },
21        compression: CompressionConfig {
22            crp_mode: Some("tdd".to_string()),
23            output_density: Some("terse".to_string()),
24            terse_mode: Some(true),
25            ..CompressionConfig::default()
26        },
27        translation: TranslationConfig {
28            enabled: Some(true),
29            ruleset: Some("auto".to_string()),
30        },
31        layout: LayoutConfig::default(),
32        memory: crate::core::memory_policy::MemoryPolicyOverrides::default(),
33        verification: crate::core::output_verification::VerificationConfig::default(),
34        budget: BudgetConfig {
35            max_context_tokens: Some(150_000),
36            max_shell_invocations: Some(100),
37            ..BudgetConfig::default()
38        },
39        pipeline: PipelineConfig::default(),
40        routing: RoutingConfig::default(),
41        degradation: DegradationConfig::default(),
42        autonomy: ProfileAutonomy {
43            auto_prefetch: Some(true),
44            auto_response: Some(true),
45            checkpoint_interval: Some(10),
46            ..ProfileAutonomy::default()
47        },
48        output_hints: OutputHints::default(),
49    }
50}
51
52pub(super) fn builtin_exploration() -> Profile {
53    Profile {
54        profile: ProfileMeta {
55            name: "exploration".to_string(),
56            inherits: None,
57            description: "Broad context for understanding codebases".to_string(),
58        },
59        read: ReadConfig {
60            default_mode: Some("map".to_string()),
61            max_tokens_per_file: Some(80_000),
62            prefer_cache: Some(true),
63        },
64        compression: CompressionConfig {
65            terse_mode: Some(true),
66            output_density: Some("terse".to_string()),
67            ..CompressionConfig::default()
68        },
69        translation: TranslationConfig::default(),
70        layout: LayoutConfig::default(),
71        memory: crate::core::memory_policy::MemoryPolicyOverrides::default(),
72        verification: crate::core::output_verification::VerificationConfig::default(),
73        budget: BudgetConfig {
74            max_context_tokens: Some(200_000),
75            ..BudgetConfig::default()
76        },
77        pipeline: PipelineConfig::default(),
78        routing: RoutingConfig::default(),
79        degradation: DegradationConfig::default(),
80        autonomy: ProfileAutonomy::default(),
81        output_hints: OutputHints {
82            related_hint: Some(true),
83            compressed_hint: Some(true),
84            ..OutputHints::default()
85        },
86    }
87}
88
89fn builtin_bugfix() -> Profile {
90    Profile {
91        profile: ProfileMeta {
92            name: "bugfix".to_string(),
93            inherits: None,
94            description: "Focused context for debugging specific issues".to_string(),
95        },
96        read: ReadConfig {
97            default_mode: Some("auto".to_string()),
98            max_tokens_per_file: Some(30_000),
99            prefer_cache: Some(false),
100        },
101        compression: CompressionConfig {
102            crp_mode: Some("tdd".to_string()),
103            output_density: Some("terse".to_string()),
104            ..CompressionConfig::default()
105        },
106        translation: TranslationConfig::default(),
107        layout: LayoutConfig::default(),
108        memory: crate::core::memory_policy::MemoryPolicyOverrides::default(),
109        verification: crate::core::output_verification::VerificationConfig::default(),
110        budget: BudgetConfig {
111            max_context_tokens: Some(100_000),
112            max_shell_invocations: Some(50),
113            ..BudgetConfig::default()
114        },
115        pipeline: PipelineConfig::default(),
116        routing: RoutingConfig {
117            max_model_tier: Some("standard".to_string()),
118            ..RoutingConfig::default()
119        },
120        degradation: DegradationConfig::default(),
121        autonomy: ProfileAutonomy {
122            checkpoint_interval: Some(10),
123            ..ProfileAutonomy::default()
124        },
125        output_hints: OutputHints::default(),
126    }
127}
128
129fn builtin_hotfix() -> Profile {
130    Profile {
131        profile: ProfileMeta {
132            name: "hotfix".to_string(),
133            inherits: None,
134            description: "Minimal context, fast iteration for urgent fixes".to_string(),
135        },
136        read: ReadConfig {
137            default_mode: Some("signatures".to_string()),
138            max_tokens_per_file: Some(2_000),
139            prefer_cache: Some(true),
140        },
141        compression: CompressionConfig {
142            crp_mode: Some("tdd".to_string()),
143            output_density: Some("ultra".to_string()),
144            ..CompressionConfig::default()
145        },
146        translation: TranslationConfig::default(),
147        layout: LayoutConfig::default(),
148        memory: crate::core::memory_policy::MemoryPolicyOverrides::default(),
149        verification: crate::core::output_verification::VerificationConfig::default(),
150        budget: BudgetConfig {
151            max_context_tokens: Some(30_000),
152            max_shell_invocations: Some(20),
153            max_cost_usd: Some(1.0),
154        },
155        pipeline: PipelineConfig::default(),
156        routing: RoutingConfig {
157            max_model_tier: Some("fast".to_string()),
158            ..RoutingConfig::default()
159        },
160        degradation: DegradationConfig::default(),
161        autonomy: ProfileAutonomy {
162            checkpoint_interval: Some(5),
163            ..ProfileAutonomy::default()
164        },
165        output_hints: OutputHints::default(),
166    }
167}
168
169fn builtin_ci_debug() -> Profile {
170    Profile {
171        profile: ProfileMeta {
172            name: "ci-debug".to_string(),
173            inherits: None,
174            description: "CI/CD debugging with shell-heavy workflows".to_string(),
175        },
176        read: ReadConfig {
177            default_mode: Some("auto".to_string()),
178            max_tokens_per_file: Some(50_000),
179            prefer_cache: Some(false),
180        },
181        compression: CompressionConfig {
182            output_density: Some("terse".to_string()),
183            ..CompressionConfig::default()
184        },
185        translation: TranslationConfig::default(),
186        layout: LayoutConfig::default(),
187        memory: crate::core::memory_policy::MemoryPolicyOverrides::default(),
188        verification: crate::core::output_verification::VerificationConfig::default(),
189        budget: BudgetConfig {
190            max_context_tokens: Some(150_000),
191            max_shell_invocations: Some(200),
192            ..BudgetConfig::default()
193        },
194        pipeline: PipelineConfig::default(),
195        routing: RoutingConfig {
196            max_model_tier: Some("standard".to_string()),
197            ..RoutingConfig::default()
198        },
199        degradation: DegradationConfig::default(),
200        autonomy: ProfileAutonomy::default(),
201        output_hints: OutputHints::default(),
202    }
203}
204
205fn builtin_review() -> Profile {
206    Profile {
207        profile: ProfileMeta {
208            name: "review".to_string(),
209            inherits: None,
210            description: "Code review with broad read-only context".to_string(),
211        },
212        read: ReadConfig {
213            default_mode: Some("map".to_string()),
214            max_tokens_per_file: Some(60_000),
215            prefer_cache: Some(true),
216        },
217        compression: CompressionConfig {
218            crp_mode: Some("compact".to_string()),
219            ..CompressionConfig::default()
220        },
221        translation: TranslationConfig::default(),
222        layout: LayoutConfig {
223            enabled: Some(true),
224            ..LayoutConfig::default()
225        },
226        memory: crate::core::memory_policy::MemoryPolicyOverrides::default(),
227        verification: crate::core::output_verification::VerificationConfig::default(),
228        budget: BudgetConfig {
229            max_context_tokens: Some(150_000),
230            max_shell_invocations: Some(30),
231            ..BudgetConfig::default()
232        },
233        pipeline: PipelineConfig::default(),
234        routing: RoutingConfig {
235            max_model_tier: Some("standard".to_string()),
236            ..RoutingConfig::default()
237        },
238        degradation: DegradationConfig::default(),
239        autonomy: ProfileAutonomy::default(),
240        output_hints: OutputHints {
241            verify_footer: Some(true),
242            related_hint: Some(true),
243            compressed_hint: Some(true),
244            ..OutputHints::default()
245        },
246    }
247}
248
249fn builtin_passthrough() -> Profile {
250    Profile {
251        profile: ProfileMeta {
252            name: "passthrough".to_string(),
253            inherits: None,
254            description: "No output modification — always full content, no compression".to_string(),
255        },
256        read: ReadConfig {
257            default_mode: Some("full".to_string()),
258            max_tokens_per_file: Some(10_000_000),
259            prefer_cache: Some(false),
260        },
261        compression: CompressionConfig {
262            crp_mode: Some("off".to_string()),
263            output_density: Some("normal".to_string()),
264            entropy_threshold: None,
265            terse_mode: Some(false),
266            adaptive: None,
267        },
268        translation: TranslationConfig {
269            enabled: Some(false),
270            ..TranslationConfig::default()
271        },
272        layout: LayoutConfig::default(),
273        memory: crate::core::memory_policy::MemoryPolicyOverrides::default(),
274        verification: crate::core::output_verification::VerificationConfig::default(),
275        budget: BudgetConfig {
276            max_context_tokens: Some(1_000_000),
277            ..BudgetConfig::default()
278        },
279        pipeline: PipelineConfig {
280            intent: Some(false),
281            relevance: Some(false),
282            compression: Some(false),
283            translation: Some(false),
284        },
285        routing: RoutingConfig::default(),
286        degradation: DegradationConfig {
287            enforce: Some(false),
288            ..DegradationConfig::default()
289        },
290        autonomy: ProfileAutonomy::default(),
291        output_hints: OutputHints::default(),
292    }
293}
294
295/// Returns all built-in profile definitions.
296pub fn builtin_profiles() -> HashMap<String, Profile> {
297    let mut map = HashMap::new();
298    for p in [
299        builtin_coder(),
300        builtin_exploration(),
301        builtin_bugfix(),
302        builtin_hotfix(),
303        builtin_ci_debug(),
304        builtin_review(),
305        builtin_passthrough(),
306    ] {
307        map.insert(p.profile.name.clone(), p);
308    }
309    map
310}
311
312/// Constructs a single built-in profile by name, building only the one
313/// requested.
314///
315/// `active_profile()` resolves to a built-in on most calls (no on-disk
316/// override), and it is invoked many times per tool dispatch. Going through
317/// [`builtin_profiles`] there materialized all seven profile structs just to
318/// drop six — this hot-path shortcut builds exactly one. The match arms must
319/// stay in sync with [`builtin_profiles`].
320pub(super) fn builtin_profile(name: &str) -> Option<Profile> {
321    match name {
322        "coder" => Some(builtin_coder()),
323        "exploration" => Some(builtin_exploration()),
324        "bugfix" => Some(builtin_bugfix()),
325        "hotfix" => Some(builtin_hotfix()),
326        "ci-debug" => Some(builtin_ci_debug()),
327        "review" => Some(builtin_review()),
328        "passthrough" => Some(builtin_passthrough()),
329        _ => None,
330    }
331}