--- 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). Cuando el trabajo es un US o WI en su rama funcional, pasadas las puertas resuelve el archivado según implementation.archiveMode (pregunta, archiva directo, o nunca) moviendo su carpeta bajo docs/archive/ antes del merge; si no se archiva, el merge sigue igual. 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, **ofrece archivar el artefacto** (mover su carpeta a `docs/archive/`, solo si el usuario lo confirma) y ejecuta `git merge --no-ff`. 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:** la confirmación del archivado (paso 11) va por fuerza **después del merge** — hasta entonces no se sabe si el trabajo llega a integrarse, y el cierre (`Done` + archivado) solo tiene sentido con el código ya en la rama base. **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`. --- ## 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` | `docs/specs/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` | `docs/specs/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: `docs/specs/features/FT-XXX-[slug]/progress.md`, o la de la US/WI correspondiente | **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. --- ## 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 [`references/archive.md`](references/archive.md). Lo que este skill lee y mueve: | Artefacto | Ruta | |-----------|------| | Carpeta / documento del trabajo | US: `docs/specs/user-stories/US-XXX-[nombre-corto]/` · WI: `docs/specs/work-items/WI-XXX-[kebab-case]/` · FT: `docs/specs/features/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` | | Destino del archivado (paso 11) | US: `docs/archive/user-stories/US-XXX-[nombre-corto]/` · WI: `docs/archive/work-items/WI-XXX-[kebab-case]/` · investigaciones sueltas huérfanas: `docs/archive/research/RS-XXX-[slug]/` | --- ## 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` → `docs/specs/user-stories/US-042-exportacion-csv/`; `fix/WI-007-cache-ttl` → `docs/specs/work-items/WI-007-cache-ttl/`; `test/FT-003-carga-masiva` → `docs/specs/features/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. - 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 `docs/archive/` (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 `docs/archive/` | Si no existe en ninguna de las dos: parar e informar; el merge requiere `progress.md` poblado | | **Working tree** | `git status --porcelain` | Si hay salida: invocar automáticamente el flujo del skill **`git-commit`** sobre los cambios pendientes (sin preguntar al usuario si conviene invocarlo — la decisión de invocar es automática; `git-commit` sí puede pausar para confirmar una propuesta de división en varios commits, o detenerse ante secretos, rama protegida o hook fallido, y eso no lo decide `work-integrate`) y continuar una vez quede limpio; si `git-commit` no logra dejarlo limpio, parar e informar el motivo. Detalle operativo (fallback sin `git-commit`, working tree parcialmente limpio): ver [Validación antes de mergear](#validación-antes-de-mergear) | | **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. - **Working tree limpio:** `git status --porcelain` sin salida. Si hay cambios sin commitear, **invocar automáticamente el flujo del skill `git-commit`** sobre ellos (sin preguntar al usuario si conviene invocarlo — la decisión de invocar es automática, no requiere permiso previo) y continuar una vez el working tree quede limpio. La invocación delega en `git-commit` todo su criterio operativo (agrupación por cambio lógico, inferencia de tipo/scope/mensaje, staging, detección de secretos, confirmación de la propuesta de división) — `work-integrate` no decide un mensaje de commit ni qué stagear por su cuenta. **`git-commit` no tiene modo silencioso**: un commit único lo ejecuta sin confirmar, pero puede pausar para confirmar su **propuesta de división** cuando el diff se reparte en varios commits (con `commitConfirmation = always`) y puede detenerse del todo ante secretos, rama protegida o hook fallido; ese comportamiento no se suprime ni se evita al invocarlo desde aquí — «sin preguntar al usuario» se refiere solo a que `work-integrate` no pide permiso para *invocar* `git-commit`, no a que esas pausas y paradas propias de `git-commit` desaparezcan. - **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. - **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 secretos detectados, o por una decisión que el propio `git-commit` no puede resolver solo), eso sí bloquea el merge — informar el motivo reportado. - **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. > **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 es una condición, es una oferta):** superadas las tres puertas se resuelve el archivado de la carpeta del trabajo en `docs/archive/` según `implementation.archiveMode` antes del merge. Ni preguntarlo, ni archivarlo directo, ni saltarlo por política bloquea nada; lo único que bloquea es que el `git mv` falle una vez decidido archivar (destino ya ocupado) — ver [references/archive.md](references/archive.md). - **Working tree limpio otra vez, ya pasadas las puertas:** las puertas pueden dejar cambios sin commitear (correcciones aplicadas por `quality-check`, o por `work-implement` en su modo corrección) **y sus propios artefactos versionados**: `docs/audits/quality-check.md`, `docs/audits/code-review.md` y el `coverage.md` del trabajo, que se escriben siempre; más el **renombrado del archivado**, si el usuario lo confirmó. (`.sdd-devkit/quality-check-run.json` no aparece: está en el `.gitignore` por ser una caché local.) Antes del merge, re-comprobar `git status --porcelain` e invocar de nuevo `git-commit` si hay salida — el **código** que se integra debe ser exactamente el que verificaron las puertas, con sus artefactos. El renombrado del archivado es la única salvedad: mueve documentación bajo `docs/specs/`, no toca código ni fuentes de prueba, así que no invalida los veredictos de `quality-check` ni de `code-review`. Sí desplaza el `SPEC_FINGERPRINT` de `coverage-verify` (se calcula sobre la carpeta del artefacto, cuyas rutas cambian): su `coverage.md` se regenerará una vez en la siguiente validación, sin más consecuencia. **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. **Verificar working tree limpio** con `git status --porcelain`. Si hay salida, **invocar automáticamente el flujo del skill `git-commit`** sobre los cambios pendientes (sin preguntar al usuario si conviene invocarlo) y esperar a que termine; con el working tree limpio, continuar al siguiente paso. Si `git-commit` no logra dejarlo limpio (incluido el caso de quedar parcialmente limpio, o de no estar disponible), aplicar el criterio de [Validación antes de mergear](#validación-antes-de-mergear) — reintentar sobre el remanente o parar e informar el motivo, según corresponda. 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 `docs/archive/` 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). 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`, 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 de cualquier commit a propósito:** seguir adelante dejaría un commit nuevo en una rama que solo había que dejar en paz. 8. **Re-comprobar el working tree tras las puertas.** Las puertas dejan cambios sin commitear de dos clases: **correcciones** (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 `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). Volver a ejecutar `git status --porcelain` y, si hay salida, **invocar de nuevo `git-commit`** con el mismo criterio del paso 2. **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 las dos operaciones de cierre se hacen **sobre la rama base**, en un único commit propio, separado del merge: **11.1 Marcar el trabajo como `Done`.** 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 Resolver el archivado del artefacto.** Mismas condiciones de aplicabilidad que el `Done`: `US-XXX`/`WI-XXX` en rama funcional, y carpeta todavía en la ruta activa (si el paso 3 la encontró ya bajo `docs/archive/`, informarlo y saltar). Si no aplica, **no se resuelve `archiveMode` ni se pregunta nada**. Si aplica, resolver `implementation.archiveMode` (ver [references/archive.md](references/archive.md#política-implementationarchivemode)): con `ask` (por defecto), mostrar la carpeta origen → destino y las investigaciones sueltas que se irían con ella, y pedir confirmación con la herramienta de preguntas estructuradas — respuesta binaria, **preguntar primero, mover después**; con `always`, `git mv` directo, mostrando igual el bloque origen → destino en el reporte; con `never`, no archivar ni preguntar. Si no se archiva —negativa del usuario, sesión desatendida, o `never`— se anota el motivo para el paso 12 y se sigue: **el merge ya está hecho y no depende de esto.** Procedimiento completo (destinos, investigaciones `RS-XXX` huérfanas, reparación de enlaces, guards) en [references/archive.md](references/archive.md). **11.3 Commitear el cierre en la rama base.** Un solo commit con el `progress.md` en `Done` y, si lo hubo, el `git mv` del archivado: `chore(): cerrar trabajo` (+ « y archivar» si se movió). Invocar `git-commit` sobre esos cambios; 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í.** 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 posterior que debe poder leerse —y revertirse— por separado. > **Por qué después del merge.** Archivar y marcar `Done` en la rama del trabajo, antes de integrar, obligaba a decidir el cierre a ciegas: si el merge fallaba, o el usuario detectaba un problema al probar la integración, el artefacto ya estaba archivado y el trabajo «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. **`pr-create` mantiene su comportamiento:** ahí el archivado va en la rama antes del PR, porque el merge lo hace la plataforma y el skill no vuelve a tener el control después. 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. Si el paso 11 movió algo, incluir su **bloque de archivado** (origen → destino y qué pasó con las investigaciones sueltas; formato en [references/archive.md](references/archive.md)). Si no archivó —el usuario lo declinó, no había con quién confirmar, rama `test/`, o el trabajo ya estaba archivado—, decirlo en una línea **con el motivo**, en vez de omitirlo en silencio. 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. | | `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. | | La carpeta del trabajo movida a `docs/archive/` y el `progress.md` en `Done` | No viajan en el merge: se hacen **en la rama base, después del merge** (paso 11), en un commit de cierre propio. El `coverage.md` que la carpeta lleva dentro se mueve con ella. | | `.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) | | Archivado del artefacto (paso 11, tras el merge): cuándo aplica y cuándo no, destinos, `git mv` y guards, investigaciones `RS-XXX` sueltas huérfanas, reparación de enlaces, formato del reporte, anti-patrones | [references/archive.md](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](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/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/implementation.md`](../../references/implementation.md): **Política de implementación** — de aquí sale `archiveMode`. *Antes de resolver el archivado (paso 11).* - [`${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.*