@@ -16,8 +16,11 @@ fn collect_watch_paths(store: &SkillStore) -> Vec<PathBuf> {
1616 let mut paths = vec ! [ central_repo:: skills_dir( ) , central_repo:: scenarios_dir( ) ] ;
1717
1818 for adapter in tool_adapters:: all_tool_adapters ( store) {
19- paths. push ( adapter. skills_dir ( ) ) ;
20- paths. extend ( adapter. all_scan_dirs ( ) ) ;
19+ let skills_dir = adapter. skills_dir ( ) ;
20+ if skills_dir. exists ( ) {
21+ paths. push ( skills_dir) ;
22+ }
23+ paths. extend ( adapter. additional_existing_scan_dirs ( ) ) ;
2124 }
2225
2326 if let Ok ( projects) = store. get_all_projects ( ) {
@@ -71,15 +74,19 @@ fn watch_target(path: &Path) -> Option<PathBuf> {
7174 . map ( |parent| parent. to_path_buf ( ) )
7275}
7376
77+ fn collect_watch_targets ( store : & SkillStore ) -> HashSet < PathBuf > {
78+ collect_watch_paths ( store)
79+ . into_iter ( )
80+ . filter_map ( |path| watch_target ( & path) )
81+ . collect ( )
82+ }
83+
7484fn sync_watch_set (
7585 watcher : & mut RecommendedWatcher ,
7686 watched : & mut HashSet < PathBuf > ,
7787 store : & SkillStore ,
7888) {
79- let desired: HashSet < PathBuf > = collect_watch_paths ( store)
80- . into_iter ( )
81- . filter_map ( |path| watch_target ( & path) )
82- . collect ( ) ;
89+ let desired = collect_watch_targets ( store) ;
8390
8491 for stale in watched. difference ( & desired) . cloned ( ) . collect :: < Vec < _ > > ( ) {
8592 if let Err ( err) = watcher. unwatch ( & stale) {
@@ -156,8 +163,11 @@ pub fn start_file_watcher<R: tauri::Runtime>(app: tauri::AppHandle<R>, store: Ar
156163
157164#[ cfg( test) ]
158165mod tests {
159- use super :: collect_watch_paths;
160- use crate :: core:: skill_store:: { ProjectRecord , SkillStore } ;
166+ use super :: { collect_watch_paths, collect_watch_targets} ;
167+ use crate :: core:: {
168+ skill_store:: { ProjectRecord , SkillStore } ,
169+ tool_adapters:: CustomToolDef ,
170+ } ;
161171 use std:: fs;
162172 use tempfile:: tempdir;
163173
@@ -192,4 +202,32 @@ mod tests {
192202 assert ! ( !paths. contains( & skills_root. parent( ) . unwrap( ) . to_path_buf( ) ) ) ;
193203 assert ! ( !paths. contains( & disabled_root. parent( ) . unwrap( ) . to_path_buf( ) ) ) ;
194204 }
205+
206+ #[ test]
207+ fn missing_global_agent_paths_do_not_watch_parent_directories ( ) {
208+ let tmp = tempdir ( ) . unwrap ( ) ;
209+ let db_path = tmp. path ( ) . join ( "watcher.db" ) ;
210+ let custom_parent = tmp. path ( ) . join ( "custom-agent" ) ;
211+ let missing_skills_root = custom_parent. join ( "skills" ) ;
212+ fs:: create_dir_all ( & custom_parent) . unwrap ( ) ;
213+
214+ let store = SkillStore :: new ( & db_path) . unwrap ( ) ;
215+ store
216+ . set_setting (
217+ "custom_tools" ,
218+ & serde_json:: to_string ( & vec ! [ CustomToolDef {
219+ key: "missing_custom" . to_string( ) ,
220+ display_name: "Missing Custom" . to_string( ) ,
221+ skills_dir: missing_skills_root. to_string_lossy( ) . to_string( ) ,
222+ project_relative_skills_dir: None ,
223+ } ] )
224+ . unwrap ( ) ,
225+ )
226+ . unwrap ( ) ;
227+
228+ let targets = collect_watch_targets ( & store) ;
229+
230+ assert ! ( !targets. contains( & custom_parent) ) ;
231+ assert ! ( !targets. contains( & missing_skills_root) ) ;
232+ }
195233}
0 commit comments