mirror of
https://github.com/secondsky/claude-skills.git
synced 2026-09-18 19:54:22 +08:00
fb6e3f1c2b
* fix(scripts): adversarial audit fixes across generators, validators, review tooling
Round-1 adversarial subagent review found 13 confirmed bugs across the
plugin-marketplace scripts. All verified fixed:
Critical:
- review-skill.sh: ((VAR++)) returned 1 under set -e when counter was 0,
aborting the script on the first finding and making the entire report
unreachable for any non-perfect skill. Add || true.
- review-skill.sh: date -d is GNU-only; on macOS every skill with
last_verified was falsely flagged as ~20500 days stale. Use BSD date -jf
with GNU fallback.
Important:
- validate-frontmatter.sh: set -e + validate_skill '$file' aborted on the
first failing skill; summary never printed. Guard with || true
(CRITICAL_COUNT already tracks failures).
- validate-json-schemas.sh: plugin_count=1 when zero files found
(echo '' | wc -l); report falsely showed 'Total: 1'. Explicit empty guard.
- generate-marketplace.sh: version sync read .plugins[0] (always the
alphabetically-first plugin), masking drift instead of detecting it.
Now asserts all plugin versions agree; fails loudly on drift.
- baseline-audit-all.sh: wrote to planning/ which doesn't exist; died before
processing any skill. mkdir -p the output dir.
- check-versions.sh: head -n -1 is GNU-only; silently zeroed the dep list
on macOS. Use portable sed '$d'.
- sync-plugins.sh: codex loop counted updates even when jq/mv failed, no
validation before mv, no .tmp cleanup. Now validates + cleans up + counts
only on success. Corrected misleading 'lockstep' comment (version-only).
- generate-marketplace.sh: heredoc interpolated raw values into JSON (latent
injection if a description gained a quote/backslash/newline). Build each
entry with jq -nc --arg.
- fix-frontmatter.mjs: closing --- swallowed when description was last field;
1-space indent emitted invalid >- content; merged unrelated lists;
falsely re-folded already-valid descriptions (non-idempotent, churned 25
files). Added block-scalar idempotency guard, non-blank-continuation
check, delimiter stop, per-list indent scoping.
Minor/hygiene:
- Align divergent version defaults (1.0.0 vs 3.0.0) across codex/marketplace
generators.
- Add pipefail to generate-marketplace.sh + generate-codex-manifests.sh.
* fix(scripts): round-2 adversarial findings — propagate ((VAR++)) fix + harden date parse
Round-2 adversarial review (on commit 154847fb) found two remaining
Important issues in the same bug families:
- baseline-audit-all.sh: the ((VAR++)) counters (COMPLETED, CRITICAL_SKILLS,
HIGH_SKILLS, MEDIUM_SKILLS, CLEAN_SKILLS) had no || true guard, so under
set -euo pipefail the audit aborted on the first skill — the same bug class
fixed in review-skill.sh but not propagated to this caller. Also default
`days=0` so a missing grep match can't throw 'integer expression expected'.
- review-skill.sh: the BSD/GNU date fallback left verified_epoch=0 when the
last_verified value was a quoted scalar or non-YYYY-MM-DD format, silently
flagging the skill as ~20,500 days stale (the exact false-positive the fix
targeted). Now strips surrounding quotes, and if neither parser recognizes
the value, skips the staleness check instead of computing a bogus age.
Both verified: baseline-audit-all now runs all 182 skills to completion;
review-skill date path handles quoted/ISO/unrecognized values correctly.
* fix(fix-frontmatter): cover all YAML block-scalar headers; preserve blank lines on list break
Addresses CodeRabbit review on PR #85:
- Idempotency regex only matched >| with optional chomping (-/+). YAML also
allows indentation indicators (|2, >3) and header comments (| # c), plus
any-order indicator combos (|3+, >2-). Now parses the header token
(before any comment) against the full grammar, leaving all valid
block-scalar headers untouched.
- fixListIndentation dropped buffered blank lines when the list block broke
on a different-indentation line: the blanks were consumed (j advanced)
but never pushed to out. Buffer them as pendingBlanks and push on the
break path so trailing blanks survive in the output.
Verified: 15-case regex test all-correct; idempotent on clean repo (0 files);
validate-frontmatter + validate-json-schemas still green.
174 lines
6.1 KiB
Bash
Executable File
174 lines
6.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# baseline-audit-all.sh - Run quick automated checks on all skills
|
|
# Generates summary data for SKILLS_REVIEW_PROGRESS.md
|
|
# Usage: ./scripts/baseline-audit-all.sh
|
|
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
# Skills live under plugins/<plugin>/skills/<skill>/ and .agents/skills/<skill>/
|
|
# (the repo was restructured away from a flat top-level skills/ directory).
|
|
PLUGINS_DIR="$REPO_ROOT/plugins"
|
|
AGENTS_SKILLS_DIR="$REPO_ROOT/.agents/skills"
|
|
REVIEW_SCRIPT="$REPO_ROOT/scripts/review-skill.sh"
|
|
OUTPUT_FILE="$REPO_ROOT/planning/baseline-audit-results.txt"
|
|
|
|
# List all skill names (one per SKILL.md) across the supported layouts.
|
|
all_skill_names() {
|
|
find "$PLUGINS_DIR" -mindepth 4 -maxdepth 4 -type f -name "SKILL.md" \
|
|
-path "*/skills/*/SKILL.md" 2>/dev/null \
|
|
| sed 's#.*/skills/##; s#/SKILL\.md$##' | sort -u
|
|
find "$AGENTS_SKILLS_DIR" -mindepth 2 -maxdepth 2 -type f -name "SKILL.md" 2>/dev/null \
|
|
| sed 's#.*/skills/##; s#/SKILL\.md$##' | sort -u
|
|
}
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
# Counters
|
|
TOTAL_SKILLS=0
|
|
COMPLETED=0
|
|
CRITICAL_SKILLS=0
|
|
HIGH_SKILLS=0
|
|
MEDIUM_SKILLS=0
|
|
CLEAN_SKILLS=0
|
|
|
|
# Check review script exists
|
|
if [ ! -x "$REVIEW_SCRIPT" ]; then
|
|
echo -e "${RED}Error: review-skill.sh not found or not executable${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
echo "════════════════════════════════════════════════════════════"
|
|
echo " BASELINE AUDIT: All Skills"
|
|
echo "════════════════════════════════════════════════════════════"
|
|
echo ""
|
|
echo "Starting baseline audit..."
|
|
echo "Output will be saved to: $OUTPUT_FILE"
|
|
echo ""
|
|
|
|
# Ensure the output directory exists (planning/ is not guaranteed to be
|
|
# present; without this the `cat >` below fails under `set -e` before any
|
|
# skill is processed).
|
|
mkdir -p "$(dirname "$OUTPUT_FILE")"
|
|
|
|
# Initialize output file
|
|
cat > "$OUTPUT_FILE" << 'EOF'
|
|
# Baseline Audit Results
|
|
# Generated: $(date +"%Y-%m-%d %H:%M:%S")
|
|
#
|
|
# Format: SKILL_NAME | CRITICAL | HIGH | MEDIUM | LOW | STATUS | NOTES
|
|
#
|
|
EOF
|
|
|
|
# Get all skill names (across plugins/ and .agents/skills/)
|
|
SKILLS=($(all_skill_names))
|
|
TOTAL_SKILLS=${#SKILLS[@]}
|
|
|
|
echo "Found $TOTAL_SKILLS skills to audit"
|
|
echo ""
|
|
|
|
# Process each skill
|
|
for skill in "${SKILLS[@]}"; do
|
|
# `((VAR++))` returns exit status 1 when VAR is 0; under `set -e` this would
|
|
# abort the audit on the first skill (same bug class fixed in review-skill.sh).
|
|
((COMPLETED++)) || true
|
|
|
|
echo -ne "[$COMPLETED/$TOTAL_SKILLS] Checking $skill..."
|
|
|
|
# Run review script in quick mode, capture output
|
|
output=$("$REVIEW_SCRIPT" "$skill" --quick 2>&1 || true)
|
|
|
|
# Extract issue counts
|
|
critical=$(echo "$output" | grep -o "🔴 CRITICAL ([0-9]*)" | grep -o "[0-9]*" || echo "0")
|
|
high=$(echo "$output" | grep -o "🟡 HIGH ([0-9]*)" | grep -o "[0-9]*" || echo "0")
|
|
medium=$(echo "$output" | grep -o "🟠 MEDIUM ([0-9]*)" | grep -o "[0-9]*" || echo "0")
|
|
low=$(echo "$output" | grep -o "🟢 LOW ([0-9]*)" | grep -o "[0-9]*" || echo "0")
|
|
|
|
# Determine status
|
|
status="CLEAN"
|
|
priority="🟢 Low"
|
|
|
|
if [ "$critical" -gt 0 ]; then
|
|
((CRITICAL_SKILLS++)) || true
|
|
status="CRITICAL"
|
|
priority="🔴 Critical"
|
|
echo -e " ${RED}CRITICAL${NC} (${critical} critical, ${high} high, ${medium} medium)"
|
|
elif [ "$high" -gt 0 ]; then
|
|
((HIGH_SKILLS++)) || true
|
|
status="HIGH"
|
|
priority="🟡 High"
|
|
echo -e " ${YELLOW}HIGH${NC} (${high} high, ${medium} medium)"
|
|
elif [ "$medium" -gt 0 ]; then
|
|
((MEDIUM_SKILLS++)) || true
|
|
status="MEDIUM"
|
|
priority="🟠 Medium"
|
|
echo -e " ${BLUE}MEDIUM${NC} (${medium} medium, ${low} low)"
|
|
else
|
|
((CLEAN_SKILLS++)) || true
|
|
echo -e " ${GREEN}CLEAN${NC}"
|
|
fi
|
|
|
|
# Extract specific issues for notes
|
|
notes=""
|
|
if echo "$output" | grep -q "Missing YAML frontmatter"; then
|
|
notes="$notes NO_YAML"
|
|
fi
|
|
if echo "$output" | grep -q "Name mismatch"; then
|
|
notes="$notes NAME_MISMATCH"
|
|
fi
|
|
if echo "$output" | grep -q "Last verified.*days ago"; then
|
|
# Default to 0 so a missing/empty match doesn't make `[ "" -gt 90 ]` throw
|
|
# "integer expression expected" under set -e/u and abort the audit.
|
|
days=$(echo "$output" | grep -o "Last verified [0-9]* days ago" | grep -o "[0-9]*" || echo "0")
|
|
[ -z "$days" ] && days=0
|
|
if [ "$days" -gt 90 ]; then
|
|
notes="$notes STALE_${days}d"
|
|
fi
|
|
fi
|
|
if echo "$output" | grep -q "hasn't been verified"; then
|
|
notes="$notes NO_VERIFICATION"
|
|
fi
|
|
|
|
# Write to output file
|
|
echo "$skill|$critical|$high|$medium|$low|$status|$priority|$notes" >> "$OUTPUT_FILE"
|
|
done
|
|
|
|
echo ""
|
|
echo "════════════════════════════════════════════════════════════"
|
|
echo " BASELINE AUDIT COMPLETE"
|
|
echo "════════════════════════════════════════════════════════════"
|
|
echo ""
|
|
echo "Summary:"
|
|
echo " Total Skills: $TOTAL_SKILLS"
|
|
echo " 🔴 Critical: $CRITICAL_SKILLS (immediate attention)"
|
|
echo " 🟡 High: $HIGH_SKILLS (fix soon)"
|
|
echo " 🟠 Medium: $MEDIUM_SKILLS (minor issues)"
|
|
echo " 🟢 Clean: $CLEAN_SKILLS (no issues found)"
|
|
echo ""
|
|
echo "Results saved to: $OUTPUT_FILE"
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo "1. Review $OUTPUT_FILE for detailed breakdown"
|
|
echo "2. Update planning/SKILLS_REVIEW_PROGRESS.md"
|
|
echo "3. Prioritize critical/high issues"
|
|
echo "4. Begin systematic reviews"
|
|
echo ""
|
|
|
|
# Generate summary statistics
|
|
echo "## Summary Statistics" >> "$OUTPUT_FILE"
|
|
echo "" >> "$OUTPUT_FILE"
|
|
echo "- Total Skills: $TOTAL_SKILLS" >> "$OUTPUT_FILE"
|
|
echo "- Critical Priority: $CRITICAL_SKILLS" >> "$OUTPUT_FILE"
|
|
echo "- High Priority: $HIGH_SKILLS" >> "$OUTPUT_FILE"
|
|
echo "- Medium Priority: $MEDIUM_SKILLS" >> "$OUTPUT_FILE"
|
|
echo "- Clean: $CLEAN_SKILLS" >> "$OUTPUT_FILE"
|
|
echo "" >> "$OUTPUT_FILE"
|
|
|
|
exit 0
|