From 71b7304a9acde7193318cdd271231f8c2d10a5f7 Mon Sep 17 00:00:00 2001 From: yusyus Date: Sun, 8 Feb 2026 02:27:22 +0300 Subject: [PATCH] refactor: Remove legacy config format support (v2.11.0) BREAKING CHANGE: Legacy config format no longer supported Changes: - ConfigValidator now only accepts unified format with 'sources' array - Removed _validate_legacy() method - Removed convert_legacy_to_unified() and all conversion helpers - Simplified get_sources_by_type() and has_multiple_sources() - Updated __main__ to remove legacy format checks - Converted claude-code.json to unified format - Deleted blender.json (duplicate of blender-unified.json) - Clear error message when legacy format detected Error message shows: - Legacy format was removed in v2.11.0 - Example of old vs new format - Migration guide link Code reduction: -86 lines All 65 tests passing Co-Authored-By: Claude Sonnet 4.5 --- FINAL_STATUS.md | 7 + configs/blender.json | 198 ------------------ configs/claude-code.json | 242 ++++++++++++++-------- src/skill_seekers/cli/config_validator.py | 166 ++++----------- 4 files changed, 209 insertions(+), 404 deletions(-) delete mode 100644 configs/blender.json diff --git a/FINAL_STATUS.md b/FINAL_STATUS.md index 967ed40..8cd9fbd 100644 --- a/FINAL_STATUS.md +++ b/FINAL_STATUS.md @@ -22,6 +22,12 @@ - ✅ All 65 tests passing - ✅ Runtime behavior verified +### Legacy Config Format Removal +- ✅ All configs converted to unified format +- ✅ Legacy validation methods removed +- ✅ Clear error messages for old configs +- ✅ Simplified codebase (removed 86 lines) + --- ## 📊 Key Metrics @@ -181,6 +187,7 @@ Status: ✅ ALL PASSED ## 📦 Commits ``` +PENDING refactor: Remove legacy config format support (v2.11.0) c8195bc fix: QA audit - Fix 5 critical bugs in preset system 19fa91e docs: Add comprehensive summary for all 4 phases (v2.11.0) 67c3ab9 feat(cli): Implement formal preset system for analyze command (Phase 4) diff --git a/configs/blender.json b/configs/blender.json deleted file mode 100644 index 3863d1d..0000000 --- a/configs/blender.json +++ /dev/null @@ -1,198 +0,0 @@ -{ - "name": "blender", - "description": "Blender 3D creation suite for modeling, animation, rendering, compositing, video editing, and game development. Use for 3D modeling, sculpting, animation, shading, rendering, simulation, video editing, and Python scripting.", - "base_url": "https://docs.blender.org/manual/en/latest/", - "selectors": { - "main_content": "article[role='main']", - "title": "h1", - "code_blocks": "pre code, div.highlight pre" - }, - "url_patterns": { - "include": [ - "/getting_started/", - "/interface/", - "/editors/", - "/modeling/", - "/sculpt_paint/", - "/grease_pencil/", - "/animation/", - "/physics/", - "/render/", - "/scene_layout/", - "/compositing/", - "/video_editing/", - "/files/", - "/addons/", - "/advanced/", - "/troubleshooting/" - ], - "exclude": [ - "/_static/", - "/_images/", - "/search.html", - "/genindex.html", - "/glossary.html", - "/index.html$" - ] - }, - "categories": { - "getting_started": [ - "getting_started", - "installing", - "configuration", - "introduction", - "quickstart", - "about" - ], - "interface": [ - "interface", - "window_system", - "keymap", - "controls", - "operators", - "tools", - "ui", - "navigation" - ], - "modeling": [ - "modeling", - "mesh", - "curve", - "surface", - "metaball", - "text", - "volume", - "geometry_nodes", - "modifiers", - "mesh_tools", - "edit_mode" - ], - "sculpting": [ - "sculpt", - "sculpting", - "brush", - "texture_paint", - "vertex_paint", - "weight_paint", - "dynamic_paint" - ], - "grease_pencil": [ - "grease_pencil", - "2d_animation", - "drawing", - "stroke" - ], - "animation": [ - "animation", - "keyframe", - "rigging", - "armature", - "constraints", - "drivers", - "shape_keys", - "motion_paths", - "timeline", - "dope_sheet", - "graph_editor", - "nla" - ], - "physics": [ - "physics", - "simulation", - "particles", - "hair", - "fluid", - "cloth", - "soft_body", - "rigid_body", - "dynamic_paint", - "force_fields" - ], - "shading": [ - "shading", - "shader", - "material", - "texture", - "nodes", - "shader_nodes", - "lighting", - "world" - ], - "rendering": [ - "render", - "eevee", - "cycles", - "workbench", - "freestyle", - "camera", - "output", - "color_management", - "optimization" - ], - "compositing": [ - "compositing", - "compositor", - "nodes", - "color_correction", - "filters", - "matte" - ], - "video_editing": [ - "video_editing", - "vse", - "sequencer", - "strips", - "effects", - "preview" - ], - "scene_layout": [ - "scene", - "object", - "collection", - "properties", - "outliner", - "view_layers" - ], - "files_assets": [ - "files", - "import", - "export", - "asset", - "library", - "data_blocks", - "linking", - "append" - ], - "addons": [ - "addon", - "plugin", - "extension", - "import_export" - ], - "scripting": [ - "scripting", - "python", - "api", - "bpy", - "operator", - "custom", - "automation" - ], - "advanced": [ - "advanced", - "command_line", - "app_templates", - "extensions", - "limits" - ], - "troubleshooting": [ - "troubleshooting", - "crash", - "recover", - "gpu", - "graphics" - ] - }, - "rate_limit": 0.5, - "max_pages": 1500 -} diff --git a/configs/claude-code.json b/configs/claude-code.json index 8a15604..e042aa3 100644 --- a/configs/claude-code.json +++ b/configs/claude-code.json @@ -1,84 +1,164 @@ { - "_migration_note": "TODO: Migrate to external skill-seekers-configs repo. Kept temporarily to preserve PR #244 work.", "name": "claude-code", "description": "Claude Code CLI and development environment. Use for Claude Code features, tools, workflows, MCP integration, plugins, hooks, configuration, deployment, and AI-assisted development.", - "base_url": "https://code.claude.com/docs/en/", - "start_urls": [ - "https://code.claude.com/docs/en/overview", - "https://code.claude.com/docs/en/quickstart", - "https://code.claude.com/docs/en/common-workflows", - "https://code.claude.com/docs/en/claude-code-on-the-web", - "https://code.claude.com/docs/en/desktop", - "https://code.claude.com/docs/en/chrome", - "https://code.claude.com/docs/en/vs-code", - "https://code.claude.com/docs/en/jetbrains", - "https://code.claude.com/docs/en/github-actions", - "https://code.claude.com/docs/en/gitlab-ci-cd", - "https://code.claude.com/docs/en/slack", - "https://code.claude.com/docs/en/sub-agents", - "https://code.claude.com/docs/en/plugins", - "https://code.claude.com/docs/en/discover-plugins", - "https://code.claude.com/docs/en/skills", - "https://code.claude.com/docs/en/output-styles", - "https://code.claude.com/docs/en/hooks-guide", - "https://code.claude.com/docs/en/headless", - "https://code.claude.com/docs/en/mcp", - "https://code.claude.com/docs/en/third-party-integrations", - "https://code.claude.com/docs/en/amazon-bedrock", - "https://code.claude.com/docs/en/google-vertex-ai", - "https://code.claude.com/docs/en/microsoft-foundry", - "https://code.claude.com/docs/en/network-config", - "https://code.claude.com/docs/en/llm-gateway", - "https://code.claude.com/docs/en/devcontainer", - "https://code.claude.com/docs/en/sandboxing", - "https://code.claude.com/docs/en/setup", - "https://code.claude.com/docs/en/iam", - "https://code.claude.com/docs/en/security", - "https://code.claude.com/docs/en/data-usage", - "https://code.claude.com/docs/en/monitoring-usage", - "https://code.claude.com/docs/en/costs", - "https://code.claude.com/docs/en/analytics", - "https://code.claude.com/docs/en/plugin-marketplaces", - "https://code.claude.com/docs/en/settings", - "https://code.claude.com/docs/en/terminal-config", - "https://code.claude.com/docs/en/model-config", - "https://code.claude.com/docs/en/memory", - "https://code.claude.com/docs/en/statusline", - "https://code.claude.com/docs/en/cli-reference", - "https://code.claude.com/docs/en/interactive-mode", - "https://code.claude.com/docs/en/slash-commands", - "https://code.claude.com/docs/en/checkpointing", - "https://code.claude.com/docs/en/hooks", - "https://code.claude.com/docs/en/plugins-reference", - "https://code.claude.com/docs/en/troubleshooting", - "https://code.claude.com/docs/en/legal-and-compliance" - ], - "selectors": { - "main_content": "#content-area, #content-container, article, main", - "title": "h1", - "code_blocks": "pre code" - }, - "url_patterns": { - "include": ["/docs/en/"], - "exclude": [ - "/docs/fr/", "/docs/de/", "/docs/it/", "/docs/ja/", "/docs/es/", - "/docs/ko/", "/docs/zh-CN/", "/docs/zh-TW/", "/docs/ru/", - "/docs/id/", "/docs/pt/", "/changelog", "github.com" - ] - }, - "categories": { - "getting_started": ["overview", "quickstart", "common-workflows"], - "ide_integrations": ["vs-code", "jetbrains", "desktop", "chrome", "claude-code-on-the-web", "slack"], - "ci_cd": ["github-actions", "gitlab-ci-cd"], - "building": ["sub-agents", "subagent", "plugins", "discover-plugins", "skills", "output-styles", "hooks-guide", "headless", "programmatic"], - "mcp": ["mcp", "model-context-protocol"], - "deployment": ["third-party-integrations", "amazon-bedrock", "google-vertex-ai", "microsoft-foundry", "network-config", "llm-gateway", "devcontainer", "sandboxing"], - "administration": ["setup", "iam", "security", "data-usage", "monitoring-usage", "costs", "analytics", "plugin-marketplaces"], - "configuration": ["settings", "terminal-config", "model-config", "memory", "statusline"], - "reference": ["cli-reference", "interactive-mode", "slash-commands", "checkpointing", "hooks", "plugins-reference"], - "troubleshooting": ["troubleshooting"], - "legal": ["legal-and-compliance"] - }, - "rate_limit": 0.5, - "max_pages": 250 -} + "merge_mode": "rule-based", + "sources": [ + { + "type": "documentation", + "_migration_note": "TODO: Migrate to external skill-seekers-configs repo. Kept temporarily to preserve PR #244 work.", + "base_url": "https://code.claude.com/docs/en/", + "start_urls": [ + "https://code.claude.com/docs/en/overview", + "https://code.claude.com/docs/en/quickstart", + "https://code.claude.com/docs/en/common-workflows", + "https://code.claude.com/docs/en/claude-code-on-the-web", + "https://code.claude.com/docs/en/desktop", + "https://code.claude.com/docs/en/chrome", + "https://code.claude.com/docs/en/vs-code", + "https://code.claude.com/docs/en/jetbrains", + "https://code.claude.com/docs/en/github-actions", + "https://code.claude.com/docs/en/gitlab-ci-cd", + "https://code.claude.com/docs/en/slack", + "https://code.claude.com/docs/en/sub-agents", + "https://code.claude.com/docs/en/plugins", + "https://code.claude.com/docs/en/discover-plugins", + "https://code.claude.com/docs/en/skills", + "https://code.claude.com/docs/en/output-styles", + "https://code.claude.com/docs/en/hooks-guide", + "https://code.claude.com/docs/en/headless", + "https://code.claude.com/docs/en/mcp", + "https://code.claude.com/docs/en/third-party-integrations", + "https://code.claude.com/docs/en/amazon-bedrock", + "https://code.claude.com/docs/en/google-vertex-ai", + "https://code.claude.com/docs/en/microsoft-foundry", + "https://code.claude.com/docs/en/network-config", + "https://code.claude.com/docs/en/llm-gateway", + "https://code.claude.com/docs/en/devcontainer", + "https://code.claude.com/docs/en/sandboxing", + "https://code.claude.com/docs/en/setup", + "https://code.claude.com/docs/en/iam", + "https://code.claude.com/docs/en/security", + "https://code.claude.com/docs/en/data-usage", + "https://code.claude.com/docs/en/monitoring-usage", + "https://code.claude.com/docs/en/costs", + "https://code.claude.com/docs/en/analytics", + "https://code.claude.com/docs/en/plugin-marketplaces", + "https://code.claude.com/docs/en/settings", + "https://code.claude.com/docs/en/terminal-config", + "https://code.claude.com/docs/en/model-config", + "https://code.claude.com/docs/en/memory", + "https://code.claude.com/docs/en/statusline", + "https://code.claude.com/docs/en/cli-reference", + "https://code.claude.com/docs/en/interactive-mode", + "https://code.claude.com/docs/en/slash-commands", + "https://code.claude.com/docs/en/checkpointing", + "https://code.claude.com/docs/en/hooks", + "https://code.claude.com/docs/en/plugins-reference", + "https://code.claude.com/docs/en/troubleshooting", + "https://code.claude.com/docs/en/legal-and-compliance" + ], + "selectors": { + "main_content": "#content-area, #content-container, article, main", + "title": "h1", + "code_blocks": "pre code" + }, + "url_patterns": { + "include": [ + "/docs/en/" + ], + "exclude": [ + "/docs/fr/", + "/docs/de/", + "/docs/it/", + "/docs/ja/", + "/docs/es/", + "/docs/ko/", + "/docs/zh-CN/", + "/docs/zh-TW/", + "/docs/ru/", + "/docs/id/", + "/docs/pt/", + "/changelog", + "github.com" + ] + }, + "categories": { + "getting_started": [ + "overview", + "quickstart", + "common-workflows" + ], + "ide_integrations": [ + "vs-code", + "jetbrains", + "desktop", + "chrome", + "claude-code-on-the-web", + "slack" + ], + "ci_cd": [ + "github-actions", + "gitlab-ci-cd" + ], + "building": [ + "sub-agents", + "subagent", + "plugins", + "discover-plugins", + "skills", + "output-styles", + "hooks-guide", + "headless", + "programmatic" + ], + "mcp": [ + "mcp", + "model-context-protocol" + ], + "deployment": [ + "third-party-integrations", + "amazon-bedrock", + "google-vertex-ai", + "microsoft-foundry", + "network-config", + "llm-gateway", + "devcontainer", + "sandboxing" + ], + "administration": [ + "setup", + "iam", + "security", + "data-usage", + "monitoring-usage", + "costs", + "analytics", + "plugin-marketplaces" + ], + "configuration": [ + "settings", + "terminal-config", + "model-config", + "memory", + "statusline" + ], + "reference": [ + "cli-reference", + "interactive-mode", + "slash-commands", + "checkpointing", + "hooks", + "plugins-reference" + ], + "troubleshooting": [ + "troubleshooting" + ], + "legal": [ + "legal-and-compliance" + ] + }, + "rate_limit": 0.5, + "max_pages": 250 + } + ] +} \ No newline at end of file diff --git a/src/skill_seekers/cli/config_validator.py b/src/skill_seekers/cli/config_validator.py index b156ad9..c3329a3 100644 --- a/src/skill_seekers/cli/config_validator.py +++ b/src/skill_seekers/cli/config_validator.py @@ -6,8 +6,10 @@ Validates unified config format that supports multiple sources: - documentation (website scraping) - github (repository scraping) - pdf (PDF document scraping) +- local (local codebase analysis) -Also provides backward compatibility detection for legacy configs. +Legacy config format support removed in v2.11.0. +All configs must use unified format with 'sources' array. """ import json @@ -21,7 +23,7 @@ logger = logging.getLogger(__name__) class ConfigValidator: """ - Validates unified config format and provides backward compatibility. + Validates unified config format (legacy support removed in v2.11.0). """ # Valid source types @@ -49,7 +51,7 @@ class ConfigValidator: else: self.config_path = config_or_path self.config = self._load_config() - self.is_unified = self._detect_format() + self.is_unified = True # Always unified format now def _load_config(self) -> dict[str, Any]: """Load JSON config file.""" @@ -61,19 +63,9 @@ class ConfigValidator: except json.JSONDecodeError as e: raise ValueError(f"Invalid JSON in config file: {e}") from e - def _detect_format(self) -> bool: - """ - Detect if config is unified format or legacy. - - Returns: - True if unified format (has 'sources' array) - False if legacy format - """ - return "sources" in self.config and isinstance(self.config["sources"], list) - def validate(self) -> bool: """ - Validate config based on detected format. + Validate unified config format. Returns: True if valid @@ -81,10 +73,32 @@ class ConfigValidator: Raises: ValueError if invalid with detailed error message """ - if self.is_unified: - return self._validate_unified() - else: - return self._validate_legacy() + # Check if legacy format (no sources array) + if "sources" not in self.config: + raise ValueError( + "\n❌ LEGACY CONFIG FORMAT DETECTED\n\n" + " Legacy config format was removed in v2.11.0.\n" + " All configs must now use unified format with 'sources' array.\n\n" + " OLD FORMAT (removed):\n" + " {\n" + ' "name": "example",\n' + ' "base_url": "https://..."\n' + " }\n\n" + " NEW FORMAT (required):\n" + " {\n" + ' "name": "example",\n' + ' "description": "...",\n' + ' "sources": [\n' + " {\n" + ' "type": "documentation",\n' + ' "base_url": "https://..."\n' + " }\n" + " ]\n" + " }\n\n" + " 📖 See: https://skillseekersweb.com/docs/config-format\n" + ) + + return self._validate_unified() def _validate_unified(self) -> bool: """Validate unified config format.""" @@ -239,117 +253,21 @@ class ConfigValidator: f"Source {index} (local): Invalid ai_mode '{ai_mode}'. Must be one of {self.VALID_AI_MODES}" ) - def _validate_legacy(self) -> bool: - """ - Validate legacy config format (backward compatibility). - - Legacy configs are the old format used by doc_scraper, github_scraper, pdf_scraper. - """ - logger.info("Detected legacy config format (backward compatible)") - - # Detect which legacy type based on fields - if "base_url" in self.config: - logger.info("Legacy type: documentation") - elif "repo" in self.config: - logger.info("Legacy type: github") - elif "pdf" in self.config or "path" in self.config: - logger.info("Legacy type: pdf") - else: - raise ValueError("Cannot detect legacy config type (missing base_url, repo, or pdf)") - - return True - - def convert_legacy_to_unified(self) -> dict[str, Any]: - """ - Convert legacy config to unified format. - - Returns: - Unified config dict - """ - if self.is_unified: - logger.info("Config already in unified format") - return self.config - - logger.info("Converting legacy config to unified format...") - - # Detect legacy type and convert - if "base_url" in self.config: - return self._convert_legacy_documentation() - elif "repo" in self.config: - return self._convert_legacy_github() - elif "pdf" in self.config or "path" in self.config: - return self._convert_legacy_pdf() - else: - raise ValueError("Cannot convert: unknown legacy format") - - def _convert_legacy_documentation(self) -> dict[str, Any]: - """Convert legacy documentation config to unified.""" - unified = { - "name": self.config.get("name", "unnamed"), - "description": self.config.get("description", "Documentation skill"), - "merge_mode": "rule-based", - "sources": [ - { - "type": "documentation", - **{k: v for k, v in self.config.items() if k not in ["name", "description"]}, - } - ], - } - return unified - - def _convert_legacy_github(self) -> dict[str, Any]: - """Convert legacy GitHub config to unified.""" - unified = { - "name": self.config.get("name", "unnamed"), - "description": self.config.get("description", "GitHub repository skill"), - "merge_mode": "rule-based", - "sources": [ - { - "type": "github", - **{k: v for k, v in self.config.items() if k not in ["name", "description"]}, - } - ], - } - return unified - - def _convert_legacy_pdf(self) -> dict[str, Any]: - """Convert legacy PDF config to unified.""" - unified = { - "name": self.config.get("name", "unnamed"), - "description": self.config.get("description", "PDF document skill"), - "merge_mode": "rule-based", - "sources": [ - { - "type": "pdf", - **{k: v for k, v in self.config.items() if k not in ["name", "description"]}, - } - ], - } - return unified - def get_sources_by_type(self, source_type: str) -> list[dict[str, Any]]: """ Get all sources of a specific type. Args: - source_type: 'documentation', 'github', or 'pdf' + source_type: 'documentation', 'github', 'pdf', or 'local' Returns: List of sources matching the type """ - if not self.is_unified: - # For legacy, convert and get sources - unified = self.convert_legacy_to_unified() - sources = unified["sources"] - else: - sources = self.config["sources"] - + sources = self.config["sources"] return [s for s in sources if s.get("type") == source_type] def has_multiple_sources(self) -> bool: """Check if config has multiple sources (requires merging).""" - if not self.is_unified: - return False return len(self.config["sources"]) > 1 def needs_api_merge(self) -> bool: @@ -406,18 +324,16 @@ if __name__ == "__main__": validator = validate_config(config_file) print("\n✅ Config valid!") - print(f" Format: {'Unified' if validator.is_unified else 'Legacy'}") print(f" Name: {validator.config.get('name')}") - if validator.is_unified: - sources = validator.config["sources"] - print(f" Sources: {len(sources)}") - for i, source in enumerate(sources): - print(f" {i + 1}. {source['type']}") + sources = validator.config["sources"] + print(f" Sources: {len(sources)}") + for i, source in enumerate(sources): + print(f" {i + 1}. {source['type']}") - if validator.needs_api_merge(): - merge_mode = validator.config.get("merge_mode", "rule-based") - print(f" ⚠️ API merge required (mode: {merge_mode})") + if validator.needs_api_merge(): + merge_mode = validator.config.get("merge_mode", "rule-based") + print(f" ⚠️ API merge required (mode: {merge_mode})") except ValueError as e: print(f"\n❌ Config invalid: {e}")