feat: add agent schema validation with comprehensive testing

Introduce automated validation for agent YAML files using Zod to ensure
schema compliance across all agent definitions. This feature validates
17 agent files across core and module directories, catching structural
errors and maintaining consistency.

Schema Validation (tools/schema/agent.js):
- Zod-based schema validating metadata, persona, menu, prompts, and critical actions
- Module-aware validation: module field required for src/modules/**/agents/,
  optional for src/core/agents/
- Enforces kebab-case unique triggers and at least one command target per menu item
- Validates persona.principles as array (not string)
- Comprehensive refinements for data integrity

CLI Validator (tools/validate-agent-schema.js):
- Scans src/{core,modules/*}/agents/*.agent.yaml
- Parses with js-yaml and validates using Zod schema
- Reports detailed errors with file paths and field paths
- Exits 1 on failures, 0 on success
- Accepts optional project_root parameter for testing

Testing (679 lines across 3 test files):
- test/test-cli-integration.sh: CLI behavior and error handling tests
- test/unit-test-schema.js: Direct schema validation unit tests
- test/test-agent-schema.js: Comprehensive fixture-based tests
- 50 test fixtures covering valid and invalid scenarios
- ESLint configured to support CommonJS test files
- Prettier configured to ignore intentionally broken fixtures

CI Integration (.github/workflows/lint.yaml):
- Renamed from format-check.yaml to lint.yaml
- Added schema-validation job running npm run validate:schemas
- Runs in parallel with prettier and eslint jobs
- Validates on all pull requests

Data Cleanup:
- Fixed src/core/agents/bmad-master.agent.yaml: converted persona.principles
  from string to array format

Documentation:
- Updated schema-classification.md with validation section
- Documents validator usage, enforcement rules, and CI integration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Alex Verkhovsky
2025-10-20 02:14:33 -07:00
parent 940cc15751
commit 6b9ab8b201
64 changed files with 2732 additions and 11 deletions

View File

@@ -0,0 +1,23 @@
# Test: Empty principles array
# Expected: FAIL
# Error code: too_small
# Error path: agent.persona.principles
# Error minimum: 1
agent:
metadata:
id: empty-principles
name: Empty Principles
title: Empty Principles
icon:
persona:
role: Test agent
identity: Test identity
communication_style: Test style
principles: []
menu:
- trigger: help
description: Show help
action: display_help

View File

@@ -0,0 +1,26 @@
# Test: Empty string in principles array
# Expected: FAIL
# Error code: custom
# Error path: agent.persona.principles[1]
# Error message: agent.persona.principles[] must be a non-empty string
agent:
metadata:
id: empty-principle-string
name: Empty Principle String
title: Empty Principle
icon:
persona:
role: Test agent
identity: Test identity
communication_style: Test style
principles:
- Valid principle
- " "
- Another valid principle
menu:
- trigger: help
description: Show help
action: display_help

View File

@@ -0,0 +1,26 @@
# Test: Extra unknown fields in persona
# Expected: FAIL
# Error code: unrecognized_keys
# Error path: agent.persona
# Error keys: ["extra_field", "another_extra"]
agent:
metadata:
id: extra-persona-fields
name: Extra Persona Fields
title: Extra Persona
icon:
persona:
role: Test agent
identity: Test identity
communication_style: Test style
principles:
- Test principle
extra_field: Not allowed
another_extra: Also invalid
menu:
- trigger: help
description: Show help
action: display_help

View File

@@ -0,0 +1,23 @@
# Test: Missing required persona.role field
# Expected: FAIL
# Error code: invalid_type
# Error path: agent.persona.role
# Error expected: string
agent:
metadata:
id: missing-role
name: Missing Role
title: Missing Role
icon:
persona:
identity: Test identity
communication_style: Test style
principles:
- Test principle
menu:
- trigger: help
description: Show help
action: display_help

View File

@@ -0,0 +1,23 @@
# Test: principles as string instead of array
# Expected: FAIL
# Error code: invalid_type
# Error path: agent.persona.principles
# Error expected: array
agent:
metadata:
id: principles-string
name: Principles String
title: Principles String
icon:
persona:
role: Test agent
identity: Test identity
communication_style: Test style
principles: This should be an array, not a string
menu:
- trigger: help
description: Show help
action: display_help