@rfxlamia/skillkit 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/agents/creative-copywriter.md +212 -0
- package/agents/agents/dario-amodei.md +135 -0
- package/agents/agents/doc-simplifier.md +63 -0
- package/agents/agents/kotlin-pro.md +433 -0
- package/agents/agents/red-team.md +136 -0
- package/agents/agents/sam-altman.md +121 -0
- package/agents/agents/seo-manager.md +184 -0
- package/package.json +1 -1
- package/skills/skillkit-help/SKILL.md +81 -0
- package/skills/skillkit-help/knowledge/application/09-case-studies.md +257 -0
- package/skills/skillkit-help/knowledge/application/12-testing-and-validation.md +276 -0
- package/skills/skillkit-help/knowledge/foundation/01-why-skills-exist.md +246 -0
- package/skills/skillkit-help/knowledge/foundation/02-skills-vs-subagents-comparison.md +312 -0
- package/skills/skillkit-help/knowledge/foundation/03-skills-vs-subagents-decision-tree.md +346 -0
- package/skills/skillkit-help/knowledge/foundation/06-platform-constraints.md +237 -0
- package/skills/skillkit-help/knowledge/foundation/08-when-not-to-use-skills.md +270 -0
- package/skills/skillkit-help/template/SKILL.md +52 -0
- package/skills/skills/adversarial-review/SKILL.md +219 -0
- package/skills/skills/baby-education/SKILL.md +260 -0
- package/skills/skills/baby-education/references/advanced-techniques.md +323 -0
- package/skills/skills/baby-education/references/transformations.md +345 -0
- package/skills/skills/been-there-done-that/SKILL.md +455 -0
- package/skills/skills/been-there-done-that/references/analysis-patterns.md +162 -0
- package/skills/skills/been-there-done-that/references/git-commands.md +132 -0
- package/skills/skills/been-there-done-that/references/tree-insertion-logic.md +145 -0
- package/skills/skills/coolhunter/SKILL.md +270 -0
- package/skills/skills/coolhunter/assets/elicitation-methods.csv +51 -0
- package/skills/skills/coolhunter/knowledge/elicitation-methods.md +312 -0
- package/skills/skills/coolhunter/references/workflow-execution.md +238 -0
- package/skills/skills/coolhunter/workflow-plan-coolhunter.md +232 -0
- package/skills/skills/creative-copywriting/SKILL.md +324 -0
- package/skills/skills/creative-copywriting/databases/README.md +60 -0
- package/skills/skills/creative-copywriting/databases/carousel-structures.csv +16 -0
- package/skills/skills/creative-copywriting/databases/emotional-arcs.csv +11 -0
- package/skills/skills/creative-copywriting/databases/hook-formulas.csv +51 -0
- package/skills/skills/creative-copywriting/databases/power-words.csv +201 -0
- package/skills/skills/creative-copywriting/databases/psychological-triggers.csv +21 -0
- package/skills/skills/creative-copywriting/databases/read-more-patterns.csv +26 -0
- package/skills/skills/creative-copywriting/databases/swipe-triggers.csv +31 -0
- package/skills/skills/creative-copywriting/references/carousel-psychology.md +223 -0
- package/skills/skills/creative-copywriting/references/hook-anatomy.md +169 -0
- package/skills/skills/creative-copywriting/references/power-word-science.md +134 -0
- package/skills/skills/creative-copywriting/references/storytelling-frameworks.md +157 -0
- package/skills/skills/diverse-content-gen/SKILL.md +201 -0
- package/skills/skills/diverse-content-gen/references/advanced-techniques.md +320 -0
- package/skills/skills/diverse-content-gen/references/research-findings.md +379 -0
- package/skills/skills/diverse-content-gen/references/task-workflows.md +241 -0
- package/skills/skills/diverse-content-gen/references/tool-integration.md +419 -0
- package/skills/skills/diverse-content-gen/references/troubleshooting.md +426 -0
- package/skills/skills/diverse-content-gen/references/vs-core-technique.md +240 -0
- package/skills/skills/framework-critical-thinking/SKILL.md +220 -0
- package/skills/skills/framework-critical-thinking/references/bias_detector.md +375 -0
- package/skills/skills/framework-critical-thinking/references/fallback_handler.md +239 -0
- package/skills/skills/framework-critical-thinking/references/memory_curator.md +161 -0
- package/skills/skills/framework-critical-thinking/references/metacognitive_monitor.md +297 -0
- package/skills/skills/framework-critical-thinking/references/producer_critic_orchestrator.md +333 -0
- package/skills/skills/framework-critical-thinking/references/reasoning_router.md +235 -0
- package/skills/skills/framework-critical-thinking/references/reasoning_validator.md +97 -0
- package/skills/skills/framework-critical-thinking/references/reflection_trigger.md +78 -0
- package/skills/skills/framework-critical-thinking/references/self_verification.md +388 -0
- package/skills/skills/framework-critical-thinking/references/uncertainty_quantifier.md +207 -0
- package/skills/skills/framework-initiative/SKILL.md +231 -0
- package/skills/skills/framework-initiative/references/examples.md +150 -0
- package/skills/skills/framework-initiative/references/impact-analysis.md +157 -0
- package/skills/skills/framework-initiative/references/intent-patterns.md +145 -0
- package/skills/skills/framework-initiative/references/star-framework.md +165 -0
- package/skills/skills/humanize-docs/SKILL.md +203 -0
- package/skills/skills/humanize-docs/references/advanced-techniques.md +13 -0
- package/skills/skills/humanize-docs/references/core-transformations.md +368 -0
- package/skills/skills/humanize-docs/references/detection-patterns.md +400 -0
- package/skills/skills/humanize-docs/references/examples-gallery.md +374 -0
- package/skills/skills/imagine/SKILL.md +190 -0
- package/skills/skills/imagine/references/artstyle-corporate-memphis.md +625 -0
- package/skills/skills/imagine/references/artstyle-crewdson-hyperrealism.md +295 -0
- package/skills/skills/imagine/references/artstyle-iphone-social-media.md +426 -0
- package/skills/skills/imagine/references/artstyle-sciencesaru.md +276 -0
- package/skills/skills/pre-deploy-checklist/README.md +26 -0
- package/skills/skills/pre-deploy-checklist/SKILL.md +153 -0
- package/skills/skills/pre-deploy-checklist/references/checklist-categories.md +174 -0
- package/skills/skills/pre-deploy-checklist/references/domain-prompts.md +216 -0
- package/skills/skills/prompt-engineering/SKILL.md +209 -0
- package/skills/skills/prompt-engineering/references/advanced-combinations.md +444 -0
- package/skills/skills/prompt-engineering/references/chain-of-thought.md +140 -0
- package/skills/skills/prompt-engineering/references/decision_matrix.md +220 -0
- package/skills/skills/prompt-engineering/references/few-shot.md +346 -0
- package/skills/skills/prompt-engineering/references/json-format.md +270 -0
- package/skills/skills/prompt-engineering/references/natural-language.md +420 -0
- package/skills/skills/prompt-engineering/references/pitfalls.md +365 -0
- package/skills/skills/prompt-engineering/references/prompt-chaining.md +498 -0
- package/skills/skills/prompt-engineering/references/react.md +108 -0
- package/skills/skills/prompt-engineering/references/self-consistency.md +322 -0
- package/skills/skills/prompt-engineering/references/tree-of-thoughts.md +386 -0
- package/skills/skills/prompt-engineering/references/xml-format.md +220 -0
- package/skills/skills/prompt-engineering/references/yaml-format.md +488 -0
- package/skills/skills/prompt-engineering/references/zero-shot.md +74 -0
- package/skills/skills/quick-spec/SKILL.md +280 -0
- package/skills/skills/quick-spec/assets/tech-spec-template.md +74 -0
- package/skills/skills/quick-spec/references/step-01-understand.md +189 -0
- package/skills/skills/quick-spec/references/step-02-investigate.md +144 -0
- package/skills/skills/quick-spec/references/step-03-generate.md +128 -0
- package/skills/skills/quick-spec/references/step-04-review.md +173 -0
- package/skills/skills/quick-spec/tests/__pycache__/test_skill.cpython-314-pytest-9.0.2.pyc +0 -0
- package/skills/skills/quick-spec/tests/test_scenarios.md +83 -0
- package/skills/skills/quick-spec/tests/test_skill.py +136 -0
- package/skills/skills/readme-expert/SKILL.md +538 -0
- package/skills/skills/readme-expert/knowledge/INDEX.md +192 -0
- package/skills/skills/readme-expert/knowledge/application/quality-standards.md +470 -0
- package/skills/skills/readme-expert/knowledge/application/script-executor.md +604 -0
- package/skills/skills/readme-expert/knowledge/application/template-library.md +822 -0
- package/skills/skills/readme-expert/knowledge/foundation/codebase-scanner.md +361 -0
- package/skills/skills/readme-expert/knowledge/foundation/validation-checklist.md +481 -0
- package/skills/skills/red-teaming/SKILL.md +321 -0
- package/skills/skills/red-teaming/references/ai-llm-redteam.md +517 -0
- package/skills/skills/red-teaming/references/attack-techniques.md +410 -0
- package/skills/skills/red-teaming/references/cybersecurity-redteam.md +383 -0
- package/skills/skills/red-teaming/references/tools-frameworks.md +446 -0
- package/skills/skills/releasing/.skillkit-mode +1 -0
- package/skills/skills/releasing/SKILL.md +225 -0
- package/skills/skills/releasing/references/version-detection.md +108 -0
- package/skills/skills/screenwriter/SKILL.md +273 -0
- package/skills/skills/screenwriter/references/advanced-techniques.md +216 -0
- package/skills/skills/screenwriter/references/pipeline-integration.md +266 -0
- package/skills/skills/skillkit/.claude/settings.local.json +7 -0
- package/skills/skills/skillkit/.claude-plugin/plugin.json +27 -0
- package/skills/skills/skillkit/CHANGELOG.md +484 -0
- package/skills/skills/skillkit/SKILL.md +511 -0
- package/skills/skills/skillkit/commands/skillkit.md +6 -0
- package/skills/skills/skillkit/commands/validate-plan.md +6 -0
- package/skills/skills/skillkit/commands/verify.md +6 -0
- package/skills/skills/skillkit/knowledge/INDEX.md +352 -0
- package/skills/skills/skillkit/knowledge/application/09-case-studies.md +257 -0
- package/skills/skills/skillkit/knowledge/application/10-technical-architecture.md +324 -0
- package/skills/skills/skillkit/knowledge/application/11-adoption-strategy.md +267 -0
- package/skills/skills/skillkit/knowledge/application/12-testing-and-validation.md +276 -0
- package/skills/skills/skillkit/knowledge/application/13-competitive-landscape.md +198 -0
- package/skills/skills/skillkit/knowledge/foundation/01-why-skills-exist.md +246 -0
- package/skills/skills/skillkit/knowledge/foundation/02-skills-vs-subagents-comparison.md +312 -0
- package/skills/skills/skillkit/knowledge/foundation/03-skills-vs-subagents-decision-tree.md +346 -0
- package/skills/skills/skillkit/knowledge/foundation/04-hybrid-patterns.md +308 -0
- package/skills/skills/skillkit/knowledge/foundation/05-token-economics.md +275 -0
- package/skills/skills/skillkit/knowledge/foundation/06-platform-constraints.md +237 -0
- package/skills/skills/skillkit/knowledge/foundation/07-security-concerns.md +322 -0
- package/skills/skills/skillkit/knowledge/foundation/08-when-not-to-use-skills.md +270 -0
- package/skills/skills/skillkit/knowledge/plugin-guide.md +614 -0
- package/skills/skills/skillkit/knowledge/tools/14-validation-tools-guide.md +150 -0
- package/skills/skills/skillkit/knowledge/tools/15-cost-tools-guide.md +157 -0
- package/skills/skills/skillkit/knowledge/tools/16-security-tools-guide.md +122 -0
- package/skills/skills/skillkit/knowledge/tools/17-pattern-tools-guide.md +161 -0
- package/skills/skills/skillkit/knowledge/tools/18-decision-helper-guide.md +243 -0
- package/skills/skills/skillkit/knowledge/tools/19-test-generator-guide.md +275 -0
- package/skills/skills/skillkit/knowledge/tools/20-split-skill-guide.md +149 -0
- package/skills/skills/skillkit/knowledge/tools/21-quality-scorer-guide.md +226 -0
- package/skills/skills/skillkit/knowledge/tools/22-migration-helper-guide.md +356 -0
- package/skills/skills/skillkit/knowledge/tools/23-subagent-creation-guide.md +448 -0
- package/skills/skills/skillkit/knowledge/tools/24-behavioral-testing-guide.md +122 -0
- package/skills/skills/skillkit/references/proposal-generation.md +982 -0
- package/skills/skills/skillkit/references/rationalization-catalog.md +75 -0
- package/skills/skills/skillkit/references/research-methodology.md +661 -0
- package/skills/skills/skillkit/references/section-2-full-creation-workflow.md +452 -0
- package/skills/skills/skillkit/references/section-3-validation-workflow-existing-skill.md +63 -0
- package/skills/skills/skillkit/references/section-4-decision-workflow-skills-vs-subagents.md +64 -0
- package/skills/skills/skillkit/references/section-5-migration-workflow-doc-to-skill.md +58 -0
- package/skills/skills/skillkit/references/section-6-subagent-creation-workflow.md +499 -0
- package/skills/skills/skillkit/references/section-7-knowledge-reference-map.md +72 -0
- package/skills/skills/skillkit/scripts/__pycache__/decision_helper.cpython-314.pyc +0 -0
- package/skills/skills/skillkit/scripts/__pycache__/quick_validate.cpython-312.pyc +0 -0
- package/skills/skills/skillkit/scripts/__pycache__/quick_validate.cpython-314.pyc +0 -0
- package/skills/skills/skillkit/scripts/__pycache__/test_generator.cpython-314-pytest-9.0.2.pyc +0 -0
- package/skills/skills/skillkit/scripts/decision_helper.py +799 -0
- package/skills/skills/skillkit/scripts/init_skill.py +400 -0
- package/skills/skills/skillkit/scripts/init_subagent.py +231 -0
- package/skills/skills/skillkit/scripts/migration_helper.py +669 -0
- package/skills/skills/skillkit/scripts/package_skill.py +211 -0
- package/skills/skills/skillkit/scripts/pattern_detector.py +381 -0
- package/skills/skills/skillkit/scripts/pattern_detector_new.py +382 -0
- package/skills/skills/skillkit/scripts/pressure_tester.py +157 -0
- package/skills/skills/skillkit/scripts/quality_scorer.py +999 -0
- package/skills/skills/skillkit/scripts/quick_validate.py +100 -0
- package/skills/skills/skillkit/scripts/security_scanner.py +474 -0
- package/skills/skills/skillkit/scripts/split_skill.py +540 -0
- package/skills/skills/skillkit/scripts/test_generator.py +695 -0
- package/skills/skills/skillkit/scripts/token_estimator.py +493 -0
- package/skills/skills/skillkit/scripts/utils/__init__.py +49 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/__init__.cpython-312.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/budget_tracker.cpython-312.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/budget_tracker.cpython-314.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/output_formatter.cpython-312.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/output_formatter.cpython-314.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/reference_validator.cpython-312.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/reference_validator.cpython-314.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/budget_tracker.py +388 -0
- package/skills/skills/skillkit/scripts/utils/output_formatter.py +263 -0
- package/skills/skills/skillkit/scripts/utils/reference_validator.py +401 -0
- package/skills/skills/skillkit/scripts/validate_skill.py +594 -0
- package/skills/skills/skillkit/tests/test_behavioral.py +39 -0
- package/skills/skills/skillkit/tests/test_scenarios.md +83 -0
- package/skills/skills/skillkit/tests/test_skill.py +136 -0
- package/skills/skills/skillkit-help/SKILL.md +81 -0
- package/skills/skills/skillkit-help/knowledge/application/09-case-studies.md +257 -0
- package/skills/skills/skillkit-help/knowledge/application/12-testing-and-validation.md +276 -0
- package/skills/skills/skillkit-help/knowledge/foundation/01-why-skills-exist.md +246 -0
- package/skills/skills/skillkit-help/knowledge/foundation/02-skills-vs-subagents-comparison.md +312 -0
- package/skills/skills/skillkit-help/knowledge/foundation/03-skills-vs-subagents-decision-tree.md +346 -0
- package/skills/skills/skillkit-help/knowledge/foundation/06-platform-constraints.md +237 -0
- package/skills/skills/skillkit-help/knowledge/foundation/08-when-not-to-use-skills.md +270 -0
- package/skills/skills/skillkit-help/template/SKILL.md +52 -0
- package/skills/skills/social-media-seo/SKILL.md +278 -0
- package/skills/skills/social-media-seo/databases/caption-styles.csv +31 -0
- package/skills/skills/social-media-seo/databases/engagement-tactics.csv +16 -0
- package/skills/skills/social-media-seo/databases/hashtag-strategies.csv +21 -0
- package/skills/skills/social-media-seo/databases/hook-formulas.csv +26 -0
- package/skills/skills/social-media-seo/databases/keyword-clusters.csv +11 -0
- package/skills/skills/social-media-seo/databases/thread-structures.csv +26 -0
- package/skills/skills/social-media-seo/databases/viral-patterns.csv +21 -0
- package/skills/skills/social-media-seo/references/analytics-guide.md +321 -0
- package/skills/skills/social-media-seo/references/instagram-seo.md +235 -0
- package/skills/skills/social-media-seo/references/threads-seo.md +305 -0
- package/skills/skills/social-media-seo/references/x-twitter-seo.md +337 -0
- package/skills/skills/social-media-seo/scripts/query_database.py +191 -0
- package/skills/skills/storyteller/SKILL.md +241 -0
- package/skills/skills/storyteller/references/transformation-methodology.md +293 -0
- package/skills/skills/storyteller/references/visual-vocabulary.md +177 -0
- package/skills/skills/thread-pro/SKILL.md +162 -0
- package/skills/skills/thread-pro/anti-ai-patterns.md +120 -0
- package/skills/skills/thread-pro/hook-formulas.md +138 -0
- package/skills/skills/thread-pro/references/anti-ai-patterns.md +120 -0
- package/skills/skills/thread-pro/references/hook-formulas.md +138 -0
- package/skills/skills/thread-pro/references/thread-structures.md +240 -0
- package/skills/skills/thread-pro/references/voice-injection.md +130 -0
- package/skills/skills/thread-pro/thread-structures.md +240 -0
- package/skills/skills/thread-pro/voice-injection.md +130 -0
- package/skills/skills/tinkering/SKILL.md +251 -0
- package/skills/skills/tinkering/references/graduation-checklist.md +100 -0
- package/skills/skills/validate-plan/.skillkit-mode +1 -0
- package/skills/skills/validate-plan/SKILL.md +406 -0
- package/skills/skills/validate-plan/references/dry-principles.md +251 -0
- package/skills/skills/validate-plan/references/gap-analysis-guide.md +320 -0
- package/skills/skills/validate-plan/references/tdd-patterns.md +413 -0
- package/skills/skills/validate-plan/references/yagni-checklist.md +330 -0
- package/skills/skills/verify-before-ship/.skillkit-mode +1 -0
- package/skills/skills/verify-before-ship/SKILL.md +116 -0
- package/skills/skills/verify-before-ship/references/anti-rationalization.md +212 -0
- package/skills/skills/verify-before-ship/references/verification-gates.md +305 -0
- package/skills-manifest.json +8 -2
- package/src/picker.js +11 -5
- package/src/picker.test.js +36 -1
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Cross-Reference Validation - File Existence Checking
|
|
4
|
+
|
|
5
|
+
Validates that all file references in SKILL.md actually exist in the skill directory.
|
|
6
|
+
Prevents broken references and orphaned files from being packaged.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
from utils.reference_validator import CrossReferenceValidator
|
|
10
|
+
|
|
11
|
+
validator = CrossReferenceValidator(skill_path='/path/to/skill')
|
|
12
|
+
result = validator.validate_skill_md()
|
|
13
|
+
|
|
14
|
+
if result['status'] == 'fail':
|
|
15
|
+
print(f"Missing files: {result['missing_files']}")
|
|
16
|
+
print(f"Suggestion: {result['suggestion']}")
|
|
17
|
+
|
|
18
|
+
Version: 1.0
|
|
19
|
+
Part of: Advanced Skill Creator v1.2 - Issue #5 fix (File Existence Validation)
|
|
20
|
+
Reference: TEST-REPORT.md Issue #5 - Validation Doesn't Check File Existence
|
|
21
|
+
TEST-REPORT.md Issue #1 - Broken Reference Pattern
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import os
|
|
25
|
+
import re
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
from typing import Dict, List, Tuple, Optional, Any
|
|
28
|
+
from dataclasses import dataclass, field
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class ValidationResult:
|
|
33
|
+
"""Result of cross-reference validation."""
|
|
34
|
+
status: str # 'pass' or 'fail'
|
|
35
|
+
message: str
|
|
36
|
+
missing_files: List[str] = field(default_factory=list)
|
|
37
|
+
orphaned_files: List[str] = field(default_factory=list)
|
|
38
|
+
valid_references: List[str] = field(default_factory=list)
|
|
39
|
+
suggestion: str = ""
|
|
40
|
+
details: Dict[str, Any] = field(default_factory=dict)
|
|
41
|
+
|
|
42
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
43
|
+
"""Convert to dictionary for JSON serialization."""
|
|
44
|
+
return {
|
|
45
|
+
'status': self.status,
|
|
46
|
+
'message': self.message,
|
|
47
|
+
'missing_files': self.missing_files,
|
|
48
|
+
'orphaned_files': self.orphaned_files,
|
|
49
|
+
'valid_references': self.valid_references,
|
|
50
|
+
'suggestion': self.suggestion,
|
|
51
|
+
'details': self.details
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class CrossReferenceValidator:
|
|
56
|
+
"""
|
|
57
|
+
Validate cross-references between SKILL.md and actual files.
|
|
58
|
+
|
|
59
|
+
Addresses:
|
|
60
|
+
- Issue #1: Broken Reference Pattern (files referenced but not created)
|
|
61
|
+
- Issue #5: File Existence Validation (must check actual files)
|
|
62
|
+
- Issue #7: Orphaned Files (files exist but not referenced)
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
# Patterns to extract file references from markdown
|
|
66
|
+
MARKDOWN_LINK_PATTERN = r'\[([^\]]+)\]\(([^)]+)\)' # [text](path)
|
|
67
|
+
CODE_REFERENCE_PATTERN = r'`([^`]+\.(md|py|json|yaml|txt))`' # `filename.ext`
|
|
68
|
+
PATH_REFERENCE_PATTERN = r'(?:files?|resources?|knowledge|files?:)\s+([^\s\n]+\.(?:md|py))' # "file: path.md"
|
|
69
|
+
|
|
70
|
+
def __init__(self, skill_path: str):
|
|
71
|
+
"""
|
|
72
|
+
Initialize validator.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
skill_path: Path to skill directory
|
|
76
|
+
"""
|
|
77
|
+
self.skill_path = Path(skill_path)
|
|
78
|
+
self.skill_md_path = self.skill_path / 'SKILL.md'
|
|
79
|
+
|
|
80
|
+
def validate_skill_md(self) -> ValidationResult:
|
|
81
|
+
"""
|
|
82
|
+
Validate SKILL.md references against actual files.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
ValidationResult with status, missing/orphaned files, and suggestions
|
|
86
|
+
"""
|
|
87
|
+
if not self.skill_path.exists():
|
|
88
|
+
return ValidationResult(
|
|
89
|
+
status='fail',
|
|
90
|
+
message=f"Skill directory not found: {self.skill_path}",
|
|
91
|
+
suggestion=f"Create skill directory at {self.skill_path}"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
if not self.skill_md_path.exists():
|
|
95
|
+
return ValidationResult(
|
|
96
|
+
status='fail',
|
|
97
|
+
message="SKILL.md not found",
|
|
98
|
+
suggestion="Create SKILL.md in skill directory"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Read SKILL.md content
|
|
102
|
+
try:
|
|
103
|
+
with open(self.skill_md_path, 'r', encoding='utf-8') as f:
|
|
104
|
+
skill_md_content = f.read()
|
|
105
|
+
except Exception as e:
|
|
106
|
+
return ValidationResult(
|
|
107
|
+
status='fail',
|
|
108
|
+
message=f"Error reading SKILL.md: {e}",
|
|
109
|
+
suggestion="Ensure SKILL.md is readable"
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Extract references
|
|
113
|
+
referenced_files = self._extract_file_references(skill_md_content)
|
|
114
|
+
|
|
115
|
+
# Check which references exist
|
|
116
|
+
missing_files = []
|
|
117
|
+
valid_references = []
|
|
118
|
+
|
|
119
|
+
for ref in referenced_files:
|
|
120
|
+
full_path = self.skill_path / ref
|
|
121
|
+
if full_path.exists():
|
|
122
|
+
valid_references.append(ref)
|
|
123
|
+
else:
|
|
124
|
+
missing_files.append(ref)
|
|
125
|
+
|
|
126
|
+
# Find orphaned files (exist but not referenced)
|
|
127
|
+
orphaned_files = self._find_orphaned_files(referenced_files)
|
|
128
|
+
|
|
129
|
+
# Determine status and message
|
|
130
|
+
if missing_files or orphaned_files:
|
|
131
|
+
status = 'fail'
|
|
132
|
+
message = self._build_failure_message(missing_files, orphaned_files)
|
|
133
|
+
suggestion = self._build_suggestion(missing_files, orphaned_files)
|
|
134
|
+
else:
|
|
135
|
+
status = 'pass'
|
|
136
|
+
message = f"All {len(valid_references)} file references are valid"
|
|
137
|
+
suggestion = ""
|
|
138
|
+
|
|
139
|
+
return ValidationResult(
|
|
140
|
+
status=status,
|
|
141
|
+
message=message,
|
|
142
|
+
missing_files=missing_files,
|
|
143
|
+
orphaned_files=orphaned_files,
|
|
144
|
+
valid_references=valid_references,
|
|
145
|
+
suggestion=suggestion,
|
|
146
|
+
details={
|
|
147
|
+
'referenced_files_count': len(referenced_files),
|
|
148
|
+
'valid_references_count': len(valid_references),
|
|
149
|
+
'missing_files_count': len(missing_files),
|
|
150
|
+
'orphaned_files_count': len(orphaned_files)
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
def _extract_file_references(self, content: str) -> List[str]:
|
|
155
|
+
"""
|
|
156
|
+
Extract file references from SKILL.md content.
|
|
157
|
+
|
|
158
|
+
Looks for:
|
|
159
|
+
1. Markdown links: [text](path/to/file.md)
|
|
160
|
+
2. Code references: `filename.md`
|
|
161
|
+
3. Path patterns: "file: path/to/file.md"
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
content: SKILL.md content
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
List of unique file references (relative paths)
|
|
168
|
+
"""
|
|
169
|
+
references = set()
|
|
170
|
+
|
|
171
|
+
# Pattern 1: Markdown links [text](path)
|
|
172
|
+
for match in re.finditer(self.MARKDOWN_LINK_PATTERN, content):
|
|
173
|
+
path = match.group(2)
|
|
174
|
+
# Only include local file references (not URLs)
|
|
175
|
+
if not path.startswith('http') and path.endswith(('.md', '.py', '.txt')):
|
|
176
|
+
references.add(path)
|
|
177
|
+
|
|
178
|
+
# Pattern 2: Code references `filename.ext`
|
|
179
|
+
for match in re.finditer(self.CODE_REFERENCE_PATTERN, content):
|
|
180
|
+
references.add(match.group(1))
|
|
181
|
+
|
|
182
|
+
# Pattern 3: Path patterns with keywords
|
|
183
|
+
for match in re.finditer(self.PATH_REFERENCE_PATTERN, content):
|
|
184
|
+
references.add(match.group(1))
|
|
185
|
+
|
|
186
|
+
# Normalize paths (remove ../ prefixes if at root)
|
|
187
|
+
normalized = set()
|
|
188
|
+
for ref in references:
|
|
189
|
+
# Clean up relative path notation
|
|
190
|
+
if ref.startswith('./'):
|
|
191
|
+
ref = ref[2:]
|
|
192
|
+
normalized.add(ref)
|
|
193
|
+
|
|
194
|
+
return sorted(list(normalized))
|
|
195
|
+
|
|
196
|
+
def _find_orphaned_files(self, referenced_files: List[str]) -> List[str]:
|
|
197
|
+
"""
|
|
198
|
+
Find files that exist but are not referenced in SKILL.md.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
referenced_files: List of referenced files
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
List of orphaned files found
|
|
205
|
+
"""
|
|
206
|
+
orphaned = []
|
|
207
|
+
referenced_normalized = set(referenced_files)
|
|
208
|
+
|
|
209
|
+
# Walk through skill directory
|
|
210
|
+
for root, dirs, files in os.walk(self.skill_path):
|
|
211
|
+
# Skip hidden directories
|
|
212
|
+
dirs[:] = [d for d in dirs if not d.startswith('.')]
|
|
213
|
+
|
|
214
|
+
for file in files:
|
|
215
|
+
if file.endswith(('.md', '.py', '.txt', '.json', '.yaml')):
|
|
216
|
+
full_path = Path(root) / file
|
|
217
|
+
rel_path = str(full_path.relative_to(self.skill_path))
|
|
218
|
+
|
|
219
|
+
# Check if referenced
|
|
220
|
+
is_referenced = any(
|
|
221
|
+
rel_path == ref or
|
|
222
|
+
rel_path.endswith(ref) or
|
|
223
|
+
ref.endswith(file)
|
|
224
|
+
for ref in referenced_normalized
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
if not is_referenced:
|
|
228
|
+
# Exclude common non-referenced files
|
|
229
|
+
if file not in ['SKILL.md', '.gitignore', 'README.md']:
|
|
230
|
+
orphaned.append(rel_path)
|
|
231
|
+
|
|
232
|
+
return sorted(orphaned)
|
|
233
|
+
|
|
234
|
+
def _build_failure_message(self, missing: List[str], orphaned: List[str]) -> str:
|
|
235
|
+
"""Build human-readable failure message."""
|
|
236
|
+
parts = []
|
|
237
|
+
|
|
238
|
+
if missing:
|
|
239
|
+
parts.append(f"❌ {len(missing)} referenced files not found: {', '.join(missing[:3])}")
|
|
240
|
+
if len(missing) > 3:
|
|
241
|
+
parts[-1] += f" (+{len(missing) - 3} more)"
|
|
242
|
+
|
|
243
|
+
if orphaned:
|
|
244
|
+
parts.append(f"⚠️ {len(orphaned)} orphaned files in skill directory")
|
|
245
|
+
|
|
246
|
+
return " | ".join(parts)
|
|
247
|
+
|
|
248
|
+
def _build_suggestion(self, missing: List[str], orphaned: List[str]) -> str:
|
|
249
|
+
"""Build actionable suggestion for fixing issues."""
|
|
250
|
+
suggestions = []
|
|
251
|
+
|
|
252
|
+
if missing:
|
|
253
|
+
suggestions.append(
|
|
254
|
+
f"Remove {len(missing)} broken reference(s) from SKILL.md, "
|
|
255
|
+
f"or create the missing files: {', '.join(missing[:2])}"
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
if orphaned:
|
|
259
|
+
suggestions.append(
|
|
260
|
+
f"Either: (a) Add {len(orphaned)} orphaned file(s) to SKILL.md documentation, "
|
|
261
|
+
f"or (b) delete them from skill directory"
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
return " | ".join(suggestions) if suggestions else ""
|
|
265
|
+
|
|
266
|
+
def validate_skill_directory(self, strict: bool = False) -> ValidationResult:
|
|
267
|
+
"""
|
|
268
|
+
Comprehensive validation of entire skill directory.
|
|
269
|
+
|
|
270
|
+
Checks:
|
|
271
|
+
- SKILL.md exists and is valid
|
|
272
|
+
- All references valid
|
|
273
|
+
- No orphaned files (if strict=True)
|
|
274
|
+
|
|
275
|
+
Args:
|
|
276
|
+
strict: If True, orphaned files cause failure. If False, just warning.
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
ValidationResult
|
|
280
|
+
"""
|
|
281
|
+
result = self.validate_skill_md()
|
|
282
|
+
|
|
283
|
+
# If strict mode, orphaned files cause failure
|
|
284
|
+
if strict and result.orphaned_files:
|
|
285
|
+
result.status = 'fail'
|
|
286
|
+
result.message = f"{result.message} (strict mode: orphaned files not allowed)"
|
|
287
|
+
|
|
288
|
+
return result
|
|
289
|
+
|
|
290
|
+
def check_reference(self, reference: str) -> bool:
|
|
291
|
+
"""
|
|
292
|
+
Check if a single reference exists.
|
|
293
|
+
|
|
294
|
+
Args:
|
|
295
|
+
reference: File reference to check
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
True if file exists, False otherwise
|
|
299
|
+
"""
|
|
300
|
+
full_path = self.skill_path / reference
|
|
301
|
+
return full_path.exists()
|
|
302
|
+
|
|
303
|
+
def list_all_references(self) -> Dict[str, List[str]]:
|
|
304
|
+
"""
|
|
305
|
+
List all references in SKILL.md organized by category.
|
|
306
|
+
|
|
307
|
+
Returns:
|
|
308
|
+
Dict with 'valid', 'missing', 'orphaned' lists
|
|
309
|
+
"""
|
|
310
|
+
try:
|
|
311
|
+
with open(self.skill_md_path, 'r', encoding='utf-8') as f:
|
|
312
|
+
content = f.read()
|
|
313
|
+
except Exception:
|
|
314
|
+
return {'valid': [], 'missing': [], 'orphaned': []}
|
|
315
|
+
|
|
316
|
+
referenced = self._extract_file_references(content)
|
|
317
|
+
valid = [f for f in referenced if self.check_reference(f)]
|
|
318
|
+
missing = [f for f in referenced if not self.check_reference(f)]
|
|
319
|
+
orphaned = self._find_orphaned_files(referenced)
|
|
320
|
+
|
|
321
|
+
return {
|
|
322
|
+
'valid': valid,
|
|
323
|
+
'missing': missing,
|
|
324
|
+
'orphaned': orphaned
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
class SkillPackageValidator:
|
|
329
|
+
"""
|
|
330
|
+
Validate skill before packaging.
|
|
331
|
+
|
|
332
|
+
Ensures:
|
|
333
|
+
1. All referenced files exist (no broken references)
|
|
334
|
+
2. No orphaned files included in package
|
|
335
|
+
3. SKILL.md is syntactically valid
|
|
336
|
+
"""
|
|
337
|
+
|
|
338
|
+
def __init__(self, skill_path: str):
|
|
339
|
+
"""
|
|
340
|
+
Initialize validator.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
skill_path: Path to skill directory
|
|
344
|
+
"""
|
|
345
|
+
self.skill_path = Path(skill_path)
|
|
346
|
+
self.ref_validator = CrossReferenceValidator(skill_path)
|
|
347
|
+
|
|
348
|
+
def validate_for_packaging(self, strict: bool = False) -> ValidationResult:
|
|
349
|
+
"""
|
|
350
|
+
Validate skill is ready for packaging.
|
|
351
|
+
|
|
352
|
+
Args:
|
|
353
|
+
strict: If True, any issues cause failure
|
|
354
|
+
|
|
355
|
+
Returns:
|
|
356
|
+
ValidationResult indicating if safe to package
|
|
357
|
+
"""
|
|
358
|
+
result = self.ref_validator.validate_skill_directory(strict=strict)
|
|
359
|
+
|
|
360
|
+
if result.status == 'fail':
|
|
361
|
+
result.suggestion = (
|
|
362
|
+
f"Fix issues before packaging: {result.suggestion}"
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
return result
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
if __name__ == '__main__':
|
|
369
|
+
# Example usage
|
|
370
|
+
import sys
|
|
371
|
+
|
|
372
|
+
if len(sys.argv) < 2:
|
|
373
|
+
print("Usage: python reference_validator.py <skill_path> [--strict]")
|
|
374
|
+
sys.exit(1)
|
|
375
|
+
|
|
376
|
+
skill_path = sys.argv[1]
|
|
377
|
+
strict_mode = '--strict' in sys.argv
|
|
378
|
+
|
|
379
|
+
validator = CrossReferenceValidator(skill_path)
|
|
380
|
+
result = validator.validate_skill_md()
|
|
381
|
+
|
|
382
|
+
print(f"Status: {result.status.upper()}")
|
|
383
|
+
print(f"Message: {result.message}")
|
|
384
|
+
|
|
385
|
+
if result.missing_files:
|
|
386
|
+
print(f"\nMissing files ({len(result.missing_files)}):")
|
|
387
|
+
for f in result.missing_files:
|
|
388
|
+
print(f" ❌ {f}")
|
|
389
|
+
|
|
390
|
+
if result.orphaned_files:
|
|
391
|
+
print(f"\nOrphaned files ({len(result.orphaned_files)}):")
|
|
392
|
+
for f in result.orphaned_files:
|
|
393
|
+
print(f" ⚠️ {f}")
|
|
394
|
+
|
|
395
|
+
if result.suggestion:
|
|
396
|
+
print(f"\nSuggestion: {result.suggestion}")
|
|
397
|
+
|
|
398
|
+
if result.valid_references:
|
|
399
|
+
print(f"\nValid references: {len(result.valid_references)}")
|
|
400
|
+
|
|
401
|
+
sys.exit(0 if result.status == 'pass' else 1)
|