@tinkcarlos/skillora 0.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.
Files changed (234) hide show
  1. package/.claude/skills/.temp-skill-index.md +245 -0
  2. package/.claude/skills/SKILL.md +264 -0
  3. package/.claude/skills/api-scaffolding/SKILL.md +431 -0
  4. package/.claude/skills/api-scaffolding/agents/backend-architect.md +282 -0
  5. package/.claude/skills/api-scaffolding/agents/django-pro.md +144 -0
  6. package/.claude/skills/api-scaffolding/agents/fastapi-pro.md +156 -0
  7. package/.claude/skills/api-scaffolding/agents/graphql-architect.md +146 -0
  8. package/.claude/skills/api-scaffolding/skills/fastapi-templates/SKILL.md +171 -0
  9. package/.claude/skills/api-testing-observability/SKILL.md +583 -0
  10. package/.claude/skills/api-testing-observability/agents/api-documenter.md +146 -0
  11. package/.claude/skills/api-testing-observability/commands/api-mock.md +1320 -0
  12. package/.claude/skills/brainstorming/SKILL.md +283 -0
  13. package/.claude/skills/bug-fixing/SKILL.md +382 -0
  14. package/.claude/skills/bug-fixing/references/backend-guide.md +132 -0
  15. package/.claude/skills/bug-fixing/references/bug-guide.md +354 -0
  16. package/.claude/skills/bug-fixing/references/bug-record-template.md +134 -0
  17. package/.claude/skills/bug-fixing/references/bug-records.md +88 -0
  18. package/.claude/skills/bug-fixing/references/code-review-gate.md +81 -0
  19. package/.claude/skills/bug-fixing/references/common-bugs.md +140 -0
  20. package/.claude/skills/bug-fixing/references/complete-workflow.md +361 -0
  21. package/.claude/skills/bug-fixing/references/config-driven-fixes.md +136 -0
  22. package/.claude/skills/bug-fixing/references/context-isolation-protocol.md +268 -0
  23. package/.claude/skills/bug-fixing/references/cross-surface-regression.md +120 -0
  24. package/.claude/skills/bug-fixing/references/database-investigation.md +129 -0
  25. package/.claude/skills/bug-fixing/references/dependency-and-integrity-protocol.md +369 -0
  26. package/.claude/skills/bug-fixing/references/fix-completeness-checklist.md +239 -0
  27. package/.claude/skills/bug-fixing/references/frontend-guide.md +219 -0
  28. package/.claude/skills/bug-fixing/references/fullstack-joint-guide.md +123 -0
  29. package/.claude/skills/bug-fixing/references/functional-breakage.md +117 -0
  30. package/.claude/skills/bug-fixing/references/ide-lint-errors-guide.md +176 -0
  31. package/.claude/skills/bug-fixing/references/impact-analysis.md +511 -0
  32. package/.claude/skills/bug-fixing/references/investigation-checklist.md +263 -0
  33. package/.claude/skills/bug-fixing/references/knowledge-extraction-guide.md +531 -0
  34. package/.claude/skills/bug-fixing/references/knowledge-workflow.md +212 -0
  35. package/.claude/skills/bug-fixing/references/post-edit-quality-gate.md +30 -0
  36. package/.claude/skills/bug-fixing/references/python-env-and-testing.md +126 -0
  37. package/.claude/skills/bug-fixing/references/rca-guide.md +428 -0
  38. package/.claude/skills/bug-fixing/references/similar-bug-patterns.md +113 -0
  39. package/.claude/skills/bug-fixing/references/skill-delegation-guide.md +350 -0
  40. package/.claude/skills/bug-fixing/references/skill-orchestration.md +155 -0
  41. package/.claude/skills/bug-fixing/references/testing-strategy.md +350 -0
  42. package/.claude/skills/bug-fixing/references/tooling-build-scripts.md +162 -0
  43. package/.claude/skills/bug-fixing/references/user-input-validation.md +77 -0
  44. package/.claude/skills/bug-fixing/references/ux-patterns.md +158 -0
  45. package/.claude/skills/bug-fixing/references/windows-terminal-hygiene.md +106 -0
  46. package/.claude/skills/bug-fixing/references/zero-regression-matrix.md +239 -0
  47. package/.claude/skills/bug-fixing/references/zero-risk-protocol.md +102 -0
  48. package/.claude/skills/bug-fixing/scripts/format_code.py +611 -0
  49. package/.claude/skills/bug-fixing/scripts/generate_report_template.py +74 -0
  50. package/.claude/skills/bug-fixing/scripts/lint_check.py +816 -0
  51. package/.claude/skills/bug-fixing/scripts/requirements.txt +36 -0
  52. package/.claude/skills/cicd-pipeline/SKILL.md +300 -0
  53. package/.claude/skills/code-review/SKILL.md +535 -0
  54. package/.claude/skills/code-review/references/anti-pattern-scan.md +102 -0
  55. package/.claude/skills/code-review/references/automated-analysis.md +456 -0
  56. package/.claude/skills/code-review/references/backend-common-issues.md +589 -0
  57. package/.claude/skills/code-review/references/backend-expert-guide.md +415 -0
  58. package/.claude/skills/code-review/references/backend-review.md +868 -0
  59. package/.claude/skills/code-review/references/batch-processing-strategy.md +198 -0
  60. package/.claude/skills/code-review/references/call-chain-analysis-protocol.md +166 -0
  61. package/.claude/skills/code-review/references/common-patterns.md +321 -0
  62. package/.claude/skills/code-review/references/configuration-review.md +425 -0
  63. package/.claude/skills/code-review/references/control-flow-completeness.md +114 -0
  64. package/.claude/skills/code-review/references/database-review.md +298 -0
  65. package/.claude/skills/code-review/references/dependency-and-integrity-protocol.md +313 -0
  66. package/.claude/skills/code-review/references/external-standards.md +51 -0
  67. package/.claude/skills/code-review/references/feature-review.md +329 -0
  68. package/.claude/skills/code-review/references/file-review-template.md +326 -0
  69. package/.claude/skills/code-review/references/frontend-advanced.md +654 -0
  70. package/.claude/skills/code-review/references/frontend-common-issues.md +482 -0
  71. package/.claude/skills/code-review/references/frontend-expert-guide.md +342 -0
  72. package/.claude/skills/code-review/references/frontend-review.md +783 -0
  73. package/.claude/skills/code-review/references/fullstack-consistency.md +418 -0
  74. package/.claude/skills/code-review/references/fullstack-review.md +477 -0
  75. package/.claude/skills/code-review/references/functional-completeness.md +386 -0
  76. package/.claude/skills/code-review/references/hidden-bugs-detection.md +473 -0
  77. package/.claude/skills/code-review/references/ide-lint-errors-guide.md +173 -0
  78. package/.claude/skills/code-review/references/infrastructure-review.md +453 -0
  79. package/.claude/skills/code-review/references/iteration-review.md +264 -0
  80. package/.claude/skills/code-review/references/job-review.md +335 -0
  81. package/.claude/skills/code-review/references/layered-checklist-protocol.md +157 -0
  82. package/.claude/skills/code-review/references/logic-completeness.md +535 -0
  83. package/.claude/skills/code-review/references/mandatory-checklist.md +288 -0
  84. package/.claude/skills/code-review/references/multi-language-guide.md +800 -0
  85. package/.claude/skills/code-review/references/new-project-review.md +226 -0
  86. package/.claude/skills/code-review/references/non-code-files-review.md +451 -0
  87. package/.claude/skills/code-review/references/overlooked-issues.md +657 -0
  88. package/.claude/skills/code-review/references/platform-specific-review.md +195 -0
  89. package/.claude/skills/code-review/references/precision-analysis-protocol.md +260 -0
  90. package/.claude/skills/code-review/references/python-patterns.md +494 -0
  91. package/.claude/skills/code-review/references/rca-techniques.md +362 -0
  92. package/.claude/skills/code-review/references/report-template.md +430 -0
  93. package/.claude/skills/code-review/references/resource-limits-and-degradation.md +137 -0
  94. package/.claude/skills/code-review/references/review-dimensions.md +311 -0
  95. package/.claude/skills/code-review/references/review-guide.md +202 -0
  96. package/.claude/skills/code-review/references/review-knowledge-workflow.md +257 -0
  97. package/.claude/skills/code-review/references/review-progress-tracker-protocol.md +172 -0
  98. package/.claude/skills/code-review/references/review-record-template.md +195 -0
  99. package/.claude/skills/code-review/references/skill-orchestration.md +143 -0
  100. package/.claude/skills/code-review/references/ui-ux-review.md +470 -0
  101. package/.claude/skills/containerization/SKILL.md +313 -0
  102. package/.claude/skills/database-migrations/agents/database-admin.md +142 -0
  103. package/.claude/skills/database-migrations/agents/database-optimizer.md +144 -0
  104. package/.claude/skills/database-migrations/commands/migration-observability.md +408 -0
  105. package/.claude/skills/database-migrations/commands/sql-migrations.md +492 -0
  106. package/.claude/skills/finishing-a-development-branch/SKILL.md +319 -0
  107. package/.claude/skills/frontend-design/LICENSE.txt +177 -0
  108. package/.claude/skills/frontend-design/SKILL.md +587 -0
  109. package/.claude/skills/frontend-design/references/color-consistency.md +487 -0
  110. package/.claude/skills/frontend-design/references/color-palettes-full.md +657 -0
  111. package/.claude/skills/frontend-design/references/design-system-generator.md +285 -0
  112. package/.claude/skills/frontend-design/references/font-pairings-full.md +705 -0
  113. package/.claude/skills/frontend-design/references/industry-anti-patterns.md +281 -0
  114. package/.claude/skills/frontend-design/references/layout-anti-patterns.md +582 -0
  115. package/.claude/skills/frontend-design/references/motion-patterns.md +659 -0
  116. package/.claude/skills/frontend-design/references/pre-delivery-checklist.md +153 -0
  117. package/.claude/skills/frontend-design/references/responsive-design.md +555 -0
  118. package/.claude/skills/frontend-design/references/style-modification-rules.md +335 -0
  119. package/.claude/skills/frontend-design/references/ui-styles-full.md +383 -0
  120. package/.claude/skills/frontend-design/references/ui-styles-rating.md +191 -0
  121. package/.claude/skills/frontend-design/references/ux-guidelines.md +640 -0
  122. package/.claude/skills/fullstack-developer/SKILL.md +512 -0
  123. package/.claude/skills/fullstack-developer/references/api-contract-guide.md +312 -0
  124. package/.claude/skills/fullstack-developer/references/api-response-patterns.md +223 -0
  125. package/.claude/skills/fullstack-developer/references/async-patterns.md +220 -0
  126. package/.claude/skills/fullstack-developer/references/bug-prevention.md +914 -0
  127. package/.claude/skills/fullstack-developer/references/code-quality-checklist.md +271 -0
  128. package/.claude/skills/fullstack-developer/references/complete-development-workflow.md +278 -0
  129. package/.claude/skills/fullstack-developer/references/context-isolation-protocol.md +256 -0
  130. package/.claude/skills/fullstack-developer/references/database-migration.md +331 -0
  131. package/.claude/skills/fullstack-developer/references/dependency-and-integrity-protocol.md +390 -0
  132. package/.claude/skills/fullstack-developer/references/development-phases.md +333 -0
  133. package/.claude/skills/fullstack-developer/references/expert-guide.md +214 -0
  134. package/.claude/skills/fullstack-developer/references/file-import-patterns.md +114 -0
  135. package/.claude/skills/fullstack-developer/references/graceful-degradation-patterns.md +78 -0
  136. package/.claude/skills/fullstack-developer/references/ide-lint-errors-guide.md +183 -0
  137. package/.claude/skills/fullstack-developer/references/integration-testing.md +301 -0
  138. package/.claude/skills/fullstack-developer/references/mock-api-patterns.md +307 -0
  139. package/.claude/skills/fullstack-developer/references/phase-gate-template.md +249 -0
  140. package/.claude/skills/fullstack-developer/references/post-edit-quality-gate.md +30 -0
  141. package/.claude/skills/fullstack-developer/references/python-engineering.md +79 -0
  142. package/.claude/skills/fullstack-developer/references/skill-orchestration.md +214 -0
  143. package/.claude/skills/fullstack-developer/references/skill-router-table.md +304 -0
  144. package/.claude/skills/fullstack-developer/references/state-sync.md +217 -0
  145. package/.claude/skills/fullstack-developer/references/ui-testing-checklist.md +292 -0
  146. package/.claude/skills/fullstack-developer/scripts/format_code.py +611 -0
  147. package/.claude/skills/fullstack-developer/scripts/lint_check.py +816 -0
  148. package/.claude/skills/fullstack-developer/scripts/requirements.txt +36 -0
  149. package/.claude/skills/performance-optimization/SKILL.md +250 -0
  150. package/.claude/skills/product-requirements/SKILL.md +357 -0
  151. package/.claude/skills/product-requirements/references/acceptance-criteria.md +335 -0
  152. package/.claude/skills/product-requirements/references/answer-first-questioning-protocol.md +299 -0
  153. package/.claude/skills/product-requirements/references/competitive-analysis-guide.md +183 -0
  154. package/.claude/skills/product-requirements/references/document-accuracy-protocol.md +253 -0
  155. package/.claude/skills/product-requirements/references/document-management-protocol.md +278 -0
  156. package/.claude/skills/product-requirements/references/external-standards.md +62 -0
  157. package/.claude/skills/product-requirements/references/feature-spec-template.md +359 -0
  158. package/.claude/skills/product-requirements/references/knowledge-acquisition-protocol.md +251 -0
  159. package/.claude/skills/product-requirements/references/plan-execution-protocol.md +334 -0
  160. package/.claude/skills/product-requirements/references/plan-generation-protocol.md +264 -0
  161. package/.claude/skills/product-requirements/references/prioritization-frameworks.md +80 -0
  162. package/.claude/skills/product-requirements/references/requirement-decomposition-protocol.md +291 -0
  163. package/.claude/skills/product-requirements/references/user-story-examples.md +297 -0
  164. package/.claude/skills/product-requirements/references/workflow-templates.md +266 -0
  165. package/.claude/skills/react-best-practices/SKILL.md +198 -0
  166. package/.claude/skills/react-best-practices/references/advanced-patterns.md +94 -0
  167. package/.claude/skills/react-best-practices/references/bundle-optimization.md +182 -0
  168. package/.claude/skills/react-best-practices/references/client-data-fetching.md +112 -0
  169. package/.claude/skills/react-best-practices/references/complete-guide.md +2249 -0
  170. package/.claude/skills/react-best-practices/references/eliminating-waterfalls.md +169 -0
  171. package/.claude/skills/react-best-practices/references/javascript-performance.md +256 -0
  172. package/.claude/skills/react-best-practices/references/rendering-performance.md +230 -0
  173. package/.claude/skills/react-best-practices/references/rerender-optimization.md +214 -0
  174. package/.claude/skills/react-best-practices/references/server-performance.md +182 -0
  175. package/.claude/skills/security-audit/SKILL.md +226 -0
  176. package/.claude/skills/shared-references/advanced-debugging-techniques.md +186 -0
  177. package/.claude/skills/shared-references/code-quality-checklist.md +218 -0
  178. package/.claude/skills/shared-references/code-review-efficiency-guide.md +125 -0
  179. package/.claude/skills/shared-references/mcp-dependency-compatibility-protocol.md +276 -0
  180. package/.claude/skills/shared-references/skill-call-graph.md +230 -0
  181. package/.claude/skills/shared-references/skill-orchestration-protocol.md +281 -0
  182. package/.claude/skills/shared-references/subagent-dispatch-templates.md +199 -0
  183. package/.claude/skills/skill-expert-skills/LICENSE.txt +204 -0
  184. package/.claude/skills/skill-expert-skills/QUICK_NAVIGATION.md +374 -0
  185. package/.claude/skills/skill-expert-skills/SKILL.md +247 -0
  186. package/.claude/skills/skill-expert-skills/docs/_index.md +91 -0
  187. package/.claude/skills/skill-expert-skills/references/deep-research-methodology.md +389 -0
  188. package/.claude/skills/skill-expert-skills/references/docs-generation-workflow.md +398 -0
  189. package/.claude/skills/skill-expert-skills/references/domain-expertise-protocol.md +343 -0
  190. package/.claude/skills/skill-expert-skills/references/domain-knowledge/_index.md +54 -0
  191. package/.claude/skills/skill-expert-skills/references/domain-knowledge/backend-expertise.md +517 -0
  192. package/.claude/skills/skill-expert-skills/references/domain-knowledge/bug-fixing-expertise.md +363 -0
  193. package/.claude/skills/skill-expert-skills/references/domain-knowledge/code-review-expertise.md +392 -0
  194. package/.claude/skills/skill-expert-skills/references/domain-knowledge/frontend-expertise.md +410 -0
  195. package/.claude/skills/skill-expert-skills/references/domain-knowledge-template.md +503 -0
  196. package/.claude/skills/skill-expert-skills/references/examples.md +782 -0
  197. package/.claude/skills/skill-expert-skills/references/integration-examples.md +655 -0
  198. package/.claude/skills/skill-expert-skills/references/knowledge-validation-checklist.md +246 -0
  199. package/.claude/skills/skill-expert-skills/references/latest-knowledge-acquisition.md +461 -0
  200. package/.claude/skills/skill-expert-skills/references/mcp-tools-guide.md +439 -0
  201. package/.claude/skills/skill-expert-skills/references/official-best-practices.md +616 -0
  202. package/.claude/skills/skill-expert-skills/references/patterns.md +218 -0
  203. package/.claude/skills/skill-expert-skills/references/plugin-skills-guide.md +432 -0
  204. package/.claude/skills/skill-expert-skills/references/requirement-elicitation-protocol.md +290 -0
  205. package/.claude/skills/skill-expert-skills/references/skill-creator-SKILL.md +353 -0
  206. package/.claude/skills/skill-expert-skills/references/skill-templates.md +583 -0
  207. package/.claude/skills/skill-expert-skills/references/skills-knowledge-base.md +561 -0
  208. package/.claude/skills/skill-expert-skills/references/tools-guide.md +379 -0
  209. package/.claude/skills/skill-expert-skills/references/troubleshooting.md +378 -0
  210. package/.claude/skills/skill-expert-skills/references/universality-guide.md +205 -0
  211. package/.claude/skills/skill-expert-skills/references/writing-style-guide.md +466 -0
  212. package/.claude/skills/skill-expert-skills/scripts/__pycache__/quick_validate.cpython-313.pyc +0 -0
  213. package/.claude/skills/skill-expert-skills/scripts/__pycache__/universal_validate.cpython-313.pyc +0 -0
  214. package/.claude/skills/skill-expert-skills/scripts/analyze_trigger.py +425 -0
  215. package/.claude/skills/skill-expert-skills/scripts/diff_with_official.py +188 -0
  216. package/.claude/skills/skill-expert-skills/scripts/init_skill.py +349 -0
  217. package/.claude/skills/skill-expert-skills/scripts/package_skill.py +156 -0
  218. package/.claude/skills/skill-expert-skills/scripts/quick_validate.py +493 -0
  219. package/.claude/skills/skill-expert-skills/scripts/requirements.txt +2 -0
  220. package/.claude/skills/skill-expert-skills/scripts/universal_validate.py +182 -0
  221. package/.claude/skills/skill-expert-skills/scripts/upgrade_skill.py +431 -0
  222. package/.claude/skills/subagent-driven-development/SKILL.md +268 -0
  223. package/.claude/skills/test-driven-development/SKILL.md +246 -0
  224. package/.claude/skills/test-driven-development/references/testing-anti-patterns.md +192 -0
  225. package/.claude/skills/using-git-worktrees/SKILL.md +266 -0
  226. package/.claude/skills/using-skillstack/SKILL.md +127 -0
  227. package/.claude/skills/vercel-deploy/SKILL.md +166 -0
  228. package/.claude/skills/vercel-deploy/scripts/deploy.sh +249 -0
  229. package/.claude/skills/verification-before-completion/SKILL.md +305 -0
  230. package/.claude/skills/writing-plans/SKILL.md +259 -0
  231. package/README.md +69 -0
  232. package/bin/cli.js +468 -0
  233. package/lib/init.js +333 -0
  234. package/package.json +29 -0
