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.
- package/CHANGELOG.md +33 -0
- package/README.md +29 -14
- package/commands/demo.md +1 -1
- package/dist/context-bus.js +70 -0
- package/dist/context-db.js +265 -0
- package/dist/continuity.js +12 -0
- package/dist/file-watcher.js +79 -0
- package/dist/index.js +152 -1
- package/dist/l0-indexer.js +158 -0
- package/dist/mcp-context-server.js +400 -0
- package/dist/migrate-json-to-sqlite.js +126 -0
- package/dist/skill-chain.js +19 -3
- package/dist/token-budget.js +108 -0
- package/dist/uri-resolver.js +203 -0
- package/package.json +7 -1
- package/skills/_shared/helpers.md +50 -14
- package/skills/cm-autopilot/SKILL.md +29 -0
- package/skills/cm-autopilot/scripts/autopilot.py +190 -0
- package/skills/cm-continuity/SKILL.md +90 -28
- package/skills/cm-quality-gate/SKILL.md +11 -1
- package/skills/cm-safe-deploy/SKILL.md +38 -2
- package/skills/cm-security-gate/SKILL.md +158 -34
- package/skills/cm-skill-chain/SKILL.md +47 -1
- package/skills/cm-start/SKILL.md +11 -2
- package/skills/cm-test-gate/SKILL.md +3 -0
- package/skills/boxme-git-config/SKILL.md +0 -56
- package/skills/boxme-local-dev/SKILL.md +0 -66
- package/skills/jobs-to-be-done/SKILL.md +0 -266
- package/skills/jobs-to-be-done/references/case-studies.md +0 -154
- package/skills/jobs-to-be-done/references/competitive-strategy.md +0 -280
- package/skills/jobs-to-be-done/references/diagnostics.md +0 -158
- package/skills/jobs-to-be-done/references/innovation-process.md +0 -392
- package/skills/jobs-to-be-done/references/organizational-change.md +0 -328
- package/skills/marketplace-report-crawler/SKILL.md +0 -176
- package/skills/marketplace-report-crawler/config/accounts.json +0 -41
- package/skills/marketplace-report-crawler/config/report-types.json +0 -422
- package/skills/marketplace-report-crawler/config/sessions.json +0 -3
- package/skills/marketplace-report-crawler/scripts/ab-wrapper.sh +0 -102
- package/skills/marketplace-report-crawler/scripts/browser-actions/lazada/lazada-actions.js +0 -114
- package/skills/marketplace-report-crawler/scripts/browser-actions/shopee/shopee-actions.js +0 -94
- package/skills/marketplace-report-crawler/scripts/browser-actions/tiktok/tiktok-actions.js +0 -272
- package/skills/marketplace-report-crawler/scripts/crawl-runner.js +0 -281
- package/skills/marketplace-report-crawler/scripts/session-check.sh +0 -72
- package/skills/marketplace-report-crawler/scripts/session-manager.sh +0 -349
- package/skills/marketplace-report-crawler/scripts/setup-folders.sh +0 -83
- package/skills/medical-research/SKILL.md +0 -194
- package/skills/medical-research/scripts/evidence_checker.py +0 -288
- package/skills/mom-test/SKILL.md +0 -267
- package/skills/mom-test/references/avoiding-bad-data.md +0 -221
- package/skills/mom-test/references/case-studies.md +0 -306
- package/skills/mom-test/references/commitment-advancement.md +0 -219
- package/skills/mom-test/references/finding-conversations.md +0 -251
- package/skills/mom-test/references/processing-learning.md +0 -256
- package/skills/mom-test/references/question-patterns.md +0 -198
- package/skills/pandasai-analytics/SKILL.md +0 -251
- package/skills/release-it/SKILL.md +0 -235
- package/skills/release-it/references/anti-patterns.md +0 -279
- package/skills/release-it/references/capacity-planning.md +0 -285
- package/skills/release-it/references/chaos-engineering.md +0 -325
- package/skills/release-it/references/deployment-strategies.md +0 -331
- package/skills/release-it/references/observability.md +0 -301
- package/skills/release-it/references/stability-patterns.md +0 -355
- package/skills/skill-creator-ultra/.agents/workflows/skill-audit.md +0 -37
- package/skills/skill-creator-ultra/.agents/workflows/skill-compare.md +0 -34
- package/skills/skill-creator-ultra/.agents/workflows/skill-export.md +0 -51
- package/skills/skill-creator-ultra/.agents/workflows/skill-generate.md +0 -39
- package/skills/skill-creator-ultra/.agents/workflows/skill-scaffold.md +0 -52
- package/skills/skill-creator-ultra/.agents/workflows/skill-simulate.md +0 -25
- package/skills/skill-creator-ultra/.agents/workflows/skill-stats.md +0 -31
- package/skills/skill-creator-ultra/.agents/workflows/skill-validate.md +0 -25
- package/skills/skill-creator-ultra/README.md +0 -1242
- package/skills/skill-creator-ultra/SKILL.md +0 -388
- package/skills/skill-creator-ultra/agents/analyzer.md +0 -274
- package/skills/skill-creator-ultra/agents/comparator.md +0 -202
- package/skills/skill-creator-ultra/agents/grader.md +0 -223
- package/skills/skill-creator-ultra/assets/eval_review.html +0 -146
- package/skills/skill-creator-ultra/eval-viewer/generate_review.py +0 -471
- package/skills/skill-creator-ultra/eval-viewer/viewer.html +0 -1325
- package/skills/skill-creator-ultra/examples/example_anthropic_frontend.md +0 -109
- package/skills/skill-creator-ultra/examples/example_anthropic_pdf.md +0 -116
- package/skills/skill-creator-ultra/examples/example_api_docs.md +0 -189
- package/skills/skill-creator-ultra/examples/example_db_migration.md +0 -253
- package/skills/skill-creator-ultra/examples/example_git_commit.md +0 -111
- package/skills/skill-creator-ultra/install.ps1 +0 -289
- package/skills/skill-creator-ultra/install.sh +0 -313
- package/skills/skill-creator-ultra/phases/phase1_interview.md +0 -202
- package/skills/skill-creator-ultra/phases/phase2_extract.md +0 -55
- package/skills/skill-creator-ultra/phases/phase3_detect.md +0 -57
- package/skills/skill-creator-ultra/phases/phase4_generate.md +0 -543
- package/skills/skill-creator-ultra/phases/phase5_test.md +0 -319
- package/skills/skill-creator-ultra/phases/phase6_eval.md +0 -301
- package/skills/skill-creator-ultra/phases/phase7_iterate.md +0 -103
- package/skills/skill-creator-ultra/phases/phase8_optimize.md +0 -113
- package/skills/skill-creator-ultra/resources/advanced_patterns.md +0 -499
- package/skills/skill-creator-ultra/resources/anti_patterns.md +0 -376
- package/skills/skill-creator-ultra/resources/blueprints.md +0 -498
- package/skills/skill-creator-ultra/resources/checklist.md +0 -243
- package/skills/skill-creator-ultra/resources/composition_cookbook.md +0 -291
- package/skills/skill-creator-ultra/resources/description_optimization.md +0 -90
- package/skills/skill-creator-ultra/resources/eval_guide.md +0 -133
- package/skills/skill-creator-ultra/resources/industry_questions.md +0 -189
- package/skills/skill-creator-ultra/resources/interview_questions.md +0 -200
- package/skills/skill-creator-ultra/resources/pattern_detection.md +0 -200
- package/skills/skill-creator-ultra/resources/prompt_engineering.md +0 -531
- package/skills/skill-creator-ultra/resources/schemas.md +0 -430
- package/skills/skill-creator-ultra/resources/script_integration.md +0 -593
- package/skills/skill-creator-ultra/resources/scripts_guide.md +0 -339
- package/skills/skill-creator-ultra/resources/skill_template.md +0 -124
- package/skills/skill-creator-ultra/resources/skill_writing_guide.md +0 -634
- package/skills/skill-creator-ultra/resources/versioning_guide.md +0 -193
- package/skills/skill-creator-ultra/scripts/ci_eval.py +0 -200
- package/skills/skill-creator-ultra/scripts/package_skill.py +0 -165
- package/skills/skill-creator-ultra/scripts/simulate_skill.py +0 -398
- package/skills/skill-creator-ultra/scripts/skill_audit.py +0 -611
- package/skills/skill-creator-ultra/scripts/skill_compare.py +0 -265
- package/skills/skill-creator-ultra/scripts/skill_export.py +0 -334
- package/skills/skill-creator-ultra/scripts/skill_scaffold.py +0 -403
- package/skills/skill-creator-ultra/scripts/skill_stats.py +0 -339
- package/skills/skill-creator-ultra/scripts/validate_skill.py +0 -411
- package/skills/tailwind-mastery/SKILL.md +0 -229
- package/skills/vercel-react-best-practices/AGENTS.md +0 -3373
- package/skills/vercel-react-best-practices/README.md +0 -123
- package/skills/vercel-react-best-practices/SKILL.md +0 -143
- package/skills/vercel-react-best-practices/rules/_sections.md +0 -46
- package/skills/vercel-react-best-practices/rules/_template.md +0 -28
- package/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
- package/skills/vercel-react-best-practices/rules/advanced-init-once.md +0 -42
- package/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -39
- package/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
- package/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -80
- package/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -51
- package/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
- package/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
- package/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -59
- package/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
- package/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
- package/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
- package/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
- package/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
- package/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
- package/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
- package/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
- package/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -107
- package/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
- package/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
- package/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
- package/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
- package/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
- package/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +0 -60
- package/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
- package/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
- package/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
- package/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
- package/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
- package/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
- package/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
- package/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
- package/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
- package/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
- package/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
- package/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
- package/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +0 -30
- package/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +0 -85
- package/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +0 -68
- package/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
- package/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +0 -75
- package/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
- package/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
- package/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +0 -40
- package/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
- package/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
- package/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
- package/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +0 -38
- package/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
- package/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +0 -45
- package/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +0 -82
- package/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -35
- package/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +0 -64
- package/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
- package/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +0 -59
- package/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +0 -73
- package/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
- package/skills/vercel-react-best-practices/rules/server-auth-actions.md +0 -96
- package/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
- package/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
- package/skills/vercel-react-best-practices/rules/server-dedup-props.md +0 -65
- package/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +0 -142
- package/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
- package/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
- package/skills/web-design-guidelines/SKILL.md +0 -39
|
@@ -1,398 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
simulate_skill.py — Mô phỏng chạy thử Skill với input giả
|
|
4
|
-
|
|
5
|
-
Sử dụng:
|
|
6
|
-
python simulate_skill.py /path/to/SKILL.md
|
|
7
|
-
|
|
8
|
-
Script sẽ:
|
|
9
|
-
1. Parse SKILL.md
|
|
10
|
-
2. Trích xuất Instructions (các bước)
|
|
11
|
-
3. Trích xuất Examples (input/output mẫu)
|
|
12
|
-
4. Mô phỏng "dry run" — đi qua từng bước
|
|
13
|
-
5. Report: Bước nào rõ ràng, bước nào mơ hồ
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
import sys
|
|
17
|
-
import os
|
|
18
|
-
import re
|
|
19
|
-
from pathlib import Path
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class Colors:
|
|
23
|
-
PASS = '\033[92m'
|
|
24
|
-
FAIL = '\033[91m'
|
|
25
|
-
WARN = '\033[93m'
|
|
26
|
-
INFO = '\033[96m'
|
|
27
|
-
BOLD = '\033[1m'
|
|
28
|
-
DIM = '\033[2m'
|
|
29
|
-
RESET = '\033[0m'
|
|
30
|
-
|
|
31
|
-
@staticmethod
|
|
32
|
-
def enable_windows():
|
|
33
|
-
if os.name == 'nt':
|
|
34
|
-
try:
|
|
35
|
-
import ctypes
|
|
36
|
-
kernel32 = ctypes.windll.kernel32
|
|
37
|
-
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
|
|
38
|
-
except Exception:
|
|
39
|
-
pass
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def parse_frontmatter(content):
|
|
43
|
-
"""Trích xuất YAML frontmatter."""
|
|
44
|
-
pattern = r'^---\s*\n(.*?)\n---\s*\n(.*)$'
|
|
45
|
-
match = re.match(pattern, content, re.DOTALL)
|
|
46
|
-
if not match:
|
|
47
|
-
return {}, content
|
|
48
|
-
|
|
49
|
-
yaml_content = match.group(1)
|
|
50
|
-
body = match.group(2)
|
|
51
|
-
|
|
52
|
-
frontmatter = {}
|
|
53
|
-
current_key = None
|
|
54
|
-
current_value = []
|
|
55
|
-
|
|
56
|
-
for line in yaml_content.strip().split('\n'):
|
|
57
|
-
if ':' in line and not line.startswith(' ') and not line.startswith('\t'):
|
|
58
|
-
if current_key:
|
|
59
|
-
frontmatter[current_key] = '\n'.join(current_value).strip().strip('"').strip("'")
|
|
60
|
-
key, _, value = line.partition(':')
|
|
61
|
-
current_key = key.strip()
|
|
62
|
-
current_value = [value.strip().strip('"').strip("'").strip('|')]
|
|
63
|
-
elif current_key:
|
|
64
|
-
current_value.append(line.strip())
|
|
65
|
-
|
|
66
|
-
if current_key:
|
|
67
|
-
frontmatter[current_key] = '\n'.join(current_value).strip()
|
|
68
|
-
|
|
69
|
-
return frontmatter, body
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def extract_steps(body):
|
|
73
|
-
"""Trích xuất các bước từ Instructions section."""
|
|
74
|
-
steps = []
|
|
75
|
-
in_instructions = False
|
|
76
|
-
current_step = None
|
|
77
|
-
|
|
78
|
-
for line in body.split('\n'):
|
|
79
|
-
stripped = line.strip()
|
|
80
|
-
|
|
81
|
-
# Bắt đầu section Instructions
|
|
82
|
-
if re.match(r'^#{1,2}\s+Instructions', stripped, re.IGNORECASE):
|
|
83
|
-
in_instructions = True
|
|
84
|
-
continue
|
|
85
|
-
|
|
86
|
-
# Kết thúc section (gặp heading mới cùng level)
|
|
87
|
-
if in_instructions and re.match(r'^#{1,2}\s+(?!Bước|Step|Stage)', stripped):
|
|
88
|
-
if not re.match(r'^#{3,}', stripped):
|
|
89
|
-
break
|
|
90
|
-
|
|
91
|
-
if in_instructions:
|
|
92
|
-
# Tìm numbered step
|
|
93
|
-
step_match = re.match(r'^(\d+)\.\s+(.+)', stripped)
|
|
94
|
-
if step_match:
|
|
95
|
-
if current_step:
|
|
96
|
-
steps.append(current_step)
|
|
97
|
-
current_step = {
|
|
98
|
-
'number': int(step_match.group(1)),
|
|
99
|
-
'text': step_match.group(2),
|
|
100
|
-
'sub_steps': [],
|
|
101
|
-
'has_condition': False,
|
|
102
|
-
'has_action': False,
|
|
103
|
-
'has_error_handling': False,
|
|
104
|
-
}
|
|
105
|
-
elif current_step and stripped.startswith(('-', '*', '•')):
|
|
106
|
-
sub = stripped.lstrip('-*• ').strip()
|
|
107
|
-
current_step['sub_steps'].append(sub)
|
|
108
|
-
|
|
109
|
-
if current_step:
|
|
110
|
-
steps.append(current_step)
|
|
111
|
-
|
|
112
|
-
return steps
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
def extract_examples(body):
|
|
116
|
-
"""Trích xuất ví dụ từ Examples section."""
|
|
117
|
-
examples = []
|
|
118
|
-
in_examples = False
|
|
119
|
-
current_example = None
|
|
120
|
-
|
|
121
|
-
for line in body.split('\n'):
|
|
122
|
-
stripped = line.strip()
|
|
123
|
-
|
|
124
|
-
if re.match(r'^#{1,2}\s+Examples', stripped, re.IGNORECASE):
|
|
125
|
-
in_examples = True
|
|
126
|
-
continue
|
|
127
|
-
|
|
128
|
-
if in_examples and re.match(r'^#{1,2}\s+(?!Ví dụ|Example)', stripped):
|
|
129
|
-
if not re.match(r'^#{3,}', stripped):
|
|
130
|
-
break
|
|
131
|
-
|
|
132
|
-
if in_examples:
|
|
133
|
-
example_match = re.match(r'^#{2,3}\s+(?:Ví dụ|Example)\s*\d*[:.]\s*(.*)', stripped, re.IGNORECASE)
|
|
134
|
-
if example_match:
|
|
135
|
-
if current_example:
|
|
136
|
-
examples.append(current_example)
|
|
137
|
-
current_example = {
|
|
138
|
-
'title': example_match.group(1),
|
|
139
|
-
'has_input': False,
|
|
140
|
-
'has_output': False,
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if current_example:
|
|
144
|
-
if re.match(r'\*\*Input', stripped, re.IGNORECASE):
|
|
145
|
-
current_example['has_input'] = True
|
|
146
|
-
if re.match(r'\*\*Output', stripped, re.IGNORECASE):
|
|
147
|
-
current_example['has_output'] = True
|
|
148
|
-
|
|
149
|
-
if current_example:
|
|
150
|
-
examples.append(current_example)
|
|
151
|
-
|
|
152
|
-
return examples
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
def extract_constraints(body):
|
|
156
|
-
"""Trích xuất constraints."""
|
|
157
|
-
constraints = []
|
|
158
|
-
in_constraints = False
|
|
159
|
-
|
|
160
|
-
for line in body.split('\n'):
|
|
161
|
-
stripped = line.strip()
|
|
162
|
-
|
|
163
|
-
if re.match(r'^#{1,2}\s+Constraints', stripped, re.IGNORECASE):
|
|
164
|
-
in_constraints = True
|
|
165
|
-
continue
|
|
166
|
-
|
|
167
|
-
if in_constraints and re.match(r'^#{1,2}\s+', stripped):
|
|
168
|
-
if not re.match(r'^#{3,}', stripped):
|
|
169
|
-
break
|
|
170
|
-
|
|
171
|
-
if in_constraints:
|
|
172
|
-
constraint_match = re.match(r'^[-*]\s+(.+)', stripped)
|
|
173
|
-
if constraint_match:
|
|
174
|
-
text = constraint_match.group(1)
|
|
175
|
-
is_negative = any(kw in text.upper() for kw in ['KHÔNG ĐƯỢC', 'KHÔNG BAO GIỜ', 'TUYỆT ĐỐI KHÔNG', 'NEVER', '🚫'])
|
|
176
|
-
is_positive = any(kw in text.upper() for kw in ['LUÔN LUÔN', 'ALWAYS', 'BẮT BUỘC', '✅'])
|
|
177
|
-
constraints.append({
|
|
178
|
-
'text': text,
|
|
179
|
-
'type': 'negative' if is_negative else ('positive' if is_positive else 'neutral'),
|
|
180
|
-
})
|
|
181
|
-
|
|
182
|
-
return constraints
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
# Danh sách từ mơ hồ cần cảnh báo
|
|
186
|
-
AMBIGUOUS_WORDS = [
|
|
187
|
-
('xử lý', 'parse/validate/transform/filter'),
|
|
188
|
-
('kiểm tra', 'so sánh X với Y / đảm bảo X ≥ 0'),
|
|
189
|
-
('tối ưu', 'giảm thời gian <2s / giảm bundle <500KB'),
|
|
190
|
-
('phù hợp', 'khớp regex / thuộc danh sách X'),
|
|
191
|
-
('tốt', 'pass test / response <200ms'),
|
|
192
|
-
('sạch', 'không duplicate / function <30 dòng'),
|
|
193
|
-
('nhiều', '≥5 items / >1000 rows'),
|
|
194
|
-
('lớn', '>10MB / >1000 records'),
|
|
195
|
-
('nhanh', '<2s / <100ms'),
|
|
196
|
-
]
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
def analyze_step(step):
|
|
200
|
-
"""Phân tích chất lượng 1 bước."""
|
|
201
|
-
issues = []
|
|
202
|
-
text = step['text'].lower()
|
|
203
|
-
all_text = text + ' ' + ' '.join(s.lower() for s in step['sub_steps'])
|
|
204
|
-
|
|
205
|
-
# Check conditional logic
|
|
206
|
-
step['has_condition'] = any(kw in all_text for kw in ['nếu', 'if', 'khi', 'when', 'trường hợp'])
|
|
207
|
-
|
|
208
|
-
# Check actionable
|
|
209
|
-
action_verbs = ['đọc', 'ghi', 'chạy', 'tạo', 'xóa', 'kiểm', 'gửi', 'parse', 'scan',
|
|
210
|
-
'hỏi', 'hiển thị', 'output', 'lưu', 'copy', 'move', 'validate',
|
|
211
|
-
'generate', 'deploy', 'build', 'test', 'review', 'format',
|
|
212
|
-
'trích xuất', 'phân tích', 'so sánh', 'merge', 'sort',
|
|
213
|
-
'kích hoạt', 'báo', 'cảnh báo', 'confirm', 'xác nhận']
|
|
214
|
-
step['has_action'] = any(verb in all_text for verb in action_verbs)
|
|
215
|
-
|
|
216
|
-
# Check error handling
|
|
217
|
-
error_keywords = ['lỗi', 'fail', 'error', 'exception', 'không tìm', 'không có',
|
|
218
|
-
'nếu fail', 'nếu lỗi', 'trường hợp xấu', 'fallback']
|
|
219
|
-
step['has_error_handling'] = any(kw in all_text for kw in error_keywords)
|
|
220
|
-
|
|
221
|
-
# Check ambiguous words
|
|
222
|
-
for word, suggestion in AMBIGUOUS_WORDS:
|
|
223
|
-
if word in text:
|
|
224
|
-
issues.append(f'Từ mơ hồ "{word}" → Nên cụ thể hơn: {suggestion}')
|
|
225
|
-
|
|
226
|
-
# Check too short
|
|
227
|
-
if len(step['text'].split()) < 4 and len(step['sub_steps']) == 0:
|
|
228
|
-
issues.append('Bước quá ngắn, thiếu chi tiết')
|
|
229
|
-
|
|
230
|
-
return issues
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
def simulate(skill_path):
|
|
234
|
-
"""Chạy mô phỏng toàn bộ skill."""
|
|
235
|
-
Colors.enable_windows()
|
|
236
|
-
|
|
237
|
-
path = Path(skill_path)
|
|
238
|
-
if path.is_dir():
|
|
239
|
-
path = path / 'SKILL.md'
|
|
240
|
-
|
|
241
|
-
if not path.exists():
|
|
242
|
-
print(f"{Colors.FAIL}❌ Không tìm thấy: {path}{Colors.RESET}")
|
|
243
|
-
return False
|
|
244
|
-
|
|
245
|
-
content = path.read_text(encoding='utf-8', errors='ignore')
|
|
246
|
-
frontmatter, body = parse_frontmatter(content)
|
|
247
|
-
steps = extract_steps(body)
|
|
248
|
-
examples = extract_examples(body)
|
|
249
|
-
constraints = extract_constraints(body)
|
|
250
|
-
|
|
251
|
-
print(f"\n{Colors.BOLD}{'='*60}{Colors.RESET}")
|
|
252
|
-
print(f"{Colors.BOLD}🧪 SKILL SIMULATOR — Mô phỏng chạy thử{Colors.RESET}")
|
|
253
|
-
print(f"{Colors.BOLD}{'='*60}{Colors.RESET}")
|
|
254
|
-
|
|
255
|
-
name = frontmatter.get('name', path.parent.name)
|
|
256
|
-
desc = frontmatter.get('description', '(không có)')
|
|
257
|
-
print(f"\n{Colors.INFO}📌 Skill: {name}{Colors.RESET}")
|
|
258
|
-
print(f"{Colors.DIM}📝 {desc[:100]}{'...' if len(desc) > 100 else ''}{Colors.RESET}\n")
|
|
259
|
-
|
|
260
|
-
# ---- Simulate Steps ----
|
|
261
|
-
print(f"{Colors.BOLD}🔄 DRY RUN — Đi qua từng bước:{Colors.RESET}\n")
|
|
262
|
-
|
|
263
|
-
total_issues = 0
|
|
264
|
-
actionable_steps = 0
|
|
265
|
-
conditional_steps = 0
|
|
266
|
-
error_handled_steps = 0
|
|
267
|
-
|
|
268
|
-
for step in steps:
|
|
269
|
-
issues = analyze_step(step)
|
|
270
|
-
total_issues += len(issues)
|
|
271
|
-
|
|
272
|
-
if step['has_action']:
|
|
273
|
-
actionable_steps += 1
|
|
274
|
-
if step['has_condition']:
|
|
275
|
-
conditional_steps += 1
|
|
276
|
-
if step['has_error_handling']:
|
|
277
|
-
error_handled_steps += 1
|
|
278
|
-
|
|
279
|
-
# Status icon
|
|
280
|
-
if issues:
|
|
281
|
-
icon = f"{Colors.WARN}⚠️{Colors.RESET}"
|
|
282
|
-
elif step['has_action']:
|
|
283
|
-
icon = f"{Colors.PASS}✅{Colors.RESET}"
|
|
284
|
-
else:
|
|
285
|
-
icon = f"{Colors.WARN}🔸{Colors.RESET}"
|
|
286
|
-
|
|
287
|
-
# Flags
|
|
288
|
-
flags = []
|
|
289
|
-
if step['has_condition']:
|
|
290
|
-
flags.append('🔀 Rẽ nhánh')
|
|
291
|
-
if step['has_error_handling']:
|
|
292
|
-
flags.append('🛡️ Error handling')
|
|
293
|
-
if not step['has_action']:
|
|
294
|
-
flags.append(f'{Colors.WARN}⚠️ Thiếu hành động cụ thể{Colors.RESET}')
|
|
295
|
-
|
|
296
|
-
flag_str = f" [{', '.join(flags)}]" if flags else ""
|
|
297
|
-
|
|
298
|
-
print(f" {icon} Bước {step['number']}: {step['text'][:70]}{flag_str}")
|
|
299
|
-
|
|
300
|
-
for sub in step['sub_steps'][:3]:
|
|
301
|
-
print(f" {Colors.DIM} └─ {sub[:65]}{Colors.RESET}")
|
|
302
|
-
|
|
303
|
-
for issue in issues:
|
|
304
|
-
print(f" {Colors.WARN} ⚠️ {issue}{Colors.RESET}")
|
|
305
|
-
|
|
306
|
-
print()
|
|
307
|
-
|
|
308
|
-
# ---- Examples Analysis ----
|
|
309
|
-
print(f"{Colors.BOLD}📋 Examples Analysis:{Colors.RESET}")
|
|
310
|
-
if examples:
|
|
311
|
-
for i, ex in enumerate(examples, 1):
|
|
312
|
-
input_icon = f"{Colors.PASS}✅{Colors.RESET}" if ex['has_input'] else f"{Colors.FAIL}❌{Colors.RESET}"
|
|
313
|
-
output_icon = f"{Colors.PASS}✅{Colors.RESET}" if ex['has_output'] else f"{Colors.FAIL}❌{Colors.RESET}"
|
|
314
|
-
print(f" Ví dụ {i}: {ex['title'][:50]}")
|
|
315
|
-
print(f" Input: {input_icon} Output: {output_icon}")
|
|
316
|
-
else:
|
|
317
|
-
print(f" {Colors.WARN}⚠️ Không tìm thấy ví dụ nào!{Colors.RESET}")
|
|
318
|
-
print()
|
|
319
|
-
|
|
320
|
-
# ---- Constraints Analysis ----
|
|
321
|
-
print(f"{Colors.BOLD}🚧 Constraints Analysis:{Colors.RESET}")
|
|
322
|
-
neg_count = sum(1 for c in constraints if c['type'] == 'negative')
|
|
323
|
-
pos_count = sum(1 for c in constraints if c['type'] == 'positive')
|
|
324
|
-
neu_count = sum(1 for c in constraints if c['type'] == 'neutral')
|
|
325
|
-
|
|
326
|
-
if constraints:
|
|
327
|
-
print(f" 🚫 Negative (KHÔNG ĐƯỢC): {neg_count}")
|
|
328
|
-
print(f" ✅ Positive (LUÔN LUÔN): {pos_count}")
|
|
329
|
-
print(f" 🔸 Neutral: {neu_count}")
|
|
330
|
-
else:
|
|
331
|
-
print(f" {Colors.WARN}⚠️ Không tìm thấy constraints!{Colors.RESET}")
|
|
332
|
-
print()
|
|
333
|
-
|
|
334
|
-
# ---- Overall Score ----
|
|
335
|
-
print(f"{Colors.BOLD}{'='*60}{Colors.RESET}")
|
|
336
|
-
print(f"{Colors.BOLD}📊 SIMULATION REPORT:{Colors.RESET}\n")
|
|
337
|
-
|
|
338
|
-
metrics = [
|
|
339
|
-
('Tổng bước', len(steps), None),
|
|
340
|
-
('Bước có hành động cụ thể', actionable_steps, len(steps)),
|
|
341
|
-
('Bước có logic rẽ nhánh', conditional_steps, None),
|
|
342
|
-
('Bước có error handling', error_handled_steps, len(steps)),
|
|
343
|
-
('Ví dụ có Input+Output', sum(1 for e in examples if e['has_input'] and e['has_output']), len(examples)),
|
|
344
|
-
('Constraints (negative)', neg_count, None),
|
|
345
|
-
('Issues phát hiện', total_issues, None),
|
|
346
|
-
]
|
|
347
|
-
|
|
348
|
-
for label, value, total in metrics:
|
|
349
|
-
if total:
|
|
350
|
-
pct = value / total * 100 if total > 0 else 0
|
|
351
|
-
color = Colors.PASS if pct >= 80 else Colors.WARN if pct >= 50 else Colors.FAIL
|
|
352
|
-
print(f" {color}{label}: {value}/{total} ({pct:.0f}%){Colors.RESET}")
|
|
353
|
-
else:
|
|
354
|
-
print(f" {Colors.INFO}{label}: {value}{Colors.RESET}")
|
|
355
|
-
|
|
356
|
-
# Grade
|
|
357
|
-
print()
|
|
358
|
-
score = 0
|
|
359
|
-
if len(steps) > 0:
|
|
360
|
-
score += min(30, actionable_steps / len(steps) * 30) # 30 pts for actionable
|
|
361
|
-
score += min(20, error_handled_steps / len(steps) * 20) # 20 pts for error handling
|
|
362
|
-
score += min(20, len(examples) * 10) # 20 pts for examples (2=full)
|
|
363
|
-
score += min(15, neg_count * 5) # 15 pts for constraints
|
|
364
|
-
score -= total_issues * 3 # -3 pts per issue
|
|
365
|
-
score = max(0, min(100, score))
|
|
366
|
-
|
|
367
|
-
if score >= 90:
|
|
368
|
-
grade, msg = 'A+', '🏆 Skill mô phỏng hoàn hảo!'
|
|
369
|
-
elif score >= 80:
|
|
370
|
-
grade, msg = 'A', '👍 Skill rất tốt, sẵn sàng deploy!'
|
|
371
|
-
elif score >= 65:
|
|
372
|
-
grade, msg = 'B', '⚠️ Khá tốt, cần cải thiện một số bước.'
|
|
373
|
-
elif score >= 50:
|
|
374
|
-
grade, msg = 'C', '⚠️ Cần sửa đáng kể trước khi deploy.'
|
|
375
|
-
else:
|
|
376
|
-
grade, msg = 'F', '❌ Cần viết lại phần lớn skill.'
|
|
377
|
-
|
|
378
|
-
color = Colors.PASS if score >= 80 else Colors.WARN if score >= 50 else Colors.FAIL
|
|
379
|
-
print(f" {color}{Colors.BOLD}Score: {score:.0f}/100 — Grade: {grade}{Colors.RESET}")
|
|
380
|
-
print(f" {color}{msg}{Colors.RESET}")
|
|
381
|
-
print(f"\n{Colors.BOLD}{'='*60}{Colors.RESET}\n")
|
|
382
|
-
|
|
383
|
-
return score >= 65
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
if __name__ == '__main__':
|
|
387
|
-
if len(sys.argv) < 2:
|
|
388
|
-
print("Sử dụng: python simulate_skill.py <path-to-SKILL.md-or-skill-folder>")
|
|
389
|
-
print("Ví dụ: python simulate_skill.py ./my-skill/")
|
|
390
|
-
sys.exit(1)
|
|
391
|
-
|
|
392
|
-
target = sys.argv[1]
|
|
393
|
-
if not os.path.exists(target):
|
|
394
|
-
print(f"❌ Không tìm thấy: {target}")
|
|
395
|
-
sys.exit(1)
|
|
396
|
-
|
|
397
|
-
success = simulate(target)
|
|
398
|
-
sys.exit(0 if success else 1)
|