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