---
id: collect-visual-evidence
agent: qa
title: Coletar evidência visual (EvidenceManifest)
inputs: [story, rotas, viewports]
outputs: [.nexus/evidence/<story>/evidence-manifest.json, capturas .png]
elicit: false
modes: [interactive, yolo]
---

# Coletar evidência visual (EvidenceManifest)

**Objetivo:** produzir prova VISUAL verificável de que a UI da story realmente renderiza e se comporta
como afirmado — capturas das rotas alteradas em cada viewport, com hash — reunidas num
`evidence-manifest.json` (contrato `EvidenceManifest`, ADR-E5). O motor valida o manifesto (arquivo
existe + hash bate); a Quinn julga o conteúdo. Sem app rodando, não há evidência: o veredito é
**BLOCKED honesto**, nunca um PASS no escuro.

**Pré-condições:**
- A story tem superfície visual (rotas/telas alteradas). Story puramente de backend/CLI não usa esta
  task — a evidência dela é teste verde + log, não screenshot.
- Existe um comando para subir o app (dev server / preview) e as rotas a capturar estão definidas
  (da story ou do frontend-spec). Sem rotas, não há o que capturar — pergunte, não invente.

## Passos

1. **Suba o app.** Inicie o servidor de preview e espere ficar pronto. **Se o app não sobe** (erro de
   build, porta ocupada, crash no boot) → PARE: o veredito é **BLOCKED** com o log do erro. UI que não
   inicia não tem evidência a coletar — e isso é um achado, não um contratempo.
2. **Defina a matriz de captura.** Para cada rota alterada × cada viewport-alvo (ex.: `375×812` mobile,
   `768×1024` tablet, `1440×900` desktop), uma captura. Estados que a AC menciona (vazio, carregando,
   erro, hover, acordeão aberto) são capturas próprias — o "antes/depois" de uma interação são dois
   arquivos, não um.
3. **Capture com o browser real.** Navegue até a rota, ajuste o viewport, aguarde a rede/estado
   estabilizar e tire o screenshot em disco sob `.nexus/evidence/<story>/`. Console com erro durante a
   captura é achado — anexe junto (encadeia `*console-check`). Captura não é "abri e pareceu ok": é o
   arquivo salvo.
4. **Calcule o hash.** Para cada arquivo, compute o SHA-256 do conteúdo. O hash é o que torna a
   evidência à prova de troca silenciosa: o motor recusa manifesto cujo hash não bate com o arquivo.
5. **Escreva o manifesto.** Grave `.nexus/evidence/<story>/evidence-manifest.json` conforme o contrato
   `EvidenceManifest`: `storyId` + `capturas[]`, cada uma com `rota`, `viewport`, `arquivo`,
   `timestamp`, `sha256`. Manifesto sem nenhuma captura para uma story visual é FAIL, não vazio ok.
6. **Devolva para o gate.** As capturas viram `evidenceRefs` no `<verdict>` da Quinn. É a Quinn que
   julga se a evidência sustenta o "pronto" — esta task só a produz de forma honesta e verificável.

## Critério de pronto (DoD)

- [ ] App subiu (ou BLOCKED registrado com o log real do erro de boot)
- [ ] Toda rota alterada × viewport-alvo capturada; estados de AC como capturas próprias
- [ ] Cada arquivo existe em `.nexus/evidence/<story>/` e tem SHA-256 calculado
- [ ] `evidence-manifest.json` válido contra o contrato `EvidenceManifest` (parseia, hashes batem)
- [ ] Erros de console durante a captura anexados como achado, não descartados

## Falha / recuperação

- **App não sobe** → BLOCKED com o log; não há evidência a inventar. É a resposta correta do gate.
- **Rota alterada sem captura** → manifesto incompleto = FAIL; a cobertura declarada tem de bater com a
  real (declarado=real vale para evidência também).
- **Hash não bate com o arquivo** → o motor recusa o manifesto (fail-closed); recapture, não edite o
  JSON à mão.
- **Sem viewports/rotas definidos** → pergunte à story/frontend-spec; capturar "o que der" não é
  evidência, é ruído.
