Implement dynamic file discovery for components (PR #133)

Replace hardcoded file arrays with dynamic discovery system:
- CoreComponent: Auto-discovers framework .md files in Core directory
- CommandsComponent: Auto-discovers command .md files in Commands directory
- Eliminates manual maintenance of file lists
- Maintains backward compatibility and error handling
- Adds comprehensive logging and validation

Key changes:
- Added _discover_framework_files() and _discover_command_files() methods
- Added shared _discover_files_in_directory() utility
- Replaced hardcoded arrays with dynamic discovery calls
- Includes filtering, sorting, and error handling
- Validates 9 framework files and 16 command files correctly
- Clean up documentation formatting

Resolves maintenance burden described in PR #133 while preserving
all existing functionality and security validation.

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
NomenAK
2025-07-15 11:16:58 +02:00
parent 5279cdd4e0
commit a0def375e1
4 changed files with 128 additions and 42 deletions

View File

@@ -1,11 +1,5 @@
# COMMANDS.md - SuperClaude Command Execution Framework
---
framework: "SuperClaude v3.0"
execution-engine: "Claude Code"
wave-compatibility: "Full"
---
Command execution framework for Claude Code SuperClaude integration.
## Command System Architecture

View File

@@ -531,8 +531,3 @@ orchestrator_config:
### Custom Routing Rules
Users can add custom routing patterns via YAML configuration files.
---

View File

@@ -22,25 +22,8 @@ class CommandsComponent(Component):
self.file_manager = FileManager()
self.settings_manager = SettingsManager(self.install_dir)
# Define command files to install
self.command_files = [
"analyze.md",
"build.md",
"implement.md",
"cleanup.md",
"design.md",
"document.md",
"estimate.md",
"explain.md",
"git.md",
"improve.md",
"index.md",
"load.md",
"spawn.md",
"task.md",
"test.md",
"troubleshoot.md"
]
# Dynamically discover command files to install
self.command_files = self._discover_command_files()
def get_metadata(self) -> Dict[str, str]:
"""Get component metadata"""
@@ -343,6 +326,68 @@ class CommandsComponent(Component):
return len(errors) == 0, errors
def _discover_command_files(self) -> List[str]:
"""
Dynamically discover command .md files in the Commands directory
Returns:
List of command filenames (e.g., ['analyze.md', 'build.md', ...])
"""
return self._discover_files_in_directory(
self._get_source_dir(),
extension='.md',
exclude_patterns=['README.md', 'CHANGELOG.md', 'LICENSE.md']
)
def _discover_files_in_directory(self, directory: Path, extension: str = '.md',
exclude_patterns: List[str] = None) -> List[str]:
"""
Shared utility for discovering files in a directory
Args:
directory: Directory to scan
extension: File extension to look for (default: '.md')
exclude_patterns: List of filename patterns to exclude
Returns:
List of filenames found in the directory
"""
if exclude_patterns is None:
exclude_patterns = []
try:
if not directory.exists():
self.logger.warning(f"Source directory not found: {directory}")
return []
if not directory.is_dir():
self.logger.warning(f"Source path is not a directory: {directory}")
return []
# Discover files with the specified extension
files = []
for file_path in directory.iterdir():
if (file_path.is_file() and
file_path.suffix.lower() == extension.lower() and
file_path.name not in exclude_patterns):
files.append(file_path.name)
# Sort for consistent ordering
files.sort()
self.logger.debug(f"Discovered {len(files)} {extension} files in {directory}")
if files:
self.logger.debug(f"Files found: {files}")
return files
except PermissionError:
self.logger.error(f"Permission denied accessing directory: {directory}")
return []
except Exception as e:
self.logger.error(f"Error discovering files in {directory}: {e}")
return []
def _get_source_dir(self) -> Path:
"""Get source directory for command files"""
# Assume we're in SuperClaude/setup/components/commands.py

View File

@@ -24,18 +24,8 @@ class CoreComponent(Component):
self.file_manager = FileManager()
self.settings_manager = SettingsManager(self.install_dir)
# Define framework files to install
self.framework_files = [
"CLAUDE.md",
"COMMANDS.md",
"FLAGS.md",
"PRINCIPLES.md",
"RULES.md",
"MCP.md",
"PERSONAS.md",
"ORCHESTRATOR.md",
"MODES.md"
]
# Dynamically discover framework files to install
self.framework_files = self._discover_framework_files()
def get_metadata(self) -> Dict[str, str]:
"""Get component metadata"""
@@ -323,6 +313,68 @@ class CoreComponent(Component):
return len(errors) == 0, errors
def _discover_framework_files(self) -> List[str]:
"""
Dynamically discover framework .md files in the Core directory
Returns:
List of framework filenames (e.g., ['CLAUDE.md', 'COMMANDS.md', ...])
"""
return self._discover_files_in_directory(
self._get_source_dir(),
extension='.md',
exclude_patterns=['README.md', 'CHANGELOG.md', 'LICENSE.md']
)
def _discover_files_in_directory(self, directory: Path, extension: str = '.md',
exclude_patterns: List[str] = None) -> List[str]:
"""
Shared utility for discovering files in a directory
Args:
directory: Directory to scan
extension: File extension to look for (default: '.md')
exclude_patterns: List of filename patterns to exclude
Returns:
List of filenames found in the directory
"""
if exclude_patterns is None:
exclude_patterns = []
try:
if not directory.exists():
self.logger.warning(f"Source directory not found: {directory}")
return []
if not directory.is_dir():
self.logger.warning(f"Source path is not a directory: {directory}")
return []
# Discover files with the specified extension
files = []
for file_path in directory.iterdir():
if (file_path.is_file() and
file_path.suffix.lower() == extension.lower() and
file_path.name not in exclude_patterns):
files.append(file_path.name)
# Sort for consistent ordering
files.sort()
self.logger.debug(f"Discovered {len(files)} {extension} files in {directory}")
if files:
self.logger.debug(f"Files found: {files}")
return files
except PermissionError:
self.logger.error(f"Permission denied accessing directory: {directory}")
return []
except Exception as e:
self.logger.error(f"Error discovering files in {directory}: {e}")
return []
def _get_source_dir(self) -> Path:
"""Get source directory for framework files"""
# Assume we're in SuperClaude/setup/components/core.py