codymaster 4.4.5 → 4.5.2

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 (197) 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 +5 -1
  16. package/scripts/gate-0-secrets.js +63 -0
  17. package/scripts/gate-1-syntax.js +53 -0
  18. package/scripts/gate-5-dist-verify.js +55 -0
  19. package/scripts/gate-6-smoke-test.js +30 -0
  20. package/scripts/index-codebase.sh +552 -0
  21. package/scripts/mcp-bridge.js +284 -0
  22. package/scripts/postinstall.js +301 -0
  23. package/scripts/security-fixer.js +143 -0
  24. package/scripts/security-scan.js +55 -0
  25. package/scripts/test-gemini.js +13 -0
  26. package/scripts/todo-bridge.js +112 -0
  27. package/skills/_shared/helpers.md +50 -14
  28. package/skills/cm-autopilot/SKILL.md +29 -0
  29. package/skills/cm-autopilot/scripts/autopilot.py +190 -0
  30. package/skills/cm-continuity/SKILL.md +90 -28
  31. package/skills/cm-skill-chain/SKILL.md +47 -1
  32. package/skills/cm-start/SKILL.md +11 -2
  33. package/skills/boxme-git-config/SKILL.md +0 -56
  34. package/skills/boxme-local-dev/SKILL.md +0 -66
  35. package/skills/jobs-to-be-done/SKILL.md +0 -266
  36. package/skills/jobs-to-be-done/references/case-studies.md +0 -154
  37. package/skills/jobs-to-be-done/references/competitive-strategy.md +0 -280
  38. package/skills/jobs-to-be-done/references/diagnostics.md +0 -158
  39. package/skills/jobs-to-be-done/references/innovation-process.md +0 -392
  40. package/skills/jobs-to-be-done/references/organizational-change.md +0 -328
  41. package/skills/marketplace-report-crawler/SKILL.md +0 -176
  42. package/skills/marketplace-report-crawler/config/accounts.json +0 -41
  43. package/skills/marketplace-report-crawler/config/report-types.json +0 -422
  44. package/skills/marketplace-report-crawler/config/sessions.json +0 -3
  45. package/skills/marketplace-report-crawler/scripts/ab-wrapper.sh +0 -102
  46. package/skills/marketplace-report-crawler/scripts/browser-actions/lazada/lazada-actions.js +0 -114
  47. package/skills/marketplace-report-crawler/scripts/browser-actions/shopee/shopee-actions.js +0 -94
  48. package/skills/marketplace-report-crawler/scripts/browser-actions/tiktok/tiktok-actions.js +0 -272
  49. package/skills/marketplace-report-crawler/scripts/crawl-runner.js +0 -281
  50. package/skills/marketplace-report-crawler/scripts/session-check.sh +0 -72
  51. package/skills/marketplace-report-crawler/scripts/session-manager.sh +0 -349
  52. package/skills/marketplace-report-crawler/scripts/setup-folders.sh +0 -83
  53. package/skills/medical-research/SKILL.md +0 -194
  54. package/skills/medical-research/scripts/evidence_checker.py +0 -288
  55. package/skills/mom-test/SKILL.md +0 -267
  56. package/skills/mom-test/references/avoiding-bad-data.md +0 -221
  57. package/skills/mom-test/references/case-studies.md +0 -306
  58. package/skills/mom-test/references/commitment-advancement.md +0 -219
  59. package/skills/mom-test/references/finding-conversations.md +0 -251
  60. package/skills/mom-test/references/processing-learning.md +0 -256
  61. package/skills/mom-test/references/question-patterns.md +0 -198
  62. package/skills/pandasai-analytics/SKILL.md +0 -251
  63. package/skills/release-it/SKILL.md +0 -235
  64. package/skills/release-it/references/anti-patterns.md +0 -279
  65. package/skills/release-it/references/capacity-planning.md +0 -285
  66. package/skills/release-it/references/chaos-engineering.md +0 -325
  67. package/skills/release-it/references/deployment-strategies.md +0 -331
  68. package/skills/release-it/references/observability.md +0 -301
  69. package/skills/release-it/references/stability-patterns.md +0 -355
  70. package/skills/skill-creator-ultra/.agents/workflows/skill-audit.md +0 -37
  71. package/skills/skill-creator-ultra/.agents/workflows/skill-compare.md +0 -34
  72. package/skills/skill-creator-ultra/.agents/workflows/skill-export.md +0 -51
  73. package/skills/skill-creator-ultra/.agents/workflows/skill-generate.md +0 -39
  74. package/skills/skill-creator-ultra/.agents/workflows/skill-scaffold.md +0 -52
  75. package/skills/skill-creator-ultra/.agents/workflows/skill-simulate.md +0 -25
  76. package/skills/skill-creator-ultra/.agents/workflows/skill-stats.md +0 -31
  77. package/skills/skill-creator-ultra/.agents/workflows/skill-validate.md +0 -25
  78. package/skills/skill-creator-ultra/README.md +0 -1242
  79. package/skills/skill-creator-ultra/SKILL.md +0 -388
  80. package/skills/skill-creator-ultra/agents/analyzer.md +0 -274
  81. package/skills/skill-creator-ultra/agents/comparator.md +0 -202
  82. package/skills/skill-creator-ultra/agents/grader.md +0 -223
  83. package/skills/skill-creator-ultra/assets/eval_review.html +0 -146
  84. package/skills/skill-creator-ultra/eval-viewer/generate_review.py +0 -471
  85. package/skills/skill-creator-ultra/eval-viewer/viewer.html +0 -1325
  86. package/skills/skill-creator-ultra/examples/example_anthropic_frontend.md +0 -109
  87. package/skills/skill-creator-ultra/examples/example_anthropic_pdf.md +0 -116
  88. package/skills/skill-creator-ultra/examples/example_api_docs.md +0 -189
  89. package/skills/skill-creator-ultra/examples/example_db_migration.md +0 -253
  90. package/skills/skill-creator-ultra/examples/example_git_commit.md +0 -111
  91. package/skills/skill-creator-ultra/install.ps1 +0 -289
  92. package/skills/skill-creator-ultra/install.sh +0 -313
  93. package/skills/skill-creator-ultra/phases/phase1_interview.md +0 -202
  94. package/skills/skill-creator-ultra/phases/phase2_extract.md +0 -55
  95. package/skills/skill-creator-ultra/phases/phase3_detect.md +0 -57
  96. package/skills/skill-creator-ultra/phases/phase4_generate.md +0 -543
  97. package/skills/skill-creator-ultra/phases/phase5_test.md +0 -319
  98. package/skills/skill-creator-ultra/phases/phase6_eval.md +0 -301
  99. package/skills/skill-creator-ultra/phases/phase7_iterate.md +0 -103
  100. package/skills/skill-creator-ultra/phases/phase8_optimize.md +0 -113
  101. package/skills/skill-creator-ultra/resources/advanced_patterns.md +0 -499
  102. package/skills/skill-creator-ultra/resources/anti_patterns.md +0 -376
  103. package/skills/skill-creator-ultra/resources/blueprints.md +0 -498
  104. package/skills/skill-creator-ultra/resources/checklist.md +0 -243
  105. package/skills/skill-creator-ultra/resources/composition_cookbook.md +0 -291
  106. package/skills/skill-creator-ultra/resources/description_optimization.md +0 -90
  107. package/skills/skill-creator-ultra/resources/eval_guide.md +0 -133
  108. package/skills/skill-creator-ultra/resources/industry_questions.md +0 -189
  109. package/skills/skill-creator-ultra/resources/interview_questions.md +0 -200
  110. package/skills/skill-creator-ultra/resources/pattern_detection.md +0 -200
  111. package/skills/skill-creator-ultra/resources/prompt_engineering.md +0 -531
  112. package/skills/skill-creator-ultra/resources/schemas.md +0 -430
  113. package/skills/skill-creator-ultra/resources/script_integration.md +0 -593
  114. package/skills/skill-creator-ultra/resources/scripts_guide.md +0 -339
  115. package/skills/skill-creator-ultra/resources/skill_template.md +0 -124
  116. package/skills/skill-creator-ultra/resources/skill_writing_guide.md +0 -634
  117. package/skills/skill-creator-ultra/resources/versioning_guide.md +0 -193
  118. package/skills/skill-creator-ultra/scripts/ci_eval.py +0 -200
  119. package/skills/skill-creator-ultra/scripts/package_skill.py +0 -165
  120. package/skills/skill-creator-ultra/scripts/simulate_skill.py +0 -398
  121. package/skills/skill-creator-ultra/scripts/skill_audit.py +0 -611
  122. package/skills/skill-creator-ultra/scripts/skill_compare.py +0 -265
  123. package/skills/skill-creator-ultra/scripts/skill_export.py +0 -334
  124. package/skills/skill-creator-ultra/scripts/skill_scaffold.py +0 -403
  125. package/skills/skill-creator-ultra/scripts/skill_stats.py +0 -339
  126. package/skills/skill-creator-ultra/scripts/validate_skill.py +0 -411
  127. package/skills/tailwind-mastery/SKILL.md +0 -229
  128. package/skills/vercel-react-best-practices/AGENTS.md +0 -3373
  129. package/skills/vercel-react-best-practices/README.md +0 -123
  130. package/skills/vercel-react-best-practices/SKILL.md +0 -143
  131. package/skills/vercel-react-best-practices/rules/_sections.md +0 -46
  132. package/skills/vercel-react-best-practices/rules/_template.md +0 -28
  133. package/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
  134. package/skills/vercel-react-best-practices/rules/advanced-init-once.md +0 -42
  135. package/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -39
  136. package/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
  137. package/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -80
  138. package/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -51
  139. package/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
  140. package/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
  141. package/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -59
  142. package/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
  143. package/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
  144. package/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
  145. package/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
  146. package/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
  147. package/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
  148. package/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
  149. package/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
  150. package/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -107
  151. package/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
  152. package/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
  153. package/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
  154. package/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
  155. package/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
  156. package/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +0 -60
  157. package/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
  158. package/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
  159. package/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
  160. package/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
  161. package/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
  162. package/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
  163. package/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
  164. package/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
  165. package/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
  166. package/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
  167. package/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
  168. package/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
  169. package/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +0 -30
  170. package/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +0 -85
  171. package/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +0 -68
  172. package/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
  173. package/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +0 -75
  174. package/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
  175. package/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
  176. package/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +0 -40
  177. package/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
  178. package/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
  179. package/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
  180. package/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +0 -38
  181. package/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
  182. package/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +0 -45
  183. package/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +0 -82
  184. package/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -35
  185. package/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +0 -64
  186. package/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
  187. package/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +0 -59
  188. package/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +0 -73
  189. package/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
  190. package/skills/vercel-react-best-practices/rules/server-auth-actions.md +0 -96
  191. package/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
  192. package/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
  193. package/skills/vercel-react-best-practices/rules/server-dedup-props.md +0 -65
  194. package/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +0 -142
  195. package/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
  196. package/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
  197. 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)