MCPcopy Index your code
hub / github.com/VectifyAI/OpenKB / validate_skill

Function validate_skill

openkb/skill/validator.py:76–255  ·  view source on GitHub ↗

Run all structural checks on a single compiled skill directory. Args: skill_dir: `` /output/skills/ `` strict: if True, warnings are surfaced; otherwise only errors Returns a ValidationResult. Use ``result.passed`` for the default semantics (errors block, warnin

(skill_dir: Path, *, strict: bool = False)

Source from the content-addressed store, hash-verified

74
75
76def validate_skill(skill_dir: Path, *, strict: bool = False) -> ValidationResult:
77 """Run all structural checks on a single compiled skill directory.
78
79 Args:
80 skill_dir: ``<kb>/output/skills/<name>``
81 strict: if True, warnings are surfaced; otherwise only errors
82
83 Returns a ValidationResult. Use ``result.passed`` for the default
84 semantics (errors block, warnings don&#x27;t); use ``result.passed_strict``
85 when running ``--strict``.
86 """
87 result = ValidationResult()
88 skill_dir = Path(skill_dir)
89
90 if not skill_dir.is_dir():
91 result.errors.append(f"Skill directory does not exist: {skill_dir}")
92 return result
93
94 skill_md = skill_dir / "SKILL.md"
95 if not skill_md.exists():
96 result.errors.append("Missing required file: SKILL.md")
97 return result
98
99 # File size
100 skill_size = skill_md.stat().st_size
101 if skill_size > SKILL_MD_MAX_BYTES:
102 result.errors.append(f"SKILL.md is {skill_size} bytes; max is {SKILL_MD_MAX_BYTES} bytes.")
103
104 text = skill_md.read_text(encoding="utf-8")
105
106 # Frontmatter
107 fm = _extract_frontmatter(text)
108 if fm is None:
109 result.errors.append("SKILL.md has no YAML frontmatter (must start with `---` ... `---`).")
110 return result
111
112 try:
113 meta = yaml.safe_load(fm) or {}
114 except yaml.YAMLError as exc:
115 result.errors.append(f"Frontmatter is not valid YAML: {exc}")
116 return result
117
118 if not isinstance(meta, dict):
119 result.errors.append("Frontmatter must be a YAML mapping.")
120 return result
121
122 extras = set(meta.keys()) - ALLOWED_FRONTMATTER_KEYS
123 if extras:
124 # Treat as warning, not error — keeps strict mode user-controllable
125 result.warnings.append(
126 f"Frontmatter contains unknown keys: {sorted(extras)}. "
127 f"Anthropic Skills spec only allows: "
128 f"{sorted(ALLOWED_FRONTMATTER_KEYS)}."
129 )
130
131 # name field
132 name = meta.get("name")
133 if not name:

Callers 15

test_missing_skill_mdFunction · 0.90
test_no_frontmatterFunction · 0.90
test_malformed_yamlFunction · 0.90
test_name_missingFunction · 0.90
test_description_missingFunction · 0.90

Calls 3

_non_stdlib_importsFunction · 0.85
ValidationResultClass · 0.70
getMethod · 0.45

Tested by 15

test_missing_skill_mdFunction · 0.72
test_no_frontmatterFunction · 0.72
test_malformed_yamlFunction · 0.72
test_name_missingFunction · 0.72
test_description_missingFunction · 0.72