mirror of
https://github.com/proffesor-for-testing/agentic-qe.git
synced 2026-09-19 08:45:47 +08:00
fd2f37eaa0
Changes: - Fix README.md agent counts (48 QE agents = 41 main + 7 subagents) - Fix README.md skill counts (15 QE-specific skills) - Fix v3/README.md agent counts (47 → 48) - Fix init-wizard.ts hooks from 'npx @agentic-qe/v3' to 'npx agentic-qe' - Complete v2 → v2/ folder reorganization (54 items moved) - Update root package.json to point to v3 as main version Verified claims: - 48 QE agents (41 main + 7 TDD subagents) - 15 QE-specific skills - 12 DDD bounded contexts - ~5,600+ tests - HNSW, ReasoningBank, Queen Coordinator features exist Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
210 lines
6.2 KiB
Bash
Executable File
210 lines
6.2 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Validation script for skill frontmatter
|
|
# Checks all skills have valid YAML frontmatter for progressive disclosure
|
|
|
|
set -euo pipefail
|
|
|
|
SKILLS_DIR=".claude/skills"
|
|
RESULTS_FILE="/tmp/skill-frontmatter-validation.json"
|
|
ERRORS=0
|
|
WARNINGS=0
|
|
TOTAL=0
|
|
VALID=0
|
|
MISSING=()
|
|
INVALID=()
|
|
WARNINGS_LIST=()
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
echo "🔍 Validating skill frontmatter..."
|
|
echo ""
|
|
|
|
# Initialize results JSON
|
|
cat > "$RESULTS_FILE" <<EOF
|
|
{
|
|
"timestamp": "$(date -Iseconds)",
|
|
"total_skills": 0,
|
|
"valid_skills": 0,
|
|
"missing_frontmatter": [],
|
|
"invalid_frontmatter": [],
|
|
"warnings": [],
|
|
"token_savings": {
|
|
"before_tokens": 0,
|
|
"after_tokens": 0,
|
|
"reduction_percent": 0
|
|
}
|
|
}
|
|
EOF
|
|
|
|
# Function to check if file has valid YAML frontmatter
|
|
validate_frontmatter() {
|
|
local file="$1"
|
|
local skill_name
|
|
skill_name=$(basename "$(dirname "$file")")
|
|
|
|
TOTAL=$((TOTAL + 1))
|
|
|
|
# Check if file starts with ---
|
|
if ! head -n 1 "$file" | grep -q "^---$"; then
|
|
echo -e "${RED}✗${NC} $skill_name: Missing frontmatter"
|
|
MISSING+=("$skill_name")
|
|
ERRORS=$((ERRORS + 1))
|
|
return 1
|
|
fi
|
|
|
|
# Extract frontmatter (between first two --- markers)
|
|
local frontmatter
|
|
frontmatter=$(awk '/^---$/{flag=!flag;next}flag' "$file" | head -n 20)
|
|
|
|
# Check required fields
|
|
if ! echo "$frontmatter" | grep -q "^name:"; then
|
|
echo -e "${RED}✗${NC} $skill_name: Missing 'name' field"
|
|
INVALID+=("$skill_name")
|
|
ERRORS=$((ERRORS + 1))
|
|
return 1
|
|
fi
|
|
|
|
if ! echo "$frontmatter" | grep -q "^description:"; then
|
|
echo -e "${RED}✗${NC} $skill_name: Missing 'description' field"
|
|
INVALID+=("$skill_name")
|
|
ERRORS=$((ERRORS + 1))
|
|
return 1
|
|
fi
|
|
|
|
# Check description length (<1024 chars)
|
|
local desc_length
|
|
desc_length=$(echo "$frontmatter" | grep "^description:" | cut -d':' -f2- | wc -c)
|
|
if [ "$desc_length" -gt 1024 ]; then
|
|
echo -e "${YELLOW}⚠${NC} $skill_name: Description too long ($desc_length chars > 1024)"
|
|
WARNINGS_LIST+=("$skill_name: Description too long ($desc_length chars)")
|
|
WARNINGS=$((WARNINGS + 1))
|
|
fi
|
|
|
|
# Check YAML syntax (basic check)
|
|
if ! echo "$frontmatter" | grep -qE "^[a-z_]+: .+"; then
|
|
echo -e "${RED}✗${NC} $skill_name: Invalid YAML syntax"
|
|
INVALID+=("$skill_name")
|
|
ERRORS=$((ERRORS + 1))
|
|
return 1
|
|
fi
|
|
|
|
echo -e "${GREEN}✓${NC} $skill_name"
|
|
VALID=$((VALID + 1))
|
|
return 0
|
|
}
|
|
|
|
# Calculate token savings
|
|
calculate_token_savings() {
|
|
local skills_dir="$1"
|
|
local total_content_size=0
|
|
local total_frontmatter_size=0
|
|
|
|
while IFS= read -r -d '' file; do
|
|
# Full content size (approximate tokens = chars / 4)
|
|
local content_size
|
|
content_size=$(wc -c < "$file")
|
|
total_content_size=$((total_content_size + content_size))
|
|
|
|
# Frontmatter size (only name + description loaded initially)
|
|
local frontmatter_size
|
|
frontmatter_size=$(awk '/^---$/{flag=!flag;next}flag' "$file" | head -n 20 | wc -c)
|
|
total_frontmatter_size=$((total_frontmatter_size + frontmatter_size))
|
|
done < <(find "$skills_dir" -name "SKILL.md" -type f -print0)
|
|
|
|
# Approximate token counts (1 token ≈ 4 characters)
|
|
local before_tokens=$((total_content_size / 4))
|
|
local after_tokens=$((total_frontmatter_size / 4))
|
|
local reduction_percent=0
|
|
|
|
if [ "$before_tokens" -gt 0 ]; then
|
|
reduction_percent=$(( (before_tokens - after_tokens) * 100 / before_tokens ))
|
|
fi
|
|
|
|
echo "$before_tokens $after_tokens $reduction_percent"
|
|
}
|
|
|
|
# Main validation loop
|
|
echo "Scanning skills in $SKILLS_DIR..."
|
|
echo ""
|
|
|
|
while IFS= read -r -d '' file; do
|
|
validate_frontmatter "$file" || true
|
|
done < <(find "$SKILLS_DIR" -name "SKILL.md" -type f -print0 | sort -z)
|
|
|
|
# Calculate token savings
|
|
echo ""
|
|
echo "📊 Calculating token savings..."
|
|
read -r before_tokens after_tokens reduction_percent <<< "$(calculate_token_savings "$SKILLS_DIR")"
|
|
|
|
# Summary
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "📋 VALIDATION SUMMARY"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
echo "Total skills: $TOTAL"
|
|
echo -e "Valid skills: ${GREEN}$VALID${NC}"
|
|
echo -e "Missing frontmatter: ${RED}${#MISSING[@]}${NC}"
|
|
echo -e "Invalid frontmatter: ${RED}${#INVALID[@]}${NC}"
|
|
echo -e "Warnings: ${YELLOW}$WARNINGS${NC}"
|
|
echo ""
|
|
echo "💰 TOKEN SAVINGS (Progressive Disclosure)"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo "Before (full load): ~${before_tokens} tokens"
|
|
echo "After (frontmatter): ~${after_tokens} tokens"
|
|
echo -e "Reduction: ${GREEN}${reduction_percent}%${NC}"
|
|
echo ""
|
|
|
|
# List errors if any
|
|
if [ ${#MISSING[@]} -gt 0 ]; then
|
|
echo -e "${RED}❌ Skills missing frontmatter:${NC}"
|
|
printf ' - %s\n' "${MISSING[@]}"
|
|
echo ""
|
|
fi
|
|
|
|
if [ ${#INVALID[@]} -gt 0 ]; then
|
|
echo -e "${RED}❌ Skills with invalid frontmatter:${NC}"
|
|
printf ' - %s\n' "${INVALID[@]}"
|
|
echo ""
|
|
fi
|
|
|
|
if [ ${#WARNINGS_LIST[@]} -gt 0 ]; then
|
|
echo -e "${YELLOW}⚠️ Warnings:${NC}"
|
|
printf ' - %s\n' "${WARNINGS_LIST[@]}"
|
|
echo ""
|
|
fi
|
|
|
|
# Update results JSON
|
|
cat > "$RESULTS_FILE" <<EOF
|
|
{
|
|
"timestamp": "$(date -Iseconds)",
|
|
"total_skills": $TOTAL,
|
|
"valid_skills": $VALID,
|
|
"missing_frontmatter": $(printf '%s\n' "${MISSING[@]}" | jq -R . | jq -s . 2>/dev/null || echo "[]"),
|
|
"invalid_frontmatter": $(printf '%s\n' "${INVALID[@]}" | jq -R . | jq -s . 2>/dev/null || echo "[]"),
|
|
"warnings": $(printf '%s\n' "${WARNINGS_LIST[@]}" | jq -R . | jq -s . 2>/dev/null || echo "[]"),
|
|
"token_savings": {
|
|
"before_tokens": $before_tokens,
|
|
"after_tokens": $after_tokens,
|
|
"reduction_percent": $reduction_percent
|
|
}
|
|
}
|
|
EOF
|
|
|
|
echo "📄 Results saved to: $RESULTS_FILE"
|
|
echo ""
|
|
|
|
# Exit with error code if validation failed
|
|
if [ $ERRORS -gt 0 ]; then
|
|
echo -e "${RED}❌ Validation FAILED${NC}"
|
|
exit 1
|
|
else
|
|
echo -e "${GREEN}✅ Validation PASSED${NC}"
|
|
exit 0
|
|
fi
|