developer-feedback

Captura feedback de testing manual del desarrollador, genera evidencia local y crea GitHub issue vinculado a acceptance criteria.

embedbuild/specbox-engine2 installsApache-2.0Synced Aug 27

Works with

Claude CodeCursorCodex CLIGitHub CopilotGemini CLI

Agent Skills format with YAML frontmatter. Claude Code reads it as-is.

---
name: "developer-feedback"
description: "Captura feedback de testing manual del desarrollador, genera evidencia local y crea GitHub issue vinculado a acceptance criteria."
license: "Apache-2.0"
---

# /feedback (Global)

Captura feedback de testing manual del desarrollador, genera evidencia local y crea GitHub issue vinculado a acceptance criteria.

## Uso

```
/feedback [feature] [--ac AC-XX] [--severity critical|major|minor]
```

**Modos de invocacion:**
- `/feedback invoice-detail` → Feedback para feature "invoice-detail"
- `/feedback` → Sin argumento: auto-detecta feature desde la rama actual
- `/feedback invoice-detail --ac AC-03 --severity critical` → Con metadata inline
- `/feedback resolve FB-NNN` → Marcar feedback como resuelto
- `/feedback list [feature]` → Listar feedback del feature

---

## Paso 0.0 — Política de Autopilot v5.29.0

Antes de cada pregunta, llama a `evaluateDecision(decision_key, context)` desde `.claude/hooks/lib/autopilot.mjs`.

| Pregunta del skill | decision_key | Default si auto |
|--------------------|--------------|------------------|
| Recopilación de campos del feedback (Paso 2) | `feedback_field_classification` | siempre `ask` (calidad de spec) |
| Crear GitHub issue | `destructive_action` | siempre `ask` (acción visible externa) |
| Marcar AC como inválido (puede invalidar AG-09) | `destructive_action` | siempre `ask` |

**Regla**: la calidad del feedback no se compromete con autopilot. Esta skill captura información del usuario sobre bugs detectados — la información debe ser completa o se corrompe la trazabilidad.

---

## Paso 0: Detectar Contexto del Feature

### 0.1 Resolver feature name

```
¿Que recibi?
├── nombre_de_feature → Usar directamente
├── "resolve FB-NNN" → Ir a sub-comando Resolve (Paso R)
├── "list [feature]" → Ir a sub-comando List (Paso L)
├── sin argumento → Detectar desde rama actual
│   ├── feature/invoice-detail → feature = "invoice-detail"
│   ├── main/master → Preguntar: "¿Para que feature es el feedback?"
│   └── otro → Extraer nombre de la rama
└── Argumento no reconocido → Preguntar al usuario
```

```bash
git branch --show-current
```

### 0.2 Verificar directorio de evidencia

```bash
ls .quality/evidence/${feature}/ 2>/dev/null
```

Si no existe:
- Crear directorio: `mkdir -p .quality/evidence/${feature}/feedback/`
- INFO: "Directorio de evidencia creado para '{feature}'."

Si existe pero no tiene subdirectorio feedback:
- Crear: `mkdir -p .quality/evidence/${feature}/feedback/`

### 0.3 Detectar repositorio GitHub

```bash
git remote get-url origin 2>/dev/null
```

Extraer owner/repo del URL para la creacion del GitHub issue.
Si no hay remote → WARNING: "No se detecto repositorio remoto. Solo se creara evidencia local."

---

## Paso 1: Localizar PRD y Acceptance Criteria

### 1.1 Buscar PRD

```
¿Donde esta el PRD?
├── .quality/evidence/${feature}/acceptance-report.json existe
│   └── Extraer criteria de ahi (ya parseados por AG-09b)
├── doc/prd/${feature}.md existe
│   └── Parsear seccion "Criterios de Aceptacion > Funcionales"
├── Plan referencia work item (PROYECTO-XX)
│   └── Obtener via doc/plans/${feature}_plan.md
└── No se encuentra PRD
    └── Continuar SIN AC-XX linkage (campo ac_ids sera [])
    └── WARNING: "No PRD found. Feedback will be created without AC-XX linkage."
```

