@@ -38,9 +38,11 @@ pub struct CaptureManager {
3838 pub tag_to_index : HashMap < String , usize > ,
3939 pub num_turns : usize ,
4040 pub num_tools_this_turn : usize ,
41- // test
4241 pub last_user_message : Option < String > ,
4342 pub user_message_lock : bool ,
43+ /// If true, delete the current session's shadow repo directory when dropped.
44+ #[ serde( default ) ]
45+ pub clean_on_drop : bool ,
4446}
4547
4648#[ derive( Debug , Clone , Serialize , Deserialize ) ]
@@ -65,7 +67,10 @@ impl CaptureManager {
6567 ) ;
6668 }
6769 // Reuse bare repo init to keep storage model consistent.
68- Self :: manual_init ( os, shadow_path) . await
70+ let mut s = Self :: manual_init ( os, shadow_path) . await ?;
71+ // Auto-initialized captures are considered ephemeral: clean when session ends.
72+ s. clean_on_drop = true ;
73+ Ok ( s)
6974 }
7075
7176 pub async fn manual_init ( os : & Os , path : impl AsRef < Path > ) -> Result < Self > {
@@ -103,6 +108,7 @@ impl CaptureManager {
103108 num_tools_this_turn : 0 ,
104109 last_user_message : None ,
105110 user_message_lock : false ,
111+ clean_on_drop : false ,
106112 } )
107113 }
108114
@@ -229,6 +235,31 @@ impl CaptureManager {
229235 }
230236}
231237
238+ impl Drop for CaptureManager {
239+ fn drop ( & mut self ) {
240+ // Only clean if this session was auto-initialized (ephemeral).
241+ if !self . clean_on_drop {
242+ return ;
243+ }
244+ let path = self . shadow_repo_path . clone ( ) ;
245+ // Prefer spawning on an active Tokio runtime if available.
246+ if let Ok ( handle) = tokio:: runtime:: Handle :: try_current ( ) {
247+ handle. spawn ( async move {
248+ // Best-effort: swallow errors; we don't want to block Drop or panic here.
249+ let _ = tokio:: fs:: remove_dir_all ( path) . await ;
250+ } ) ;
251+ return ;
252+ }
253+
254+ // Fallback: spawn a detached background thread. Still non-blocking.
255+ let _ = std:: thread:: Builder :: new ( )
256+ . name ( "q-capture-cleaner" . into ( ) )
257+ . spawn ( move || {
258+ let _ = std:: fs:: remove_dir_all ( & path) ;
259+ } ) ;
260+ }
261+ }
262+
232263pub const CAPTURE_MESSAGE_MAX_LENGTH : usize = 60 ;
233264
234265pub fn truncate_message ( s : & str , max_chars : usize ) -> String {
0 commit comments