From d0d7d5a9397c77d63eed68f6fc3f4a8fb2d12926 Mon Sep 17 00:00:00 2001 From: yusyus Date: Sat, 21 Mar 2026 21:39:22 +0300 Subject: [PATCH] chore: remove stale root-level test scripts and junk files Remove files that should never have been committed: - test_api.py, test_httpx_quick.sh, test_httpx_skill.sh (ad-hoc test scripts) - test_week2_features.py (one-off validation script) - test_results.log (log file) - =0.24.0 (accidental pip error output) - demo_conflicts.py (demo script) - ruff_errors.txt (stale lint output) - TESTING_GAP_REPORT.md (stale one-time report) Co-Authored-By: Claude Opus 4.6 (1M context) --- =0.24.0 | 18 -- TESTING_GAP_REPORT.md | 345 -------------------------------- demo_conflicts.py | 204 ------------------- ruff_errors.txt | 439 ----------------------------------------- test_api.py | 43 ---- test_httpx_quick.sh | 62 ------ test_httpx_skill.sh | 249 ----------------------- test_results.log | 65 ------ test_week2_features.py | 273 ------------------------- 9 files changed, 1698 deletions(-) delete mode 100644 =0.24.0 delete mode 100644 TESTING_GAP_REPORT.md delete mode 100644 demo_conflicts.py delete mode 100644 ruff_errors.txt delete mode 100644 test_api.py delete mode 100644 test_httpx_quick.sh delete mode 100755 test_httpx_skill.sh delete mode 100644 test_results.log delete mode 100755 test_week2_features.py diff --git a/=0.24.0 b/=0.24.0 deleted file mode 100644 index 83a1f95..0000000 --- a/=0.24.0 +++ /dev/null @@ -1,18 +0,0 @@ -error: externally-managed-environment - -Γ— This environment is externally managed -╰─> To install Python packages system-wide, try 'pacman -S - python-xyz', where xyz is the package you are trying to - install. - - If you wish to install a non-Arch-packaged Python package, - create a virtual environment using 'python -m venv path/to/venv'. - Then use path/to/venv/bin/python and path/to/venv/bin/pip. - - If you wish to install a non-Arch packaged Python application, - it may be easiest to use 'pipx install xyz', which will manage a - virtual environment for you. Make sure you have python-pipx - installed via pacman. - -note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages. -hint: See PEP 668 for the detailed specification. diff --git a/TESTING_GAP_REPORT.md b/TESTING_GAP_REPORT.md deleted file mode 100644 index 2277fb0..0000000 --- a/TESTING_GAP_REPORT.md +++ /dev/null @@ -1,345 +0,0 @@ -# Comprehensive Testing Gap Report - -**Project:** Skill Seekers v3.1.0 -**Date:** 2026-02-22 -**Total Test Files:** 113 -**Total Test Functions:** ~208+ (collected: 2173 tests) - ---- - -## Executive Summary - -### Overall Test Health: 🟑 GOOD with Gaps - -| Category | Status | Coverage | Key Gaps | -|----------|--------|----------|----------| -| CLI Arguments | βœ… Good | 85% | Some edge cases | -| Workflow System | βœ… Excellent | 90% | Inline stage parsing edge cases | -| Scrapers | 🟑 Moderate | 70% | Missing real HTTP/PDF tests | -| Enhancement | 🟑 Partial | 60% | Core logic not tested | -| MCP Tools | 🟑 Good | 75% | 8 tools not covered | -| Integration/E2E | 🟑 Moderate | 65% | Heavy mocking | -| Adaptors | βœ… Good | 80% | Good coverage per platform | - ---- - -## Detailed Findings by Category - -### 1. CLI Argument Tests βœ… GOOD - -**Files Reviewed:** -- `test_analyze_command.py` (269 lines, 26 tests) -- `test_unified.py` - TestUnifiedCLIArguments class (6 tests) -- `test_pdf_scraper.py` - TestPDFCLIArguments class (4 tests) -- `test_create_arguments.py` (399 lines) -- `test_create_integration_basic.py` (310 lines, 23 tests) - -**Strengths:** -- All new workflow flags are tested (`--enhance-workflow`, `--enhance-stage`, `--var`, `--workflow-dry-run`) -- Argument parsing thoroughly tested -- Default values verified -- Complex command combinations tested - -**Gaps:** -- `test_create_integration_basic.py`: 2 tests skipped (source auto-detection not fully tested) -- No tests for invalid argument combinations beyond basic parsing errors - ---- - -### 2. Workflow Tests βœ… EXCELLENT - -**Files Reviewed:** -- `test_workflow_runner.py` (445 lines, 30+ tests) -- `test_workflows_command.py` (571 lines, 40+ tests) -- `test_workflow_tools_mcp.py` (295 lines, 20+ tests) - -**Strengths:** -- Comprehensive workflow execution tests -- Variable substitution thoroughly tested -- Dry-run mode tested -- Workflow chaining tested -- All 6 workflow subcommands tested (list, show, copy, add, remove, validate) -- MCP workflow tools tested - -**Minor Gaps:** -- No tests for `_build_inline_engine` edge cases -- No tests for malformed stage specs (empty, invalid format) - ---- - -### 3. Scraper Tests 🟑 MODERATE with Significant Gaps - -**Files Reviewed:** -- `test_scraper_features.py` (524 lines) - Doc scraper features -- `test_codebase_scraper.py` (478 lines) - Codebase analysis -- `test_pdf_scraper.py` (558 lines) - PDF scraper -- `test_github_scraper.py` (1015 lines) - GitHub scraper -- `test_unified_analyzer.py` (428 lines) - Unified analyzer - -**Critical Gaps:** - -#### A. Missing Real External Resource Tests -| Resource | Test Type | Status | -|----------|-----------|--------| -| HTTP Requests (docs) | Mocked only | ❌ Gap | -| PDF Extraction | Mocked only | ❌ Gap | -| GitHub API | Mocked only | ❌ Gap (acceptable) | -| Local Files | Real tests | βœ… Good | - -#### B. Missing Core Function Tests -| Function | Location | Priority | -|----------|----------|----------| -| `UnifiedScraper.run()` | unified_scraper.py | πŸ”΄ High | -| `UnifiedScraper._scrape_documentation()` | unified_scraper.py | πŸ”΄ High | -| `UnifiedScraper._scrape_github()` | unified_scraper.py | πŸ”΄ High | -| `UnifiedScraper._scrape_pdf()` | unified_scraper.py | πŸ”΄ High | -| `UnifiedScraper._scrape_local()` | unified_scraper.py | 🟑 Medium | -| `DocToSkillConverter.scrape()` | doc_scraper.py | πŸ”΄ High | -| `PDFToSkillConverter.extract_pdf()` | pdf_scraper.py | πŸ”΄ High | - -#### C. PDF Scraper Limited Coverage -- No actual PDF parsing tests (only mocked) -- OCR functionality not tested -- Page range extraction not tested - ---- - -### 4. Enhancement Tests 🟑 PARTIAL - MAJOR GAPS - -**Files Reviewed:** -- `test_enhance_command.py` (367 lines, 25+ tests) -- `test_enhance_skill_local.py` (163 lines, 14 tests) - -**Critical Gap in `test_enhance_skill_local.py`:** - -| Function | Lines | Tested? | Priority | -|----------|-------|---------|----------| -| `summarize_reference()` | ~50 | ❌ No | πŸ”΄ High | -| `create_enhancement_prompt()` | ~200 | ❌ No | πŸ”΄ High | -| `run()` | ~100 | ❌ No | πŸ”΄ High | -| `_run_headless()` | ~130 | ❌ No | πŸ”΄ High | -| `_run_background()` | ~80 | ❌ No | 🟑 Medium | -| `_run_daemon()` | ~60 | ❌ No | 🟑 Medium | -| `write_status()` | ~30 | ❌ No | 🟑 Medium | -| `read_status()` | ~40 | ❌ No | 🟑 Medium | -| `detect_terminal_app()` | ~80 | ❌ No | 🟑 Medium | - -**Current Tests Only Cover:** -- Agent presets configuration -- Command building -- Agent name normalization -- Environment variable handling - -**Recommendation:** Add comprehensive tests for the core enhancement logic. - ---- - -### 5. MCP Tool Tests 🟑 GOOD with Coverage Gaps - -**Files Reviewed:** -- `test_mcp_fastmcp.py` (868 lines) -- `test_mcp_server.py` (715 lines) -- `test_mcp_vector_dbs.py` (259 lines) -- `test_real_world_fastmcp.py` (558 lines) - -**Coverage Analysis:** - -| Tool Category | Tools | Tested | Coverage | -|---------------|-------|--------|----------| -| Config Tools | 3 | 3 | βœ… 100% | -| Scraping Tools | 8 | 4 | 🟑 50% | -| Packaging Tools | 4 | 4 | βœ… 100% | -| Splitting Tools | 2 | 2 | βœ… 100% | -| Source Tools | 5 | 5 | βœ… 100% | -| Vector DB Tools | 4 | 4 | βœ… 100% | -| Workflow Tools | 5 | 0 | ❌ 0% | -| **Total** | **31** | **22** | **🟑 71%** | - -**Untested Tools:** -1. `detect_patterns` -2. `extract_test_examples` -3. `build_how_to_guides` -4. `extract_config_patterns` -5. `list_workflows` -6. `get_workflow` -7. `create_workflow` -8. `update_workflow` -9. `delete_workflow` - -**Note:** `test_mcp_server.py` tests legacy server, `test_mcp_fastmcp.py` tests modern server. - ---- - -### 6. Integration/E2E Tests 🟑 MODERATE - -**Files Reviewed:** -- `test_create_integration_basic.py` (310 lines) -- `test_e2e_three_stream_pipeline.py` (598 lines) -- `test_analyze_e2e.py` (344 lines) -- `test_install_skill_e2e.py` (533 lines) -- `test_c3_integration.py` (362 lines) - -**Issues Found:** - -1. **Skipped Tests:** - - `test_create_detects_web_url` - Source auto-detection incomplete - - `test_create_invalid_source_shows_error` - Error handling incomplete - - `test_cli_via_unified_command` - Asyncio issues - -2. **Heavy Mocking:** - - Most GitHub API tests use mocking - - No real HTTP tests for doc scraping - - Integration tests don't test actual integration - -3. **Limited Scope:** - - Only `--quick` preset tested (not `--comprehensive`) - - C3.x tests use mock data only - - Most E2E tests are unit tests with mocks - ---- - -### 7. Adaptor Tests βœ… GOOD - -**Files Reviewed:** -- `test_adaptors/test_adaptors_e2e.py` (893 lines) -- `test_adaptors/test_claude_adaptor.py` (314 lines) -- `test_adaptors/test_gemini_adaptor.py` (146 lines) -- `test_adaptors/test_openai_adaptor.py` (188 lines) -- Plus 8 more platform adaptors - -**Strengths:** -- Each adaptor has dedicated tests -- Package format testing -- Upload success/failure scenarios -- Platform-specific features tested - -**Minor Gaps:** -- Some adaptors only test 1-2 scenarios -- Error handling coverage varies by platform - ---- - -### 8. Config/Validation Tests βœ… GOOD - -**Files Reviewed:** -- `test_config_validation.py` (270 lines) -- `test_config_extractor.py` (629 lines) -- `test_config_fetcher.py` (340 lines) - -**Strengths:** -- Unified vs legacy format detection -- Field validation comprehensive -- Error message quality tested - ---- - -## Summary of Critical Testing Gaps - -### πŸ”΄ HIGH PRIORITY (Must Fix) - -1. **Enhancement Core Logic** - - File: `test_enhance_skill_local.py` - - Missing: 9 major functions - - Impact: Core feature untested - -2. **Unified Scraper Main Flow** - - File: New tests needed - - Missing: `_scrape_*()` methods, `run()` orchestration - - Impact: Multi-source scraping untested - -3. **Actual HTTP/PDF/GitHub Integration** - - Missing: Real external resource tests - - Impact: Only mock tests exist - -### 🟑 MEDIUM PRIORITY (Should Fix) - -4. **MCP Workflow Tools** - - Missing: 5 workflow tools (0% coverage) - - Impact: MCP workflow features untested - -5. **Skipped Integration Tests** - - 3 tests skipped - - Impact: Source auto-detection incomplete - -6. **PDF Real Extraction** - - Missing: Actual PDF parsing - - Impact: PDF feature quality unknown - -### 🟒 LOW PRIORITY (Nice to Have) - -7. **Additional Scraping Tools** - - Missing: 4 scraping tool tests - - Impact: Low (core tools covered) - -8. **Edge Case Coverage** - - Missing: Invalid argument combinations - - Impact: Low (happy path covered) - ---- - -## Recommendations - -### Immediate Actions (Next Sprint) - -1. **Add Enhancement Logic Tests** (~400 lines) - - Test `summarize_reference()` - - Test `create_enhancement_prompt()` - - Test `run()` method - - Test status read/write - -2. **Fix Skipped Tests** (~100 lines) - - Fix asyncio issues in `test_cli_via_unified_command` - - Complete source auto-detection tests - -3. **Add MCP Workflow Tool Tests** (~200 lines) - - Test all 5 workflow tools - -### Short Term (Next Month) - -4. **Add Unified Scraper Integration Tests** (~300 lines) - - Test main orchestration flow - - Test individual source scraping - -5. **Add Real PDF Tests** (~150 lines) - - Test with actual PDF files - - Test OCR if available - -### Long Term (Next Quarter) - -6. **HTTP Integration Tests** (~200 lines) - - Test with real websites (use test sites) - - Mock server approach - -7. **Complete E2E Pipeline** (~300 lines) - - Full workflow from scrape to upload - - Real GitHub repo (fork test repo) - ---- - -## Test Quality Metrics - -| Metric | Score | Notes | -|--------|-------|-------| -| Test Count | 🟒 Good | 2173+ tests | -| Coverage | 🟑 Moderate | ~75% estimated | -| Real Tests | 🟑 Moderate | Many mocked | -| Documentation | 🟒 Good | Most tests documented | -| Maintenance | 🟒 Good | Tests recently updated | - ---- - -## Conclusion - -The Skill Seekers test suite is **comprehensive in quantity** (2173+ tests) but has **quality gaps** in critical areas: - -1. **Core enhancement logic** is largely untested -2. **Multi-source scraping** orchestration lacks integration tests -3. **MCP workflow tools** have zero coverage -4. **Real external resource** testing is minimal - -**Priority:** Fix the πŸ”΄ HIGH priority gaps first, as they impact core functionality. - ---- - -*Report generated: 2026-02-22* -*Reviewer: Systematic test review with parallel subagent analysis* diff --git a/demo_conflicts.py b/demo_conflicts.py deleted file mode 100644 index 5ee5f72..0000000 --- a/demo_conflicts.py +++ /dev/null @@ -1,204 +0,0 @@ -#!/usr/bin/env python3 -""" -Demo: Conflict Detection and Reporting - -This demonstrates the unified scraper's ability to detect and report -conflicts between documentation and code implementation. -""" - -import json -import sys -from pathlib import Path - -# Add CLI to path -sys.path.insert(0, str(Path(__file__).parent / "cli")) - - -print("=" * 70) -print("UNIFIED SCRAPER - CONFLICT DETECTION DEMO") -print("=" * 70) -print() - -# Load test data -print("πŸ“‚ Loading test data...") -print(" - Documentation APIs from example docs") -print(" - Code APIs from example repository") -print() - -with open("cli/conflicts.json") as f: - conflicts_data = json.load(f) - -conflicts = conflicts_data["conflicts"] -summary = conflicts_data["summary"] - -print(f"βœ… Loaded {summary['total']} conflicts") -print() - -# Display summary -print("=" * 70) -print("CONFLICT SUMMARY") -print("=" * 70) -print() - -print(f"πŸ“Š **Total Conflicts**: {summary['total']}") -print() - -print("**By Type:**") -for conflict_type, count in summary["by_type"].items(): - if count > 0: - emoji = ( - "πŸ“–" - if conflict_type == "missing_in_docs" - else "πŸ’»" - if conflict_type == "missing_in_code" - else "⚠️" - ) - print(f" {emoji} {conflict_type}: {count}") -print() - -print("**By Severity:**") -for severity, count in summary["by_severity"].items(): - if count > 0: - emoji = "πŸ”΄" if severity == "high" else "🟑" if severity == "medium" else "🟒" - print(f" {emoji} {severity.upper()}: {count}") -print() - -# Display detailed conflicts -print("=" * 70) -print("DETAILED CONFLICT REPORTS") -print("=" * 70) -print() - -# Group by severity -high = [c for c in conflicts if c["severity"] == "high"] -medium = [c for c in conflicts if c["severity"] == "medium"] -low = [c for c in conflicts if c["severity"] == "low"] - -# Show high severity first -if high: - print("πŸ”΄ **HIGH SEVERITY CONFLICTS** (Requires immediate attention)") - print("-" * 70) - for conflict in high: - print() - print(f"**API**: `{conflict['api_name']}`") - print(f"**Type**: {conflict['type']}") - print(f"**Issue**: {conflict['difference']}") - print(f"**Suggestion**: {conflict['suggestion']}") - - if conflict["docs_info"]: - print("\n**Documented as**:") - print(f" Signature: {conflict['docs_info'].get('raw_signature', 'N/A')}") - - if conflict["code_info"]: - print("\n**Implemented as**:") - params = conflict["code_info"].get("parameters", []) - param_str = ", ".join( - f"{p['name']}: {p.get('type_hint', 'Any')}" for p in params if p["name"] != "self" - ) - print(f" Signature: {conflict['code_info']['name']}({param_str})") - print(f" Return type: {conflict['code_info'].get('return_type', 'None')}") - print( - f" Location: {conflict['code_info'].get('source', 'N/A')}:{conflict['code_info'].get('line', '?')}" - ) - print() - -# Show medium severity -if medium: - print("🟑 **MEDIUM SEVERITY CONFLICTS** (Review recommended)") - print("-" * 70) - for conflict in medium[:3]: # Show first 3 - print() - print(f"**API**: `{conflict['api_name']}`") - print(f"**Type**: {conflict['type']}") - print(f"**Issue**: {conflict['difference']}") - - if conflict["code_info"]: - print(f"**Location**: {conflict['code_info'].get('source', 'N/A')}") - - if len(medium) > 3: - print(f"\n ... and {len(medium) - 3} more medium severity conflicts") - print() - -# Example: How conflicts appear in final skill -print("=" * 70) -print("HOW CONFLICTS APPEAR IN SKILL.MD") -print("=" * 70) -print() - -example_conflict = high[0] if high else medium[0] if medium else conflicts[0] - -print("```markdown") -print("## πŸ”§ API Reference") -print() -print("### ⚠️ APIs with Conflicts") -print() -print(f"#### `{example_conflict['api_name']}`") -print() -print(f"⚠️ **Conflict**: {example_conflict['difference']}") -print() - -if example_conflict.get("docs_info"): - print("**Documentation says:**") - print("```") - print(example_conflict["docs_info"].get("raw_signature", "N/A")) - print("```") - print() - -if example_conflict.get("code_info"): - print("**Code implementation:**") - print("```python") - params = example_conflict["code_info"].get("parameters", []) - param_strs = [] - for p in params: - if p["name"] == "self": - continue - param_str = p["name"] - if p.get("type_hint"): - param_str += f": {p['type_hint']}" - if p.get("default"): - param_str += f" = {p['default']}" - param_strs.append(param_str) - - sig = f"def {example_conflict['code_info']['name']}({', '.join(param_strs)})" - if example_conflict["code_info"].get("return_type"): - sig += f" -> {example_conflict['code_info']['return_type']}" - - print(sig) - print("```") -print() - -print("*Source: both (conflict)*") -print("```") -print() - -# Key takeaways -print("=" * 70) -print("KEY TAKEAWAYS") -print("=" * 70) -print() - -print("βœ… **What the Unified Scraper Does:**") -print(" 1. Extracts APIs from both documentation and code") -print(" 2. Compares them to detect discrepancies") -print(" 3. Classifies conflicts by type and severity") -print(" 4. Provides actionable suggestions") -print(" 5. Shows both versions transparently in the skill") -print() - -print("⚠️ **Common Conflict Types:**") -print(" - **Missing in docs**: Undocumented features in code") -print(" - **Missing in code**: Documented but not implemented") -print(" - **Signature mismatch**: Different parameters/types") -print(" - **Description mismatch**: Different explanations") -print() - -print("🎯 **Value:**") -print(" - Identifies documentation gaps") -print(" - Catches outdated documentation") -print(" - Highlights implementation differences") -print(" - Creates single source of truth showing reality") -print() - -print("=" * 70) -print("END OF DEMO") -print("=" * 70) diff --git a/ruff_errors.txt b/ruff_errors.txt deleted file mode 100644 index cda7875..0000000 --- a/ruff_errors.txt +++ /dev/null @@ -1,439 +0,0 @@ -ARG002 Unused method argument: `config_type` - --> src/skill_seekers/cli/config_extractor.py:294:47 - | -292 | return None -293 | -294 | def _infer_purpose(self, file_path: Path, config_type: str) -> str: - | ^^^^^^^^^^^ -295 | """Infer configuration purpose from file path and name""" -296 | path_lower = str(file_path).lower() - | - -SIM102 Use a single `if` statement instead of nested `if` statements - --> src/skill_seekers/cli/config_extractor.py:469:17 - | -468 | for node in ast.walk(tree): -469 | / if isinstance(node, ast.Assign): -470 | | # Get variable name and skip private variables -471 | | if len(node.targets) == 1 and isinstance(node.targets[0], ast.Name) and not node.targets[0].id.startswith("_"): - | |___________________________________________________________________________________________________________________________________^ -472 | key = node.targets[0].id - | -help: Combine `if` statements using `and` - -ARG002 Unused method argument: `node` - --> src/skill_seekers/cli/config_extractor.py:585:41 - | -583 | return "" -584 | -585 | def _extract_python_docstring(self, node: ast.AST) -> str: - | ^^^^ -586 | """Extract docstring/comment for Python node""" -587 | # This is simplified - real implementation would need more context - | - -B904 Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling - --> src/skill_seekers/cli/config_validator.py:60:13 - | -58 | return json.load(f) -59 | except FileNotFoundError: -60 | raise ValueError(f"Config file not found: {self.config_path}") - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -61 | except json.JSONDecodeError as e: -62 | raise ValueError(f"Invalid JSON in config file: {e}") - | - -B904 Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling - --> src/skill_seekers/cli/config_validator.py:62:13 - | -60 | raise ValueError(f"Config file not found: {self.config_path}") -61 | except json.JSONDecodeError as e: -62 | raise ValueError(f"Invalid JSON in config file: {e}") - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -63 | -64 | def _detect_format(self) -> bool: - | - -SIM113 Use `enumerate()` for index variable `completed` in `for` loop - --> src/skill_seekers/cli/doc_scraper.py:1068:25 - | -1066 | logger.warning(" ⚠️ Worker exception: %s", e) -1067 | -1068 | completed += 1 - | ^^^^^^^^^^^^^^ -1069 | -1070 | with self.lock: - | - -B904 Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling - --> src/skill_seekers/cli/github_scraper.py:353:17 - | -351 | except GithubException as e: -352 | if e.status == 404: -353 | raise ValueError(f"Repository not found: {self.repo_name}") - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -354 | raise - | - -E402 Module level import not at top of file - --> src/skill_seekers/cli/llms_txt_downloader.py:5:1 - | -3 | """ABOUTME: Validates markdown content and handles timeouts with exponential backoff""" -4 | -5 | import time - | ^^^^^^^^^^^ -6 | -7 | import requests - | - -E402 Module level import not at top of file - --> src/skill_seekers/cli/llms_txt_downloader.py:7:1 - | -5 | import time -6 | -7 | import requests - | ^^^^^^^^^^^^^^^ - | - -E402 Module level import not at top of file - --> src/skill_seekers/cli/llms_txt_parser.py:5:1 - | -3 | """ABOUTME: Extracts titles, content, code samples, and headings from markdown""" -4 | -5 | import re - | ^^^^^^^^^ -6 | from urllib.parse import urljoin - | - -E402 Module level import not at top of file - --> src/skill_seekers/cli/llms_txt_parser.py:6:1 - | -5 | import re -6 | from urllib.parse import urljoin - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - -SIM102 Use a single `if` statement instead of nested `if` statements - --> src/skill_seekers/cli/pattern_recognizer.py:430:13 - | -428 | # Python: __init__ or __new__ -429 | # Java/C#: private constructor (detected by naming) -430 | / if method.name in ["__new__", "__init__", "constructor"]: -431 | | # Check if it has logic (not just pass) -432 | | if method.docstring or len(method.parameters) > 1: - | |__________________________________________________________________^ -433 | evidence.append(f"Controlled initialization: {method.name}") -434 | confidence += 0.3 - | -help: Combine `if` statements using `and` - -SIM102 Use a single `if` statement instead of nested `if` statements - --> src/skill_seekers/cli/pattern_recognizer.py:538:13 - | -536 | for method in class_sig.methods: -537 | method_lower = method.name.lower() -538 | / if any(name in method_lower for name in factory_method_names): -539 | | # Check if method returns something (has return type or is not void) -540 | | if method.return_type or "create" in method_lower: - | |__________________________________________________________________^ -541 | return PatternInstance( -542 | pattern_type=self.pattern_type, - | -help: Combine `if` statements using `and` - -SIM102 Use a single `if` statement instead of nested `if` statements - --> src/skill_seekers/cli/pattern_recognizer.py:916:9 - | -914 | # Check __init__ for composition (takes object parameter) -915 | init_method = next((m for m in class_sig.methods if m.name == "__init__"), None) -916 | / if init_method: -917 | | # Check if takes object parameter (not just self) -918 | | if len(init_method.parameters) > 1: # More than just 'self' - | |_______________________________________________^ -919 | param_names = [p.name for p in init_method.parameters if p.name != "self"] -920 | if any( - | -help: Combine `if` statements using `and` - -F821 Undefined name `l` - --> src/skill_seekers/cli/pdf_extractor_poc.py:302:28 - | -300 | 1 for line in code.split("\n") if line.strip().startswith(("#", "//", "/*", "*", "--")) -301 | ) -302 | total_lines = len([l for line in code.split("\n") if line.strip()]) - | ^ -303 | if total_lines > 0 and comment_lines / total_lines > 0.7: -304 | issues.append("Mostly comments") - | - -F821 Undefined name `l` - --> src/skill_seekers/cli/pdf_extractor_poc.py:330:18 - | -329 | # Factor 3: Number of lines -330 | lines = [l for line in code.split("\n") if line.strip()] - | ^ -331 | if 2 <= len(lines) <= 50: -332 | score += 1.0 - | - -B007 Loop control variable `keywords` not used within loop body - --> src/skill_seekers/cli/pdf_scraper.py:167:30 - | -165 | # Keyword-based categorization -166 | # Initialize categories -167 | for cat_key, keywords in self.categories.items(): - | ^^^^^^^^ -168 | categorized[cat_key] = {"title": cat_key.replace("_", " ").title(), "pages": []} - | -help: Rename unused `keywords` to `_keywords` - -SIM115 Use a context manager for opening files - --> src/skill_seekers/cli/pdf_scraper.py:434:26 - | -432 | f.write("**Generated by Skill Seeker** | PDF Documentation Scraper\n") -433 | -434 | line_count = len(open(filename, encoding="utf-8").read().split("\n")) - | ^^^^ -435 | print(f" Generated: {filename} ({line_count} lines)") - | - -E741 Ambiguous variable name: `l` - --> src/skill_seekers/cli/quality_checker.py:318:44 - | -316 | else: -317 | if links: -318 | internal_links = [l for t, l in links if not l.startswith("http")] - | ^ -319 | if internal_links: -320 | self.report.add_info( - | - -SIM102 Use a single `if` statement instead of nested `if` statements - --> src/skill_seekers/cli/test_example_extractor.py:364:13 - | -363 | for node in ast.walk(func_node): -364 | / if isinstance(node, ast.Assign) and isinstance(node.value, ast.Call): -365 | | # Check if meaningful instantiation -366 | | if self._is_meaningful_instantiation(node): - | |___________________________________________________________^ -367 | code = ast.unparse(node) - | -help: Combine `if` statements using `and` - -SIM102 Use a single `if` statement instead of nested `if` statements - --> src/skill_seekers/cli/test_example_extractor.py:412:13 - | -410 | for i, stmt in enumerate(statements): -411 | # Look for method calls -412 | / if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call): -413 | | # Check if next statement is an assertion -414 | | if i + 1 < len(statements): - | |___________________________________________^ -415 | next_stmt = statements[i + 1] -416 | if self._is_assertion(next_stmt): - | -help: Combine `if` statements using `and` - -SIM102 Use a single `if` statement instead of nested `if` statements - --> src/skill_seekers/cli/test_example_extractor.py:460:13 - | -459 | for node in ast.walk(func_node): -460 | / if isinstance(node, ast.Assign) and isinstance(node.value, ast.Dict): -461 | | # Must have 2+ keys and be meaningful -462 | | if len(node.value.keys) >= 2: - | |_____________________________________________^ -463 | code = ast.unparse(node) - | -help: Combine `if` statements using `and` - -SIM102 Use a single `if` statement instead of nested `if` statements - --> src/skill_seekers/cli/unified_skill_builder.py:1070:13 - | -1069 | # If no languages from C3.7, try to get from GitHub data -1070 | / if not languages: -1071 | | # github_data already available from method scope -1072 | | if github_data.get("languages"): - | |________________________________________________^ -1073 | # GitHub data has languages as list, convert to dict with count 1 -1074 | languages = dict.fromkeys(github_data["languages"], 1) - | -help: Combine `if` statements using `and` - -ARG001 Unused function argument: `request` - --> src/skill_seekers/mcp/server_fastmcp.py:1159:32 - | -1157 | from starlette.routing import Route -1158 | -1159 | async def health_check(request): - | ^^^^^^^ -1160 | """Health check endpoint.""" -1161 | return JSONResponse( - | - -ARG002 Unused method argument: `tmp_path` - --> tests/test_bootstrap_skill.py:54:56 - | -53 | @pytest.mark.slow -54 | def test_bootstrap_script_runs(self, project_root, tmp_path): - | ^^^^^^^^ -55 | """Test that bootstrap script runs successfully. - | - -B007 Loop control variable `message` not used within loop body - --> tests/test_install_agent.py:374:44 - | -372 | # With force - should succeed -373 | results_with_force = install_to_all_agents(self.skill_dir, force=True) -374 | for _agent_name, (success, message) in results_with_force.items(): - | ^^^^^^^ -375 | assert success is True - | -help: Rename unused `message` to `_message` - -SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements - --> tests/test_install_agent.py:418:9 - | -416 | def test_cli_requires_agent_flag(self): -417 | """Test that CLI fails without --agent flag.""" -418 | / with pytest.raises(SystemExit) as exc_info: -419 | | with patch("sys.argv", ["install_agent.py", str(self.skill_dir)]): - | |______________________________________________________________________________^ -420 | main() - | -help: Combine `with` statements - -SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements - --> tests/test_issue_219_e2e.py:278:9 - | -276 | self.skipTest("anthropic package not installed") -277 | -278 | / with patch.dict(os.environ, {"ANTHROPIC_API_KEY": "test-key"}): -279 | | with patch("skill_seekers.cli.enhance_skill.anthropic.Anthropic") as mock_anthropic: - | |________________________________________________________________________________________________^ -280 | enhancer = SkillEnhancer(self.skill_dir) - | -help: Combine `with` statements - -SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements - --> tests/test_llms_txt_downloader.py:33:5 - | -31 | downloader = LlmsTxtDownloader("https://example.com/llms.txt", max_retries=2) -32 | -33 | / with patch("requests.get", side_effect=requests.Timeout("Connection timeout")) as mock_get: -34 | | with patch("time.sleep") as mock_sleep: # Mock sleep to speed up test - | |_______________________________________________^ -35 | content = downloader.download() - | -help: Combine `with` statements - -SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements - --> tests/test_llms_txt_downloader.py:88:5 - | -86 | downloader = LlmsTxtDownloader("https://example.com/llms.txt", max_retries=3) -87 | -88 | / with patch("requests.get", side_effect=requests.Timeout("Connection timeout")): -89 | | with patch("time.sleep") as mock_sleep: - | |_______________________________________________^ -90 | content = downloader.download() - | -help: Combine `with` statements - -F821 Undefined name `l` - --> tests/test_markdown_parsing.py:100:21 - | - 98 | ) - 99 | # Should only include .md links -100 | md_links = [l for line in result["links"] if ".md" in l] - | ^ -101 | self.assertEqual(len(md_links), len(result["links"])) - | - -F821 Undefined name `l` - --> tests/test_markdown_parsing.py:100:63 - | - 98 | ) - 99 | # Should only include .md links -100 | md_links = [l for line in result["links"] if ".md" in l] - | ^ -101 | self.assertEqual(len(md_links), len(result["links"])) - | - -SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements - --> tests/test_skip_llms_txt.py:75:17 - | -73 | converter = DocToSkillConverter(config, dry_run=False) -74 | -75 | / with patch.object(converter, "_try_llms_txt", return_value=False) as mock_try: -76 | | with patch.object(converter, "scrape_page"): - | |________________________________________________________________^ -77 | with patch.object(converter, "save_summary"): -78 | converter.scrape_all() - | -help: Combine `with` statements - -SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements - --> tests/test_skip_llms_txt.py:98:17 - | - 96 | converter = DocToSkillConverter(config, dry_run=False) - 97 | - 98 | / with patch.object(converter, "_try_llms_txt") as mock_try: - 99 | | with patch.object(converter, "scrape_page"): - | |________________________________________________________________^ -100 | with patch.object(converter, "save_summary"): -101 | converter.scrape_all() - | -help: Combine `with` statements - -SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements - --> tests/test_skip_llms_txt.py:121:17 - | -119 | converter = DocToSkillConverter(config, dry_run=True) -120 | -121 | / with patch.object(converter, "_try_llms_txt") as mock_try: -122 | | with patch.object(converter, "save_summary"): - | |_________________________________________________________________^ -123 | converter.scrape_all() -124 | mock_try.assert_not_called() - | -help: Combine `with` statements - -SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements - --> tests/test_skip_llms_txt.py:148:17 - | -146 | converter = DocToSkillConverter(config, dry_run=False) -147 | -148 | / with patch.object(converter, "_try_llms_txt", return_value=False) as mock_try: -149 | | with patch.object(converter, "scrape_page_async", return_value=None): - | |_________________________________________________________________________________________^ -150 | with patch.object(converter, "save_summary"): -151 | converter.scrape_all() - | -help: Combine `with` statements - -SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements - --> tests/test_skip_llms_txt.py:172:17 - | -170 | converter = DocToSkillConverter(config, dry_run=False) -171 | -172 | / with patch.object(converter, "_try_llms_txt") as mock_try: -173 | | with patch.object(converter, "scrape_page_async", return_value=None): - | |_________________________________________________________________________________________^ -174 | with patch.object(converter, "save_summary"): -175 | converter.scrape_all() - | -help: Combine `with` statements - -SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements - --> tests/test_skip_llms_txt.py:304:17 - | -302 | return None -303 | -304 | / with patch.object(converter, "scrape_page", side_effect=mock_scrape): -305 | | with patch.object(converter, "save_summary"): - | |_________________________________________________________________^ -306 | converter.scrape_all() -307 | # Should have attempted to scrape the base URL - | -help: Combine `with` statements - -Found 38 errors. diff --git a/test_api.py b/test_api.py deleted file mode 100644 index c63223d..0000000 --- a/test_api.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python3 -"""Quick test of the config analyzer""" - -import sys - -sys.path.insert(0, "api") - -from pathlib import Path - -from api.config_analyzer import ConfigAnalyzer - -# Initialize analyzer -config_dir = Path("configs") -analyzer = ConfigAnalyzer(config_dir, base_url="https://api.skillseekersweb.com") - -# Test analyzing all configs -print("Testing config analyzer...") -print("-" * 60) - -configs = analyzer.analyze_all_configs() -print(f"\nβœ… Found {len(configs)} configs") - -# Show first 3 configs -print("\nπŸ“‹ Sample Configs:") -for config in configs[:3]: - print(f"\n Name: {config['name']}") - print(f" Type: {config['type']}") - print(f" Category: {config['category']}") - print(f" Tags: {', '.join(config['tags'])}") - print(f" Source: {config['primary_source'][:50]}...") - print(f" File Size: {config['file_size']} bytes") - -# Test category counts -print("\n\nπŸ“Š Categories:") -categories = {} -for config in configs: - cat = config["category"] - categories[cat] = categories.get(cat, 0) + 1 - -for cat, count in sorted(categories.items()): - print(f" {cat}: {count} configs") - -print("\nβœ… All tests passed!") diff --git a/test_httpx_quick.sh b/test_httpx_quick.sh deleted file mode 100644 index d02c08c..0000000 --- a/test_httpx_quick.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash -# Quick Test - HTTPX Skill (Documentation Only, No GitHub) -# For faster testing without full C3.x analysis - -set -e - -echo "πŸš€ Quick HTTPX Skill Test (Docs Only)" -echo "======================================" -echo "" - -# Simple config - docs only -CONFIG_FILE="configs/httpx_quick.json" - -# Create quick config (docs only) -cat > "$CONFIG_FILE" << 'EOF' -{ - "name": "httpx_quick", - "description": "HTTPX HTTP client for Python - Quick test version", - "base_url": "https://www.python-httpx.org/", - "selectors": { - "main_content": "article.md-content__inner", - "title": "h1", - "code_blocks": "pre code" - }, - "url_patterns": { - "include": ["/quickstart/", "/advanced/", "/api/"], - "exclude": ["/changelog/", "/contributing/"] - }, - "categories": { - "getting_started": ["quickstart", "install"], - "api": ["api", "reference"], - "advanced": ["async", "http2"] - }, - "rate_limit": 0.3, - "max_pages": 50 -} -EOF - -echo "βœ“ Created quick config (docs only, max 50 pages)" -echo "" - -# Run scraper -echo "πŸ” Scraping documentation..." -START_TIME=$(date +%s) - -skill-seekers scrape --config "$CONFIG_FILE" --output output/httpx_quick - -END_TIME=$(date +%s) -DURATION=$((END_TIME - START_TIME)) - -echo "" -echo "βœ… Complete in ${DURATION}s" -echo "" -echo "πŸ“Š Results:" -echo " Output: output/httpx_quick/" -echo " SKILL.md: $(wc -l < output/httpx_quick/SKILL.md) lines" -echo " References: $(find output/httpx_quick/references -name "*.md" 2>/dev/null | wc -l) files" -echo "" -echo "πŸ” Preview:" -head -30 output/httpx_quick/SKILL.md -echo "" -echo "πŸ“¦ Next: skill-seekers package output/httpx_quick/" diff --git a/test_httpx_skill.sh b/test_httpx_skill.sh deleted file mode 100755 index 3b11c10..0000000 --- a/test_httpx_skill.sh +++ /dev/null @@ -1,249 +0,0 @@ -#!/bin/bash -# Test Script for HTTPX Skill Generation -# Tests all C3.x features and experimental capabilities - -set -e # Exit on error - -echo "==================================" -echo "πŸ§ͺ HTTPX Skill Generation Test" -echo "==================================" -echo "" -echo "This script will test:" -echo " βœ“ Unified multi-source scraping (docs + GitHub)" -echo " βœ“ Three-stream GitHub analysis" -echo " βœ“ C3.x features (patterns, tests, guides, configs, architecture)" -echo " βœ“ AI enhancement (LOCAL mode)" -echo " βœ“ Quality metrics" -echo " βœ“ Packaging" -echo "" -read -p "Press Enter to start (or Ctrl+C to cancel)..." - -# Configuration -CONFIG_FILE="configs/httpx_comprehensive.json" -OUTPUT_DIR="output/httpx" -SKILL_NAME="httpx" - -# Step 1: Clean previous output -echo "" -echo "πŸ“ Step 1: Cleaning previous output..." -if [ -d "$OUTPUT_DIR" ]; then - rm -rf "$OUTPUT_DIR" - echo " βœ“ Cleaned $OUTPUT_DIR" -fi - -# Step 2: Validate config -echo "" -echo "πŸ” Step 2: Validating configuration..." -if [ ! -f "$CONFIG_FILE" ]; then - echo " βœ— Config file not found: $CONFIG_FILE" - exit 1 -fi -echo " βœ“ Config file found" - -# Show config summary -echo "" -echo "πŸ“‹ Config Summary:" -echo " Name: httpx" -echo " Sources: Documentation + GitHub (C3.x analysis)" -echo " Analysis Depth: c3x (full analysis)" -echo " Features: API ref, patterns, test examples, guides, architecture" -echo "" - -# Step 3: Run unified scraper -echo "πŸš€ Step 3: Running unified scraper (this will take 10-20 minutes)..." -echo " This includes:" -echo " - Documentation scraping" -echo " - GitHub repo cloning and analysis" -echo " - C3.1: Design pattern detection" -echo " - C3.2: Test example extraction" -echo " - C3.3: How-to guide generation" -echo " - C3.4: Configuration extraction" -echo " - C3.5: Architectural overview" -echo " - C3.6: AI enhancement preparation" -echo "" - -START_TIME=$(date +%s) - -# Run unified scraper with all features -python -m skill_seekers.cli.unified_scraper \ - --config "$CONFIG_FILE" \ - --output "$OUTPUT_DIR" \ - --verbose - -SCRAPE_END_TIME=$(date +%s) -SCRAPE_DURATION=$((SCRAPE_END_TIME - START_TIME)) - -echo "" -echo " βœ“ Scraping completed in ${SCRAPE_DURATION}s" - -# Step 4: Show analysis results -echo "" -echo "πŸ“Š Step 4: Analysis Results Summary" -echo "" - -# Check for C3.1 patterns -if [ -f "$OUTPUT_DIR/c3_1_patterns.json" ]; then - PATTERN_COUNT=$(python3 -c "import json; print(len(json.load(open('$OUTPUT_DIR/c3_1_patterns.json', 'r'))))") - echo " C3.1 Design Patterns: $PATTERN_COUNT patterns detected" -fi - -# Check for C3.2 test examples -if [ -f "$OUTPUT_DIR/c3_2_test_examples.json" ]; then - EXAMPLE_COUNT=$(python3 -c "import json; data=json.load(open('$OUTPUT_DIR/c3_2_test_examples.json', 'r')); print(len(data.get('examples', [])))") - echo " C3.2 Test Examples: $EXAMPLE_COUNT examples extracted" -fi - -# Check for C3.3 guides -GUIDE_COUNT=0 -if [ -d "$OUTPUT_DIR/guides" ]; then - GUIDE_COUNT=$(find "$OUTPUT_DIR/guides" -name "*.md" | wc -l) - echo " C3.3 How-To Guides: $GUIDE_COUNT guides generated" -fi - -# Check for C3.4 configs -if [ -f "$OUTPUT_DIR/c3_4_configs.json" ]; then - CONFIG_COUNT=$(python3 -c "import json; print(len(json.load(open('$OUTPUT_DIR/c3_4_configs.json', 'r'))))") - echo " C3.4 Configurations: $CONFIG_COUNT config patterns found" -fi - -# Check for C3.5 architecture -if [ -f "$OUTPUT_DIR/c3_5_architecture.md" ]; then - ARCH_LINES=$(wc -l < "$OUTPUT_DIR/c3_5_architecture.md") - echo " C3.5 Architecture: Overview generated ($ARCH_LINES lines)" -fi - -# Check for API reference -if [ -f "$OUTPUT_DIR/api_reference.md" ]; then - API_LINES=$(wc -l < "$OUTPUT_DIR/api_reference.md") - echo " API Reference: Generated ($API_LINES lines)" -fi - -# Check for dependency graph -if [ -f "$OUTPUT_DIR/dependency_graph.json" ]; then - echo " Dependency Graph: Generated" -fi - -# Check SKILL.md -if [ -f "$OUTPUT_DIR/SKILL.md" ]; then - SKILL_LINES=$(wc -l < "$OUTPUT_DIR/SKILL.md") - echo " SKILL.md: Generated ($SKILL_LINES lines)" -fi - -echo "" - -# Step 5: Quality assessment (pre-enhancement) -echo "πŸ“ˆ Step 5: Quality Assessment (Pre-Enhancement)" -echo "" - -# Count references -if [ -d "$OUTPUT_DIR/references" ]; then - REF_COUNT=$(find "$OUTPUT_DIR/references" -name "*.md" | wc -l) - TOTAL_REF_LINES=$(find "$OUTPUT_DIR/references" -name "*.md" -exec wc -l {} + | tail -1 | awk '{print $1}') - echo " Reference Files: $REF_COUNT files ($TOTAL_REF_LINES total lines)" -fi - -# Estimate quality score (basic heuristics) -QUALITY_SCORE=3 # Base score - -# Add points for features -[ -f "$OUTPUT_DIR/c3_1_patterns.json" ] && QUALITY_SCORE=$((QUALITY_SCORE + 1)) -[ -f "$OUTPUT_DIR/c3_2_test_examples.json" ] && QUALITY_SCORE=$((QUALITY_SCORE + 1)) -[ $GUIDE_COUNT -gt 0 ] && QUALITY_SCORE=$((QUALITY_SCORE + 1)) -[ -f "$OUTPUT_DIR/c3_4_configs.json" ] && QUALITY_SCORE=$((QUALITY_SCORE + 1)) -[ -f "$OUTPUT_DIR/c3_5_architecture.md" ] && QUALITY_SCORE=$((QUALITY_SCORE + 1)) -[ -f "$OUTPUT_DIR/api_reference.md" ] && QUALITY_SCORE=$((QUALITY_SCORE + 1)) - -echo " Estimated Quality (Pre-Enhancement): $QUALITY_SCORE/10" -echo "" - -# Step 6: AI Enhancement (LOCAL mode) -echo "πŸ€– Step 6: AI Enhancement (LOCAL mode)" -echo "" -echo " This will use Claude Code to enhance the skill" -echo " Expected improvement: $QUALITY_SCORE/10 β†’ 8-9/10" -echo "" - -read -p " Run AI enhancement? (y/n) [y]: " RUN_ENHANCEMENT -RUN_ENHANCEMENT=${RUN_ENHANCEMENT:-y} - -if [ "$RUN_ENHANCEMENT" = "y" ]; then - echo " Running LOCAL enhancement (force mode ON)..." - - python -m skill_seekers.cli.enhance_skill_local \ - "$OUTPUT_DIR" \ - --mode LOCAL \ - --force - - ENHANCE_END_TIME=$(date +%s) - ENHANCE_DURATION=$((ENHANCE_END_TIME - SCRAPE_END_TIME)) - - echo "" - echo " βœ“ Enhancement completed in ${ENHANCE_DURATION}s" - - # Post-enhancement quality - POST_QUALITY=9 # Assume significant improvement - echo " Estimated Quality (Post-Enhancement): $POST_QUALITY/10" -else - echo " Skipping enhancement" -fi - -echo "" - -# Step 7: Package skill -echo "πŸ“¦ Step 7: Packaging Skill" -echo "" - -python -m skill_seekers.cli.package_skill \ - "$OUTPUT_DIR" \ - --target claude \ - --output output/ - -PACKAGE_FILE="output/${SKILL_NAME}.zip" - -if [ -f "$PACKAGE_FILE" ]; then - PACKAGE_SIZE=$(du -h "$PACKAGE_FILE" | cut -f1) - echo " βœ“ Package created: $PACKAGE_FILE ($PACKAGE_SIZE)" -else - echo " βœ— Package creation failed" - exit 1 -fi - -echo "" - -# Step 8: Final Summary -END_TIME=$(date +%s) -TOTAL_DURATION=$((END_TIME - START_TIME)) -MINUTES=$((TOTAL_DURATION / 60)) -SECONDS=$((TOTAL_DURATION % 60)) - -echo "==================================" -echo "βœ… Test Complete!" -echo "==================================" -echo "" -echo "πŸ“Š Summary:" -echo " Total Time: ${MINUTES}m ${SECONDS}s" -echo " Output Directory: $OUTPUT_DIR" -echo " Package: $PACKAGE_FILE ($PACKAGE_SIZE)" -echo "" -echo "πŸ“ˆ Features Tested:" -echo " βœ“ Multi-source scraping (docs + GitHub)" -echo " βœ“ Three-stream analysis" -echo " βœ“ C3.1 Pattern detection" -echo " βœ“ C3.2 Test examples" -echo " βœ“ C3.3 How-to guides" -echo " βœ“ C3.4 Config extraction" -echo " βœ“ C3.5 Architecture overview" -if [ "$RUN_ENHANCEMENT" = "y" ]; then - echo " βœ“ AI enhancement (LOCAL)" -fi -echo " βœ“ Packaging" -echo "" -echo "πŸ” Next Steps:" -echo " 1. Review SKILL.md: cat $OUTPUT_DIR/SKILL.md | head -50" -echo " 2. Check patterns: cat $OUTPUT_DIR/c3_1_patterns.json | jq '.'" -echo " 3. Review guides: ls $OUTPUT_DIR/guides/" -echo " 4. Upload to Claude: skill-seekers upload $PACKAGE_FILE" -echo "" -echo "πŸ“ File Structure:" -tree -L 2 "$OUTPUT_DIR" | head -30 -echo "" diff --git a/test_results.log b/test_results.log deleted file mode 100644 index 9f11615..0000000 --- a/test_results.log +++ /dev/null @@ -1,65 +0,0 @@ -============================= test session starts ============================== -platform linux -- Python 3.14.2, pytest-8.4.2, pluggy-1.6.0 -- /usr/bin/python -cachedir: .pytest_cache -hypothesis profile 'default' -rootdir: /mnt/1ece809a-2821-4f10-aecb-fcdf34760c0b/Git/Skill_Seekers -configfile: pyproject.toml -plugins: anyio-4.12.1, hypothesis-6.150.0, cov-6.1.1, typeguard-4.4.4 -collecting ... collected 1940 items / 1 error - -==================================== ERRORS ==================================== -_________________ ERROR collecting tests/test_preset_system.py _________________ -ImportError while importing test module '/mnt/1ece809a-2821-4f10-aecb-fcdf34760c0b/Git/Skill_Seekers/tests/test_preset_system.py'. -Hint: make sure your test modules/packages have valid Python names. -Traceback: -/usr/lib/python3.14/site-packages/_pytest/python.py:498: in importtestmodule - mod = import_path( -/usr/lib/python3.14/site-packages/_pytest/pathlib.py:587: in import_path - importlib.import_module(module_name) -/usr/lib/python3.14/importlib/__init__.py:88: in import_module - return _bootstrap._gcd_import(name[level:], package, level) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:1398: in _gcd_import - ??? -:1371: in _find_and_load - ??? -:1342: in _find_and_load_unlocked - ??? -:938: in _load_unlocked - ??? -/usr/lib/python3.14/site-packages/_pytest/assertion/rewrite.py:186: in exec_module - exec(co, module.__dict__) -tests/test_preset_system.py:9: in - from skill_seekers.cli.presets import PresetManager, PRESETS, AnalysisPreset -E ImportError: cannot import name 'PresetManager' from 'skill_seekers.cli.presets' (/mnt/1ece809a-2821-4f10-aecb-fcdf34760c0b/Git/Skill_Seekers/src/skill_seekers/cli/presets/__init__.py) -=============================== warnings summary =============================== -../../../../usr/lib/python3.14/site-packages/_pytest/config/__init__.py:1474 - /usr/lib/python3.14/site-packages/_pytest/config/__init__.py:1474: PytestConfigWarning: Unknown config option: asyncio_default_fixture_loop_scope - - self._warn_or_fail_if_strict(f"Unknown config option: {key}\n") - -../../../../usr/lib/python3.14/site-packages/_pytest/config/__init__.py:1474 - /usr/lib/python3.14/site-packages/_pytest/config/__init__.py:1474: PytestConfigWarning: Unknown config option: asyncio_mode - - self._warn_or_fail_if_strict(f"Unknown config option: {key}\n") - -tests/test_mcp_fastmcp.py:21 - /mnt/1ece809a-2821-4f10-aecb-fcdf34760c0b/Git/Skill_Seekers/tests/test_mcp_fastmcp.py:21: DeprecationWarning: The legacy server.py is deprecated and will be removed in v3.0.0. Please update your MCP configuration to use 'server_fastmcp' instead: - OLD: python -m skill_seekers.mcp.server - NEW: python -m skill_seekers.mcp.server_fastmcp - The new server provides the same functionality with improved performance. - from mcp.server import FastMCP - -src/skill_seekers/cli/test_example_extractor.py:50 - /mnt/1ece809a-2821-4f10-aecb-fcdf34760c0b/Git/Skill_Seekers/src/skill_seekers/cli/test_example_extractor.py:50: PytestCollectionWarning: cannot collect test class 'TestExample' because it has a __init__ constructor (from: tests/test_test_example_extractor.py) - @dataclass - -src/skill_seekers/cli/test_example_extractor.py:920 - /mnt/1ece809a-2821-4f10-aecb-fcdf34760c0b/Git/Skill_Seekers/src/skill_seekers/cli/test_example_extractor.py:920: PytestCollectionWarning: cannot collect test class 'TestExampleExtractor' because it has a __init__ constructor (from: tests/test_test_example_extractor.py) - class TestExampleExtractor: - --- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html -=========================== short test summary info ============================ -ERROR tests/test_preset_system.py -!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!! -========================= 5 warnings, 1 error in 1.11s ========================= diff --git a/test_week2_features.py b/test_week2_features.py deleted file mode 100755 index c42a98b..0000000 --- a/test_week2_features.py +++ /dev/null @@ -1,273 +0,0 @@ -#!/usr/bin/env python3 -""" -Quick validation script for Week 2 features. -Run this to verify all new capabilities are working. -""" - -import sys -from pathlib import Path -import tempfile -import shutil - -# Add src to path for testing -sys.path.insert(0, str(Path(__file__).parent / "src")) - -def test_vector_databases(): - """Test all 4 vector database adaptors.""" - from skill_seekers.cli.adaptors import get_adaptor - import json - - print("πŸ“¦ Testing vector database adaptors...") - - # Create minimal test data - with tempfile.TemporaryDirectory() as tmpdir: - skill_dir = Path(tmpdir) / 'test_skill' - skill_dir.mkdir() - (skill_dir / 'SKILL.md').write_text('# Test\n\nContent.') - - targets = ['weaviate', 'chroma', 'faiss', 'qdrant'] - for target in targets: - try: - adaptor = get_adaptor(target) - package_path = adaptor.package(skill_dir, Path(tmpdir)) - assert package_path.exists(), f"{target} package not created" - print(f" βœ… {target.capitalize()}") - except Exception as e: - print(f" ❌ {target.capitalize()}: {e}") - return False - - return True - - -def test_streaming(): - """Test streaming ingestion.""" - from skill_seekers.cli.streaming_ingest import StreamingIngester - - print("πŸ“ˆ Testing streaming ingestion...") - - try: - large_content = "Test content. " * 500 - ingester = StreamingIngester(chunk_size=1000, chunk_overlap=100) - - chunks = list(ingester.chunk_document( - large_content, - {'source': 'test'} - )) - - assert len(chunks) > 5, "Expected multiple chunks" - assert all(len(chunk[0]) <= 1100 for chunk in chunks), "Chunk too large" - - print(f" βœ… Chunked {len(large_content)} chars into {len(chunks)} chunks") - return True - except Exception as e: - print(f" ❌ Streaming test failed: {e}") - return False - - -def test_incremental(): - """Test incremental updates.""" - from skill_seekers.cli.incremental_updater import IncrementalUpdater - import time - - print("⚑ Testing incremental updates...") - - try: - with tempfile.TemporaryDirectory() as tmpdir: - skill_dir = Path(tmpdir) / 'test_skill' - skill_dir.mkdir() - - # Create references directory - refs_dir = skill_dir / 'references' - refs_dir.mkdir() - - # Create initial version - (skill_dir / 'SKILL.md').write_text('# V1\n\nInitial content.') - (refs_dir / 'guide.md').write_text('# Guide\n\nInitial guide.') - - updater = IncrementalUpdater(skill_dir) - updater.current_versions = updater._scan_documents() # Scan before saving - updater.save_current_versions() - - # Small delay to ensure different timestamps - time.sleep(0.01) - - # Make changes - (skill_dir / 'SKILL.md').write_text('# V2\n\nUpdated content.') - (refs_dir / 'new_ref.md').write_text('# New Reference\n\nNew documentation.') - - # Detect changes (loads previous versions internally) - updater2 = IncrementalUpdater(skill_dir) - changes = updater2.detect_changes() - - # Verify we have changes - assert changes.has_changes, "No changes detected" - assert len(changes.added) > 0, f"New file not detected" - assert len(changes.modified) > 0, f"Modified file not detected" - - print(f" βœ… Detected {len(changes.added)} added, {len(changes.modified)} modified") - return True - except Exception as e: - print(f" ❌ Incremental test failed: {e}") - return False - - -def test_multilang(): - """Test multi-language support.""" - from skill_seekers.cli.multilang_support import ( - LanguageDetector, - MultiLanguageManager - ) - - print("🌍 Testing multi-language support...") - - try: - detector = LanguageDetector() - - # Test language detection - en_text = "This is an English document about programming." - es_text = "Este es un documento en espaΓ±ol sobre programaciΓ³n." - - en_detected = detector.detect(en_text) - es_detected = detector.detect(es_text) - - assert en_detected.code == 'en', f"Expected 'en', got '{en_detected.code}'" - assert es_detected.code == 'es', f"Expected 'es', got '{es_detected.code}'" - - # Test filename detection - assert detector.detect_from_filename('README.en.md') == 'en' - assert detector.detect_from_filename('guide.es.md') == 'es' - - # Test manager - manager = MultiLanguageManager() - manager.add_document('doc.md', en_text, {}) - manager.add_document('doc.es.md', es_text, {}) - - languages = manager.get_languages() - assert 'en' in languages and 'es' in languages - - print(f" βœ… Detected {len(languages)} languages") - return True - except Exception as e: - print(f" ❌ Multi-language test failed: {e}") - return False - - -def test_embeddings(): - """Test embedding pipeline.""" - from skill_seekers.cli.embedding_pipeline import ( - EmbeddingPipeline, - EmbeddingConfig - ) - - print("πŸ’° Testing embedding pipeline...") - - try: - with tempfile.TemporaryDirectory() as tmpdir: - config = EmbeddingConfig( - provider='local', - model='test-model', - dimension=64, - batch_size=10, - cache_dir=Path(tmpdir) - ) - - pipeline = EmbeddingPipeline(config) - - # Test generation (first run) - texts = ['doc1', 'doc2', 'doc3'] - result1 = pipeline.generate_batch(texts, show_progress=False) - - assert len(result1.embeddings) == 3, "Expected 3 embeddings" - assert len(result1.embeddings[0]) == 64, "Wrong dimension" - assert result1.generated_count == 3, "Should generate all on first run" - - # Test caching (second run with same texts) - result2 = pipeline.generate_batch(texts, show_progress=False) - - assert result2.cached_count == 3, "Caching not working" - assert result2.generated_count == 0, "Should not generate on second run" - - print(f" βœ… First run: {result1.generated_count} generated") - print(f" βœ… Second run: {result2.cached_count} cached (100% cache hit)") - return True - except Exception as e: - print(f" ❌ Embedding test failed: {e}") - return False - - -def test_quality(): - """Test quality metrics.""" - from skill_seekers.cli.quality_metrics import QualityAnalyzer - - print("πŸ“Š Testing quality metrics...") - - try: - with tempfile.TemporaryDirectory() as tmpdir: - skill_dir = Path(tmpdir) / 'test_skill' - skill_dir.mkdir() - - # Create test skill - (skill_dir / 'SKILL.md').write_text('# Test Skill\n\nContent.') - - refs_dir = skill_dir / 'references' - refs_dir.mkdir() - (refs_dir / 'guide.md').write_text('# Guide\n\nGuide content.') - - # Analyze quality - analyzer = QualityAnalyzer(skill_dir) - report = analyzer.generate_report() - - assert report.overall_score.total_score > 0, "Score is 0" - assert report.overall_score.grade in ['A+', 'A', 'A-', 'B+', 'B', 'B-', 'C+', 'C', 'C-', 'D', 'F'] - assert len(report.metrics) == 4, "Expected 4 metrics" - - print(f" βœ… Grade: {report.overall_score.grade} ({report.overall_score.total_score:.1f}/100)") - return True - except Exception as e: - print(f" ❌ Quality test failed: {e}") - return False - - -def main(): - """Run all tests.""" - print("=" * 70) - print("πŸ§ͺ Week 2 Feature Validation") - print("=" * 70) - print() - - tests = [ - ("Vector Databases", test_vector_databases), - ("Streaming Ingestion", test_streaming), - ("Incremental Updates", test_incremental), - ("Multi-Language", test_multilang), - ("Embedding Pipeline", test_embeddings), - ("Quality Metrics", test_quality), - ] - - passed = 0 - failed = 0 - - for name, test_func in tests: - try: - if test_func(): - passed += 1 - else: - failed += 1 - except Exception as e: - print(f" ❌ Unexpected error: {e}") - failed += 1 - print() - - print("=" * 70) - print(f"πŸ“Š Results: {passed}/{len(tests)} passed") - - if failed == 0: - print("πŸŽ‰ All Week 2 features validated successfully!") - return 0 - else: - print(f"⚠️ {failed} test(s) failed") - return 1 - - -if __name__ == '__main__': - sys.exit(main())