SuperAPI AI Directory

work-integrate

Testing & quality

View repository

Updated 10-15 23:42

About this skill

Skill: Integración de trabajo

Guía para cerrar e integrar el trabajo ya implementado —una historia de usuario US-XXX o una tarea de mantenimiento WI-XXX— verificando que su progress.md tenga todas las unidades del trabajo en Done, que pasen las puertas de calidad de cierre (quality-check, code-review y coverage-verify, en ese orden), y luego hacer merge de la rama actual hacia la rama desde la que se creó.

Alcance del submit: El skill cierra localmente lo ya implementado. Verifica condiciones y ejecuta git merge --no-ff. No archiva el artefacto: archivar es una decisión posterior a la revisión humana y la hace el skill que produjo el artefacto (/work-define US-XXX archive, /work-plan WI-XXX archive; ver ${PLUGIN_ROOT}/references/archive.md). No hace push, no borra ramas, no crea MRs/PRs, no modifica el contenido de progress.md, y no resuelve conflictos —con la única salida declarada del modify/delete sobre los dos informes de docs/audits/, que se resuelve por el lado del borrado (ver references/flows.md). Lo que no esté en Done bloquea el merge — el usuario decide cómo proceder, nunca se fuerza.

Encaja al final de los ciclos work-define → work-plan → work-implement (historias y tareas de mantenimiento). Ver Handoffs del ciclo en references/examples.md.


Cómo preguntar al usuario

Mecanismo, ritmo y fallback compartidos: ${PLUGIN_ROOT}/references/asking.md.

Cada vez que este skill o sus referencias digan preguntar, pedir, confirmar, validar o sugerir algo al usuario, asume ese mecanismo; no se repite allí.

La tanda inicial va antes de cualquier operación git y cubre: trabajo asociado a la rama, carpeta ambigua y rama base. No empezar a mover, mergear ni archivar con lagunas abiertas.

Excepción al ritmo: el cierre del trabajo (paso 11, Done) va por fuerza después del merge — hasta entonces no se sabe si el trabajo llega a integrarse.

Rama base ambigua: listar los candidatos detectados como opciones tappables (p. ej. develop, main, release/2026.q2); no proponer un default implícito.


Rutas de las referencias compartidas

${PLUGIN_ROOT} es la raíz del plugin instalado (la carpeta que contiene skills/, agents/ y references/), y toda referencia compartida de este skill se escribe como ${PLUGIN_ROOT}/references/<archivo>.md. Para resolverla: la raíz es la carpeta desde la que se cargó este archivo, dos niveles arriba (<raíz>/skills/<nombre>/SKILL.md) — el cliente anuncia esa ubicación al invocar el skill (p. ej. «Base directory for this skill: …»). Si esa ubicación no está disponible, localizar la instalación buscando el manifiesto del plugin: PLUGIN_ROOT="$(dirname "$(grep -rl '\"name\": *\"sdd-devkit\"' "$HOME/.claude/plugins" --include=plugin.json 2>/dev/null | head -1)")". En ambos casos, verificar antes de usarla que $PLUGIN_ROOT/references/language.md existe. El destino de cada enlace markdown (../../references/…) existe solo para navegar el repositorio en GitHub o en un editor: no resolverlo desde el directorio de trabajo. Nunca buscar references/ en el proyecto: un <proyecto>/references/language.md que no existe no es un archivo que falte, es una ruta mal resuelta — corregir la raíz y volver a leer, sin preguntar al usuario ni saltarse la lectura.

Resolución de idioma

Antes de ejecutar este skill, DEBES leer ${PLUGIN_ROOT}/references/language.md.

Las reglas de language.md son obligatorias y tienen prioridad para determinar el idioma de todos los artefactos, documentos y mensajes generados por este skill.

No continúes hasta haber leído y aplicado language.md.

Enlaces a archivos del proyecto: DEBES leer y aplicar ${PLUGIN_ROOT}/references/linking.md — todo archivo o carpeta existente del proyecto que este skill mencione en un artefacto, documento o mensaje (identificadores como US-XXX o WF-XXX, rutas, índices) se escribe como enlace Markdown que lo abre.


Resolución de las puertas de cierre

Antes de ejecutar este skill, DEBES leer ${PLUGIN_ROOT}/references/verification.md.

Las reglas de verification.md son obligatorias y determinan, vía verification.qualityCheck.enabled / verification.codeReview.enabled / verification.requirementCoverage.enabled, si corre cada puerta antes del merge (true la ejecuta, false la omite).

