Skip to content

Improve analyze-and-plan skill quality (65% → 94%) #57

Improve analyze-and-plan skill quality (65% → 94%)

Improve analyze-and-plan skill quality (65% → 94%) #57

Workflow file for this run

name: Tessl Skill Review
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
tessl-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: tesslio/setup-tessl@v2
- name: Detect changed skills
id: detect
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
# Build list of all skill directories (parents of SKILL.md)
ALL_SKILL_DIRS=$(find skills -name SKILL.md -exec dirname {} \; | sort)
# For each changed file, find which skill directory it belongs to
DIRS=""
for changed_file in $CHANGED_FILES; do
for skill_dir in $ALL_SKILL_DIRS; do
case "$changed_file" in
"$skill_dir"/*)
# Check not already added
case " $DIRS " in
*" $skill_dir "*) ;;
*) DIRS="$DIRS $skill_dir" ;;
esac
break
;;
esac
done
done
DIRS=$(echo "$DIRS" | xargs) # trim whitespace
# Check for unmatched changes under skills/
UNMATCHED=false
for changed_file in $CHANGED_FILES; do
case "$changed_file" in
skills/*)
MATCHED=false
for skill_dir in $ALL_SKILL_DIRS; do
case "$changed_file" in
"$skill_dir"/*) MATCHED=true; break ;;
esac
done
if [ "$MATCHED" = "false" ]; then
UNMATCHED=true
break
fi
;;
esac
done
if [ "$UNMATCHED" = "true" ]; then
echo "Unmatched changes under skills/ detected — reviewing all skills"
DIRS=$(find skills -name SKILL.md -exec dirname {} \; 2>/dev/null | tr "\n" " " | xargs)
fi
if [ -z "$DIRS" ]; then
echo "skip=true" >> "$GITHUB_OUTPUT"
echo "No skill files changed."
else
echo "skip=false" >> "$GITHUB_OUTPUT"
echo "dirs=$DIRS" >> "$GITHUB_OUTPUT"
echo "Changed skills: $DIRS"
fi
else
# Push to main: review all skills
echo "skip=false" >> "$GITHUB_OUTPUT"
echo "dirs=" >> "$GITHUB_OUTPUT"
echo "Push to main — will review all skills."
fi
- name: Post skip summary
if: steps.detect.outputs.skip == 'true'
run: |
echo "## Skill Review" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "No skills changed — review skipped." >> "$GITHUB_STEP_SUMMARY"
- name: Review skills
if: steps.detect.outputs.skip != 'true'
run: |
THRESHOLD=50
PASS=0
FAIL=0
SUMMARY_FILE=$(mktemp)
ERRORS_FILE=$(mktemp)
SKILL_DIRS_INPUT="${{ steps.detect.outputs.dirs }}"
SKILL_LIST_FILE=$(mktemp)
trap 'rm -f "$SKILL_LIST_FILE" "$SUMMARY_FILE" "$ERRORS_FILE"' EXIT
if [ -z "$SKILL_DIRS_INPUT" ]; then
# Push to main or no filter: review all skills
find skills -name SKILL.md -exec dirname {} \; > "$SKILL_LIST_FILE"
else
# PR mode: use detected skill dirs
printf '%s\n' $SKILL_DIRS_INPUT > "$SKILL_LIST_FILE"
fi
while IFS= read -r dir; do
[ -z "$dir" ] && continue
SKILL_NAME=$(basename "$dir")
echo "::group::Reviewing $SKILL_NAME"
EXIT_CODE=0
OUTPUT=$(tessl skill review "$dir" 2>&1) || EXIT_CODE=$?
echo "$OUTPUT"
echo "::endgroup::"
if [ "$EXIT_CODE" -ne 0 ]; then
echo "::warning::tessl skill review failed for $SKILL_NAME (exit code $EXIT_CODE)"
FAIL=$((FAIL + 1))
echo "| $SKILL_NAME | error | ❌ |" >> "$SUMMARY_FILE"
continue
fi
SCORE=$(echo "$OUTPUT" | grep -oE '[0-9]+%' | tail -1 | tr -d '%')
if [ -z "$SCORE" ]; then
echo "::warning::Could not parse score for $SKILL_NAME"
SCORE=0
fi
if [ "$SCORE" -lt "$THRESHOLD" ]; then
FAIL=$((FAIL + 1))
echo " ❌ $SKILL_NAME: ${SCORE}% (below ${THRESHOLD}%)" >> "$ERRORS_FILE"
echo "| $SKILL_NAME | ${SCORE}% | ❌ |" >> "$SUMMARY_FILE"
else
PASS=$((PASS + 1))
echo "| $SKILL_NAME | ${SCORE}% | ✅ |" >> "$SUMMARY_FILE"
fi
done < "$SKILL_LIST_FILE"
TOTAL=$((PASS + FAIL))
# Fail if no skills were reviewed (push to main only)
if [ "$TOTAL" -eq 0 ] && [ "${{ github.event_name }}" != "pull_request" ]; then
echo "::error::No skills were reviewed — expected at least one"
exit 1
fi
# Write GitHub Step Summary
{
echo "## Skill Review"
echo ""
echo "| Skill | Score | Status |"
echo "|-------|-------|--------|"
cat "$SUMMARY_FILE"
echo "| **Total** | **$PASS/$TOTAL passed** | $([ "$FAIL" -eq 0 ] && echo '✅' || echo '❌') |"
} >> "$GITHUB_STEP_SUMMARY"
# Stdout summary for logs
echo ""
echo "============================="
echo " Skill Review Summary"
echo "============================="
echo " Total: $TOTAL"
echo " Passed: $PASS"
echo " Failed: $FAIL"
if [ -s "$ERRORS_FILE" ]; then
echo ""
echo " Failed skills:"
cat "$ERRORS_FILE"
fi
echo "============================="
if [ "$FAIL" -gt 0 ]; then
echo "::error::$FAIL skill(s) scored below ${THRESHOLD}%"
exit 1
fi