| name | phpstan-resolver |
| description | Résout automatiquement les erreurs PHPStan détectées dans le projet en analysant et corrigeant les problèmes de types stricts, annotations generics, array shapes et collections Doctrine. Boucle jusqu'à zéro erreur ou stagnation. |
| allowed-tools | Task, Bash, Read, Edit, Grep, Glob, TodoWrite |
| model | claude-opus-4-1-20250805 |
PHPStan Error Resolver Skill
Variables
PHPSTAN_CONFIG="phpstan.neon" # ou phpstan.neon.dist
PHPSTAN_BIN="./vendor/bin/phpstan"
ERROR_BATCH_SIZE=5
MAX_ITERATIONS=10
Workflow
Étape 0: Timing
START_TIME=$(date +%s)
date
Étape 1: Vérification Environnement
# Vérifier PHPStan installé
if [ ! -f "$PHPSTAN_BIN" ]; then
echo "❌ PHPStan non trouvé: $PHPSTAN_BIN"
exit 1
fi
# Vérifier config PHPStan
if [ ! -f "$PHPSTAN_CONFIG" ] && [ ! -f "phpstan.neon.dist" ]; then
echo "❌ Configuration PHPStan introuvable"
exit 1
fi
# Utiliser phpstan.neon.dist si phpstan.neon absent
if [ ! -f "$PHPSTAN_CONFIG" ]; then
PHPSTAN_CONFIG="phpstan.neon.dist"
fi
echo "✅ Environnement PHPStan valide"
echo " Config: $PHPSTAN_CONFIG"
Étape 2: Exécution Initiale PHPStan
echo "🔍 Analyse PHPStan initiale..."
# Exécuter PHPStan
$PHPSTAN_BIN analyze --no-progress --error-format=json > /tmp/phpstan_initial.json
# Parser résultat
TOTAL_ERRORS_INITIAL=$(jq '.totals.file_errors' /tmp/phpstan_initial.json)
if [ "$TOTAL_ERRORS_INITIAL" -eq 0 ]; then
echo "✅ Aucune erreur PHPStan détectée"
exit 0
fi
echo "📊 Erreurs détectées: $TOTAL_ERRORS_INITIAL"
Étape 3: TodoWrite Initialisation
todos:
- content: "Analyser erreurs PHPStan"
status: "completed"
activeForm: "Analyse des erreurs PHPStan"
- content: "Grouper erreurs par fichier"
status: "pending"
activeForm: "Groupement des erreurs par fichier"
- content: "Résoudre erreurs (itération 1)"
status: "pending"
activeForm: "Résolution des erreurs (itération 1)"
- content: "Vérifier résolution"
status: "pending"
activeForm: "Vérification de la résolution"
Étape 4: Groupement Erreurs par Fichier
Marquer todo #2 in_progress.
# Parser JSON et grouper par fichier
jq -r '.files | to_entries[] | "\(.key)|\(.value.messages | length)"' /tmp/phpstan_initial.json > /tmp/phpstan_files.txt
# Afficher groupement
echo "📁 Erreurs par fichier:"
cat /tmp/phpstan_files.txt | while IFS='|' read file count; do
echo " - $file: $count erreurs"
done
Marquer todo #2 completed.
Étape 5: Boucle de Résolution
Marquer todo #3 in_progress.
ITERATION=1
ERRORS_CURRENT=$TOTAL_ERRORS_INITIAL
ERRORS_PREVIOUS=0
while [ $ITERATION -le $MAX_ITERATIONS ] && [ $ERRORS_CURRENT -gt 0 ] && [ $ERRORS_CURRENT -ne $ERRORS_PREVIOUS ]; do
echo ""
echo "🔄 Itération $ITERATION/$MAX_ITERATIONS"
echo " Erreurs: $ERRORS_CURRENT"
# Traiter chaque fichier avec erreurs
cat /tmp/phpstan_files.txt | while IFS='|' read file error_count; do
if [ "$error_count" -gt 0 ]; then
echo " 📝 Traitement: $file ($error_count erreurs)"
# Extraire erreurs pour ce fichier
jq -r --arg file "$file" '.files[$file].messages[] | "\(.line)|\(.message)"' /tmp/phpstan_initial.json > /tmp/phpstan_file_errors.txt
# Limiter batch size
head -n $ERROR_BATCH_SIZE /tmp/phpstan_file_errors.txt > /tmp/phpstan_batch.txt
# Déléguer à agent phpstan-error-resolver
echo "Utiliser agent @phpstan-error-resolver avec:"
echo "Fichier: $file"
echo "Erreurs:"
cat /tmp/phpstan_batch.txt
# L'agent lit le fichier, analyse erreurs, applique corrections via Edit
fi
done
# Re-exécuter PHPStan
echo " 🔍 Vérification post-correction..."
$PHPSTAN_BIN analyze --no-progress --error-format=json > /tmp/phpstan_iteration_${ITERATION}.json
ERRORS_PREVIOUS=$ERRORS_CURRENT
ERRORS_CURRENT=$(jq '.totals.file_errors' /tmp/phpstan_iteration_${ITERATION}.json)
echo " 📊 Résultat: $ERRORS_CURRENT erreurs restantes"
# Mettre à jour fichiers avec erreurs
jq -r '.files | to_entries[] | "\(.key)|\(.value.messages | length)"' /tmp/phpstan_iteration_${ITERATION}.json > /tmp/phpstan_files.txt
ITERATION=$((ITERATION + 1))
done
Marquer todo #3 completed.
Étape 6: Analyse Résultat Final
Marquer todo #4 in_progress.
ERRORS_FIXED=$((TOTAL_ERRORS_INITIAL - ERRORS_CURRENT))
SUCCESS_RATE=$(awk "BEGIN {printf \"%.1f\", ($ERRORS_FIXED / $TOTAL_ERRORS_INITIAL) * 100}")
echo ""
echo "📊 Résumé Final:"
echo " - Erreurs initiales: $TOTAL_ERRORS_INITIAL"
echo " - Erreurs restantes: $ERRORS_CURRENT"
echo " - Erreurs corrigées: $ERRORS_FIXED"
echo " - Taux de succès: ${SUCCESS_RATE}%"
echo " - Itérations: $((ITERATION - 1))/$MAX_ITERATIONS"
# Identifier fichiers non résolus
if [ $ERRORS_CURRENT -gt 0 ]; then
echo ""
echo "⚠️ Fichiers avec erreurs restantes:"
cat /tmp/phpstan_files.txt | while IFS='|' read file count; do
if [ "$count" -gt 0 ]; then
echo " - $file: $count erreurs"
fi
done
fi
Marquer todo #4 completed.
Étape 7: Rapport Final
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
if [ $DURATION -lt 60 ]; then
DURATION_STR="${DURATION}s"
elif [ $DURATION -lt 3600 ]; then
MINUTES=$((DURATION / 60))
SECONDS=$((DURATION % 60))
DURATION_STR="${MINUTES}m ${SECONDS}s"
else
HOURS=$((DURATION / 3600))
MINUTES=$(((DURATION % 3600) / 60))
SECONDS=$((DURATION % 60))
DURATION_STR="${HOURS}h ${MINUTES}m ${SECONDS}s"
fi
echo "⏱️ Durée: $DURATION_STR"
task: "Résolution des erreurs PHPStan"
status: "terminé"
details:
total_errors_initial: $TOTAL_ERRORS_INITIAL
total_errors_final: $ERRORS_CURRENT
errors_fixed: $ERRORS_FIXED
success_rate: "${SUCCESS_RATE}%"
iterations: $((ITERATION - 1))
files:
fixed:
- [Liste des fichiers corrigés]
failed:
- [Liste des fichiers non résolus]
statistics:
success_rate: "${SUCCESS_RATE}%"
execution_time: "$DURATION_STR"
phpstan_level: "[Niveau détecté depuis config]"
notes:
- "Toutes les erreurs PHPStan ont été analysées"
- "Les corrections ont été appliquées automatiquement"
- "Relancer si erreurs restantes avec contexte différent"
Error Handling
- PHPStan non trouvé → ARRÊT (exit 1)
- Config PHPStan absente → ARRÊT (exit 1)
- Stagnation (erreurs ne diminuent plus) → ARRÊT avec rapport
- Max itérations atteint → ARRÊT avec rapport
Notes
- Utilise l'agent
@phpstan-error-resolverpour corrections - Batch size de 5 erreurs par fichier par itération
- Maximum 10 itérations pour éviter boucles infinies
- Parser JSON via
jq - Marquer CHAQUE todo completed immédiatement après succès