### 1.2 Mostrar AC-XX disponibles

Si se encontro PRD, listar los AC-XX con sus descripciones para que el usuario pueda seleccionar.

Si ya existe `acceptance-report.json`, mostrar tambien el status actual de cada AC-XX:

```
AC-XX disponibles:
  AC-01: Usuario puede crear propiedad [PASS]
  AC-02: Validacion inline al perder foco [PASS]
  AC-03: Preview de factura con zoom [PASS]
```

---

## Paso 2: Recopilar Feedback del Desarrollador

### 2.1 Informacion requerida

Preguntar interactivamente (a menos que se proporcione inline con --ac y --severity):

| Campo | Obligatorio | Ejemplo |
|-------|:-----------:|---------|
| **description** | Si | "El boton de factura abre un PDF en vez de mostrar preview inline con zoom" |
| **expected** | Si | "Preview inline del PDF con controles de zoom y pan, embebido en la pagina" |
| **actual** | Si | "Se abre una nueva pestana con el PDF raw sin controles de zoom" |
| **severity** | Si | `critical` / `major` / `minor` |
| **ac_ids** | No | `["AC-03", "AC-05"]` (seleccionar de la lista del Paso 1) |
| **screenshot_path** | No | `./screenshots/invoice-bug.png` (path relativo o absoluto) |
| **steps_to_reproduce** | No | Lista de pasos para reproducir |

### 2.2 Validar severity

| Severity | Criterio | Efecto en merge |
|----------|----------|-----------------|
| `critical` | Funcionalidad principal rota, crash, data loss | **BLOQUEA** merge |
| `major` | Funcionalidad secundaria rota, UX grave | **BLOQUEA** merge |
| `minor` | Cosmetico, texto incorrecto, mejora visual | NO bloquea (warning) |

### 2.3 Validar AC-XX

Si el usuario proporciono --ac AC-XX:
- Verificar que el AC-XX existe en el PRD o acceptance-report.json
- Si no existe → WARNING y preguntar si continuar sin linkage

---

## Paso 3: Asignar ID al Feedback

### 3.1 Calcular siguiente FB-NNN

```bash
existing=$(ls .quality/evidence/${feature}/feedback/FB-*.json 2>/dev/null | wc -l | tr -d ' ')
next_id=$(printf "FB-%03d" $((existing + 1)))
```

### 3.2 Timestamp

```bash
timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
```

---

## Paso 4: Crear Archivo de Feedback Local

### 4.1 Guardar JSON

Archivo: `.quality/evidence/${feature}/feedback/${next_id}.json`

```json
{
  "id": "FB-001",
  "feature": "{feature}",
  "timestamp": "2026-03-01T14:30:00Z",
  "reporter": "developer",
  "severity": "critical",
  "status": "open",
  "ac_ids": ["AC-03"],
  "description": "Invoice detail shows PDF open button instead of inline preview",
  "expected": "Inline PDF preview with zoom and pan controls embedded in the page",
  "actual": "Opens a new tab with raw PDF without zoom controls",
  "steps_to_reproduce": [
    "Navigate to Invoices list",
    "Click on any invoice",
    "Click 'View PDF' button"
  ],
  "screenshot": "feedback/FB-001-screenshot.png",
  "github_issue": null,
  "invalidates_acceptance": true,
  "resolution": null,
  "resolved_at": null
}
```

### 4.2 Copiar screenshot (si se proporciono)

Si `screenshot_path` fue proporcionado:
```bash
cp "${screenshot_path}" ".quality/evidence/${feature}/feedback/${next_id}-screenshot.png"
```

Si no se proporciono screenshot → `"screenshot": null`

### 4.3 Determinar `invalidates_acceptance`

