diff --git a/crates/skills/src/commands.rs b/crates/skills/src/commands.rs index 5428d3ddf..5cf4b3acd 100644 --- a/crates/skills/src/commands.rs +++ b/crates/skills/src/commands.rs @@ -140,10 +140,15 @@ fn locale_compare(a: &str, b: &str) -> std::cmp::Ordering { fn check(io: &mut Io) -> R<()> { let (sys, _) = ctx(io); let root = sys.find_project_root(); - // Home-rooted checkout = user-level install. Use User scope so leftover - // project-layout dirs and unrelated harness skills cannot make a current - // impeccable install look stale (#824). - let scope = if sys.is_home_dir(&root) { Some(Scope::User) } else { None }; + // Prefer the user-level tree when one exists so leftover project-layout + // dirs cannot make a current install look stale (#824). Stay on inferred + // scope otherwise so a home-rooted project install (`install -y`) is + // still visible. + let scope = if sys.is_home_dir(&root) && sys.is_already_installed(&root, Some(Scope::User)).is_some() { + Some(Scope::User) + } else { + None + }; if sys.is_already_installed(&root, scope).is_none() { out(io, "Impeccable is not installed in this project."); out(io, "Run `npx impeccable install` to install."); diff --git a/crates/skills/tests/drift_ports_tests.rs b/crates/skills/tests/drift_ports_tests.rs index 093e76794..4d37efd87 100644 --- a/crates/skills/tests/drift_ports_tests.rs +++ b/crates/skills/tests/drift_ports_tests.rs @@ -527,6 +527,33 @@ fn check_ignores_leftover_pi_project_layout_in_home_rooted_tree() { std::fs::remove_dir_all(&root).ok(); } +#[test] +fn check_sees_home_rooted_project_scope_pi_install() { + let root = temp_root("check-824-pi-project"); + let home = format!("{root}/home"); + let tmpdir = format!("{root}/tmp"); + for d in [&home, &tmpdir] { + std::fs::create_dir_all(d).unwrap(); + } + std::fs::create_dir_all(format!("{home}/.git")).unwrap(); + let bundle_root = create_fake_universal_bundle(&home, &[".pi"]); + let env = base_env(&home, &tmpdir, &bundle_root); + + let r = run_cli( + &["install", "-y", "--scope=project", "--no-hooks", "--providers=pi"], + &home, + &env, + ); + assert_eq!(r.code, 0, "{}\n{}", r.stdout, r.stderr); + assert!(std::path::Path::new(&format!("{home}/.pi/skills/impeccable/SKILL.md")).exists()); + assert!(!std::path::Path::new(&format!("{home}/.pi/agent/skills/impeccable/SKILL.md")).exists()); + + let r = run_cli(&["check"], &home, &env); + assert!(!r.stdout.contains("not installed"), "{}\n{}", r.stdout, r.stderr); + assert!(r.stdout.contains("Skills are up to date"), "{}\n{}", r.stdout, r.stderr); + std::fs::remove_dir_all(&root).ok(); +} + #[test] fn check_reports_stale_impeccable_in_home_rooted_tree() { let root = temp_root("check-824-stale");