Painel Local — Cypress Core

Documenta o painel (painel-local/, npm run painel): o que ele é, pra que serve, e como cada aba funciona. Não confundir com estrategia-de-testes.md (o que a suíte cobre) ou triagem-de-falhas.md (o processo de investigar uma falha) — este documento é sobre a ferramenta, não sobre o produto nem sobre o processo.

O que é

Uma interface web local ("Painel de Controle - Cypress") que reúne, num lugar só, as ações do dia a dia de quem mantém esta suíte: rodar specs sem decorar comando de terminal, ver o relatório da última execução, consultar a documentação do projeto, e transformar uma falha capturada automaticamente em Story/Bug/comentário no Azure DevOps — sem digitar nada à mão duas vezes.

Não é um serviço, não fica no ar sozinho, não roda em produção nem em CI: é um servidor Node comum (painel-local/server.js), escutando só em 127.0.0.1:4737 (nunca na rede), que você sobe quando precisa e fecha quando termina. Não salva nada por conta própria — relê package.json, cypress/e2e/, docs/falhas-pendentes.md e docs/historico-de-falhas.md a cada requisição, e publica no Azure DevOps na hora, sem cache/banco local.

Como rodar

npm run painel

Abre sozinho http://localhost:4737 no navegador padrão.

Aba Dashboard

Primeira aba do painel — visão geral do mês antes de decidir o que rodar. Reorganizada em 04/09/2026 pra seguir a estrutura de um layout de referência que o usuário aprovou (subheader + linha de KPIs + grade de cards + tabela) — mantendo a regra de sempre: todo número aqui é real, calculado a partir de dashboard-execucoes.md e historico-de-falhas.md, sem banco/estado próprio. Onde o layout de referência mostrava algo sem equivalente real no projeto (branch/commit/autor por execução, um painel "Azure Backlog" com sincronização própria, duração média de suíte — nada disso é rastreado hoje), o widget foi trocado por algo que a gente realmente tem, em vez de inventar número.

Cada gráfico/lista mostra uma mensagem própria quando não há dado suficiente no mês (em vez de gráfico vazio/quebrado). Botão "🔄 Atualizar Telemetria" relê tudo do zero.

Os 2 donuts (montarDonutHtml(), painel-local/client.js) são SVG puro desenhado à mão, sem lib de gráfico — trocado do Chart.js em 04/09/2026 (sugestão de layout do Stitch: anel com buraco no centro e glow por segmento via drop-shadow na própria cor, não Chart.js/canvas). Chart.js foi removido do projeto inteiro (não sobrou outro uso). Os 4 cartões desta linha (2 donuts + Módulos + Work Items recentes) têm sempre a mesma altura — a do maior — de propósito (pedido do usuário, mesmo dia): .grid-dashboard usa align-items no padrão (stretch), não start.

docs/dashboard-execucoes.md

Tabela alimentada sozinha pelo hook after:run do Cypress (cypress.config.js) — toda execução via cypress run (headless; cypress open não dispara after:run) vira uma linha nova, sucesso ou falha, com data, qual script do package.json foi usado (detectado comparando o conjunto de specs que rodou contra o conjunto que cada cy:run* cobre — não dá pra ler isso do process.argv dentro do processo do Cypress, ele não reflete o comando original do terminal), total/aprovados/reprovados e quais specs tiveram falha. Igual a falhas-pendentes.md: não editar à mão, é fato bruto que o Dashboard consome. Versionado (vai pro git) — é histórico, não cache local.

Aba Execução

Roda specs sem precisar lembrar o comando exato. Reorganizada em 04/09/2026 (a versão anterior — 3 colunas de larguras desiguais, um console sempre aberto do lado espremendo o conteúdo — foi considerada "bagunçada" pelo usuário; esta é a 2ª tentativa, com um mockup interativo aprovado antes de mexer no código de verdade):

Visual (04/09/2026)

Paleta, tipografia e componentes (topbar, chips, badges, console) adaptados de um design system de referência que o usuário aprovou ("Precision Engineering Dashboard" — zinc scale neutra + azul/verde/âmbar/vermelho só pra estado de execução, fontes Geist/Inter/JetBrains Mono via Google Fonts, raios pequenos 4/6/8px, bordas finas no lugar de sombra). Dois detalhes ficam ao vivo, não decorativos:

Badges e status (✅/❌/⚠️/🔗 antigos) viraram um indicador de 6px colorido (.dot, classes dot-verde/dot-amarelo/dot-vermelho/dot-azul/dot-cinza) + texto — mesmo padrão pros 6 lugares que mostram estado (badge "já reportado", badge "demanda aprovada", badge "cria dado real", resultado de teste em "Rodar por demanda", status do console). Ícones decorativos em botões (🔎 busca, 🧹 limpar, 🔄 atualizar, ⛶ tela cheia etc.) não foram trocados — decisão de escopo, não pedido explícito do usuário; dá pra revisitar depois se quiser ir mais longe.

