Back to skills
SKILL.md
2884 1 Filetype Enum Extension D6d7f8de
ASecurity``` **Official Schema Sources** (architecture lines 1487-1493): - Hooks: <https://docs.anthropic.com/en/docs/claude-code/hooks.md> - Agents: <https://docs.anthropic.com/en/docs/claude-code/sub-agents.md> - MCP: <https://modelcontextprotocol.io/docs/server> - LSP: <https://docs.anthropic.com/en/docs/claude-code/plugins.md#lsp-servers> - Plugins: <https://docs.anthropic.com/en/docs/claude-code/plugins.md> **Token Counting** (plugin_validator.py lines 44-45): - Library: tiktoken 0.8.0+ - Encodin...
- 9 stars
- 0 votes
- 0 copies
- 1 view
- Added October 11, 2026
Works with
Security analysis
100/100npx -y skills add tools-only/X-Skills --skill 2884-1-filetype-enum-extension_d6d7f8de --agent claude-codeAre you the author of 2884 1 Filetype Enum Extension D6d7f8de?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/tools-only-2884-1-filetype-enum-extension-d6d7f8de)---
task: "1"
title: "FileType Enum Extension"
status: not-started
agent: "@python-cli-architect"
priority: 1
complexity: s
---
## Context Manifest
_Generated by context-gathering agent on 2026-02-13_
### How This Currently Works: Plugin Validation Architecture
The plugin_validator.py (3045 lines) implements a protocol-based validation framework with 9 existing validators that check skills, agents, commands, and plugin structure. When a file is validated:
1. **File Type Detection** (lines 147-165): `FileType.detect_file_type()` classifies files into 5 types (SKILL, AGENT, COMMAND, PLUGIN, UNKNOWN) based on filename and path patterns
2. **Validator Selection** (lines 2896-2913): Hard-coded dispatch selects validators per file type - skills get 7 validators, agents get 4, commands get 4, plugins get 1
3. **Single-File Read** (optimization needed): Currently multiple validators may re-read same file - architecture spec requires reading once and passing content to all validators (lines 814-836 of architecture spec)
4. **Validation Execution**: Each validator implements the Validator protocol (lines 249-286) with `validate(path: Path) -> ValidationResult`, `can_fix() -> bool`, `fix(path: Path) -> list[str]`
5. **Result Aggregation** (lines 2865-2951): Collects ValidationResult objects from all validators
6. **Report Generation** (lines 2599-2858): Three reporter implementations (Console, CI, Summary) format and display results
**Data Models** (lines 168-242):
- `ValidationIssue` (frozen dataclass): field, severity, message, code, line, suggestion, docs_url
- `ValidationResult` (frozen dataclass): passed, errors, warnings, info
- `ComplexityMetrics` (frozen dataclass): total_tokens, frontmatter_tokens, body_tokens, encoding
**Token-Based Complexity** (lines 1939-2122): ComplexityValidator uses tiktoken library (cl100k_base encoding) to count tokens instead of lines. Thresholds: 4000 tokens warning (SK006), 10000 tokens error (SK007). Architecture at lines 44-45 defines these constants.
**Pydantic Schema Validation** (lines 1030-1236): Three frontmatter models:
- `SkillFrontmatter` (10 fields, all optional, normalizes CSV fields)
- `CommandFrontmatter` (7 fields, description required, normalizes CSV)
- `AgentFrontmatter` (9+ fields, name+description required, uses camelCase per official schema)
**Validation Flow per Validator:**
1. **FrontmatterValidator** (lines 1243-1600): Extracts YAML frontmatter, validates with Pydantic model, converts Pydantic errors to ValidationIssues, auto-fixes YAML arrays→CSV, multiline→single-line, removes name field from plugin skills (Claude Code bug workaround lines 1541-1560)
2. **NameFormatValidator** (lines 1603-1787): Checks name pattern `^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$`, no auto-fix
3. **DescriptionValidator** (lines 1790-1936): Checks min 20 chars (SK004), requires trigger phrases (SK005) from REQUIRED_TRIGGER_PHRASES constant (lines 56-64), no auto-fix
4. **ComplexityValidator** (lines 1939-2122): Uses tiktoken to count tokens, splits frontmatter vs body, no auto-fix
5. **InternalLinkValidator** (lines 448-631): Regex extracts markdown links, checks file existence, ignores code blocks (lines 468-490), no auto-fix
6. **ProgressiveDisclosureValidator** (lines 334-441): Checks for references/, examples/, scripts/ directories, INFO severity only, no auto-fix
7. **NamespaceReferenceValidator** (lines 638-1023): Parses namespace-qualified references (Skill(), Task(), @agent, /command), resolves from settings.json, checks target file exists, no auto-fix
8. **PluginStructureValidator** (lines 2125-2414): Validates plugin.json schema, runs `claude plugin validate` CLI if available (lines 2421-2500), no auto-fix
**Known UX Bugs:**
- Lines 2681-2709: ConsoleReporter counts ValidationResult objects not unique files (shows "7 files" for 1 file with 7 validators)
- Lines 904-911: Dead code in NamespaceReferenceValidator after early return (need coverage verification before removal)
- Line 1802: DescriptionValidator fires SK005 on commands (commands don't need trigger phrases since explicitly invoked)
**Error Code Registry** (lines 71-109): 23 existing codes across 6 categories:
- FM001-FM010: Frontmatter errors (10 codes)
- SK001-SK007: Skill errors (7 codes)
- LK001-LK002: Link errors (2 codes)
- PD001-PD003: Progressive disclosure (3 codes)
- PL001-PL005: Plugin errors (5 codes)
- NR001-NR002: Namespace reference errors (2 codes)
### For New Feature Implementation: Hook/MCP/LSP Configuration Validation
**Architecture Requirements** (architect-plugin-linter.md):
Need to add 4 new FileType variants (lines 85-130 of architecture):
- `HOOK_CONFIG` - Detects `hooks.json` exact filename
- `MCP_CONFIG` - Detects `.mcp.json` exact filename
- `LSP_CONFIG` - Detects `.lsp.json` exact filename
- `HOOK_SCRIPT` - Detects `hooks/*.{js,py,sh}` directory pattern
**Detection Priority** (architecture lines 105-130):
1. Exact filename matches (hooks.json, .mcp.json, .lsp.json)
2. Special filenames (SKILL.md, plugin.json)
3. Directory-based (agents/, commands/, hooks/)
4. UNKNOWN fallback
**New Pydantic Models Required** (architecture lines 135-312):
**HookConfig Schema** (architecture lines 135-194, official source: <https://docs.anthropic.com/en/docs/claude-code/hooks.md>):
- 15 valid event types: SessionStart, UserPromptSubmit, PreToolUse, PermissionRequest, PostToolUse, PostToolUseFailure, Notification, SubagentStart, SubagentStop, Stop, TeammateIdle, TaskCompleted, PreCompact, SessionEnd, ToolUseFailure
- 3 hook types: COMMAND (shell execution), PROMPT (LLM injection), AGENT (sub-agent invocation)
- Discriminated union on type field - command/prompt/agent fields required based on type
- Matcher field contains regex pattern (must validate compilation without execution)
- Timeout field must be positive integer if present
**MCPConfig Schema** (architecture lines 196-222, official source: <https://modelcontextprotocol.io/docs/server>):
- Required: command (non-empty string)
- Optional: args (list of strings NOT single string), env (dict[str, str]), cwd (directory path)
- Validation: command existence check with shutil.which() as WARNING only (may not exist at validation time)
**LSPConfig Schema** (architecture lines 224-265, official source: <https://docs.anthropic.com/en/docs/claude-code/plugins.md#lsp-servers>):
- Required: command (non-empty string), extensionToLanguage (non-empty dict)
- Extension keys must start with dot (.py not py or *.py)
- Language values must be lowercase identifiers
- Transport: stdio or socket only
- Timeouts must be positive integers
- maxRestarts must be positive
**AgentFrontmatter Enum Enhancement** (architecture lines 267-312):
Existing AgentFrontmatter model (lines 1167-1235) needs 3 new enum validations:
- `model` field: Add AgentModel enum (sonnet, opus, haiku, inherit)
- `permissionMode` field: Add AgentPermissionMode enum (6 values including default, acceptEdits, dontAsk, etc.)
- `memory` field: Add AgentMemory enum (user, project, local)
**New Validators Required** (architecture lines 360-580):
**HookConfigValidator** (architecture lines 360-420):
- No auto-fix (JSON too complex)
- Validates 15 event types with fuzzy matching suggestions for unknown types
- Validates hook type discriminators
- Compiles regex patterns without execution (security)
- Error codes: HK001-HK010
**MCPConfigValidator** (architecture lines 422-473):
- No auto-fix
- Command existence check via shutil.which() produces WARNING not error
- Args must be list[str] not single string
- Env must be dict[str, str]
- Error codes: MC001-MC010
**LSPConfigValidator** (architecture lines 475-528):
- No auto-fix
- Strict extension format validation (.py not py)
- Lowercase language identifier enforcement
- Transport enum validation
- Error codes: LS001-LS010
**AgentEnumValidator** (architecture lines 530-580):
- No auto-fix (would guess user intent)
- Validates enum fields against official schema
- Provides suggestions for invalid enum values
- Only runs on FileType.AGENT files
- Error codes: AG001-AG010
**DescriptionValidator Modification** (architecture lines 582-629):
Current signature: `validate(self, path: Path, content: str) -> ValidationResult`
New signature: `validate(self, path: Path, content: str, file_type: FileType) -> ValidationResult`
Behavior change:
- Skip SK005 (trigger phrase check) when `file_type == FileType.COMMAND`
- Continue SK005 for SKILL and AGENT types
- Preserve SK004 (length check) for all types
**Validator Registration** (architecture lines 637-697):
Need to create VALIDATORS_BY_TYPE dispatch table:
```python
VALIDATORS_BY_TYPE: dict[FileType, list[type[Validator]]] = {
FileType.SKILL: [FrontmatterValidator, NameFormatValidator, DescriptionValidator, ComplexityValidator, InternalLinkValidator, ProgressiveDisclosureValidator, NamespaceReferenceValidator],
FileType.AGENT: [FrontmatterValidator, NameFormatValidator, DescriptionValidator, AgentEnumValidator, NamespaceReferenceValidator],
FileType.COMMAND: [FrontmatterValidator, DescriptionValidator, NamespaceReferenceValidator], # SK005 skipped
FileType.HOOK_CONFIG: [HookConfigValidator],
FileType.MCP_CONFIG: [MCPConfigValidator],
FileType.LSP_CONFIG: [LSPConfigValidator],
FileType.PLUGIN: [PluginStructureValidator],
}
```
**Error Code Registry Expansion** (architecture lines 700-763):
Need 40 new error code constants (lines 71-109 pattern):
- HK001-HK010: Hook configuration errors (10 codes)
- MC001-MC010: MCP configuration errors (10 codes)
- LS001-LS010: LSP configuration errors (10 codes)
- AG001-AG010: Agent enum errors (10 codes)
**Report Generation Fix** (architecture lines 836-893):
Change from counting validators to counting files:
- Current: `len(results)` counts ValidationResult objects
- Required: Count unique file paths `len(set(path for path, _ in results))`
- Message change: "X validators passed" → "X files validated"
- Group issues by file path, then by error code within file
**Dead Code Removal** (architecture lines 1149-1165):
Lines 904-911 in NamespaceReferenceValidator contain unreachable nested skill reference resolution after early return line 903. Verify with coverage before removal.
**Testing Strategy** (architecture lines 900-1027):
Minimum coverage: 80% overall, 90% for new validators
Test files needed:
- test_hook_config_validator.py - parametrize 15 event types, test all HK error codes
- test_mcp_config_validator.py - mock shutil.which(), test warning vs error severity
- test_lsp_config_validator.py - parametrize extension formats, test language identifier validation
- test_agent_enum_validator.py - parametrize valid enum combinations, test suggestion quality
- test_file_type_detection.py - test all 9 FileType values, edge cases (nested paths)
- test_report_generation.py - verify file counts not validator counts
- test_description_validator.py - add file_type parameter tests
**Performance Requirements** (architecture lines 1060-1097):
- Single file: <1 second
- Plugin with 10 components: <5 seconds
- Full repository scan: <30 seconds
- Optimization: Read each file once, pass content to all validators (no redundant I/O)
**Pre-Commit Integration** (architecture lines 1129-1143):
Current .pre-commit-config.yaml pattern (line 1136):
```yaml
files: '^plugins/.*(SKILL\.md|agents/.*\.md|commands/.*\.md|plugin\.json)$'
```
Required enhancement:
```yaml
files: '^plugins/.*(SKILL\.md|agents/.*\.md|commands/.*\.md|plugin\.json|hooks\.json|\.mcp\.json|\.lsp\.json)$'
```
### Technical Reference Details
#### Component Interfaces & Signatures
**FileType Enum Extension** (plugin_validator.py lines 138-166, architecture lines 85-130):
```python
class FileType(StrEnum):
SKILL = "skill"
AGENT = "agent"
COMMAND = "command"
PLUGIN = "plugin"
HOOK_CONFIG = "hook_config" # NEW
MCP_CONFIG = "mcp_config" # NEW
LSP_CONFIG = "lsp_config" # NEW
HOOK_SCRIPT = "hook_script" # NEW
UNKNOWN = "unknown"
@staticmethod
def detect_file_type(path: Path) -> FileType:
"""Detect file type from path structure and filename.
Detection priority order:
1. Exact filename matches (hooks.json, .mcp.json, .lsp.json)
2. Special filenames (SKILL.md, plugin.json)
3. Directory-based (agents/, commands/, hooks/)
4. UNKNOWN fallback
"""
```
**Validator Protocol** (plugin_validator.py lines 249-286, unchanged):
```python
class Validator(Protocol):
def validate(self, path: Path, content: str) -> ValidationResult: ...
def can_fix(self, issue: ValidationIssue) -> bool: ...
def fix(self, path: Path, content: str) -> str: ...
```
**DescriptionValidator Signature Change** (architecture lines 596-629):
```python
class DescriptionValidator:
def validate(
self,
path: Path,
content: str,
file_type: FileType # NEW PARAMETER
) -> ValidationResult:
"""Validate description field with file-type awareness.
Checks:
- Minimum length (SK004) - ALL file types
- Trigger phrases (SK005) - ONLY skills and agents, skip commands
Args:
path: Path to file
content: File content
file_type: FileType enum (determines SK005 behavior)
Returns:
ValidationResult with SK errors (SK005 skipped for commands)
"""
```
#### Data Structures
**HookConfig Pydantic Models** (architecture lines 135-194):
```python
from pydantic import BaseModel, Field
class HookType(StrEnum):
COMMAND = "command"
PROMPT = "prompt"
AGENT = "agent"
class HookEventType(StrEnum):
SESSION_START = "SessionStart"
USER_PROMPT_SUBMIT = "UserPromptSubmit"
PRE_TOOL_USE = "PreToolUse"
PERMISSION_REQUEST = "PermissionRequest"
POST_TOOL_USE = "PostToolUse"
POST_TOOL_USE_FAILURE = "PostToolUseFailure"
NOTIFICATION = "Notification"
SUBAGENT_START = "SubagentStart"
SUBAGENT_STOP = "SubagentStop"
STOP = "Stop"
TEAMMATE_IDLE = "TeammateIdle"
TASK_COMPLETED = "TaskCompleted"
PRE_COMPACT = "PreCompact"
SESSION_END = "SessionEnd"
class HookDefinition(BaseModel):
type: HookType
command: str | None = None # Required if type=command
prompt: str | None = None # Required if type=prompt
agent: str | None = None # Required if type=agent
timeout: int | None = None
model: str | None = None
class EventMatcher(BaseModel):
matcher: str | None = None # Optional regex pattern
hooks: list[HookDefinition]
class HookConfig(BaseModel):
hooks: dict[str, list[EventMatcher]] # Event name → matchers
```
**MCPConfig Pydantic Models** (architecture lines 196-222):
```python
class MCPServer(BaseModel):
command: str
args: list[str] = Field(default_factory=list)
env: dict[str, str] = Field(default_factory=dict)
cwd: str | None = None
class MCPConfig(BaseModel):
mcpServers: dict[str, MCPServer]
```
**LSPConfig Pydantic Models** (architecture lines 224-265):
```python
class LSPTransport(StrEnum):
STDIO = "stdio"
SOCKET = "socket"
class LSPServer(BaseModel):
command: str
extensionToLanguage: dict[str, str]
args: list[str] = Field(default_factory=list)
transport: LSPTransport = LSPTransport.STDIO
env: dict[str, str] = Field(default_factory=dict)
initializationOptions: dict[str, Any] = Field(default_factory=dict)
settings: dict[str, Any] = Field(default_factory=dict)
workspaceFolder: str | None = None
startupTimeout: int | None = None
shutdownTimeout: int | None = None
restartOnCrash: bool = False
maxRestarts: int | None = None
class LSPConfig(BaseModel):
lspServers: dict[str, LSPServer]
```
**AgentFrontmatter Enum Models** (architecture lines 267-312):
```python
class AgentModel(StrEnum):
SONNET = "sonnet"
OPUS = "opus"
HAIKU = "haiku"
INHERIT = "inherit"
class AgentPermissionMode(StrEnum):
DEFAULT = "default"
ACCEPT_EDITS = "acceptEdits"
DELEGATE = "delegate"
DONT_ASK = "dontAsk"
BYPASS_PERMISSIONS = "bypassPermissions"
PLAN = "plan"
class AgentMemory(StrEnum):
USER = "user"
PROJECT = "project"
LOCAL = "local"
class AgentFrontmatter(BaseModel):
name: str # Required
description: str # Required
model: AgentModel | None = None # Enhanced with enum
permissionMode: AgentPermissionMode | None = None # Enhanced with enum
memory: AgentMemory | None = None # NEW with enum
# ... other existing fields (existing validators unchanged)
```
#### Configuration Requirements
**Official Schema Sources** (architecture lines 1487-1493):
- Hooks: <https://docs.anthropic.com/en/docs/claude-code/hooks.md>
- Agents: <https://docs.anthropic.com/en/docs/claude-code/sub-agents.md>
- MCP: <https://modelcontextprotocol.io/docs/server>
- LSP: <https://docs.anthropic.com/en/docs/claude-code/plugins.md#lsp-servers>
- Plugins: <https://docs.anthropic.com/en/docs/claude-code/plugins.md>
**Token Counting** (plugin_validator.py lines 44-45):
- Library: tiktoken 0.8.0+
- Encoding: cl100k_base
- Warning threshold: 4000 tokens
- Error threshold: 10000 tokens
**Dependencies** (plugin_validator.py lines 1-11):
```python
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "typer>=0.21.0",
# "rich>=13.0.0",
# "tiktoken>=0.8.0",
# "pyyaml>=6.0",
# "pydantic>=2.0.0",
# ]
# ///
```
#### File Locations
**Implementation Target**: `plugins/plugin-creator/scripts/plugin_validator.py`
**Key Line Regions**:
- Lines 71-109: Error code constants (add 40 new constants)
- Lines 138-166: FileType enum (add 4 new variants)
- Lines 147-165: detect_file_type() method (enhance detection logic)
- Lines 1030-1236: Pydantic models (add HookConfig, MCPConfig, LSPConfig, agent enums)
- Lines 1790-1936: DescriptionValidator (add file_type parameter)
- Lines 2896-2913: Validator registration (create VALIDATORS_BY_TYPE dispatch)
- Lines 2681-2709: ConsoleReporter.summarize() (fix file counting)
- Lines 904-911: Dead code removal (verify with coverage first)
**Test Files to Create**:
- `plugins/plugin-creator/tests/test_hook_config_validator.py`
- `plugins/plugin-creator/tests/test_mcp_config_validator.py`
- `plugins/plugin-creator/tests/test_lsp_config_validator.py`
- `plugins/plugin-creator/tests/test_agent_enum_validator.py`
- `plugins/plugin-creator/tests/test_file_type_detection.py`
- `plugins/plugin-creator/tests/test_report_generation.py`
**Test Files to Modify**:
- `plugins/plugin-creator/tests/test_description_validator.py` (add file_type parameter tests)
**Documentation to Update**:
- `plugins/plugin-creator/scripts/ERROR_CODES.md` (add 40 new error code entries)
**Pre-Commit Config**:
- `.pre-commit-config.yaml` (update file pattern around line 1136)
#### References
**Primary Sources** (Read Before Implementation):
1. **Task decomposition**: `./plan/tasks-1-plugin-linter.md` - Complete task breakdown with dependencies
2. **Architecture specification**: `./plan/architect-plugin-linter.md` - WHAT to build (interfaces, contracts, schemas)
3. **Feature context**: `./plan/feature-context-plugin-linter.md` - WHY this feature exists, gaps identified
4. **Codebase analysis**: `./plan/codebase/plugin-validator-architecture.md` - HOW current system works
5. **Main implementation**: `./plugins/plugin-creator/scripts/plugin_validator.py` - Complete 3045-line validator
6. **Existing tests**: `./plugins/plugin-creator/tests/` - Test patterns to follow (11 test files)
7. **Pre-commit config**: `./.pre-commit-config.yaml` - Hook integration patterns
**Official Documentation** (Cite in Model Docstrings):
- Hooks schema: <https://docs.anthropic.com/en/docs/claude-code/hooks.md>
- Agent schema: <https://docs.anthropic.com/en/docs/claude-code/sub-agents.md>
- MCP schema: <https://modelcontextprotocol.io/docs/server>
- LSP schema: <https://docs.anthropic.com/en/docs/claude-code/plugins.md#lsp-servers>
**Testing Standards** (architecture lines 1030-1051):
- Fixture type hints required: `Generator[YieldType, None, None]`
- Test function signatures: All parameters typed, `-> None` return type
- Mocking: pytest-mock only, NEVER unittest.mock
- AAA pattern: Arrange-Act-Assert with comments
- Property-based: Use hypothesis for validation functions, minimum 500 examples
**Verification Checklist Before Starting**:
- [ ] Read complete architecture specification (architect-plugin-linter.md)
- [ ] Read complete task decomposition (tasks-1-plugin-linter.md)
- [ ] Read current plugin_validator.py implementation (all 3045 lines)
- [ ] Read all official schema documentation URLs above
- [ ] Understand FileType detection priority order
- [ ] Understand Validator protocol contract
- [ ] Understand validation pipeline flow (detect → select → validate → aggregate → report)
- [ ] Understand token-based complexity measurement (tiktoken usage)
- [ ] Understand Pydantic field validator patterns from existing models
- [ ] Understand existing test file structure (conftest.py fixtures, test class patterns)
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.