No continúes hasta haber leído y aplicado verification.md.

Excepción deliberada: esto decide si la puerta corre, nunca si aprueba. Una puerta que se ejecuta manda con su veredicto igual que siempre; una omitida no bloquea, pero tampoco cuenta como aprobada y se reporta como tal, con su motivo.


Límite de intentos y escalamiento

Antes de ejecutar este skill, DEBES leer ${PLUGIN_ROOT}/references/escalation.md.

Las reglas de escalation.md son obligatorias y determinan, vía escalation.maxAttempts y escalation.onLimit, cuántos intentos consecutivos se hacen sobre el mismo problema que no se resuelve —una puerta de cierre que sigue en rojo tras corregir, o una validación previa que no se logra dejar en verde— y qué se hace al agotarlos: detener el trabajo sobre ese problema, presentar el parte de bloqueo y preguntar al usuario cómo seguir (ask), o marcarlo como BLOCKED en el informe y continuar con el alcance que no dependa de él (report).

El contador es por problema, no global, y el límite es un techo, no una cuota: si no hay una hipótesis nueva que justifique el siguiente intento, se escala ya. Nunca se «resuelve» un bloqueo desactivando o saltando una prueba, relajando una aserción ni bajando un umbral.

No continúes hasta haber leído y aplicado escalation.md.


Tipos de trabajo

El tipo se determina por el identificador presente en el nombre de rama. Cada tipo fija de dónde se deriva la carpeta, dónde vive el progress.md y qué se considera una unidad a cerrar.

Tipo Identificador en la rama progress.md Unidad a verificar en Done
Historia de usuario US-XXX <changesPath>/user-stories/US-XXX-[nombre-corto]/progress.md (por carpeta de la US) todas las TK-XXX de la US
Tarea de mantenimiento WI-XXX <changesPath>/work-items/WI-XXX-[kebab-case]/progress.md (por carpeta del WI) todas las unidades del WI-XXX en su propio progress.md
Automatización de pruebas rama con prefijo test/ + FT-XXX, US-XXX o WI-XXX En la carpeta del artefacto padre: <currentPath>/FT-XXX-[slug]/progress.md, o la de la US/WI correspondiente. Repositorio solo de pruebas (implementation.scope: tests en .sdd-devkit/settings.json): no hay progress.md; se lee test-cases-automation.md del padre — ver la nota de abajo todas las unidades de esa ejecución (el FT-XXX completo, o cada TC-XXX del alcance)

Una rama = un trabajo. El skill cierra el trabajo asociado a la rama actual. Cada tipo tiene su progress.md dentro de la carpeta del trabajo (la US, el WI o el feature) y contiene únicamente ese trabajo; se verifican todas sus unidades.

Ramas test/: el entregable son pruebas automatizadas de los TC-XXX documentados por test-define (ver work-implement, references/test-cases.md). El progress.md de la US o el WI puede contener unidades de otras ramas (TK-XXX, el propio WI-XXX): en ese caso se verifican en Done solo las unidades TC-XXX/FT-XXX de esta ejecución, no las del trabajo funcional.

Ramas test/ en un repositorio solo de pruebas (.sdd-devkit/settings.json con implementation.scope: tests): ese repositorio no tiene progress.md y no se le exige. El archivo a leer es test-cases-automation.md en la carpeta del padre, y el estado de cada unidad es el valor de su línea **Estado:** (o **Status:**) bajo el encabezado ### <ID>: … — Pending, In Progress o Done, siempre en inglés — porque ese archivo no lleva marcas ocultas <!-- unit:… -->. Comparar case-insensitive y sin espacios extra; cualquier valor distinto de Done bloquea el merge. Todo lo demás del flujo (puertas, rama base, merge, cierre) es idéntico; en el paso 11 el Done del trabajo se marca en la línea **Estado:** del encabezado de test-cases-automation.md. Con scope: code o sin la clave, esta nota no aplica.


Ubicación de archivos

Layout completo del harness e identificadores: ${PLUGIN_ROOT}/references/artifacts.md. Este skill es el que ejecuta el archivado; su contrato para el resto del catálogo está en ${PLUGIN_ROOT}/references/archive.md.

Lo que este skill lee y mueve:

