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,193 +0,0 @@
|
|
|
1
|
-
# 🔄 Versioning Guide — Hướng Dẫn Nâng Cấp Skill Theo Thời Gian
|
|
2
|
-
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
## Tại sao cần Versioning?
|
|
6
|
-
|
|
7
|
-
Skill không phải "tạo xong là xong". Theo thời gian:
|
|
8
|
-
|
|
9
|
-
- 🔧 Tool/API thay đổi → Skill lỗi thời
|
|
10
|
-
- 📈 Quy trình cải tiến → Cần cập nhật
|
|
11
|
-
- 🐛 Phát hiện bugs → Cần fix
|
|
12
|
-
- 💡 Có ý tưởng mới → Cần mở rộng
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## Quy tắc Versioning
|
|
17
|
-
|
|
18
|
-
### Semantic Versioning cho Skill: `vX.Y.Z`
|
|
19
|
-
|
|
20
|
-
| Thay đổi | Version | Ví dụ |
|
|
21
|
-
|---|---|---|
|
|
22
|
-
| **MAJOR (X)** — Breaking change, thay đổi lớn | v1.0 → v**2**.0 | Viết lại Instructions, đổi pattern |
|
|
23
|
-
| **MINOR (Y)** — Thêm tính năng, không phá cũ | v1.0 → v1.**1** | Thêm ví dụ, thêm constraint |
|
|
24
|
-
| **PATCH (Z)** — Sửa lỗi nhỏ | v1.0.0 → v1.0.**1** | Fix typo, chỉnh wording |
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## Cách ghi Version trong SKILL.md
|
|
29
|
-
|
|
30
|
-
### Thêm vào cuối YAML frontmatter
|
|
31
|
-
|
|
32
|
-
```markdown
|
|
33
|
-
---
|
|
34
|
-
name: my-skill
|
|
35
|
-
description: ...
|
|
36
|
-
version: 2.1.0
|
|
37
|
-
last_updated: 2026-06-15
|
|
38
|
-
---
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### Thêm Changelog section
|
|
42
|
-
|
|
43
|
-
```markdown
|
|
44
|
-
# Changelog
|
|
45
|
-
|
|
46
|
-
## v2.1.0 (2026-06-15)
|
|
47
|
-
### Added
|
|
48
|
-
- Thêm ví dụ edge case cho input Unicode
|
|
49
|
-
- Thêm constraint: Không xóa file gốc
|
|
50
|
-
|
|
51
|
-
### Changed
|
|
52
|
-
- Cải thiện Step 3: Thêm validation sau transform
|
|
53
|
-
|
|
54
|
-
## v2.0.0 (2026-04-01) — BREAKING
|
|
55
|
-
### Changed
|
|
56
|
-
- Viết lại Instructions theo chuỗi pipeline
|
|
57
|
-
- Đổi từ Pattern Basic → Pattern Pipeline
|
|
58
|
-
|
|
59
|
-
### Removed
|
|
60
|
-
- Bỏ Step cũ "Xử lý thủ công"
|
|
61
|
-
|
|
62
|
-
## v1.0.0 (2026-03-03)
|
|
63
|
-
- Initial release
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
---
|
|
67
|
-
|
|
68
|
-
## Quy trình nâng cấp Skill
|
|
69
|
-
|
|
70
|
-
### Step 1: Đánh giá (khi nào cần upgrade?)
|
|
71
|
-
|
|
72
|
-
Checklist review hàng quý:
|
|
73
|
-
|
|
74
|
-
- [ ] Skill có hoạt động đúng không? (Test với input mới)
|
|
75
|
-
- [ ] Tool/API skill dùng có thay đổi không?
|
|
76
|
-
- [ ] User phản hồi gì? Có pain point nào?
|
|
77
|
-
- [ ] Có anti-pattern nào trong skill hiện tại không? (Xem `anti_patterns.md`)
|
|
78
|
-
- [ ] Complexity có tăng không? Cần tách skill?
|
|
79
|
-
|
|
80
|
-
### Step 2: Lên kế hoạch
|
|
81
|
-
|
|
82
|
-
```markdown
|
|
83
|
-
## Upgrade Plan: [tên-skill] v1.0 → v2.0
|
|
84
|
-
|
|
85
|
-
### Mục tiêu:
|
|
86
|
-
- [Gì cần thay đổi]
|
|
87
|
-
|
|
88
|
-
### Thay đổi cụ thể:
|
|
89
|
-
- [ ] Instructions bước X: Thêm validation
|
|
90
|
-
- [ ] Examples: Thêm 1 edge case mới
|
|
91
|
-
- [ ] Constraints: Thêm quy tắc bảo mật
|
|
92
|
-
|
|
93
|
-
### Backward Compatibility:
|
|
94
|
-
- Có phá gì không? [CÓ/KHÔNG]
|
|
95
|
-
- Nếu CÓ → MAJOR version bump (v2.0)
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### Step 3: Thực hiện
|
|
99
|
-
|
|
100
|
-
1. Sửa SKILL.md
|
|
101
|
-
2. Cập nhật version trong frontmatter
|
|
102
|
-
3. Thêm entry vào Changelog
|
|
103
|
-
4. Chạy validate_skill.py
|
|
104
|
-
5. Test với input mẫu
|
|
105
|
-
|
|
106
|
-
### Step 4: Deploy
|
|
107
|
-
|
|
108
|
-
1. Copy file mới vào đúng vị trí (global/workspace)
|
|
109
|
-
2. Mở chat mới để AI reload skill
|
|
110
|
-
3. Test lại 1 lần
|
|
111
|
-
|
|
112
|
-
---
|
|
113
|
-
|
|
114
|
-
## Template Changelog Entry
|
|
115
|
-
|
|
116
|
-
```markdown
|
|
117
|
-
## vX.Y.Z (YYYY-MM-DD)
|
|
118
|
-
|
|
119
|
-
### Added
|
|
120
|
-
- [Tính năng mới / Ví dụ mới / Constraint mới]
|
|
121
|
-
|
|
122
|
-
### Changed
|
|
123
|
-
- [Thay đổi behavior / Cải thiện instruction]
|
|
124
|
-
|
|
125
|
-
### Fixed
|
|
126
|
-
- [Bug fix / Typo fix]
|
|
127
|
-
|
|
128
|
-
### Removed
|
|
129
|
-
- [Chức năng bị bỏ]
|
|
130
|
-
|
|
131
|
-
### Deprecated
|
|
132
|
-
- [Chức năng sẽ bỏ trong tương lai]
|
|
133
|
-
|
|
134
|
-
### Security
|
|
135
|
-
- [Cải thiện bảo mật]
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
---
|
|
139
|
-
|
|
140
|
-
## Branching Strategy (Cho team dùng Git)
|
|
141
|
-
|
|
142
|
-
```
|
|
143
|
-
main branch: Skill production (đang dùng)
|
|
144
|
-
develop branch: Skill đang phát triển
|
|
145
|
-
feature/xxx: Tính năng mới cho skill
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Workflow
|
|
149
|
-
|
|
150
|
-
```mermaid
|
|
151
|
-
gitgraph
|
|
152
|
-
commit id:"v1.0.0 release"
|
|
153
|
-
branch develop
|
|
154
|
-
commit id:"Thêm ví dụ mới"
|
|
155
|
-
commit id:"Fix constraint"
|
|
156
|
-
checkout main
|
|
157
|
-
merge develop id:"v1.1.0 release"
|
|
158
|
-
branch feature/safety
|
|
159
|
-
commit id:"Thêm Safety Check"
|
|
160
|
-
checkout develop
|
|
161
|
-
merge feature/safety
|
|
162
|
-
checkout main
|
|
163
|
-
merge develop id:"v2.0.0 release"
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
## Quy tắc Deprecation
|
|
169
|
-
|
|
170
|
-
Khi cần bỏ tính năng:
|
|
171
|
-
|
|
172
|
-
1. **Ghi chú Deprecated** trong MINOR version (v1.2)
|
|
173
|
-
|
|
174
|
-
```markdown
|
|
175
|
-
# Instructions
|
|
176
|
-
## Step 3: [DEPRECATED — Sẽ bỏ ở v2.0]
|
|
177
|
-
Dùng Step 3b thay thế.
|
|
178
|
-
|
|
179
|
-
## Step 3b: (Mới)
|
|
180
|
-
...
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
1. **Xóa thực sự** trong MAJOR version (v2.0)
|
|
184
|
-
|
|
185
|
-
2. **Ghi vào Changelog:**
|
|
186
|
-
|
|
187
|
-
```markdown
|
|
188
|
-
### Deprecated (v1.2.0)
|
|
189
|
-
- Step 3 "Xử lý thủ công" — Dùng Step 3b "Xử lý tự động" thay thế
|
|
190
|
-
|
|
191
|
-
### Removed (v2.0.0)
|
|
192
|
-
- Step 3 "Xử lý thủ công" — Đã bỏ hoàn toàn
|
|
193
|
-
```
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
ci_eval.py — Chạy skill eval trong CI/CD pipeline.
|
|
4
|
-
|
|
5
|
-
Đọc eval_results.json, kiểm tra pass/fail, return exit code phù hợp.
|
|
6
|
-
Dùng trong GitHub Actions, GitLab CI, hoặc bất kỳ CI system nào.
|
|
7
|
-
|
|
8
|
-
Usage:
|
|
9
|
-
python ci_eval.py <path/to/eval_results.json> [--min-score 80] [--strict]
|
|
10
|
-
|
|
11
|
-
Options:
|
|
12
|
-
--min-score N Minimum overall score % to pass (default: 80)
|
|
13
|
-
--strict Fail on any security warning (not just critical fails)
|
|
14
|
-
--format text|json Output format (default: text)
|
|
15
|
-
--badge Generate badge-compatible output
|
|
16
|
-
|
|
17
|
-
Examples:
|
|
18
|
-
# Basic: pass if score >= 80%
|
|
19
|
-
python ci_eval.py evals/eval_results.json
|
|
20
|
-
|
|
21
|
-
# Strict: pass if score >= 90% and zero security issues
|
|
22
|
-
python ci_eval.py evals/eval_results.json --min-score 90 --strict
|
|
23
|
-
|
|
24
|
-
# In GitHub Actions:
|
|
25
|
-
# - name: Eval skill
|
|
26
|
-
# run: python scripts/ci_eval.py evals/eval_results.json --min-score 85
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
import json
|
|
30
|
-
import sys
|
|
31
|
-
import argparse
|
|
32
|
-
from pathlib import Path
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def grade_from_score(score):
|
|
36
|
-
"""Convert percentage score to letter grade."""
|
|
37
|
-
if score >= 95:
|
|
38
|
-
return "S"
|
|
39
|
-
elif score >= 90:
|
|
40
|
-
return "A"
|
|
41
|
-
elif score >= 80:
|
|
42
|
-
return "B"
|
|
43
|
-
elif score >= 70:
|
|
44
|
-
return "C"
|
|
45
|
-
elif score >= 60:
|
|
46
|
-
return "D"
|
|
47
|
-
else:
|
|
48
|
-
return "F"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def check_security(security, strict=False):
|
|
52
|
-
"""Check security results. Returns (passed, issues)."""
|
|
53
|
-
issues = []
|
|
54
|
-
critical_checks = ["prompt_injection", "pii_exposure", "secret_leakage"]
|
|
55
|
-
warning_checks = ["scope_escape", "destructive_commands"]
|
|
56
|
-
|
|
57
|
-
for check in critical_checks:
|
|
58
|
-
result = security.get(check, "unknown")
|
|
59
|
-
if result not in ("pass", "PASS"):
|
|
60
|
-
issues.append(f"🔴 CRITICAL: {check} = {result}")
|
|
61
|
-
|
|
62
|
-
for check in warning_checks:
|
|
63
|
-
result = security.get(check, "unknown")
|
|
64
|
-
if result not in ("pass", "PASS"):
|
|
65
|
-
issues.append(f"🟡 WARNING: {check} = {result}")
|
|
66
|
-
|
|
67
|
-
if strict:
|
|
68
|
-
return len(issues) == 0, issues
|
|
69
|
-
|
|
70
|
-
# Non-strict: only fail on critical
|
|
71
|
-
critical_issues = [i for i in issues if "CRITICAL" in i]
|
|
72
|
-
return len(critical_issues) == 0, issues
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
def format_text(data, score, grade, security_passed, security_issues, min_score, verdict):
|
|
76
|
-
"""Format output as human-readable text."""
|
|
77
|
-
lines = []
|
|
78
|
-
lines.append("=" * 50)
|
|
79
|
-
lines.append(f"📊 CI EVAL REPORT — {data.get('skill', 'unknown')}")
|
|
80
|
-
lines.append("=" * 50)
|
|
81
|
-
lines.append("")
|
|
82
|
-
|
|
83
|
-
# Test results
|
|
84
|
-
tests = data.get("tests", [])
|
|
85
|
-
if tests:
|
|
86
|
-
lines.append("📋 Test Results:")
|
|
87
|
-
for t in tests:
|
|
88
|
-
name = t.get("name", "?")
|
|
89
|
-
ws = t.get("weighted_score", 0)
|
|
90
|
-
pr = t.get("pass_rate", 0)
|
|
91
|
-
lines.append(f" {name}: {ws*100:.0f}% (pass rate: {pr*100:.0f}%)")
|
|
92
|
-
lines.append("")
|
|
93
|
-
|
|
94
|
-
# Dimensions (average across tests)
|
|
95
|
-
if tests and tests[0].get("dimensions"):
|
|
96
|
-
lines.append("📊 Dimension Averages:")
|
|
97
|
-
dim_keys = ["correctness", "completeness", "format", "adherence",
|
|
98
|
-
"safety", "efficiency", "robustness"]
|
|
99
|
-
for dk in dim_keys:
|
|
100
|
-
vals = [t["dimensions"].get(dk, 0) for t in tests if "dimensions" in t]
|
|
101
|
-
avg = sum(vals) / len(vals) if vals else 0
|
|
102
|
-
bar = "█" * int(avg) + "░" * (5 - int(avg))
|
|
103
|
-
lines.append(f" {dk:20s} {avg:.1f}/5 {bar}")
|
|
104
|
-
lines.append("")
|
|
105
|
-
|
|
106
|
-
# Security
|
|
107
|
-
lines.append(f"🔐 Security: {'PASS ✅' if security_passed else 'FAIL ❌'}")
|
|
108
|
-
for issue in security_issues:
|
|
109
|
-
lines.append(f" {issue}")
|
|
110
|
-
lines.append("")
|
|
111
|
-
|
|
112
|
-
# Overall
|
|
113
|
-
lines.append(f"📈 Overall Score: {score:.0f}% ({grade})")
|
|
114
|
-
lines.append(f"🎯 Minimum: {min_score}%")
|
|
115
|
-
lines.append(f"🏁 Verdict: {verdict}")
|
|
116
|
-
lines.append("=" * 50)
|
|
117
|
-
|
|
118
|
-
return "\n".join(lines)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
def format_json_output(data, score, grade, security_passed, security_issues, verdict):
|
|
122
|
-
"""Format output as JSON for downstream tools."""
|
|
123
|
-
return json.dumps({
|
|
124
|
-
"skill": data.get("skill", "unknown"),
|
|
125
|
-
"score": round(score, 1),
|
|
126
|
-
"grade": grade,
|
|
127
|
-
"security_passed": security_passed,
|
|
128
|
-
"security_issues": security_issues,
|
|
129
|
-
"verdict": verdict
|
|
130
|
-
}, indent=2)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
def main():
|
|
134
|
-
parser = argparse.ArgumentParser(
|
|
135
|
-
description="CI/CD Skill Eval Checker — validate eval_results.json"
|
|
136
|
-
)
|
|
137
|
-
parser.add_argument("eval_file", help="Path to eval_results.json")
|
|
138
|
-
parser.add_argument("--min-score", type=float, default=80,
|
|
139
|
-
help="Minimum overall score %% to pass (default: 80)")
|
|
140
|
-
parser.add_argument("--strict", action="store_true",
|
|
141
|
-
help="Fail on any security warning (not just criticals)")
|
|
142
|
-
parser.add_argument("--format", choices=["text", "json"], default="text",
|
|
143
|
-
help="Output format")
|
|
144
|
-
parser.add_argument("--badge", action="store_true",
|
|
145
|
-
help="Print badge-compatible single line")
|
|
146
|
-
args = parser.parse_args()
|
|
147
|
-
|
|
148
|
-
# Read eval results
|
|
149
|
-
eval_path = Path(args.eval_file)
|
|
150
|
-
if not eval_path.exists():
|
|
151
|
-
print(f"❌ File not found: {eval_path}")
|
|
152
|
-
sys.exit(2)
|
|
153
|
-
|
|
154
|
-
try:
|
|
155
|
-
data = json.loads(eval_path.read_text(encoding="utf-8"))
|
|
156
|
-
except json.JSONDecodeError as e:
|
|
157
|
-
print(f"❌ Invalid JSON: {e}")
|
|
158
|
-
sys.exit(2)
|
|
159
|
-
|
|
160
|
-
# Extract score
|
|
161
|
-
score = data.get("overall_score", 0)
|
|
162
|
-
if isinstance(score, float) and score <= 1.0:
|
|
163
|
-
score *= 100 # Convert 0-1 to 0-100
|
|
164
|
-
|
|
165
|
-
grade = grade_from_score(score)
|
|
166
|
-
|
|
167
|
-
# Check security
|
|
168
|
-
security = data.get("security", {})
|
|
169
|
-
security_passed, security_issues = check_security(security, args.strict)
|
|
170
|
-
|
|
171
|
-
# Determine verdict
|
|
172
|
-
if not security_passed:
|
|
173
|
-
verdict = "BLOCKED_SECURITY"
|
|
174
|
-
elif score >= args.min_score:
|
|
175
|
-
verdict = "DEPLOY_OK"
|
|
176
|
-
else:
|
|
177
|
-
verdict = "NEEDS_ITERATION"
|
|
178
|
-
|
|
179
|
-
# Output
|
|
180
|
-
if args.badge:
|
|
181
|
-
emoji = "✅" if verdict == "DEPLOY_OK" else "❌"
|
|
182
|
-
print(f"{emoji} {grade} ({score:.0f}%) | Security: {'✅' if security_passed else '❌'}")
|
|
183
|
-
elif args.format == "json":
|
|
184
|
-
print(format_json_output(data, score, grade, security_passed,
|
|
185
|
-
security_issues, verdict))
|
|
186
|
-
else:
|
|
187
|
-
print(format_text(data, score, grade, security_passed,
|
|
188
|
-
security_issues, args.min_score, verdict))
|
|
189
|
-
|
|
190
|
-
# Exit code
|
|
191
|
-
if verdict == "DEPLOY_OK":
|
|
192
|
-
sys.exit(0)
|
|
193
|
-
elif verdict == "BLOCKED_SECURITY":
|
|
194
|
-
sys.exit(3)
|
|
195
|
-
else:
|
|
196
|
-
sys.exit(1)
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if __name__ == "__main__":
|
|
200
|
-
main()
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
package_skill.py — Đóng gói skill thành file .skill (zip) để phân phối.
|
|
4
|
-
|
|
5
|
-
Adapted from Anthropic's skill-creator package_skill.py.
|
|
6
|
-
Standalone version — không dependency ngoài Python stdlib.
|
|
7
|
-
|
|
8
|
-
Usage:
|
|
9
|
-
python package_skill.py <path/to/skill-folder> [output-directory]
|
|
10
|
-
|
|
11
|
-
Example:
|
|
12
|
-
python package_skill.py ~/.gemini/antigravity/skills/my-skill
|
|
13
|
-
python package_skill.py ~/.gemini/antigravity/skills/my-skill ./dist
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
import fnmatch
|
|
17
|
-
import sys
|
|
18
|
-
import zipfile
|
|
19
|
-
import yaml
|
|
20
|
-
from pathlib import Path
|
|
21
|
-
|
|
22
|
-
# Patterns to exclude when packaging
|
|
23
|
-
EXCLUDE_DIRS = {"__pycache__", "node_modules", ".git", "evals"}
|
|
24
|
-
EXCLUDE_GLOBS = {"*.pyc", "*.pyo"}
|
|
25
|
-
EXCLUDE_FILES = {".DS_Store", "Thumbs.db"}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def should_exclude(rel_path: Path) -> bool:
|
|
29
|
-
"""Check if a path should be excluded from packaging."""
|
|
30
|
-
parts = rel_path.parts
|
|
31
|
-
if any(part in EXCLUDE_DIRS for part in parts):
|
|
32
|
-
return True
|
|
33
|
-
name = rel_path.name
|
|
34
|
-
if name in EXCLUDE_FILES:
|
|
35
|
-
return True
|
|
36
|
-
return any(fnmatch.fnmatch(name, pat) for pat in EXCLUDE_GLOBS)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def validate_skill(skill_path: Path) -> tuple:
|
|
40
|
-
"""
|
|
41
|
-
Validate skill structure — standalone version.
|
|
42
|
-
Returns (is_valid: bool, message: str).
|
|
43
|
-
"""
|
|
44
|
-
skill_md = skill_path / "SKILL.md"
|
|
45
|
-
if not skill_md.exists():
|
|
46
|
-
return False, "SKILL.md not found"
|
|
47
|
-
|
|
48
|
-
content = skill_md.read_text(encoding="utf-8")
|
|
49
|
-
|
|
50
|
-
# Check YAML frontmatter
|
|
51
|
-
if not content.startswith("---"):
|
|
52
|
-
return False, "SKILL.md missing YAML frontmatter (---)"
|
|
53
|
-
|
|
54
|
-
try:
|
|
55
|
-
end = content.index("---", 3)
|
|
56
|
-
frontmatter = content[3:end].strip()
|
|
57
|
-
meta = yaml.safe_load(frontmatter)
|
|
58
|
-
except (ValueError, yaml.YAMLError) as e:
|
|
59
|
-
return False, f"Invalid YAML frontmatter: {e}"
|
|
60
|
-
|
|
61
|
-
if not meta or not isinstance(meta, dict):
|
|
62
|
-
return False, "YAML frontmatter is empty"
|
|
63
|
-
|
|
64
|
-
if "name" not in meta:
|
|
65
|
-
return False, "Missing 'name' in frontmatter"
|
|
66
|
-
|
|
67
|
-
if "description" not in meta:
|
|
68
|
-
return False, "Missing 'description' in frontmatter"
|
|
69
|
-
|
|
70
|
-
desc = str(meta.get("description", ""))
|
|
71
|
-
if len(desc) < 20:
|
|
72
|
-
return False, f"Description too short ({len(desc)} chars) — minimum 20"
|
|
73
|
-
|
|
74
|
-
return True, f"Valid skill: {meta['name']}"
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def package_skill(skill_path, output_dir=None):
|
|
78
|
-
"""
|
|
79
|
-
Package a skill folder into a .skill file (zip format).
|
|
80
|
-
|
|
81
|
-
Args:
|
|
82
|
-
skill_path: Path to the skill folder
|
|
83
|
-
output_dir: Optional output directory (defaults to cwd)
|
|
84
|
-
|
|
85
|
-
Returns:
|
|
86
|
-
Path to created .skill file, or None if error
|
|
87
|
-
"""
|
|
88
|
-
skill_path = Path(skill_path).resolve()
|
|
89
|
-
|
|
90
|
-
if not skill_path.exists():
|
|
91
|
-
print(f"❌ Error: Skill folder not found: {skill_path}")
|
|
92
|
-
return None
|
|
93
|
-
|
|
94
|
-
if not skill_path.is_dir():
|
|
95
|
-
print(f"❌ Error: Not a directory: {skill_path}")
|
|
96
|
-
return None
|
|
97
|
-
|
|
98
|
-
# Validate before packaging
|
|
99
|
-
print("🔍 Validating skill...")
|
|
100
|
-
valid, message = validate_skill(skill_path)
|
|
101
|
-
if not valid:
|
|
102
|
-
print(f"❌ Validation failed: {message}")
|
|
103
|
-
return None
|
|
104
|
-
print(f"✅ {message}\n")
|
|
105
|
-
|
|
106
|
-
# Output location
|
|
107
|
-
skill_name = skill_path.name
|
|
108
|
-
if output_dir:
|
|
109
|
-
output_path = Path(output_dir).resolve()
|
|
110
|
-
output_path.mkdir(parents=True, exist_ok=True)
|
|
111
|
-
else:
|
|
112
|
-
output_path = Path.cwd()
|
|
113
|
-
|
|
114
|
-
skill_filename = output_path / f"{skill_name}.skill"
|
|
115
|
-
|
|
116
|
-
# Create .skill file (zip)
|
|
117
|
-
try:
|
|
118
|
-
file_count = 0
|
|
119
|
-
with zipfile.ZipFile(skill_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
|
120
|
-
for file_path in sorted(skill_path.rglob('*')):
|
|
121
|
-
if not file_path.is_file():
|
|
122
|
-
continue
|
|
123
|
-
arcname = file_path.relative_to(skill_path.parent)
|
|
124
|
-
if should_exclude(arcname):
|
|
125
|
-
print(f" ⏭ Skipped: {arcname}")
|
|
126
|
-
continue
|
|
127
|
-
zipf.write(file_path, arcname)
|
|
128
|
-
print(f" 📄 Added: {arcname}")
|
|
129
|
-
file_count += 1
|
|
130
|
-
|
|
131
|
-
size_kb = skill_filename.stat().st_size / 1024
|
|
132
|
-
print(f"\n✅ Packaged {file_count} files → {skill_filename}")
|
|
133
|
-
print(f"📦 Size: {size_kb:.1f} KB")
|
|
134
|
-
return skill_filename
|
|
135
|
-
|
|
136
|
-
except Exception as e:
|
|
137
|
-
print(f"❌ Error creating .skill file: {e}")
|
|
138
|
-
return None
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
def main():
|
|
142
|
-
if len(sys.argv) < 2:
|
|
143
|
-
print("📦 Skill Packager — Đóng gói skill thành .skill file")
|
|
144
|
-
print()
|
|
145
|
-
print("Usage: python package_skill.py <path/to/skill> [output-dir]")
|
|
146
|
-
print()
|
|
147
|
-
print("Example:")
|
|
148
|
-
print(" python package_skill.py ~/.gemini/antigravity/skills/my-skill")
|
|
149
|
-
print(" python package_skill.py ./my-skill ./dist")
|
|
150
|
-
sys.exit(1)
|
|
151
|
-
|
|
152
|
-
skill_path = sys.argv[1]
|
|
153
|
-
output_dir = sys.argv[2] if len(sys.argv) > 2 else None
|
|
154
|
-
|
|
155
|
-
print(f"📦 Packaging skill: {skill_path}")
|
|
156
|
-
if output_dir:
|
|
157
|
-
print(f" Output: {output_dir}")
|
|
158
|
-
print()
|
|
159
|
-
|
|
160
|
-
result = package_skill(skill_path, output_dir)
|
|
161
|
-
sys.exit(0 if result else 1)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if __name__ == '__main__':
|
|
165
|
-
main()
|