```
SI ac_ids no esta vacio:
  SI acceptance-report.json existe:
    SI algun AC-XX referenciado tiene status "PASS":
      invalidates_acceptance = true
      WARNING: "Este feedback invalida un criterio previamente ACCEPTED."
    SI todos los AC-XX referenciados ya tienen status "FAIL":
      invalidates_acceptance = false
      INFO: "Los criterios referenciados ya estaban en FAIL."
  ELSE:
    invalidates_acceptance = true (precaucion)
ELSE (sin AC-XX linkage):
  invalidates_acceptance = false
  SI severity == "critical":
    invalidates_acceptance = true (un critical sin AC-XX linkage aun bloquea)
```

---

## Paso 5: Crear GitHub Issue

### 5.1 Pre-condicion

Si no se detecto remote en Paso 0.3 → saltar este paso. `"github_issue": null`.

### 5.2 Construir titulo y body

**Titulo**: `[FB-{NNN}] [{severity}] {description_short} ({feature})`
Max 100 caracteres. Truncar description si necesario.

**Body**:
```markdown
## Developer Feedback: FB-{NNN}

**Feature**: {feature}
**Severity**: {severity}
**Date**: {timestamp}
**Acceptance Criteria**: {ac_ids o "N/A"}

### Expected Behavior
{expected}

### Actual Behavior
{actual}

### Steps to Reproduce
{steps_to_reproduce o "Not provided"}

### Screenshot
{Si hay screenshot: adjuntar referencia. Si no: "Not provided"}

### Impact on Acceptance
{Si invalidates_acceptance: "⚠️ This feedback invalidates previously ACCEPTED criteria: {ac_ids}. Merge is blocked until resolved."}
{Si no: "No direct impact on acceptance criteria."}

---
Filed by [SpecBox Engine](https://github.com/jesusperezdeveloper/specbox-engine) `/feedback`
```

### 5.3 Labels

```
labels: ["feedback", "{severity}"]
```

### 5.4 Crear issue via MCP

Usar `mcp__github__create_issue` con owner, repo, title, body, labels.

### 5.5 Actualizar JSON local

Tras crear el issue, actualizar `${next_id}.json`:
```json
"github_issue": {"number": N, "url": "https://github.com/{owner}/{repo}/issues/{N}"}
```

Si falla la creacion del issue:
- WARNING: "No se pudo crear GitHub issue. Evidencia local guardada."
- `"github_issue": null`
- NO bloquear el flujo

---

## Paso 6: Actualizar Estado del Pipeline

### 6.1 Actualizar acceptance-report.json (si aplica)

Solo si `invalidates_acceptance == true` Y `acceptance-report.json` existe:

Para cada AC-XX referenciado en ac_ids con status "PASS":
- Cambiar `"status": "PASS"` → `"status": "INVALIDATED"`
- Agregar campo `"invalidated_by": "FB-{NNN}"`
- Agregar campo `"invalidated_at": "{timestamp}"`

Recalcular summary:
- Si antes era ACCEPTED y ahora hay criterios INVALIDATED → cambiar verdict a `"INVALIDATED"`
- Actualizar `blocking_criteria` con los criterios invalidados

### 6.1a Reflejar la invalidación en el board (FreeForm + MCP remoto)

> **Contrato de tracking I/O (UC-660/661)**: cuando el backend del proyecto es
> FreeForm **y** el MCP server es remoto (`SPECBOX_ENGINE_MCP_URL` definido), el
> server NO puede leer ni escribir `doc/tracking/items.json` del cliente. Toda
> mutación del board debe ir por el **bridge** `.claude/hooks/lib/mcp-client-io.mjs`
> con content-passing — nunca pasando `project_path` como ruta de filesystem del
> server. Este es el patrón canónico que `/feedback`, `/prd` e `/implement` deben
> seguir al mutar FreeForm.

Aplica **solo** si `invalidates_acceptance == true`, el backend es FreeForm, y
hay un UC asociado al feature en el board. Si el backend es Trello/Plane/Native,
o el MCP es local, usar las tools directamente sin el bundle (el server resuelve
el almacenamiento). Si no hay UC en el board para el feature, omitir este paso.

