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 deprogress.md, y no resuelve conflictos —con la única salida declarada delmodify/deletesobre los dos informes dedocs/audits/, que se resuelve por el lado del borrado (ver references/flows.md). Lo que no esté enDonebloquea 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.mddentro 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 losTC-XXXdocumentados portest-define(verwork-implement,references/test-cases.md). Elprogress.mdde la US o el WI puede contener unidades de otras ramas (TK-XXX, el propioWI-XXX): en ese caso se verifican enDonesolo las unidadesTC-XXX/FT-XXXde esta ejecución, no las del trabajo funcional.Ramas
test/en un repositorio solo de pruebas (.sdd-devkit/settings.jsonconimplementation.scope: tests): ese repositorio no tieneprogress.mdy no se le exige. El archivo a leer estest-cases-automation.mden 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 ProgressoDone, siempre en inglés — porque ese archivo no lleva marcas ocultas<!-- unit:… -->. Comparar case-insensitive y sin espacios extra; cualquier valor distinto deDonebloquea el merge. Todo lo demás del flujo (puertas, rama base, merge, cierre) es idéntico; en el paso 11 elDonedel trabajo se marca en la línea**Estado:**del encabezado detest-cases-automation.md. Conscope: codeo 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 prefijofeature/obligatorio. - Work item:
feature/WI-XXX-[kebab-case]por defecto; se aceptan además los prefijos por tipo que usawork-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 propioprogress.md). - Una rama sin un prefijo válido para su tipo o sin un identificador
US-XXX/WI-XXX/FT-XXXreconocible no es submiteable por este skill. spike/WI-XXX-...nunca es submiteable. Es la rama de unWIde tipospike: código experimental que por definición no se integra; su entregable es elspike-report.mdy el desarrollo definitivo se formaliza en una US o en otro WI (verwork-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 conAC-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.mdcompleto antes de iniciar cualquier operación git. Las tres condiciones (rama, working tree, estados) se evalúan antes de cambiar de rama o invocargit 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-...; otest/+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 --porcelainse ejecuta para saber qué hay pendiente, pero no se invocagit-commitantes de las puertas.quality-checkcalcula su fingerprint sobre commit + working tree ycode-reviewrevisagit 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: parsearprogress.mdy confirmar que cada unidad del trabajo de la rama tiene estadoDone. 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. Elprogress.mdvive en la carpeta del trabajo (la US o el WI) y contiene solo ese trabajo: para US son susTK, para WI las unidades de su propioprogress.md. Estados comoPending,In Progresso 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-reviewla necesita para acotar su diff. - Verificaciones automatizadas — solo si
verification.qualityCheck.enabledla activa: ejecutarquality-check(modificadordefault) 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 veredictoAPPROVEDpermite continuar:REJECTEDeINCOMPLETEbloquean el merge hasta que el usuario corrija los problemas y la corrida se repita con veredictoAPPROVED. Si la política la omite, el merge continúa sin esa evidencia y así se reporta. - Code review — solo si
verification.codeReview.enabledla activa: ejecutarcode-reviewdespués dequality-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 quequality-checkhaya podido dejar al corregir. Emite su propio veredicto, independiente del anterior: soloAPPROVEDpermite continuar;REJECTEDeINCOMPLETEbloquean el merge hasta que los hallazgos se corrijan o se justifiquen y la revisión se repita con veredictoAPPROVED. Si la política la omite, el merge continúa sin revisión cualitativa y así se reporta. - Trazabilidad — solo si
verification.requirementCoverage.enabledla activa: ejecutarcoverage-verifysobre el trabajo de la rama (US-XXX/WI-XXX), después dequality-checkpara que reutilice suquality-check-run.jsonsin re-ejecutar pruebas. Cuando corre, soloAPPROVED(oAPPROVED_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> … -->.APPROVEDdeja pasar;REJECTEDeINCOMPLETEbloquean;APPROVED_WITH_NOTES(solocoverage-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-commitdel cierre: al terminar las puertas el árbol contiene el trabajo que estaba pendiente al empezar, las correcciones aplicadas porquality-check(o porwork-implementen su modo corrección) y los artefactos versionados de las puertas (docs/audits/quality-check.md,docs/audits/code-review.mdy elcriteria-coverage.mddel trabajo, que se escriben siempre;.sdd-devkit/quality-check-run.jsonno aparece: está en el.gitignorepor ser una caché local). Todo se comitea en una sola invocación degit-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 engit-committodo su criterio operativo (agrupación, inferencia de tipo/scope/mensaje, staging, confirmación de la división) —work-integrateno decide un mensaje ni qué stagear;git-commitno 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 decidework-integrate.- Si
git-commitno 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 ejecutargit add/git commitdirectos como sustituto (el único commit directo de este skill es el cierre mecánico del paso 11.2). - Si
git-commitdeja 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 comprobargit status --porcelaine invocargit-commitde nuevo sobre el remanente (mismo criterio, sin preguntar) hasta que quede limpio o se detenga por un motivo real. - Si
git-commitse detiene sin dejarlo limpio (p. ej. por una decisión que el propiogit-commitno puede resolver solo), eso sí bloquea el merge — informar el motivo reportado.
- Si
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.
-
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. -
Inventariar el working tree con
git status --porcelainy 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. -
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 suprogress.mddesde esa ruta y saltar luego el archivado del paso 11 (elDonedel trabajo sí se marca, sobre la carpeta archivada). Si no está en ninguna de las dos, o hay varias coincidentes, parar. -
Leer
progress.md(en la carpeta del trabajo) y validar que todas las unidades del trabajo de la rama tienen estadoDone. Si alguna no lo está, parar mostrando la lista completa de unidades noDonecon su estado actual. -
Resolver la rama base — antes de las puertas, porque
code-reviewla necesita para acotar su diff. Resolverla primero contraintegrationBranchesde${PLUGIN_ROOT}/references/git.md: si la lista está declarada, la base es una de esas ramas y no se adivina. Comprobar sucommitPolicyantes 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 conpr-create, o terminar. No mergear «avisando».- No declarada → resolverla desde el historial de la rama:
git reflog show <branch>→ buscar la entrada inicial conCreated from <ref>obranch: Created from <ref>.- Fallback:
git config --get branch.<branch>.mergey derivar la rama base local correspondiente. - Si ninguno concluye o hay ambigüedad: preguntar al usuario sin proponer un default.
-
Resolver y ejecutar las puertas. Antes de la primera, aplicar
${PLUGIN_ROOT}/references/verification.md: las puertas conenabled: falseno 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(modificadordefault) sobre la rama actual. Si el veredicto esREJECTEDoINCOMPLETE, parar y reportar el informe al usuario — no continuar con el merge hasta obtener veredictoAPPROVEDen una nueva ejecución.6.2
code-reviewconbase <rama-base>(la del paso 5). Su alcance incluye los cambios sin commitear, así que también revisa las correcciones quequality-checkhaya 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 forzarrevalidatedesde aquí. Un❌/⚠️previo lo revisa de nuevo por su cuenta. Si el veredicto esREJECTEDoINCOMPLETE, parar y reportar los hallazgos — no continuar hasta obtenerAPPROVEDcon los hallazgos bloqueantes corregidos o justificados.6.3
coverage-verifysobre el trabajo de la rama (después dequality-check, para reutilizar suquality-check-run.json; siquality-checkquedó omitida,coverage-verifyinvocará él mismo el modotests-onlyal no encontrar corrida fresca). Si el veredicto esREJECTED, parar y reportar los criterios faltantes/fallidos — no mergear hasta obtenerAPPROVED(oAPPROVED_WITH_NOTES, mostrando las observaciones al usuario).Con todas las puertas activas en veredicto que deja pasar, resolver
verification.handoff: conask(comportamiento por defecto), preguntar al usuario si se continúa con el merge y el cierre (pasos 7 en adelante); conalways, continuar directo sin preguntar. -
Calcular delta con
git rev-list --count <base>..HEAD. Es una puerta, no solo un dato para el reporte: si el resultado es0y 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 delta0pero árbol sucio sí hay trabajo nuevo: continuar, que el paso 8 lo comitee, y recalcular el delta antes del merge. -
Commitear todo el trabajo pendiente — única invocación de
git-commitdel cierre. El árbol contiene ahora tres clases de cambios: el trabajo que estaba pendiente al empezar (paso 2), las correcciones de las puertas (aplicadas porquality-checko porwork-implementen su modo corrección) y sus propios artefactos —docs/audits/quality-check.md,docs/audits/code-review.mdy elcriteria-coverage.mddel 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). Ejecutargit status --porcelainy, si hay salida, invocargit-commitcon 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 comoDone: 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. -
Cambiar a la rama base con
git checkout <base>. Si falla, parar y reportar. -
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-XXXoWI-XXX) y<nombre-corto>su nombre/slug sin el prefijo de rama.Las dos comprobaciones no son adorno:
MERGE_HEADconfirma que el merge quedó realmente en curso. Si git respondió Already up to date, no hay merge, y ejecutar elgit rm+git commitde 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 rminterpreta las rutas relativas al cwd, así que sin ese ancla, lanzado desdepackages/api/, no casarían,--ignore-unmatchdevolvería0sin borrar nada, y los informes se integrarían en la base en silencio mientras el paso 12 reporta lo contrario. Y elglobcon**/inicial las hace casar a cualquier profundidad, que es lo que exige el monorepo por el otro lado:quality-checkaudita el módulo elegido, no el repo entero, y escribe su informe en eldocs/audits/de ese módulo (packages/api/docs/audits/quality-check.md). Con:(top)docs/audits/…a secas —anclado pero literal— solo casaría eldocs/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 elFINGERPRINTdequality-checkexcluye**/docs/**y nodocs/.**/casa también cero directorios, así que el caso de repo simple sigue cubierto. Elgit ls-files --cachedposterior es el cinturón: verifica el resultado en vez de confiar en el código de salida. Tiene que serls-files, nogit diff --cached: el diff lista también los borrados stageados, así que cuando la base ya trackeaba el informe —y elgit rmfuncionó— la ruta aparecería igual y el guard cortaría un merge correcto.ls-files --cachedresponde la pregunta que importa: ¿queda algo de esos dos archivos en el índice?
--ignore-unmatchestá 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 desave-reporty losarch-audit-*.mdse quedan. Si surge conflicto, ir al flujo de conflictos. -
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 unWIde tipobug-fixcuya cabecera citaOrigen: WI-XXX (bug), actualizar además en eseWIde tipobugla líneaResolución:aFixed (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 elprogress.mddel trabajo, poner el estado del trabajo (el encabezado**Estado:**y su marca<!-- work:id=… · status=Done -->) enDoney actualizarUltima actualizacion. Es el estado del trabajo, no de sus unidades: las unidades ya estabanDonedesde la implementación (paso 4 lo exige); el trabajo entero solo lo está cuando su código vive en la rama base. Solo aplica aUS-XXXyWI-XXXen su rama funcional; una ramatest/no cierra el trabajo (su paso 4 solo verificó las unidadesTC-XXXde 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 invocagit-commit.git add -A -- <ruta del progress.md>(más la ruta delREADME.mddelWIde tipobugsi se actualizó suResolución:en 11.1), comprobar congit diff --cached --name-onlyque el índice contiene solo esas rutas, ygit commit -m "chore(<ID>): cerrar trabajo". La rama base escommitPolicy: merge(paso 5), así que no hay confirmación extra de rama protegida; si la base fuerapull_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
Doneen 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). -
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.mdenDone, 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 archiveo/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
developserían mentira. Nadie corrió las puertas sobredevelop; 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. Verpr-create.
Conflictos y rama base ambigua: si el
git mergeproduce conflictos, seguir el Flujo de manejo de conflictos, que clasifica antes de abortar: unmodify/deletesobre los dos informes dedocs/audits/se resuelve por el lado del borrado y el merge continúa; cualquier otro conflicto se aborta congit 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.
${PLUGIN_ROOT}/references/language.md: Idioma — resolución obligatoria del idioma de artefactos, documentos y mensajes. Lectura obligatoria antes de ejecutar el skill.${PLUGIN_ROOT}/references/linking.md: Enlaces — toda referencia a un archivo del proyecto se escribe como enlace que lo abre. Lectura obligatoria antes de ejecutar el skill.${PLUGIN_ROOT}/references/asking.md: Preguntas — mecanismo estructurado, ritmo, fallback. Antes de la primera pregunta.${PLUGIN_ROOT}/references/artifacts.md: Artefactos — rutas del harness, identificadores, archivado. Al resolver una ruta o calcular un ID.${PLUGIN_ROOT}/references/verification.md: Política de verificación — qué puertas corren antes del merge (enabled) y si el cierre continúa con archivado y merge sin preguntar (handoff). Lectura obligatoria antes de ejecutar el skill.${PLUGIN_ROOT}/references/archive.md: Archivado — este skill no archiva; aplica solo el contrato de lectura (fallback a<archivedPath>, IDs ocupados). Al localizar la carpeta del trabajo.${PLUGIN_ROOT}/references/git.md: Política de commit y push — de aquí saleintegrationBranchesy sucommitPolicy. Al resolver la rama base.${PLUGIN_ROOT}/references/escalation.md: Límite de intentos — cuántos intentos consecutivos se hacen sobre un mismo problema que no se resuelve antes de escalar al usuario, y qué hacer al agotarlos. Lectura obligatoria antes de ejecutar el skill.