Communitygithub.com

Art4/continuous-refactoring

Suite de compétences pour le refactoring continu d'une base de code.

Qu'est-ce que continuous-refactoring ?

Cette compétence d'agent, conçue pour les assistants de codage IA comme Claude Code, Cursor ou Codex, automatise un cycle de refactoring continu basé sur l'observation et la proposition. Elle ne modifie jamais le code directement, mais détecte des opportunités de refactoring, suit l'état des propositions en cours, et transmet ses constats à d'autres compétences spécialisées (`refactor-design`, `refactor-implement`, `refactor-learn`) pour la prise de décision et l'exécution. Le processus suit un flux précis : vérification des préconditions (git, limite de tickets ouverts), reprise du travail en attente, détection des demandes de fusion fusionnées ou fermées, et proposition de nouveaux nœuds de refactoring à partir d'un arbre d'outillage. Il gère également les tickets marqués manuellement par un humain comme candidats au refactoring. Chaque cycle produit des constats (pour apprentissage), un éventuel candidat à reprendre, et une liste de propositions pour le prochain cycle, sans jamais décider de l'issue.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add Art4/continuous-refactoring

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Refactor Scan

Détecter, ne jamais écrire. Propose ce sur quoi on pourrait travailler ensuite et remarque ce qui s'est déjà résolu depuis le dernier passage — ne crée jamais de ticket, ne décide jamais d'un résultat. refactor-design crée des tickets pour ce qui est choisi ; refactor-learn agit sur ce que cette compétence détecte.

Processus

1. Vérifier les préconditions

  • Pas de dépôt git → arrêter le passage, le signaler, ne rien proposer.
  • Cinq tickets ouverts refactor:candidate ou plus → arrêter, ne rien proposer de nouveau ; laisser le travail existant se terminer d'abord.

2. Reprendre d'abord le travail en attente

Lire le champ Pending candidates du fichier bookkeeping.md des Notes de Refactoring (skills/continuous-refactoring/references/refactoring-bookkeeping.md). S'il nomme un ticket, un passage précédent de refactor-design l'a créé mais a été interrompu avant qu'une demande de fusion ne suive. Proposer exactement ce ticket et s'arrêter — terminer le travail en attente prime sur la proposition de nouveau travail.

3. Détecter l'état fermé/fusionné des éléments mémorisés

Obtenir l'ensemble mémorisé — docs/agents/issue-tracker.md nomme un tracker natif par étiquette (GitHub, GitLab) → chaque ticket ouvert refactor:candidate, résolu en sa demande de fusion liée via la référence croisée native ticket↔PR de fermeture du tracker (le Closes #<n> que refactor-implement étape 5 met déjà sur une MR de livraison) ; un ticket sans PR liée n'a rien à réconcilier à cette étape. Sinon → chaque entrée dans merge-requests.md des Notes de Refactoring. Pour chacune, vérifier le tracker externe/git : la MR est-elle toujours ouverte, le ticket est-il toujours ouvert ?

