From b90f219bd179766227a02f8e33cfa57ba5086d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?d=20=F0=9F=94=B9?= Date: Thu, 23 Apr 2026 14:06:14 +0800 Subject: [PATCH] fix(skills): validate bundled SKILL.md front-matter in CI (fixes #2443) (#2457) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(skills): validate bundled SKILL.md front-matter in CI (fixes #2443) Adds a parametrized backend test that runs `_validate_skill_frontmatter` against every bundled SKILL.md under `skills/public/`, so a broken front-matter fails CI with a per-skill error message instead of surfacing as a runtime gateway-load warning. The new test caught two pre-existing breakages on `main` and fixes them: * `bootstrap/SKILL.md`: the unquoted description had a second `:` mid-line ("Also trigger for updates: ..."), which YAML parses as a nested mapping ("mapping values are not allowed here"). Rewrites the description as a folded scalar (`>-`), which preserves the original wording (including the embedded colon, double quotes, and apostrophes) without further escaping. This complements PR #2436 (single-file colon→hyphen patch) with a more general convention that survives future edits. * `chart-visualization/SKILL.md`: used `dependency:` which is not in `ALLOWED_FRONTMATTER_PROPERTIES`. Renamed to `compatibility:`, the documented field for "Required tools, dependencies" per skill-creator. No code reads `dependency` (verified by grep across backend/). * Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Fix the lint error --------- Co-authored-by: Willem Jiang Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- backend/tests/test_skills_bundled.py | 31 ++++++++++++++++++++++ skills/public/bootstrap/SKILL.md | 8 +++++- skills/public/chart-visualization/SKILL.md | 2 +- 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 backend/tests/test_skills_bundled.py diff --git a/backend/tests/test_skills_bundled.py b/backend/tests/test_skills_bundled.py new file mode 100644 index 000000000..0e99997a2 --- /dev/null +++ b/backend/tests/test_skills_bundled.py @@ -0,0 +1,31 @@ +"""Validate every bundled SKILL.md under skills/public/. + +Catches regressions like #2443 — a SKILL.md whose YAML front-matter fails to +parse (e.g. an unquoted description containing a colon, which YAML interprets +as a nested mapping). Each bundled skill is checked individually so the +failure message identifies the exact file. +""" + +from pathlib import Path + +import pytest + +from deerflow.skills.validation import _validate_skill_frontmatter + +SKILLS_PUBLIC_DIR = Path(__file__).resolve().parents[2] / "skills" / "public" +BUNDLED_SKILL_DIRS = sorted(p.parent for p in SKILLS_PUBLIC_DIR.rglob("SKILL.md")) + + +@pytest.mark.parametrize( + "skill_dir", + BUNDLED_SKILL_DIRS, + ids=lambda p: str(p.relative_to(SKILLS_PUBLIC_DIR)), +) +def test_bundled_skill_frontmatter_is_valid(skill_dir: Path) -> None: + valid, msg, name = _validate_skill_frontmatter(skill_dir) + assert valid, f"{skill_dir.relative_to(SKILLS_PUBLIC_DIR)}: {msg}" + assert name, f"{skill_dir.relative_to(SKILLS_PUBLIC_DIR)}: no name extracted" + + +def test_skills_public_dir_has_skills() -> None: + assert BUNDLED_SKILL_DIRS, f"no SKILL.md found under {SKILLS_PUBLIC_DIR}" diff --git a/skills/public/bootstrap/SKILL.md b/skills/public/bootstrap/SKILL.md index 38698d2d4..ab328d5fb 100644 --- a/skills/public/bootstrap/SKILL.md +++ b/skills/public/bootstrap/SKILL.md @@ -1,6 +1,12 @@ --- name: bootstrap -description: Generate a personalized SOUL.md through a warm, adaptive onboarding conversation. Trigger when the user wants to create, set up, or initialize their AI partner's identity — e.g., "create my SOUL.md", "bootstrap my agent", "set up my AI partner", "define who you are", "let's do onboarding", "personalize this AI", "make you mine", or when a SOUL.md is missing. Also trigger for updates: "update my SOUL.md", "change my AI's personality", "tweak the soul". +description: >- + Generate a personalized SOUL.md through a warm, adaptive onboarding conversation. + Trigger when the user wants to create, set up, or initialize their AI partner's + identity — e.g., "create my SOUL.md", "bootstrap my agent", "set up my AI + partner", "define who you are", "let's do onboarding", "personalize this AI", + "make you mine", or when a SOUL.md is missing. Also trigger for updates: + "update my SOUL.md", "change my AI's personality", "tweak the soul". --- # Bootstrap Soul diff --git a/skills/public/chart-visualization/SKILL.md b/skills/public/chart-visualization/SKILL.md index 7bc91344f..d7c6358d8 100644 --- a/skills/public/chart-visualization/SKILL.md +++ b/skills/public/chart-visualization/SKILL.md @@ -1,7 +1,7 @@ --- name: chart-visualization description: This skill should be used when the user wants to visualize data. It intelligently selects the most suitable chart type from 26 available options, extracts parameters based on detailed specifications, and generates a chart image using a JavaScript script. -dependency: +compatibility: nodejs: ">=18.0.0" ---