buildwright 0.0.5 → 0.0.7
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/package.json +1 -1
- package/templates/.buildwright/agents/README.md +53 -0
- package/templates/.buildwright/agents/architect.md +143 -0
- package/templates/.buildwright/agents/security-engineer.md +193 -0
- package/templates/.buildwright/agents/staff-engineer.md +134 -0
- package/templates/.buildwright/claws/README.md +89 -0
- package/templates/.buildwright/claws/TEMPLATE.md +71 -0
- package/templates/.buildwright/claws/backend.md +114 -0
- package/templates/.buildwright/claws/database.md +120 -0
- package/templates/.buildwright/claws/devops.md +175 -0
- package/templates/.buildwright/claws/frontend.md +111 -0
- package/templates/.buildwright/commands/bw-analyse.md +86 -0
- package/templates/.buildwright/commands/bw-claw.md +332 -0
- package/templates/.buildwright/commands/bw-help.md +85 -0
- package/templates/.buildwright/commands/bw-new-feature.md +504 -0
- package/templates/.buildwright/commands/bw-quick.md +323 -0
- package/templates/.buildwright/commands/bw-ship.md +288 -0
- package/templates/.buildwright/commands/bw-verify.md +108 -0
- package/templates/.buildwright/steering/naming-conventions.md +40 -0
- package/templates/.buildwright/steering/product.md +16 -0
- package/templates/.buildwright/steering/quality-gates.md +35 -0
- package/templates/.buildwright/steering/tech.md +27 -0
- package/templates/.buildwright/tasks/TEMPLATE.md +79 -0
- package/templates/.env.example +11 -1
- package/templates/.github/workflows/quality-gates.yml +150 -0
- package/templates/BUILDWRIGHT.md +99 -1
- package/templates/CLAUDE.md +150 -1
- package/templates/Makefile +86 -1
- package/templates/docs/requirements/TEMPLATE.md +33 -0
- package/templates/scripts/bump-version.sh +33 -0
- package/templates/scripts/hooks/post-checkout +24 -0
- package/templates/scripts/hooks/post-merge +14 -0
- package/templates/scripts/hooks/pre-commit +14 -0
- package/templates/scripts/install-hooks.sh +35 -0
- package/templates/scripts/release.sh +38 -0
- package/templates/scripts/sync-agents.sh +294 -0
- package/templates/scripts/validate-skill.sh +156 -0
- package/templates/.buildwright +0 -1
- package/templates/.github +0 -1
- package/templates/docs +0 -1
- package/templates/scripts +0 -1
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Sync agent configurations across Claude Code, OpenCode, Cursor, and OpenClaw
|
|
3
|
+
#
|
|
4
|
+
# Source of truth: .buildwright/ (tool-agnostic canonical config)
|
|
5
|
+
# Generates:
|
|
6
|
+
# .claude/commands/ ← from .buildwright/commands/ (paths rewritten to .claude/)
|
|
7
|
+
# .claude/agents/ ← from .buildwright/agents/
|
|
8
|
+
# .claude/claws/ ← from .buildwright/claws/
|
|
9
|
+
# .claude/steering/ ← from .buildwright/steering/
|
|
10
|
+
# .claude/tasks/ ← from .buildwright/tasks/
|
|
11
|
+
# .opencode/commands/ ← from .buildwright/commands/ (paths rewritten to .opencode/)
|
|
12
|
+
# .opencode/agents/ ← from .buildwright/agents/
|
|
13
|
+
# .opencode/claws/ ← from .buildwright/claws/
|
|
14
|
+
# .opencode/steering/ ← from .buildwright/steering/
|
|
15
|
+
# .cursor/rules/steering/ ← .mdc files with alwaysApply: true
|
|
16
|
+
# .cursor/rules/commands/ ← .mdc files with alwaysApply: false
|
|
17
|
+
# .cursor/rules/agents/ ← .mdc files with alwaysApply: false
|
|
18
|
+
# .cursor/rules/claws/ ← .mdc files with alwaysApply: false
|
|
19
|
+
# AGENTS.md ← CLAUDE.md with OpenCode header prepended
|
|
20
|
+
# dist/buildwright/ ← SKILL.md packaged for ClawHub
|
|
21
|
+
#
|
|
22
|
+
# Usage: scripts/sync-agents.sh [--check]
|
|
23
|
+
# --check: Verify sync without modifying files (exit 1 if out of sync)
|
|
24
|
+
|
|
25
|
+
set -e
|
|
26
|
+
|
|
27
|
+
CHECK_ONLY=false
|
|
28
|
+
if [ "$1" = "--check" ]; then
|
|
29
|
+
CHECK_ONLY=true
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
33
|
+
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
34
|
+
cd "$ROOT_DIR"
|
|
35
|
+
|
|
36
|
+
# ============================================================================
|
|
37
|
+
# Helpers
|
|
38
|
+
# ============================================================================
|
|
39
|
+
|
|
40
|
+
# sync_dir SRC DST [REWRITE_FROM REWRITE_TO]
|
|
41
|
+
# Copies directory, optionally rewriting path references in .md files
|
|
42
|
+
sync_dir() {
|
|
43
|
+
local src="$1"
|
|
44
|
+
local dst="$2"
|
|
45
|
+
local rewrite_from="${3:-}"
|
|
46
|
+
local rewrite_to="${4:-}"
|
|
47
|
+
|
|
48
|
+
if [ ! -d "$src" ]; then
|
|
49
|
+
return
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
if [ "$CHECK_ONLY" = true ]; then
|
|
53
|
+
if [ ! -d "$dst" ]; then
|
|
54
|
+
echo "MISSING: $dst (should be synced from $src)"
|
|
55
|
+
SYNC_NEEDED=true
|
|
56
|
+
return
|
|
57
|
+
fi
|
|
58
|
+
# Generate expected output to temp dir and compare
|
|
59
|
+
local tmpdir
|
|
60
|
+
tmpdir=$(mktemp -d)
|
|
61
|
+
cp -R "$src/"* "$tmpdir/" 2>/dev/null || true
|
|
62
|
+
if [ -n "$rewrite_from" ] && [ -n "$rewrite_to" ]; then
|
|
63
|
+
find "$tmpdir" -name "*.md" -exec sed -i "s|$rewrite_from|$rewrite_to|g" {} + 2>/dev/null || true
|
|
64
|
+
fi
|
|
65
|
+
if ! diff -rq "$tmpdir" "$dst" > /dev/null 2>&1; then
|
|
66
|
+
echo "OUT OF SYNC: $dst differs from $src"
|
|
67
|
+
SYNC_NEEDED=true
|
|
68
|
+
fi
|
|
69
|
+
rm -rf "$tmpdir"
|
|
70
|
+
else
|
|
71
|
+
mkdir -p "$dst"
|
|
72
|
+
rsync -a --delete "$src/" "$dst/" 2>/dev/null || (rm -rf "$dst"/* && cp -R "$src/"* "$dst/")
|
|
73
|
+
# Rewrite path references for tool-specific copies
|
|
74
|
+
if [ -n "$rewrite_from" ] && [ -n "$rewrite_to" ]; then
|
|
75
|
+
find "$dst" -name "*.md" -exec sed -i "s|$rewrite_from|$rewrite_to|g" {} + 2>/dev/null || true
|
|
76
|
+
fi
|
|
77
|
+
echo " synced $src → $dst"
|
|
78
|
+
fi
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# Global vars used by set_cursor_frontmatter / sync_cursor_dir
|
|
82
|
+
CURSOR_ALWAYS_APPLY=""
|
|
83
|
+
CURSOR_DESCRIPTION=""
|
|
84
|
+
|
|
85
|
+
# set_cursor_frontmatter PRESET FILENAME
|
|
86
|
+
# Sets CURSOR_ALWAYS_APPLY and CURSOR_DESCRIPTION globals for the given file.
|
|
87
|
+
set_cursor_frontmatter() {
|
|
88
|
+
local preset="$1"
|
|
89
|
+
local filename="$2"
|
|
90
|
+
|
|
91
|
+
case "$preset" in
|
|
92
|
+
steering|codebase) CURSOR_ALWAYS_APPLY="true" ;;
|
|
93
|
+
*) CURSOR_ALWAYS_APPLY="false" ;;
|
|
94
|
+
esac
|
|
95
|
+
|
|
96
|
+
case "${preset}:${filename}" in
|
|
97
|
+
steering:product) CURSOR_DESCRIPTION="Buildwright product context: goals, features, user personas, business constraints" ;;
|
|
98
|
+
steering:tech) CURSOR_DESCRIPTION="Buildwright technical context: stack, commands, architecture patterns" ;;
|
|
99
|
+
steering:quality-gates) CURSOR_DESCRIPTION="Buildwright quality gates: automated checks that must pass before merge" ;;
|
|
100
|
+
steering:naming-conventions) CURSOR_DESCRIPTION="Buildwright naming conventions: canonical field and endpoint registry" ;;
|
|
101
|
+
codebase:STACK) CURSOR_DESCRIPTION="Codebase tech stack: languages, runtime, frameworks, dependencies, integrations" ;;
|
|
102
|
+
codebase:ARCHITECTURE) CURSOR_DESCRIPTION="Codebase architecture: layers, data flow, entry points, directory structure" ;;
|
|
103
|
+
codebase:CONVENTIONS) CURSOR_DESCRIPTION="Codebase conventions: naming, code style, imports, error handling, testing patterns" ;;
|
|
104
|
+
codebase:CONCERNS) CURSOR_DESCRIPTION="Codebase concerns: tech debt, bugs, security risks, performance bottlenecks" ;;
|
|
105
|
+
command:bw-new-feature) CURSOR_DESCRIPTION="Buildwright bw-new-feature: full pipeline for new features with spec and TDD" ;;
|
|
106
|
+
command:bw-claw) CURSOR_DESCRIPTION="Buildwright bw-claw: multi-agent cross-domain feature development" ;;
|
|
107
|
+
command:bw-quick) CURSOR_DESCRIPTION="Buildwright bw-quick: fast path for bug fixes and small tasks" ;;
|
|
108
|
+
command:bw-ship) CURSOR_DESCRIPTION="Buildwright bw-ship: quality pipeline then commit, push, and PR" ;;
|
|
109
|
+
command:bw-verify) CURSOR_DESCRIPTION="Buildwright bw-verify: quick quality checks (typecheck, lint, test, build)" ;;
|
|
110
|
+
command:bw-help) CURSOR_DESCRIPTION="Buildwright bw-help: list all available Buildwright commands" ;;
|
|
111
|
+
command:bw-analyse) CURSOR_DESCRIPTION="Buildwright bw-analyse: analyse codebase, write structured docs to .buildwright/codebase/, update tech.md" ;;
|
|
112
|
+
agent:architect) CURSOR_DESCRIPTION="Buildwright Architect agent persona" ;;
|
|
113
|
+
agent:staff-engineer) CURSOR_DESCRIPTION="Buildwright Staff Engineer agent persona" ;;
|
|
114
|
+
agent:security-engineer) CURSOR_DESCRIPTION="Buildwright Security Engineer agent persona" ;;
|
|
115
|
+
claw:frontend) CURSOR_DESCRIPTION="Buildwright Frontend domain specialist claw" ;;
|
|
116
|
+
claw:backend) CURSOR_DESCRIPTION="Buildwright Backend domain specialist claw" ;;
|
|
117
|
+
claw:database) CURSOR_DESCRIPTION="Buildwright Database domain specialist claw" ;;
|
|
118
|
+
claw:devops) CURSOR_DESCRIPTION="Buildwright DevOps domain specialist claw" ;;
|
|
119
|
+
*) CURSOR_DESCRIPTION="Buildwright ${preset}: ${filename}" ;;
|
|
120
|
+
esac
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
# sync_cursor_dir SRC DST_SUBDIR PRESET
|
|
124
|
+
# Converts .md files in SRC to .mdc files in .cursor/rules/DST_SUBDIR,
|
|
125
|
+
# prepending YAML frontmatter and rewriting @.buildwright/ → @.cursor/rules/.
|
|
126
|
+
# Skips README and TEMPLATE files.
|
|
127
|
+
sync_cursor_dir() {
|
|
128
|
+
local src="$1"
|
|
129
|
+
local dst_subdir="$2"
|
|
130
|
+
local preset="$3"
|
|
131
|
+
local dst=".cursor/rules/$dst_subdir"
|
|
132
|
+
|
|
133
|
+
if [ ! -d "$src" ]; then
|
|
134
|
+
return
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
if [ "$CHECK_ONLY" = false ]; then
|
|
138
|
+
mkdir -p "$dst"
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
for src_file in "$src"/*.md; do
|
|
142
|
+
[ -f "$src_file" ] || continue
|
|
143
|
+
local filename
|
|
144
|
+
filename=$(basename "$src_file" .md)
|
|
145
|
+
|
|
146
|
+
# Skip meta files — they're internal docs, not rules
|
|
147
|
+
case "$filename" in
|
|
148
|
+
README|TEMPLATE) continue ;;
|
|
149
|
+
esac
|
|
150
|
+
|
|
151
|
+
local dst_file="$dst/$filename.mdc"
|
|
152
|
+
set_cursor_frontmatter "$preset" "$filename"
|
|
153
|
+
|
|
154
|
+
if [ "$CHECK_ONLY" = true ]; then
|
|
155
|
+
if [ ! -f "$dst_file" ]; then
|
|
156
|
+
echo "MISSING: $dst_file"
|
|
157
|
+
SYNC_NEEDED=true
|
|
158
|
+
else
|
|
159
|
+
local tmpfile
|
|
160
|
+
tmpfile=$(mktemp)
|
|
161
|
+
{
|
|
162
|
+
printf '%s\n' "---"
|
|
163
|
+
printf 'description: "%s"\n' "$CURSOR_DESCRIPTION"
|
|
164
|
+
printf '%s\n' "globs: []"
|
|
165
|
+
printf 'alwaysApply: %s\n' "$CURSOR_ALWAYS_APPLY"
|
|
166
|
+
printf '%s\n' "---"
|
|
167
|
+
sed 's|@\.buildwright/|@.cursor/rules/|g' "$src_file"
|
|
168
|
+
} > "$tmpfile"
|
|
169
|
+
if ! diff -q "$dst_file" "$tmpfile" > /dev/null 2>&1; then
|
|
170
|
+
echo "OUT OF SYNC: $dst_file"
|
|
171
|
+
SYNC_NEEDED=true
|
|
172
|
+
fi
|
|
173
|
+
rm -f "$tmpfile"
|
|
174
|
+
fi
|
|
175
|
+
else
|
|
176
|
+
{
|
|
177
|
+
printf '%s\n' "---"
|
|
178
|
+
printf 'description: "%s"\n' "$CURSOR_DESCRIPTION"
|
|
179
|
+
printf '%s\n' "globs: []"
|
|
180
|
+
printf 'alwaysApply: %s\n' "$CURSOR_ALWAYS_APPLY"
|
|
181
|
+
printf '%s\n' "---"
|
|
182
|
+
sed 's|@\.buildwright/|@.cursor/rules/|g' "$src_file"
|
|
183
|
+
} > "$dst_file"
|
|
184
|
+
fi
|
|
185
|
+
done
|
|
186
|
+
|
|
187
|
+
if [ "$CHECK_ONLY" = false ]; then
|
|
188
|
+
echo " synced $src → $dst (*.mdc)"
|
|
189
|
+
fi
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
# ============================================================================
|
|
193
|
+
# 1. .buildwright/ → .claude/ (rewrite .buildwright/ → .claude/)
|
|
194
|
+
# ============================================================================
|
|
195
|
+
|
|
196
|
+
if [ "$CHECK_ONLY" = false ]; then
|
|
197
|
+
echo "Syncing agent configurations..."
|
|
198
|
+
echo ""
|
|
199
|
+
fi
|
|
200
|
+
|
|
201
|
+
SYNC_NEEDED=false
|
|
202
|
+
|
|
203
|
+
sync_dir ".buildwright/commands" ".claude/commands" ".buildwright/" ".claude/"
|
|
204
|
+
sync_dir ".buildwright/agents" ".claude/agents" ".buildwright/" ".claude/"
|
|
205
|
+
sync_dir ".buildwright/claws" ".claude/claws" ".buildwright/" ".claude/"
|
|
206
|
+
sync_dir ".buildwright/steering" ".claude/steering"
|
|
207
|
+
sync_dir ".buildwright/codebase" ".claude/codebase"
|
|
208
|
+
sync_dir ".buildwright/tasks" ".claude/tasks"
|
|
209
|
+
|
|
210
|
+
# ============================================================================
|
|
211
|
+
# 2. .buildwright/ → .opencode/ (rewrite .buildwright/ → .opencode/)
|
|
212
|
+
# ============================================================================
|
|
213
|
+
|
|
214
|
+
sync_dir ".buildwright/commands" ".opencode/commands" ".buildwright/" ".opencode/"
|
|
215
|
+
sync_dir ".buildwright/agents" ".opencode/agents" ".buildwright/" ".opencode/"
|
|
216
|
+
sync_dir ".buildwright/claws" ".opencode/claws" ".buildwright/" ".opencode/"
|
|
217
|
+
sync_dir ".buildwright/steering" ".opencode/steering"
|
|
218
|
+
sync_dir ".buildwright/codebase" ".opencode/codebase"
|
|
219
|
+
|
|
220
|
+
# ============================================================================
|
|
221
|
+
# 3. CLAUDE.md → AGENTS.md
|
|
222
|
+
# ============================================================================
|
|
223
|
+
|
|
224
|
+
generate_agents_md() {
|
|
225
|
+
local target="$1"
|
|
226
|
+
printf '%s\n' "---" \
|
|
227
|
+
"# OpenCode agent instructions" \
|
|
228
|
+
"# Auto-generated from CLAUDE.md — do not edit directly" \
|
|
229
|
+
"# Run: scripts/sync-agents.sh to regenerate" \
|
|
230
|
+
"---" \
|
|
231
|
+
"" > "$target"
|
|
232
|
+
cat CLAUDE.md >> "$target"
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if [ "$CHECK_ONLY" = true ]; then
|
|
236
|
+
if [ ! -f "AGENTS.md" ]; then
|
|
237
|
+
echo "MISSING: AGENTS.md (should be generated from CLAUDE.md)"
|
|
238
|
+
SYNC_NEEDED=true
|
|
239
|
+
else
|
|
240
|
+
TMPFILE=$(mktemp)
|
|
241
|
+
generate_agents_md "$TMPFILE"
|
|
242
|
+
if ! diff -q "AGENTS.md" "$TMPFILE" > /dev/null 2>&1; then
|
|
243
|
+
echo "OUT OF SYNC: AGENTS.md differs from CLAUDE.md"
|
|
244
|
+
SYNC_NEEDED=true
|
|
245
|
+
fi
|
|
246
|
+
rm -f "$TMPFILE"
|
|
247
|
+
fi
|
|
248
|
+
else
|
|
249
|
+
generate_agents_md "AGENTS.md"
|
|
250
|
+
echo " generated AGENTS.md from CLAUDE.md"
|
|
251
|
+
fi
|
|
252
|
+
|
|
253
|
+
# ============================================================================
|
|
254
|
+
# 4. .buildwright/ → .cursor/rules/ (convert to .mdc with frontmatter)
|
|
255
|
+
# ============================================================================
|
|
256
|
+
|
|
257
|
+
sync_cursor_dir ".buildwright/steering" "steering" "steering"
|
|
258
|
+
sync_cursor_dir ".buildwright/codebase" "codebase" "codebase"
|
|
259
|
+
sync_cursor_dir ".buildwright/commands" "commands" "command"
|
|
260
|
+
sync_cursor_dir ".buildwright/agents" "agents" "agent"
|
|
261
|
+
sync_cursor_dir ".buildwright/claws" "claws" "claw"
|
|
262
|
+
|
|
263
|
+
# ============================================================================
|
|
264
|
+
# 5. Package for ClawHub (dist/)
|
|
265
|
+
# ============================================================================
|
|
266
|
+
|
|
267
|
+
if [ "$CHECK_ONLY" = false ] && [ -f "SKILL.md" ]; then
|
|
268
|
+
mkdir -p dist/buildwright
|
|
269
|
+
cp SKILL.md dist/buildwright/
|
|
270
|
+
echo " packaged dist/buildwright/SKILL.md for ClawHub"
|
|
271
|
+
fi
|
|
272
|
+
|
|
273
|
+
# ============================================================================
|
|
274
|
+
# Result
|
|
275
|
+
# ============================================================================
|
|
276
|
+
|
|
277
|
+
if [ "$CHECK_ONLY" = true ]; then
|
|
278
|
+
if [ "$SYNC_NEEDED" = true ]; then
|
|
279
|
+
echo ""
|
|
280
|
+
echo "Run 'scripts/sync-agents.sh' to fix."
|
|
281
|
+
exit 1
|
|
282
|
+
else
|
|
283
|
+
echo "All synced."
|
|
284
|
+
exit 0
|
|
285
|
+
fi
|
|
286
|
+
else
|
|
287
|
+
echo ""
|
|
288
|
+
echo "Sync complete. Source of truth: .buildwright/"
|
|
289
|
+
echo " .buildwright/ → .claude/ (paths rewritten)"
|
|
290
|
+
echo " .buildwright/ → .opencode/ (paths rewritten)"
|
|
291
|
+
echo " .buildwright/ → .cursor/rules/ (.mdc with frontmatter)"
|
|
292
|
+
echo " CLAUDE.md → AGENTS.md"
|
|
293
|
+
echo " SKILL.md → dist/buildwright/SKILL.md"
|
|
294
|
+
fi
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Validate SKILL.md against the Agent Skills specification (agentskills.io)
|
|
3
|
+
#
|
|
4
|
+
# Checks:
|
|
5
|
+
# 1. YAML frontmatter exists and is valid
|
|
6
|
+
# 2. Required fields: name, description
|
|
7
|
+
# 3. Recommended fields: license, compatibility, metadata
|
|
8
|
+
# 4. File size under 500 lines (best practice)
|
|
9
|
+
#
|
|
10
|
+
# Usage: scripts/validate-skill.sh [path/to/SKILL.md]
|
|
11
|
+
|
|
12
|
+
set -e
|
|
13
|
+
|
|
14
|
+
SKILL_FILE="${1:-SKILL.md}"
|
|
15
|
+
|
|
16
|
+
if [ ! -f "$SKILL_FILE" ]; then
|
|
17
|
+
echo "ERROR: $SKILL_FILE not found"
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
ERRORS=0
|
|
22
|
+
WARNINGS=0
|
|
23
|
+
|
|
24
|
+
echo "Validating $SKILL_FILE against Agent Skills spec..."
|
|
25
|
+
echo ""
|
|
26
|
+
|
|
27
|
+
# ============================================================================
|
|
28
|
+
# Check 1: YAML frontmatter exists
|
|
29
|
+
# ============================================================================
|
|
30
|
+
|
|
31
|
+
if ! head -1 "$SKILL_FILE" | grep -q "^---$"; then
|
|
32
|
+
echo "ERROR: Missing YAML frontmatter (file must start with ---)"
|
|
33
|
+
ERRORS=$((ERRORS + 1))
|
|
34
|
+
else
|
|
35
|
+
echo " [PASS] YAML frontmatter exists"
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# Check frontmatter closing (count lines that are exactly ---)
|
|
39
|
+
DELIM_COUNT=$(grep -c "^---$" "$SKILL_FILE" || true)
|
|
40
|
+
if [ "$DELIM_COUNT" -lt 2 ]; then
|
|
41
|
+
echo "ERROR: YAML frontmatter not properly closed (missing second ---)"
|
|
42
|
+
ERRORS=$((ERRORS + 1))
|
|
43
|
+
else
|
|
44
|
+
echo " [PASS] YAML frontmatter properly closed"
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# ============================================================================
|
|
48
|
+
# Check 2: Required fields
|
|
49
|
+
# ============================================================================
|
|
50
|
+
|
|
51
|
+
# Extract frontmatter
|
|
52
|
+
FRONTMATTER=$(awk '/^---$/{n++; next} n==1{print} n==2{exit}' "$SKILL_FILE")
|
|
53
|
+
|
|
54
|
+
if echo "$FRONTMATTER" | grep -q "^name:"; then
|
|
55
|
+
echo " [PASS] Required field: name"
|
|
56
|
+
else
|
|
57
|
+
echo "ERROR: Missing required field: name"
|
|
58
|
+
ERRORS=$((ERRORS + 1))
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
if echo "$FRONTMATTER" | grep -q "^description:"; then
|
|
62
|
+
echo " [PASS] Required field: description"
|
|
63
|
+
else
|
|
64
|
+
echo "ERROR: Missing required field: description"
|
|
65
|
+
ERRORS=$((ERRORS + 1))
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# ============================================================================
|
|
69
|
+
# Check 3: Recommended fields
|
|
70
|
+
# ============================================================================
|
|
71
|
+
|
|
72
|
+
if echo "$FRONTMATTER" | grep -q "^license:"; then
|
|
73
|
+
echo " [PASS] Recommended field: license"
|
|
74
|
+
else
|
|
75
|
+
echo " [WARN] Missing recommended field: license"
|
|
76
|
+
WARNINGS=$((WARNINGS + 1))
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
if echo "$FRONTMATTER" | grep -q "^compatibility:"; then
|
|
80
|
+
echo " [PASS] Recommended field: compatibility"
|
|
81
|
+
else
|
|
82
|
+
echo " [WARN] Missing recommended field: compatibility"
|
|
83
|
+
WARNINGS=$((WARNINGS + 1))
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
if echo "$FRONTMATTER" | grep -q "^metadata:"; then
|
|
87
|
+
echo " [PASS] Recommended field: metadata"
|
|
88
|
+
else
|
|
89
|
+
echo " [WARN] Missing recommended field: metadata"
|
|
90
|
+
WARNINGS=$((WARNINGS + 1))
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# ============================================================================
|
|
94
|
+
# Check 4: Metadata sub-fields
|
|
95
|
+
# ============================================================================
|
|
96
|
+
|
|
97
|
+
if echo "$FRONTMATTER" | grep -q "version:"; then
|
|
98
|
+
echo " [PASS] Metadata: version"
|
|
99
|
+
else
|
|
100
|
+
echo " [WARN] Missing metadata: version"
|
|
101
|
+
WARNINGS=$((WARNINGS + 1))
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
if echo "$FRONTMATTER" | grep -q "author:"; then
|
|
105
|
+
echo " [PASS] Metadata: author"
|
|
106
|
+
else
|
|
107
|
+
echo " [WARN] Missing metadata: author"
|
|
108
|
+
WARNINGS=$((WARNINGS + 1))
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
if echo "$FRONTMATTER" | grep -q "tags:"; then
|
|
112
|
+
echo " [PASS] Metadata: tags (improves discoverability)"
|
|
113
|
+
else
|
|
114
|
+
echo " [WARN] Missing metadata: tags (recommended for ClawHub/marketplace discoverability)"
|
|
115
|
+
WARNINGS=$((WARNINGS + 1))
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
# ============================================================================
|
|
119
|
+
# Check 5: File size
|
|
120
|
+
# ============================================================================
|
|
121
|
+
|
|
122
|
+
LINE_COUNT=$(wc -l < "$SKILL_FILE")
|
|
123
|
+
if [ "$LINE_COUNT" -gt 500 ]; then
|
|
124
|
+
echo " [WARN] SKILL.md is $LINE_COUNT lines (recommended: under 500)"
|
|
125
|
+
WARNINGS=$((WARNINGS + 1))
|
|
126
|
+
else
|
|
127
|
+
echo " [PASS] File size: $LINE_COUNT lines (under 500)"
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
# ============================================================================
|
|
131
|
+
# Check 6: Markdown body exists after frontmatter
|
|
132
|
+
# ============================================================================
|
|
133
|
+
|
|
134
|
+
BODY_LINES=$(awk '/^---$/{n++; next} n>=2{print}' "$SKILL_FILE" | grep -c "." || true)
|
|
135
|
+
if [ "$BODY_LINES" -lt 5 ]; then
|
|
136
|
+
echo " [WARN] Markdown body is very short ($BODY_LINES non-empty lines)"
|
|
137
|
+
WARNINGS=$((WARNINGS + 1))
|
|
138
|
+
else
|
|
139
|
+
echo " [PASS] Markdown body: $BODY_LINES non-empty lines"
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
# ============================================================================
|
|
143
|
+
# Result
|
|
144
|
+
# ============================================================================
|
|
145
|
+
|
|
146
|
+
echo ""
|
|
147
|
+
echo "═══════════════════════════════════════"
|
|
148
|
+
if [ "$ERRORS" -gt 0 ]; then
|
|
149
|
+
echo " FAILED: $ERRORS error(s), $WARNINGS warning(s)"
|
|
150
|
+
echo "═══════════════════════════════════════"
|
|
151
|
+
exit 1
|
|
152
|
+
else
|
|
153
|
+
echo " PASSED: 0 errors, $WARNINGS warning(s)"
|
|
154
|
+
echo "═══════════════════════════════════════"
|
|
155
|
+
exit 0
|
|
156
|
+
fi
|
package/templates/.buildwright
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
../../.buildwright
|
package/templates/.github
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
../../.github
|
package/templates/docs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
../../docs
|
package/templates/scripts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
../../scripts
|