@rfxlamia/skillkit 1.0.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 +7 -2
- package/skills/quick-spec/tests/__pycache__/test_skill.cpython-314-pytest-9.0.2.pyc +0 -0
- package/skills/skillkit/.claude/settings.local.json +7 -0
- package/skills/skillkit/scripts/__pycache__/decision_helper.cpython-314.pyc +0 -0
- package/skills/skillkit/scripts/__pycache__/quick_validate.cpython-312.pyc +0 -0
- package/skills/skillkit/scripts/__pycache__/quick_validate.cpython-314.pyc +0 -0
- package/skills/skillkit/scripts/__pycache__/test_generator.cpython-314-pytest-9.0.2.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/__init__.cpython-312.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/budget_tracker.cpython-312.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/budget_tracker.cpython-314.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/output_formatter.cpython-312.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/output_formatter.cpython-314.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/reference_validator.cpython-312.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/reference_validator.cpython-314.pyc +0 -0
- 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/banner.js +1 -1
- package/src/cli.js +15 -4
- package/src/install.js +45 -29
- package/src/install.test.js +75 -7
- package/src/picker.js +15 -4
- package/src/picker.test.js +36 -1
- package/src/scope.js +8 -39
- package/src/scope.test.js +9 -13
- package/src/tools.js +76 -0
- package/src/tools.test.js +80 -0
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Convert existing documentation to skill format.
|
|
4
|
+
Supports Markdown and text files with intelligent structure generation.
|
|
5
|
+
|
|
6
|
+
AGENT-LAYER TOOL: Called by Claude via bash_tool, outputs JSON for parsing.
|
|
7
|
+
|
|
8
|
+
This script automates the conversion of existing documentation into Claude skill format:
|
|
9
|
+
- Parses source documents (MD, TXT)
|
|
10
|
+
- Classifies sections (core vs reference)
|
|
11
|
+
- Generates proper skill structure
|
|
12
|
+
- Creates YAML frontmatter
|
|
13
|
+
- Organizes references/ directory
|
|
14
|
+
- Produces conversion report
|
|
15
|
+
|
|
16
|
+
References:
|
|
17
|
+
File 10: Technical architecture (skill structure)
|
|
18
|
+
File 05: Token economics (progressive disclosure)
|
|
19
|
+
Files 01-13: Best practices for skill design
|
|
20
|
+
|
|
21
|
+
Usage (Agent-Layer):
|
|
22
|
+
python migration_helper.py source.md --format json
|
|
23
|
+
# Returns JSON: {"status": "success", "skill_path": "...", "report": {...}}
|
|
24
|
+
|
|
25
|
+
Usage (Human-Readable):
|
|
26
|
+
python migration_helper.py source.md
|
|
27
|
+
python migration_helper.py source.md --preview
|
|
28
|
+
python migration_helper.py source.md --skill-name my-skill --output-dir ./skills/
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
import argparse
|
|
32
|
+
import json
|
|
33
|
+
import re
|
|
34
|
+
from pathlib import Path
|
|
35
|
+
from typing import Dict, List, Optional, Tuple
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class MigrationHelper:
|
|
39
|
+
"""Convert documentation to skill format."""
|
|
40
|
+
|
|
41
|
+
def __init__(self,
|
|
42
|
+
source_path: str,
|
|
43
|
+
skill_name: Optional[str] = None,
|
|
44
|
+
output_dir: Optional[str] = None,
|
|
45
|
+
preview: bool = False):
|
|
46
|
+
"""
|
|
47
|
+
Initialize migration helper.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
source_path: Path to source document
|
|
51
|
+
skill_name: Optional skill name override
|
|
52
|
+
output_dir: Output directory for skill
|
|
53
|
+
preview: If True, show plan without executing
|
|
54
|
+
|
|
55
|
+
References: File 10 (skill structure standards)
|
|
56
|
+
"""
|
|
57
|
+
self.source_path = Path(source_path)
|
|
58
|
+
self.skill_name = skill_name or self._generate_skill_name()
|
|
59
|
+
self.output_dir = Path(output_dir) if output_dir else Path.cwd()
|
|
60
|
+
self.preview = preview
|
|
61
|
+
self.source_content = None
|
|
62
|
+
self.source_format = None
|
|
63
|
+
self.sections = []
|
|
64
|
+
self.frontmatter = {}
|
|
65
|
+
|
|
66
|
+
# ========== PARSING ==========
|
|
67
|
+
|
|
68
|
+
def parse_source(self) -> Dict:
|
|
69
|
+
"""
|
|
70
|
+
Parse source document.
|
|
71
|
+
|
|
72
|
+
Supports:
|
|
73
|
+
- Markdown files (.md, .markdown)
|
|
74
|
+
- Plain text files (.txt)
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Dict with parsed structure:
|
|
78
|
+
{
|
|
79
|
+
'format': 'markdown' or 'text',
|
|
80
|
+
'sections': int,
|
|
81
|
+
'total_lines': int,
|
|
82
|
+
'has_headers': bool
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
Raises:
|
|
86
|
+
FileNotFoundError: If source doesn't exist
|
|
87
|
+
ValueError: If format unsupported
|
|
88
|
+
|
|
89
|
+
References: File 10 (content structure)
|
|
90
|
+
"""
|
|
91
|
+
if not self.source_path.exists():
|
|
92
|
+
raise FileNotFoundError(f"Source not found: {self.source_path}")
|
|
93
|
+
|
|
94
|
+
with open(self.source_path, encoding='utf-8', errors='ignore') as f:
|
|
95
|
+
self.source_content = f.read()
|
|
96
|
+
|
|
97
|
+
# Detect format
|
|
98
|
+
suffix = self.source_path.suffix.lower()
|
|
99
|
+
if suffix in ['.md', '.markdown']:
|
|
100
|
+
return self._parse_markdown()
|
|
101
|
+
elif suffix in ['.txt', '']:
|
|
102
|
+
return self._parse_plaintext()
|
|
103
|
+
else:
|
|
104
|
+
raise ValueError(f"Unsupported format: {suffix}")
|
|
105
|
+
|
|
106
|
+
def _parse_markdown(self) -> Dict:
|
|
107
|
+
"""Parse Markdown document into sections."""
|
|
108
|
+
self.source_format = 'markdown'
|
|
109
|
+
lines = self.source_content.split('\n')
|
|
110
|
+
|
|
111
|
+
# Extract sections based on headers
|
|
112
|
+
current_section = {'title': 'Introduction', 'content': [], 'level': 0, 'line_start': 0}
|
|
113
|
+
sections = []
|
|
114
|
+
|
|
115
|
+
for i, line in enumerate(lines):
|
|
116
|
+
# Match markdown headers (# Header)
|
|
117
|
+
header_match = re.match(r'^(#{1,6})\s+(.+)$', line)
|
|
118
|
+
|
|
119
|
+
if header_match:
|
|
120
|
+
# Save previous section
|
|
121
|
+
if current_section['content'] or current_section['title'] != 'Introduction':
|
|
122
|
+
current_section['line_count'] = len(current_section['content'])
|
|
123
|
+
sections.append(current_section)
|
|
124
|
+
|
|
125
|
+
# Start new section
|
|
126
|
+
level = len(header_match.group(1))
|
|
127
|
+
title = header_match.group(2).strip()
|
|
128
|
+
current_section = {
|
|
129
|
+
'title': title,
|
|
130
|
+
'content': [],
|
|
131
|
+
'level': level,
|
|
132
|
+
'line_start': i
|
|
133
|
+
}
|
|
134
|
+
else:
|
|
135
|
+
current_section['content'].append(line)
|
|
136
|
+
|
|
137
|
+
# Add last section
|
|
138
|
+
if current_section['content']:
|
|
139
|
+
current_section['line_count'] = len(current_section['content'])
|
|
140
|
+
sections.append(current_section)
|
|
141
|
+
|
|
142
|
+
self.sections = sections
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
'format': 'markdown',
|
|
146
|
+
'sections': len(sections),
|
|
147
|
+
'total_lines': len(lines),
|
|
148
|
+
'has_headers': True
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
def _parse_plaintext(self) -> Dict:
|
|
152
|
+
"""Parse plain text into sections."""
|
|
153
|
+
self.source_format = 'text'
|
|
154
|
+
lines = self.source_content.split('\n')
|
|
155
|
+
|
|
156
|
+
# For plain text, treat each paragraph as a section
|
|
157
|
+
sections = []
|
|
158
|
+
current_section = {'title': 'Content', 'content': [], 'level': 1, 'line_start': 0}
|
|
159
|
+
|
|
160
|
+
for i, line in enumerate(lines):
|
|
161
|
+
if line.strip() == '':
|
|
162
|
+
# Empty line might indicate section break
|
|
163
|
+
if current_section['content']:
|
|
164
|
+
current_section['line_count'] = len(current_section['content'])
|
|
165
|
+
sections.append(current_section)
|
|
166
|
+
current_section = {'title': f'Section {len(sections)+1}', 'content': [], 'level': 1, 'line_start': i}
|
|
167
|
+
else:
|
|
168
|
+
current_section['content'].append(line)
|
|
169
|
+
|
|
170
|
+
# Add last section
|
|
171
|
+
if current_section['content']:
|
|
172
|
+
current_section['line_count'] = len(current_section['content'])
|
|
173
|
+
sections.append(current_section)
|
|
174
|
+
|
|
175
|
+
self.sections = sections
|
|
176
|
+
|
|
177
|
+
return {
|
|
178
|
+
'format': 'text',
|
|
179
|
+
'sections': len(sections),
|
|
180
|
+
'total_lines': len(lines),
|
|
181
|
+
'has_headers': False
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
# ========== CLASSIFICATION ==========
|
|
185
|
+
|
|
186
|
+
def classify_sections(self) -> Dict:
|
|
187
|
+
"""
|
|
188
|
+
Classify sections as core or reference.
|
|
189
|
+
|
|
190
|
+
Classification rules:
|
|
191
|
+
- Core: overview, setup, quick start, basic usage, workflow
|
|
192
|
+
- Reference: advanced, troubleshooting, examples, detailed, edge cases
|
|
193
|
+
- Heuristic: sections >100 lines → reference
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
Dict with classification results
|
|
197
|
+
|
|
198
|
+
References: File 05 (progressive disclosure)
|
|
199
|
+
"""
|
|
200
|
+
core_keywords = [
|
|
201
|
+
'overview', 'introduction', 'setup', 'installation', 'install',
|
|
202
|
+
'quick start', 'getting started', 'basic', 'usage', 'workflow',
|
|
203
|
+
'how to use', 'core', 'main', 'primary'
|
|
204
|
+
]
|
|
205
|
+
|
|
206
|
+
reference_keywords = [
|
|
207
|
+
'advanced', 'troubleshoot', 'example', 'reference', 'api',
|
|
208
|
+
'edge case', 'detailed', 'appendix', 'additional', 'extended',
|
|
209
|
+
'deep dive', 'technical', 'specification', 'cookbook'
|
|
210
|
+
]
|
|
211
|
+
|
|
212
|
+
core_sections = []
|
|
213
|
+
reference_sections = []
|
|
214
|
+
|
|
215
|
+
for section in self.sections:
|
|
216
|
+
title_lower = section['title'].lower()
|
|
217
|
+
line_count = section['line_count']
|
|
218
|
+
|
|
219
|
+
# Heuristic: large sections go to reference
|
|
220
|
+
if line_count > 100:
|
|
221
|
+
reference_sections.append(section)
|
|
222
|
+
continue
|
|
223
|
+
|
|
224
|
+
# Check keywords
|
|
225
|
+
is_core = any(kw in title_lower for kw in core_keywords)
|
|
226
|
+
is_reference = any(kw in title_lower for kw in reference_keywords)
|
|
227
|
+
|
|
228
|
+
if is_reference and not is_core:
|
|
229
|
+
reference_sections.append(section)
|
|
230
|
+
else:
|
|
231
|
+
# Default to core if ambiguous or clearly core
|
|
232
|
+
core_sections.append(section)
|
|
233
|
+
|
|
234
|
+
return {
|
|
235
|
+
'core_sections': len(core_sections),
|
|
236
|
+
'reference_sections': len(reference_sections),
|
|
237
|
+
'core': core_sections,
|
|
238
|
+
'reference': reference_sections
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
# ========== FRONTMATTER GENERATION ==========
|
|
242
|
+
|
|
243
|
+
def generate_frontmatter(self, parsed: Dict) -> str:
|
|
244
|
+
"""
|
|
245
|
+
Generate YAML frontmatter for SKILL.md.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
parsed: Parsed source structure
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
YAML frontmatter string
|
|
252
|
+
|
|
253
|
+
References: File 10 (frontmatter requirements)
|
|
254
|
+
"""
|
|
255
|
+
# Extract potential description from first section
|
|
256
|
+
description = "Converted from external documentation"
|
|
257
|
+
if self.sections:
|
|
258
|
+
first_content = '\n'.join(self.sections[0]['content'][:3])
|
|
259
|
+
if first_content.strip():
|
|
260
|
+
# Take first sentence as description
|
|
261
|
+
sentences = re.split(r'[.!?]\s+', first_content)
|
|
262
|
+
if sentences:
|
|
263
|
+
description = sentences[0].strip()[:200] # Max 200 chars
|
|
264
|
+
|
|
265
|
+
frontmatter = f"""---
|
|
266
|
+
name: {self.skill_name}
|
|
267
|
+
description: "{description}"
|
|
268
|
+
source: "{self.source_path.name}"
|
|
269
|
+
converted_at: "auto-generated"
|
|
270
|
+
format: "{parsed['format']}"
|
|
271
|
+
---
|
|
272
|
+
"""
|
|
273
|
+
return frontmatter
|
|
274
|
+
|
|
275
|
+
# ========== CONVERSION PLANNING ==========
|
|
276
|
+
|
|
277
|
+
def plan_conversion(self) -> Dict:
|
|
278
|
+
"""
|
|
279
|
+
Create conversion plan.
|
|
280
|
+
|
|
281
|
+
Returns:
|
|
282
|
+
Dict with conversion plan:
|
|
283
|
+
{
|
|
284
|
+
'skill_name': str,
|
|
285
|
+
'output_path': Path,
|
|
286
|
+
'core_sections': int,
|
|
287
|
+
'reference_sections': int,
|
|
288
|
+
'estimated_tokens': int,
|
|
289
|
+
'skill_md_lines': int
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
References: File 05 (token estimation)
|
|
293
|
+
"""
|
|
294
|
+
classified = self.classify_sections()
|
|
295
|
+
|
|
296
|
+
# Estimate tokens (rough: chars / 4)
|
|
297
|
+
total_chars = len(self.source_content)
|
|
298
|
+
estimated_tokens = total_chars // 4
|
|
299
|
+
|
|
300
|
+
# Calculate SKILL.md size (core + frontmatter + links)
|
|
301
|
+
core_lines = sum(s['line_count'] for s in classified['core'])
|
|
302
|
+
frontmatter_lines = 8
|
|
303
|
+
links_lines = len(classified['reference']) * 2 # 2 lines per reference link
|
|
304
|
+
skill_md_lines = core_lines + frontmatter_lines + links_lines + 10 # +10 for Additional Resources section
|
|
305
|
+
|
|
306
|
+
output_path = self.output_dir / self.skill_name
|
|
307
|
+
|
|
308
|
+
return {
|
|
309
|
+
'skill_name': self.skill_name,
|
|
310
|
+
'output_path': output_path,
|
|
311
|
+
'core_sections': classified['core_sections'],
|
|
312
|
+
'reference_sections': classified['reference_sections'],
|
|
313
|
+
'core': classified['core'],
|
|
314
|
+
'reference': classified['reference'],
|
|
315
|
+
'estimated_tokens': estimated_tokens,
|
|
316
|
+
'skill_md_lines': skill_md_lines,
|
|
317
|
+
'source_lines': len(self.source_content.split('\n'))
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
# ========== EXECUTION ==========
|
|
321
|
+
|
|
322
|
+
def execute_conversion(self, plan: Dict) -> Dict:
|
|
323
|
+
"""
|
|
324
|
+
Execute conversion plan.
|
|
325
|
+
|
|
326
|
+
Args:
|
|
327
|
+
plan: Conversion plan from plan_conversion()
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
Dict with execution results
|
|
331
|
+
|
|
332
|
+
Raises:
|
|
333
|
+
IOError: If file operations fail
|
|
334
|
+
|
|
335
|
+
References: File 10 (skill directory structure)
|
|
336
|
+
"""
|
|
337
|
+
if self.preview:
|
|
338
|
+
return self._generate_preview_report(plan)
|
|
339
|
+
|
|
340
|
+
output_path = plan['output_path']
|
|
341
|
+
|
|
342
|
+
# Create skill directory
|
|
343
|
+
output_path.mkdir(parents=True, exist_ok=True)
|
|
344
|
+
|
|
345
|
+
# Create references directory if needed
|
|
346
|
+
if plan['reference_sections'] > 0:
|
|
347
|
+
references_dir = output_path / 'references'
|
|
348
|
+
references_dir.mkdir(exist_ok=True)
|
|
349
|
+
|
|
350
|
+
# Generate SKILL.md
|
|
351
|
+
skill_md_path = output_path / 'SKILL.md'
|
|
352
|
+
parsed = {'format': self.source_format}
|
|
353
|
+
skill_content = self._build_skill_md(plan, parsed)
|
|
354
|
+
|
|
355
|
+
with open(skill_md_path, 'w', encoding='utf-8') as f:
|
|
356
|
+
f.write(skill_content)
|
|
357
|
+
|
|
358
|
+
# Create reference files
|
|
359
|
+
reference_files = []
|
|
360
|
+
if plan['reference_sections'] > 0:
|
|
361
|
+
references_dir = output_path / 'references'
|
|
362
|
+
for section in plan['reference']:
|
|
363
|
+
filename = self._sanitize_filename(section['title']) + '.md'
|
|
364
|
+
ref_path = references_dir / filename
|
|
365
|
+
ref_content = self._build_reference_file(section)
|
|
366
|
+
|
|
367
|
+
with open(ref_path, 'w', encoding='utf-8') as f:
|
|
368
|
+
f.write(ref_content)
|
|
369
|
+
|
|
370
|
+
reference_files.append(filename)
|
|
371
|
+
|
|
372
|
+
# Generate conversion report
|
|
373
|
+
report = self._generate_conversion_report(plan, reference_files)
|
|
374
|
+
report_path = output_path / 'conversion_report.md'
|
|
375
|
+
|
|
376
|
+
with open(report_path, 'w', encoding='utf-8') as f:
|
|
377
|
+
f.write(report)
|
|
378
|
+
|
|
379
|
+
return {
|
|
380
|
+
'skill_path': str(output_path),
|
|
381
|
+
'skill_md': str(skill_md_path),
|
|
382
|
+
'references': reference_files,
|
|
383
|
+
'report': str(report_path),
|
|
384
|
+
'core_sections': plan['core_sections'],
|
|
385
|
+
'reference_sections': plan['reference_sections'],
|
|
386
|
+
'reduction_percent': round((1 - plan['skill_md_lines'] / plan['source_lines']) * 100, 1) if plan['source_lines'] > 0 else 0
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
def _build_skill_md(self, plan: Dict, parsed: Dict) -> str:
|
|
390
|
+
"""Build SKILL.md content."""
|
|
391
|
+
# Frontmatter
|
|
392
|
+
content = self.generate_frontmatter(parsed)
|
|
393
|
+
content += '\n'
|
|
394
|
+
|
|
395
|
+
# Core sections
|
|
396
|
+
for section in plan['core']:
|
|
397
|
+
# Add section header
|
|
398
|
+
if section['level'] > 0:
|
|
399
|
+
content += '#' * section['level'] + ' ' + section['title'] + '\n\n'
|
|
400
|
+
|
|
401
|
+
# Add section content
|
|
402
|
+
content += '\n'.join(section['content']) + '\n\n'
|
|
403
|
+
|
|
404
|
+
# Additional Resources section (if references exist)
|
|
405
|
+
if plan['reference_sections'] > 0:
|
|
406
|
+
content += '## Additional Resources\n\n'
|
|
407
|
+
content += 'For detailed information, see:\n\n'
|
|
408
|
+
|
|
409
|
+
for section in plan['reference']:
|
|
410
|
+
filename = self._sanitize_filename(section['title'])
|
|
411
|
+
content += f"- [{section['title']}](references/{filename}.md)\n"
|
|
412
|
+
|
|
413
|
+
content += '\n'
|
|
414
|
+
|
|
415
|
+
return content
|
|
416
|
+
|
|
417
|
+
def _build_reference_file(self, section: Dict) -> str:
|
|
418
|
+
"""Build reference file content."""
|
|
419
|
+
content = f"# {section['title']}\n\n"
|
|
420
|
+
content += '\n'.join(section['content'])
|
|
421
|
+
return content
|
|
422
|
+
|
|
423
|
+
def _generate_conversion_report(self, plan: Dict, reference_files: List[str]) -> str:
|
|
424
|
+
"""Generate conversion report."""
|
|
425
|
+
report = f"""# Conversion Report
|
|
426
|
+
|
|
427
|
+
**Source:** {self.source_path}
|
|
428
|
+
**Skill Name:** {self.skill_name}
|
|
429
|
+
**Output:** {plan['output_path']}
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## Conversion Summary
|
|
434
|
+
|
|
435
|
+
| Metric | Value |
|
|
436
|
+
|--------|-------|
|
|
437
|
+
| Source format | {self.source_format} |
|
|
438
|
+
| Total sections | {plan['core_sections'] + plan['reference_sections']} |
|
|
439
|
+
| Core sections | {plan['core_sections']} |
|
|
440
|
+
| Reference sections | {plan['reference_sections']} |
|
|
441
|
+
| Source lines | {plan['source_lines']} |
|
|
442
|
+
| SKILL.md lines | {plan['skill_md_lines']} |
|
|
443
|
+
| Reduction | {round((1 - plan['skill_md_lines'] / plan['source_lines']) * 100, 1)}% |
|
|
444
|
+
| Estimated tokens | {plan['estimated_tokens']} |
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## Structure Created
|
|
449
|
+
|
|
450
|
+
```
|
|
451
|
+
{self.skill_name}/
|
|
452
|
+
├── SKILL.md ({plan['skill_md_lines']} lines)
|
|
453
|
+
├── conversion_report.md (this file)
|
|
454
|
+
"""
|
|
455
|
+
|
|
456
|
+
if reference_files:
|
|
457
|
+
report += "└── references/\n"
|
|
458
|
+
for i, ref_file in enumerate(reference_files):
|
|
459
|
+
prefix = '├──' if i < len(reference_files) - 1 else '└──'
|
|
460
|
+
report += f" {prefix} {ref_file}\n"
|
|
461
|
+
|
|
462
|
+
report += "```\n\n---\n\n"
|
|
463
|
+
|
|
464
|
+
report += "## Next Steps\n\n"
|
|
465
|
+
report += "1. Review SKILL.md and update frontmatter description\n"
|
|
466
|
+
report += "2. Add trigger phrases (WHEN to use)\n"
|
|
467
|
+
report += "3. Validate structure: `python validate_skill.py " + self.skill_name + "/`\n"
|
|
468
|
+
report += "4. Test the skill in Claude\n"
|
|
469
|
+
report += "5. Optimize if needed: `python quality_scorer.py " + self.skill_name + "/ --format json`\n\n"
|
|
470
|
+
|
|
471
|
+
report += "---\n\n"
|
|
472
|
+
report += "**References:** Files 01-13 for best practices | File 10 for structure standards\n"
|
|
473
|
+
|
|
474
|
+
return report
|
|
475
|
+
|
|
476
|
+
def _generate_preview_report(self, plan: Dict) -> Dict:
|
|
477
|
+
"""Generate preview report without executing."""
|
|
478
|
+
return {
|
|
479
|
+
'preview': True,
|
|
480
|
+
'skill_name': plan['skill_name'],
|
|
481
|
+
'output_path': str(plan['output_path']),
|
|
482
|
+
'core_sections': plan['core_sections'],
|
|
483
|
+
'reference_sections': plan['reference_sections'],
|
|
484
|
+
'estimated_lines': plan['skill_md_lines'],
|
|
485
|
+
'source_lines': plan['source_lines'],
|
|
486
|
+
'reduction_percent': round((1 - plan['skill_md_lines'] / plan['source_lines']) * 100, 1) if plan['source_lines'] > 0 else 0
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
# ========== HELPERS ==========
|
|
490
|
+
|
|
491
|
+
def _sanitize_filename(self, title: str) -> str:
|
|
492
|
+
"""Convert section title to valid filename."""
|
|
493
|
+
# Remove special characters
|
|
494
|
+
filename = re.sub(r'[^\w\s-]', '', title)
|
|
495
|
+
# Replace spaces with hyphens
|
|
496
|
+
filename = filename.lower().replace(' ', '-')
|
|
497
|
+
# Remove multiple hyphens
|
|
498
|
+
filename = re.sub(r'-+', '-', filename)
|
|
499
|
+
return filename.strip('-')
|
|
500
|
+
|
|
501
|
+
def _generate_skill_name(self) -> str:
|
|
502
|
+
"""Auto-generate skill name from source."""
|
|
503
|
+
name = self.source_path.stem
|
|
504
|
+
name = re.sub(r'[^\w-]', '-', name)
|
|
505
|
+
name = re.sub(r'-+', '-', name)
|
|
506
|
+
return name.lower().strip('-')
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
def main():
|
|
510
|
+
"""CLI entry point."""
|
|
511
|
+
parser = argparse.ArgumentParser(
|
|
512
|
+
description="Convert documentation to skill format (AGENT-LAYER TOOL)",
|
|
513
|
+
epilog="References: File 10 for skill structure | Files 01-13 for best practices"
|
|
514
|
+
)
|
|
515
|
+
parser.add_argument(
|
|
516
|
+
'source',
|
|
517
|
+
type=str,
|
|
518
|
+
help='Source document path (MD or TXT)'
|
|
519
|
+
)
|
|
520
|
+
parser.add_argument(
|
|
521
|
+
'--skill-name',
|
|
522
|
+
type=str,
|
|
523
|
+
help='Skill name (auto-generated if not specified)'
|
|
524
|
+
)
|
|
525
|
+
parser.add_argument(
|
|
526
|
+
'--output-dir',
|
|
527
|
+
type=str,
|
|
528
|
+
help='Output directory (current dir if not specified)'
|
|
529
|
+
)
|
|
530
|
+
parser.add_argument(
|
|
531
|
+
'--preview',
|
|
532
|
+
action='store_true',
|
|
533
|
+
help='Preview conversion without executing'
|
|
534
|
+
)
|
|
535
|
+
parser.add_argument(
|
|
536
|
+
'--format',
|
|
537
|
+
choices=['text', 'json'],
|
|
538
|
+
default='text',
|
|
539
|
+
help='Output format (json for agent-layer, text for human)'
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
args = parser.parse_args()
|
|
543
|
+
|
|
544
|
+
try:
|
|
545
|
+
helper = MigrationHelper(
|
|
546
|
+
args.source,
|
|
547
|
+
skill_name=args.skill_name,
|
|
548
|
+
output_dir=args.output_dir,
|
|
549
|
+
preview=args.preview
|
|
550
|
+
)
|
|
551
|
+
|
|
552
|
+
# Parse source
|
|
553
|
+
parsed = helper.parse_source()
|
|
554
|
+
|
|
555
|
+
# Plan conversion
|
|
556
|
+
plan = helper.plan_conversion()
|
|
557
|
+
|
|
558
|
+
# Execute or preview
|
|
559
|
+
result = helper.execute_conversion(plan)
|
|
560
|
+
|
|
561
|
+
# Agent-layer JSON output
|
|
562
|
+
if args.format == 'json':
|
|
563
|
+
report = {
|
|
564
|
+
'status': 'success',
|
|
565
|
+
'source': str(helper.source_path),
|
|
566
|
+
'format': parsed['format'],
|
|
567
|
+
'skill_name': result.get('skill_path', plan['skill_name']),
|
|
568
|
+
'preview': args.preview,
|
|
569
|
+
'conversion': {
|
|
570
|
+
'source_lines': plan['source_lines'],
|
|
571
|
+
'skill_md_lines': plan['skill_md_lines'],
|
|
572
|
+
'core_sections': result['core_sections'],
|
|
573
|
+
'reference_sections': result['reference_sections'],
|
|
574
|
+
'reduction_percent': result.get('reduction_percent', 0)
|
|
575
|
+
},
|
|
576
|
+
'output': {
|
|
577
|
+
'skill_path': result.get('skill_path'),
|
|
578
|
+
'skill_md': result.get('skill_md'),
|
|
579
|
+
'references': result.get('references', []),
|
|
580
|
+
'report': result.get('report')
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
print(json.dumps(report, indent=2))
|
|
584
|
+
return 0
|
|
585
|
+
|
|
586
|
+
# Human-readable text output
|
|
587
|
+
if args.preview:
|
|
588
|
+
print("\n" + "="*60)
|
|
589
|
+
print("CONVERSION PREVIEW")
|
|
590
|
+
print("="*60)
|
|
591
|
+
print(f"\nSource: {helper.source_path}")
|
|
592
|
+
print(f"Format: {parsed['format']}")
|
|
593
|
+
print(f"Skill name: {plan['skill_name']}")
|
|
594
|
+
print(f"Output: {plan['output_path']}")
|
|
595
|
+
print(f"\nSections:")
|
|
596
|
+
print(f" Core (→ SKILL.md): {plan['core_sections']}")
|
|
597
|
+
print(f" Reference (→ references/): {plan['reference_sections']}")
|
|
598
|
+
print(f"\nEstimates:")
|
|
599
|
+
print(f" Source lines: {plan['source_lines']}")
|
|
600
|
+
print(f" SKILL.md lines: {plan['skill_md_lines']}")
|
|
601
|
+
print(f" Reduction: {round((1 - plan['skill_md_lines'] / plan['source_lines']) * 100, 1)}%")
|
|
602
|
+
print(f" Tokens: ~{plan['estimated_tokens']}")
|
|
603
|
+
print("="*60)
|
|
604
|
+
print("\nUse without --preview to execute conversion.")
|
|
605
|
+
else:
|
|
606
|
+
print("\n" + "="*60)
|
|
607
|
+
print("CONVERSION COMPLETE")
|
|
608
|
+
print("="*60)
|
|
609
|
+
print(f"\n✅ Skill created: {result['skill_path']}")
|
|
610
|
+
print(f" SKILL.md: {plan['skill_md_lines']} lines")
|
|
611
|
+
print(f" Core sections: {result['core_sections']}")
|
|
612
|
+
print(f" Reference files: {result['reference_sections']}")
|
|
613
|
+
print(f" Reduction: {result['reduction_percent']}%")
|
|
614
|
+
print(f"\n📄 Files created:")
|
|
615
|
+
print(f" - SKILL.md")
|
|
616
|
+
if result['references']:
|
|
617
|
+
print(f" - references/ ({len(result['references'])} files)")
|
|
618
|
+
print(f" - conversion_report.md")
|
|
619
|
+
print("\n" + "="*60)
|
|
620
|
+
print("Next steps:")
|
|
621
|
+
print(" 1. Review SKILL.md")
|
|
622
|
+
print(" 2. Update frontmatter description")
|
|
623
|
+
print(f" 3. Validate: python validate_skill.py {result['skill_path']}/")
|
|
624
|
+
print("="*60 + "\n")
|
|
625
|
+
|
|
626
|
+
return 0
|
|
627
|
+
|
|
628
|
+
except FileNotFoundError as e:
|
|
629
|
+
if args.format == 'json':
|
|
630
|
+
error_report = {
|
|
631
|
+
'status': 'error',
|
|
632
|
+
'error_type': 'FileNotFound',
|
|
633
|
+
'message': str(e),
|
|
634
|
+
'help': 'Ensure source file exists and path is correct'
|
|
635
|
+
}
|
|
636
|
+
print(json.dumps(error_report, indent=2))
|
|
637
|
+
else:
|
|
638
|
+
print(f"⌠Error: {e}")
|
|
639
|
+
return 1
|
|
640
|
+
|
|
641
|
+
except ValueError as e:
|
|
642
|
+
if args.format == 'json':
|
|
643
|
+
error_report = {
|
|
644
|
+
'status': 'error',
|
|
645
|
+
'error_type': 'UnsupportedFormat',
|
|
646
|
+
'message': str(e),
|
|
647
|
+
'help': 'Only .md, .markdown, and .txt files are supported'
|
|
648
|
+
}
|
|
649
|
+
print(json.dumps(error_report, indent=2))
|
|
650
|
+
else:
|
|
651
|
+
print(f"⌠Error: {e}")
|
|
652
|
+
return 1
|
|
653
|
+
|
|
654
|
+
except Exception as e:
|
|
655
|
+
if args.format == 'json':
|
|
656
|
+
error_report = {
|
|
657
|
+
'status': 'error',
|
|
658
|
+
'error_type': 'UnexpectedError',
|
|
659
|
+
'message': str(e),
|
|
660
|
+
'help': 'Check file permissions and content format'
|
|
661
|
+
}
|
|
662
|
+
print(json.dumps(error_report, indent=2))
|
|
663
|
+
else:
|
|
664
|
+
print(f"⌠Unexpected error: {e}")
|
|
665
|
+
return 2
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
if __name__ == "__main__":
|
|
669
|
+
exit(main())
|