Artefacto Ruta
Carpeta / documento del trabajo US: <changesPath>/user-stories/US-XXX-[nombre-corto]/ · WI: <changesPath>/work-items/WI-XXX-[kebab-case]/ · FT: <currentPath>/FT-XXX-[slug]/
Progreso del trabajo progress.md dentro de esa carpeta
Unidades referenciadas US: …/TK-XXX-[kebab-case].md · WI: el propio …/README.md · pruebas: …/test-cases/TC-XXX-[slug].md

Convenciones de rama

  • Historia de usuario: feature/US-XXX-[nombre-corto] con prefijo feature/ obligatorio.
  • Work item: feature/WI-XXX-[kebab-case] por defecto; se aceptan además los prefijos por tipo que usa work-implement: fix/WI-XXX-..., chore/WI-XXX-..., refactor/WI-XXX-....
  • Automatización de pruebas: prefijo test/ + el identificador del artefacto padre: test/FT-XXX-[slug], test/US-XXX-[nombre-corto], test/WI-XXX-[kebab-case].
  • XXX: tres dígitos con cero a la izquierda (sin ADO); coincide con el identificador del trabajo.
  • La carpeta/documento del trabajo se deriva descontando el prefijo de rama y leyendo el identificador: feature/US-042-exportacion-csv → <changesPath>/user-stories/US-042-exportacion-csv/; fix/WI-007-cache-ttl → <changesPath>/work-items/WI-007-cache-ttl/; test/FT-003-carga-masiva → <currentPath>/FT-003-carga-masiva/ (cada uno con su propio progress.md).
  • Una rama sin un prefijo válido para su tipo o sin un identificador US-XXX / WI-XXX / FT-XXX reconocible no es submiteable por este skill.
  • spike/WI-XXX-... nunca es submiteable. Es la rama de un WI de tipo spike: código experimental que por definición no se integra; su entregable es el spike-report.md y el desarrollo definitivo se formaliza en una US o en otro WI (ver work-implement/references/work-items.md → Variante spike). Parar con razón concreta —Rama spike/WI-014-…: los spikes no se integran; formaliza el resultado con /work-define o /work-plan— sin ejecutar puertas ni merge, aunque el usuario insista: si quiere integrar ese código, debe convertirlo primero en un WI implementable con AC-XXX.
  • Ejemplos: feature/US-042-exportacion-csv, fix/WI-013-fuga-memoria, test/FT-003-carga-masiva.

Información requerida antes de mergear

Antes de tocar git, el agente debe tener clara la siguiente información. No asumir nada — si algún dato no se resuelve, preguntar al usuario.

Dato Cómo obtenerlo Si no está disponible
Rama actual y tipo git branch --show-current; el tipo se infiere del identificador (US-/WI-/FT-) y del prefijo (test/ ⇒ automatización de pruebas) Si no encaja con un patrón válido: preguntar a qué trabajo corresponde antes de continuar
Carpeta/documento del trabajo Derivar del nombre de rama según el tipo (ver Tipos de trabajo); si no está en la ruta activa, buscarla bajo <archivedPath>/ (el trabajo pudo archivarse en una corrida anterior) Si no existe en ninguna de las dos: parar e informar; si hay varias coincidentes: preguntar cuál
Estado de progress.md Leer el archivo en la ubicación correspondiente al tipo; si el trabajo ya está archivado, en su ruta bajo <archivedPath>/. En una rama test/ de un repositorio solo de pruebas (implementation.scope: tests), el archivo es test-cases-automation.md del padre Si no existe en ninguna de las dos: parar e informar; el merge requiere progress.md (o test-cases-automation.md, en el caso externo) poblado
Working tree git status --porcelain Si hay salida, no se comitea todavía: las puertas verifican commit + working tree (lo sin commitear incluido), así que el único commit del cierre se hace después de ellas (paso 8), en una sola invocación de git-commit que recoge el trabajo pendiente, las correcciones y los informes. Solo se anota qué hay pendiente para reportarlo
Rama base (1) git reflog show <branch> → línea Created from; (2) git config --get branch.<branch>.merge; (3) preguntar al usuario No asumir main, master ni develop por defecto

Leer el progress.md completo antes de iniciar cualquier operación git. Las tres condiciones (rama, working tree, estados) se evalúan antes de cambiar de rama o invocar git merge.


Validación antes de mergear

Antes de cambiar de rama o ejecutar el merge, verificar las siguientes condiciones. Si alguna falla, no mergear — informar al usuario y resolver primero.

