Communitygithub.com

Refactor Scan

Suite de habilidades para la refactorización continua de una base de código.

¿Qué es Refactor Scan?

Refactor Scan es una habilidad para agentes de IA (como Claude Code, Cursor, Codex) diseñada para monitorear y coordinar el proceso de refactorización continua de un proyecto de software. Su función principal es detectar oportunidades de refactorización y hacer seguimiento del estado de las que ya están en curso, sin decidir el resultado final ni crear incidencias automáticamente. La habilidad inspecciona el repositorio en busca de nodos de herramientas pendientes (definidos en un árbol de herramientas), verifica condiciones previas (como límites de incidencias abiertas) y reconcilia el estado de las solicitudes de pull asociadas a incidencias de refactorización. Si detecta cambios en las revisiones o comentarios, puede identificar candidatos para reanudar el trabajo. Además, reconoce candidatos etiquetados externamente y maneja casos sin acceso a API de forjas (GitHub/GitLab) mediante un modo de reconciliación solo con git. La habilidad produce hallazgos que envía a `refactor-learn`, propuestas para `refactor-prioritize` y, en su caso, candidatos para reanudar que van directamente a `refactor-implement`.

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

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

¿Qué hace Refactor Scan?

Detecta, nunca escribe. Propone en qué se podría trabajar a continuación y detecta lo que ya se ha resuelto por sí solo desde la última pasada — nunca crea una incidencia, nunca decide un resultado. refactor-design crea incidencias para lo que se elige; refactor-learn actúa sobre lo que esta habilidad detecta.

Proceso

1. Comprobar condiciones previas

  • No hay repositorio git → detener la pasada, informarlo, no proponer nada.
  • Cinco o más incidencias abiertas con la etiqueta refactor:candidate → detener, no proponer nada nuevo; dejar que el trabajo existente se resuelva primero.

2. Reanudar trabajo pendiente primero

Leer el campo Pending candidates de las Notas de Refactorización (skills/continuous-refactoring/references/refactoring-bookkeeping.md). Si nombra una incidencia, una pasada anterior de refactor-design la creó pero fue interrumpida antes de que le siguiera una solicitud de merge. Proponer exactamente esa incidencia y detenerse — terminar el trabajo pendiente tiene prioridad sobre proponer trabajo nuevo.

3. Detectar estado recordado cerrado/fusionado

