[DBA-295] Migrate validate-agent-guidance from Bash to Python#79
[DBA-295] Migrate validate-agent-guidance from Bash to Python#79
validate-agent-guidance from Bash to Python#79Conversation
There was a problem hiding this comment.
Pull request overview
Migrates the agent guidance/skills Tier-1 validator from a Bash script to a typed Python module, and updates local tooling (Makefile + pre-commit) to invoke the new validator via uv.
Changes:
- Added
scripts/validate_agent_guidance.pyimplementing skill structure, cross-reference, and eval JSON validation (plus YAML frontmatter checks). - Removed
scripts/validate-agent-guidance.sh. - Updated
make lint-skillsand thevalidate-agent-guidancepre-commit hook to run the Python validator.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
scripts/validate_agent_guidance.py |
New Python implementation of the guidance/skills static validator (structure, references, eval JSON, frontmatter). |
scripts/validate-agent-guidance.sh |
Deleted legacy Bash validator. |
Makefile |
Points lint-skills at the new Python validator. |
.pre-commit-config.yaml |
Updates the local hook to run the new Python validator via uv. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
SimonKaran13
left a comment
There was a problem hiding this comment.
As copilot suggested, scripts/smoke-test-skills.sh still references validate-agent-guidance.sh. Let's make sure it's not referenced anywhere before merging
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
7815c57 to
a812709
Compare
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| m = re.match(r"^---\r?\n(.*?)\r?\n---(?:\r?\n|$)", self._content, re.DOTALL) | ||
| if not m: | ||
| return {} | ||
| parsed = yaml.safe_load(m.group(1)) |
There was a problem hiding this comment.
MdFile.frontmatter calls yaml.safe_load(...) without handling yaml.YAMLError. Invalid frontmatter will crash the validator with a traceback instead of producing a clean validation error; catch YAML parse errors and surface them as a normal validation message.
| parsed = yaml.safe_load(m.group(1)) | |
| try: | |
| parsed = yaml.safe_load(m.group(1)) | |
| except yaml.YAMLError: | |
| # Invalid YAML frontmatter: treat as missing frontmatter to avoid crashing. | |
| return {} |
| if fm.get("name") and fm["name"] != skill_name: | ||
| errors.append(f"{skill_name}/SKILL.md frontmatter 'name' ({fm['name']!r}) does not match directory name") |
There was a problem hiding this comment.
validate_skill_structure() only checks that name/description keys exist in frontmatter, not that they have non-empty values. With YAML, description: parses as None (and currently becomes 'None'), so empty required fields can slip through; validate the values are non-empty.
| if fm.get("name") and fm["name"] != skill_name: | |
| errors.append(f"{skill_name}/SKILL.md frontmatter 'name' ({fm['name']!r}) does not match directory name") | |
| continue | |
| value = fm.get(field) | |
| # Require non-empty string values for required fields | |
| if not isinstance(value, str) or not value.strip(): | |
| errors.append( | |
| f"{skill_name}/SKILL.md frontmatter field '{field}' must be a non-empty string" | |
| ) | |
| name_value = fm.get("name") | |
| if isinstance(name_value, str): | |
| name_stripped = name_value.strip() | |
| if name_stripped and name_stripped != skill_name: | |
| errors.append( | |
| f"{skill_name}/SKILL.md frontmatter 'name' ({name_value!r}) does not match directory name" | |
| ) |
# Conflicts: # scripts/validate-agent-guidance.sh
Summary
Replaces the Bash validate-agent-guidance script with a typed Python module
that is easier to extend and maintain. Adds
MdFileandClaudeDirdataclasses for structured, lazy-parsed access to skills and agents.
Changes
Python rewrite of the validator
Replaced
scripts/validate-agent-guidance.shwithscripts/validate_agent_guidance.py.Introduced
MdFile(lazy-parsed markdown with cached properties) andClaudeDir(.claude/directory withskill_dirs,skill_files,agent_fileslistings). Adds YAML frontmatter validation:nameanddescriptionfields required,namemust match the skill directory name.Files
scripts/validate_agent_guidance.pyscripts/validate-agent-guidance.sh(deleted)Tooling update
Updated
make lint-skillsand the pre-commit hook to invoke the Python script.Files
Makefile.pre-commit-config.yamlTest Plan
make lint-skillspassesmake checkpasses (ruff + mypy + pre-commit hook)🤖 Generated with Claude Code