@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.
Files changed (247) hide show
  1. package/agents/agents/creative-copywriter.md +212 -0
  2. package/agents/agents/dario-amodei.md +135 -0
  3. package/agents/agents/doc-simplifier.md +63 -0
  4. package/agents/agents/kotlin-pro.md +433 -0
  5. package/agents/agents/red-team.md +136 -0
  6. package/agents/agents/sam-altman.md +121 -0
  7. package/agents/agents/seo-manager.md +184 -0
  8. package/package.json +1 -1
  9. package/skills/skillkit-help/SKILL.md +81 -0
  10. package/skills/skillkit-help/knowledge/application/09-case-studies.md +257 -0
  11. package/skills/skillkit-help/knowledge/application/12-testing-and-validation.md +276 -0
  12. package/skills/skillkit-help/knowledge/foundation/01-why-skills-exist.md +246 -0
  13. package/skills/skillkit-help/knowledge/foundation/02-skills-vs-subagents-comparison.md +312 -0
  14. package/skills/skillkit-help/knowledge/foundation/03-skills-vs-subagents-decision-tree.md +346 -0
  15. package/skills/skillkit-help/knowledge/foundation/06-platform-constraints.md +237 -0
  16. package/skills/skillkit-help/knowledge/foundation/08-when-not-to-use-skills.md +270 -0
  17. package/skills/skillkit-help/template/SKILL.md +52 -0
  18. package/skills/skills/adversarial-review/SKILL.md +219 -0
  19. package/skills/skills/baby-education/SKILL.md +260 -0
  20. package/skills/skills/baby-education/references/advanced-techniques.md +323 -0
  21. package/skills/skills/baby-education/references/transformations.md +345 -0
  22. package/skills/skills/been-there-done-that/SKILL.md +455 -0
  23. package/skills/skills/been-there-done-that/references/analysis-patterns.md +162 -0
  24. package/skills/skills/been-there-done-that/references/git-commands.md +132 -0
  25. package/skills/skills/been-there-done-that/references/tree-insertion-logic.md +145 -0
  26. package/skills/skills/coolhunter/SKILL.md +270 -0
  27. package/skills/skills/coolhunter/assets/elicitation-methods.csv +51 -0
  28. package/skills/skills/coolhunter/knowledge/elicitation-methods.md +312 -0
  29. package/skills/skills/coolhunter/references/workflow-execution.md +238 -0
  30. package/skills/skills/coolhunter/workflow-plan-coolhunter.md +232 -0
  31. package/skills/skills/creative-copywriting/SKILL.md +324 -0
  32. package/skills/skills/creative-copywriting/databases/README.md +60 -0
  33. package/skills/skills/creative-copywriting/databases/carousel-structures.csv +16 -0
  34. package/skills/skills/creative-copywriting/databases/emotional-arcs.csv +11 -0
  35. package/skills/skills/creative-copywriting/databases/hook-formulas.csv +51 -0
  36. package/skills/skills/creative-copywriting/databases/power-words.csv +201 -0
  37. package/skills/skills/creative-copywriting/databases/psychological-triggers.csv +21 -0
  38. package/skills/skills/creative-copywriting/databases/read-more-patterns.csv +26 -0
  39. package/skills/skills/creative-copywriting/databases/swipe-triggers.csv +31 -0
  40. package/skills/skills/creative-copywriting/references/carousel-psychology.md +223 -0
  41. package/skills/skills/creative-copywriting/references/hook-anatomy.md +169 -0
  42. package/skills/skills/creative-copywriting/references/power-word-science.md +134 -0
  43. package/skills/skills/creative-copywriting/references/storytelling-frameworks.md +157 -0
  44. package/skills/skills/diverse-content-gen/SKILL.md +201 -0
  45. package/skills/skills/diverse-content-gen/references/advanced-techniques.md +320 -0
  46. package/skills/skills/diverse-content-gen/references/research-findings.md +379 -0
  47. package/skills/skills/diverse-content-gen/references/task-workflows.md +241 -0
  48. package/skills/skills/diverse-content-gen/references/tool-integration.md +419 -0
  49. package/skills/skills/diverse-content-gen/references/troubleshooting.md +426 -0
  50. package/skills/skills/diverse-content-gen/references/vs-core-technique.md +240 -0
  51. package/skills/skills/framework-critical-thinking/SKILL.md +220 -0
  52. package/skills/skills/framework-critical-thinking/references/bias_detector.md +375 -0
  53. package/skills/skills/framework-critical-thinking/references/fallback_handler.md +239 -0
  54. package/skills/skills/framework-critical-thinking/references/memory_curator.md +161 -0
  55. package/skills/skills/framework-critical-thinking/references/metacognitive_monitor.md +297 -0
  56. package/skills/skills/framework-critical-thinking/references/producer_critic_orchestrator.md +333 -0
  57. package/skills/skills/framework-critical-thinking/references/reasoning_router.md +235 -0
  58. package/skills/skills/framework-critical-thinking/references/reasoning_validator.md +97 -0
  59. package/skills/skills/framework-critical-thinking/references/reflection_trigger.md +78 -0
  60. package/skills/skills/framework-critical-thinking/references/self_verification.md +388 -0
  61. package/skills/skills/framework-critical-thinking/references/uncertainty_quantifier.md +207 -0
  62. package/skills/skills/framework-initiative/SKILL.md +231 -0
  63. package/skills/skills/framework-initiative/references/examples.md +150 -0
  64. package/skills/skills/framework-initiative/references/impact-analysis.md +157 -0
  65. package/skills/skills/framework-initiative/references/intent-patterns.md +145 -0
  66. package/skills/skills/framework-initiative/references/star-framework.md +165 -0
  67. package/skills/skills/humanize-docs/SKILL.md +203 -0
  68. package/skills/skills/humanize-docs/references/advanced-techniques.md +13 -0
  69. package/skills/skills/humanize-docs/references/core-transformations.md +368 -0
  70. package/skills/skills/humanize-docs/references/detection-patterns.md +400 -0
  71. package/skills/skills/humanize-docs/references/examples-gallery.md +374 -0
  72. package/skills/skills/imagine/SKILL.md +190 -0
  73. package/skills/skills/imagine/references/artstyle-corporate-memphis.md +625 -0
  74. package/skills/skills/imagine/references/artstyle-crewdson-hyperrealism.md +295 -0
  75. package/skills/skills/imagine/references/artstyle-iphone-social-media.md +426 -0
  76. package/skills/skills/imagine/references/artstyle-sciencesaru.md +276 -0
  77. package/skills/skills/pre-deploy-checklist/README.md +26 -0
  78. package/skills/skills/pre-deploy-checklist/SKILL.md +153 -0
  79. package/skills/skills/pre-deploy-checklist/references/checklist-categories.md +174 -0
  80. package/skills/skills/pre-deploy-checklist/references/domain-prompts.md +216 -0
  81. package/skills/skills/prompt-engineering/SKILL.md +209 -0
  82. package/skills/skills/prompt-engineering/references/advanced-combinations.md +444 -0
  83. package/skills/skills/prompt-engineering/references/chain-of-thought.md +140 -0
  84. package/skills/skills/prompt-engineering/references/decision_matrix.md +220 -0
  85. package/skills/skills/prompt-engineering/references/few-shot.md +346 -0
  86. package/skills/skills/prompt-engineering/references/json-format.md +270 -0
  87. package/skills/skills/prompt-engineering/references/natural-language.md +420 -0
  88. package/skills/skills/prompt-engineering/references/pitfalls.md +365 -0
  89. package/skills/skills/prompt-engineering/references/prompt-chaining.md +498 -0
  90. package/skills/skills/prompt-engineering/references/react.md +108 -0
  91. package/skills/skills/prompt-engineering/references/self-consistency.md +322 -0
  92. package/skills/skills/prompt-engineering/references/tree-of-thoughts.md +386 -0
  93. package/skills/skills/prompt-engineering/references/xml-format.md +220 -0
  94. package/skills/skills/prompt-engineering/references/yaml-format.md +488 -0
  95. package/skills/skills/prompt-engineering/references/zero-shot.md +74 -0
  96. package/skills/skills/quick-spec/SKILL.md +280 -0
  97. package/skills/skills/quick-spec/assets/tech-spec-template.md +74 -0
  98. package/skills/skills/quick-spec/references/step-01-understand.md +189 -0
  99. package/skills/skills/quick-spec/references/step-02-investigate.md +144 -0
  100. package/skills/skills/quick-spec/references/step-03-generate.md +128 -0
  101. package/skills/skills/quick-spec/references/step-04-review.md +173 -0
  102. package/skills/skills/quick-spec/tests/__pycache__/test_skill.cpython-314-pytest-9.0.2.pyc +0 -0
  103. package/skills/skills/quick-spec/tests/test_scenarios.md +83 -0
  104. package/skills/skills/quick-spec/tests/test_skill.py +136 -0
  105. package/skills/skills/readme-expert/SKILL.md +538 -0
  106. package/skills/skills/readme-expert/knowledge/INDEX.md +192 -0
  107. package/skills/skills/readme-expert/knowledge/application/quality-standards.md +470 -0
  108. package/skills/skills/readme-expert/knowledge/application/script-executor.md +604 -0
  109. package/skills/skills/readme-expert/knowledge/application/template-library.md +822 -0
  110. package/skills/skills/readme-expert/knowledge/foundation/codebase-scanner.md +361 -0
  111. package/skills/skills/readme-expert/knowledge/foundation/validation-checklist.md +481 -0
  112. package/skills/skills/red-teaming/SKILL.md +321 -0
  113. package/skills/skills/red-teaming/references/ai-llm-redteam.md +517 -0
  114. package/skills/skills/red-teaming/references/attack-techniques.md +410 -0
  115. package/skills/skills/red-teaming/references/cybersecurity-redteam.md +383 -0
  116. package/skills/skills/red-teaming/references/tools-frameworks.md +446 -0
  117. package/skills/skills/releasing/.skillkit-mode +1 -0
  118. package/skills/skills/releasing/SKILL.md +225 -0
  119. package/skills/skills/releasing/references/version-detection.md +108 -0
  120. package/skills/skills/screenwriter/SKILL.md +273 -0
  121. package/skills/skills/screenwriter/references/advanced-techniques.md +216 -0
  122. package/skills/skills/screenwriter/references/pipeline-integration.md +266 -0
  123. package/skills/skills/skillkit/.claude/settings.local.json +7 -0
  124. package/skills/skills/skillkit/.claude-plugin/plugin.json +27 -0
  125. package/skills/skills/skillkit/CHANGELOG.md +484 -0
  126. package/skills/skills/skillkit/SKILL.md +511 -0
  127. package/skills/skills/skillkit/commands/skillkit.md +6 -0
  128. package/skills/skills/skillkit/commands/validate-plan.md +6 -0
  129. package/skills/skills/skillkit/commands/verify.md +6 -0
  130. package/skills/skills/skillkit/knowledge/INDEX.md +352 -0
  131. package/skills/skills/skillkit/knowledge/application/09-case-studies.md +257 -0
  132. package/skills/skills/skillkit/knowledge/application/10-technical-architecture.md +324 -0
  133. package/skills/skills/skillkit/knowledge/application/11-adoption-strategy.md +267 -0
  134. package/skills/skills/skillkit/knowledge/application/12-testing-and-validation.md +276 -0
  135. package/skills/skills/skillkit/knowledge/application/13-competitive-landscape.md +198 -0
  136. package/skills/skills/skillkit/knowledge/foundation/01-why-skills-exist.md +246 -0
  137. package/skills/skills/skillkit/knowledge/foundation/02-skills-vs-subagents-comparison.md +312 -0
  138. package/skills/skills/skillkit/knowledge/foundation/03-skills-vs-subagents-decision-tree.md +346 -0
  139. package/skills/skills/skillkit/knowledge/foundation/04-hybrid-patterns.md +308 -0
  140. package/skills/skills/skillkit/knowledge/foundation/05-token-economics.md +275 -0
  141. package/skills/skills/skillkit/knowledge/foundation/06-platform-constraints.md +237 -0
  142. package/skills/skills/skillkit/knowledge/foundation/07-security-concerns.md +322 -0
  143. package/skills/skills/skillkit/knowledge/foundation/08-when-not-to-use-skills.md +270 -0
  144. package/skills/skills/skillkit/knowledge/plugin-guide.md +614 -0
  145. package/skills/skills/skillkit/knowledge/tools/14-validation-tools-guide.md +150 -0
  146. package/skills/skills/skillkit/knowledge/tools/15-cost-tools-guide.md +157 -0
  147. package/skills/skills/skillkit/knowledge/tools/16-security-tools-guide.md +122 -0
  148. package/skills/skills/skillkit/knowledge/tools/17-pattern-tools-guide.md +161 -0
  149. package/skills/skills/skillkit/knowledge/tools/18-decision-helper-guide.md +243 -0
  150. package/skills/skills/skillkit/knowledge/tools/19-test-generator-guide.md +275 -0
  151. package/skills/skills/skillkit/knowledge/tools/20-split-skill-guide.md +149 -0
  152. package/skills/skills/skillkit/knowledge/tools/21-quality-scorer-guide.md +226 -0
  153. package/skills/skills/skillkit/knowledge/tools/22-migration-helper-guide.md +356 -0
  154. package/skills/skills/skillkit/knowledge/tools/23-subagent-creation-guide.md +448 -0
  155. package/skills/skills/skillkit/knowledge/tools/24-behavioral-testing-guide.md +122 -0
  156. package/skills/skills/skillkit/references/proposal-generation.md +982 -0
  157. package/skills/skills/skillkit/references/rationalization-catalog.md +75 -0
  158. package/skills/skills/skillkit/references/research-methodology.md +661 -0
  159. package/skills/skills/skillkit/references/section-2-full-creation-workflow.md +452 -0
  160. package/skills/skills/skillkit/references/section-3-validation-workflow-existing-skill.md +63 -0
  161. package/skills/skills/skillkit/references/section-4-decision-workflow-skills-vs-subagents.md +64 -0
  162. package/skills/skills/skillkit/references/section-5-migration-workflow-doc-to-skill.md +58 -0
  163. package/skills/skills/skillkit/references/section-6-subagent-creation-workflow.md +499 -0
  164. package/skills/skills/skillkit/references/section-7-knowledge-reference-map.md +72 -0
  165. package/skills/skills/skillkit/scripts/__pycache__/decision_helper.cpython-314.pyc +0 -0
  166. package/skills/skills/skillkit/scripts/__pycache__/quick_validate.cpython-312.pyc +0 -0
  167. package/skills/skills/skillkit/scripts/__pycache__/quick_validate.cpython-314.pyc +0 -0
  168. package/skills/skills/skillkit/scripts/__pycache__/test_generator.cpython-314-pytest-9.0.2.pyc +0 -0
  169. package/skills/skills/skillkit/scripts/decision_helper.py +799 -0
  170. package/skills/skills/skillkit/scripts/init_skill.py +400 -0
  171. package/skills/skills/skillkit/scripts/init_subagent.py +231 -0
  172. package/skills/skills/skillkit/scripts/migration_helper.py +669 -0
  173. package/skills/skills/skillkit/scripts/package_skill.py +211 -0
  174. package/skills/skills/skillkit/scripts/pattern_detector.py +381 -0
  175. package/skills/skills/skillkit/scripts/pattern_detector_new.py +382 -0
  176. package/skills/skills/skillkit/scripts/pressure_tester.py +157 -0
  177. package/skills/skills/skillkit/scripts/quality_scorer.py +999 -0
  178. package/skills/skills/skillkit/scripts/quick_validate.py +100 -0
  179. package/skills/skills/skillkit/scripts/security_scanner.py +474 -0
  180. package/skills/skills/skillkit/scripts/split_skill.py +540 -0
  181. package/skills/skills/skillkit/scripts/test_generator.py +695 -0
  182. package/skills/skills/skillkit/scripts/token_estimator.py +493 -0
  183. package/skills/skills/skillkit/scripts/utils/__init__.py +49 -0
  184. package/skills/skills/skillkit/scripts/utils/__pycache__/__init__.cpython-312.pyc +0 -0
  185. package/skills/skills/skillkit/scripts/utils/__pycache__/__init__.cpython-314.pyc +0 -0
  186. package/skills/skills/skillkit/scripts/utils/__pycache__/budget_tracker.cpython-312.pyc +0 -0
  187. package/skills/skills/skillkit/scripts/utils/__pycache__/budget_tracker.cpython-314.pyc +0 -0
  188. package/skills/skills/skillkit/scripts/utils/__pycache__/output_formatter.cpython-312.pyc +0 -0
  189. package/skills/skills/skillkit/scripts/utils/__pycache__/output_formatter.cpython-314.pyc +0 -0
  190. package/skills/skills/skillkit/scripts/utils/__pycache__/reference_validator.cpython-312.pyc +0 -0
  191. package/skills/skills/skillkit/scripts/utils/__pycache__/reference_validator.cpython-314.pyc +0 -0
  192. package/skills/skills/skillkit/scripts/utils/budget_tracker.py +388 -0
  193. package/skills/skills/skillkit/scripts/utils/output_formatter.py +263 -0
  194. package/skills/skills/skillkit/scripts/utils/reference_validator.py +401 -0
  195. package/skills/skills/skillkit/scripts/validate_skill.py +594 -0
  196. package/skills/skills/skillkit/tests/test_behavioral.py +39 -0
  197. package/skills/skills/skillkit/tests/test_scenarios.md +83 -0
  198. package/skills/skills/skillkit/tests/test_skill.py +136 -0
  199. package/skills/skills/skillkit-help/SKILL.md +81 -0
  200. package/skills/skills/skillkit-help/knowledge/application/09-case-studies.md +257 -0
  201. package/skills/skills/skillkit-help/knowledge/application/12-testing-and-validation.md +276 -0
  202. package/skills/skills/skillkit-help/knowledge/foundation/01-why-skills-exist.md +246 -0
  203. package/skills/skills/skillkit-help/knowledge/foundation/02-skills-vs-subagents-comparison.md +312 -0
  204. package/skills/skills/skillkit-help/knowledge/foundation/03-skills-vs-subagents-decision-tree.md +346 -0
  205. package/skills/skills/skillkit-help/knowledge/foundation/06-platform-constraints.md +237 -0
  206. package/skills/skills/skillkit-help/knowledge/foundation/08-when-not-to-use-skills.md +270 -0
  207. package/skills/skills/skillkit-help/template/SKILL.md +52 -0
  208. package/skills/skills/social-media-seo/SKILL.md +278 -0
  209. package/skills/skills/social-media-seo/databases/caption-styles.csv +31 -0
  210. package/skills/skills/social-media-seo/databases/engagement-tactics.csv +16 -0
  211. package/skills/skills/social-media-seo/databases/hashtag-strategies.csv +21 -0
  212. package/skills/skills/social-media-seo/databases/hook-formulas.csv +26 -0
  213. package/skills/skills/social-media-seo/databases/keyword-clusters.csv +11 -0
  214. package/skills/skills/social-media-seo/databases/thread-structures.csv +26 -0
  215. package/skills/skills/social-media-seo/databases/viral-patterns.csv +21 -0
  216. package/skills/skills/social-media-seo/references/analytics-guide.md +321 -0
  217. package/skills/skills/social-media-seo/references/instagram-seo.md +235 -0
  218. package/skills/skills/social-media-seo/references/threads-seo.md +305 -0
  219. package/skills/skills/social-media-seo/references/x-twitter-seo.md +337 -0
  220. package/skills/skills/social-media-seo/scripts/query_database.py +191 -0
  221. package/skills/skills/storyteller/SKILL.md +241 -0
  222. package/skills/skills/storyteller/references/transformation-methodology.md +293 -0
  223. package/skills/skills/storyteller/references/visual-vocabulary.md +177 -0
  224. package/skills/skills/thread-pro/SKILL.md +162 -0
  225. package/skills/skills/thread-pro/anti-ai-patterns.md +120 -0
  226. package/skills/skills/thread-pro/hook-formulas.md +138 -0
  227. package/skills/skills/thread-pro/references/anti-ai-patterns.md +120 -0
  228. package/skills/skills/thread-pro/references/hook-formulas.md +138 -0
  229. package/skills/skills/thread-pro/references/thread-structures.md +240 -0
  230. package/skills/skills/thread-pro/references/voice-injection.md +130 -0
  231. package/skills/skills/thread-pro/thread-structures.md +240 -0
  232. package/skills/skills/thread-pro/voice-injection.md +130 -0
  233. package/skills/skills/tinkering/SKILL.md +251 -0
  234. package/skills/skills/tinkering/references/graduation-checklist.md +100 -0
  235. package/skills/skills/validate-plan/.skillkit-mode +1 -0
  236. package/skills/skills/validate-plan/SKILL.md +406 -0
  237. package/skills/skills/validate-plan/references/dry-principles.md +251 -0
  238. package/skills/skills/validate-plan/references/gap-analysis-guide.md +320 -0
  239. package/skills/skills/validate-plan/references/tdd-patterns.md +413 -0
  240. package/skills/skills/validate-plan/references/yagni-checklist.md +330 -0
  241. package/skills/skills/verify-before-ship/.skillkit-mode +1 -0
  242. package/skills/skills/verify-before-ship/SKILL.md +116 -0
  243. package/skills/skills/verify-before-ship/references/anti-rationalization.md +212 -0
  244. package/skills/skills/verify-before-ship/references/verification-gates.md +305 -0
  245. package/skills-manifest.json +8 -2
  246. package/src/picker.js +11 -5
  247. package/src/picker.test.js +36 -1
