juanca202/sdd-devkit

trace-validate

>- Generar un reporte de trazabilidad que cruza los criterios de aceptación de un artefacto —una historia de usuario (US-XXX), una tarea de mantenimiento (WI-XXX), un feature ya implementado (FT-XXX) o cualquier documento cuyos criterios tengan identificador codificado (AC-001, 1.1, R-3…)— contra los casos y artefactos de prueba del repositorio. Por cada criterio indica qué lo cubre, su estado (`COVERED` / `PARTIAL` / `UNCOVERED`), si la prueba se ejecutó y con qué resultado, y cierra con un ve…

First seen Jun 19, 2026

Installation

$ npx skills add juanca202/sdd-devkit --skill trace-validate

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from juanca202/sdd-devkit · top by installs.

npx skills add juanca202/sdd-devkit

Browse all from juanca202/sdd-devkit

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Open issues 0
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

LicenseMIT

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 44,236 B
  • docs SUMMARY.md 1,033 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 56 installs

SKILL.md

Skill: Validar trazabilidad de un trabajo

Genera un reporte de trazabilidad que cruza los criterios de aceptación de un trabajo contra los casos de prueba y los artefactos de prueba automatizada (unit, integración, e2e) presentes en el repositorio, y emite un veredicto sobre si el trabajo queda cubierto.