¿Qué verificar?

  • Rama actual con formato válido para su tipo: feature/US-XXX-...; feature/|fix/|chore/|refactor/ + WI-XXX-...; o test/ + FT-XXX-...|US-XXX-...|WI-XXX-.... Sin un identificador reconocible no se puede derivar la carpeta/documento del trabajo. spike/ no es un prefijo válido: se rechaza siempre (ver Convención de ramas).
  • Working tree inventariado, no limpio: git status --porcelain se ejecuta para saber qué hay pendiente, pero no se invoca git-commit antes de las puertas. quality-check calcula su fingerprint sobre commit + working tree y code-review revisa git diff <base> con lo sin commitear incluido, así que verifican exactamente el árbol que luego se comitea. Commitear antes y otra vez después duplicaba la invocación más cara del cierre sin añadir garantía alguna. El commit llega en el paso 8, una sola vez.
  • Carpeta/documento del trabajo existe: la ubicación correspondiente al tipo, con su progress.md.
  • Unidades del trabajo en Done: parsear progress.md y confirmar que cada unidad del trabajo de la rama tiene estado Done. El estado se lee de la marca oculta de la unidad (<!-- unit:id=… · status=… -->), no de la etiqueta visible, que va en el idioma resuelto; comparar el valor case-insensitive y sin espacios extra. El progress.md vive en la carpeta del trabajo (la US o el WI) y contiene solo ese trabajo: para US son sus TK, para WI las unidades de su propio progress.md. Estados como Pending, In Progress o vacío bloquean el merge.
  • Rama base resoluble (antes de las puertas): identificada por reflog, por config, o confirmada explícitamente por el usuario. Si hay varios candidatos plausibles y ninguno definitivo, preguntar. Se resuelve antes de invocar las puertas porque code-review la necesita para acotar su diff.
  • Verificaciones automatizadas — solo si verification.qualityCheck.enabled la activa: ejecutar quality-check (modificador default) antes del merge — es la compuerta de cierre que corre la batería completa de pruebas sobre la rama consolidada y persiste .sdd-devkit/quality-check-run.json. Cuando corre, solo un veredicto APPROVED permite continuar: REJECTED e INCOMPLETE bloquean el merge hasta que el usuario corrija los problemas y la corrida se repita con veredicto APPROVED. Si la política la omite, el merge continúa sin esa evidencia y así se reporta.
  • Code review — solo si verification.codeReview.enabled la activa: ejecutar code-review después de quality-check, pasándole la rama base ya resuelta (base <rama>) — es la revisión cualitativa (intención, arquitectura y diseño) sobre el diff de la rama contra esa base, incluidos los cambios sin commitear que quality-check haya podido dejar al corregir. Emite su propio veredicto, independiente del anterior: solo APPROVED permite continuar; REJECTED e INCOMPLETE bloquean el merge hasta que los hallazgos se corrijan o se justifiquen y la revisión se repita con veredicto APPROVED. Si la política la omite, el merge continúa sin revisión cualitativa y así se reporta.
  • Trazabilidad — solo si verification.requirementCoverage.enabled la activa: ejecutar coverage-verify sobre el trabajo de la rama (US-XXX/WI-XXX), después de quality-check para que reutilice su quality-check-run.json sin re-ejecutar pruebas. Cuando corre, solo APPROVED (o APPROVED_WITH_NOTES, mostrando las observaciones) permite continuar; REJECTED (algún criterio de aceptación sin cubrir o con prueba fallida) bloquea el merge. Si la política la omite, el merge continúa sin evidencia de cobertura y así se reporta.

