1#[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 gh_auth_is_passthrough() {
67 assert_eq!(classify("gh auth login", &[]), OutputPolicy::Passthrough);
68 }
69
70 #[test]
71 fn gh_api_is_verbatim() {
72 assert_eq!(
74 classify("gh api repos/owner/repo/issues", &[]),
75 OutputPolicy::Verbatim
76 );
77 }
78
79 #[test]
80 fn user_excluded_is_passthrough() {
81 let excl = vec!["mycommand".to_string()];
82 assert_eq!(
83 classify("mycommand --flag", &excl),
84 OutputPolicy::Passthrough
85 );
86 }
87
88 #[test]
89 fn curl_is_verbatim() {
90 assert_eq!(
91 classify("curl https://api.example.com", &[]),
92 OutputPolicy::Verbatim
93 );
94 }
95
96 #[test]
97 fn cat_is_verbatim() {
98 assert_eq!(classify("cat package.json", &[]), OutputPolicy::Verbatim);
99 }
100
101 #[test]
102 fn cargo_build_is_compressible() {
103 assert_eq!(classify("cargo build", &[]), OutputPolicy::Compressible);
104 }
105
106 #[test]
107 fn npm_test_is_compressible() {
108 assert_eq!(classify("npm test", &[]), OutputPolicy::Compressible);
109 }
110
111 #[test]
112 fn dev_server_is_passthrough() {
113 assert_eq!(classify("npm run dev", &[]), OutputPolicy::Passthrough);
114 assert_eq!(classify("cargo watch", &[]), OutputPolicy::Passthrough);
115 assert_eq!(classify("cargo run", &[]), OutputPolicy::Passthrough);
116 }
117
118 #[test]
119 fn git_diff_is_verbatim() {
120 let policy = classify("git diff", &[]);
125 assert_eq!(policy, OutputPolicy::Compressible);
130 }
131
132 #[test]
133 fn auth_commands_are_passthrough() {
134 assert_eq!(classify("az login", &[]), OutputPolicy::Passthrough);
135 assert_eq!(
136 classify("gcloud auth login", &[]),
137 OutputPolicy::Passthrough
138 );
139 assert_eq!(classify("firebase login", &[]), OutputPolicy::Passthrough);
140 }
141
142 #[test]
143 fn jq_is_verbatim() {
144 assert_eq!(
145 classify("jq '.items' data.json", &[]),
146 OutputPolicy::Verbatim
147 );
148 }
149
150 #[test]
151 fn unknown_command_is_compressible() {
152 assert_eq!(
153 classify("some-random-tool --flag", &[]),
154 OutputPolicy::Compressible
155 );
156 }
157
158 #[test]
159 fn piped_jq_is_verbatim() {
160 assert_eq!(
161 classify("kubectl get pods -o json | jq '.items[]'", &[]),
162 OutputPolicy::Verbatim
163 );
164 }
165
166 #[test]
167 fn policy_is_protected() {
168 assert!(OutputPolicy::Passthrough.is_protected());
169 assert!(OutputPolicy::Verbatim.is_protected());
170 assert!(!OutputPolicy::Compressible.is_protected());
171 }
172
173 #[test]
176 fn issue_198_gh_api_jq() {
177 assert_eq!(
179 classify("gh api repos/yvgude/lean-ctx/issues/198 --jq '.body'", &[]),
180 OutputPolicy::Verbatim
181 );
182 }
183
184 #[test]
185 fn issue_159_cat_pubspec() {
186 assert_eq!(classify("cat pubspec.yaml", &[]), OutputPolicy::Verbatim);
187 }
188
189 #[test]
190 fn issue_114_git_stash() {
191 let p = classify("git stash show", &[]);
196 assert_eq!(p, OutputPolicy::Compressible);
197 }
198
199 #[test]
200 fn issue_194_git_diff_raw() {
201 let p = classify("git diff --cached", &[]);
203 assert_eq!(p, OutputPolicy::Compressible);
204 }
205
206 #[test]
207 fn npm_install_is_compressible() {
208 assert_eq!(
210 classify("npm install -g deepseek-tui", &[]),
211 OutputPolicy::Compressible
212 );
213 }
214
215 #[test]
216 fn pip_install_is_compressible() {
217 assert_eq!(
218 classify("pip install flask", &[]),
219 OutputPolicy::Compressible
220 );
221 }
222
223 #[test]
224 fn kubectl_get_yaml_is_verbatim() {
225 assert_eq!(
226 classify("kubectl get pods -o yaml", &[]),
227 OutputPolicy::Verbatim
228 );
229 }
230
231 #[test]
232 fn docker_inspect_is_verbatim() {
233 assert_eq!(
234 classify("docker inspect my-container", &[]),
235 OutputPolicy::Verbatim
236 );
237 }
238
239 #[test]
240 fn terraform_output_is_verbatim() {
241 assert_eq!(classify("terraform output", &[]), OutputPolicy::Verbatim);
242 }
243
244 #[test]
245 fn heroku_logs_is_verbatim() {
246 assert_eq!(classify("heroku logs --tail", &[]), OutputPolicy::Verbatim);
247 }
248
249 #[test]
250 fn gh_pr_list_is_compressible() {
251 assert_eq!(classify("gh pr list", &[]), OutputPolicy::Compressible);
252 }
253
254 #[test]
255 fn lean_ctx_is_passthrough() {
256 assert_eq!(
257 classify("lean-ctx init powershell", &[]),
258 OutputPolicy::Passthrough
259 );
260 assert_eq!(
261 classify("lean-ctx overview", &[]),
262 OutputPolicy::Passthrough
263 );
264 }
265
266 #[test]
267 fn stripe_list_is_verbatim() {
268 assert_eq!(classify("stripe charges list", &[]), OutputPolicy::Verbatim);
269 }
270
271 #[test]
274 fn git_commit_is_verbatim() {
275 assert_eq!(
276 classify("git commit -m \"feat: add feature\"", &[]),
277 OutputPolicy::Verbatim
278 );
279 }
280
281 #[test]
282 fn git_push_is_verbatim() {
283 assert_eq!(
284 classify("git push origin main", &[]),
285 OutputPolicy::Verbatim
286 );
287 }
288
289 #[test]
290 fn git_pull_is_verbatim() {
291 assert_eq!(classify("git pull --rebase", &[]), OutputPolicy::Verbatim);
292 }
293
294 #[test]
295 fn git_merge_is_verbatim() {
296 assert_eq!(
297 classify("git merge feature-branch", &[]),
298 OutputPolicy::Verbatim
299 );
300 }
301
302 #[test]
303 fn git_rebase_is_verbatim() {
304 assert_eq!(classify("git rebase main", &[]), OutputPolicy::Verbatim);
305 }
306
307 #[test]
308 fn git_cherry_pick_is_verbatim() {
309 assert_eq!(
310 classify("git cherry-pick abc1234", &[]),
311 OutputPolicy::Verbatim
312 );
313 }
314
315 #[test]
316 fn git_tag_is_verbatim() {
317 assert_eq!(classify("git tag v1.0.0", &[]), OutputPolicy::Verbatim);
318 }
319
320 #[test]
321 fn git_status_still_compressible() {
322 assert_eq!(classify("git status", &[]), OutputPolicy::Compressible);
323 }
324
325 #[test]
326 fn git_log_still_compressible() {
327 assert_eq!(
328 classify("git log --oneline", &[]),
329 OutputPolicy::Compressible
330 );
331 }
332}