diff --git a/bin/doctor b/bin/doctor index ceab5df..784bdf5 100755 --- a/bin/doctor +++ b/bin/doctor @@ -109,6 +109,15 @@ do continue fi + # A real directory where a link belongs holds content nothing manages: it + # cannot receive new skills and silently shadows the checkout. Distinguished + # from the foreign-checkout case below because the fix differs — move it + # aside and re-run install.sh, rather than re-point a link. + if [ ! -L "$dir" ] && [ -d "$dir" ]; then + add FAIL unmanaged "$dir is a real directory, not a link into the checkout — it holds $(count_skills "$dir") unmanaged skill(s); move it aside and re-run install.sh" + continue + fi + # Resolve to a physical path and confirm it lands inside THIS checkout. # A link that resolves to a different checkout is the dangerous case: it # works, so nothing complains, while serving stale content. diff --git a/tests/doctor_test.sh b/tests/doctor_test.sh index f18eb8d..3265961 100644 --- a/tests/doctor_test.sh +++ b/tests/doctor_test.sh @@ -112,6 +112,19 @@ mkdir -p "$f/home/.claude/skills" ln -sfn "$f/ck/skills/alpha" "$f/home/.claude/skills/alpha" assert_fails "$f" 'legacy' 'leftover per-skill Claude symlinks are reported' +# --- 7b. harness dir is a REAL directory, not a link into the checkout ------- +# Found on flamingo 2026-08-26: ~/.config/crush/skills held real directories +# from a pre-plugin install. The old message read "resolves to +# , outside the active checkout" — naming the directory as its own +# resolution target, which is true but useless. It must say the dir is not a +# link at all, because the fix (move it aside, re-run install.sh) is different +# from the fix for a link into a foreign checkout. +f=$(new_fixture realdir) +mkdir -p "$f/home/.agents" "$f/home/.config/crush/skills/alpha" +ln -sfn "$f/ck/skills" "$f/home/.agents/skills" +printf -- '---\nname: alpha\ndescription: a\n---\n' > "$f/home/.config/crush/skills/alpha/SKILL.md" +assert_fails "$f" 'not a link' 'real directory is reported as unmanaged, not as "outside"' + # --- 7. dangling link inside a harness dir (not the canonical link itself) -- # Exercises the per-entry scan rather than the canonical-link check: this is # the shape the 243 dead links actually had.