[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.
| | ||
| @cached_property | ||
| def _content(self) -> str: | ||
| return self.path.read_text() |
There was a problem hiding this comment.
Path.read_text() uses the platform default encoding; several SKILL.md files contain non-ASCII characters (e.g., “≥”, “—”), so this can raise decode errors on non-UTF-8 locales. Read files with an explicit encoding="utf-8" (and apply the same to other read_text() calls in this script for consistency).
| return self.path.read_text() | |
| return self.path.read_text(encoding="utf-8") |
| def frontmatter(self) -> dict[str, str]: | ||
| """Parse YAML-style frontmatter between leading --- delimiters into a flat dict.""" | ||
| m = re.match(r"^---\n(.*?)\n---\n", self._content, re.DOTALL) | ||
| if not m: | ||
| return {} | ||
| result: dict[str, str] = {} | ||
| for line in m.group(1).splitlines(): | ||
| if ": " in line: | ||
| key, _, value = line.partition(": ") | ||
| result[key.strip()] = value.strip() | ||
| return result |
There was a problem hiding this comment.
The frontmatter parsing is a very narrow subset of YAML and is brittle to Windows line endings and common YAML constructs (quoted values containing :, multiline strings, etc.), which can cause false “missing frontmatter”/missing-field errors. Since the repo already depends on PyYAML, consider parsing the frontmatter block with yaml.safe_load and validating it’s a mapping, and loosen the delimiter regex to tolerate \r\n and end-of-file after the closing ---.
| continue | ||
| | ||
| md = MdFile(skill_file) | ||
| | ||
| fm = md.frontmatter |
There was a problem hiding this comment.
validate_skill_structure() creates a new MdFile for each SKILL.md, but the later validators iterate claude.skill_files which creates separate MdFile instances for the same paths. This causes each SKILL.md to be read/parsing work repeated across validators; consider building a single cached list/map of MdFile instances and reusing it across all validations.
| uv run python scripts/validate_agent_guidance.py | ||
| | ||
| smoke-skills: | ||
| scripts/smoke-test-skills.sh No newline at end of file |
There was a problem hiding this comment.
make smoke-skills (scripts/smoke-test-skills.sh) and docs still reference scripts/validate-agent-guidance.sh, which this PR deletes. Update those call sites/docs to invoke uv run python scripts/validate_agent_guidance.py (or make lint-skills) so smoke tests and documentation don’t break after this change.
| scripts/smoke-test-skills.sh | |
| $(MAKE) lint-skills |
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