Una puerta omitida no es una puerta aprobada. Registrar cada omisión con su motivo (policy, enabled: false) y arrastrarla hasta el reporte del cierre y el mensaje al usuario. Nunca listarla como aprobada ni callarla. Si las tres quedan omitidas, decirlo de forma destacada: el merge se hace sin ninguna verificación de cierre. Cómo se lee un veredicto. Los informes de las puertas se redactan en el idioma resuelto del repo, así que ni la palabra ni el símbolo del encabezado son comparables. Lo que se lee es la marca oculta del pie del informe: <!-- <skill>:verdict=<VALOR> … -->. APPROVED deja pasar; REJECTED e INCOMPLETE bloquean; APPROVED_WITH_NOTES (solo coverage-verify) no bloquea: se muestran las observaciones y se continúa. Contrato completo en ${PLUGIN_ROOT}/references/verdicts.md.

  • Archivado: no forma parte del cierre. Este skill no archiva ni lo ofrece; si el trabajo ya está bajo <archivedPath> (Regla 1 de ${PLUGIN_ROOT}/references/archive.md), se lee desde ahí y se informa.
  • Working tree limpio tras las puertas — la única invocación de git-commit del cierre: al terminar las puertas el árbol contiene el trabajo que estaba pendiente al empezar, las correcciones aplicadas por quality-check (o por work-implement en su modo corrección) y los artefactos versionados de las puertas (docs/audits/quality-check.md, docs/audits/code-review.md y el criteria-coverage.md del trabajo, que se escriben siempre; .sdd-devkit/quality-check-run.json no aparece: está en el .gitignore por ser una caché local). Todo se comitea en una sola invocación de git-commit (que puede repartirlo en varios commits si mezcla temas, con su propuesta de división), y el merge solo procede con el árbol limpio: el código que se integra es exactamente el que verificaron las puertas, con sus artefactos. Reglas de la invocación: delega en git-commit todo su criterio operativo (agrupación, inferencia de tipo/scope/mensaje, staging, confirmación de la división) — work-integrate no decide un mensaje ni qué stagear; git-commit no tiene modo silencioso: un commit único lo ejecuta sin confirmar, pero puede pausar para confirmar una propuesta de división o detenerse ante rama protegida o hook fallido, y eso no lo decide work-integrate.
    • Si git-commit no está disponible (skill no instalado o no localizable en el entorno): parar y avisar, mostrando los archivos pendientes y sugiriendo al usuario commitear manualmente antes de reintentar — no ejecutar git add/git commit directos como sustituto (el único commit directo de este skill es el cierre mecánico del paso 11.2).
    • Si git-commit deja el working tree parcialmente limpio por una decisión de alcance suya (p. ej. commiteó unos archivos pero dejó otros fuera deliberadamente): no es un error — volver a comprobar git status --porcelain e invocar git-commit de nuevo sobre el remanente (mismo criterio, sin preguntar) hasta que quede limpio o se detenga por un motivo real.
    • Si git-commit se detiene sin dejarlo limpio (p. ej. por una decisión que el propio git-commit no puede resolver solo), eso sí bloquea el merge — informar el motivo reportado.

Si hay conflicto: ` ⚠️ No es posible mergear todavía:

  • <razón concreta>
  • [<TK-XXX | WI-XXX>: estado-actual] — `

Ejemplos de razón concreta: Rama actual no cumple un patrón válido: rama es 'hotfix-cache', Working tree sucio: 3 archivos modificados, progress.md: TK-002 en In Progress, TK-005 en Pending, progress.md: WI-007 en In Progress, Rama base ambigua: candidatos main, develop, release/2026.q2.


Flujo: Submit estándar