Pas de gh/glab (ou autre API/token de forge) disponible → passer à la réconciliation uniquement par git au lieu de sauter cette étape (ne jamais essayer d'installer gh/glab ici non plus — traiter leur absence exactement comme le déclencheur de ce repli) : skills/refactor-scan/references/git-only-reconciliation.md. Pas de remote du tout (git remote -v vide) → la variante locale uniquement du même fichier — un candidat mémorisé peut avoir été fusionné ou rejeté par un humain travaillant purement en local, conformément à opening-a-merge-request.md section "Aucune forge/remote disponible".

  • Fusionné → un constat : livré.

  • Fermé sans fusion → un constat : refusé — noter si les commentaires de fermeture donnent une raison structurelle du mainteneur (hors périmètre) ou non.

  • Toujours ouvert, avec une activité de relecture (une revue ou un commentaire) plus récente que le dernier commit de la branche → un candidat à reprendre, pas un constat — personne n'a encore décidé quoi que ce soit, cela a juste besoin d'un autre regard. Accès API disponible → lire aussi l'état réel de la revue avec le timestamp (gh pr view <n> --json reviews,reviewDecision ou équivalent) — ne pas s'arrêter à "quelque chose a changé" :

    • CHANGES_REQUESTED, non traité (pas de commit plus récent que la revue) → toujours un candidat à reprendre, mais transmettre les commentaires/corps de la revue avec, pas seulement la branche — refactor-implement étape 1 lit et traite ce retour spécifique, pas seulement réexamine la branche de zéro.
    • Un commentaire, ou une revue APPROVED sans retour bloquant → la gestion générique existante du candidat à reprendre ; rien d'autre à attacher.

    Le transmettre de la même manière que l'étape 2 transmet une entrée Pending candidates : directement à refactor-implement, en contournant refactor-prioritize/refactor-design (il a déjà une conception et une MR ouverte ; seule la boucle de correction s'applique — refactor-implement étape 1 supporte déjà la reprise d'une branche existante). Pas d'accès API (repli git uniquement) → l'état de la revue reste indisponible exactement comme documenté dans git-only-reconciliation.md ; cet affinement ne s'applique pas là.

  • Toujours ouvert, rien n'a changé → pas de constat.

Vérifier aussi chaque entrée dans out-of-scope/<node>.md des Notes de Refactoring nommant une condition **Bloqué par :** PHP >= X.Y (tooling_tree.py's detect_nodes() le rapporte directement lorsqu'il est exécuté ; à la main, comparer avec le require.php/config.platform.php actuel du composer.json de la cible) — si la version actuelle de PHP de la cible satisfait désormais la condition, un constat : ce rejet est annulé. Pas de champ Bloqué par :, ou condition toujours non satisfaite → jamais un constat.

Transmettre chaque constat à refactor-learn — cette compétence ne fait que remarquer ; elle ne marque jamais rien done/wontfix et n'écrit jamais elle-même dans out-of-scope/ des Notes de Refactoring.

3b. Détecter les candidats étiquetés extérieurement

Accès API disponible (pas le repli git uniquement) → interroger aussi les tickets ouverts refactor:candidate qui ne sont pas déjà pris en compte : pas l'entrée Pending candidates de l'étape 2, pas l'ensemble mémorisé de l'étape 3 (un ticket avec une demande de fusion liée est déjà en vol). Ce qui reste est un candidat qu'un humain (ou un autre processus) a étiqueté directement, que cette boucle n'a jamais conçu ni implémenté — en fonctionnement normal, les propres candidats de la suite sont toujours couverts par l'un de ces deux, donc rien de plus n'est nécessaire pour distinguer "les nôtres" de "ceux des autres". Transmettre chacun comme une proposition, la même liste à laquelle les propositions de l'arbre d'outillage de l'étape 4 se joignent — refactor-prioritize les classe à côté de tout le reste selon ses facteurs habituels ; ils concourent sur leurs propres mérites, ne sautent jamais la file d'attente simplement pour exister. Pas d'accès API (repli git uniquement) → sauter cette étape entièrement, git seul ne peut pas énumérer les tickets par étiquette.

4. Proposer les nœuds de l'arbre d'outillage

Sauter si l'étape 2 a déjà proposé un candidat en attente.

Exécuter python3 skills/refactor-scan/references/tooling_tree.py <dépôt-cible> et lire le champ next du JSON — l'ensemble réel, actuellement non bloqué, les nœuds rejetés (une entrée existante dans out-of-scope/<node>.md des Notes de Refactoring) déjà exclus, prendre tel quel le nombre d'entrées qu'il contient. Pas roadmap (une simulation prospective, pas des options réelles aujourd'hui). Lire aussi withheld : les nœuds qui autrement seraient dans next mais attendent un parent recommandé non décidé — chaque entrée nomme le(s) parent(s). Pas de python3, ou non autorisé → envoyer un sous-agent avec le prompt de skills/refactor-scan/references/tree-walk-prompt.md ({N}=all) — il parcourt les mêmes documents d'arbre manuellement (lit d'abord le champ Fulfilled nodes de bookkeeping.md des Notes de Refactoring pour éviter de re-dériver l'état mis en cache, saute tout nœud avec une entrée hors périmètre) ; pas de mécanisme de sous-agent → exécuter ses étapes vous-même en ligne.

  • Nœuds d'outillage ordinaires (loop-config, et nœuds de spécialisation de langage, par ex. skills/refactor-scan/references/php-tooling-tree.md) — proposés par leur Nom (jamais l'identifiant brut) ; chacun est déjà entièrement spécifié dans son document d'arbre.
  • structural-scan — proposé une fois que chaque nœud avec une arête resolved vers lui est résolu (rempli, ou explicitement rejeté sous out-of-scope/ des Notes de Refactoring) : editorconfig à la racine générique, plus le propre nœud d'agrégation de la spécialisation de langage active (PHP : php-structural-scan), lui-même résolu une fois que chacun de ses propres parents résolus est résolu (skills/refactor-scan/references/tooling-tree.md). Seul structural-scan est jamais proposé de cette manière — php-structural-scan est une pure tuyauterie, jamais un candidat. Le proposer est simplement le nommer ; le parcours de la base de code a lieu dans refactor-design, seulement pour le nœud effectivement choisi.
  • Aucun arbre de langage reconnu : structural-scan attend toujours editorconfig, la feuille racine générique — pas immédiatement proposable simplement parce qu'aucun arbre spécifique à un langage ne s'applique.

Sortie

Transmise par l'orchestrateur, simplement :

  • Quelle précondition a arrêté le passage, le cas échéant — rien ci-dessous ne s'applique à ce passage.
  • Constat (éventuellement vide) → refactor-learn.
  • Un candidat à reprendre, si détecté → directement à refactor-implement, en contournant refactor-prioritize/refactor-design.
  • Propositions — le candidat en attente seul, ou chaque Nom de nœud actuellement non bloqué (jamais les identifiants bruts, jamais en majuscules) plus tout candidat étiqueté extérieurement de l'étape 3b, ou rien → refactor-prioritize. Chaque nœud actuellement non bloqué (parents requis remplis, non rejeté, chaque parent recommandé déjà décidé) — jamais un sous-ensemble tronqué par priorité. Avec cela, nommer chaque nœud withheld et le(s) parent(s) qu'il attend (par ex. "Rector : Type Coverage Set — attend : PHP CS Fixer").

Critère de complétion

Les constats (le cas échéant) transmis à refactor-learn, un candidat à reprendre (le cas échéant) transmis directement à refactor-implement, les propositions (le cas échéant) transmises à refactor-prioritize — ou une précondition a arrêté le passage et le rapport indique laquelle. Jamais un nœud avec des entrées au-delà de structural-scan dans la même liste.

Skills associés