fix(skills): resolve skill_view by frontmatter name when dir name differs

skills_list() surfaces each skill's frontmatter `name:`, but skill_view()
only matched on the on-disk directory name (Strategy 2). When a skill's
directory is a shorter category/alias that differs from its frontmatter
name, skill_view(name) failed to find it. Extend the recursive Strategy-2
walk to also match frontmatter `name:`, guarded by a try/except so an
unreadable/malformed SKILL.md can't break discovery.

Adds a regression test that creates a skill whose directory name differs
from its frontmatter name and asserts skill_view resolves it (fails on
current main, passes with this change).

Salvaged the skill_view fix from #39682 onto current main as a standalone,
single-concern change with the test the original PR lacked.

Co-authored-by: foras910521-lab <foras910521-lab@users.noreply.github.com>
This commit is contained in:
kshitijk4poor
2026-06-10 10:51:45 +05:30
co-authored by foras910521-lab
parent bf7abc2f73
commit 9caa12f4ec
2 changed files with 32 additions and 1 deletions
+12 -1
View File
@@ -1032,10 +1032,21 @@ def skill_view(
_record(None, categorized_path.with_suffix(".md"))
# Strategy 2: recursive by directory name (catches nested skills
# like "foundations/runtime/explore-codebase" called by bare name).
# like "foundations/runtime/explore-codebase" called by bare name),
# plus frontmatter `name:` lookup. `skills_list()` exposes the
# frontmatter name, so `skill_view(name)` must accept it too even
# when the on-disk directory is a shorter category/alias.
for found_skill_md in iter_skill_index_files(search_dir, "SKILL.md"):
if found_skill_md.parent.name == name:
_record(found_skill_md.parent, found_skill_md)
continue
try:
fm_content = found_skill_md.read_text(encoding="utf-8")
fm, _ = _parse_frontmatter(fm_content)
except Exception:
fm = {}
if fm.get("name") == name:
_record(found_skill_md.parent, found_skill_md)
# Strategy 3: legacy flat <name>.md files anywhere under the dir.
for found_md in search_dir.rglob(f"{name}.md"):