Camino feliz cuando todas las verificaciones pasan.

  1. Detectar rama actual con git branch --show-current, identificar el tipo por el identificador (US-/WI-) y validar el patrón de rama de ese tipo. Si no encaja, parar y preguntar.

  2. Inventariar el working tree con git status --porcelain y anotar lo pendiente. No commitear aquí: las puertas verifican commit + working tree, y el único commit del cierre se hace tras ellas (paso 8). Si no hay salida, simplemente no habrá trabajo pendiente que recoger.

  3. Localizar la carpeta/documento del trabajo según el tipo (ver Tipos de trabajo). Si no está en la ruta activa, buscarla bajo <archivedPath>/ antes de rendirse: si aparece ahí, el trabajo ya estaba archivado — continuar el flujo leyendo su progress.md desde esa ruta y saltar luego el archivado del paso 11 (el Done del trabajo sí se marca, sobre la carpeta archivada). Si no está en ninguna de las dos, o hay varias coincidentes, parar.

  4. Leer progress.md (en la carpeta del trabajo) y validar que todas las unidades del trabajo de la rama tienen estado Done. Si alguna no lo está, parar mostrando la lista completa de unidades no Done con su estado actual.

  5. Resolver la rama base — antes de las puertas, porque code-review la necesita para acotar su diff. Resolverla primero contra integrationBranches de ${PLUGIN_ROOT}/references/git.md: si la lista está declarada, la base es una de esas ramas y no se adivina. Comprobar su commitPolicy antes de seguir:

    • merge → continuar con el flujo normal.
    • pull_request → parar aquí. Esa rama no admite merge local: informarlo y ofrecer dos salidas — crear el PR con pr-create, o terminar. No mergear «avisando».
    • No declarada → resolverla desde el historial de la rama:
      • git reflog show <branch> → buscar la entrada inicial con Created from <ref> o branch: Created from <ref>.
      • Fallback: git config --get branch.<branch>.merge y derivar la rama base local correspondiente.
      • Si ninguno concluye o hay ambigüedad: preguntar al usuario sin proponer un default.
  6. Resolver y ejecutar las puertas. Antes de la primera, aplicar ${PLUGIN_ROOT}/references/verification.md: las puertas con enabled: false no se ejecutan ni se ofrecen. Anotar cada omisión con su motivo para el paso 12. Luego, en este orden y solo las activas:

    6.1 quality-check (modificador default) sobre la rama actual. Si el veredicto es REJECTED o INCOMPLETE, parar y reportar el informe al usuario — no continuar con el merge hasta obtener veredicto APPROVED en una nueva ejecución.

    6.2 code-review con base <rama-base> (la del paso 5). Su alcance incluye los cambios sin commitear, así que también revisa las correcciones que quality-check haya podido aplicar. Si su informe existente ya estaba fresco y aprobado (mismo fingerprint, misma base y mismo modo, sin correcciones en el 6.1), lo devuelve sin volver a revisar; no forzar revalidate desde aquí. Un ❌/⚠️ previo lo revisa de nuevo por su cuenta. Si el veredicto es REJECTED o INCOMPLETE, parar y reportar los hallazgos — no continuar hasta obtener APPROVED con los hallazgos bloqueantes corregidos o justificados.

    6.3 coverage-verify sobre el trabajo de la rama (después de quality-check, para reutilizar su quality-check-run.json; si quality-check quedó omitida, coverage-verify invocará él mismo el modo tests-only al no encontrar corrida fresca). Si el veredicto es REJECTED, parar y reportar los criterios faltantes/fallidos — no mergear hasta obtener APPROVED (o APPROVED_WITH_NOTES, mostrando las observaciones al usuario).

    Con todas las puertas activas en veredicto que deja pasar, resolver verification.handoff: con ask (comportamiento por defecto), preguntar al usuario si se continúa con el merge y el cierre (pasos 7 en adelante); con always, continuar directo sin preguntar.

  7. Calcular delta con git rev-list --count <base>..HEAD. Es una puerta, no solo un dato para el reporte: si el resultado es 0 y el working tree está limpio (paso 2 sin salida y puertas sin correcciones), la rama ya está integrada (típicamente porque el PR se mergeó en la plataforma) — parar y avisar, sin tocar nada. Seguir adelante produciría un commit que no es un merge y que solo borra archivos, con un mensaje que miente. Va antes del commit del paso 8 a propósito: seguir adelante dejaría un commit nuevo en una rama que solo había que dejar en paz. Con delta 0 pero árbol sucio sí hay trabajo nuevo: continuar, que el paso 8 lo comitee, y recalcular el delta antes del merge.

  8. Commitear todo el trabajo pendiente — única invocación de git-commit del cierre. El árbol contiene ahora tres clases de cambios: el trabajo que estaba pendiente al empezar (paso 2), las correcciones de las puertas (aplicadas por quality-check o por work-implement en su modo corrección) y sus propios artefactos —docs/audits/quality-check.md, docs/audits/code-review.md y el criteria-coverage.md del trabajo, que se escriben siempre—. Todo se commitea: la rama debe conservar su evidencia (el paso 10 es quien decide qué no pasa a la base). Ejecutar git status --porcelain y, si hay salida, invocar git-commit con el criterio de Validación antes de mergear (agrupa en varios commits si mezcla temas; reinvocar solo sobre un remanente dejado por decisión de alcance). El merge solo procede con el árbol limpio: el código que se integra es exactamente el que verificaron las puertas. Aquí no se archiva ni se marca nada como Done: eso va después del merge (paso 11), porque hasta que el código no está integrado y el usuario puede probarlo en la rama base, el trabajo no está cerrado.

  9. Cambiar a la rama base con git checkout <base>. Si falla, parar y reportar.

  10. Ejecutar el merge en tres tiempos, para que los informes de las puertas no lleguen a la rama base (ver Los informes de las puertas no se integran):

    git merge --no-ff --no-commit <feature-branch>
    test -f "$(git rev-parse --git-dir)/MERGE_HEAD" || { echo "no hay merge en curso"; exit 1; }
    git rm -q -f --ignore-unmatch ':(top,glob)**/docs/audits/quality-check.md' ':(top,glob)**/docs/audits/code-review.md'
    test -z "$(git ls-files --cached -- ':(top,glob)**/docs/audits/quality-check.md' ':(top,glob)**/docs/audits/code-review.md')" \
      || { echo "los informes siguen en el índice"; exit 1; }
    git commit -m "Merge <ID>: <nombre-corto>"
    

    <ID> es el identificador del trabajo (US-XXX o WI-XXX) y <nombre-corto> su nombre/slug sin el prefijo de rama.

    Las dos comprobaciones no son adorno:

    • MERGE_HEAD confirma que el merge quedó realmente en curso. Si git respondió Already up to date, no hay merge, y ejecutar el git rm + git commit de todos modos crearía un commit normal que borra dos archivos de la base. Parar ahí.
    • :(top,glob)**/… en las rutas hace dos cosas, y las dos hacen falta. :(top) las ancla a la raíz del repositorio: git rm interpreta las rutas relativas al cwd, así que sin ese ancla, lanzado desde packages/api/, no casarían, --ignore-unmatch devolvería 0 sin borrar nada, y los informes se integrarían en la base en silencio mientras el paso 12 reporta lo contrario. Y el glob con **/ inicial las hace casar a cualquier profundidad, que es lo que exige el monorepo por el otro lado: quality-check audita el módulo elegido, no el repo entero, y escribe su informe en el docs/audits/ de ese módulo (packages/api/docs/audits/quality-check.md). Con :(top)docs/audits/… a secas —anclado pero literal— solo casaría el docs/ de la raíz, y el informe del módulo se colaría en la base con el mismo silencio. Es la misma razón por la que el FINGERPRINT de quality-check excluye **/docs/** y no docs/. **/ casa también cero directorios, así que el caso de repo simple sigue cubierto. El git ls-files --cached posterior es el cinturón: verifica el resultado en vez de confiar en el código de salida. Tiene que ser ls-files, no git diff --cached: el diff lista también los borrados stageados, así que cuando la base ya trackeaba el informe —y el git rm funcionó— la ruta aparecería igual y el guard cortaría un merge correcto. ls-files --cached responde la pregunta que importa: ¿queda algo de esos dos archivos en el índice?

    --ignore-unmatch está para el caso legítimo de que un informe no se haya commiteado en la rama, no para tapar rutas mal resueltas. Borrar exactamente esos dos archivos, ni uno más: las copias de save-report y los arch-audit-*.md se quedan. Si surge conflicto, ir al flujo de conflictos.

  11. Cerrar el trabajo en la rama base — después del merge, nunca antes. Con el merge hecho, el código ya está integrado y el usuario puede probarlo donde de verdad importa; solo entonces el trabajo pasa a estar cerrado, y el cierre se hace sobre la rama base, en un único commit propio, separado del merge:

    11.1 Marcar el trabajo como Done. Si el trabajo es un WI de tipo bug-fix cuya cabecera cita Origen: WI-XXX (bug), actualizar además en ese WI de tipo bug la línea Resolución: a Fixed (WI-YYY) — misma búsqueda en ruta activa y archivo; si el bug vive en otro repositorio (registrado desde un repo de pruebas), solo mencionarlo en el reporte. En el progress.md del trabajo, poner el estado del trabajo (el encabezado **Estado:** y su marca <!-- work:id=… · status=Done -->) en Done y actualizar Ultima actualizacion. Es el estado del trabajo, no de sus unidades: las unidades ya estaban Done desde la implementación (paso 4 lo exige); el trabajo entero solo lo está cuando su código vive en la rama base. Solo aplica a US-XXX y WI-XXX en su rama funcional; una rama test/ no cierra el trabajo (su paso 4 solo verificó las unidades TC-XXX de esa ejecución).

    11.2 Commitear el cierre en la rama base — commit directo. Es un commit mecánico (ver Commit directo en ${PLUGIN_ROOT}/references/git.md): mensaje fijo y alcance conocido, así que no se invoca git-commit. git add -A -- <ruta del progress.md> (más la ruta del README.md del WI de tipo bug si se actualizó su Resolución: en 11.1), comprobar con git diff --cached --name-only que el índice contiene solo esas rutas, y git commit -m "chore(<ID>): cerrar trabajo". La rama base es commitPolicy: merge (paso 5), así que no hay confirmación extra de rama protegida; si la base fuera pull_request, el flujo ni siquiera habría llegado aquí. Si el hook falla, parar e informar con su mensaje. Nunca meter este cierre dentro del commit de merge del paso 10: el merge integra exactamente el código verificado, y el cierre es un cambio de estado del artefacto.

    Por qué después del merge. Marcar Done en la rama del trabajo, antes de integrar, obligaba a decidir el cierre a ciegas: si el merge fallaba, el trabajo quedaba «cerrado» sin estarlo. Con el cierre en la base y después del merge, el orden refleja la realidad: se integra, se prueba, se cierra. El archivado queda fuera de este skill: lo pide el usuario, tras su revisión, al skill que produjo el artefacto (/work-define US-XXX archive, /work-plan WI-XXX archive).

  12. Reportar resultado al usuario: rama origen (con su prefijo), rama destino, número de commits integrados, hash del commit de merge, hash del commit de cierre (paso 11) con el progress.md en Done, estado del HEAD, el estado de cada una de las tres puertas —veredicto si corrió, u «omitida» con su motivo si no— y nota explícita de que no se hizo push ni se borró la rama del trabajo. Recordar en una línea que el artefacto sigue en su ruta activa y que, tras la revisión, puede archivarse con el skill que lo produjo (/work-define US-XXX archive o /work-plan WI-XXX archive). Mencionar también que los informes de las puertas quedaron en la rama del trabajo y no se integraron.