Tema claro/escuro

Botão 🌙/☀️ no cabeçalho alterna o tema — aplicado via atributo data-tema na tag <html> (index.html) e persistido em localStorage. Escuro é o padrão (pedido do usuário, 04/09/2026 — não olha mais prefers-color-scheme do sistema) pra quem nunca trocou antes; quem trocar pra claro tem isso lembrado nas próximas visitas. Toda cor do painel é uma variável CSS que já responde sozinha à troca; a única exceção cuidada à parte são os donuts da aba Dashboard (montarDonutHtml()), cujo glow por segmento precisa de hex literal (não aceita var()) — carregarDashboard() (client.js) escolhe o hex certo por tema via CORES_STATUS, e o botão de tema força um recarregamento do Dashboard ao trocar. Paleta do tema ESCURO recalibrada em 04/09/2026 (sugestão do Stitch, passo de contraste acessível WCAG AA) — só o escuro, o claro continua o "Precision Engineering Dashboard" de antes. O console de execução (ver acima) fica sempre escuro, nos dois temas — de propósito, mesmo padrão de terminal/log que a maioria das ferramentas de dev mantém independente do tema geral do app. Logo do topbar é painel-local/logo_transparent.png (marca gradiente, sem texto) — funciona nos 2 temas sem precisar de variante separada.

Flag "Modo Dev" (topo, visível em toda aba)

Separa execução de desenvolvimento (rodando um spec novo várias vezes, ajustando seletor) de teste válido de verdade — pedido do usuário, 04/09/2026, pra não furar as métricas do Dashboard nem encher a fila de falhas pendentes com ruído de quem está construindo automação.

Um único toggle (🧪 Modo Dev, pill no topbar, persistido em localStorage) — nunca mistura os 2 universos, é sempre um ou outro:

Nada nunca deixa de ser gravado — docs/dashboard-execucoes.md (coluna Modo, dev/real) e docs/falhas-pendentes.md (linha **Modo:** dev, omitida quando é real) recebem toda execução sempre; o toggle só decide o que aparece. Ausência da marca (linhas de antes dessa flag existir) conta como real.

Mecanicamente: o servidor do painel e o processo do Cypress são processos SEPARADOS (spawn), sem memória compartilhada — só arquivo em disco e o comando de linha. Por isso o toggle acrescenta --env modoDev=true (ou -- --env modoDev=true pros scripts npm run) no comando spawnado (iniciarExecucao, 4 rotas: /api/rodar, /api/rodar-spec, /api/rodar-varios, /api/demanda/rodar), e cypress.config.jsconfig.env.modoDev na hora de gravar cada linha. GET /api/dashboard/GET /api/falhas recebem ?modoDev=true/false refletindo o estado ATUAL do toggle no navegador.

"Work Items no Azure" (KPI, donut, lista publicados) fica de fora de propósito — publicar uma demanda real no Azure é sempre uma ação deliberada, não faz sentido "modo dev" pra isso.

Aba Relatório (Mochawesome)

Mostra o mochawesome-report/ da última execução (gerado por qualquer cypress run disparado na aba Execução) direto num iframe, com botão "🔄 Atualizar" (relê o relatório mais recente) e "⛶ Tela cheia" — útil porque o relatório tem bastante informação por tela e o iframe padrão fica pequeno pra ler confortavelmente. Conteúdo do iframe em si não foi alterado no visual (04/09/2026) — é o relatório real do Mochawesome, fora do controle do painel.

Aba Documentação (HTML)

Mostra o docs/html/ (gerado por npm run docs:build/npm run watch) direto no painel — a mesma documentação que você está lendo agora, sem precisar abrir os arquivos .html à parte. Também tem "🔄 Atualizar" e "⛶ Tela cheia". Mesmo caso da aba Relatório: conteúdo do iframe não mudou no visual.

Aba Azure DevOps

2 sub-abas (mesmo padrão de "Por demanda/Scripts/Cenários específicos" da aba Execução & Specs — adicionado 04/09/2026, pedido do usuário: "sentindo falta de consultar todas as demandas já criadas, não só as mais recentes do Dashboard"):

Callout "Modo Direto" (topo da aba, 04/09/2026): lembra que nada fica salvo localmente e que a publicação vai direto pra API do Azure — o pill "OAuth Token Ativo"/"Sem conexão" ao lado é real, mesma checagem (GET /api/iteracao-atual) que alimenta o pill do topbar.

Categoria do erro (ex.: TIMEOUT, ASSERTION FAILED) antes da data/spec de cada card: não é um campo novo — é tipoDeErro() (client.js) lendo palavras-chave no texto REAL do erro já capturado (nunca um valor à parte que poderia divergir do que está no <pre> abaixo).