Procedimiento (round-trip de 3 pasos):

```bash
# 1) Leer el items.json local como string vía el bridge (resuelve la raíz del
#    repo con git rev-parse, aplica el guard de path-traversal).
ITEMS=$(node -e "
  import('./.claude/hooks/lib/mcp-client-io.mjs').then(m =>
    process.stdout.write(m.readTrackingBundle())
  );
")
```

```
# 2) Llamar la tool de mutación con content-passing. Por cada AC-XX invalidado,
#    marcarlo no-completado en el board para que el estado refleje el feedback;
#    opcionalmente mover el UC a un estado bloqueado si el feedback es
#    critical/major. Pasar items_content=<ITEMS> y capturar el items_content
#    mutado que la tool devuelve.
mark_ac(uc_id=<UC>, ac_id="AC-03", completed=false, items_content=<ITEMS>)
   → devuelve { ..., items_content: "<items.json mutado>" }
```

```bash
# 3) Persistir el string mutado de vuelta al disco del cliente vía el bridge.
node -e "
  const mutated = process.env.MUTATED_ITEMS;
  import('./.claude/hooks/lib/mcp-client-io.mjs').then(m =>
    m.writeTrackingBundle(mutated)
  );
"
# (pasar el items_content devuelto por env MUTATED_ITEMS para evitar quoting)
```