Los informes de las puertas no se integran

docs/audits/quality-check.md y docs/audits/code-review.md son fotos de una rama concreta: su encabezado lleva la rama y el commit sobre los que se corrieron las puertas. Se versionan en la rama del trabajo —ahí valen: quedan junto a los commits que verifican, y el revisor los ve en el PR— pero no deben llegar a la rama base, por dos razones:

  • En develop serían mentira. Nadie corrió las puertas sobre develop; ese archivo diría «APPROVED» sobre una rama que ni siquiera es la suya. Y con cada integración lo pisaría la última feature en entrar.
  • Viven en una ruta fija, así que toda rama escribe el mismo archivo: dejarlos integrarse convierte cada merge en un conflicto seguro sobre un artefacto generado.

Por eso el paso 10 parte el merge: --no-commit deja el resultado en el índice, se retiran los dos informes y el commit de merge se cierra ya sin ellos. La rama del trabajo conserva los suyos intactos — no se reescribe su historia, solo se decide qué entra en la base.

Qué NO se toca:

Artefacto Por qué se queda
docs/audits/arch-audit-*.md Auditorías de arquitectura del repositorio, no de una rama. Su sitio es la rama base.
docs/audits/quality-check-<timestamp>.md · code-review-<timestamp>.md Copias de save-report: el usuario las pidió para conservar histórico. Llevan marca de tiempo, así que no colisionan ni pisan nada.
criteria-coverage.md del trabajo Vive junto a su artefacto en docs/specs/, es del trabajo y no de la rama, y se integra con él.
El progress.md en Done No viaja en el merge: se hace en la rama base, después del merge (paso 11), en un commit de cierre propio.
.sdd-devkit/quality-check-run.json Ni aparece: está en el .gitignore.