Badge "🔗 Já reportado": aparece antes do título de uma falha sempre que aquele MESMO teste (título exato) já virou Story/Bug/Task ou já foi comentado num item existente antes — reconhece sozinho uma recorrência, sem precisar abrir o Azure pra conferir. Funciona lendo uma tabela dedicada em historico-de-falhas.md ("Work Items do Azure DevOps vinculados"), que o próprio painel preenche sozinho toda vez que uma publicação tem sucesso — não precisa (nem deve) editar essa tabela na mão.

Falha sai da fila sozinha ao publicar: assim que Story/Bug/Task/comentário publica com sucesso, o painel também remove aquela entrada de docs/falhas-pendentes.md — a partir daquele momento o teste já tem número de demanda no Azure, não precisa mais ficar pendente ali (regra em CLAUDE.md: um achado que já é bug confirmado do Core, mas ainda sem número de demanda, fica de propósito na fila até esse momento — é diferente de "ainda não foi investigado").

"✕ Ignorar" / "🗑 Ignorar todos" (09/09/2026, pedido do usuário: "precisa ter uma forma de limpar pela tela mesmo"): removem entrada(s) de docs/falhas-pendentes.md sem publicar nada no Azure — diferente de "Falha sai da fila sozinha ao publicar" acima, que só acontece depois de um Story/Bug/Task/comentário real. "Ignorar" tira só a falha aberta no momento (POST /api/falhas/ignorar, reaproveita a mesma removerFalhaPendenteSeExistir() usada pela publicação — mesmo critério de match, título exato do teste); "Ignorar todos" tira a fila inteira do modo (Dev/Real) que está sendo visto (POST /api/falhas/ignorar-todos, removerTodasFalhasPendentes() em server.js) — nunca mistura os 2 universos, mesmo critério da flag "Modo Dev" (ver abaixo). Os 2 pedem confirmação (confirm() do navegador) antes de agir, e nenhum dos 2 cria linha em historico-de-falhas.md nem vínculo na tabela de Work Items — "ignorar" é "não preciso ver isso agora", não "já investiguei/reportei". Se o mesmo teste falhar de novo numa execução futura, a captura automática (cypress/support/e2e.js) registra uma entrada nova sozinha, do zero — nada fica "silenciado pra sempre" por ter sido ignorado antes.

Badge "⚠️ Demanda em 'X' — teste ainda falha": aparece junto do badge acima quando o work item vinculado já está num estado avançado (Testing/Validation/Deployment/Closed) mas o teste continua falhando de verdade — sinal de que a correção pode não ter chegado neste ambiente ainda, ou é regressão. O painel consulta o estado ao vivo na API do Azure toda vez que a aba carrega (não fica só no que foi salvo na hora do vínculo) — se a consulta falhar (PAT ausente, rede fora), simplesmente não mostra o badge, sem quebrar o resto da lista.

Botão "✨ Análise IA" (formulário de Story/Bug/Task/comentário, 09/09/2026): preenche automaticamente Motivo do retorno, Comportamento esperado/encontrado, Passos para reproduzir e Exemplo, chamando o Gemini (POST /api/ia/analisarscripts/gemini-ia.js) com o teste, o erro e o conteúdo real do spec (lido do disco pelo servidor, nunca inventado). Só preenche os campos — não publica nada sozinho, sempre revisar antes de "✓ Confirmar e publicar". Precisa de cypress.env.jsongemini.apiKey configurada (ver CLAUDE.md pra detalhe do modelo usado e como gerar a key); sem isso, o botão mostra o erro de config e os campos continuam editáveis manualmente como antes. Reverte a decisão de 03/09/2026 de não automatizar — aquela rejeitava especificamente a API da Anthropic, por exigir faturamento separado do Claude Code; o Gemini tem free tier sem cartão. Pedir formatação direto no chat com o Claude Code continua funcionando como alternativa (útil sem a key configurada, ou pra um texto mais elaborado).

Onde fica o código

Arquivo Papel
painel-local/server.js Toda a lógica — lê disco, valida, chama scripts/azure-devops.js, serve os arquivos estáticos e as pastas geradas (mochawesome-report/, docs/html/)
painel-local/index.html Estrutura das abas + estilo
painel-local/client.js Front-end sem framework (busca, renderização dos cards, chamadas fetch pra API do próprio painel)

Reaproveita 100% scripts/azure-devops.js pra tudo que é Azure DevOps — a lógica de autenticação/API mora lá, o painel só é a interface.

Fonte: construído incrementalmente ao longo de 03/09/2026, sessão a sessão, junto com quem usa — ver CLAUDE.md, seção "Manter o painel local em dia", pra decisões descartadas no caminho (ex.: botão de IA paga) e detalhe técnico de cada mecanismo automático.