Reglas:
- **Nunca** llamar la tool con `project_path` apuntando a una ruta del cliente:
  en remoto el server resolvería contra su propio FS (bug raíz de v6.7.0 #82).
- El bridge es la **única** puerta: no hacer `Read`/`Write` directos sobre
  `doc/tracking/items.json` desde la skill.
- Fire-and-forget defensivo: si el round-trip falla, la evidencia local
  (`acceptance-report.json`, `FB-*.json`) ya está guardada y es la fuente de
  verdad del gate de merge; reportar WARNING y continuar sin bloquear el flujo.

### 6.2 Crear/actualizar feedback-summary.json

Archivo: `.quality/evidence/${feature}/feedback-summary.json`

Leer todos los `FB-*.json` del directorio y agregar:

```json
{
  "feature": "{feature}",
  "last_updated": "ISO",
  "total": 3,
  "open": 2,
  "resolved": 1,
  "by_severity": {
    "critical": 1,
    "major": 1,
    "minor": 0
  },
  "blocking": true,
  "blocking_ids": ["FB-001", "FB-002"],
  "invalidated_criteria": ["AC-03"]
}
```

Campo `blocking`: `true` si hay algun feedback open con severity "critical" o "major".
Campo `blocking_ids`: lista de FB-NNN que son open + critical/major.
Campo `invalidated_criteria`: union de ac_ids de todos los FB-NNN con invalidates_acceptance=true y status=open.

---

## Output Final

```
## Feedback Registrado

**ID**: FB-{NNN}
**Feature**: {feature}
**Severity**: {severity}
**AC-XX afectados**: {ac_ids o "Ninguno"}

### Evidencia local
`.quality/evidence/{feature}/feedback/FB-{NNN}.json`

### GitHub Issue
{url del issue o "No creado (sin remote)"}

### Impacto en Acceptance
{Si invalidates_acceptance: "⚠️ El veredicto de AG-09b ha sido INVALIDATED. AC-XX cambiados a INVALIDATED. El merge esta bloqueado hasta resolver este feedback."}
{Si no: "Sin impacto directo en acceptance gate."}

### Siguiente paso
- Corregir el problema y ejecutar `/feedback resolve FB-{NNN}`
- O re-ejecutar `/implement` que re-evaluara los criterios
```

---

## Sub-comando: /feedback resolve FB-{NNN}

### Paso R.1: Localizar feedback

```bash
cat .quality/evidence/${feature}/feedback/FB-{NNN}.json
```

Si no se proporciono feature → buscar FB-{NNN}.json en todos los features:
```bash
find .quality/evidence/ -name "FB-{NNN}.json" 2>/dev/null
```

### Paso R.2: Validar resolucion

Preguntar al desarrollador:
- "¿El problema fue corregido? Describe brevemente la resolucion."

### Paso R.3: Actualizar feedback JSON

Modificar `FB-{NNN}.json`:
```json
{
  "status": "resolved",
  "resolution": "{descripcion de la resolucion}",
  "resolved_at": "ISO timestamp"
}
```

### Paso R.4: Actualizar acceptance-report.json

Si el feedback tenia `invalidates_acceptance: true` y AC-XX fue INVALIDATED por este feedback:
- Cambiar status del AC-XX de "INVALIDATED" a "NEEDS_REVALIDATION"
- Esto indica que AG-09b debe re-ejecutarse para confirmar

**IMPORTANTE**: NEEDS_REVALIDATION no es PASS. El merge sigue bloqueado hasta que AG-09b re-valide.

### Paso R.5: Actualizar feedback-summary.json

Recalcular contadores (total, open, resolved, blocking, blocking_ids, invalidated_criteria).

### Paso R.6: Cerrar GitHub issue

Si `github_issue` no es null:

```bash
gh issue comment {number} --body "✅ Resolved: {resolution}

Marked as resolved by SpecBox Engine \`/feedback resolve\`"

gh issue close {number}
```

### Paso R.7: Output

```
## Feedback Resuelto

**ID**: FB-{NNN}
**Resolucion**: {resolution}
**GitHub Issue**: Cerrado ({url})

### Estado del pipeline
{Si quedan feedback blocking: "Aun hay {N} feedback abiertos bloqueando merge: {blocking_ids}"}
{Si no quedan blocking: "No hay feedback bloqueante. AC-XX en NEEDS_REVALIDATION — ejecutar /implement para re-validar."}
```

---

## Sub-comando: /feedback list [feature]

### Paso L.1: Resolver feature

Si se proporciona feature → usar ese.
Si no → detectar desde rama actual (misma logica que Paso 0.1).

### Paso L.2: Listar feedback

Leer `feedback-summary.json` y todos los `FB-*.json`:

```
## Feedback: {feature}

| ID | Severity | AC-XX | Status | GitHub | Descripcion |
|----|----------|-------|--------|--------|-------------|
| FB-001 | critical | AC-03 | open | #42 | Preview PDF no funciona |
| FB-002 | major | AC-01 | resolved | #43 | Error en creacion |
| FB-003 | minor | — | open | #44 | Typo en label |

**Bloqueantes**: FB-001 (critical)
**Criterios invalidados**: AC-03
```

Si no hay feedback → "No hay feedback registrado para '{feature}'."

---

## Checklist

- [ ] Feature detectado (de argumento o rama)
- [ ] PRD localizado (si existe) y AC-XX listados
- [ ] Feedback recopilado (description, expected, actual, severity)
- [ ] FB-NNN ID asignado secuencialmente
- [ ] JSON guardado en .quality/evidence/{feature}/feedback/
- [ ] Screenshot copiado (si proporcionado)
- [ ] GitHub issue creado con labels correctos
- [ ] JSON actualizado con github_issue URL
- [ ] acceptance-report.json actualizado si invalidates_acceptance
- [ ] board reflejado vía bridge si FreeForm+remoto e invalidates_acceptance (Paso 6.1a)
- [ ] feedback-summary.json creado/actualizado
- [ ] Output final con impacto en acceptance reportado

---

## Referencia rapida

| Accion | Comando |
|--------|---------|
| Nuevo feedback | `/feedback [feature]` |
| Con metadata | `/feedback feature --ac AC-03 --severity critical` |
| Resolver | `/feedback resolve FB-001` |
| Listar | `/feedback list [feature]` |
| Severity que bloquea | critical, major |
| Severity que no bloquea | minor |
| Evidencia local | `.quality/evidence/{feature}/feedback/` |
| Resumen agregado | `.quality/evidence/{feature}/feedback-summary.json` |

More General & Other skills

← All General & Other skills

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY