test(skills): cover same-name inspect/install provenance mixup

Pin ClawHub to GitHub-style identifiers and keep catalog metadata
from being paired with a foreign same-named bundle.
This commit is contained in:
xxxigm
2026-08-17 22:22:17 +07:00
committed by kshitij
parent 696fef6214
commit a6ddfa5769
2 changed files with 151 additions and 0 deletions

View File

@@ -186,6 +186,101 @@ def test_check_for_skill_updates_does_not_fall_back_across_registries():
assert "bundle" not in results[0], "must not carry a foreign registry's bundle"
def test_resolve_does_not_pair_catalog_meta_with_foreign_same_name_bundle():
"""Inspect metadata from one registry must not ship with another registry's files.
skills.sh can inspect ``owner/repo/skills/skillopt`` while ClawHub used to
fetch by last path segment ``skillopt`` and return a different author's
SKILL.md. The header then showed the requested identifier and the preview
showed the wrong skill.
"""
from hermes_cli.skills_hub import _resolve_source_meta_and_bundle
from tools.skills_hub import SkillBundle, SkillMeta
class CatalogSource:
def inspect(self, identifier):
return SkillMeta(
name="skillopt",
description="kanban-based pipelines",
source="skills.sh",
identifier="skills-sh/latipun7/agent-skill-collections/skills/skillopt",
trust_level="community",
)
def fetch(self, identifier):
return None
class ForeignSlugSource:
def inspect(self, identifier):
return SkillMeta(
name="skillopt",
description="Train, evaluate, and improve Agent skill files",
source="clawhub",
identifier="skillopt",
trust_level="community",
)
def fetch(self, identifier):
return SkillBundle(
name="skillopt",
files={"SKILL.md": "# Train, evaluate, and improve Agent skill files\n"},
source="clawhub",
identifier="skillopt",
trust_level="community",
)
meta, bundle, matched = _resolve_source_meta_and_bundle(
"latipun7/agent-skill-collections/skills/skillopt",
[CatalogSource(), ForeignSlugSource()],
)
assert bundle is not None
assert bundle.source == "clawhub"
assert meta is not None
assert meta.source == "clawhub"
assert meta.identifier == "skillopt"
assert "kanban-based" not in (meta.description or "")
assert matched is not None
assert matched.__class__ is ForeignSlugSource
def test_resolve_keeps_catalog_meta_when_later_sources_do_not_fetch():
from hermes_cli.skills_hub import _resolve_source_meta_and_bundle
from tools.skills_hub import SkillMeta
class CatalogSource:
def inspect(self, identifier):
return SkillMeta(
name="skillopt",
description="kanban-based pipelines",
source="skills.sh",
identifier="skills-sh/latipun7/agent-skill-collections/skills/skillopt",
trust_level="community",
)
def fetch(self, identifier):
return None
class QuietSource:
def inspect(self, identifier):
return None
def fetch(self, identifier):
return None
meta, bundle, matched = _resolve_source_meta_and_bundle(
"latipun7/agent-skill-collections/skills/skillopt",
[CatalogSource(), QuietSource()],
)
assert bundle is None
assert meta is not None
assert meta.source == "skills.sh"
assert meta.identifier.endswith("latipun7/agent-skill-collections/skills/skillopt")
assert matched is not None
assert matched.__class__ is CatalogSource
# ---------------------------------------------------------------------------

View File

@@ -370,6 +370,62 @@ class TestClawHubSource(unittest.TestCase):
self.assertEqual(results[0].identifier, "only-skill")
mock_write_cache.assert_called_once()
def test_parse_identifier_accepts_clawhub_shapes(self):
self.assertEqual(ClawHubSource._parse_identifier("skillopt"), ("skillopt", None))
self.assertEqual(ClawHubSource._parse_identifier("clawhub/skillopt"), ("skillopt", None))
self.assertEqual(
ClawHubSource._parse_identifier("@harrylabsj/skillopt"),
("skillopt", "harrylabsj"),
)
self.assertEqual(
ClawHubSource._parse_identifier("harrylabsj/skills/skillopt"),
("skillopt", "harrylabsj"),
)
def test_parse_identifier_rejects_github_style_paths(self):
self.assertIsNone(
ClawHubSource._parse_identifier("latipun7/agent-skill-collections/skillopt")
)
self.assertIsNone(
ClawHubSource._parse_identifier(
"latipun7/agent-skill-collections/skills/skillopt"
)
)
self.assertIsNone(
ClawHubSource._parse_identifier(
"skills-sh/latipun7/agent-skill-collections/skills/skillopt"
)
)
@patch("tools.skills_hub.httpx.get")
def test_inspect_does_not_claim_github_style_identifier(self, mock_get):
meta = self.src.inspect("latipun7/agent-skill-collections/skills/skillopt")
self.assertIsNone(meta)
mock_get.assert_not_called()
@patch("tools.skills_hub.httpx.get")
def test_fetch_does_not_claim_github_style_identifier(self, mock_get):
bundle = self.src.fetch("latipun7/agent-skill-collections/skillopt")
self.assertIsNone(bundle)
mock_get.assert_not_called()
@patch("tools.skills_hub.httpx.get")
def test_inspect_rejects_owner_mismatch_on_clawhub_url_path(self, mock_get):
mock_get.return_value = _MockResponse(
status_code=200,
json_data={
"slug": "skillopt",
"displayName": "SkillOpt",
"summary": "Train, evaluate, and improve Agent skill files",
"owner": {"handle": "harrylabsj"},
},
)
meta = self.src.inspect("latipun7/skills/skillopt")
self.assertIsNone(meta)
mock_get.assert_called_once()
class TestClawHubCatalogWalkBounded(unittest.TestCase):
"""max_items bounds the walk so browse's cold-start fallback renders one