lean_ctx/core/
adaptive.rs1#![allow(dead_code)]
2use crate::core::cache::SessionCache;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum TaskComplexity {
6 Mechanical,
7 Standard,
8 Architectural,
9}
10
11impl TaskComplexity {
12 pub fn instruction_suffix(&self) -> &'static str {
13 match self {
14 TaskComplexity::Mechanical => {
15 "TASK COMPLEXITY: mechanical\n\
16 Minimal reasoning needed. Act immediately, report result in one line."
17 }
18 TaskComplexity::Standard => {
19 "TASK COMPLEXITY: standard\n\
20 Brief reasoning allowed. Summarize approach in 1-2 lines, then act."
21 }
22 TaskComplexity::Architectural => {
23 "TASK COMPLEXITY: architectural\n\
24 Full reasoning expected. Outline approach, consider edge cases, then act."
25 }
26 }
27 }
28
29 pub fn encoded_suffix(&self) -> String {
30 use crate::core::protocol::encode_instructions;
31 match self {
32 TaskComplexity::Mechanical => encode_instructions("mechanical"),
33 TaskComplexity::Standard => encode_instructions("standard"),
34 TaskComplexity::Architectural => encode_instructions("architectural"),
35 }
36 }
37
38 fn complexity_label(&self) -> &'static str {
39 match self {
40 TaskComplexity::Mechanical => "mechanical",
41 TaskComplexity::Standard => "standard",
42 TaskComplexity::Architectural => "architectural",
43 }
44 }
45}
46
47pub fn classify_from_context(cache: &SessionCache) -> TaskComplexity {
48 let stats = cache.get_stats();
49 let unique_files = cache.get_all_entries().len();
50 let total_reads = stats.total_reads;
51
52 if unique_files <= 1 && total_reads <= 3 {
53 return TaskComplexity::Mechanical;
54 }
55
56 if unique_files >= 5 || total_reads >= 15 {
57 return TaskComplexity::Architectural;
58 }
59
60 TaskComplexity::Standard
61}
62
63pub fn classify_from_signals(
64 file_count: usize,
65 has_tests: bool,
66 has_multi_lang: bool,
67) -> TaskComplexity {
68 if has_tests && file_count >= 5 {
69 return TaskComplexity::Architectural;
70 }
71
72 if has_multi_lang || file_count >= 3 {
73 return TaskComplexity::Standard;
74 }
75
76 TaskComplexity::Mechanical
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn test_mechanical_classification() {
85 let result = classify_from_signals(1, false, false);
86 assert_eq!(result, TaskComplexity::Mechanical);
87 }
88
89 #[test]
90 fn test_standard_classification() {
91 let result = classify_from_signals(3, false, false);
92 assert_eq!(result, TaskComplexity::Standard);
93 }
94
95 #[test]
96 fn test_architectural_classification() {
97 let result = classify_from_signals(5, true, false);
98 assert_eq!(result, TaskComplexity::Architectural);
99 }
100
101 #[test]
102 fn test_multi_lang_triggers_standard() {
103 let result = classify_from_signals(1, false, true);
104 assert_eq!(result, TaskComplexity::Standard);
105 }
106
107 #[test]
108 fn test_instruction_suffix_not_empty() {
109 assert!(!TaskComplexity::Mechanical.instruction_suffix().is_empty());
110 assert!(!TaskComplexity::Standard.instruction_suffix().is_empty());
111 assert!(!TaskComplexity::Architectural
112 .instruction_suffix()
113 .is_empty());
114 }
115
116 #[test]
117 fn test_context_based_mechanical() {
118 let cache = SessionCache::new();
119 let result = classify_from_context(&cache);
120 assert_eq!(result, TaskComplexity::Mechanical);
121 }
122}