fix(skills): ignore support docs in skill discovery
Support files under references/, templates/, assets/, and scripts/ are progressive-disclosure data loaded through skill_view(..., file_path=...). They should not be treated as standalone skills during discovery or collision checks. This prevents archived skill packages or support markdown files inside a real skill from shadowing active skills with the same name while still allowing top-level categories named scripts/templates/assets/references. Tests cover: - pruning nested SKILL.md files inside skill support directories - preserving support-named top-level categories - avoiding skill_view collisions from support markdown - keeping archived package SKILL.md files accessible only through file_path
This commit is contained in:
committed by
Teknium
parent
7493de7fc3
commit
9137b86a52
@@ -1225,6 +1225,89 @@ class TestSkillViewCollisionDetection:
|
||||
assert result["success"] is True
|
||||
assert "LOCAL VERSION" in result["content"]
|
||||
|
||||
def test_support_markdown_does_not_collide_with_real_skill(self, tmp_path):
|
||||
"""Supporting reference docs named <skill>.md are not skills.
|
||||
|
||||
A real-world regression had creative/sketch/SKILL.md become
|
||||
unloadable because another skill carried
|
||||
references/styles/sketch.md. Support files are loaded via
|
||||
skill_view(skill, file_path=...), not as bare skill names.
|
||||
"""
|
||||
local_dir = tmp_path / "local"
|
||||
external_dir = tmp_path / "external"
|
||||
local_dir.mkdir()
|
||||
external_dir.mkdir()
|
||||
|
||||
_make_skill(local_dir, "article-illustrator", category="creative")
|
||||
support_file = (
|
||||
local_dir
|
||||
/ "creative"
|
||||
/ "article-illustrator"
|
||||
/ "references"
|
||||
/ "styles"
|
||||
/ "sketch.md"
|
||||
)
|
||||
support_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
support_file.write_text("# Sketch style support doc\n")
|
||||
_make_skill(local_dir, "sketch", category="creative", body="REAL SKETCH SKILL")
|
||||
|
||||
p1, p2 = self._patch_dirs(local_dir, [external_dir])
|
||||
with p1, p2:
|
||||
raw = skill_view("sketch")
|
||||
|
||||
result = json.loads(raw)
|
||||
assert result["success"] is True
|
||||
assert result["path"] == "creative/sketch/SKILL.md"
|
||||
assert "REAL SKETCH SKILL" in result["content"]
|
||||
|
||||
def test_reference_package_skill_md_is_not_active_skill(self, tmp_path):
|
||||
"""Curator-preserved package SKILL.md files under references stay data.
|
||||
|
||||
Umbrella consolidations may preserve an old skill as
|
||||
references/old-skill-package/SKILL.md. That package must not appear in
|
||||
skills_list/system prompts and must not resolve as skill_view("old-skill").
|
||||
The package can still be opened explicitly through the umbrella's
|
||||
file_path progressive-disclosure channel.
|
||||
"""
|
||||
local_dir = tmp_path / "local"
|
||||
external_dir = tmp_path / "external"
|
||||
local_dir.mkdir()
|
||||
external_dir.mkdir()
|
||||
|
||||
_make_skill(local_dir, "umbrella", category="creative", body="UMBRELLA")
|
||||
package = (
|
||||
local_dir
|
||||
/ "creative"
|
||||
/ "umbrella"
|
||||
/ "references"
|
||||
/ "old-skill-package"
|
||||
)
|
||||
package.mkdir(parents=True, exist_ok=True)
|
||||
(package / "SKILL.md").write_text(
|
||||
"---\nname: old-skill\ndescription: Preserved old skill.\n---\n\nOLD BODY\n"
|
||||
)
|
||||
|
||||
p1, p2 = self._patch_dirs(local_dir, [external_dir])
|
||||
with p1, p2:
|
||||
names = {skill["name"] for skill in _find_all_skills()}
|
||||
old_raw = skill_view("old-skill")
|
||||
direct_package_raw = skill_view("creative/umbrella/references/old-skill-package")
|
||||
package_raw = skill_view(
|
||||
"umbrella", file_path="references/old-skill-package/SKILL.md"
|
||||
)
|
||||
|
||||
assert "umbrella" in names
|
||||
assert "old-skill" not in names
|
||||
old_result = json.loads(old_raw)
|
||||
assert old_result["success"] is False
|
||||
assert "not found" in old_result["error"]
|
||||
direct_package_result = json.loads(direct_package_raw)
|
||||
assert direct_package_result["success"] is False
|
||||
assert "not found" in direct_package_result["error"]
|
||||
package_result = json.loads(package_raw)
|
||||
assert package_result["success"] is True
|
||||
assert "OLD BODY" in package_result["content"]
|
||||
|
||||
def test_external_skill_resolves_when_no_collision(self, tmp_path):
|
||||
"""External-only skills still resolve normally when there's no
|
||||
local skill of the same name."""
|
||||
|
||||
Reference in New Issue
Block a user