Esta limpieza solo cubre los merges que hace este skill. Un merge desde la UI de GitHub/GitLab —el camino de pr-create— sí propaga los informes: ahí la limpieza hay que hacerla en la rama base después de integrar. Ver pr-create.


Conflictos y rama base ambigua: si el git merge produce conflictos, seguir el Flujo de manejo de conflictos, que clasifica antes de abortar: un modify/delete sobre los dos informes de docs/audits/ se resuelve por el lado del borrado y el merge continúa; cualquier otro conflicto se aborta con git merge --abort, se reporta y se para. Si la rama base no se resuelve por reflog ni config, seguir el Flujo de rama base ambigua (listar candidatos, preguntar, no asumir default). Ambos flujos íntegros y el checklist detallado están en references/flows.md.


Mapa de referencias

Cargar bajo demanda; el contenido íntegro vive en estos archivos:

Necesitas… Archivo
Flujo de manejo de conflictos, flujo de rama base ambigua, checklist detallado antes de mergear references/flows.md
Contrato de lectura de artefactos archivados (fallback y numeración) — este skill no archiva ${PLUGIN_ROOT}/references/archive.md
Ejemplos por tipo (US/WI: camino feliz, unidad pendiente, base ambigua, working tree sucio, conflicto, prefijo inválido), anti-patrones, y notas (handoffs del ciclo, progress.md, estados, detección de rama base, sin push intencional, mensaje al usuario) references/examples.md

Referencias compartidas del plugin

Reglas transversales del catálogo; viven en la raíz del plugin, no en este skill.