Plugin Validator Implementation - Task Decomposition
Architecture Reference: ./plugin-validator-architecture.md
Created: 2026-01-30
Execution Model: Massively Parallel AI Agent Swarm
Total Tasks: 23 across 4 priorities
Task Dependency Graph
graph TD
%% Priority 1 - Foundation
T1[T1: Data Models]
T2[T2: Validator Protocol]
T3[T3: FrontmatterValidator Port]
%% Priority 2 - Core Validators
T4[T4: NameFormatValidator]
T5[T5: DescriptionValidator]
T6[T6: ComplexityValidator]
T7[T7: ProgressiveDisclosureValidator]
T8[T8: InternalLinkValidator]
T9[T9: PluginStructureValidator]
%% Priority 3 - Infrastructure
T10[T10: Reporter Layer]
T11[T11: CLI Layer]
T12[T12: Integration Layer]
%% Priority 4 - Testing
T13[T13: Test Fixtures]
T14[T14: Validator Unit Tests]
T15[T15: CLI Integration Tests]
T16[T16: Token Counting Tests]
T17[T17: External Tool Tests]
%% Priority 5 - Migration
T18[T18: PEP 723 Script Creation]
T19[T19: Pre-commit Hook Update]
T20[T20: Documentation Updates]
T21[T21: Bash Script Deprecation]
T22[T22: Reference Updates]
T23[T23: Verification & QA]
%% Dependencies
T1 --> T2
T2 --> T3
T2 --> T4
T2 --> T5
T2 --> T6
T2 --> T7
T2 --> T8
T2 --> T9
T3 --> T10
T4 --> T10
T5 --> T10
T6 --> T10
T7 --> T10
T8 --> T10
T9 --> T10
T10 --> T11
T9 --> T12
T11 --> T13
T3 --> T13
T13 --> T14
T13 --> T15
T13 --> T16
T13 --> T17
T3 --> T18
T4 --> T18
T5 --> T18
T6 --> T18
T7 --> T18
T8 --> T18
T9 --> T18
T10 --> T18
T11 --> T18
T12 --> T18
T18 --> T19
T18 --> T20
T18 --> T21
T18 --> T22
T19 --> T23
T20 --> T23
T21 --> T23
T22 --> T23
SYNC CHECKPOINT 1: Foundation Complete
Convergence Point: Tasks T1 + T2 + T3
Quality Gates:
- Data models compile with mypy strict mode
- Validator protocol type-checks correctly
- FrontmatterValidator passes existing tests
- No regressions from validate_frontmatter.py
Reflection Questions:
- Do data models cover all validation scenarios?
- Is the protocol flexible enough for future validators?
- Are error codes correctly assigned?
Proceed only after: All Priority 1 tasks complete and quality gates pass
SYNC CHECKPOINT 2: Validators Complete
Convergence Point: Tasks T4 + T5 + T6 + T7 + T8 + T9 + T10 + T11 + T12
Quality Gates:
- All validators implement the Validator protocol
- Each validator has complete error code coverage
- Complexity validator uses tiktoken correctly
- CLI layer accepts all specified arguments
- Reporter layer formats output correctly
- Integration layer handles claude CLI absence gracefully
Reflection Questions:
- Are validation rules consistent across validators?
- Do error messages provide actionable guidance?
- Is token-based complexity measurement accurate?
- Does CLI UX match design intent?
Proceed only after: All Priority 2-3 tasks complete and quality gates pass
SYNC CHECKPOINT 3: Tests Complete
Convergence Point: Tasks T13 + T14 + T15 + T16 + T17
Quality Gates:
- Test coverage ≥80% (line and branch)
- Critical validators coverage ≥95%
- All pytest tests pass
- Type checking passes (mypy --strict)
- Property-based tests cover edge cases
Reflection Questions:
- Are test fixtures representative of real usage?
- Do tests cover failure modes adequately?
- Are integration tests isolated from external dependencies?
Proceed only after: All Priority 4 tasks complete and quality gates pass
SYNC CHECKPOINT 4: Migration Complete
Convergence Point: Tasks T18 + T19 + T20 + T21 + T22 + T23
Quality Gates:
- PEP 723 script executes successfully
- Pre-commit hook runs without errors
- All documentation references updated
- Bash scripts deprecated with notices
- No broken links in documentation
- End-to-end validation workflow succeeds
Reflection Questions:
- Does migration maintain backwards compatibility?
- Are users guided through the transition?
- Is the new tool discoverable?
Proceed only after: All Priority 5 tasks complete and quality gates pass
Priority 1: Foundation (No Dependencies)
Task T1: Data Models and Error Codes
Status: ✅ COMPLETE
Started: 2026-02-02T15:15:00Z
Completed: 2026-02-02T15:30:00Z
Agent: python-cli-architect
Dependencies: None
Priority: 1 (Foundational)
Complexity: Medium
Accuracy Risk: Medium (error code schema must match architecture)
Context: Implement core data structures for validation results, issues, and error codes. These models are used by all validators and reporters.
Objective: Create type-safe data models for ValidationResult, ValidationIssue, ComplexityMetrics, and FileType with complete error code catalog.
Required Inputs:
- Architecture spec:
./plugin-validator-architecture.mdlines 136-480 - Error code catalog: lines 836-887
- Token measurement spec: lines 1119-1168
Requirements:
- Create
ValidationResultdataclass with passed/errors/warnings/info - Create
ValidationIssuedataclass with field/severity/message/code/line/suggestion/docs_url - Create
ComplexityMetricsdataclass with token counts and thresholds - Create
FileTypeStrEnum with skill/agent/command/plugin/unknown - Implement error code constants (FM001-FM010, SK001-SK007, LK001-LK002, PD001-PD003, PL001-PL005)
- Implement documentation URL generator for error codes
Constraints:
- Use Python 3.11+ syntax (
str | None, notOptional[str]) - All dataclasses must be frozen or use
__post_init__validation - Error codes must remain stable (no code reuse)
- Must not import from external validation libraries
Expected Outputs:
- File created:
plugins/plugin-creator/scripts/plugin_validator.py(initial structure with data models only) - Models: ValidationResult, ValidationIssue, ComplexityMetrics, FileType
- Constants: ERROR_CODE_BASE_URL, token thresholds, name patterns
Acceptance Criteria:
- All dataclasses type-check with mypy strict mode
- Error code constants match architecture catalog exactly
- ValidationIssue.format() produces expected output format
- ComplexityMetrics.status property returns correct severity
- FileType.detect_file_type() correctly identifies file types
Verification Steps:
# Type checking
uv run mypy --strict plugins/plugin-creator/scripts/plugin_validator.py
# Unit test data models
uv run pytest tests/test_data_models.py -v
CoVe Checks:
Key claims to verify:
- Error code format matches
[CATEGORY][NUMBER]pattern - Token thresholds align with line equivalents (4000 tokens ≈ 500 lines)
- Documentation URL pattern generates valid GitHub links
- Error code format matches
Verification questions:
- Do error codes FM001-FM010 match the frontmatter error catalog in architecture lines 836-849?
- Does TOKEN_WARNING_THRESHOLD = 4000 align with "~500 lines equivalent" from line 1156?
- Does the documentation URL use the base URL from line 890?
Evidence to collect:
- Compare error code constants against lines 836-887
- Verify token threshold comments match architecture rationale
- Test URL generator with sample error code
Revision rule:
- If any error code is missing or mismatched, revise constant definitions
- If token thresholds don't match equivalents, update and document change
Can Parallelize With: T2 (after data models complete)
Reason: T2 needs ValidationResult and ValidationIssue types
Handoff: Report:
- Data model file path
- All error codes implemented (count 23)
- mypy strict mode status
- Sample ValidationIssue.format() output
Task T2: Validator Protocol Definition
Status: ✅ COMPLETE
Started: 2026-02-02T15:35:00Z
Completed: 2026-02-02T15:40:00Z
Agent: python-cli-architect
Dependencies: T1 (needs ValidationResult and ValidationIssue types)
Priority: 1 (Foundational)
Complexity: Low
Accuracy Risk: Low (protocol structure is well-defined)
Context: Define the Validator protocol that all validators must implement. This ensures consistent interfaces across validators.
Objective: Create Validator protocol with validate(), can_fix(), and fix() methods using Python Protocol typing.
Required Inputs:
- Architecture spec:
./plugin-validator-architecture.mdlines 136-176 - Data models from T1: ValidationResult, ValidationIssue
Requirements:
- Define
Validatorprotocol class with Protocol inheritance - Method:
validate(path: Path) -> ValidationResult - Method:
can_fix() -> bool - Method:
fix(path: Path) -> list[str](returns fixes applied) - Add docstrings following architecture examples
Constraints:
- Use
typing.Protocolfor structural typing - Must not use ABC (abstract base class) pattern
- Protocol methods must be type-hinted completely
- Must be compatible with Python 3.11+
Expected Outputs:
- Protocol class added to
plugins/plugin-creator/scripts/plugin_validator.py - Class:
Validatorwith three protocol methods
Acceptance Criteria:
- Protocol type-checks with mypy strict mode
- Sample validator implementation passes protocol check
- All method signatures match architecture specification
- Docstrings explain each method's purpose
Verification Steps:
# Type checking
uv run mypy --strict plugins/plugin-creator/scripts/plugin_validator.py
# Create test validator to verify protocol
uv run pytest tests/test_validator_protocol.py -v
Can Parallelize With: None (blocks all validator implementations)
Reason: All validators depend on this protocol
Handoff: Report:
- Protocol class location (file + line range)
- mypy validation status
- Confirmation of three required methods
Task T3: Port FrontmatterValidator
Status: ✅ COMPLETE
Started: 2026-02-02T15:45:00Z
Completed: 2026-02-02T16:00:00Z
Agent: python-cli-architect
Dependencies: T2 (needs Validator protocol)
Priority: 1 (Foundational - existing logic to preserve)
Complexity: High
Accuracy Risk: High (must preserve existing validation behavior exactly)
Context:
Port existing frontmatter validation logic from validate_frontmatter.py into the new consolidated tool. This validator handles YAML syntax, required fields, field types, and auto-fixing.
Objective: Create FrontmatterValidator class implementing Validator protocol with complete parity to existing validate_frontmatter.py behavior.
Required Inputs:
- Existing script:
plugins/plugin-creator/scripts/validate_frontmatter.pylines 103-187 (validation logic) - Architecture spec:
./plugin-validator-architecture.mdlines 1038-1073 - Pydantic models from validate_frontmatter.py: SkillFrontmatter, AgentFrontmatter, CommandFrontmatter
- Error codes: FM001-FM010
Requirements:
- Copy Pydantic frontmatter models (SkillFrontmatter, AgentFrontmatter, CommandFrontmatter)
- Implement
validate(path: Path) -> ValidationResult - Implement
can_fix() -> bool(returns True) - Implement
fix(path: Path) -> list[str]with auto-fix logic - Detect file type (skill/agent/command) to select schema
- Validate YAML syntax (FM002)
- Validate frontmatter delimiters (FM003)
- Validate required fields based on file type (FM001)
- Validate field types (FM005)
- Validate field values (FM006)
- Detect and fix forbidden multiline indicators (FM004)
- Detect and fix tool/skill YAML arrays → CSV strings (FM007, FM008)
- Detect and fix unquoted descriptions with colons (FM009)
- Validate name pattern (FM010)
Constraints:
- Must preserve ALL existing validation rules from validate_frontmatter.py
- Must use same Pydantic models for schema validation
- Auto-fix must only fix FM004, FM007, FM008, FM009 (not others)
- Must not break existing workflows using validate_frontmatter.py
- Must assign correct error codes to each validation failure
Expected Outputs:
- Class added:
FrontmatterValidatorimplementing Validator protocol - Pydantic models copied: SkillFrontmatter, AgentFrontmatter, CommandFrontmatter
- Methods: validate(), can_fix(), fix()
Acceptance Criteria:
- Validates skill frontmatter matching validate_frontmatter.py behavior
- Validates agent frontmatter with required name/description
- Validates command frontmatter with required description
- Auto-fixes YAML arrays to CSV strings
- Auto-fixes multiline indicators
- Auto-fixes unquoted descriptions
- Returns ValidationResult with correct error codes
- Preserves file content exactly when no fixes needed
Verification Steps:
# Compare validation results against existing script
uv run pytest tests/test_frontmatter_validator.py -v
# Test on real skill files
uv run python -c "
from plugin_validator import FrontmatterValidator
from pathlib import Path
validator = FrontmatterValidator()
result = validator.validate(Path('plugins/plugin-creator/skills/plugin-creator/SKILL.md'))
print(f'Passed: {result.passed}, Errors: {len(result.errors)}')
"
CoVe Checks:
Key claims to verify:
- Pydantic models match validate_frontmatter.py exactly
- Auto-fix logic preserves file content fidelity
- Error codes match frontmatter error catalog
- All 10 frontmatter error codes are implemented
Verification questions:
- Do the Pydantic models in lines 103-187 of validate_frontmatter.py match the copied models?
- Does the auto-fix logic for FM007 convert
["Read", "Grep"]→"Read, Grep"exactly? - Are all 10 FM error codes (FM001-FM010) assigned to validation failures?
- Does the name pattern regex
^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$match architecture line 353?
Evidence to collect:
- Read validate_frontmatter.py lines 103-187 and compare Pydantic model fields
- Test auto-fix on sample YAML array:
tools: ["Read"] - List all error code assignments in validate() method
- Compare NAME_PATTERN constant against architecture spec
Revision rule:
- If Pydantic models differ, align with validate_frontmatter.py (preserve existing)
- If auto-fix produces different output than original script, fix logic
- If any FM code is missing, add assignment
- If name pattern differs, use architecture version and document change
Can Parallelize With: None (blocks reporter and CLI layers)
Reason: FrontmatterValidator is used in CLI examples and reporter tests
Handoff: Report:
- FrontmatterValidator class location (file + line range)
- Count of validation rules implemented (14)
- Count of auto-fix rules implemented (4)
- Test results comparing to validate_frontmatter.py
- Any deviations from original behavior (must be zero)
Priority 2: Core Validators (Depends on T1, T2)
All validators in this priority can execute in parallel after T1 and T2 complete.
Task T4: NameFormatValidator
Status: ✅ COMPLETE
Started: 2026-02-02T16:05:00Z
Completed: 2026-02-02T16:10:00Z
Agent: python-cli-architect
Dependencies: T2 (needs Validator protocol)
Priority: 2 (Core validator)
Complexity: Low
Accuracy Risk: Low (pattern matching logic is straightforward)
Context: Validate skill/agent name format: lowercase, hyphens only, no leading/trailing hyphens, no consecutive hyphens, no underscores.
Objective: Create NameFormatValidator implementing Validator protocol with error codes SK001-SK003.
Required Inputs:
- Architecture spec:
./plugin-validator-architecture.mdlines 1074-1090 - Bash validation logic:
bash-validation-checks.mdlines 25-28 - Error codes: SK001 (uppercase), SK002 (underscores), SK003 (hyphens)
Requirements:
- Implement
validate(path: Path) -> ValidationResult - Implement
can_fix() -> bool(returns False) - Implement
fix(path: Path) -> list[str](raises NotImplementedError) - Extract name from frontmatter
- Check for uppercase characters (SK001)
- Check for underscores (SK002)
- Check for leading/trailing hyphens (SK003)
- Check for consecutive hyphens (SK003)
- Validate against pattern:
^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$
Constraints:
- Not auto-fixable (requires human decision)
- Must work on skills, agents, and commands
- Must handle missing name field gracefully (skip validation)
- Must use error codes SK001, SK002, SK003 correctly
Expected Outputs:
- Class added:
NameFormatValidatorimplementing Validator protocol - Regex pattern constant:
NAME_PATTERN
Acceptance Criteria:
- Detects uppercase characters (SK001)
- Detects underscores (SK002)
- Detects leading hyphens (SK003)
- Detects trailing hyphens (SK003)
- Detects consecutive hyphens (SK003)
- Passes valid names: "test-skill", "agent-123", "a"
- Returns ValidationResult with correct error codes
Verification Steps:
# Parametrized tests for name patterns
uv run pytest tests/test_name_format_validator.py -v
Can Parallelize With: T5, T6, T7, T8 (all independent validators)
Reason: No shared file writes, no cross-validator dependencies
Handoff: Report:
- NameFormatValidator class location
- Test results for all error codes (SK001, SK002, SK003)
- Confirmation of auto-fix = False
Task T5: DescriptionValidator
Status: ✅ COMPLETE
Started: 2026-02-02T16:15:00Z
Completed: 2026-02-02T16:20:00Z
Agent: python-cli-architect
Dependencies: T2 (needs Validator protocol)
Priority: 2 (Core validator)
Complexity: Low
Accuracy Risk: Low (string length and substring checks)
Context: Validate description field: minimum 20 characters, contains trigger phrases ("use when", "use this", "trigger", "activate").
Objective: Create DescriptionValidator implementing Validator protocol with error codes SK004-SK005.
Required Inputs:
- Architecture spec:
./plugin-validator-architecture.mdlines 1092-1113 - Bash validation logic:
bash-validation-checks.mdlines 31-33 - Error codes: SK004 (too short), SK005 (missing trigger phrases)
- Trigger phrase list: lines 357-358 of architecture
Requirements:
- Implement
validate(path: Path) -> ValidationResult - Implement
can_fix() -> bool(returns False) - Implement
fix(path: Path) -> list[str](raises NotImplementedError) - Extract description from frontmatter
- Check minimum length 20 characters (SK004)
- Check for trigger phrases: "use when", "use this", "trigger", "activate" (SK005)
- Both checks are warnings, not errors
Constraints:
- Not auto-fixable (requires human-written content)
- Must work on skills, agents, and commands
- Must handle missing description field gracefully
- Must use case-insensitive matching for trigger phrases
- Severity: WARNING (not ERROR)
Expected Outputs:
- Class added:
DescriptionValidatorimplementing Validator protocol - Constant:
MIN_DESCRIPTION_LENGTH = 20 - Constant:
REQUIRED_TRIGGER_PHRASES = ["use when", "use this", "trigger", "activate"]
Acceptance Criteria:
- Warns if description <20 characters (SK004)
- Warns if no trigger phrases present (SK005)
- Passes if description ≥20 chars AND contains trigger phrase
- Case-insensitive trigger phrase matching works
- Returns warnings, not errors
Verification Steps:
# Test with various descriptions
uv run pytest tests/test_description_validator.py -v
Can Parallelize With: T4, T6, T7, T8 (all independent validators)
Reason: No shared file writes, no cross-validator dependencies
Handoff: Report:
- DescriptionValidator class location
- Test results for SK004 and SK005
- Confirmation of warning severity (not error)
Task T6: ComplexityValidator (Token-Based)
Status: ✅ COMPLETE
Started: 2026-02-02T16:25:00Z
Completed: 2026-02-02T16:30:00Z
Agent: python-cli-architect
Dependencies: T2 (needs Validator protocol)
Priority: 2 (Core validator - replaces line counting)
Complexity: Medium
Accuracy Risk: Medium (tiktoken usage must be correct)
Context: Replace line-based complexity measurement with token-based measurement using tiktoken. Measures skill complexity by counting tokens in body content (excluding frontmatter).
Objective: Create ComplexityValidator implementing Validator protocol with token counting via tiktoken and error codes SK006-SK007.
Required Inputs:
- Architecture spec:
./plugin-validator-architecture.mdlines 1115-1168 - Token measurement example: lines 1122-1151
- Error codes: SK006 (warning >4000 tokens), SK007 (error >6400 tokens)
- tiktoken library documentation (external)
Requirements:
- Implement
validate(path: Path) -> ValidationResult - Implement
can_fix() -> bool(returns False) - Implement
fix(path: Path) -> list[str](raises NotImplementedError) - Use tiktoken library with cl100k_base encoding
- Split frontmatter from body content
- Count tokens in body only (exclude frontmatter)
- Warn if body_tokens > 4000 (SK006)
- Error if body_tokens > 6400 (SK007)
- Include token count in validation message
Constraints:
- Not auto-fixable (requires content restructuring)
- Must work on SKILL.md files only (not agents/commands)
- Must use cl100k_base encoding (GPT-4/Claude compatible)
- Must exclude frontmatter from token count
- Must lazy-load tiktoken encoding (performance)
Expected Outputs:
- Class added:
ComplexityValidatorimplementing Validator protocol - Constant:
TOKEN_WARNING_THRESHOLD = 4000 - Constant:
TOKEN_ERROR_THRESHOLD = 6400 - Function:
split_frontmatter(content: str) -> tuple[str, str] - PEP 723 dependency added:
tiktoken>=0.9.0
Acceptance Criteria:
- Counts tokens using tiktoken cl100k_base encoding
- Excludes frontmatter from token count
- Warns at 4001 tokens (SK006)
- Errors at 6401 tokens (SK007)
- Passes at 3999 tokens
- Validation message includes exact token count
- Encoding loads lazily (not at import time)
Verification Steps:
# Test with known token count files
uv run pytest tests/test_complexity_validator.py -v
# Test lazy loading
uv run python -c "
import sys
from plugin_validator import ComplexityValidator
# tiktoken should not be imported yet
assert 'tiktoken' not in sys.modules
validator = ComplexityValidator()
# Still not imported
assert 'tiktoken' not in sys.modules
# Now import happens
from pathlib import Path
validator.validate(Path('test.md'))
assert 'tiktoken' in sys.modules
"
CoVe Checks:
Key claims to verify:
- cl100k_base is the correct encoding for Claude
- Token thresholds match line count equivalents
- Frontmatter split regex works correctly
Verification questions:
- Is cl100k_base the encoding used by Claude according to tiktoken docs?
- Does 4000 tokens ≈ 500 lines and 6400 tokens ≈ 800 lines based on empirical testing?
- Does the frontmatter regex
^---\n(.*?)\n---\n(.*)$correctly split SKILL.md files?
Evidence to collect:
- Check tiktoken GitHub README for Claude-compatible encoding
- Test token counting on real SKILL.md files with known line counts
- Test frontmatter split on sample SKILL.md with frontmatter and body
Revision rule:
- If cl100k_base is not Claude-compatible, research and use correct encoding
- If thresholds don't align with line equivalents, recalibrate based on testing
- If frontmatter split fails on any SKILL.md, revise regex
Can Parallelize With: T4, T5, T7, T8 (all independent validators)
Reason: No shared file writes, no cross-validator dependencies
Handoff: Report:
- ComplexityValidator class location
- tiktoken dependency added to PEP 723 metadata
- Test results for threshold boundaries (3999, 4001, 6401 tokens)
- Sample token counts from real SKILL.md files
Task T7: ProgressiveDisclosureValidator
Status: ✅ COMPLETE
Started: 2026-02-02T16:35:00Z
Completed: 2026-02-02T16:40:00Z
Agent: python-cli-architect
Dependencies: T2 (needs Validator protocol)
Priority: 2 (Core validator)
Complexity: Low
Accuracy Risk: Low (directory existence checks)
Context: Check for progressive disclosure directories: references/, examples/, scripts/. Report as INFO if missing (not errors).
Objective: Create ProgressiveDisclosureValidator implementing Validator protocol with error codes PD001-PD003.
Required Inputs:
- Architecture spec:
./plugin-validator-architecture.mdlines 1170-1186 - Bash validation logic:
bash-validation-checks.mdlines 40-44 - Error codes: PD001 (no references/), PD002 (no examples/), PD003 (no scripts/)
Requirements:
- Implement
validate(path: Path) -> ValidationResult - Implement
can_fix() -> bool(returns False) - Implement
fix(path: Path) -> list[str](raises NotImplementedError) - Check for references/ directory (PD001)
- Check for examples/ directory (PD002)
- Check for scripts/ directory (PD003)
- Count files in each directory if present
- All issues are severity INFO (not warnings or errors)
Constraints:
- Not auto-fixable (requires content creation)
- Must work on skill directories only
- Severity must be INFO, not WARNING or ERROR
- Must count files recursively in each directory
Expected Outputs:
- Class added:
ProgressiveDisclosureValidatorimplementing Validator protocol - Directory list:
["references", "examples", "scripts"]
Acceptance Criteria:
- Reports INFO if references/ missing (PD001)
- Reports INFO if examples/ missing (PD002)
- Reports INFO if scripts/ missing (PD003)
- Includes file count in message if directory exists
- All issues have severity INFO
- Returns ValidationResult with info list populated
Verification Steps:
# Test with and without directories
uv run pytest tests/test_progressive_disclosure_validator.py -v
Can Parallelize With: T4, T5, T6, T8 (all independent validators)
Reason: No shared file writes, no cross-validator dependencies
Handoff: Report:
- ProgressiveDisclosureValidator class location
- Test results for all three directory checks
- Confirmation of INFO severity (not warning/error)
Task T8: InternalLinkValidator
Status: ✅ COMPLETE
Started: 2026-02-02T16:45:00Z
Completed: 2026-02-02T17:30:00Z
Agent: python-cli-architect
Dependencies: T2 (needs Validator protocol)
Priority: 2 (Core validator)
Complexity: Medium
Accuracy Risk: Medium (regex pattern must extract links correctly)
Context: Validate internal markdown links starting with ./ point to existing files. Report broken links as errors, missing ./ prefix as warnings.
Objective: Create InternalLinkValidator implementing Validator protocol with error codes LK001-LK002.
Required Inputs:
- Architecture spec:
./plugin-validator-architecture.mdlines 1188-1256 - Link extraction pattern: line 1219
\[([^\]]+)\]\(([^)]+)\) - Bash validation logic:
bash-validation-checks.mdlines 47-50 - Error codes: LK001 (broken link), LK002 (missing ./ prefix)
Requirements:
- Implement
validate(path: Path) -> ValidationResult - Implement
can_fix() -> bool(returns False) - Implement
fix(path: Path) -> list[str](raises NotImplementedError) - Extract markdown links with regex
\[([^\]]+)\]\(([^)]+)\) - Filter to relative links starting with ./
- Warn if link doesn't start with ./ (LK002)
- Error if linked file doesn't exist (LK001)
- Resolve link paths relative to SKILL.md directory
Constraints:
- Not auto-fixable (requires file creation or link correction)
- Must work on SKILL.md files only
- Must handle URL-encoded paths
- Must ignore external links (http://, https://)
- Must ignore anchor links (#section)
Expected Outputs:
- Class added:
InternalLinkValidatorimplementing Validator protocol - Regex pattern constant:
LINK_PATTERN = r"\[([^\]]+)\]\(([^)]+)\)"
Acceptance Criteria:
- Extracts markdown links correctly
- Warns if link missing ./ prefix (LK002)
- Errors if linked file doesn't exist (LK001)
- Ignores external links (http://, https://)
- Resolves paths relative to skill directory
- Returns ValidationResult with correct error codes
Verification Steps:
# Test with various link formats
uv run pytest tests/test_internal_link_validator.py -v
CoVe Checks:
Key claims to verify:
- Regex pattern correctly extracts markdown links
- Path resolution handles ../ and ./ correctly
- External link filtering works
Verification questions:
- Does the regex
\[([^\]]+)\]\(([^)]+)\)match all markdown link formats? - Does Path.resolve() handle ../relative/path.md correctly?
- Do http:// and https:// links get filtered before validation?
- Does the regex
Evidence to collect:
- Test regex against sample markdown:
[text](./file.md),[text](file.md),[text](https://example.com) - Test path resolution with sample skill directory structure
- Verify external link filtering with sample content
- Test regex against sample markdown:
Revision rule:
- If regex fails to match valid markdown links, revise pattern
Implementation Summary:
- ✅ Class added at lines 412-553 of plugin_validator.py
- ✅ Implements Validator protocol correctly
- ✅ Link extraction using regex pattern
\[([^\]]+)\]\(([^)]+)\) - ✅ Filters external links (http://, https://, ftp://)
- ✅ Filters anchor links (#section)
- ✅ Filters absolute paths (/path/to/file)
- ✅ Detects broken links → LK001 error
- ✅ Detects missing ./ prefix → LK002 warning
- ✅ Path resolution relative to SKILL.md directory
- ✅ can_fix() returns False (not auto-fixable)
- ✅ fix() raises NotImplementedError
- ✅ Passes mypy --strict type checking
- ✅ Passes ruff linting
Verification Results:
Test case: SKILL.md with:
- Good link:
[good link](./references/existing.md)→ Pass - Broken link:
[broken link](./references/missing.md)→ LK001 error - Missing prefix:
[no prefix](references/existing.md)→ LK002 warning - External:
[external](https://example.com)→ Ignored - Anchor:
[anchor](#section)→ Ignored
All tests passed successfully.
- If path resolution produces wrong paths, use different resolution method
- If external links are not filtered, add filtering logic
Can Parallelize With: T4, T5, T6, T7 (all independent validators)
Reason: No shared file writes, no cross-validator dependencies
Handoff: Report:
- InternalLinkValidator class location
- Test results for link extraction regex
- Test results for path resolution
- Confirmation of error codes LK001, LK002
Task T9: PluginStructureValidator (Claude CLI Integration)
Status: ✅ COMPLETED
Started: 2026-02-02T16:50:00Z
Completed: 2026-02-02T17:15:00Z
Agent: python-cli-architect
Dependencies: T2 (needs Validator protocol)
Priority: 2 (Core validator - external integration)
Complexity: Medium
Accuracy Risk: Low (delegates to external tool)
Context:
Integrate with claude plugin validate CLI command for plugin.json validation. Silently skip if claude CLI not available.
Objective: Create PluginStructureValidator implementing Validator protocol that delegates to claude CLI with error codes PL001-PL005.
Required Inputs:
- Architecture spec:
./plugin-validator-architecture.mdlines 1258-1286 - Claude CLI integration spec:
claude-cli-integration-spec.mdcomplete file - Error codes: PL001-PL005
Requirements:
- Implement
validate(path: Path) -> ValidationResult - Implement
can_fix() -> bool(returns False) - Implement
fix(path: Path) -> list[str](raises NotImplementedError) - Check if claude CLI available using
shutil.which("claude") - Skip validation if claude not available (return success with info message)
- Skip validation if not a plugin directory (no .claude-plugin/plugin.json)
- Run
claude plugin validate {plugin_dir}via subprocess - Parse output for errors
- Map claude output to error codes PL001-PL005
- Set timeout to 30 seconds
- Never use shell=True (security)
Constraints:
- Not auto-fixable (requires structural changes)
- Must work on plugin directories only
- Must handle claude CLI absence gracefully (skip, not error)
- Must use subprocess.run with list arguments (no shell=True)
- Must capture both stdout and stderr
- Must set timeout to prevent hanging
Expected Outputs:
- Class added:
PluginStructureValidatorimplementing Validator protocol - Function:
is_claude_available() -> bool - Constant:
CLAUDE_TIMEOUT = 30
Acceptance Criteria:
- Detects claude CLI availability with shutil.which()
- Skips validation if claude not available
- Skips validation if not plugin directory
- Runs claude plugin validate with timeout
- Parses output for errors
- Returns ValidationResult with appropriate error codes
- Never uses shell=True
- Handles subprocess timeout gracefully
Verification Steps:
# Test with claude available
uv run pytest tests/test_plugin_structure_validator.py::test_with_claude -v
# Test with claude unavailable (mocked)
uv run pytest tests/test_plugin_structure_validator.py::test_without_claude -v
# Test timeout handling
uv run pytest tests/test_plugin_structure_validator.py::test_timeout -v
Can Parallelize With: T4, T5, T6, T7, T8 (all independent validators)
Reason: No shared file writes, no cross-validator dependencies
Handoff: Report:
- PluginStructureValidator class location
- Test results for claude available/unavailable scenarios
- Test results for timeout handling
- Confirmation of no shell=True usage
Completion Summary:
Implementation Location: plugins/plugin-creator/scripts/plugin_validator.py lines 1657-1931
Key Features Implemented:
validate(path: Path) -> ValidationResult- Validates plugin structure using claude CLIcan_fix() -> bool- Returns False (not auto-fixable)fix(path: Path) -> list[str]- Raises NotImplementedError_get_claude_path() -> str | None- Detects claude CLI availability using shutil.which()_find_plugin_directory(path: Path) -> Path | None- Finds plugin root directory_parse_claude_errors(...)- Parses claude CLI output for error codes PL001-PL005
Security Features:
- Uses full path to claude executable (from shutil.which)
- Never uses shell=True (subprocess.run with list arguments)
- Timeout set to 30 seconds (CLAUDE_TIMEOUT constant)
Error Handling:
- subprocess.TimeoutExpired → PL002 error
- FileNotFoundError → Info message (skip validation)
- OSError → PL002 error
- Claude validation failure → Parsed error codes PL001-PL005
Test Results: ✅ Instantiation successful ✅ Claude CLI detection working (found at ~/.local/bin/claude) ✅ can_fix() returns False ✅ fix() raises NotImplementedError with descriptive message ✅ Plugin directory detection working (found plugins/plugin-creator) ✅ Validation on non-plugin directory skips gracefully ✅ Validation on actual plugin directory passes (plugins/plugin-creator) ✅ No shell=True usage (verified by ruff S607 check passing) ✅ Passes mypy --strict type checking ✅ Passes ruff linting
Priority 3: Infrastructure (Depends on Validators)
Task T10: Reporter Layer
Status: ✅ COMPLETED
Started: 2026-02-02T17:00:00Z
Completed: 2026-02-02T17:30:00Z
Agent: python-cli-architect
Dependencies: T3, T4, T5, T6, T7, T8, T9 (needs all validators)
Priority: 3 (Infrastructure)
Complexity: Medium
Accuracy Risk: Low (formatting logic)
Context: Create reporter classes that format validation results for human consumption using Rich library.
Objective: Create ConsoleReporter, CIReporter, and SummaryReporter classes for displaying validation results.
Required Inputs:
- Architecture spec:
./plugin-validator-architecture.mdlines 206-272 - Rich table configuration: lines 247-252
- Error display format: lines 254-265
- python3-development skill table patterns (external reference)
Requirements:
- Create Reporter protocol with report() and summarize() methods
- Create ConsoleReporter for terminal output with Rich
- Create CIReporter for plain text output (no color)
- Create SummaryReporter for single-line status
- Use Rich table box style:
box.MINIMAL_DOUBLE_HEAD - Format errors with file:line references
- Include error codes in output
- Include suggestion and docs_url if present
- Support --no-color flag
Constraints:
- Must not truncate output
- Must handle terminal width correctly
- Must work in non-TTY environments (CI)
- Must display all error details
- Must use Rich for ConsoleReporter only
Expected Outputs:
- Protocol:
Reporterwith report() and summarize() methods - Class:
ConsoleReporter(Rich-based) - Class:
CIReporter(plain text) - Class:
SummaryReporter(one-line status) - PEP 723 dependency:
typer[all]>=0.19.2(includes Rich)
Acceptance Criteria:
- ConsoleReporter displays colored output with Rich
- CIReporter displays plain text (no ANSI codes)
- SummaryReporter displays single-line status
- All reporters show file:line:code:message format
- Suggestions and docs URLs displayed when present
- Table formatting matches python3-development patterns
Verification Steps:
# Test reporter output
uv run pytest tests/test_reporters.py -v
# Visual verification of Rich output
uv run python -c "
from plugin_validator import ConsoleReporter, ValidationResult, ValidationIssue
from pathlib import Path
reporter = ConsoleReporter()
issue = ValidationIssue(
field='name',
severity='error',
message='Missing required field',
code='FM001',
suggestion='Add name: skill-name to frontmatter'
)
result = ValidationResult(passed=False, errors=[issue], warnings=[], info=[])
reporter.report([(Path('test.md'), result)])
"
Can Parallelize With: T11, T12 (after validators complete)
Reason: Reporter is used by CLI but not by Integration layer
Handoff: Report:
- Reporter class locations
- Sample output screenshots (if possible)
- Test results for all three reporters
- Confirmation of Rich dependency added
Task T11: CLI Layer
Status: ✅ COMPLETE
Started: 2026-02-02T17:35:00Z
Completed: 2026-02-02T17:50:00Z
Agent: python-cli-architect
Dependencies: T10 (needs Reporter)
Priority: 3 (Infrastructure)
Complexity: Medium
Accuracy Risk: Low (argument parsing is well-defined)
Context: Create CLI interface using Typer that accepts path, --check, --fix, --verbose, --no-color flags.
Objective: Create Typer-based CLI with main() command that orchestrates validation workflow.
Required Inputs:
- Architecture spec:
./plugin-validator-architecture.mdlines 87-129 - CLI command interface: lines 96-107
- Exit codes: lines 111-114
- Usage examples: lines 1291-1345
Requirements:
- Create Typer app with name "plugin-validator"
- Add main() command with path argument
- Add --check flag (validate only)
- Add --fix flag (auto-fix issues)
- Add --verbose flag (show all checks)
- Add --no-color flag (disable Rich colors)
- Implement file type detection
- Run appropriate validators for file type
- Collect results
- If --fix, run auto-fix for fixable validators
- Re-validate after fixes
- Report results using Reporter
- Exit with correct code (0 = success, 1 = errors, 2 = usage, 130 = Ctrl+C)
Constraints:
- Must use Typer with Annotated syntax
- Must handle Ctrl+C gracefully (exit 130)
- Must validate command-line arguments
- Must support both file and directory paths
- Must auto-discover files in directories
Expected Outputs:
- Typer app:
app = typer.Typer(name="plugin-validator") - Command:
main(path, check, fix, verbose, no_color) - PEP 723 dependency:
typer[all]>=0.19.2
Acceptance Criteria:
- Accepts path argument (file or directory)
- --check
…(truncated)