codymaster 4.4.4 → 4.5.1

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 (190) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +29 -14
  3. package/commands/demo.md +1 -1
  4. package/dist/context-bus.js +70 -0
  5. package/dist/context-db.js +265 -0
  6. package/dist/continuity.js +12 -0
  7. package/dist/file-watcher.js +79 -0
  8. package/dist/index.js +152 -1
  9. package/dist/l0-indexer.js +158 -0
  10. package/dist/mcp-context-server.js +400 -0
  11. package/dist/migrate-json-to-sqlite.js +126 -0
  12. package/dist/skill-chain.js +19 -3
  13. package/dist/token-budget.js +108 -0
  14. package/dist/uri-resolver.js +203 -0
  15. package/package.json +7 -1
  16. package/skills/_shared/helpers.md +50 -14
  17. package/skills/cm-autopilot/SKILL.md +29 -0
  18. package/skills/cm-autopilot/scripts/autopilot.py +190 -0
  19. package/skills/cm-continuity/SKILL.md +90 -28
  20. package/skills/cm-quality-gate/SKILL.md +11 -1
  21. package/skills/cm-safe-deploy/SKILL.md +38 -2
  22. package/skills/cm-security-gate/SKILL.md +158 -34
  23. package/skills/cm-skill-chain/SKILL.md +47 -1
  24. package/skills/cm-start/SKILL.md +11 -2
  25. package/skills/cm-test-gate/SKILL.md +3 -0
  26. package/skills/boxme-git-config/SKILL.md +0 -56
  27. package/skills/boxme-local-dev/SKILL.md +0 -66
  28. package/skills/jobs-to-be-done/SKILL.md +0 -266
  29. package/skills/jobs-to-be-done/references/case-studies.md +0 -154
  30. package/skills/jobs-to-be-done/references/competitive-strategy.md +0 -280
  31. package/skills/jobs-to-be-done/references/diagnostics.md +0 -158
  32. package/skills/jobs-to-be-done/references/innovation-process.md +0 -392
  33. package/skills/jobs-to-be-done/references/organizational-change.md +0 -328
  34. package/skills/marketplace-report-crawler/SKILL.md +0 -176
  35. package/skills/marketplace-report-crawler/config/accounts.json +0 -41
  36. package/skills/marketplace-report-crawler/config/report-types.json +0 -422
  37. package/skills/marketplace-report-crawler/config/sessions.json +0 -3
  38. package/skills/marketplace-report-crawler/scripts/ab-wrapper.sh +0 -102
  39. package/skills/marketplace-report-crawler/scripts/browser-actions/lazada/lazada-actions.js +0 -114
  40. package/skills/marketplace-report-crawler/scripts/browser-actions/shopee/shopee-actions.js +0 -94
  41. package/skills/marketplace-report-crawler/scripts/browser-actions/tiktok/tiktok-actions.js +0 -272
  42. package/skills/marketplace-report-crawler/scripts/crawl-runner.js +0 -281
  43. package/skills/marketplace-report-crawler/scripts/session-check.sh +0 -72
  44. package/skills/marketplace-report-crawler/scripts/session-manager.sh +0 -349
  45. package/skills/marketplace-report-crawler/scripts/setup-folders.sh +0 -83
  46. package/skills/medical-research/SKILL.md +0 -194
  47. package/skills/medical-research/scripts/evidence_checker.py +0 -288
  48. package/skills/mom-test/SKILL.md +0 -267
  49. package/skills/mom-test/references/avoiding-bad-data.md +0 -221
  50. package/skills/mom-test/references/case-studies.md +0 -306
  51. package/skills/mom-test/references/commitment-advancement.md +0 -219
  52. package/skills/mom-test/references/finding-conversations.md +0 -251
  53. package/skills/mom-test/references/processing-learning.md +0 -256
  54. package/skills/mom-test/references/question-patterns.md +0 -198
  55. package/skills/pandasai-analytics/SKILL.md +0 -251
  56. package/skills/release-it/SKILL.md +0 -235
  57. package/skills/release-it/references/anti-patterns.md +0 -279
  58. package/skills/release-it/references/capacity-planning.md +0 -285
  59. package/skills/release-it/references/chaos-engineering.md +0 -325
  60. package/skills/release-it/references/deployment-strategies.md +0 -331
  61. package/skills/release-it/references/observability.md +0 -301
  62. package/skills/release-it/references/stability-patterns.md +0 -355
  63. package/skills/skill-creator-ultra/.agents/workflows/skill-audit.md +0 -37
  64. package/skills/skill-creator-ultra/.agents/workflows/skill-compare.md +0 -34
  65. package/skills/skill-creator-ultra/.agents/workflows/skill-export.md +0 -51
  66. package/skills/skill-creator-ultra/.agents/workflows/skill-generate.md +0 -39
  67. package/skills/skill-creator-ultra/.agents/workflows/skill-scaffold.md +0 -52
  68. package/skills/skill-creator-ultra/.agents/workflows/skill-simulate.md +0 -25
  69. package/skills/skill-creator-ultra/.agents/workflows/skill-stats.md +0 -31
  70. package/skills/skill-creator-ultra/.agents/workflows/skill-validate.md +0 -25
  71. package/skills/skill-creator-ultra/README.md +0 -1242
  72. package/skills/skill-creator-ultra/SKILL.md +0 -388
  73. package/skills/skill-creator-ultra/agents/analyzer.md +0 -274
  74. package/skills/skill-creator-ultra/agents/comparator.md +0 -202
  75. package/skills/skill-creator-ultra/agents/grader.md +0 -223
  76. package/skills/skill-creator-ultra/assets/eval_review.html +0 -146
  77. package/skills/skill-creator-ultra/eval-viewer/generate_review.py +0 -471
  78. package/skills/skill-creator-ultra/eval-viewer/viewer.html +0 -1325
  79. package/skills/skill-creator-ultra/examples/example_anthropic_frontend.md +0 -109
  80. package/skills/skill-creator-ultra/examples/example_anthropic_pdf.md +0 -116
  81. package/skills/skill-creator-ultra/examples/example_api_docs.md +0 -189
  82. package/skills/skill-creator-ultra/examples/example_db_migration.md +0 -253
  83. package/skills/skill-creator-ultra/examples/example_git_commit.md +0 -111
  84. package/skills/skill-creator-ultra/install.ps1 +0 -289
  85. package/skills/skill-creator-ultra/install.sh +0 -313
  86. package/skills/skill-creator-ultra/phases/phase1_interview.md +0 -202
  87. package/skills/skill-creator-ultra/phases/phase2_extract.md +0 -55
  88. package/skills/skill-creator-ultra/phases/phase3_detect.md +0 -57
  89. package/skills/skill-creator-ultra/phases/phase4_generate.md +0 -543
  90. package/skills/skill-creator-ultra/phases/phase5_test.md +0 -319
  91. package/skills/skill-creator-ultra/phases/phase6_eval.md +0 -301
  92. package/skills/skill-creator-ultra/phases/phase7_iterate.md +0 -103
  93. package/skills/skill-creator-ultra/phases/phase8_optimize.md +0 -113
  94. package/skills/skill-creator-ultra/resources/advanced_patterns.md +0 -499
  95. package/skills/skill-creator-ultra/resources/anti_patterns.md +0 -376
  96. package/skills/skill-creator-ultra/resources/blueprints.md +0 -498
  97. package/skills/skill-creator-ultra/resources/checklist.md +0 -243
  98. package/skills/skill-creator-ultra/resources/composition_cookbook.md +0 -291
  99. package/skills/skill-creator-ultra/resources/description_optimization.md +0 -90
  100. package/skills/skill-creator-ultra/resources/eval_guide.md +0 -133
  101. package/skills/skill-creator-ultra/resources/industry_questions.md +0 -189
  102. package/skills/skill-creator-ultra/resources/interview_questions.md +0 -200
  103. package/skills/skill-creator-ultra/resources/pattern_detection.md +0 -200
  104. package/skills/skill-creator-ultra/resources/prompt_engineering.md +0 -531
  105. package/skills/skill-creator-ultra/resources/schemas.md +0 -430
  106. package/skills/skill-creator-ultra/resources/script_integration.md +0 -593
  107. package/skills/skill-creator-ultra/resources/scripts_guide.md +0 -339
  108. package/skills/skill-creator-ultra/resources/skill_template.md +0 -124
  109. package/skills/skill-creator-ultra/resources/skill_writing_guide.md +0 -634
  110. package/skills/skill-creator-ultra/resources/versioning_guide.md +0 -193
  111. package/skills/skill-creator-ultra/scripts/ci_eval.py +0 -200
  112. package/skills/skill-creator-ultra/scripts/package_skill.py +0 -165
  113. package/skills/skill-creator-ultra/scripts/simulate_skill.py +0 -398
  114. package/skills/skill-creator-ultra/scripts/skill_audit.py +0 -611
  115. package/skills/skill-creator-ultra/scripts/skill_compare.py +0 -265
  116. package/skills/skill-creator-ultra/scripts/skill_export.py +0 -334
  117. package/skills/skill-creator-ultra/scripts/skill_scaffold.py +0 -403
  118. package/skills/skill-creator-ultra/scripts/skill_stats.py +0 -339
  119. package/skills/skill-creator-ultra/scripts/validate_skill.py +0 -411
  120. package/skills/tailwind-mastery/SKILL.md +0 -229
  121. package/skills/vercel-react-best-practices/AGENTS.md +0 -3373
  122. package/skills/vercel-react-best-practices/README.md +0 -123
  123. package/skills/vercel-react-best-practices/SKILL.md +0 -143
  124. package/skills/vercel-react-best-practices/rules/_sections.md +0 -46
  125. package/skills/vercel-react-best-practices/rules/_template.md +0 -28
  126. package/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
  127. package/skills/vercel-react-best-practices/rules/advanced-init-once.md +0 -42
  128. package/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -39
  129. package/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
  130. package/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -80
  131. package/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -51
  132. package/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
  133. package/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
  134. package/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -59
  135. package/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
  136. package/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
  137. package/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
  138. package/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
  139. package/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
  140. package/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
  141. package/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
  142. package/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
  143. package/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -107
  144. package/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
  145. package/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
  146. package/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
  147. package/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
  148. package/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
  149. package/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +0 -60
  150. package/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
  151. package/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
  152. package/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
  153. package/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
  154. package/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
  155. package/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
  156. package/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
  157. package/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
  158. package/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
  159. package/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
  160. package/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
  161. package/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
  162. package/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +0 -30
  163. package/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +0 -85
  164. package/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +0 -68
  165. package/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
  166. package/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +0 -75
  167. package/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
  168. package/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
  169. package/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +0 -40
  170. package/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
  171. package/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
  172. package/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
  173. package/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +0 -38
  174. package/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
  175. package/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +0 -45
  176. package/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +0 -82
  177. package/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -35
  178. package/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +0 -64
  179. package/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
  180. package/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +0 -59
  181. package/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +0 -73
  182. package/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
  183. package/skills/vercel-react-best-practices/rules/server-auth-actions.md +0 -96
  184. package/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
  185. package/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
  186. package/skills/vercel-react-best-practices/rules/server-dedup-props.md +0 -65
  187. package/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +0 -142
  188. package/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
  189. package/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
  190. package/skills/web-design-guidelines/SKILL.md +0 -39
@@ -1,265 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- skill_compare.py — So sánh 2 phiên bản Skill.md
4
-
5
- Sử dụng:
6
- python skill_compare.py /path/to/old/SKILL.md /path/to/new/SKILL.md
7
- python skill_compare.py /path/to/old-skill/ /path/to/new-skill/
8
- python skill_compare.py /path/to/old/ /path/to/new/ --json
9
-
10
- Hiển thị:
11
- - Diff tổng quan (dòng thêm/xóa/thay đổi)
12
- - So sánh sections (thêm/xóa/thay đổi kích thước)
13
- - So sánh metrics (steps, examples, constraints)
14
- - Đánh giá: cải thiện hay tệ hơn?
15
-
16
- Developed by Thân Công Hải — Skill Generator v3.2 Expert
17
- """
18
-
19
- import sys
20
- import os
21
- import re
22
- import json
23
-
24
-
25
- class Colors:
26
- PASS = '\033[92m'
27
- FAIL = '\033[91m'
28
- WARN = '\033[93m'
29
- INFO = '\033[96m'
30
- BOLD = '\033[1m'
31
- DIM = '\033[2m'
32
- RESET = '\033[0m'
33
-
34
- @staticmethod
35
- def enable_windows():
36
- if os.name == 'nt':
37
- try:
38
- import ctypes
39
- kernel32 = ctypes.windll.kernel32
40
- kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
41
- except Exception:
42
- pass
43
-
44
-
45
- Colors.enable_windows()
46
-
47
-
48
- def parse_frontmatter(content):
49
- match = re.match(r'^---\s*\n(.*?)\n---\s*\n', content, re.DOTALL)
50
- if not match:
51
- return {}, content
52
- fm_text = match.group(1)
53
- body = content[match.end():]
54
- frontmatter = {}
55
- current_key = None
56
- current_value = []
57
- for line in fm_text.split('\n'):
58
- key_match = re.match(r'^(\w+):\s*(.*)', line)
59
- if key_match:
60
- if current_key:
61
- frontmatter[current_key] = '\n'.join(current_value).strip()
62
- current_key = key_match.group(1)
63
- current_value = [key_match.group(2)] if key_match.group(2) and key_match.group(2) != '|' else []
64
- elif current_key and line.startswith(' '):
65
- current_value.append(line.strip())
66
- if current_key:
67
- frontmatter[current_key] = '\n'.join(current_value).strip()
68
- return frontmatter, body
69
-
70
-
71
- def get_metrics(content, body):
72
- """Trích xuất metrics từ skill."""
73
- return {
74
- 'lines': content.count('\n') + 1,
75
- 'words': len(content.split()),
76
- 'chars': len(content),
77
- 'h1_sections': len(re.findall(r'^#\s+', body, re.MULTILINE)),
78
- 'h2_sections': len(re.findall(r'^##\s+', body, re.MULTILINE)),
79
- 'steps': len(re.findall(r'^\d+\.', body, re.MULTILINE)),
80
- 'examples': len(re.findall(r'^##\s+.*[Vv]í dụ|^##\s+.*[Ee]xample|^###\s+.*[Vv]í dụ', body, re.MULTILINE)),
81
- 'constraints': len(re.findall(r'(KHÔNG ĐƯỢC|LUÔN LUÔN|🚫|✅)', body)),
82
- 'code_blocks': len(re.findall(r'```', body)) // 2,
83
- 'tables': len(re.findall(r'^\|.*\|$', body, re.MULTILINE)),
84
- 'error_handling': len(re.findall(r'(nếu lỗi|fallback|retry|edge case|VERIFY)', body, re.IGNORECASE)),
85
- }
86
-
87
-
88
- def get_sections(body):
89
- """Lấy danh sách sections và kích thước."""
90
- sections = {}
91
- current = None
92
- lines = 0
93
- for line in body.split('\n'):
94
- h1 = re.match(r'^#\s+(.+)', line)
95
- if h1:
96
- if current:
97
- sections[current] = lines
98
- current = h1.group(1).strip()
99
- lines = 0
100
- else:
101
- lines += 1
102
- if current:
103
- sections[current] = lines
104
- return sections
105
-
106
-
107
- def format_delta(old_val, new_val, higher_is_better=True):
108
- """Format thay đổi với màu sắc."""
109
- delta = new_val - old_val
110
- if delta == 0:
111
- return f"{Colors.DIM}= (không đổi){Colors.RESET}"
112
-
113
- if higher_is_better:
114
- color = Colors.PASS if delta > 0 else Colors.FAIL
115
- else:
116
- color = Colors.FAIL if delta > 0 else Colors.PASS
117
-
118
- sign = '+' if delta > 0 else ''
119
- pct = round(delta / old_val * 100) if old_val > 0 else 0
120
- return f"{color}{sign}{delta} ({sign}{pct}%){Colors.RESET}"
121
-
122
-
123
- def compare_skills(path_old, path_new, json_output=False):
124
- """So sánh 2 skill."""
125
-
126
- # Resolve paths
127
- skill_old = os.path.join(path_old, 'SKILL.md') if os.path.isdir(path_old) else path_old
128
- skill_new = os.path.join(path_new, 'SKILL.md') if os.path.isdir(path_new) else path_new
129
-
130
- for path, label in [(skill_old, 'OLD'), (skill_new, 'NEW')]:
131
- if not os.path.exists(path):
132
- print(f"{Colors.FAIL}❌ Không tìm thấy {label}: {path}{Colors.RESET}")
133
- return False
134
-
135
- with open(skill_old, 'r', encoding='utf-8') as f:
136
- content_old = f.read()
137
- with open(skill_new, 'r', encoding='utf-8') as f:
138
- content_new = f.read()
139
-
140
- fm_old, body_old = parse_frontmatter(content_old)
141
- fm_new, body_new = parse_frontmatter(content_new)
142
-
143
- metrics_old = get_metrics(content_old, body_old)
144
- metrics_new = get_metrics(content_new, body_new)
145
-
146
- sections_old = get_sections(body_old)
147
- sections_new = get_sections(body_new)
148
-
149
- name_old = fm_old.get('name', 'unknown')
150
- name_new = fm_new.get('name', 'unknown')
151
-
152
- # JSON output
153
- if json_output:
154
- output = {
155
- 'old': {'name': name_old, 'file': skill_old, 'metrics': metrics_old},
156
- 'new': {'name': name_new, 'file': skill_new, 'metrics': metrics_new},
157
- 'deltas': {k: metrics_new[k] - metrics_old[k] for k in metrics_old},
158
- 'sections': {
159
- 'added': [s for s in sections_new if s not in sections_old],
160
- 'removed': [s for s in sections_old if s not in sections_new],
161
- 'changed': {s: {'old': sections_old.get(s, 0), 'new': sections_new.get(s, 0)}
162
- for s in set(sections_old) & set(sections_new)
163
- if sections_old.get(s, 0) != sections_new.get(s, 0)},
164
- },
165
- }
166
- print(json.dumps(output, ensure_ascii=False, indent=2))
167
- return True
168
-
169
- # Pretty output
170
- print()
171
- print(f"{Colors.BOLD}{'=' * 60}{Colors.RESET}")
172
- print(f"{Colors.BOLD} 🔄 SKILL COMPARE — So sánh 2 phiên bản{Colors.RESET}")
173
- print(f"{Colors.BOLD}{'=' * 60}{Colors.RESET}")
174
- print(f" {Colors.DIM}OLD: {skill_old}{Colors.RESET}")
175
- print(f" {Colors.INFO}NEW: {skill_new}{Colors.RESET}")
176
- print()
177
-
178
- # Metrics comparison
179
- metric_labels = {
180
- 'lines': ('📏 Dòng', True),
181
- 'words': ('📝 Từ', True),
182
- 'steps': ('📋 Steps', True),
183
- 'examples': ('🎯 Examples', True),
184
- 'constraints': ('⚠️ Constraints', True),
185
- 'code_blocks': ('💻 Code blocks', True),
186
- 'error_handling': ('🛡️ Error handling', True),
187
- }
188
-
189
- print(f" {Colors.BOLD}📊 So sánh metrics:{Colors.RESET}")
190
- print(f" {'Metric':<22} {'OLD':>8} {'NEW':>8} {'Thay đổi'}")
191
- print(f" {'─' * 55}")
192
-
193
- improvements = 0
194
- regressions = 0
195
-
196
- for key, (label, higher_better) in metric_labels.items():
197
- old_v = metrics_old[key]
198
- new_v = metrics_new[key]
199
- delta_str = format_delta(old_v, new_v, higher_better)
200
- print(f" {label:<22} {old_v:>8} {new_v:>8} {delta_str}")
201
-
202
- delta = new_v - old_v
203
- if (higher_better and delta > 0) or (not higher_better and delta < 0):
204
- improvements += 1
205
- elif delta != 0:
206
- regressions += 1
207
-
208
- print()
209
-
210
- # Sections comparison
211
- added = [s for s in sections_new if s not in sections_old]
212
- removed = [s for s in sections_old if s not in sections_new]
213
-
214
- if added or removed:
215
- print(f" {Colors.BOLD}📋 Sections thay đổi:{Colors.RESET}")
216
- for s in added:
217
- print(f" {Colors.PASS}+ {s} ({sections_new[s]} dòng){Colors.RESET}")
218
- for s in removed:
219
- print(f" {Colors.FAIL}- {s} ({sections_old[s]} dòng){Colors.RESET}")
220
- print()
221
-
222
- # Changed sections
223
- changed = [(s, sections_old[s], sections_new[s])
224
- for s in set(sections_old) & set(sections_new)
225
- if sections_old[s] != sections_new[s]]
226
-
227
- if changed:
228
- print(f" {Colors.BOLD}📐 Sections thay đổi kích thước:{Colors.RESET}")
229
- for name, old_lines, new_lines in sorted(changed, key=lambda x: x[2] - x[1], reverse=True):
230
- delta = new_lines - old_lines
231
- color = Colors.PASS if delta > 0 else Colors.FAIL
232
- sign = '+' if delta > 0 else ''
233
- print(f" {name[:30]:<30} {old_lines:>5} → {new_lines:>5} ({color}{sign}{delta}{Colors.RESET})")
234
- print()
235
-
236
- # Overall verdict
237
- print(f"{Colors.BOLD}{'=' * 60}{Colors.RESET}")
238
- if improvements > regressions:
239
- print(f" {Colors.PASS}🎉 VERDICT: Phiên bản mới TỐT HƠN ({improvements} cải thiện, {regressions} giảm){Colors.RESET}")
240
- elif regressions > improvements:
241
- print(f" {Colors.FAIL}⚠️ VERDICT: Phiên bản mới CÓ VẤN ĐỀ ({regressions} giảm, {improvements} cải thiện){Colors.RESET}")
242
- else:
243
- print(f" {Colors.INFO}ℹ️ VERDICT: Hai phiên bản TƯƠNG ĐƯƠNG{Colors.RESET}")
244
- print(f"{Colors.BOLD}{'=' * 60}{Colors.RESET}")
245
- print()
246
-
247
- return True
248
-
249
-
250
- if __name__ == '__main__':
251
- if len(sys.argv) < 3:
252
- print("Sử dụng: python skill_compare.py <old-path> <new-path>")
253
- print("Options:")
254
- print(" --json Output dạng JSON")
255
- print()
256
- print("Ví dụ:")
257
- print(" python skill_compare.py ./my-skill-v1/ ./my-skill-v2/")
258
- print(" python skill_compare.py old-SKILL.md new-SKILL.md")
259
- sys.exit(1)
260
-
261
- target_old = sys.argv[1]
262
- target_new = sys.argv[2]
263
- json_mode = '--json' in sys.argv
264
-
265
- compare_skills(target_old, target_new, json_output=json_mode)
@@ -1,334 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- skill_export.py — Chuyển đổi SKILL.md sang format các nền tảng khác
4
-
5
- Sử dụng:
6
- python skill_export.py /path/to/SKILL.md --platform cursor
7
- python skill_export.py /path/to/skill-folder/ --platform claude
8
- python skill_export.py /path/to/skill-folder/ --platform all
9
- python skill_export.py /path/to/skill-folder/ --platform all --output ./exports/
10
-
11
- Nền tảng hỗ trợ:
12
- cursor → .cursor/rules/<name>.mdc
13
- claude → CLAUDE.md (Custom Commands)
14
- windsurf → .windsurf/rules/<name>.md
15
- cline → .clinerules (Custom Instructions)
16
- copilot → .github/copilot-instructions.md
17
- openclaw → System Prompt (text file)
18
- all → Export tất cả
19
-
20
- Developed by Thân Công Hải — Skill Generator v3.2 Expert
21
- """
22
-
23
- import sys
24
- import os
25
- import re
26
- from pathlib import Path
27
- from datetime import datetime
28
-
29
-
30
- # ============================================================
31
- # COLOR OUTPUT
32
- # ============================================================
33
-
34
- class Colors:
35
- PASS = '\033[92m'
36
- FAIL = '\033[91m'
37
- WARN = '\033[93m'
38
- INFO = '\033[96m'
39
- BOLD = '\033[1m'
40
- DIM = '\033[2m'
41
- RESET = '\033[0m'
42
-
43
- @staticmethod
44
- def enable_windows():
45
- if os.name == 'nt':
46
- try:
47
- import ctypes
48
- kernel32 = ctypes.windll.kernel32
49
- kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
50
- except Exception:
51
- pass
52
-
53
-
54
- Colors.enable_windows()
55
-
56
-
57
- # ============================================================
58
- # PARSERS
59
- # ============================================================
60
-
61
- def parse_frontmatter(content):
62
- """Trích xuất YAML frontmatter."""
63
- match = re.match(r'^---\s*\n(.*?)\n---\s*\n', content, re.DOTALL)
64
- if not match:
65
- return {}, content
66
-
67
- fm_text = match.group(1)
68
- body = content[match.end():]
69
- frontmatter = {}
70
- current_key = None
71
- current_value = []
72
-
73
- for line in fm_text.split('\n'):
74
- key_match = re.match(r'^(\w+):\s*(.*)', line)
75
- if key_match:
76
- if current_key:
77
- frontmatter[current_key] = '\n'.join(current_value).strip()
78
- current_key = key_match.group(1)
79
- current_value = [key_match.group(2)] if key_match.group(2) and key_match.group(2) != '|' else []
80
- elif current_key and line.startswith(' '):
81
- current_value.append(line.strip())
82
-
83
- if current_key:
84
- frontmatter[current_key] = '\n'.join(current_value).strip()
85
-
86
- return frontmatter, body
87
-
88
-
89
- def extract_trigger_phrases(description):
90
- """Trích xuất trigger phrases từ description."""
91
- triggers = re.findall(r'"([^"]+)"', description)
92
- return triggers
93
-
94
-
95
- # ============================================================
96
- # EXPORTERS
97
- # ============================================================
98
-
99
- def export_cursor(frontmatter, body, name):
100
- """Export sang Cursor .mdc rule format."""
101
- desc = frontmatter.get('description', '')
102
- triggers = extract_trigger_phrases(desc)
103
- trigger_str = ', '.join([f'"{t}"' for t in triggers]) if triggers else f'"{name}"'
104
-
105
- return f"""---
106
- description: {desc.split(chr(10))[0] if desc else name}
107
- globs:
108
- alwaysApply: false
109
- ---
110
-
111
- # {name}
112
-
113
- > Trigger: {trigger_str}
114
- > Converted from SKILL.md by Skill Generator v3.2
115
-
116
- {body}
117
-
118
- <!-- Generated by Skill Generator v3.2 — Export: Cursor -->
119
- """
120
-
121
-
122
- def export_claude(frontmatter, body, name):
123
- """Export sang Claude Code CLAUDE.md format."""
124
- desc = frontmatter.get('description', '')
125
-
126
- return f"""# {name}
127
-
128
- > {desc}
129
- > Converted from SKILL.md by Skill Generator v3.2
130
-
131
- {body}
132
-
133
- <!-- Generated by Skill Generator v3.2 — Export: Claude Code -->
134
- """
135
-
136
-
137
- def export_windsurf(frontmatter, body, name):
138
- """Export sang Windsurf Cascade Rule format."""
139
- desc = frontmatter.get('description', '')
140
-
141
- return f"""---
142
- trigger: manual
143
- description: {desc.split(chr(10))[0] if desc else name}
144
- ---
145
-
146
- # {name}
147
-
148
- > {desc}
149
- > Converted from SKILL.md by Skill Generator v3.2
150
-
151
- {body}
152
-
153
- <!-- Generated by Skill Generator v3.2 — Export: Windsurf -->
154
- """
155
-
156
-
157
- def export_cline(frontmatter, body, name):
158
- """Export sang Cline Custom Instructions format."""
159
- desc = frontmatter.get('description', '')
160
-
161
- return f"""# Custom Instruction: {name}
162
-
163
- ## Mô tả
164
- {desc}
165
-
166
- ## Hướng dẫn
167
- Khi user yêu cầu liên quan đến skill này, hãy tuân theo quy trình dưới đây:
168
-
169
- {body}
170
-
171
- <!-- Generated by Skill Generator v3.2 — Export: Cline -->
172
- """
173
-
174
-
175
- def export_copilot(frontmatter, body, name):
176
- """Export sang GitHub Copilot instructions format."""
177
- desc = frontmatter.get('description', '')
178
-
179
- return f"""## {name}
180
-
181
- {desc}
182
-
183
- ### Quy trình thực hiện
184
-
185
- {body}
186
-
187
- <!-- Generated by Skill Generator v3.2 — Export: GitHub Copilot -->
188
- """
189
-
190
-
191
- def export_openclaw(frontmatter, body, name):
192
- """Export sang OpenClaw System Prompt format."""
193
- desc = frontmatter.get('description', '')
194
-
195
- return f"""[SYSTEM PROMPT — {name}]
196
-
197
- Mô tả: {desc}
198
-
199
- ---
200
-
201
- {body}
202
-
203
- ---
204
- [END SYSTEM PROMPT]
205
- Generated by Skill Generator v3.2 — Export: OpenClaw
206
- """
207
-
208
-
209
- EXPORTERS = {
210
- 'cursor': {'fn': export_cursor, 'ext': '.mdc', 'dir': '.cursor/rules', 'label': 'Cursor Rule'},
211
- 'claude': {'fn': export_claude, 'ext': '.md', 'dir': '.claude/commands', 'label': 'Claude Code Command'},
212
- 'windsurf': {'fn': export_windsurf, 'ext': '.md', 'dir': '.windsurf/rules', 'label': 'Windsurf Rule'},
213
- 'cline': {'fn': export_cline, 'ext': '.md', 'dir': '.clinerules', 'label': 'Cline Instructions'},
214
- 'copilot': {'fn': export_copilot, 'ext': '.md', 'dir': '.github', 'label': 'Copilot Instructions'},
215
- 'openclaw': {'fn': export_openclaw, 'ext': '.txt', 'dir': 'openclaw', 'label': 'OpenClaw System Prompt'},
216
- }
217
-
218
-
219
- # ============================================================
220
- # MAIN
221
- # ============================================================
222
-
223
- def export_skill(target_path, platform, output_dir=None):
224
- """Chạy export cho skill."""
225
-
226
- # Tìm SKILL.md
227
- if os.path.isdir(target_path):
228
- skill_md = os.path.join(target_path, 'SKILL.md')
229
- else:
230
- skill_md = target_path
231
-
232
- if not os.path.exists(skill_md):
233
- print(f"{Colors.FAIL}❌ Không tìm thấy SKILL.md tại: {skill_md}{Colors.RESET}")
234
- return False
235
-
236
- with open(skill_md, 'r', encoding='utf-8') as f:
237
- content = f.read()
238
-
239
- frontmatter, body = parse_frontmatter(content)
240
- name = frontmatter.get('name', 'unnamed-skill')
241
-
242
- # Determine platforms
243
- platforms = list(EXPORTERS.keys()) if platform == 'all' else [platform]
244
-
245
- if output_dir is None:
246
- output_dir = os.path.join(os.path.dirname(skill_md), 'exports')
247
-
248
- os.makedirs(output_dir, exist_ok=True)
249
-
250
- print()
251
- print(f"{Colors.BOLD}{'=' * 55}{Colors.RESET}")
252
- print(f"{Colors.BOLD} 📦 SKILL EXPORT — Chuyển đổi đa nền tảng{Colors.RESET}")
253
- print(f"{Colors.BOLD} Skill: {Colors.INFO}{name}{Colors.RESET}")
254
- print(f"{Colors.BOLD}{'=' * 55}{Colors.RESET}")
255
- print()
256
-
257
- exported = 0
258
-
259
- for p in platforms:
260
- if p not in EXPORTERS:
261
- print(f" {Colors.FAIL}❌ Nền tảng '{p}' không hỗ trợ{Colors.RESET}")
262
- continue
263
-
264
- exporter = EXPORTERS[p]
265
- export_content = exporter['fn'](frontmatter, body, name)
266
-
267
- # Create platform subdirectory
268
- platform_dir = os.path.join(output_dir, p)
269
- os.makedirs(platform_dir, exist_ok=True)
270
-
271
- # Write file
272
- filename = f"{name}{exporter['ext']}"
273
- filepath = os.path.join(platform_dir, filename)
274
-
275
- with open(filepath, 'w', encoding='utf-8') as f:
276
- f.write(export_content)
277
-
278
- lines = len(export_content.split('\n'))
279
- print(f" {Colors.PASS}✅ {exporter['label']}{Colors.RESET}")
280
- print(f" 📄 {filepath}")
281
- print(f" 📏 {lines} dòng")
282
- print()
283
- exported += 1
284
-
285
- # Summary
286
- print(f"{Colors.BOLD}{'=' * 55}{Colors.RESET}")
287
- print(f" {Colors.PASS}📊 Đã export {exported}/{len(platforms)} nền tảng{Colors.RESET}")
288
- print(f" {Colors.DIM}📁 Output: {output_dir}{Colors.RESET}")
289
- print(f"{Colors.BOLD}{'=' * 55}{Colors.RESET}")
290
- print()
291
-
292
- # Usage hint
293
- print(f" {Colors.INFO}💡 Cách dùng file export:{Colors.RESET}")
294
- for p in platforms:
295
- if p in EXPORTERS:
296
- ex = EXPORTERS[p]
297
- print(f" {p}: Copy {ex['dir']}/{name}{ex['ext']} vào dự án")
298
- print()
299
-
300
- return exported > 0
301
-
302
-
303
- if __name__ == '__main__':
304
- if len(sys.argv) < 2:
305
- print("Sử dụng: python skill_export.py <path> --platform <platform>")
306
- print()
307
- print("Platforms: cursor, claude, windsurf, cline, copilot, openclaw, all")
308
- print()
309
- print("Options:")
310
- print(" --platform <name> Nền tảng đích (bắt buộc)")
311
- print(" --output <dir> Thư mục output (mặc định: ./exports/)")
312
- print()
313
- print("Ví dụ:")
314
- print(" python skill_export.py ./my-skill/ --platform cursor")
315
- print(" python skill_export.py ./my-skill/ --platform all")
316
- print(" python skill_export.py ./my-skill/ --platform all --output ./exports/")
317
- sys.exit(1)
318
-
319
- target = sys.argv[1]
320
- platform = 'all'
321
- output = None
322
-
323
- for i, arg in enumerate(sys.argv):
324
- if arg == '--platform' and i + 1 < len(sys.argv):
325
- platform = sys.argv[i + 1].lower()
326
- elif arg == '--output' and i + 1 < len(sys.argv):
327
- output = sys.argv[i + 1]
328
-
329
- if not os.path.exists(target):
330
- print(f"❌ Không tìm thấy: {target}")
331
- sys.exit(1)
332
-
333
- success = export_skill(target, platform, output)
334
- sys.exit(0 if success else 1)