Skip to content

Skill catalog: label a skill whose frontmatter does not parse by its directory, and say why - #6

Merged
ligon merged 2 commits into
mainfrom
fix/skill-catalog-frontmatter-fallback
Sep 9, 2026
Merged

Skill catalog: label a skill whose frontmatter does not parse by its directory, and say why#6
ligon merged 2 commits into
mainfrom
fix/skill-catalog-frontmatter-fallback

Conversation

@ligon

@ligon ligon commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Companion to ligon/sucoder-skills#1 / ligon/sucoder-skills#2 (which fix the two affected skill files). This fixes the generator side so the next broken skill is visible instead of silent.

What was wrong. A SKILL.md whose YAML frontmatter fails to parse rendered in the session catalog as

- SKILL (load with `Read tool: ~/.sucoder/skills/workshop-problem/SKILL.md`)

_read_skill_metadata (sucoder/mirror.py) caught the YAMLError, set data = {}, and returned None; _readable_skill_name then fell back to path.stem, which for every Agent-Skills-style skill is the constant SKILL. Nothing was logged. Two shared skills shipped that way for ten weeks. A frontmatter that parsed to a non-mapping (a bare list) was worse: data.get raised AttributeError out of the prelude build.

Change.

  • _read_skill_metadata returns SkillMetadata(name, description, error) (a NamedTuple). A present-but-unusable frontmatter yields name="" and a one-line error with file coordinates — mapping values are not allowed here at line 3, column 164 — from PyYAML's problem / problem_mark. The reader does not invent a name.
  • _readable_skill_name falls back to the directory name for a SKILL.md (stem otherwise) and puts (frontmatter did not parse: …) in the description slot, so the catalog line carries the diagnosis.
  • The three call sites test metadata.name rather than truthiness and logger.warning once per broken skill per launch. A catalog file with broken frontmatter keeps its generic SKILL CATALOG header rather than being renamed to its directory.

Rendered against the live ~/.sucoder/skills on this node (pre-#2 checkout):

- workshop-problem — (frontmatter did not parse: mapping values are not allowed here at line 3, column 164)
- research-writer — (frontmatter did not parse: mapping values are not allowed here at line 3, column 314)
- prior-art-ledger — Use this skill at the start of a non-trivial task in an existing code repository, …

Tests. Five added in tests/test_mirror.py: broken / valid (regression pin) / non-mapping frontmatter at the unit level, the display-name fallback, and a prelude test that a catalog referencing a broken skill renders - workshop-problem — (frontmatter did not parse: mapping values are not allowed here and that no line starts with - SKILL. Full suite: 655 passed (650 on f72f815). mypy sucoder/mirror.py under the repo's [tool.mypy]: the same two pre-existing var-annotated errors before and after, none in the changed code.

Not changed. scripts/generate_unified_skills_catalog.py does not read local frontmatter (it fetches curated remote skills), so there is nothing to fail closed there — closing out a remark I made earlier that it might.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EVtHa4ZXum7AbKRRSsSNxm

…directory, and say why

A SKILL.md whose YAML frontmatter fails to parse rendered in the session
catalog as a bare "SKILL" -- no name, no description, nothing logged.
_read_skill_metadata swallowed the YAMLError and returned None, and
_readable_skill_name fell back to path.stem, which for every
Agent-Skills-style skill is the constant "SKILL".  Two shared skills
(workshop-problem, research-writer) shipped that way for ten weeks because
an unquoted ': ' in the description is a mapping indicator to YAML
(ligon/sucoder-skills#1, fixed there by ligon/sucoder-skills#2).

- _read_skill_metadata returns a SkillMetadata(name, description, error)
  NamedTuple.  A frontmatter block that is present but unusable -- YAML
  error, or a non-mapping document, which used to raise AttributeError out
  of the prelude build -- yields name "" and an actionable one-line error
  with FILE coordinates ("mapping values are not allowed here at line 3,
  column 163").  The reader does not invent a name.
- _readable_skill_name falls back to the directory name for a SKILL.md
  (the stem otherwise) and puts "(frontmatter did not parse: ...)" in the
  description slot, so the catalog line carries the diagnosis.
- The three call sites (_skill_blocks, _render_skill_catalog,
  _format_skill_reference) test metadata.name rather than truthiness and
  log a warning per broken skill per launch.  A catalog file with broken
  frontmatter keeps its generic "SKILL CATALOG" header.

Tests: unit tests for the broken / valid / non-mapping cases and the
display-name fallback, plus a prelude test asserting the entry reads
"- workshop-problem — (frontmatter did not parse: ..." and no line starts
with "- SKILL".  Full suite 655 passed (650 before).  mypy on
sucoder/mirror.py reports the same two pre-existing errors before and
after.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVtHa4ZXum7AbKRRSsSNxm
@ligon
ligon merged commit 80581c8 into main Sep 9, 2026
4 checks passed
@ligon
ligon deleted the fix/skill-catalog-frontmatter-fallback branch September 12, 2026 20:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant