# 2886 Plugin Validator Tasks 1c020e4a

> Plugin Validator Implementation - Task Decomposition

- Skill: `tools-only/2886-plugin-validator-tasks-1c020e4a` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add tools-only/2886-plugin-validator-tasks-1c020e4a`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tools-only/2886-plugin-validator-tasks-1c020e4a/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: tools-only (https://skillmd.com/u/tools-only)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/tools-only/2886-plugin-validator-tasks-1c020e4a

---

# 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

```mermaid
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.md` lines 136-480
- Error code catalog: lines 836-887
- Token measurement spec: lines 1119-1168

**Requirements**:

1. Create `ValidationResult` dataclass with passed/errors/warnings/info
2. Create `ValidationIssue` dataclass with field/severity/message/code/line/suggestion/docs_url
3. Create `ComplexityMetrics` dataclass with token counts and thresholds
4. Create `FileType` StrEnum with skill/agent/command/plugin/unknown
5. Implement error code constants (FM001-FM010, SK001-SK007, LK001-LK002, PD001-PD003, PL001-PL005)
6. Implement documentation URL generator for error codes

**Constraints**:

- Use Python 3.11+ syntax (`str | None`, not `Optional[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**:

1. All dataclasses type-check with mypy strict mode
2. Error code constants match architecture catalog exactly
3. ValidationIssue.format() produces expected output format
4. ComplexityMetrics.status property returns correct severity
5. FileType.detect_file_type() correctly identifies file types

**Verification Steps**:

```bash
# 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

- Verification questions:

  1. Do error codes FM001-FM010 match the frontmatter error catalog in architecture lines 836-849?
  2. Does TOKEN_WARNING_THRESHOLD = 4000 align with "~500 lines equivalent" from line 1156?
  3. 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.md` lines 136-176
- Data models from T1: ValidationResult, ValidationIssue

**Requirements**:

1. Define `Validator` protocol class with Protocol inheritance
2. Method: `validate(path: Path) -> ValidationResult`
3. Method: `can_fix() -> bool`
4. Method: `fix(path: Path) -> list[str]` (returns fixes applied)
5. Add docstrings following architecture examples

**Constraints**:

- Use `typing.Protocol` for 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: `Validator` with three protocol methods

**Acceptance Criteria**:

1. Protocol type-checks with mypy strict mode
2. Sample validator implementation passes protocol check
3. All method signatures match architecture specification
4. Docstrings explain each method's purpose

**Verification Steps**:

```bash
# 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.py` lines 103-187 (validation logic)
- Architecture spec: `./plugin-validator-architecture.md` lines 1038-1073
- Pydantic models from validate_frontmatter.py: SkillFrontmatter, AgentFrontmatter, CommandFrontmatter
- Error codes: FM001-FM010

**Requirements**:

1. Copy Pydantic frontmatter models (SkillFrontmatter, AgentFrontmatter, CommandFrontmatter)
2. Implement `validate(path: Path) -> ValidationResult`
3. Implement `can_fix() -> bool` (returns True)
4. Implement `fix(path: Path) -> list[str]` with auto-fix logic
5. Detect file type (skill/agent/command) to select schema
6. Validate YAML syntax (FM002)
7. Validate frontmatter delimiters (FM003)
8. Validate required fields based on file type (FM001)
9. Validate field types (FM005)
10. Validate field values (FM006)
11. Detect and fix forbidden multiline indicators (FM004)
12. Detect and fix tool/skill YAML arrays → CSV strings (FM007, FM008)
13. Detect and fix unquoted descriptions with colons (FM009)
14. 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: `FrontmatterValidator` implementing Validator protocol
- Pydantic models copied: SkillFrontmatter, AgentFrontmatter, CommandFrontmatter
- Methods: validate(), can_fix(), fix()

**Acceptance Criteria**:

1. Validates skill frontmatter matching validate_frontmatter.py behavior
2. Validates agent frontmatter with required name/description
3. Validates command frontmatter with required description
4. Auto-fixes YAML arrays to CSV strings
5. Auto-fixes multiline indicators
6. Auto-fixes unquoted descriptions
7. Returns ValidationResult with correct error codes
8. Preserves file content exactly when no fixes needed

**Verification Steps**:

```bash
# 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:

  1. Do the Pydantic models in lines 103-187 of validate_frontmatter.py match the copied models?
  2. Does the auto-fix logic for FM007 convert `["Read", "Grep"]` → `"Read, Grep"` exactly?
  3. Are all 10 FM error codes (FM001-FM010) assigned to validation failures?
  4. 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.md` lines 1074-1090
- Bash validation logic: `bash-validation-checks.md` lines 25-28
- Error codes: SK001 (uppercase), SK002 (underscores), SK003 (hyphens)

**Requirements**:

1. Implement `validate(path: Path) -> ValidationResult`
2. Implement `can_fix() -> bool` (returns False)
3. Implement `fix(path: Path) -> list[str]` (raises NotImplementedError)
4. Extract name from frontmatter
5. Check for uppercase characters (SK001)
6. Check for underscores (SK002)
7. Check for leading/trailing hyphens (SK003)
8. Check for consecutive hyphens (SK003)
9. 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: `NameFormatValidator` implementing Validator protocol
- Regex pattern constant: `NAME_PATTERN`

**Acceptance Criteria**:

1. Detects uppercase characters (SK001)
2. Detects underscores (SK002)
3. Detects leading hyphens (SK003)
4. Detects trailing hyphens (SK003)
5. Detects consecutive hyphens (SK003)
6. Passes valid names: "test-skill", "agent-123", "a"
7. Returns ValidationResult with correct error codes

**Verification Steps**:

```bash
# 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.md` lines 1092-1113
- Bash validation logic: `bash-validation-checks.md` lines 31-33
- Error codes: SK004 (too short), SK005 (missing trigger phrases)
- Trigger phrase list: lines 357-358 of architecture

**Requirements**:

1. Implement `validate(path: Path) -> ValidationResult`
2. Implement `can_fix() -> bool` (returns False)
3. Implement `fix(path: Path) -> list[str]` (raises NotImplementedError)
4. Extract description from frontmatter
5. Check minimum length 20 characters (SK004)
6. Check for trigger phrases: "use when", "use this", "trigger", "activate" (SK005)
7. 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: `DescriptionValidator` implementing Validator protocol
- Constant: `MIN_DESCRIPTION_LENGTH = 20`
- Constant: `REQUIRED_TRIGGER_PHRASES = ["use when", "use this", "trigger", "activate"]`

**Acceptance Criteria**:

1. Warns if description <20 characters (SK004)
2. Warns if no trigger phrases present (SK005)
3. Passes if description ≥20 chars AND contains trigger phrase
4. Case-insensitive trigger phrase matching works
5. Returns warnings, not errors

**Verification Steps**:

```bash
# 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.md` lines 1115-1168
- Token measurement example: lines 1122-1151
- Error codes: SK006 (warning >4000 tokens), SK007 (error >6400 tokens)
- tiktoken library documentation (external)

**Requirements**:

1. Implement `validate(path: Path) -> ValidationResult`
2. Implement `can_fix() -> bool` (returns False)
3. Implement `fix(path: Path) -> list[str]` (raises NotImplementedError)
4. Use tiktoken library with cl100k_base encoding
5. Split frontmatter from body content
6. Count tokens in body only (exclude frontmatter)
7. Warn if body_tokens > 4000 (SK006)
8. Error if body_tokens > 6400 (SK007)
9. 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: `ComplexityValidator` implementing 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**:

1. Counts tokens using tiktoken cl100k_base encoding
2. Excludes frontmatter from token count
3. Warns at 4001 tokens (SK006)
4. Errors at 6401 tokens (SK007)
5. Passes at 3999 tokens
6. Validation message includes exact token count
7. Encoding loads lazily (not at import time)

**Verification Steps**:

```bash
# 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:

  1. Is cl100k_base the encoding used by Claude according to tiktoken docs?
  2. Does 4000 tokens ≈ 500 lines and 6400 tokens ≈ 800 lines based on empirical testing?
  3. 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.md` lines 1170-1186
- Bash validation logic: `bash-validation-checks.md` lines 40-44
- Error codes: PD001 (no references/), PD002 (no examples/), PD003 (no scripts/)

**Requirements**:

1. Implement `validate(path: Path) -> ValidationResult`
2. Implement `can_fix() -> bool` (returns False)
3. Implement `fix(path: Path) -> list[str]` (raises NotImplementedError)
4. Check for references/ directory (PD001)
5. Check for examples/ directory (PD002)
6. Check for scripts/ directory (PD003)
7. Count files in each directory if present
8. 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: `ProgressiveDisclosureValidator` implementing Validator protocol
- Directory list: `["references", "examples", "scripts"]`

**Acceptance Criteria**:

1. Reports INFO if references/ missing (PD001)
2. Reports INFO if examples/ missing (PD002)
3. Reports INFO if scripts/ missing (PD003)
4. Includes file count in message if directory exists
5. All issues have severity INFO
6. Returns ValidationResult with info list populated

**Verification Steps**:

```bash
# 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.md` lines 1188-1256
- Link extraction pattern: line 1219 `\[([^\]]+)\]\(([^)]+)\)`
- Bash validation logic: `bash-validation-checks.md` lines 47-50
- Error codes: LK001 (broken link), LK002 (missing ./ prefix)

**Requirements**:

1. Implement `validate(path: Path) -> ValidationResult`
2. Implement `can_fix() -> bool` (returns False)
3. Implement `fix(path: Path) -> list[str]` (raises NotImplementedError)
4. Extract markdown links with regex `\[([^\]]+)\]\(([^)]+)\)`
5. Filter to relative links starting with ./
6. Warn if link doesn't start with ./ (LK002)
7. Error if linked file doesn't exist (LK001)
8. 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: `InternalLinkValidator` implementing Validator protocol
- Regex pattern constant: `LINK_PATTERN = r"\[([^\]]+)\]\(([^)]+)\)"`

**Acceptance Criteria**:

1. Extracts markdown links correctly
2. Warns if link missing ./ prefix (LK002)
3. Errors if linked file doesn't exist (LK001)
4. Ignores external links (http://, https://)
5. Resolves paths relative to skill directory
6. Returns ValidationResult with correct error codes

**Verification Steps**:

```bash
# 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:

  1. Does the regex `\[([^\]]+)\]\(([^)]+)\)` match all markdown link formats?
  2. Does Path.resolve() handle ../relative/path.md correctly?
  3. Do http:// and https:// links get filtered before validation?

- 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

- 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.md` lines 1258-1286
- Claude CLI integration spec: `claude-cli-integration-spec.md` complete file
- Error codes: PL001-PL005

