--- name: work-integrate description: Cerrar e integrar el trabajo de una historia de usuario (US-XXX), una tarea de mantenimiento (WI-XXX) o una automatización de pruebas (rama test/ sobre un US-XXX, WI-XXX o FT-XXX) haciendo merge de la rama hacia la rama desde la que se creó, previa verificación de que progress.md tenga todas las unidades del trabajo en Done y de que pasen las puertas de calidad de cierre (quality-check, code-review y coverage-verify). No archiva el artefacto — eso lo pide el usuario después de su revisión al skill que lo produjo (work-define / work-plan con el modificador archive). En ramas test/ no archiva. Activar cuando el usuario pida cerrar, entregar, mergear, integrar, finalizar o hacer submit del trabajo de una historia, un WI, un feature o de la rama actual. license: MIT --- # 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`](../../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](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](references/examples.md). --- ## Cómo preguntar al usuario Mecanismo, ritmo y fallback compartidos: [`${PLUGIN_ROOT}/references/asking.md`](../../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/.md`. Para resolverla: la raíz es la **carpeta desde la que se cargó este archivo**, dos niveles arriba (`/skills//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 `/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`](../../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`](../../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`](../../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`](../../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` | `/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` | `/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: `/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; en `scope: tests`, el artefacto padre es la única unidad) | > **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 `### : …` — `Pending`, `In Progress` o `Done`, siempre en inglés — porque ese archivo **no lleva marcas ocultas** ``. 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, con un matiz en las puertas: `quality-check` audita solo el código propio del repo y **no ejecuta** los specs contra el sistema externo, y `coverage-verify` toma su ejecución de `test-cases-automation.md`; un spec fiel al TC en rojo es un hallazgo registrado y **no bloquea el merge**; 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`](../../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`](../../references/archive.md). Lo que este skill lee y mueve: | Artefacto | Ruta | |-----------|------| | Carpeta / documento del trabajo | US: `/user-stories/US-XXX-[nombre-corto]/` · WI: `/work-items/WI-XXX-[kebab-case]/` · FT: `/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` → `/user-stories/US-042-exportacion-csv/`; `fix/WI-007-cache-ttl` → `/work-items/WI-007-cache-ttl/`; `test/FT-003-carga-masiva` → `/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](#tipos-de-trabajo)); si no está en la ruta activa, buscarla bajo `/` (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 `/`. 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 ` → línea `Created from`; (2) `git config --get 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](#convenciones-de-rama)). - **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 ` 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 (``), 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 `) — 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. **En un repositorio solo de pruebas (`implementation.scope: tests`) `coverage-verify` no es puerta y no se invoca**, aunque `requirementCoverage.enabled` esté activo: trazaría la cobertura del **sistema bajo prueba**, no la calidad de este repositorio. Se reporta `N/A` con motivo «repositorio solo de pruebas»; las puertas son `quality-check` y `code-review`. Contrato en [`${PLUGIN_ROOT}/references/implementation.md`](../../references/implementation.md#modo-pruebas-implementationscope-tests--contrato-para-el-catálogo). > **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: ``. `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`](../../references/verdicts.md). - **Archivado: no forma parte del cierre.** Este skill no archiva ni lo ofrece; si el trabajo ya está bajo `` (Regla 1 de [`${PLUGIN_ROOT}/references/archive.md`](../../references/archive.md#contrato-para-el-resto-del-catálogo)), 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: - - [: 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](#tipos-de-trabajo)). Si no está en la ruta activa, buscarla bajo `/` 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`](../../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 ` → buscar la entrada inicial con `Created from ` o `branch: Created from `. - Fallback: `git config --get 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`](../../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 ` (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). **Excepción `scope: tests`:** **omitir este paso** — `coverage-verify` no se invoca; registrar `N/A` («repositorio solo de pruebas») en el reporte de cierre y continuar con las dos puertas restantes. 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 ..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](#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 `. 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](#los-informes-de-las-puertas-no-se-integran)): ```bash git merge --no-ff --no-commit 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 : " ``` `` es el identificador del trabajo (`US-XXX` o `WI-XXX`) y `` 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: BUG-XXX`, actualizar además en ese incidente (`/incidents/BUG-XXX-…/README.md`, o bajo `/incidents/`) la línea `Resolución:` a `Fixed (WI-YYY)` — única escritura de este skill sobre un incidente, permitida también si está archivado; si el incidente 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 ``) 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](../../references/git.md#commit-directo) en `${PLUGIN_ROOT}/references/git.md`): mensaje fijo y alcance conocido, así que **no se invoca `git-commit`**. `git add -A -- ` (más la ruta del `README.md` del incidente `BUG-XXX` 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(): 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-.md` · `code-review-.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`](../pr-create/SKILL.md). --- > **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](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](references/flows.md) | | Contrato de lectura de artefactos archivados (fallback y numeración) — este skill **no** archiva | [`${PLUGIN_ROOT}/references/archive.md`](../../references/archive.md#contrato-para-el-resto-del-catálogo) | | 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](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`](../../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`](../../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`](../../references/asking.md): **Preguntas** — mecanismo estructurado, ritmo, fallback. *Antes de la primera pregunta.* - [`${PLUGIN_ROOT}/references/artifacts.md`](../../references/artifacts.md): **Artefactos** — rutas del harness, identificadores, archivado. *Al resolver una ruta o calcular un ID.* - [`${PLUGIN_ROOT}/references/verification.md`](../../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`](../../references/archive.md): **Archivado** — este skill no archiva; aplica solo el contrato de lectura (fallback a ``, IDs ocupados). *Al localizar la carpeta del trabajo.* - [`${PLUGIN_ROOT}/references/git.md`](../../references/git.md): **Política de commit y push** — de aquí sale `integrationBranches` y su `commitPolicy`. *Al resolver la rama base.* - [`${PLUGIN_ROOT}/references/escalation.md`](../../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.*