@@ -0,0 +1,493 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Enhanced skill validation script with quality diagnostics
4
+ Features:
5
+ - Structure validation (frontmatter, naming, etc.)
6
+ - Conciseness check (< 500 lines recommended, < 800 lines max)
7
+ - Quality scoring (0-100)
8
+ - Actionable recommendations
9
+ - Resource statistics (references, scripts, assets)
10
+ """
11
+
12
+ import sys
13
+ import os
14
+ import re
15
+ import json
16
+ from pathlib import Path
17
+ from typing import Dict, List, Tuple, Any
18
+
19
+ # Configure stdout/stderr encoding for Windows
20
+ def _configure_stdio() -> None:
21
+ """Ensure UTF-8 encoding for stdout/stderr on Windows"""
22
+ import sys
23
+ for stream in (sys.stdout, sys.stderr):
24
+ try:
25
+ stream.reconfigure(encoding='utf-8', errors='replace')
26
+ except Exception:
27
+ # Some environments don't support reconfigure()
28
+ pass
29
+
30
+ _configure_stdio()
31
+
32
+ # Optional dependency: PyYAML
33
+ try:
34
+ import yaml
35
+ except ImportError: # pragma: no cover
36
+ yaml = None
37
+
38
+ # Conciseness thresholds for SKILL.md
39
+ SKILL_LINES_EXCELLENT = 200 # Excellent: very concise
40
+ SKILL_LINES_GOOD = 350 # Good: reasonably concise
41
+ SKILL_LINES_WARN = 500 # Soft limit: trigger warning
42
+ SKILL_LINES_ERROR = 800 # Hard limit: trigger error
43
+
44
+
45
+ class SkillQualityReport:
46
+ """Quality report for a skill"""
47
+
48
+ def __init__(self):
49
+ self.valid = True
50
+ self.errors: List[str] = []
51
+ self.warnings: List[str] = []
52
+ self.recommendations: List[str] = []
53
+ self.metrics: Dict[str, Any] = {}
54
+ self.score = 0
55
+
56
+ def add_error(self, message: str):
57
+ self.valid = False
58
+ self.errors.append(f"❌ ERROR: {message}")
59
+
60
+ def add_warning(self, message: str):
61
+ self.warnings.append(f"⚠️ WARNING: {message}")
62
+
63
+ def add_recommendation(self, message: str):
64
+ self.recommendations.append(f"💡 RECOMMENDATION: {message}")
65
+
66
+ def format_output(self, verbose: bool = False) -> str:
67
+ """Format report as human-readable text"""
68
+ lines = []
69
+
70
+ # Header
71
+ if self.valid:
72
+ lines.append("=" * 70)
73
+ lines.append("✅ SKILL VALIDATION PASSED")
74
+ lines.append("=" * 70)
75
+ else:
76
+ lines.append("=" * 70)
77
+ lines.append("❌ SKILL VALIDATION FAILED")
78
+ lines.append("=" * 70)
79
+
80
+ lines.append("")
81
+
82
+ # Quality Score
83
+ if self.valid:
84
+ score_bar = self._get_score_bar(self.score)
85
+ score_label = self._get_score_label(self.score)
86
+ lines.append(f"📊 Quality Score: {self.score}/100 {score_bar} ({score_label})")
87
+ lines.append("")
88
+
89
+ # Metrics
90
+ if self.metrics and verbose:
91
+ lines.append("📈 Metrics:")
92
+ for key, value in self.metrics.items():
93
+ lines.append(f" • {key}: {value}")
94
+ lines.append("")
95
+
96
+ # Errors
97
+ if self.errors:
98
+ lines.append("🔴 Errors (Must Fix):")
99
+ for error in self.errors:
100
+ lines.append(f" {error}")
101
+ lines.append("")
102
+
103
+ # Warnings
104
+ if self.warnings:
105
+ lines.append("🟡 Warnings (Should Fix):")
106
+ for warning in self.warnings:
107
+ lines.append(f" {warning}")
108
+ lines.append("")
109
+
110
+ # Recommendations
111
+ if self.recommendations:
112
+ lines.append("💡 Recommendations (Nice to Have):")
113
+ for rec in self.recommendations:
114
+ lines.append(f" {rec}")
115
+ lines.append("")
116
+
117
+ # Summary
118
+ if self.valid:
119
+ lines.append("=" * 70)
120
+ lines.append("✨ Summary:")
121
+ lines.append(f" Errors: {len(self.errors)}")
122
+ lines.append(f" Warnings: {len(self.warnings)}")
123
+ lines.append(f" Recommendations: {len(self.recommendations)}")
124
+ if self.score >= 90:
125
+ lines.append(" Status: 🏆 Excellent - Production Ready")
126
+ elif self.score >= 75:
127
+ lines.append(" Status: ✅ Good - Minor improvements suggested")
128
+ elif self.score >= 60:
129
+ lines.append(" Status: ⚠️ Fair - Consider improvements")
130
+ else:
131
+ lines.append(" Status: ⚠️ Needs Improvement")
132
+ lines.append("=" * 70)
133
+
134
+ return "\n".join(lines)
135
+
136
+ def _get_score_bar(self, score: int) -> str:
137
+ """Generate visual score bar"""
138
+ filled = int(score / 10)
139
+ empty = 10 - filled
140
+ return "█" * filled + "░" * empty
141
+
142
+ def _get_score_label(self, score: int) -> str:
143
+ """Get score label"""
144
+ if score >= 90:
145
+ return "Excellent"
146
+ elif score >= 75:
147
+ return "Good"
148
+ elif score >= 60:
149
+ return "Fair"
150
+ else:
151
+ return "Needs Improvement"
152
+
153
+
154
+ def count_resources(skill_path: Path) -> Dict[str, int]:
155
+ """Count resource files in references/, scripts/, assets/"""
156
+ counts = {
157
+ 'references': 0,
158
+ 'scripts': 0,
159
+ 'assets': 0
160
+ }
161
+
162
+ for dir_name in ['references', 'scripts', 'assets']:
163
+ dir_path = skill_path / dir_name
164
+ if dir_path.exists() and dir_path.is_dir():
165
+ # Count non-hidden files (excluding __pycache__, etc.)
166
+ counts[dir_name] = len([
167
+ f for f in dir_path.rglob('*')
168
+ if f.is_file()
169
+ and not f.name.startswith('.')
170
+ and '__pycache__' not in str(f)
171
+ ])
172
+
173
+ return counts
174
+
175
+
176
+ def check_problematic_special_chars(content: str) -> List[str]:
177
+ """Check for special characters in backticks that may cause parsing issues"""
178
+ issues = []
179
+
180
+ # Pattern to find single special characters in backticks
181
+ # These can be misinterpreted as bash commands by Claude Code
182
+ problematic_patterns = [
183
+ (r'`!`', 'exclamation mark (!)', 'non-null assertion'),
184
+ (r'`\$`', 'dollar sign ($)', 'variable prefix'),
185
+ (r'`#`', 'hash (#)', 'comment marker'),
186
+ (r'`\|`', 'pipe (|)', 'vertical bar'),
187
+ ]
188
+
189
+ for pattern, char_name, replacement in problematic_patterns:
190
+ if re.search(pattern, content):
191
+ issues.append(
192
+ f"Found {char_name} in backticks which may cause parsing errors. "
193
+ f"Use '{replacement}' instead."
194
+ )
195
+
196
+ return issues
197
+
198
+
199
+ def analyze_description_quality(description: str) -> Tuple[int, List[str]]:
200
+ """Analyze description quality and return score + suggestions"""
201
+ score = 0
202
+ suggestions = []
203
+
204
+ # Check length (should be descriptive but not too long)
205
+ desc_len = len(description)
206
+ if 100 <= desc_len <= 800:
207
+ score += 20
208
+ elif desc_len < 100:
209
+ suggestions.append("Description is quite short. Consider adding more trigger scenarios.")
210
+ elif desc_len > 800:
211
+ suggestions.append("Description is very long. Consider condensing to key trigger scenarios.")
212
+ else:
213
+ score += 10
214
+
215
+ # Check for "Use when:" section (good practice)
216
+ if "use when" in description.lower() or "trigger" in description.lower():
217
+ score += 25
218
+ else:
219
+ suggestions.append("Add 'Use when:' section to clarify trigger scenarios.")
220
+
221
+ # Check for output description
222
+ if any(keyword in description.lower() for keyword in ['output', 'produce', 'generate', 'create']):
223
+ score += 15
224
+ else:
225
+ suggestions.append("Describe what the skill outputs or produces.")
226
+
227
+ # Check for specific examples/keywords
228
+ if description.count('\n-') >= 3 or description.count('\n*') >= 3:
229
+ score += 20 # Has bullet points (likely detailed)
230
+ else:
231
+ suggestions.append("Use bullet points to list specific trigger scenarios (3-5 recommended).")
232
+
233
+ # Check for "Not for:" section (good boundary setting)
234
+ if "not for" in description.lower():
235
+ score += 20
236
+ else:
237
+ suggestions.append("Consider adding 'Not for:' section to set clear boundaries.")
238
+
239
+ return score, suggestions
240
+
241
+
242
+ def calculate_quality_score(report: SkillQualityReport,
243
+ skill_path: Path,
244
+ frontmatter: dict,
245
+ total_lines: int) -> int:
246
+ """Calculate overall quality score (0-100)"""
247
+ score = 0
248
+
249
+ # 1. Conciseness Score (30 points)
250
+ if total_lines <= SKILL_LINES_EXCELLENT:
251
+ score += 30
252
+ report.metrics['conciseness'] = f"Excellent ({total_lines} lines, {int(total_lines/SKILL_LINES_WARN*100)}% of threshold)"
253
+ elif total_lines <= SKILL_LINES_GOOD:
254
+ score += 25
255
+ report.metrics['conciseness'] = f"Very Good ({total_lines} lines, {int(total_lines/SKILL_LINES_WARN*100)}% of threshold)"
256
+ elif total_lines < SKILL_LINES_WARN:
257
+ score += 20
258
+ report.metrics['conciseness'] = f"Good ({total_lines} lines, {int(total_lines/SKILL_LINES_WARN*100)}% of threshold)"
259
+ elif total_lines < SKILL_LINES_ERROR:
260
+ score += 10
261
+ report.metrics['conciseness'] = f"Acceptable ({total_lines} lines, {int(total_lines/SKILL_LINES_WARN*100)}% of threshold)"
262
+ report.add_warning(f"SKILL.md is approaching length limit ({total_lines}/{SKILL_LINES_ERROR} lines)")
263
+ else:
264
+ score += 0
265
+ report.metrics['conciseness'] = f"Too Long ({total_lines} lines exceeds {SKILL_LINES_ERROR} limit)"
266
+
267
+ # 2. Description Quality (25 points)
268
+ desc_score, desc_suggestions = analyze_description_quality(frontmatter.get('description', ''))
269
+ score += desc_score
270
+ report.metrics['description_quality'] = f"{desc_score}/25 points"
271
+ for suggestion in desc_suggestions:
272
+ report.add_recommendation(suggestion)
273
+
274
+ # 3. Best Practices (25 points)
275
+ best_practices_score = 0
276
+
277
+ # Has allowed-tools (5 points)
278
+ if 'allowed-tools' in frontmatter:
279
+ best_practices_score += 5
280
+ else:
281
+ report.add_warning("'allowed-tools' is missing. Recommend specifying minimal tools for security.")
282
+
283
+ # Has references/ directory (10 points)
284
+ resources = count_resources(skill_path)
285
+ if resources['references'] > 0:
286
+ best_practices_score += 10
287
+ report.metrics['references_count'] = resources['references']
288
+ else:
289
+ report.add_recommendation("Consider adding references/ for detailed knowledge/checklists.")
290
+
291
+ # Has scripts/ directory (5 points)
292
+ if resources['scripts'] > 0:
293
+ best_practices_score += 5
294
+ report.metrics['scripts_count'] = resources['scripts']
295
+
296
+ # Directory name matches skill name (5 points)
297
+ if skill_path.name == frontmatter.get('name', ''):
298
+ best_practices_score += 5
299
+
300
+ score += best_practices_score
301
+ report.metrics['best_practices'] = f"{best_practices_score}/25 points"
302
+
303
+ # 4. Structure Quality (20 points)
304
+ structure_score = 0
305
+
306
+ # Read SKILL.md content for structure analysis
307
+ skill_md = skill_path / 'SKILL.md'
308
+ content = skill_md.read_text(encoding="utf-8-sig").lower()
309
+
310
+ # Has decision tree or workflow (8 points)
311
+ if 'decision tree' in content or 'workflow' in content or '##' in content:
312
+ structure_score += 8
313
+ else:
314
+ report.add_recommendation("Add a decision tree or workflow section for clarity.")
315
+
316
+ # Has output contract/format (7 points)
317
+ if 'output' in content and ('contract' in content or 'format' in content or 'structure' in content):
318
+ structure_score += 7
319
+ else:
320
+ report.add_recommendation("Define clear output contract/format for predictability.")
321
+
322
+ # Has troubleshooting/FAQ (5 points)
323
+ if 'troubleshoot' in content or 'faq' in content or 'common' in content:
324
+ structure_score += 5
325
+
326
+ score += structure_score
327
+ report.metrics['structure'] = f"{structure_score}/20 points"
328
+
329
+ return min(score, 100) # Cap at 100
330
+
331
+
332
+ def validate_skill(skill_path: str, verbose: bool = False) -> Tuple[bool, str]:
333
+ """Enhanced validation with quality diagnostics"""
334
+ skill_path = Path(skill_path)
335
+ report = SkillQualityReport()
336
+
337
+ # Check SKILL.md exists
338
+ skill_md = skill_path / 'SKILL.md'
339
+ if not skill_md.exists():
340
+ report.add_error("SKILL.md not found")
341
+ return False, report.format_output(verbose)
342
+
343
+ # Read and validate encoding
344
+ try:
345
+ content = skill_md.read_text(encoding="utf-8-sig")
346
+ except UnicodeDecodeError:
347
+ report.add_error("SKILL.md must be UTF-8 encoded (optionally with BOM)")
348
+ return False, report.format_output(verbose)
349
+
350
+ # Check frontmatter
351
+ if not content.startswith('---'):
352
+ report.add_error("No YAML frontmatter found")
353
+ return False, report.format_output(verbose)
354
+
355
+ # Extract frontmatter
356
+ match = re.match(r'^---\r?\n(.*?)\r?\n---', content, re.DOTALL)
357
+ if not match:
358
+ report.add_error("Invalid frontmatter format")
359
+ return False, report.format_output(verbose)
360
+
361
+ frontmatter_text = match.group(1)
362
+
363
+ # Parse YAML frontmatter
364
+ if yaml is None:
365
+ report.add_error(
366
+ "Missing dependency: PyYAML. "
367
+ "Install with: python -m pip install -r .claude/skills/skill-expert-skills/scripts/requirements.txt"
368
+ )
369
+ return False, report.format_output(verbose)
370
+
371
+ try:
372
+ frontmatter = yaml.safe_load(frontmatter_text)
373
+ if not isinstance(frontmatter, dict):
374
+ report.add_error("Frontmatter must be a YAML dictionary")
375
+ return False, report.format_output(verbose)
376
+ except yaml.YAMLError as e:
377
+ report.add_error(f"Invalid YAML in frontmatter: {e}")
378
+ return False, report.format_output(verbose)
379
+
380
+ # Validate frontmatter fields
381
+ ALLOWED_PROPERTIES = {'name', 'description', 'license', 'allowed-tools', 'metadata', 'compatibility'}
382
+ unexpected_keys = set(frontmatter.keys()) - ALLOWED_PROPERTIES
383
+ if unexpected_keys:
384
+ report.add_error(
385
+ f"Unexpected key(s) in frontmatter: {', '.join(sorted(unexpected_keys))}. "
386
+ f"Allowed: {', '.join(sorted(ALLOWED_PROPERTIES))}"
387
+ )
388
+
389
+ # Check required fields
390
+ if 'name' not in frontmatter:
391
+ report.add_error("Missing 'name' in frontmatter")
392
+ if 'description' not in frontmatter:
393
+ report.add_error("Missing 'description' in frontmatter")
394
+
395
+ # If errors so far, return early
396
+ if report.errors:
397
+ return False, report.format_output(verbose)
398
+
399
+ # Validate name
400
+ name = frontmatter.get('name', '').strip()
401
+ if name:
402
+ if not isinstance(name, str):
403
+ report.add_error(f"Name must be a string, got {type(name).__name__}")
404
+ elif not re.match(r'^[a-z0-9-]+$', name):
405
+ report.add_error(f"Name '{name}' should be hyphen-case (lowercase, digits, hyphens only)")
406
+ elif name.startswith('-') or name.endswith('-') or '--' in name:
407
+ report.add_error(f"Name '{name}' cannot start/end with hyphen or contain consecutive hyphens")
408
+ elif len(name) > 64:
409
+ report.add_error(f"Name is too long ({len(name)} chars). Max 64 chars.")
410
+
411
+ # Directory name check
412
+ if skill_path.name != name:
413
+ report.add_error(f"Directory name '{skill_path.name}' must match frontmatter name '{name}'")
414
+
415
+ # Validate description
416
+ description = frontmatter.get('description', '').strip()
417
+ if description:
418
+ if not isinstance(description, str):
419
+ report.add_error(f"Description must be a string, got {type(description).__name__}")
420
+ elif '<' in description or '>' in description:
421
+ report.add_error("Description cannot contain angle brackets (< or >)")
422
+ elif len(description) > 1024:
423
+ report.add_error(f"Description is too long ({len(description)} chars). Max 1024 chars.")
424
+
425
+ # If errors, return early
426
+ if report.errors:
427
+ return False, report.format_output(verbose)
428
+
429
+ # Calculate metrics
430
+ total_lines = content.count('\n') + 1
431
+ report.metrics['skill_md_lines'] = total_lines
432
+
433
+ # Count resources
434
+ resources = count_resources(skill_path)
435
+
436
+ # Hard error: too long
437
+ if total_lines >= SKILL_LINES_ERROR:
438
+ report.add_error(
439
+ f"SKILL.md is too long ({total_lines} lines, max {SKILL_LINES_ERROR}). "
440
+ f"Move detailed content to references/"
441
+ )
442
+ return False, report.format_output(verbose)
443
+
444
+ # Check for problematic special characters in backticks
445
+ problematic_chars = check_problematic_special_chars(content)
446
+ for char_issue in problematic_chars:
447
+ report.add_warning(char_issue)
448
+
449
+ # Calculate quality score
450
+ report.score = calculate_quality_score(report, skill_path, frontmatter, total_lines)
451
+
452
+ # Add resource-based recommendations
453
+ if resources['references'] == 0:
454
+ report.add_recommendation("Add references/ directory for detailed documentation")
455
+ elif resources['references'] >= 10:
456
+ report.add_recommendation(f"Many reference files ({resources['references']}). Ensure good navigation in SKILL.md")
457
+
458
+ if resources['scripts'] == 0 and total_lines > 300:
459
+ report.add_recommendation("Consider extracting repetitive logic into scripts/")
460
+
461
+ # Add score-based recommendations
462
+ if report.score < 90:
463
+ if report.score < 75:
464
+ report.add_recommendation("Review examples.md in references/ for best practices")
465
+ report.add_recommendation("Run universal_validate.py to check portability")
466
+
467
+ return report.valid, report.format_output(verbose)
468
+
469
+
470
+ if __name__ == "__main__":
471
+ # Parse arguments
472
+ verbose = False
473
+ skill_dir = None
474
+
475
+ for arg in sys.argv[1:]:
476
+ if arg in ['-v', '--verbose']:
477
+ verbose = True
478
+ elif arg in ['-h', '--help']:
479
+ print("Usage: python quick_validate.py <skill_directory> [--verbose|-v]")
480
+ print("\nOptions:")
481
+ print(" -v, --verbose Show detailed metrics")
482
+ print(" -h, --help Show this help message")
483
+ sys.exit(0)
484
+ else:
485
+ skill_dir = arg
486
+
487
+ if not skill_dir:
488
+ print("Usage: python quick_validate.py <skill_directory> [--verbose|-v]")
489
+ sys.exit(1)
490
+
491
+ valid, message = validate_skill(skill_dir, verbose=verbose)
492
+ print(message)
493
+ sys.exit(0 if valid else 1)
@@ -0,0 +1,182 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Universal (cross-project) validation for Skills content.
4
+
5
+ This script enforces a *high-confidence* subset of the "cross-project universal" rule:
6
+ - It flags obvious project-specific fingerprints like absolute user paths (Windows/macOS/Linux).
7
+
8
+ It intentionally avoids over-aggressive heuristics that would create many false positives.
9
+
10
+ Usage:
11
+ python universal_validate.py <path/to/skill-folder>
12
+ Exit codes:
13
+ 0: no issues found
14
+ 1: violations found
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import re
20
+ import sys
21
+ from dataclasses import dataclass
22
+ from pathlib import Path
23
+ from typing import Iterable, List, Tuple
24
+
25
+
26
+ def _configure_stdio() -> None:
27
+ """
28
+ Avoid UnicodeEncodeError on Windows consoles (e.g., GBK) by ensuring
29
+ unencodable characters are safely replaced instead of crashing.
30
+ """
31
+ for stream in (sys.stdout, sys.stderr):
32
+ try:
33
+ stream.reconfigure(errors="replace")
34
+ except Exception:
35
+ # Some environments replace stdio with objects that don't support reconfigure().
36
+ pass
37
+
38
+
39
+ _configure_stdio()
40
+
41
+
42
+ @dataclass(frozen=True)
43
+ class Finding:
44
+ file: Path
45
+ line_no: int
46
+ kind: str
47
+ pattern_name: str
48
+ excerpt: str
49
+
50
+
51
+ def iter_text_files(skill_dir: Path) -> Iterable[Path]:
52
+ # Include Skill entry and common text/reference files.
53
+ include_names = {"SKILL.md"}
54
+ include_suffixes = {".md", ".txt", ".json", ".yaml", ".yml"}
55
+
56
+ for p in skill_dir.rglob("*"):
57
+ if not p.is_file():
58
+ continue
59
+ if p.name in include_names or p.suffix.lower() in include_suffixes:
60
+ # Skip huge binary-ish files if any mistakenly match.
61
+ # (We only include common text suffixes; this is just a final guard.)
62
+ yield p
63
+
64
+
65
+ def read_text_lines(path: Path) -> List[str]:
66
+ # Use UTF-8 with BOM support. If a file isn't UTF-8, treat as a violation because
67
+ # cross-platform skills should be portable and readable.
68
+ try:
69
+ return path.read_text(encoding="utf-8-sig").splitlines()
70
+ except UnicodeDecodeError:
71
+ return [
72
+ "UNIVERSAL_VALIDATE_ERROR: file is not UTF-8 decodable; use UTF-8 encoding for portability."
73
+ ]
74
+
75
+
76
+ def scan_lines(lines: List[str]) -> List[Tuple[int, str]]:
77
+ return [(i + 1, line) for i, line in enumerate(lines)]
78
+
79
+
80
+ ERROR_PATTERNS: List[Tuple[str, re.Pattern[str]]] = [
81
+ # Windows absolute paths: C:\Users\name\..., D:\repo\...
82
+ ("windows_drive_path", re.compile(r"(?i)\b[a-z]:\\[^ \t\r\n]+")),
83
+ # Windows UNC paths: \\server\share\...
84
+ ("windows_unc_path", re.compile(r"\\\\[^ \t\r\n]+")),
85
+ # macOS/Linux user home paths: /Users/name/... or /home/name/...
86
+ ("posix_user_home_path", re.compile(r"/(?:Users|home)/[A-Za-z0-9._-]+/[^ \t\r\n]*")),
87
+ # Tilde home paths: ~/...
88
+ ("tilde_home_path", re.compile(r"~\/[^ \t\r\n]+")),
89
+ # file:// URIs (often embed local paths)
90
+ ("file_uri", re.compile(r"(?i)\bfile:///[^\s]+")),
91
+ ]
92
+
93
+ def is_placeholder_match(match_text: str) -> bool:
94
+ """
95
+ Treat obvious placeholder examples as non-violations.
96
+
97
+ We allow patterns like `C:\\...` or `/Users/...` used as generic examples in docs.
98
+ This keeps the validator useful while avoiding self-failing documentation.
99
+ """
100
+ return "..." in match_text
101
+
102
+
103
+ def validate_universal(skill_dir: Path) -> Tuple[bool, List[Finding]]:
104
+ findings: List[Finding] = []
105
+
106
+ for file_path in iter_text_files(skill_dir):
107
+ # Skip this skill's own LICENSE file — it is legal text and not part of "skill logic".
108
+ if file_path.name.lower() == "license.txt":
109
+ continue
110
+
111
+ lines = read_text_lines(file_path)
112
+ # If file is not decodable, treat as ERROR at line 1.
113
+ if lines and lines[0].startswith("UNIVERSAL_VALIDATE_ERROR:"):
114
+ findings.append(
115
+ Finding(
116
+ file=file_path,
117
+ line_no=1,
118
+ kind="ERROR",
119
+ pattern_name="non_utf8_file",
120
+ excerpt=lines[0],
121
+ )
122
+ )
123
+ continue
124
+
125
+ for line_no, line in scan_lines(lines):
126
+ for pattern_name, pattern in ERROR_PATTERNS:
127
+ m = pattern.search(line)
128
+ if not m:
129
+ continue
130
+ if is_placeholder_match(m.group(0)):
131
+ continue
132
+ excerpt = line.strip()
133
+ if len(excerpt) > 240:
134
+ excerpt = excerpt[:237] + "..."
135
+ findings.append(
136
+ Finding(
137
+ file=file_path,
138
+ line_no=line_no,
139
+ kind="ERROR",
140
+ pattern_name=pattern_name,
141
+ excerpt=excerpt,
142
+ )
143
+ )
144
+
145
+ ok = not any(f.kind == "ERROR" for f in findings)
146
+ return ok, findings
147
+
148
+
149
+ def main() -> int:
150
+ if len(sys.argv) != 2:
151
+ print("Usage: python universal_validate.py <skill_directory>")
152
+ return 1
153
+
154
+ skill_dir = Path(sys.argv[1]).resolve()
155
+ if not skill_dir.exists() or not skill_dir.is_dir():
156
+ print(f"[ERROR] skill directory not found or not a directory: {skill_dir}")
157
+ return 1
158
+
159
+ ok, findings = validate_universal(skill_dir)
160
+ if ok:
161
+ print("[OK] Universal validation passed (no high-confidence project-specific fingerprints found).")
162
+ return 0
163
+
164
+ print("[FAIL] Universal validation failed:")
165
+ for f in findings:
166
+ rel = f.file
167
+ try:
168
+ rel = f.file.relative_to(Path.cwd())
169
+ except Exception:
170
+ pass
171
+ print(f"- {f.kind} {f.pattern_name} at {rel}:{f.line_no}: {f.excerpt}")
172
+
173
+ print("\nFix guidance:")
174
+ print("- Remove absolute user paths (C:\\..., /Users/..., /home/..., ~/...).")
175
+ print("- Replace them with cross-project, relative, or conceptual descriptions (avoid project placeholders).")
176
+ return 1
177
+
178
+
179
+ if __name__ == "__main__":
180
+ raise SystemExit(main())
181
+
182
+