**Requirements**:

1. Implement `validate(path: Path) -> ValidationResult`
2. Implement `can_fix() -> bool` (returns False)
3. Implement `fix(path: Path) -> list[str]` (raises NotImplementedError)
4. Check if claude CLI available using `shutil.which("claude")`
5. Skip validation if claude not available (return success with info message)
6. Skip validation if not a plugin directory (no .claude-plugin/plugin.json)
7. Run `claude plugin validate {plugin_dir}` via subprocess
8. Parse output for errors
9. Map claude output to error codes PL001-PL005
10. Set timeout to 30 seconds
11. 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: `PluginStructureValidator` implementing Validator protocol
- Function: `is_claude_available() -> bool`
- Constant: `CLAUDE_TIMEOUT = 30`

**Acceptance Criteria**:

1. Detects claude CLI availability with shutil.which()
2. Skips validation if claude not available
3. Skips validation if not plugin directory
4. Runs claude plugin validate with timeout
5. Parses output for errors
6. Returns ValidationResult with appropriate error codes
7. Never uses shell=True
8. Handles subprocess timeout gracefully

**Verification Steps**:

```bash
# 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**:
1. `validate(path: Path) -> ValidationResult` - Validates plugin structure using claude CLI
2. `can_fix() -> bool` - Returns False (not auto-fixable)
3. `fix(path: Path) -> list[str]` - Raises NotImplementedError
4. `_get_claude_path() -> str | None` - Detects claude CLI availability using shutil.which()
5. `_find_plugin_directory(path: Path) -> Path | None` - Finds plugin root directory
6. `_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 /home/ubuntulinuxqa2/.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.md` lines 206-272
- Rich table configuration: lines 247-252
- Error display format: lines 254-265
- python3-development skill table patterns (external reference)

**Requirements**:

1. Create Reporter protocol with report() and summarize() methods
2. Create ConsoleReporter for terminal output with Rich
3. Create CIReporter for plain text output (no color)
4. Create SummaryReporter for single-line status
5. Use Rich table box style: `box.MINIMAL_DOUBLE_HEAD`
6. Format errors with file:line references
7. Include error codes in output
8. Include suggestion and docs_url if present
9. 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: `Reporter` with 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**:

1. ConsoleReporter displays colored output with Rich
2. CIReporter displays plain text (no ANSI codes)
3. SummaryReporter displays single-line status
4. All reporters show file:line:code:message format
5. Suggestions and docs URLs displayed when present
6. Table formatting matches python3-development patterns

**Verification Steps**:

```bash
# 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.md` lines 87-129
- CLI command interface: lines 96-107
- Exit codes: lines 111-114
- Usage examples: lines 1291-1345

**Requirements**:

1. Create Typer app with name "plugin-validator"
2. Add main() command with path argument
3. Add --check flag (validate only)
4. Add --fix flag (auto-fix issues)
5. Add --verbose flag (show all checks)
6. Add --no-color flag (disable Rich colors)
7. Implement file type detection
8. Run appropriate validators for file type
9. Collect results
10. If --fix, run auto-fix for fixable validators
11. Re-validate after fixes
12. Report results using Reporter
13. 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**:

1. Accepts path argument (file or di

…(truncated)
