lean_ctx/shell/
output_policy.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum OutputPolicy {
16 Passthrough,
20
21 Verbatim,
25
26 Compressible,
30}
31
32impl OutputPolicy {
33 pub fn is_protected(&self) -> bool {
36 matches!(self, Self::Passthrough | Self::Verbatim)
37 }
38}
39
40pub fn classify(command: &str, user_excluded: &[String]) -> OutputPolicy {
48 if is_passthrough(command, user_excluded) {
49 return OutputPolicy::Passthrough;
50 }
51 if super::compress::is_verbatim_output(command) {
52 return OutputPolicy::Verbatim;
53 }
54 OutputPolicy::Compressible
55}
56
57fn is_passthrough(command: &str, user_excluded: &[String]) -> bool {
58 super::compress::is_excluded_command(command, user_excluded)
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn passthrough_beats_verbatim() {
67 assert_eq!(
70 classify("gh api repos/owner/repo/issues", &[]),
71 OutputPolicy::Passthrough
72 );
73 }
74
75 #[test]
76 fn user_excluded_is_passthrough() {
77 let excl = vec!["mycommand".to_string()];
78 assert_eq!(
79 classify("mycommand --flag", &excl),
80 OutputPolicy::Passthrough
81 );
82 }
83
84 #[test]
85 fn curl_is_verbatim() {
86 assert_eq!(
87 classify("curl https://api.example.com", &[]),
88 OutputPolicy::Verbatim
89 );
90 }
91
92 #[test]
93 fn cat_is_verbatim() {
94 assert_eq!(classify("cat package.json", &[]), OutputPolicy::Verbatim);
95 }
96
97 #[test]
98 fn cargo_build_is_compressible() {
99 assert_eq!(classify("cargo build", &[]), OutputPolicy::Compressible);
100 }
101
102 #[test]
103 fn npm_test_is_compressible() {
104 assert_eq!(classify("npm test", &[]), OutputPolicy::Compressible);
105 }
106
107 #[test]
108 fn dev_server_is_passthrough() {
109 assert_eq!(classify("npm run dev", &[]), OutputPolicy::Passthrough);
110 assert_eq!(classify("cargo watch", &[]), OutputPolicy::Passthrough);
111 assert_eq!(classify("cargo run", &[]), OutputPolicy::Passthrough);
112 }
113
114 #[test]
115 fn git_diff_is_verbatim() {
116 let policy = classify("git diff", &[]);
121 assert_eq!(policy, OutputPolicy::Compressible);
126 }
127
128 #[test]
129 fn auth_commands_are_passthrough() {
130 assert_eq!(classify("az login", &[]), OutputPolicy::Passthrough);
131 assert_eq!(
132 classify("gcloud auth login", &[]),
133 OutputPolicy::Passthrough
134 );
135 assert_eq!(classify("firebase login", &[]), OutputPolicy::Passthrough);
136 }
137
138 #[test]
139 fn jq_is_verbatim() {
140 assert_eq!(
141 classify("jq '.items' data.json", &[]),
142 OutputPolicy::Verbatim
143 );
144 }
145
146 #[test]
147 fn unknown_command_is_compressible() {
148 assert_eq!(
149 classify("some-random-tool --flag", &[]),
150 OutputPolicy::Compressible
151 );
152 }
153
154 #[test]
155 fn piped_jq_is_verbatim() {
156 assert_eq!(
157 classify("kubectl get pods -o json | jq '.items[]'", &[]),
158 OutputPolicy::Verbatim
159 );
160 }
161
162 #[test]
163 fn policy_is_protected() {
164 assert!(OutputPolicy::Passthrough.is_protected());
165 assert!(OutputPolicy::Verbatim.is_protected());
166 assert!(!OutputPolicy::Compressible.is_protected());
167 }
168
169 #[test]
172 fn issue_198_gh_api_jq() {
173 assert_eq!(
175 classify("gh api repos/yvgude/lean-ctx/issues/198 --jq '.body'", &[]),
176 OutputPolicy::Passthrough
177 );
178 }
179
180 #[test]
181 fn issue_159_cat_pubspec() {
182 assert_eq!(classify("cat pubspec.yaml", &[]), OutputPolicy::Verbatim);
183 }
184
185 #[test]
186 fn issue_114_git_stash() {
187 let p = classify("git stash show", &[]);
192 assert_eq!(p, OutputPolicy::Compressible);
193 }
194
195 #[test]
196 fn issue_194_git_diff_raw() {
197 let p = classify("git diff --cached", &[]);
199 assert_eq!(p, OutputPolicy::Compressible);
200 }
201
202 #[test]
203 fn npm_install_is_compressible() {
204 assert_eq!(
206 classify("npm install -g deepseek-tui", &[]),
207 OutputPolicy::Compressible
208 );
209 }
210
211 #[test]
212 fn pip_install_is_compressible() {
213 assert_eq!(
214 classify("pip install flask", &[]),
215 OutputPolicy::Compressible
216 );
217 }
218
219 #[test]
220 fn kubectl_get_yaml_is_verbatim() {
221 assert_eq!(
222 classify("kubectl get pods -o yaml", &[]),
223 OutputPolicy::Verbatim
224 );
225 }
226
227 #[test]
228 fn docker_inspect_is_verbatim() {
229 assert_eq!(
230 classify("docker inspect my-container", &[]),
231 OutputPolicy::Verbatim
232 );
233 }
234
235 #[test]
236 fn terraform_output_is_verbatim() {
237 assert_eq!(classify("terraform output", &[]), OutputPolicy::Verbatim);
238 }
239
240 #[test]
241 fn heroku_logs_is_verbatim() {
242 assert_eq!(classify("heroku logs --tail", &[]), OutputPolicy::Verbatim);
243 }
244
245 #[test]
246 fn gh_pr_list_is_passthrough() {
247 assert_eq!(classify("gh pr list", &[]), OutputPolicy::Passthrough);
249 }
250
251 #[test]
252 fn lean_ctx_is_passthrough() {
253 assert_eq!(
254 classify("lean-ctx init powershell", &[]),
255 OutputPolicy::Passthrough
256 );
257 assert_eq!(
258 classify("lean-ctx overview", &[]),
259 OutputPolicy::Passthrough
260 );
261 }
262
263 #[test]
264 fn stripe_list_is_verbatim() {
265 assert_eq!(classify("stripe charges list", &[]), OutputPolicy::Verbatim);
266 }
267}