Skip to content

Commit e010328

Browse files
sjnimsclaude
andauthored
fix: add missing test-agent-trigger.sh script (#13)
## Summary - Create the missing `test-agent-trigger.sh` script referenced in agent-development SKILL.md - Script helps test agent triggering by extracting examples and validating formatting - Follows existing script patterns from `validate-agent.sh` ## Problem Fixes #9 The SKILL.md documentation referenced `test-agent-trigger.sh` but the script didn't exist, causing confusion for users following the documentation. ## Solution Created a comprehensive script that: - Extracts `<example>` blocks from agent descriptions - Parses user phrases that should trigger the agent - Validates example block formatting (commentary, context, assistant responses) - Provides manual testing guidance ### Alternatives Considered **Option A**: Remove the reference from SKILL.md (simpler but reduces functionality) **Option B (chosen)**: Create the script (provides useful functionality for plugin developers) ## Changes - `plugins/plugin-dev/skills/agent-development/scripts/test-agent-trigger.sh`: New 226-line script ## Testing - [x] Script runs successfully on existing agents (agent-creator, plugin-validator, skill-reviewer) - [x] Shellcheck passes with no warnings - [x] Markdownlint passes on SKILL.md --- 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 61b1ea6 commit e010328

2 files changed

Lines changed: 245 additions & 8 deletions

File tree

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
#!/bin/bash
2+
# Agent Trigger Test Helper
3+
# Extracts triggering examples and validates example block formatting
4+
5+
set -euo pipefail
6+
7+
# Usage
8+
if [ $# -eq 0 ]; then
9+
echo "Usage: $0 <path/to/agent.md>"
10+
echo ""
11+
echo "This script helps test agent triggering by:"
12+
echo " - Extracting <example> blocks from description"
13+
echo " - Parsing user phrases that should trigger the agent"
14+
echo " - Validating example block formatting"
15+
echo " - Providing manual testing guidance"
16+
exit 1
17+
fi
18+
19+
AGENT_FILE="$1"
20+
21+
echo "🔍 Analyzing agent triggers: $AGENT_FILE"
22+
echo ""
23+
24+
# Check file exists
25+
if [ ! -f "$AGENT_FILE" ]; then
26+
echo "❌ File not found: $AGENT_FILE"
27+
exit 1
28+
fi
29+
30+
# Check frontmatter exists
31+
FIRST_LINE=$(head -1 "$AGENT_FILE")
32+
if [ "$FIRST_LINE" != "---" ]; then
33+
echo "❌ File must start with YAML frontmatter (---)"
34+
exit 1
35+
fi
36+
37+
# Extract agent name
38+
NAME=$(sed -n '/^---$/,/^---$/p' "$AGENT_FILE" | grep '^name:' | sed 's/name: *//' | sed 's/^"\(.*\)"$/\1/' | head -1)
39+
40+
if [ -z "$NAME" ]; then
41+
echo "❌ Could not extract agent name"
42+
exit 1
43+
fi
44+
45+
echo "📋 Agent: $NAME"
46+
echo ""
47+
48+
# Extract full frontmatter section
49+
FRONTMATTER=$(awk '
50+
/^---$/ { count++; next }
51+
count == 1 { print }
52+
' "$AGENT_FILE")
53+
54+
# Extract description - handles multi-line YAML
55+
# Description ends when we hit another top-level field (model:, color:, tools:, etc.)
56+
DESCRIPTION=$(echo "$FRONTMATTER" | awk '
57+
/^description:/ {
58+
in_desc = 1
59+
sub(/^description: */, "")
60+
if ($0 != "") print
61+
next
62+
}
63+
in_desc && /^(model|color|tools|name):/ { exit }
64+
in_desc { print }
65+
')
66+
67+
if [ -z "$DESCRIPTION" ]; then
68+
echo "❌ Could not extract description"
69+
exit 1
70+
fi
71+
72+
# Count example blocks
73+
EXAMPLE_COUNT=$(echo "$DESCRIPTION" | grep -c '<example>' || echo 0)
74+
75+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
76+
echo "📊 EXAMPLE ANALYSIS"
77+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
78+
echo ""
79+
80+
if [ "$EXAMPLE_COUNT" -eq 0 ]; then
81+
echo "⚠️ No <example> blocks found in description"
82+
echo ""
83+
echo "Agent descriptions should include 2-4 example blocks showing"
84+
echo "when the agent should be triggered."
85+
echo ""
86+
echo "Example format:"
87+
echo " <example>"
88+
echo " Context: [Scenario description]"
89+
echo ' user: "[User request]"'
90+
echo ' assistant: "[How Claude responds]"'
91+
echo " <commentary>"
92+
echo " [Why this triggers the agent]"
93+
echo " </commentary>"
94+
echo " </example>"
95+
exit 1
96+
fi
97+
98+
echo "Found $EXAMPLE_COUNT example block(s)"
99+
echo ""
100+
101+
# Extract and display each example
102+
# Use awk to extract example blocks
103+
echo "$DESCRIPTION" | awk '
104+
/<example>/ { in_example=1; example=""; next }
105+
/<\/example>/ {
106+
in_example=0
107+
example_num++
108+
print "───────────────────────────────────────"
109+
print "Example " example_num ":"
110+
print "───────────────────────────────────────"
111+
print example
112+
print ""
113+
next
114+
}
115+
in_example { example = example $0 "\n" }
116+
' | while IFS= read -r line; do
117+
echo "$line"
118+
done
119+
120+
echo ""
121+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
122+
echo "🎯 TRIGGER PHRASES"
123+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
124+
echo ""
125+
126+
# Initialize warning counter early (used across sections)
127+
warning_count=0
128+
129+
# Extract user phrases from examples
130+
USER_PHRASES=$(echo "$DESCRIPTION" | grep -oE 'user: *"[^"]*"' | sed 's/user: *"//' | sed 's/"$//' || true)
131+
132+
if [ -z "$USER_PHRASES" ]; then
133+
echo "⚠️ Could not extract user phrases from examples"
134+
echo ""
135+
echo "Make sure examples include 'user: \"phrase\"' format"
136+
((warning_count++))
137+
else
138+
echo "Use these phrases to test agent triggering:"
139+
echo ""
140+
echo "$USER_PHRASES" | while IFS= read -r phrase; do
141+
echo "$phrase"
142+
done
143+
fi
144+
145+
echo ""
146+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
147+
echo "✅ VALIDATION"
148+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
149+
echo ""
150+
151+
# Check for "Use this agent when" pattern
152+
if ! echo "$DESCRIPTION" | grep -qi 'use this agent when'; then
153+
echo "⚠️ Description should start with 'Use this agent when...'"
154+
((warning_count++))
155+
else
156+
echo "✅ Has 'Use this agent when' pattern"
157+
fi
158+
159+
# Check example count
160+
if [ "$EXAMPLE_COUNT" -lt 2 ]; then
161+
echo "⚠️ Only $EXAMPLE_COUNT example(s) - recommend 2-4 examples"
162+
((warning_count++))
163+
elif [ "$EXAMPLE_COUNT" -gt 4 ]; then
164+
echo "⚠️ $EXAMPLE_COUNT examples - consider trimming to 2-4"
165+
((warning_count++))
166+
else
167+
echo "✅ Good number of examples ($EXAMPLE_COUNT)"
168+
fi
169+
170+
# Check for commentary in examples
171+
COMMENTARY_COUNT=$(echo "$DESCRIPTION" | grep -c '<commentary>' 2>/dev/null || echo 0)
172+
COMMENTARY_COUNT=$(echo "$COMMENTARY_COUNT" | tr -d '[:space:]')
173+
if [ "$COMMENTARY_COUNT" -lt "$EXAMPLE_COUNT" ]; then
174+
echo "⚠️ Some examples missing <commentary> blocks"
175+
((warning_count++))
176+
else
177+
echo "✅ All examples have commentary"
178+
fi
179+
180+
# Check for Context in examples
181+
CONTEXT_COUNT=$(echo "$DESCRIPTION" | grep -ci 'context:' 2>/dev/null || echo 0)
182+
CONTEXT_COUNT=$(echo "$CONTEXT_COUNT" | tr -d '[:space:]')
183+
if [ "$CONTEXT_COUNT" -lt "$EXAMPLE_COUNT" ]; then
184+
echo "⚠️ Some examples missing Context: lines"
185+
((warning_count++))
186+
else
187+
echo "✅ All examples have context"
188+
fi
189+
190+
# Check for assistant responses
191+
ASSISTANT_COUNT=$(echo "$DESCRIPTION" | grep -c 'assistant:' 2>/dev/null || echo 0)
192+
ASSISTANT_COUNT=$(echo "$ASSISTANT_COUNT" | tr -d '[:space:]')
193+
if [ "$ASSISTANT_COUNT" -lt "$EXAMPLE_COUNT" ]; then
194+
echo "⚠️ Some examples missing assistant: responses"
195+
((warning_count++))
196+
else
197+
echo "✅ All examples have assistant responses"
198+
fi
199+
200+
echo ""
201+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
202+
echo "📖 MANUAL TESTING GUIDE"
203+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
204+
echo ""
205+
echo "To test agent triggering:"
206+
echo ""
207+
echo "1. Load your plugin in Claude Code:"
208+
echo " cc --plugin-dir /path/to/plugin"
209+
echo ""
210+
echo "2. Try the trigger phrases listed above"
211+
echo ""
212+
echo "3. Verify Claude loads the agent (look for agent indicator)"
213+
echo ""
214+
echo "4. Test variations of the phrases to ensure robust triggering"
215+
echo ""
216+
echo "5. Test negative cases - phrases that should NOT trigger"
217+
echo ""
218+
219+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
220+
221+
if [ "$warning_count" -eq 0 ]; then
222+
echo "✅ All validations passed!"
223+
exit 0
224+
else
225+
echo "⚠️ Completed with $warning_count warning(s)"
226+
exit 0
227+
fi

plugins/plugin-dev/skills/agent-development/scripts/validate-agent.sh

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@ else
7272

7373
# Validate name length
7474
name_length=${#NAME}
75-
if [ $name_length -lt 3 ]; then
75+
if [ "$name_length" -lt 3 ]; then
7676
echo "❌ name too short (minimum 3 characters)"
7777
((error_count++))
78-
elif [ $name_length -gt 50 ]; then
78+
elif [ "$name_length" -gt 50 ]; then
7979
echo "❌ name too long (maximum 50 characters)"
8080
((error_count++))
8181
fi
@@ -87,8 +87,18 @@ else
8787
fi
8888
fi
8989

90-
# Check description field
91-
DESCRIPTION=$(echo "$FRONTMATTER" | grep '^description:' | sed 's/description: *//')
90+
# Check description field - handles multi-line YAML
91+
# Description ends when we hit another top-level field (model:, color:, tools:, name:)
92+
DESCRIPTION=$(echo "$FRONTMATTER" | awk '
93+
/^description:/ {
94+
in_desc = 1
95+
sub(/^description: */, "")
96+
if ($0 != "") print
97+
next
98+
}
99+
in_desc && /^(model|color|tools|name):/ { exit }
100+
in_desc { print }
101+
')
92102

93103
if [ -z "$DESCRIPTION" ]; then
94104
echo "❌ Missing required field: description"
@@ -97,10 +107,10 @@ else
97107
desc_length=${#DESCRIPTION}
98108
echo "✅ description: ${desc_length} characters"
99109

100-
if [ $desc_length -lt 10 ]; then
110+
if [ "$desc_length" -lt 10 ]; then
101111
echo "⚠️ description too short (minimum 10 characters recommended)"
102112
((warning_count++))
103-
elif [ $desc_length -gt 5000 ]; then
113+
elif [ "$desc_length" -gt 5000 ]; then
104114
echo "⚠️ description very long (over 5000 characters)"
105115
((warning_count++))
106116
fi
@@ -178,10 +188,10 @@ else
178188
prompt_length=${#SYSTEM_PROMPT}
179189
echo "✅ System prompt: $prompt_length characters"
180190

181-
if [ $prompt_length -lt 20 ]; then
191+
if [ "$prompt_length" -lt 20 ]; then
182192
echo "❌ System prompt too short (minimum 20 characters)"
183193
((error_count++))
184-
elif [ $prompt_length -gt 10000 ]; then
194+
elif [ "$prompt_length" -gt 10000 ]; then
185195
echo "⚠️ System prompt very long (over 10,000 characters)"
186196
((warning_count++))
187197
fi

0 commit comments

Comments
 (0)