El trazado primario es para historias de usuario (US-XXX) con sus criterios de aceptación. Sirve igual para cualquier otro artefacto que tenga criterios con identificador codificado — el formato es indiferente (AC-001, 1.1, R-3…) y se usa verbatim, sin normalizar (ver [Tipos de trabajo y criterios](#tipos-de-trabajo-y-criterios)). Es el mismo contrato que produce test-define.

Qué hace: lee, mapea, obtiene los resultados de pruebas delegando en quality-check y reporta. Es una actividad de verificación, no de desarrollo.

No ejecuta pruebas por sí mismo. La ejecución de la batería de pruebas se delega en quality-check: si existe una corrida previa fresca de quality-check (sin cambios en el código desde entonces), se reutilizan sus resultados; si no, se invoca quality-check en modo tests-only para producirlos. Ver [Resultados de pruebas: delegación en quality-check](#resultados-de-pruebas-delegación-en-quality-check).

Reporte idempotente. Si no han cambiado ni el código, ni las pruebas, ni los criterios y casos de prueba del artefacto desde la última vez que se generó el coverage.md, no se genera un documento nuevo: se devuelven los mismos resultados del reporte existente. Ver [Reutilización del reporte (idempotencia)](#reutilización-del-reporte-idempotencia).

Qué NO hace: no escribe ni modifica código de aplicación, no escribe nuevos tests (eso es de quality-specialist vía work-implement), no edita la especificación de producto (README de la US, TK-XXX, WI-XXX, FT-XXX, validation.md, ADRs), ni corre la suite de pruebas directamente. Lo único que produce es el reporte de trazabilidad. Lo que no se puede determinar de las fuentes va a Observaciones o se pregunta al usuario — nunca se inventa cobertura ni resultados.


Alcance del informe

El informe de este skill cubre un artefacto concreto y sus criterios de aceptación. La pregunta es «¿cada criterio de este trabajo está probado?», así que el universo lo definen los criterios del artefacto, no los archivos que cambiaron ni el repositorio completo.

Consecuencias prácticas:

  • Se validan todos los criterios del artefacto, aunque en esta rama no se haya tocado el código de alguno de ellos: un criterio cuya prueba nunca se escribió sigue siendo un hueco.
  • No se reportan pruebas ni código ajenos al artefacto. Tests de otros trabajos, cobertura global o fallos en módulos que no mapean a ningún criterio de este artefacto no entran en la matriz — a lo sumo van a «Observaciones y pendientes».
  • Si la rama abarca varios trabajos, se valida uno por corrida, con su propio coverage.md junto a su artefacto. Los resultados de pruebas sí son compartidos (vienen de la corrida de quality-check), pero el mapeo es por artefacto.
  • La clave de frescura tiene una mitad de rama y otra de artefacto. El FINGERPRINT cubre el código y los tests de todo el árbol, así que un cambio en otro trabajo de la misma rama invalida también este coverage.md; el SPEC_FINGERPRINT cubre solo la carpeta de este artefacto. Es conservador a propósito: prefiere revalidar de más antes que devolver un reporte que ya no corresponde.

Subagente

Si el proyecto define el subagente quality-specialist, ejecutar este skill bajo ese subagente (es el mismo agente que escribe los tests en el cierre de work-implement, por lo que es el contexto natural para validarlos). Si no existe en el proyecto, ejecutar el flujo normalmente.


Tipos de trabajo y criterios

El tipo se determina por el identificador que indique el usuario o por la ruta de trabajo. Cada tipo fija de dónde se leen los criterios de aceptación y con qué códigos se traza.

Tipo Identificador Dónde viven los criterios Códigos a trazar
Historia de usuario US-XXX Sección Criterios de aceptación del README.md de la US (lista plana, habitualmente AC-XXX) El identificador de cada criterio, en el orden en que aparecen
Tarea de mantenimiento WI-XXX Sección ## Criterios de aceptación del README.md del WI (WI-XXX-[kebab]/README.md) El identificador de cada criterio, en el orden en que aparecen
Feature (funcionalidad ya implementada) FT-XXX Sección ## Criterios de aceptación del README.md del feature (docs/specs/features/FT-XXX-[slug]/README.md) El identificador de cada criterio, en el orden en que aparecen
Cualquier otro artefacto de especificación Ruta o nombre que indique el usuario La sección de criterios del documento (puede llamarse «Criterios de aceptación», «Requisitos», «Acceptance Criteria»…) El identificador de cada criterio, tal como aparece

El requisito no es el formato, es que exista identificador. En todo el flujo, «criterio» se refiere al identificador tal como está escrito en el artefactoAC-012, 1.3, R-3, CA-07 son todos válidos. Nunca normalizar ni renombrar: el vínculo de trazabilidad debe ser buscable literalmente tanto en el artefacto como en los TCs que produjo test-define. Si el trabajo no tiene criterios, o los tiene sin identificador, no hay nada que trazar → bloquear (ver «Cuándo bloquear»).

FT — validar cobertura de funcionalidad ya implementada. Un FT-XXX es el
registro de una funcionalidad ya implementada (inferida de código legacy por el
análisis de work-research, o simplemente el registro de funcionalidad existente),
no trabajo por construir. Validarlo responde: *¿esa funcionalidad ya existente está
cubierta por pruebas?* Un criterio UNCOVERED significa que ese comportamiento
carece de pruebas (un hueco a cerrar escribiendo tests), no que falte código
funcional. Sus casos de prueba documentados viven en
docs/specs/features/FT-XXX-[slug]/test-cases/, igual que en una US o un WI.


Modificadores de invocación

Las claves son en inglés (estándar); el usuario puede nombrarlas en español y se mapean. Sin modificador, se asume el comportamiento por defecto.

Modifier Efecto exacto
revalidate Forzar la regeneración del coverage.md aunque el existente esté fresco: ignorar la comprobación del Paso 0 y ejecutar el flujo completo. Sinónimos aceptados: «revalidar», «forzar», «vuelve a validar». Necesario cuando los criterios viven fuera del repo (un ticket, un documento externo) y han cambiado allí — eso el SPEC_FINGERPRINT no puede verlo. Mismo modificador y mismo significado que en [code-review](../code-review/SKILL.md).

Cómo preguntar al usuario

Mecanismo, ritmo y fallback compartidos: [../../reference/asking.md](../../reference/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í.


Resolución de idioma

Antes de ejecutar este skill, DEBES leer [../../reference/language.md](../../reference/language.md).

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

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

Excepción deliberada: la salida y los mensajes de error de las herramientas de prueba no se traducen; se citan literales.


Información requerida antes de generar el reporte

No inventar nada. Si un dato no es explícito, obtenerlo del repo o preguntar al usuario.

Dato Cómo obtenerlo Si no está disponible
Trabajo a validar Indicado por el usuario o inferido de la ruta de trabajo; determinar el tipo (US-XXX / WI-XXX / FT-XXX / otro artefacto) Preguntar qué trabajo validar; sin él no se puede generar el reporte
Criterios de aceptación Según el tipo (ver [Tipos de trabajo y criterios](#tipos-de-trabajo-y-criterios)) Si el trabajo no tiene criterios de aceptación: bloquear y reportar — sin criterios no hay nada que trazar
Casos de prueba Fuente primaria: la carpeta test-cases/ junto al artefacto y su índice test-cases/README.md, más la línea Casos de prueba: que test-define deja bajo cada criterio. Fallback: inferir desde los tests del repo Si no hay casos documentados, derivar la cobertura desde los artefactos de prueba del repo
Artefactos de prueba Buscar en el repo archivos de test unit / integración / e2e relacionados con el trabajo (ver el Paso 2 en references/flow.md) Si no se encuentran, marcar criterios sin artefacto como UNCOVERED y dejar Observación
Resultados de pruebas Delegados en quality-check: caché fresca test-run.json o invocación tests-only (ver [Resultados de pruebas: delegación en quality-check](#resultados-de-pruebas-delegación-en-quality-check)) Si quality-check no puede ejecutarlas (sin stack, entorno sin correr, no disponible en la sesión) o el usuario declina la delegación: las filas con artefacto van con Ejecución = — y Resultado = NOT_RUN`, y el motivo a «Observaciones y pendientes»
Alcance Todo el trabajo por defecto; el usuario puede acotar a ciertos criterios Si es ambiguo, preguntar

Leer siempre el documento de criterios completo (el README.md del trabajo, o el archivo del artefacto externo) antes de generar el reporte. No asumir criterios que no estén escritos.


Flujo

Resumen de los pasos. El detalle íntegro de cada paso está en references/flow.md (leerlo antes de ejecutar el flujo).

  1. Comprobar frescura del reporte — si ya existe coverage.md con un fingerprint guardado y no hubo cambios en los archivos desde entonces, devolver el reporte existente sin regenerarlo (ver [Reutilización del reporte (idempotencia)](#reutilización-del-reporte-idempotencia)). Solo si hay cambios (o el usuario pide revalidar) continuar con los pasos siguientes.
  2. Localizar y leer el trabajo — resolver tipo y ubicación; extraer todos los criterios con su identificador verbatim. Sin criterios (o sin identificador) → bloquear (ver «Cuándo bloquear»).
  3. Inventariar casos y artefactos — leer la carpeta test-cases/ del artefacto y su índice como fuente primaria, y clasificar los tests del repo por tipo, con ruta y criterio.
  4. Mapear cobertura fila a fila — expandir cada criterio en sus filas (criterio × TC × tipo declarado), rellenar Evidencia y derivar el estado del criterio (ver «Estados de cobertura») con sus observaciones. No forzar mapeos inciertos.
  5. Obtener resultados de pruebas (delegando en quality-check) — reutilizar la caché test-run.json si está fresca, o invocar quality-check en modo tests-only; mapear por suite a las filas y rellenar Ejecución (quality-check / Manual / ) y Resultado (PASS / FAIL / NOT_RUN / UNCOVERED / N/A). No correr pruebas directamente. Nunca fabricar resultados (ver [Resultados de pruebas: delegación en quality-check](#resultados-de-pruebas-delegación-en-quality-check) y references/flow.md).
  6. Redactar el reporte desde assets/coverage-template.md (leerla antes de redactar): cabecera, Resumen (prosa con la procedencia + tabla de indicadores), cobertura por criterio (una fila por criterio, con su Estado), matriz de trazabilidad (una fila por criterio × TC × tipo declarado, con Evidencia, Ejecución y Resultado) y, si los hay, los caveats globales en «Observaciones y pendientes». Ver [Vistas del reporte](#vistas-del-reporte-cobertura-por-criterio-y-matriz).
  7. Emitir el veredicto (ver «Veredicto») respondiendo si todos los criterios quedan cubiertos.
  8. Entregar y guardar el reporte en la ubicación del tipo (ver «Ubicación de archivos»), grabando el fingerprint del estado actual para la próxima comprobación de frescura; no modificar otros artefactos.

Vocabulario de veredictos y estados

Antes de redactar cualquier informe, DEBES leer [../../reference/verdicts.md](../../reference/verdicts.md).

Las reglas de verdicts.md son obligatorias: el valor canónico y el símbolo son estables, y la etiqueta que lee la persona se redacta siempre en el idioma resuelto por language.md. Ninguna etiqueta de este skill se fija en un idioma concreto.

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


Estados de cobertura

Los valores de la columna Estado son canónicos: en el reporte se escribe su símbolo seguido de la etiqueta en el idioma resuelto.

Estado (canónico) Símbolo Cuándo aplicarlo
COVERED El criterio tiene al menos un caso de prueba y el artefacto que le corresponde, y lo valida de forma completa. Si se ejecutó automáticamente, pasó. Un criterio cuyos TCs son Manual por diseño también es COVERED si esos TCs lo validan por entero — ver la nota de abajo.
PARTIAL ⚠️ El criterio está cubierto solo en parte: hay prueba pero no abarca todo el criterio, el artefacto existe pero no se pudo ejecutar, el resultado fue parcial, existe solo validación manual no declarada como tal (TC automatizable aún sin automatizar), o la suite que agrupa su test dio FAIL pero no se pudo aislar si el test específico del criterio fue el que falló (ver «Mapeo a la matriz» más abajo). Detallar el límite en Observaciones.
UNCOVERED No existe caso de prueba ni artefacto que valide el criterio, o la prueba asociada falló y se pudo aislar que fue la suya.

Cobertura ≠ ejecución. Que exista prueba que valida el criterio es una cosa; que haya corrido y con qué resultado, otra. Un criterio cuya prueba falló —y se pudo aislar que fue la suya— se reporta UNCOVERED con el fallo en Observaciones; si la suite falló pero no se puede aislar el test, es PARTIAL (ver «Mapeo a la matriz»).

El status del TC filtra la cobertura. La fuente primaria es la columna Estado del índice test-cases/README.md; si el índice no la trae, abrir el TC-XXX-*.md y leer su campo Estado, con la marca oculta <!-- tc:status=Draft|Ready|Obsolete · testType=… --> como desempate. Los valores (Draft/Ready/Obsolete) son canónicos y no se traducen; lo que va en el idioma resuelto es la etiqueta del campo. Un TC Obsolete no cuenta como cobertura (dejar Observación); uno Draft cuenta como cobertura PARTIAL (aún no está listo para respaldar el criterio); solo los Ready cuentan como cobertura plena. Si el TC no trae el campo, tratarlo como Ready. Esto es distinto del Estado: del artefacto, que este skill no exige (ver «Cuándo bloquear»).

Manual por diseño vs. pendiente de automatizar. test-define distingue los dos casos en el campo Tipo de prueba del TC: Manual significa no se automatiza por decisión de diseño; cualquier otro valor (Unit, Integration, API Test, Visual Test, E2E) significa debería existir artefacto automatizado. Respetar esa declaración: un criterio con TCs Manual que lo cubren por completo es COVERED (sus filas van con Ejecución = Manual y Resultado = N/A), no una deuda; un criterio con TCs automatizables sin artefacto es PARTIAL o UNCOVERED. No penalizar una decisión de diseño ni disimular una automatización pendiente.

Un TC con varios tipos declarados se cubre por tipo. Si un TC declara Unit, E2E y solo existe el test unitario, el criterio no es COVERED: la fila E2E de la matriz queda en UNCOVERED y el criterio baja a PARTIAL, con el tipo faltante nombrado en Observaciones. La matriz muestra esa asimetría fila a fila (ver [Vistas del reporte](#vistas-del-reporte-cobertura-por-criterio-y-matriz)).


Vistas del reporte: cobertura por criterio y matriz

El reporte tiene dos tablas complementarias, no una. Separarlas evita el problema de meter en una sola fila información de granularidades distintas (un criterio puede tener varios TCs, y un TC varios tipos de prueba).

El Resumen las precede con una tabla de indicadores de cuatro columnas y una sola fila de cifras —criterios de aceptación, cubiertos, parciales, no cubiertos— cuyos tres últimos valores deben sumar el total. No lleva indicadores de pruebas (fallidas, no ejecutadas): esa granularidad ya está en la matriz y mezclar los dos ejes confunde. La procedencia de los resultados y el result por suite van en la línea «Pruebas» del Resumen; test-run.json no trae un agregado global, así que no se inventa uno.

1. Cobertura por criterio — la vista de veredicto. Una fila por criterio:

Criterio Descripción Estado Observaciones
AC-2.1 El usuario recibe confirmación por correo PARTIAL E2E declarado en TC-001 sin automatizar
AC-2.2 La plantilla del correo respeta la identidad visual COVERED Validación manual por diseño (TC-004)

2. Matriz de trazabilidad — la vista auditable. Una fila por cada combinación criterio × TC × tipo de prueba declarado: si un TC declara Unit, E2E, produce dos filas.

Criterio TC Tipo Evidencia Ejecución Resultado
AC-2.1 TC-001 Unit tests/unit/notify.test.ts quality-check Paso
AC-2.1 TC-001 E2E UNCOVERED
AC-2.2 TC-004 Manual test-cases/TC-004-revision-visual.md Manual N/A

Semántica de las columnas:

Columna Qué contiene Valores
Criterio Identificador verbatim del artefacto, repetido en cada fila suya AC-012, 1.3, R-3
TC Caso de prueba que produjo test-define TC-XXX · si el criterio no tiene TC documentado (fila derivada de un test hallado, o hueco total)
Tipo El Tipo de prueba declarado en el TC; en filas derivadas, el tipo del artefacto hallado Manual · Unit · Integration · API Test · Visual Test · E2E · (sin TC y sin artefacto)
Evidencia La prueba concreta que respalda la fila Ruta del artefacto automatizado · ruta del TC para filas Manual · si esa intención no está materializada
Ejecución Quién produjo el resultado quality-check · Manual · (no se ejecutó)
Resultado Qué dio esa prueba. Valores canónicos; en el reporte va la etiqueta en el idioma resuelto PASS · FAIL · NOT_RUN (hay artefacto, no corrió) · UNCOVERED (no hay evidencia para ese tipo) · N/A (manual por diseño)

Por qué se eliminó la columna Automática. Un no decía nada útil: no revelaba qué tipo de prueba
respaldaba el criterio, dónde vivía, ni quién produjo el resultado. Tipo + Evidencia + Ejecución dan
esa información sin ambigüedad, y la granularidad por tipo hace visible el hueco (la fila E2E sin
evidencia) en lugar de esconderlo tras un que solo hablaba del test unitario.

Evidencia = — implica Ejecución = — y Resultado = UNCOVERED`. No hay excepción: si no hay
artefacto, no hubo ejecución ni puede haber resultado. Al revés no: puede haber evidencia con
Ejecución = — y Resultado = NOT_RUN (el artefacto existe pero quality-check` no pudo correrlo;
la razón va a «Observaciones y pendientes»).

Criterio sin TC documentado pero con test hallado. Si el mapeo se infirió desde el repo (fallback del
Paso 2), la fila se escribe igual con TC = — y el tipo del artefacto hallado, y se anota en
Observaciones que el mapeo es inferido, no declarado. Solo el criterio sin TC y sin artefacto produce
la fila vacía — | — | — | — | UNCOVERED`.

Derivación del Estado del criterio a partir de sus filas. Evaluar en orden y detenerse en la primera que aplique:

# Filas del criterio Estado
1 Ninguna fila aporta cobertura — todas en UNCOVERED, o el criterio no tiene TC ni artefacto, o sus únicos TCs son Obsoleteo alguna fila dio FAIL aislado a su test UNCOVERED
2 Alguna fila en UNCOVERED/NOT_RUN, algún TC en Draft u Obsolete conviviendo con cobertura válida, o un FAIL de suite no aislable PARTIAL
3 Todas con Resultado ∈ {PASS, N/A} y todos los TCs en Ready (o sin campo Estado) COVERED

Dos destinos de observación, no intercambiables. La prueba para elegir: *¿se puede atribuir a un
criterio concreto?* Si sí, va en la columna Observaciones de la tabla 1; si no, en la **sección
«Observaciones y pendientes»**. La matriz no lleva columna de observaciones.

| Destino | Qué recibe |
|---------|------------|
| Columna Observaciones (tabla 1) | Tipo declarado sin automatizar · TC en Draft/Obsolete · FAIL no aislable · suite efectiva distinta del tipo declarado · mapeo inferido en vez de declarado · cobertura apoyada en TCs Manual (aunque sea por diseño: es el caveat que justifica el APPROVEDWITHNOTES) · límite de la cobertura |
| Sección «Observaciones y pendientes» | Suite coverage en FAIL · workingTreeClean: false (árbol sucio) · clases de prueba ausentes en el repo · ejecución no delegable y su motivo · tests que no se pudieron vincular con certeza a ningún criterio · tests o fallos ajenos al artefacto |

La sección global se omite entera si no hay ninguno. Cuando el skill diga «dejar Observación» sin más,
aplicar esta prueba.

La derivación no es cerrada sobre la matriz: dos datos viven fuera de ella. (a) el Estado del TC
(Draft/Obsolete/Ready, que viene del propio TC) y (b) si un FAIL pudo aislarse al test del
criterio. Ambos se anotan siempre en la columna Observaciones de la tabla 1 — sin esa anotación, dos
criterios con filas idénticas quedarían con estados distintos sin explicación. Un FAIL no aislable se
escribe igual (Resultado = FAIL) en la matriz; lo que lo distingue es la Observación «suite X en
FAIL, no se pudo aislar el test» y el Estado = PARTIAL` resultante.

TCs Obsolete. Sus filas se conservan en la matriz por trazabilidad con su valor real, pero **no
cuentan como cobertura** al derivar el estado: si son los únicos TCs del criterio, este cae en la fila 1
aunque sus filas digan PASS; si conviven con TCs Ready que sí lo cubren, el criterio es como máximo
PARTIAL (fila 2). En ambos casos, Observación explicando que el TC está obsoleto.


Reutilización del reporte (idempotencia)

Mismo principio de caché que quality-check y [code-review](../code-review/SKILL.md#reutilización-del-informe-idempotencia) —las tres puertas del cierre lo aplican, cada una sobre su propio artefacto—: si no hubo cambios en los archivos desde la última generación, no se produce un reporte nuevo — se devuelven los mismos resultados del coverage.md existente. Esto evita rehacer el mapeo y volver a delegar la ejecución de pruebas cuando nada cambió.

Contexto de ejecución. Como quality-check, este skill es una compuerta de cierre (al integrar o
antes del PR), no corre por tarea ni durante la implementación. La frescura se evalúa sobre la rama
consolidada del cierre. En el pipeline típico de cierre pr-create corre quality-check primero
(produce test-run.json fresco) y luego trace-validate, que reutiliza esa corrida — sin doble
ejecución de pruebas; y si el código tampoco cambió desde el último coverage.md, este Paso 0 lo
devuelve sin regenerarlo.

Clave de frescura — dos hashes, porque el reporte depende de dos cosas distintas.

Clave Qué cubre Cómo se calcula
FINGERPRINT El código y los tests. El fingerprint canónico de la tubería, idéntico al de quality-check y code-review: excluye toda carpeta oculta, cualquier docs/ y los coverage.md sueltos, para que escribir un artefacto generado no invalide la caché. Receta exacta en [quality-check](../quality-check/SKILL.md#caché-de-corrida-de-pruebas-compartida-con-trace-validate). Sobre todo el árbol, menos las exclusiones
SPEC_FINGERPRINT Los criterios y los casos de prueba del artefacto que se valida: su README.md y su carpeta test-cases/. Viven bajo docs/specs/, que el FINGERPRINT excluye — sin esta segunda clave, reescribir un criterio no invalidaría nada. Sobre la carpeta del artefacto, excluyendo su propio coverage.md

bash NOREPORT=":(exclude)${ARTEFACTO%/}/coverage.md" SPECFINGERPRINT=$( { git -C "$ROOT" ls-files -s -- "$ARTEFACTO" "$NOREPORT"; \ git -C "$ROOT" status --porcelain -uall -- "$ARTEFACTO" "$NOREPORT"; \ git -C "$ROOT" diff -- "$ARTEFACTO" "$NO_REPORT"; \ } | git hash-object --stdin )

donde $ARTEFACTO es la carpeta del trabajo (docs/specs/user-stories/US-042-…/) o, si el artefacto es un archivo suelto, su ruta. Se reutiliza el reporte solo si coinciden los dos.

La exclusión del propio reporte no es opcional. El coverage.md vive dentro de $ARTEFACTO: sin $NOREPORT, escribirlo en el Paso 7 movería el SPECFINGERPRINT, la marca de pie guardaría el hash de antes de escribir, y ninguna corrida posterior coincidiría — la idempotencia no se dispararía nunca. La clave cubre las entradas del reporte, no su salida; es el mismo motivo por el que el FINGERPRINT excluye **/coverage.md.

Y tiene que ser una ruta literal interpolando $ARTEFACTO, no un glob. ':(exclude,glob)/coverage.md' junto a un pathspec positivo hace que git excluya todo**: las tres órdenes devuelven vacío, la clave queda fija en el hash del blob vacío, y entonces la idempotencia se dispara siempre y un criterio editado nunca invalida el reporte. El EXC del FINGERPRINT puede usar globs porque ahí no hay pathspec positivo.

Por qué dos claves y no una. Meter docs/ entero en el FINGERPRINT haría que escribir cualquier informe invalidara las tres cachés — el problema que las exclusiones resuelven. Acotar la segunda clave a la carpeta del artefacto captura exactamente lo que este reporte traza, sin arrastrar el resto de la documentación. Y a diferencia de «detectar que el usuario editó los criterios», es una comprobación determinista: no depende de que el cambio haya ocurrido en esta sesión, ni de que alguien lo mencione.

Lo que sigue sin cubrirse: criterios que viven fuera del repo (un ticket de un tracker, un documento externo). Ahí no hay nada que hashear; si el artefacto es externo, decirlo en el reporte y pedir revalidate cuando cambie.

Un solo cálculo por corrida, con una excepción. Ambos hashes se computan una vez, en el Paso 0. El
FINGERPRINT sirve para las dos comprobaciones de frescura —la del coverage.md (Paso 0) y la del
test-run.json (Paso 4, delegación)—; el SPEC_FINGERPRINT solo para la primera. Los dos se regraban en el
Paso 7. Si hubo delegación en tests-only, recalcular el FINGERPRINT antes de grabar: esa corrida no
toca código, pero sí puede normalizar el .gitignore la primera vez que quality-check corre en el repo, y
eso mueve la clave. El SPEC_FINGERPRINT no se ve afectado.

Comportamiento (Paso 0 del flujo):

  1. Resolver la ubicación del trabajo y calcular FINGERPRINT y SPEC_FINGERPRINT. Siempre, haya reporte

previo o no: el Paso 7 los necesita para grabar la marca de pie, también en la primera validación.

  1. Buscar su coverage.md. Si no existe → generar normal (no hay caché).
  2. Si existe, leer los hashes guardados en su marca de pie

(<!-- trace-validate:verdict=<canónico> · fingerprint=<hash> · spec=<hash> · generated=YYYY-MM-DD -->) y reutilizarlo solo si se cumple todo: coinciden los dos hashes, el reporte no registra una ejecución fallida, y el usuario no pasó revalidate. - Se cumpleno regenerar: devolver el veredicto y el resumen del reporte existente tal cual, e indicar al usuario que no hubo cambios desde la última validación ({{fecha guardada}}). No reescribir el archivo, no delegar en quality-check. - Falla algo, no hay marca de pie (reportes antiguos), o el usuario pide revalidate → ejecutar el flujo completo (Pasos 1-7) y regrabar ambos hashes al guardar (Paso 7).

  1. La marca de pie se conserva en el documento publicado (no se elimina como el bloque de instrucciones

de la plantilla). Si está ilegible o incompleta (un hash que no parsea, marca truncada, o falta el campo spec=), no intentar repararla ni adivinar: tratar la caché como ausente, regenerar y regrabarla.

Un reporte que no pudo ejecutar las pruebas nunca se sirve desde caché. Si el reporte existente tiene
filas en NOT_RUN porque la delegación no fue posible (sin red, sin runner, el usuario declinó), su
⚠️ describe un fallo de entorno, no del código. Congelarlo significaría arrastrar ese «no se pudo
comprobar» para siempre aunque el entorno ya funcione. Regenerar y volver a intentar la delegación.

Un cambio en una carpeta oculta (.sdd-devkit/, .github/…), en docs/ fuera de la carpeta del
artefacto, o en un coverage.md no cuenta como cambio: están excluidos, así que ningún artefacto
que generen este skill, quality-check, code-review o arch-audit desplaza la clave. Los criterios y los
TC-XXX cuentan, vía SPEC_FINGERPRINT.


Resultados de pruebas: delegación en quality-check

trace-validate no ejecuta la suite de pruebas. La ejecución es responsabilidad de quality-check, que la persiste en un artefacto reutilizable test-run.json (esquema test-run/v1). Como el review es una corrida completa de la rama, este artefacto vive en una ubicación fija, no por unidad: .sdd-devkit/test-run.json, en la raíz del repositorio.

Cómo obtener los resultados (Paso 4 del flujo):

  1. Reusar el fingerprint canónico ya calculado en el Paso 0 (mismo valor; no recalcular).
  2. **Si existe test-run.json, su schema es test-run/v1, su generatedBy es "quality-check", su git.fingerprint coincide y su

suites[] cubre el conjunto de suites vigente (las dos fijas, más e2e si el repo la ejecuta y las que declare el estándar de testing) → caché fresca: no hubo cambios desde la corrida de quality-check. Reutilizar los resultados por suite sin ejecutar nada. Si generatedBy trae cualquier otro valor, descartar la caché y delegar: quality-check es el único productor autorizado. Si el estándar de testing cambió desde la corrida (suites de más o de menos), la caché es obsoleta aunque el fingerprint coincida —el estándar vive en docs/, excluido del fingerprint—: delegar. Anotar la procedencia en la línea «Pruebas» del Resumen**: «resultados tomados de la corrida de quality-check del {{commit/fecha}}».

  1. Si no existe o el fingerprint difiere (hubo cambios, o nunca corrió) → **delegar en quality-check

en modo tests-only**, que ejecuta solo los checks de pruebas, escribe test-run.json y devuelve los resultados. Luego consumir esa caché ya fresca.

  1. Si quality-check no puede ejecutarlas (stack no detectable, entorno sin poder correr, dependencias

ausentes, o el usuario declina la delegación) → las filas con artefacto van con Ejecución = — y Resultado = NOT_RUN`, con la razón en «Observaciones y pendientes», y se entrega igualmente la matriz con los artefactos hallados. Nunca fabricar resultados.

Mapeo a la matriz. Cada entrada suites[] de test-run.json trae type y result (PASS/FAIL/SKIPPED/N/A). Las dos fijasunit, coverage— vienen siempre; e2e solo si el repo la ejecuta, y el resto son suites configuradas en el estándar de testing del repo, cuyo type es el ID del requisito que las declara (p. ej. integration-testing, contract-testing) y que traen su referencia global en standard (p. ej. testing/integration-testing). Pueden no existir: si el estándar no declara integración, no hay entrada para ella —y no hay que buscar una clave fija llamada integration—, así que una fila de tipo Integration se resuelve contra la suite donde el repo la tenga (típicamente unit) o queda NOTRUN. No inferir una suite ausente ni inventar su resultado. La suite coverage no se mapea a ningún criterio: es cobertura de líneas/ramas, una métrica del repo que juzga quality-check, no cobertura funcional; si viene en FAIL, mencionarlo en «Observaciones y pendientes» y nada más. Mapeo al reporte: PASSPASS, FAILFAIL, SKIPPEDNOTRUN, N/A (el repo no tiene esa suite)→NOT_RUN, dejando en «Observaciones y pendientes» que esa clase de prueba no existe en el repo. Un criterio cuya prueba asociada dio FAIL y se pudo aislar que fue la suya se reporta UNCOVERED con el fallo en Observaciones; si la suite falló sin poder aislar el test, es PARTIAL (ver «Estados de cobertura» y la nota de granularidad más abajo).

El mapeo es por fila, no por criterio. Cada fila de la matriz (criterio × TC × tipo) se resuelve así:

Situación de la fila Evidencia Ejecución Resultado
Tipo declarado sin artefacto en el repo UNCOVERED
Artefacto hallado y la suite que lo corre dio PASS ruta quality-check PASS
Artefacto hallado y su test dio FAIL (aislable) ruta quality-check FAIL
Artefacto hallado, suite en FAIL sin poder aislar el test ruta quality-check FAIL (+ Observación «no aislable» → criterio PARTIAL)
Artefacto hallado, suite SKIPPED / ausente / no ejecutable ruta NOT_RUN
TC Manual por diseño ruta del TC Manual N/A

Ejecución dice quién produjo el resultado, no de qué clase es la prueba: eso ya lo dice la columna Tipo y la ruta de Evidencia. La suite efectiva que corrió el test (dónde vive realmente en el repo) solo se menciona cuando no coincide con el tipo declarado —un API Test que corre en unit, por ejemplo—, y va en Observaciones, no en la matriz.

Granularidad suite vs. criterio: result es por suite completa, no por test individual. Si
varios criterios mapean a tests dentro de la misma suite y esa suite da FAIL, no propagar FAIL/UNCOVERED a todos ellos sin más: si el summary u otro detalle de quality-check permite aislar qué test
falló, marcar solo ese criterio; si no hay forma de aislarlo, marcar los criterios afectados como
PARTIAL (no UNCOVERED) con la ambigüedad explicada en Observaciones. Detalle completo en
references/flow.md (Paso 4).

Si el proyecto no usa quality-check (no está disponible en la sesión), degradar con elegancia: reportar
las filas con artefacto en Ejecución = — / Resultado = NOT_RUN («ejecución delegada no disponible») —las que no tienen artefacto siguen en UNCOVERED`— y entregar la cobertura estática. No
reintroducir un runner propio en trace-validate.


Cuándo bloquear

Parar y reportar (sin generar reporte parcial) cuando:

  • El trabajo no existe o no se encuentra su documento de criterios.
  • No hay sección de criterios de aceptación, está vacía, o los criterios no tienen identificador codificado (el formato es indiferente; lo que no puede faltar es el identificador): no hay nada que trazar de forma trazable; sugerir alinear el trabajo con su skill de definición/planificación antes de validar (para un FT-XXX, completar su especificación con el flujo «Analizar legado» de work-research).

No bloquear por que el artefacto no siga las convenciones del plugin: identificadores fuera del formato AC-XXX, ubicación fuera de docs/specs/ o ausencia de campo Estado: no son motivos de bloqueo.

` WARNING No es posible generar el reporte de trazabilidad:

  • <razón concreta>
  • <acción sugerida: p. ej. definir los criterios de aceptación del trabajo antes de validar>

`


Ubicación de archivos

Layout completo del harness, identificadores y contrato de archivado: [../../reference/artifacts.md](../../reference/artifacts.md).

Lo propio de este skill:

Rol Ruta
Artefacto a trazar (entrada) La carpeta de la US-XXX / WI-XXX / FT-XXX; para cualquier otro artefacto, la ruta que indique el usuario
Casos de prueba documentados (entrada, los produce test-define) test-cases/ dentro de la carpeta del artefacto, con su índice test-cases/README.md
Caché de corrida de pruebas (entrada, la produce quality-check) .sdd-devkit/test-run.json (ubicación fija, no por unidad)
Reporte de trazabilidad (salida) coverage.md dentro de la carpeta del artefacto, allí donde se haya resuelto — activa o bajo docs/archive/; para otro artefacto, junto a él (confirmar la ruta con el usuario antes de escribir)

Un US/WI archivado se traza igual. Todo se resuelve relativo a la carpeta encontrada: los criterios, el test-cases/, la clave SPEC_FINGERPRINT y el coverage.md de salida. trace-validate es el único skill que escribe dentro de un artefacto archivado, y solo su propio informe: es un derivado del artefacto, no trabajo nuevo, y revalidar un trabajo ya integrado tiene que seguir siendo posible.


Mensaje al usuario

Solo el veredicto, el resumen de cobertura y lo que el usuario debe saber o decidir (criterios UNCOVERED/PARTIAL, pruebas que fallaron, si no se pudo ejecutar y por qué). No narrar el trabajo en curso («leí el README», «creé el archivo») ni el razonamiento interno. Listar pendientes en viñetas agrupadas por criterio.


Veredicto

Veredicto (canónico) Símbolo Cuándo aplicarlo
APPROVED Todos los criterios del trabajo en estado COVERED y, si se ejecutaron pruebas automáticas, todas pasaron.
APPROVEDWITHNOTES ⚠️ Ningún criterio en UNCOVERED, pero hay caveats que el usuario debe conocer: algún criterio en PARTIAL, cobertura apoyada en TCs Manual (aunque sea por diseño), o pruebas que no se pudieron ejecutar y por tanto no confirman nada. Enumerar cada caveat.
REJECTED Al menos un criterio en UNCOVERED, o una prueba asociada falló de forma aislable. Listar los criterios faltantes/fallidos.

Precedencia: REJECTED > APPROVEDWITHNOTES > APPROVED. Es decir, APPROVED exige cero caveats: si hay alguno (criterio PARTIAL, cobertura apoyada en TCs Manual, pruebas no ejecutadas), el veredicto es APPROVEDWITHNOTES (⚠️), no APPROVED ().

En el cierre, este ⚠️ no bloquea (a diferencia del INCOMPLETE de quality-check y code-review, que sí): work-integrate y pr-create continúan mostrando las observaciones al usuario. Por eso cada caveat debe quedar enumerado y ser legible por sí solo — es lo único que el usuario verá antes de integrar.


Handoffs del ciclo

Posición: validación / cierre de calidad — después de work-implement.

| | | |--|--| | Entrada | Trabajo (US-XXX / WI-XXX, u otro artefacto) con criterios de aceptación identificados; código implementado; idealmente tests escritos por quality-specialist en el cierre de work-implement. Resultados de pruebas vía quality-check (caché test-run.json o delegación tests-only). O un FT-XXX (registro de funcionalidad ya implementada — inferida de código legacy o documentada como existente) para comprobar si está cubierta por pruebas. | | Salida | coverage.md en la ubicación del tipo + veredicto sobre la cobertura. | | Veredicto REJECTED (US/WI) | Volver a work-implement (fase de pruebas con quality-specialist) para cubrir los criterios faltantes; revalidar después. | | Veredicto REJECTED (FT) | Hay comportamiento ya implementado sin pruebas: escribir los tests faltantes sobre el código existente (no código funcional) con work-implement en su tipo feature —que automatiza los TC-XXX del FT-XXX— y revalidar. Formalizar ese trabajo como una tarea de mantenimiento (WI-XXX) es opcional y lo decide el usuario. | | Falta funcional en el trabajo | Si la matriz revela que un criterio no es testeable o está mal definido, escalar a la definición/planificación del trabajo — para un FT, a quien lo registró (el flujo «Analizar legado» de work-research u otra fuente de la funcionalidad); no editar la especificación desde aquí. |


Mapa de referencias

Archivo Cuándo leerlo
references/flow.md Flujo paso a paso (Pasos 0-7), delegación de la ejecución de pruebas en quality-check (caché test-run.json / tests-only) y checklist completo. Leer antes de ejecutar el flujo.
references/examples.md Ejemplos por tipo (US / WI, sin criterios, sin runner, criterio sin prueba) y anti-patrones. Leer ante dudas de comportamiento.
assets/coverage-template.md Plantilla canónica del reporte de trazabilidad. Leer antes de redactar el reporte.

Referencias compartidas del plugin

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

  • [../../reference/language.md](../../reference/language.md): Idioma — resolución obligatoria del idioma de artefactos y mensajes. Lectura obligatoria antes de ejecutar el skill.
  • [../../reference/asking.md](../../reference/asking.md): Preguntas — mecanismo estructurado, ritmo, fallback. Antes de la primera pregunta.
  • [../../reference/artifacts.md](../../reference/artifacts.md): Artefactos — rutas del harness, identificadores, archivado. Al resolver una ruta o calcular un ID.