Tasks: plugin-validator UX and coverage gaps
Feature Summary
Fix UX bugs and expand validation coverage in plugin-validator.py.
Four independent sub-issues from groomed backlog item.
Pre-existing Test State
18 failed, 260 passed, 1 skipped as of 2026-02-14.
Do NOT regress any passing tests. Do NOT fix pre-existing failures unless they are directly in the scope of a task below.
Context Manifest
Primary Files
./plugins/plugin-creator/scripts/plugin-validator.py (3045 lines)
./plugins/plugin-creator/tests/conftest.py (341 lines)
Architecture
- Validator Protocol (line 249):
validate(path) -> ValidationResult, can_fix() -> bool, fix(path) -> list[str]
- FileType enum (line 138):
SKILL, AGENT, COMMAND, PLUGIN, UNKNOWN
- Error codes (lines 66-112): FM001-FM010, SK001-SK007, LK001-LK002, PD001-PD003, PL001-PL005, NR001-NR002
- Validator selection (lines 2885-2925): Skills/Agents/Commands get FrontmatterValidator, NameFormatValidator, DescriptionValidator, NamespaceReferenceValidator. Skills additionally get ComplexityValidator, InternalLinkValidator, ProgressiveDisclosureValidator. Plugins get PluginStructureValidator.
- Result collection (lines 2928-2931): Iterates validators (not files), creating duplicate path entries
- Report display (lines 2620-2710): Prints per-result, counts results as files
Test Conventions
- Module loaded via
importlib.util.spec_from_file_location("plugin_validator", ...) (conftest.py)
- Fixtures:
cli_runner, sample_skill_dir, sample_agent_dir, sample_plugin_dir, mock_frontmatter_file
- Pattern: create tmp files with frontmatter, instantiate validator, call
.validate(), assert on ValidationResult
- Class-based test organization,
pytest.mark.parametrize
Linting
- Ruff py311 strict mode
- Per-file ignores for
plugins/plugin-creator/scripts/*.py: B008, TC003
- Per-file ignores for
**/scripts/**: ANN401, DOC, PLC0415, PLR0911, S, T201
- Per-file ignores for
**/tests/**: ANN, D, DOC, E501, EXE, N, PLC, PLR, S, SLF, T
Task 1: Fix report counting — unique files not validator invocations
Status: ✅ COMPLETE
Started: 2026-02-14T16:21:00Z
Completed: 2026-02-14T16:30:00Z
Priority: P0 (Must Have)
Estimated scope: ~50 lines changed
Problem
Lines 2928-2931 iterate over validators (not files), appending (path, result) for each validator. When 1 file has 4 validators, results list has 4 entries pointing to the same path. The report at line 2630 prints "PASSED" 4 times for 1 file. The summary at line 2702 shows "Total files: 4" for 1 file.
Changes Required
- Restructure result collection (lines 2928-2931) to group results by file path
- Update report display (lines 2620-2710) to:
- Show each file once with all validator results beneath it
- Label each validator result with the validator class name (e.g., "FrontmatterValidator: PASSED")
- A file passes overall only if ALL its validators pass
- Update summary (line 2702) to count unique file paths
Acceptance Criteria
- Running validator on 1 file shows "Total files: 1"
- Each validator result is labeled with the validator name
- Summary counts unique files, not validator invocations
- All currently-passing tests remain passing
Test Requirements
- Add test: single file with multiple validators shows "Total files: 1"
- Add test: validator names appear in per-file output
Task 2: File-type-aware DescriptionValidator — SK004/SK005 scoping
Status: ✅ COMPLETE
Started: 2026-02-14T16:31:00Z
Completed: 2026-02-14T16:40:00Z
Priority: P0 (Must Have)
Estimated scope: ~80 lines changed
Problem
DescriptionValidator.validate() (line 1790) applies SK004 ("description too short") and SK005 ("missing trigger phrases") to all file types. Commands have a different frontmatter schema and don't need trigger phrases.
Changes Required
- Add
file_type: FileType parameter to DescriptionValidator.__init__() (or pass FileType to validate())
- SK005 ("missing trigger phrases"): Only fire on SKILL files
- SK004 ("description too short"): Fire on SKILL and AGENT files, not COMMAND
- Update validator selection (lines 2885-2925) to pass FileType when constructing DescriptionValidator
- Define new error code series CM001+ for command-specific description checks (future — stub only)
Acceptance Criteria
- SK005 only fires on SKILL files (not COMMAND or AGENT)
- SK004 fires on SKILL and AGENT files but not COMMAND
- Validator selection passes FileType context to DescriptionValidator
- All currently-passing tests remain passing
Test Requirements
- Add test: command file does NOT receive SK005 warning
- Add test: command file does NOT receive SK004 warning
- Add test: agent file does NOT receive SK005 warning
- Add test: agent file still receives SK004 warning
- Add test: skill file still receives both SK004 and SK005
Task 3: Hook validation — FileType.HOOK and HookValidator
Status: ✅ COMPLETE
Started: 2026-02-14T16:41:00Z
Completed: 2026-02-14T16:55:00Z
Priority: P1 (Should Have)
Estimated scope: ~200 lines new code
Problem
FileType enum (line 138) has no HOOK variant. detect_file_type() returns UNKNOWN for .js files in hooks/ directories and hooks.json files.
Changes Required
- Add
HOOK_SCRIPT and HOOK_CONFIG to FileType enum (line 138)
- Update
detect_file_type() to recognize:
.js files in hooks/ directories -> HOOK_SCRIPT
hooks.json files -> HOOK_CONFIG
- Define new error code constants: HK001 (invalid hooks.json), HK002 (invalid event type), HK003 (invalid hook structure)
- Create
HookValidator class implementing Validator protocol:
- For HOOK_CONFIG: validate JSON structure, valid event types, valid matcher patterns
- For HOOK_SCRIPT: validate file is valid JavaScript (basic syntax check), has proper shebang
- Update validator selection to assign HookValidator for HOOK_SCRIPT and HOOK_CONFIG files
- Reference:
/plugin-creator:claude-hooks-reference-2026 skill for hooks.json schema
Acceptance Criteria
detect_file_type() recognizes .js files in hooks/ directories
detect_file_type() recognizes hooks.json files
HookValidator validates hooks.json structure
- New HK001-HK003 error codes defined and used
- All currently-passing tests remain passing
Test Requirements
- New test file:
test_hook_validator.py
- Test: hooks.json with valid structure passes
- Test: hooks.json with invalid JSON fails (HK001)
- Test: hooks.json with invalid event type fails (HK002)
- Test: .js hook file detected as HOOK_SCRIPT
- Test: hooks.json detected as HOOK_CONFIG
- Test: detect_file_type for hook files returns correct FileType
Task 4: Remove dead code — nested skill error message references
Status: ✅ COMPLETE
Started: 2026-02-14T16:15:00Z
Completed: 2026-02-14T16:20:00Z
Priority: P2 (Could Have)
Estimated scope: ~10 lines changed
Problem
CORRECTION from backlog: Lines 904-911 are NOT dead code. The nested pattern plugins/{plugin}/skills/*/{name}/SKILL.md exists in the repo (e.g., python3-development/skills/testing/*/SKILL.md, python3-development/skills/development/*/SKILL.md).
However, the error message strings at lines 758-760 and 770-773 reference the nested pattern with a glob wildcard (skills/*/) which is confusing in user-facing error messages. These should be rephrased for clarity.
Changes Required
- Update error message at lines 758-760 to clarify the nested pattern (e.g., "plugins/{plugin}/skills/{name}/SKILL.md or plugins/{plugin}/skills/{category}/{name}/SKILL.md")
- Update error message at lines 770-773 similarly
- Verify no test depends on exact error message text (grep tests for the old strings)
Acceptance Criteria
- Error messages clearly describe both flat and nested skill paths
- No wildcard globs in error messages shown to users
- All currently-passing tests remain passing
Test Requirements
- Verify existing NR tests still pass after message change
- No new tests needed (cosmetic change)
Dependencies
Tasks 1-4 are independent and can be implemented in parallel.
Task 3 is the largest (new validator class, new error codes, new test file).
Execution Order (suggested)
- Task 4 (smallest, cosmetic) — builds confidence, fast win
- Task 1 (UX fix) — most visible improvement
- Task 2 (file-type awareness) — false positive elimination
- Task 3 (hook validation) — largest, new feature
1---2name: 2870-tasks-2-validator-ux-coverage-4a8ccd993description: Tasks: plugin-validator UX and coverage gaps4---56# Tasks: plugin-validator UX and coverage gaps78## Feature Summary910Fix UX bugs and expand validation coverage in `plugin-validator.py`.11Four independent sub-issues from groomed backlog item.1213## Pre-existing Test State1415**18 failed, 260 passed, 1 skipped** as of 2026-02-14.16Do NOT regress any passing tests. Do NOT fix pre-existing failures unless they are directly in the scope of a task below.1718## Context Manifest1920### Primary Files2122- `./plugins/plugin-creator/scripts/plugin-validator.py` (3045 lines)23- `./plugins/plugin-creator/tests/conftest.py` (341 lines)2425### Architecture2627- **Validator Protocol** (line 249): `validate(path) -> ValidationResult`, `can_fix() -> bool`, `fix(path) -> list[str]`28- **FileType enum** (line 138): `SKILL`, `AGENT`, `COMMAND`, `PLUGIN`, `UNKNOWN`29- **Error codes** (lines 66-112): FM001-FM010, SK001-SK007, LK001-LK002, PD001-PD003, PL001-PL005, NR001-NR00230- **Validator selection** (lines 2885-2925): Skills/Agents/Commands get FrontmatterValidator, NameFormatValidator, DescriptionValidator, NamespaceReferenceValidator. Skills additionally get ComplexityValidator, InternalLinkValidator, ProgressiveDisclosureValidator. Plugins get PluginStructureValidator.31- **Result collection** (lines 2928-2931): Iterates validators (not files), creating duplicate path entries32- **Report display** (lines 2620-2710): Prints per-result, counts results as files3334### Test Conventions3536- Module loaded via `importlib.util.spec_from_file_location("plugin_validator", ...)` (conftest.py)37- Fixtures: `cli_runner`, `sample_skill_dir`, `sample_agent_dir`, `sample_plugin_dir`, `mock_frontmatter_file`38- Pattern: create tmp files with frontmatter, instantiate validator, call `.validate()`, assert on `ValidationResult`39- Class-based test organization, `pytest.mark.parametrize`4041### Linting4243- Ruff py311 strict mode44- Per-file ignores for `plugins/plugin-creator/scripts/*.py`: B008, TC00345- Per-file ignores for `**/scripts/**`: ANN401, DOC, PLC0415, PLR0911, S, T20146- Per-file ignores for `**/tests/**`: ANN, D, DOC, E501, EXE, N, PLC, PLR, S, SLF, T4748---4950## Task 1: Fix report counting — unique files not validator invocations5152**Status**: ✅ COMPLETE53**Started**: 2026-02-14T16:21:00Z54**Completed**: 2026-02-14T16:30:00Z55**Priority**: P0 (Must Have)56**Estimated scope**: ~50 lines changed5758### Problem5960Lines 2928-2931 iterate over `validators` (not files), appending `(path, result)` for each validator. When 1 file has 4 validators, `results` list has 4 entries pointing to the same path. The report at line 2630 prints "PASSED" 4 times for 1 file. The summary at line 2702 shows "Total files: 4" for 1 file.6162### Changes Required63641. Restructure result collection (lines 2928-2931) to group results by file path652. Update report display (lines 2620-2710) to:66 - Show each file once with all validator results beneath it67 - Label each validator result with the validator class name (e.g., "FrontmatterValidator: PASSED")68 - A file passes overall only if ALL its validators pass693. Update summary (line 2702) to count unique file paths7071### Acceptance Criteria7273- Running validator on 1 file shows "Total files: 1"74- Each validator result is labeled with the validator name75- Summary counts unique files, not validator invocations76- All currently-passing tests remain passing7778### Test Requirements7980- Add test: single file with multiple validators shows "Total files: 1"81- Add test: validator names appear in per-file output8283---8485## Task 2: File-type-aware DescriptionValidator — SK004/SK005 scoping8687**Status**: ✅ COMPLETE88**Started**: 2026-02-14T16:31:00Z89**Completed**: 2026-02-14T16:40:00Z90**Priority**: P0 (Must Have)91**Estimated scope**: ~80 lines changed9293### Problem9495`DescriptionValidator.validate()` (line 1790) applies SK004 ("description too short") and SK005 ("missing trigger phrases") to all file types. Commands have a different frontmatter schema and don't need trigger phrases.9697### Changes Required98991. Add `file_type: FileType` parameter to `DescriptionValidator.__init__()` (or pass FileType to `validate()`)1002. SK005 ("missing trigger phrases"): Only fire on SKILL files1013. SK004 ("description too short"): Fire on SKILL and AGENT files, not COMMAND1024. Update validator selection (lines 2885-2925) to pass FileType when constructing DescriptionValidator1035. Define new error code series CM001+ for command-specific description checks (future — stub only)104105### Acceptance Criteria106107- SK005 only fires on SKILL files (not COMMAND or AGENT)108- SK004 fires on SKILL and AGENT files but not COMMAND109- Validator selection passes FileType context to DescriptionValidator110- All currently-passing tests remain passing111112### Test Requirements113114- Add test: command file does NOT receive SK005 warning115- Add test: command file does NOT receive SK004 warning116- Add test: agent file does NOT receive SK005 warning117- Add test: agent file still receives SK004 warning118- Add test: skill file still receives both SK004 and SK005119120---121122## Task 3: Hook validation — FileType.HOOK and HookValidator123124**Status**: ✅ COMPLETE125**Started**: 2026-02-14T16:41:00Z126**Completed**: 2026-02-14T16:55:00Z127**Priority**: P1 (Should Have)128**Estimated scope**: ~200 lines new code129130### Problem131132`FileType` enum (line 138) has no HOOK variant. `detect_file_type()` returns UNKNOWN for `.js` files in `hooks/` directories and `hooks.json` files.133134### Changes Required1351361. Add `HOOK_SCRIPT` and `HOOK_CONFIG` to `FileType` enum (line 138)1372. Update `detect_file_type()` to recognize:138 - `.js` files in `hooks/` directories -> HOOK_SCRIPT139 - `hooks.json` files -> HOOK_CONFIG1403. Define new error code constants: HK001 (invalid hooks.json), HK002 (invalid event type), HK003 (invalid hook structure)1414. Create `HookValidator` class implementing Validator protocol:142 - For HOOK_CONFIG: validate JSON structure, valid event types, valid matcher patterns143 - For HOOK_SCRIPT: validate file is valid JavaScript (basic syntax check), has proper shebang1445. Update validator selection to assign HookValidator for HOOK_SCRIPT and HOOK_CONFIG files1456. Reference: `/plugin-creator:claude-hooks-reference-2026` skill for hooks.json schema146147### Acceptance Criteria148149- `detect_file_type()` recognizes `.js` files in `hooks/` directories150- `detect_file_type()` recognizes `hooks.json` files151- `HookValidator` validates hooks.json structure152- New HK001-HK003 error codes defined and used153- All currently-passing tests remain passing154155### Test Requirements156157- New test file: `test_hook_validator.py`158- Test: hooks.json with valid structure passes159- Test: hooks.json with invalid JSON fails (HK001)160- Test: hooks.json with invalid event type fails (HK002)161- Test: .js hook file detected as HOOK_SCRIPT162- Test: hooks.json detected as HOOK_CONFIG163- Test: detect_file_type for hook files returns correct FileType164165---166167## Task 4: Remove dead code — nested skill error message references168169**Status**: ✅ COMPLETE170**Started**: 2026-02-14T16:15:00Z171**Completed**: 2026-02-14T16:20:00Z172**Priority**: P2 (Could Have)173**Estimated scope**: ~10 lines changed174175### Problem176177**CORRECTION from backlog**: Lines 904-911 are NOT dead code. The nested pattern `plugins/{plugin}/skills/*/{name}/SKILL.md` exists in the repo (e.g., `python3-development/skills/testing/*/SKILL.md`, `python3-development/skills/development/*/SKILL.md`).178179However, the error message strings at lines 758-760 and 770-773 reference the nested pattern with a glob wildcard (`skills/*/`) which is confusing in user-facing error messages. These should be rephrased for clarity.180181### Changes Required1821831. Update error message at lines 758-760 to clarify the nested pattern (e.g., "plugins/{plugin}/skills/{name}/SKILL.md or plugins/{plugin}/skills/{category}/{name}/SKILL.md")1842. Update error message at lines 770-773 similarly1853. Verify no test depends on exact error message text (grep tests for the old strings)186187### Acceptance Criteria188189- Error messages clearly describe both flat and nested skill paths190- No wildcard globs in error messages shown to users191- All currently-passing tests remain passing192193### Test Requirements194195- Verify existing NR tests still pass after message change196- No new tests needed (cosmetic change)197198---199200## Dependencies201202Tasks 1-4 are independent and can be implemented in parallel.203Task 3 is the largest (new validator class, new error codes, new test file).204205## Execution Order (suggested)2062071. Task 4 (smallest, cosmetic) — builds confidence, fast win2082. Task 1 (UX fix) — most visible improvement2093. Task 2 (file-type awareness) — false positive elimination2104. Task 3 (hook validation) — largest, new feature