Obtener el conjunto recordado — docs/agents/issue-tracker.md nombra un rastreador de etiquetas nativo (GitHub, GitLab) → cada incidencia abierta con etiqueta refactor:candidate, resuelta a su pull request vinculada mediante la referencia cruzada nativa del rastreador (el Closes #<n> que refactor-implement paso 5 ya pone en una MR que entrega); una incidencia sin PR vinculada aún no tiene nada que reconciliar en este paso. De lo contrario → cada entrada en el archivo merge-requests.md de las Notas de Refactorización. Para cada una, comprobar el rastreador externo/git: ¿la MR sigue abierta?, ¿la incidencia sigue abierta?

No hay gh/glab (u otra API/token de forja) disponible → recurrir a reconciliación solo con git en lugar de saltar este paso (nunca intentar instalar gh/glab aquí — tratar su ausencia exactamente como el desencadenante de esta alternativa): skills/refactor-scan/references/git-only-reconciliation.md. Sin remoto (git remote -v vacío) → la variante solo local del mismo archivo — un candidato recordado puede haber sido fusionado o rechazado por un humano trabajando puramente en local, según opening-a-merge-request.md sección "No forge/remote available".

  • Fusionado → un hallazgo: entregado.

  • Cerrado sin fusionar → un hallazgo: rechazado — anotar si los comentarios de cierre dan una razón estructural del mantenedor (material fuera de alcance) o no.

  • Todavía abierto, con actividad del revisor (una revisión o comentario) más reciente que el último commit de la rama → un candidato para reanudar, no un hallazgo — nadie ha decidido nada aún, solo necesita otra revisión. API disponible → leer también el estado real de la revisión junto con la marca de tiempo (gh pr view <n> --json reviews,reviewDecision o equivalente) — no detenerse en "algo cambió":

    • CHANGES_REQUESTED, sin abordar (sin commit más reciente que la revisión) → sigue siendo candidato para reanudar, pero pasar adelante los propios comentarios/cuerpo de la revisión junto con él, no solo la rama — refactor-implement paso 1 lee y aborda esa retroalimentación específica, no solo reexamina la rama desde cero.
    • Un comentario, o una revisión APPROVED sin retroalimentación bloqueante → el manejo genérico de candidato para reanudar existente; nada más que adjuntar.

    Pasarlo adelante de la misma manera que el paso 2 pasa adelante una entrada de Pending candidates: directamente a refactor-implement, saltándose refactor-prioritize/refactor-design (ya tiene un diseño y una MR abierta; solo aplica el bucle de corrección — refactor-implement paso 1 ya soporta reanudar una rama existente). Sin API (alternativa solo git) → el estado de revisión no está disponible exactamente como ya documenta git-only-reconciliation.md; este refinamiento no aplica allí.

  • Todavía abierto, nada cambió → no es un hallazgo.

También comprobar cada entrada en el archivo out-of-scope/<node>.md de las Notas de Refactorización que nombre una condición **Blocked by:** PHP >= X.Y (tooling_tree.py's detect_nodes() informa esto directamente cuando se ejecuta; manualmente, comparar con el require.php/config.platform.php del composer.json actual del objetivo) — si la versión actual de PHP del objetivo ahora la satisface, un hallazgo: este rechazo se revierte. Sin campo Blocked by:, o condición aún no cumplida → nunca un hallazgo.

Entregar cada hallazgo a refactor-learn — esta habilidad solo detecta; nunca marca nada como done/wontfix y nunca escribe en out-of-scope/ de las Notas de Refactorización.

3b. Detectar candidatos etiquetados externamente

API disponible (no la alternativa solo git) → también consultar incidencias abiertas con etiqueta refactor:candidate que no estén ya contempladas: no la entrada de Pending candidates del paso 2, no el conjunto recordado del paso 3 (una incidencia con un pull request vinculado ya está en curso). Lo que queda es un candidato que un humano (u otro proceso) etiquetó directamente, que este bucle nunca ha diseñado ni implementado — en operación normal los propios candidatos del suite siempre están cubiertos por uno de esos dos, así que no se necesita nada extra para distinguir "nuestros" de "de otros". Pasar cada uno adelante como una propuesta, a la misma lista que se unen las propuestas del árbol de herramientas del paso 4 — refactor-prioritize las clasifica junto a todo lo demás según sus factores habituales; compite por sus propios méritos, nunca se salta la cola solo por existir. Sin API (alternativa solo git) → saltar este paso por completo; git solo no puede enumerar incidencias por etiqueta.

4. Proponer nodos del árbol de herramientas

Saltar si el paso 2 ya propuso un candidato pendiente.

Ejecutar python3 skills/refactor-scan/references/tooling_tree.py <target-repo> y leer el campo next del JSON — el conjunto real, actualmente desbloqueado, nodos rechazados (una entrada existente en out-of-scope/<node>.md de las Notas de Refactorización) ya excluidos, tomar tal cual sin importar cuántas entradas tenga. No roadmap (una simulación hacia adelante, no opciones reales hoy). También leer withheld: nodos que de otro modo estarían en next pero esperan a un padre recomendado no decidido — cada entrada nombra qué padre(s). Sin python3, o no permitido → enviar un subagente con el prompt de skills/refactor-scan/references/tree-walk-prompt.md ({N}=all) — recorre los mismos documentos del árbol a mano (lee primero Fulfilled nodes del bookkeeping.md de las Notas de Refactorización para evitar re-derivar estado cachead, salta cualquier nodo con una entrada out-of-scope); sin mecanismo de subagente → ejecutar sus pasos directamente.

  • Nodos de herramientas ordinarios (loop-config, y nodos de especialización del lenguaje, p. ej. skills/refactor-scan/references/php-tooling-tree.md) — propuestos por su Nombre (nunca el slug crudo); cada uno ya está completamente especificado en su documento de árbol.
  • structural-scan — propuesto una vez que todos los nodos con una arista resolved hacia él están resueltos (cumplidos, o rechazados explícitamente bajo out-of-scope/ de las Notas de Refactorización): editorconfig en la raíz genérica, más el propio nodo de agregación de la especialización del lenguaje activo (PHP: php-structural-scan), a su vez resuelto una vez que todos sus propios padres resueltos están resueltos (skills/refactor-scan/references/tooling-tree.md). Solo structural-scan se propone de esta manera — php-structural-scan es pura tubería, nunca un candidato. Proponerlo es solo nombrarlo; la exploración del código base ocurre en refactor-design, solo para el nodo realmente elegido.
  • Ningún árbol de lenguaje reconocido: structural-scan sigue esperando a editorconfig, la hoja genérica de la raíz — no es inmediatamente proponible solo porque no aplique ningún árbol específico del lenguaje.

Salida

Entregada por el orquestador, claramente:

  • Qué condición previa detuvo la pasada, si es que alguna — nada de lo siguiente aplica en esta pasada.
  • Hallazgos (posiblemente vacíos) → refactor-learn.
  • Un candidato para reanudar, si se detectó uno → directamente a refactor-implement, omitiendo refactor-prioritize/refactor-design.
  • Propuestas — el candidato pendiente solo, o cada Nombre de nodo actualmente desbloqueado (nunca slugs, nunca limitado) más cualquier candidato etiquetado externamente del paso 3b, o ninguno → refactor-prioritize. Todos los nodos actualmente desbloqueados (padres requeridos cumplidos, no rechazados, cada padre recomendado ya decidido) — nunca un subconjunto truncado por prioridad. Junto a ello, nombrar cada nodo withheld y qué padre(s) está esperando (p. ej. "Rector: Type Coverage Set — esperando a: PHP CS Fixer").

Criterio de finalización

Hallazgos (si los hay) entregados a refactor-learn, un candidato para reanudar (si existe) entregado directamente a refactor-implement, propuestas (si las hay) entregadas a refactor-prioritize — o una condición previa detuvo la pasada y el informe dice cuál. Nunca un nodo junto con entradas más allá de structural-scan en la misma lista.

Skills relacionados