-
-
Notifications
You must be signed in to change notification settings - Fork 174
214 lines (199 loc) · 8.19 KB
/
Copy pathvalidate-agent-skills.yml
File metadata and controls
214 lines (199 loc) · 8.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
name: Validate Agent Skills
on:
push:
branches: [main]
paths:
- "agent-skills/**"
- ".claude-plugin/**"
pull_request:
branches: [main]
paths:
- "agent-skills/**"
- ".claude-plugin/**"
jobs:
validate-skills:
name: Validate agent skills structure and size
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
with:
persist-credentials: false
- name: Validate AGENTS.md exists
run: |
if [ ! -f "agent-skills/AGENTS.md" ]; then
echo "::error::Missing agent-skills/AGENTS.md"
exit 1
fi
echo "AGENTS.md exists"
- name: Validate plugin directory structure
run: |
ERRORS=0
if [ ! -f "agent-skills/.claude-plugin/plugin.json" ]; then
echo "::error::Missing agent-skills/.claude-plugin/plugin.json"
ERRORS=$((ERRORS + 1))
fi
if [ ! -d "agent-skills/skills" ]; then
echo "::error::Missing agent-skills/skills/ directory"
ERRORS=$((ERRORS + 1))
fi
if [ $ERRORS -gt 0 ]; then
echo "Found $ERRORS plugin structure error(s)"
exit 1
fi
echo "Plugin directory has correct structure"
- name: Validate marketplace.json exists
run: |
if [ ! -f ".claude-plugin/marketplace.json" ]; then
echo "::error::Missing .claude-plugin/marketplace.json"
exit 1
fi
echo "marketplace.json exists"
- name: Validate SKILL.md frontmatter
run: |
ERRORS=0
while IFS= read -r -d '' f; do
FIRST_LINE=$(head -1 "$f")
if [ "$FIRST_LINE" != "---" ]; then
echo "::error file=$f::Missing frontmatter delimiter (first line must be ---)"
ERRORS=$((ERRORS + 1))
fi
if ! grep -q "^name:" "$f"; then
echo "::error file=$f::Missing required 'name:' field in frontmatter"
ERRORS=$((ERRORS + 1))
fi
if ! grep -q "^description:" "$f"; then
echo "::error file=$f::Missing required 'description:' field in frontmatter"
ERRORS=$((ERRORS + 1))
fi
done < <(find agent-skills -name "SKILL.md" -print0)
if [ $ERRORS -gt 0 ]; then
echo "Found $ERRORS SKILL.md validation error(s)"
exit 1
fi
echo "All SKILL.md files have valid frontmatter"
- name: Validate skill directories contain SKILL.md
run: |
ERRORS=0
while IFS= read -r -d '' dir; do
SKILL_NAME=$(basename "$dir")
if [[ "$SKILL_NAME" == atmos-* ]] && [ ! -f "$dir/SKILL.md" ]; then
echo "::error::Missing SKILL.md in $dir"
ERRORS=$((ERRORS + 1))
fi
done < <(find agent-skills/skills -mindepth 1 -maxdepth 1 -type d -print0)
if [ $ERRORS -gt 0 ]; then
echo "Found $ERRORS missing SKILL.md file(s)"
exit 1
fi
echo "All skill directories contain SKILL.md"
- name: Check SKILL.md line count (max 500 lines per spec)
run: |
# Agent Skills spec recommends SKILL.md under 500 lines
# https://agentskills.io/specification#progressive-disclosure
MAX_LINES=500
ERRORS=0
while IFS= read -r -d '' f; do
LINES=$(wc -l < "$f")
if [ "$LINES" -gt "$MAX_LINES" ]; then
echo "::error file=$f::$LINES lines exceeds ${MAX_LINES}-line limit. Move detailed content to references/"
ERRORS=$((ERRORS + 1))
elif [ "$LINES" -gt 450 ]; then
echo "::warning file=$f::$LINES lines, approaching ${MAX_LINES}-line limit"
fi
done < <(find agent-skills -name "SKILL.md" -print0)
if [ $ERRORS -gt 0 ]; then
echo "Found $ERRORS SKILL.md file(s) exceeding the ${MAX_LINES}-line limit"
exit 1
fi
echo "All SKILL.md files are within the ${MAX_LINES}-line limit"
- name: Check file sizes (max 20KB for SKILL.md, max 25KB for references)
run: |
# Agent Skills spec recommends < 5000 tokens for SKILL.md body (~20KB)
# Reference files are loaded on demand so get a slightly higher limit
SKILL_MAX=20480 # 20KB for SKILL.md
REF_MAX=25600 # 25KB for reference files
SKILL_WARN=18432 # 18KB warning threshold
REF_WARN=23552 # 23KB warning threshold
ERRORS=0
# Check SKILL.md files
while IFS= read -r -d '' f; do
SIZE=$(wc -c < "$f")
if [ "$SIZE" -gt "$SKILL_MAX" ]; then
echo "::error file=$f::${SIZE} bytes exceeds ${SKILL_MAX}-byte limit. Move detailed content to references/"
ERRORS=$((ERRORS + 1))
elif [ "$SIZE" -gt "$SKILL_WARN" ]; then
echo "::warning file=$f::${SIZE} bytes, approaching ${SKILL_MAX}-byte limit"
fi
done < <(find agent-skills -name "SKILL.md" -print0)
# Check reference files
while IFS= read -r -d '' f; do
SIZE=$(wc -c < "$f")
if [ "$SIZE" -gt "$REF_MAX" ]; then
echo "::error file=$f::${SIZE} bytes exceeds ${REF_MAX}-byte limit. Split into smaller reference files"
ERRORS=$((ERRORS + 1))
elif [ "$SIZE" -gt "$REF_WARN" ]; then
echo "::warning file=$f::${SIZE} bytes, approaching ${REF_MAX}-byte limit"
fi
done < <(find agent-skills/skills/*/references -name "*.md" -print0 2>/dev/null)
# Check AGENTS.md (same limit as reference files)
if [ -f "agent-skills/AGENTS.md" ]; then
SIZE=$(wc -c < "agent-skills/AGENTS.md")
if [ "$SIZE" -gt "$REF_MAX" ]; then
echo "::error file=agent-skills/AGENTS.md::${SIZE} bytes exceeds ${REF_MAX}-byte limit"
ERRORS=$((ERRORS + 1))
fi
fi
if [ $ERRORS -gt 0 ]; then
echo "Found $ERRORS file(s) exceeding size limits"
exit 1
fi
echo "All skill files are within size limits"
- name: Validate code fence language tags
run: |
ERRORS=0
while IFS= read -r -d '' f; do
# Find opening code fences without language tags
# Track open/close state to skip closing fences
UNLABELED=$(awk '
/^```$/ {
if (!in_block) { print NR": "$0 }
in_block = !in_block
next
}
/^```[a-zA-Z]/ { in_block = 1; next }
/^```[^a-zA-Z]/ { print NR": "$0; next }
/^``` / { print NR": "$0; next }
' "$f")
if [ -n "$UNLABELED" ]; then
echo "::error file=$f::Unlabeled code fences found (add language tags like yaml, bash, text, json)"
echo "$UNLABELED"
ERRORS=$((ERRORS + 1))
fi
done < <(find agent-skills -name "*.md" -print0)
if [ $ERRORS -gt 0 ]; then
echo "Found $ERRORS file(s) with unlabeled code fences"
exit 1
fi
echo "All code fences have language tags"
- name: Validate plugin.json files
run: |
ERRORS=0
while IFS= read -r -d '' f; do
if ! python3 -c "import json; json.load(open('$f'))" 2>/dev/null; then
echo "::error file=$f::Invalid JSON syntax"
ERRORS=$((ERRORS + 1))
fi
done < <(find agent-skills -name "plugin.json" -print0)
# Also validate marketplace.json
if [ -f ".claude-plugin/marketplace.json" ]; then
if ! python3 -c "import json; json.load(open('.claude-plugin/marketplace.json'))" 2>/dev/null; then
echo "::error file=.claude-plugin/marketplace.json::Invalid JSON syntax"
ERRORS=$((ERRORS + 1))
fi
fi
if [ $ERRORS -gt 0 ]; then
echo "Found $ERRORS invalid JSON file(s)"
exit 1
fi
echo "All JSON manifests are valid"