@@ -0,0 +1,695 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Auto-generate comprehensive test scenarios for skills.
4
+ Based on skill description and validation requirements.
5
+
6
+ v1.2 Update: Parameter standardization
7
+ - Renamed --format to --test-format (test framework choice)
8
+ - Renamed --output to --format (output style)
9
+ - Backward compatibility maintained for --output (deprecated)
10
+
11
+ v2 Update: Legacy mode deprecation
12
+ - Structural-only generation (without --behavioral) is deprecated
13
+ - Preferred: --behavioral with --test-format pytest
14
+
15
+ v2.1 Note: --behavioral generates test scaffolds only (no pressure_tester.py dependency).
16
+ Real behavioral validation uses the subagent dispatch protocol in section-2.
17
+
18
+ References: File 12 (testing best practices)
19
+ """
20
+
21
+ import re
22
+ import json
23
+ import argparse
24
+ import warnings
25
+ import sys
26
+ from pathlib import Path
27
+ from typing import List, Dict, Optional
28
+
29
+ class TestGenerator:
30
+ """Generate test scenarios from skill description."""
31
+
32
+ def __init__(
33
+ self,
34
+ skill_path: str,
35
+ coverage: str = 'standard',
36
+ test_format: str = 'pytest',
37
+ output_format: str = 'text',
38
+ behavioral: bool = False
39
+ ):
40
+ """
41
+ Initialize test generator.
42
+
43
+ Args:
44
+ skill_path: Path to skill directory
45
+ coverage: 'basic', 'standard', or 'comprehensive'
46
+ test_format: 'pytest', 'unittest', or 'plain'
47
+ output_format: 'text' or 'json' (agent-layer)
48
+
49
+ References: File 12 (testing best practices)
50
+ """
51
+ self.skill_path = Path(skill_path)
52
+ self.coverage = coverage
53
+ self.test_format = test_format
54
+ self.output_format = output_format
55
+ self.skill_md_content = None
56
+ self.behavioral = behavioral
57
+ self.skill_name = None
58
+ self.capabilities = []
59
+ self.test_scenarios = []
60
+
61
+ # ========== PARSING ==========
62
+
63
+ def parse_skill_description(self) -> Dict:
64
+ """
65
+ Parse SKILL.md to extract testable capabilities.
66
+
67
+ Extracts:
68
+ - Skill name (from frontmatter)
69
+ - Main capabilities (from description)
70
+ - Trigger conditions (WHEN clauses)
71
+ - Example usages (if present)
72
+
73
+ Returns:
74
+ Dict with parsed information
75
+
76
+ Raises:
77
+ FileNotFoundError: If SKILL.md doesn't exist
78
+
79
+ References: File 02 (description structure)
80
+ """
81
+ skill_md = self.skill_path / "SKILL.md"
82
+ if not skill_md.exists():
83
+ raise FileNotFoundError(f"SKILL.md not found in {self.skill_path}")
84
+
85
+ with open(skill_md, encoding='utf-8') as f:
86
+ self.skill_md_content = f.read()
87
+
88
+ # Parse YAML frontmatter
89
+ frontmatter = self._extract_frontmatter()
90
+ self.skill_name = frontmatter.get('name', 'unknown')
91
+
92
+ # Parse capabilities
93
+ description = frontmatter.get('description', '')
94
+ self.capabilities = self._extract_capabilities(description, self.skill_md_content)
95
+
96
+ return {
97
+ 'name': self.skill_name,
98
+ 'capabilities': self.capabilities,
99
+ 'description': description
100
+ }
101
+
102
+ def _extract_frontmatter(self) -> Dict:
103
+ """
104
+ Extract YAML frontmatter from SKILL.md.
105
+
106
+ Returns:
107
+ Dict with frontmatter key-value pairs
108
+ """
109
+ pattern = r'^---\n(.*?)\n---'
110
+ match = re.search(pattern, self.skill_md_content, re.DOTALL)
111
+ if not match:
112
+ return {}
113
+
114
+ # Simple YAML parsing (key: value)
115
+ frontmatter = {}
116
+ for line in match.group(1).split('\n'):
117
+ if ':' in line:
118
+ key, value = line.split(':', 1)
119
+ frontmatter[key.strip()] = value.strip().strip('"\'')
120
+
121
+ return frontmatter
122
+
123
+ def _extract_capabilities(self, description: str, content: str) -> List[str]:
124
+ """
125
+ Extract individual capabilities from description and content.
126
+
127
+ Looks for:
128
+ - Bulleted capabilities in description
129
+ - WHEN/IF trigger clauses
130
+ - Section headers indicating features
131
+
132
+ Args:
133
+ description: Skill description from frontmatter
134
+ content: Full SKILL.md content
135
+
136
+ Returns:
137
+ List of capability descriptions
138
+ """
139
+ capabilities = []
140
+
141
+ # Extract from description bullets
142
+ for line in description.split('\n'):
143
+ if line.strip().startswith(('-', '*', '•')):
144
+ cap = line.strip().lstrip('-*• ')
145
+ if cap and len(cap) > 10: # Meaningful capability
146
+ capabilities.append(cap)
147
+
148
+ # Extract WHEN clauses
149
+ when_pattern = r'(?:when|if|for)\s+(.{20,100})'
150
+ for match in re.finditer(when_pattern, content, re.IGNORECASE):
151
+ cap = match.group(1).strip()
152
+ if cap not in capabilities:
153
+ capabilities.append(cap)
154
+
155
+ # If no capabilities found, use generic
156
+ if not capabilities:
157
+ capabilities = ["Basic functionality"]
158
+
159
+ return capabilities[:10] # Limit to 10 capabilities
160
+
161
+ # ========== TEST SCENARIO GENERATION ==========
162
+
163
+ def generate_test_scenarios(self) -> List[Dict]:
164
+ """
165
+ Generate test scenarios based on coverage level.
166
+
167
+ Returns:
168
+ List of test scenario dicts with:
169
+ - description: What to test
170
+ - priority: P0 (critical), P1 (high), P2 (medium)
171
+ - category: functional, edge_case, error_handling
172
+ - expected_result: Expected outcome
173
+
174
+ References: File 12 (test prioritization)
175
+ """
176
+ scenarios = []
177
+
178
+ # P0: Critical functional tests (always included)
179
+ scenarios.extend(self._generate_functional_tests())
180
+
181
+ if self.coverage in ['standard', 'comprehensive']:
182
+ # P1: Edge cases
183
+ scenarios.extend(self._generate_edge_case_tests())
184
+
185
+ if self.coverage == 'comprehensive':
186
+ # P2: Error handling and performance
187
+ scenarios.extend(self._generate_error_tests())
188
+ scenarios.extend(self._generate_performance_tests())
189
+
190
+ self.test_scenarios = scenarios
191
+ return scenarios
192
+
193
+ def _generate_functional_tests(self) -> List[Dict]:
194
+ """Generate P0 critical functional tests."""
195
+ tests = []
196
+
197
+ # One functional test per capability
198
+ for cap in self.capabilities:
199
+ tests.append({
200
+ 'description': f"Test {cap}",
201
+ 'priority': 'P0',
202
+ 'category': 'functional',
203
+ 'expected_result': f"Skill successfully handles: {cap}",
204
+ 'test_data': 'valid_input'
205
+ })
206
+
207
+ # Always test basic invocation
208
+ if not any('invocation' in t['description'].lower() for t in tests):
209
+ tests.insert(0, {
210
+ 'description': "Test basic skill invocation",
211
+ 'priority': 'P0',
212
+ 'category': 'functional',
213
+ 'expected_result': "Skill loads and responds to trigger",
214
+ 'test_data': 'minimal_valid'
215
+ })
216
+
217
+ return tests
218
+
219
+ def _generate_edge_case_tests(self) -> List[Dict]:
220
+ """Generate P1 edge case tests."""
221
+ return [
222
+ {
223
+ 'description': "Test with minimal input",
224
+ 'priority': 'P1',
225
+ 'category': 'edge_case',
226
+ 'expected_result': "Graceful handling of minimal valid input",
227
+ 'test_data': 'minimal'
228
+ },
229
+ {
230
+ 'description': "Test with maximum/complex input",
231
+ 'priority': 'P1',
232
+ 'category': 'edge_case',
233
+ 'expected_result': "Proper handling of complex scenarios",
234
+ 'test_data': 'complex'
235
+ }
236
+ ]
237
+
238
+ def _generate_error_tests(self) -> List[Dict]:
239
+ """Generate P2 error handling tests."""
240
+ return [
241
+ {
242
+ 'description': "Test invalid input handling",
243
+ 'priority': 'P2',
244
+ 'category': 'error_handling',
245
+ 'expected_result': "Clear error message, no crash",
246
+ 'test_data': 'invalid'
247
+ },
248
+ {
249
+ 'description': "Test missing data handling",
250
+ 'priority': 'P2',
251
+ 'category': 'error_handling',
252
+ 'expected_result': "Appropriate fallback behavior",
253
+ 'test_data': 'missing'
254
+ }
255
+ ]
256
+
257
+ def _generate_performance_tests(self) -> List[Dict]:
258
+ """Generate P2 performance tests."""
259
+ return [
260
+ {
261
+ 'description': "Test response time",
262
+ 'priority': 'P2',
263
+ 'category': 'performance',
264
+ 'expected_result': "Response within acceptable time (<2s typical)",
265
+ 'test_data': 'typical'
266
+ }
267
+ ]
268
+
269
+ # ========== OUTPUT GENERATION ==========
270
+
271
+ def generate_test_documentation(self, output_path: Path):
272
+ """
273
+ Generate human-readable test documentation.
274
+
275
+ Creates a markdown file with:
276
+ - Test overview
277
+ - Scenarios by priority
278
+ - Setup instructions
279
+
280
+ Args:
281
+ output_path: Path to write documentation
282
+ """
283
+ lines = []
284
+ lines.append(f"# Test Scenarios: {self.skill_name}\n")
285
+ lines.append(f"**Generated:** Auto-generated from SKILL.md")
286
+ lines.append(f"**Coverage:** {self.coverage}\n")
287
+
288
+ # Group by priority
289
+ for priority in ['P0', 'P1', 'P2']:
290
+ priority_scenarios = [s for s in self.test_scenarios if s['priority'] == priority]
291
+ if not priority_scenarios:
292
+ continue
293
+
294
+ lines.append(f"\n## {priority} Tests ({len(priority_scenarios)})\n")
295
+ for scenario in priority_scenarios:
296
+ lines.append(f"### {scenario['description']}")
297
+ lines.append(f"- **Category:** {scenario['category']}")
298
+ lines.append(f"- **Expected:** {scenario['expected_result']}")
299
+ lines.append(f"- **Test Data:** {scenario['test_data']}\n")
300
+
301
+ # Setup instructions
302
+ lines.append("\n## Setup\n")
303
+ lines.append("1. Install dependencies: `pip install pytest` (or unittest)")
304
+ lines.append("2. Review test scenarios above")
305
+ lines.append("3. Implement test logic in test files")
306
+ lines.append("4. Run tests: `pytest tests/`\n")
307
+
308
+ with open(output_path, 'w', encoding='utf-8') as f:
309
+ f.write('\n'.join(lines))
310
+
311
+ def generate_pytest_implementation(self, output_path: Path):
312
+ """Generate pytest test implementation."""
313
+ lines = []
314
+ lines.append("\"\"\"")
315
+ lines.append(f"Pytest tests for {self.skill_name}")
316
+ lines.append("Auto-generated - customize as needed")
317
+ lines.append("\"\"\"")
318
+ lines.append("\nimport pytest\n")
319
+
320
+ # Generate test functions
321
+ for scenario in self.test_scenarios:
322
+ test_name = self._sanitize_test_name(scenario['description'])
323
+ lines.append(f"def test_{test_name}():")
324
+ lines.append(f" \"\"\"")
325
+ lines.append(f" {scenario['description']}")
326
+ lines.append(f" Priority: {scenario['priority']}")
327
+ lines.append(f" Expected: {scenario['expected_result']}")
328
+ lines.append(f" \"\"\"")
329
+ lines.append(f" # TODO: Implement test logic")
330
+ lines.append(f" # Test data: {scenario['test_data']}")
331
+ lines.append(f" assert True, 'Test not implemented yet'\n")
332
+
333
+ with open(output_path, 'w', encoding='utf-8') as f:
334
+ f.write('\n'.join(lines))
335
+
336
+ def generate_unittest_implementation(self, output_path: Path):
337
+ """Generate unittest test implementation."""
338
+ lines = []
339
+ lines.append("\"\"\"")
340
+ lines.append(f"Unittest tests for {self.skill_name}")
341
+ lines.append("Auto-generated - customize as needed")
342
+ lines.append("\"\"\"")
343
+ lines.append("\nimport unittest\n")
344
+
345
+ lines.append(f"class Test{self.skill_name.replace('-', '_').title()}(unittest.TestCase):")
346
+ lines.append(f" \"\"\"Test suite for {self.skill_name}.\"\"\"")
347
+ lines.append("")
348
+
349
+ # Generate test methods
350
+ for scenario in self.test_scenarios:
351
+ test_name = self._sanitize_test_name(scenario['description'])
352
+ lines.append(f" def test_{test_name}(self):")
353
+ lines.append(f" \"\"\"")
354
+ lines.append(f" {scenario['description']}")
355
+ lines.append(f" Priority: {scenario['priority']}")
356
+ lines.append(f" Expected: {scenario['expected_result']}")
357
+ lines.append(f" \"\"\"")
358
+ lines.append(f" # TODO: Implement test logic")
359
+ lines.append(f" # Test data: {scenario['test_data']}")
360
+ lines.append(f" self.assertTrue(True, 'Test not implemented yet')\n")
361
+
362
+ lines.append("\nif __name__ == '__main__':")
363
+ lines.append(" unittest.main()")
364
+
365
+ with open(output_path, 'w', encoding='utf-8') as f:
366
+ f.write('\n'.join(lines))
367
+
368
+ def generate_plain_documentation(self, output_path: Path):
369
+ """Generate plain text test plan."""
370
+ lines = []
371
+ lines.append(f"TEST PLAN: {self.skill_name}")
372
+ lines.append("=" * 60)
373
+ lines.append(f"Coverage: {self.coverage}")
374
+ lines.append(f"Total scenarios: {len(self.test_scenarios)}\n")
375
+
376
+ for i, scenario in enumerate(self.test_scenarios, 1):
377
+ lines.append(f"\n{i}. {scenario['description']}")
378
+ lines.append(f" Priority: {scenario['priority']}")
379
+ lines.append(f" Category: {scenario['category']}")
380
+ lines.append(f" Expected: {scenario['expected_result']}")
381
+ lines.append(f" Test Data: {scenario['test_data']}")
382
+
383
+ with open(output_path, 'w', encoding='utf-8') as f:
384
+ f.write('\n'.join(lines))
385
+
386
+ def generate_behavioral_tests(self, skill_path: str, skill_type: str) -> str:
387
+ """
388
+ Generate pressure-test scenarios for a skill.
389
+
390
+ Returns pytest-compatible test template content.
391
+ Behavioral templates are only emitted for pytest mode.
392
+ """
393
+ _ = skill_type
394
+ if self.test_format != 'pytest':
395
+ return ""
396
+
397
+ template = '''"""
398
+ Behavioral tests for {skill_name}
399
+ Generated by test_generator.py --behavioral
400
+ """
401
+
402
+ import pytest
403
+
404
+ # RED Phase: Baseline tests (run WITHOUT skill)
405
+ class TestBaselineBehavior:
406
+ """Document how agents behave without skill."""
407
+
408
+ def test_time_pressure_rationalization(self):
409
+ """Under time pressure, agents typically..."""
410
+ # Document expected failure
411
+ pass
412
+
413
+ def test_sunk_cost_rationalization(self):
414
+ """With sunk cost, agents typically..."""
415
+ pass
416
+
417
+ # GREEN Phase: Verification tests (run WITH skill)
418
+ class TestSkillCompliance:
419
+ """Verify agents comply WITH skill."""
420
+
421
+ def test_resists_time_pressure(self):
422
+ """Skill helps agent resist time pressure."""
423
+ pass
424
+
425
+ def test_resists_sunk_cost(self):
426
+ """Skill helps agent resist sunk cost fallacy."""
427
+ pass
428
+
429
+ # REFACTOR Phase: Combined pressure
430
+ class TestCombinedPressure:
431
+ """All pressures at once."""
432
+
433
+ def test_combined_pressure_compliance(self):
434
+ """Agent complies under maximum pressure."""
435
+ pass
436
+ '''
437
+ skill_name = Path(skill_path).name
438
+ return template.format(skill_name=skill_name, skill_type=skill_type)
439
+
440
+ def _sanitize_test_name(self, description: str) -> str:
441
+ """
442
+ Convert description to valid Python function name.
443
+
444
+ Args:
445
+ description: Test description
446
+
447
+ Returns:
448
+ Sanitized function name
449
+ """
450
+ # Remove non-alphanumeric, convert spaces to underscores
451
+ name = re.sub(r'[^a-zA-Z0-9\s]', '', description)
452
+ name = name.lower().replace(' ', '_')
453
+ # Limit length and remove extra underscores
454
+ name = re.sub(r'_+', '_', name)
455
+ return name[:50].strip('_')
456
+
457
+ # ========== MAIN EXECUTION ==========
458
+
459
+ def generate(self):
460
+ """
461
+ Main generation workflow.
462
+
463
+ 1. Parse skill description
464
+ 2. Generate test scenarios
465
+ 3. Write test documentation
466
+ 4. Write test implementation
467
+
468
+ References: File 12 (testing workflow)
469
+ """
470
+ # Parse
471
+ skill_info = self.parse_skill_description()
472
+
473
+ # Generate scenarios
474
+ scenarios = self.generate_test_scenarios()
475
+
476
+ # Calculate stats
477
+ behavioral_generated = self.behavioral and self.test_format == 'pytest'
478
+
479
+ stats = {
480
+ 'skill_name': skill_info['name'],
481
+ 'capabilities_found': len(skill_info['capabilities']),
482
+ 'total_scenarios': len(scenarios),
483
+ 'by_priority': {
484
+ 'P0': sum(1 for s in scenarios if s['priority'] == 'P0'),
485
+ 'P1': sum(1 for s in scenarios if s['priority'] == 'P1'),
486
+ 'P2': sum(1 for s in scenarios if s['priority'] == 'P2')
487
+ },
488
+ 'coverage': self.coverage,
489
+ 'test_format': self.test_format,
490
+ 'behavioral': self.behavioral,
491
+ 'behavioral_generated': behavioral_generated
492
+ }
493
+
494
+ # Create tests/ directory
495
+ tests_dir = self.skill_path / "tests"
496
+ tests_dir.mkdir(exist_ok=True)
497
+
498
+ # Write outputs
499
+ self.generate_test_documentation(tests_dir / "test_scenarios.md")
500
+
501
+ if self.test_format == 'pytest':
502
+ self.generate_pytest_implementation(tests_dir / "test_skill.py")
503
+ stats['output_files'] = [
504
+ str(tests_dir / 'test_scenarios.md'),
505
+ str(tests_dir / 'test_skill.py')
506
+ ]
507
+ elif self.test_format == 'unittest':
508
+ self.generate_unittest_implementation(tests_dir / "test_skill.py")
509
+ stats['output_files'] = [
510
+ str(tests_dir / 'test_scenarios.md'),
511
+ str(tests_dir / 'test_skill.py')
512
+ ]
513
+ else: # plain
514
+ self.generate_plain_documentation(tests_dir / "test_plan.txt")
515
+ stats['output_files'] = [
516
+ str(tests_dir / 'test_scenarios.md'),
517
+ str(tests_dir / 'test_plan.txt')
518
+ ]
519
+
520
+ if behavioral_generated:
521
+ behavioral_file = tests_dir / "test_behavioral.py"
522
+ behavioral_content = self.generate_behavioral_tests(
523
+ str(self.skill_path),
524
+ "discipline"
525
+ )
526
+ with open(behavioral_file, 'w', encoding='utf-8') as f:
527
+ f.write(behavioral_content)
528
+ stats['output_files'].append(str(behavioral_file))
529
+
530
+ # Output based on format
531
+ if self.output_format == 'json':
532
+ self._output_json(stats, scenarios)
533
+ else:
534
+ self._output_text(stats, tests_dir)
535
+
536
+ return stats
537
+
538
+ def _output_json(self, stats: Dict, scenarios: List[Dict]):
539
+ """Output in JSON format for agent-layer."""
540
+ output = {
541
+ 'status': 'success',
542
+ 'skill_name': stats['skill_name'],
543
+ 'capabilities_found': stats['capabilities_found'],
544
+ 'test_scenarios': {
545
+ 'total': stats['total_scenarios'],
546
+ 'by_priority': stats['by_priority'],
547
+ 'scenarios': scenarios
548
+ },
549
+ 'configuration': {
550
+ 'coverage': stats['coverage'],
551
+ 'test_format': stats['test_format'],
552
+ 'behavioral': stats['behavioral'],
553
+ 'behavioral_generated': stats['behavioral_generated']
554
+ },
555
+ 'output_files': stats['output_files'],
556
+ 'next_steps': [
557
+ 'Review test scenarios in test_scenarios.md',
558
+ 'Implement test logic in test files',
559
+ f"Run: pytest {self.skill_path / 'tests'}" if self.test_format == 'pytest' else f"Run: python -m unittest discover {self.skill_path / 'tests'}"
560
+ ]
561
+ }
562
+ print(json.dumps(output, indent=2))
563
+
564
+ def _output_text(self, stats: Dict, tests_dir: Path):
565
+ """Output in human-readable text format."""
566
+ print(f"Generating tests for {self.skill_path}...")
567
+ print(f"Skill: {stats['skill_name']}")
568
+ print(f"Capabilities found: {stats['capabilities_found']}")
569
+ print(f"Test scenarios generated: {stats['total_scenarios']}")
570
+ print(f" - P0 (Critical): {stats['by_priority']['P0']}")
571
+ print(f" - P1 (High): {stats['by_priority']['P1']}")
572
+ print(f" - P2 (Medium): {stats['by_priority']['P2']}")
573
+
574
+ print(f"\n✔ Test documentation: {tests_dir / 'test_scenarios.md'}")
575
+
576
+ if self.test_format == 'pytest':
577
+ print(f"✔ Pytest implementation: {tests_dir / 'test_skill.py'}")
578
+ elif self.test_format == 'unittest':
579
+ print(f"✔ Unittest implementation: {tests_dir / 'test_skill.py'}")
580
+ else:
581
+ print(f"✔ Plain test plan: {tests_dir / 'test_plan.txt'}")
582
+ if stats['behavioral_generated']:
583
+ print(f"✔ Behavioral template: {tests_dir / 'test_behavioral.py'}")
584
+ elif stats['behavioral']:
585
+ print("! Behavioral template skipped (only supported with --test-format pytest)")
586
+
587
+ print(f"\nNext steps:")
588
+ print(f" 1. Review test scenarios in test_scenarios.md")
589
+ print(f" 2. Implement test logic in test files")
590
+ if self.test_format == 'pytest':
591
+ print(f" 3. Run: pytest {tests_dir}")
592
+ elif self.test_format == 'unittest':
593
+ print(f" 3. Run: python -m unittest discover {tests_dir}")
594
+ print(f"\n✔ Tests generated successfully!")
595
+
596
+ def main():
597
+ """CLI entry point with v1.2 parameter standardization."""
598
+ parser = argparse.ArgumentParser(
599
+ description="Auto-generate test scenarios for skills",
600
+ epilog="References: File 12 for testing best practices | v1.2: Standardized parameters"
601
+ )
602
+ parser.add_argument(
603
+ 'skill_path',
604
+ type=str,
605
+ help='Path to skill directory'
606
+ )
607
+ parser.add_argument(
608
+ '--coverage',
609
+ choices=['basic', 'standard', 'comprehensive'],
610
+ default='standard',
611
+ help='Test coverage level (default: standard)'
612
+ )
613
+ # v1.2: Renamed from --format (test framework choice)
614
+ parser.add_argument(
615
+ '--test-format',
616
+ choices=['pytest', 'unittest', 'plain'],
617
+ default='pytest',
618
+ help='Test framework format (default: pytest)'
619
+ )
620
+ # v1.2: Renamed from --output (standardized to --format for all tools)
621
+ parser.add_argument(
622
+ '--format',
623
+ choices=['text', 'json'],
624
+ default='text',
625
+ help='Output format: text (human-readable) or json (agent-layer)'
626
+ )
627
+ # v1.2: Backward compatibility for deprecated --output parameter
628
+ parser.add_argument(
629
+ '--output',
630
+ choices=['text', 'json'],
631
+ default=None,
632
+ help='[DEPRECATED v1.2] Use --format instead. This parameter will be removed in v2.0.'
633
+ )
634
+ parser.add_argument(
635
+ '--behavioral',
636
+ action='store_true',
637
+ help='Generate behavioral test scaffolds (v2.1: scaffolds only, real testing uses subagent protocol)'
638
+ )
639
+
640
+ args = parser.parse_args()
641
+
642
+ # v1.2: Handle backward compatibility for --output parameter
643
+ if args.output is not None:
644
+ warnings.warn(
645
+ "Parameter '--output' is deprecated (v1.2). Use '--format' instead. "
646
+ "The '--output' parameter will be removed in v2.0.0.",
647
+ DeprecationWarning,
648
+ stacklevel=2
649
+ )
650
+ output_format = args.output
651
+ else:
652
+ output_format = args.format
653
+
654
+ # v2 deprecation: legacy structural-only mode
655
+ if not args.behavioral:
656
+ warnings.warn(
657
+ "Legacy structural-only test generation mode is deprecated in v2. "
658
+ "Use '--behavioral --test-format pytest' for v2 workflow.",
659
+ DeprecationWarning,
660
+ stacklevel=2,
661
+ )
662
+
663
+ try:
664
+ generator = TestGenerator(
665
+ args.skill_path,
666
+ coverage=args.coverage,
667
+ test_format=args.test_format,
668
+ output_format=output_format,
669
+ behavioral=args.behavioral
670
+ )
671
+ generator.generate()
672
+ return 0
673
+ except FileNotFoundError as e:
674
+ if output_format == 'json':
675
+ print(json.dumps({
676
+ 'status': 'error',
677
+ 'error_type': 'FileNotFoundError',
678
+ 'message': str(e)
679
+ }))
680
+ else:
681
+ print(f"✗ Error: {e}")
682
+ return 1
683
+ except Exception as e:
684
+ if output_format == 'json':
685
+ print(json.dumps({
686
+ 'status': 'error',
687
+ 'error_type': type(e).__name__,
688
+ 'message': str(e)
689
+ }))
690
+ else:
691
+ print(f"✗ Unexpected error: {e}")
692
+ return 2
693
+
694
+ if __name__ == "__main__":
695
+ exit(main())