W2: Claude Code + GSD
Get Shit Done — o framework de desenvolvimento estruturado para times. Fases definidas, milestones rastreados, PM integrado nos gates, e testes como cidadão de primeira classe.
O que é GSD
GSD (Get Shit Done) é um plugin de skills para Claude Code que transforma o agente em um co-desenvolvedor com estrutura de projeto real. Onde o workflow Solo é livre-forma, o GSD introduz fases, milestones, gates de qualidade e integração com PM — sem tolher a criatividade técnica do desenvolvedor.
Instalação
# Instalar o plugin GSD via marketplace de skills
/plugin marketplace add gsd
# Verificar instalação
/gsd:help
# Inicializar um projeto novo
/gsd:new-projectFilosofia
O GSD parte de uma premissa simples: Claude Code é capaz de executar qualquer tarefa de desenvolvimento, mas sem estrutura, a execução livre gera desvios, retrabalho e entregas que não correspondem ao que o PM aprovou. O GSD resolve isso com um ciclo de fases explícitas:
- Discuss — entrevista o dev e o PM antes de qualquer linha de código
- Plan — pesquisa, arquitetura e quebra em tasks atômicas
- UI Phase — gera contrato visual antes de implementar frontend
- Execute — implementação wave-based com TDD embutido
- Verify — validação funcional e aprovação de PM
- Ship — PR, review automatizado e deploy
Use GSD quando: a feature tem mais de 1 dia de implementação, envolve mais de um dev ou PM, requer integrações com sistemas externos, ou exige rastreabilidade de decisões. Para tarefas triviais (<2h, sem risco), o workflow Solo é mais eficiente.
Quando NÃO usar
Hotfixes urgentes, experimentos descartáveis e protótipos de validade de hipótese não precisam de GSD. O overhead das fases Discuss e Plan é justificado apenas quando o custo do retrabalho supera o custo do planejamento.
Diagrama do Workflow GSD
O fluxo completo do GSD, desde o PRD do PM até o deploy em produção. Cada nó representa um comando ou gate de qualidade explícito.
Workflow GSD completo: do PRD ao deploy, com gates de qualidade e integração PM em cada transição de fase.
Comandos GSD por Fase
Cada fase do GSD tem um comando dedicado com comportamento e output bem definidos. Entender o que cada comando faz — e quando usá-lo — é o que diferencia um uso superficial de um uso efetivo do framework.
/gsd:new-project
Fase: Inicialização | Output: estrutura de diretórios GSD, CLAUDE.md configurado, roadmap de milestones
/gsd:new-project
# Claude pergunta:
# - Nome e descrição do projeto
# - Stack técnico
# - Milestones planejados
# - PM e devs envolvidos
#
# Gera:
# .gsd/
# PROJECT.md — contexto permanente do projeto
# milestones/ — um diretório por milestone
# phases/ — fases do milestone atual
# CLAUDE.md — atualizado com regras GSD + stack/gsd:discuss-phase
Fase: Discovery | Output: ASSUMPTIONS.md com gaps, riscos e decisões capturadas
/gsd:discuss-phase
# Claude conduz entrevista adaptativa com o dev:
# - Qual o objetivo de negócio desta fase?
# - Quais são os critérios de aceite do PM?
# - Há dependências externas ou bloqueadores?
# - Qual é a abordagem técnica preferida?
#
# Output: ASSUMPTIONS.md
# ## Entendimento
# ## Critérios de aceite
# ## Riscos identificados
# ## Decisões tomadas
# ## Perguntas em aberto para o PM/gsd:plan-phase
Fase: Planejamento | Output: RESEARCH.md + PLAN.md com tasks atômicas e critérios de conclusão
/gsd:plan-phase
# Claude pesquisa antes de planejar:
# 1. Analisa codebase existente (padrões, dependências)
# 2. Pesquisa abordagens técnicas para o problema
# 3. Documenta decisões de arquitetura em RESEARCH.md
#
# Depois quebra em PLAN.md:
# - Tasks atômicas (cada uma com critério de done)
# - Sequência de implementação (domain-first)
# - Estimativa de waves necessárias
# - Dependências entre tasks# PLAN.md — Fase 1.2: Sistema de Notificações
## Tasks
### T1: Domain layer
- [ ] Criar entidade Notification (id, userId, type, payload, readAt)
- [ ] Criar NotificationRepository interface (port)
- [ ] Testes unitários da entidade
Critério: `vitest run --testPathPattern='notification.unit'` passa
### T2: Persistence adapter
- [ ] Implementar PostgresNotificationRepository
- [ ] Migration Prisma: tabela notifications
- [ ] Testes de integração com DB real
Critério: `vitest run --testPathPattern='notification.integration'` passa
### T3: WebSocket adapter
- [ ] Implementar WebSocketNotificationService
- [ ] Handler de conexão e broadcast
- [ ] Testes de integração com socket mock
Critério: cobertura >= 80% no adapter/gsd:ui-phase
Fase: Design (apenas projetos com frontend) | Output: UI-SPEC.md com contrato visual completo antes de implementar
/gsd:ui-phase
# Gera UI-SPEC.md com:
# - Componentes necessários (lista com props)
# - Layout e responsividade
# - Estados (loading, empty, error, populated)
# - Interações e animações
# - Tokens de design a usar
#
# PM aprova UI-SPEC.md ANTES de execute-phase
# Evita retrabalho de "não era bem isso que eu imaginei"/gsd:execute-phase
Fase: Implementação | Output: código funcionando + testes passando, por waves
/gsd:execute-phase
# Executa tasks do PLAN.md em waves:
# Wave 1: domain core + ports (sem dependências externas)
# Wave 2: adapters (DB, HTTP, WebSocket)
# Wave 3: testes unitários + integração
# Wave 4: verificação (lint, type-check, testes)
#
# Entre waves pesadas: /compact automático
# Cada wave é idempotente — pode ser re-executada
# Falhas são documentadas em BLOCKERS.md/gsd:verify-work
Fase: Validação | Output: relatório de qualidade + URL de preview para PM
/gsd:verify-work
# Executa a pirâmide de testes completa:
# 1. npm run lint && npx tsc --noEmit
# 2. vitest run --testPathPattern='*.unit.test'
# 3. vitest run --testPathPattern='*.integration.test'
# 4. npx cypress run --headless
# 5. k6 run k6/load.js
#
# Gera VERIFY-REPORT.md com resultados
# Abre preview URL para revisão do PM
# Bloqueia /gsd:ship se algum gate falhar/gsd:ship
Fase: Entrega | Output: PR criado, revisado e pronto para merge
/gsd:ship
# Só executável após /gsd:verify-work com aprovação do PM
#
# Sequência:
# 1. git diff main — review final do diff
# 2. Cria PR com descrição automática (mudanças, testes, decisões)
# 3. Executa /gsd:review — peer review por agente separado
# 4. Aguarda CI passar
# 5. Merge + tag de milestone se fase for a últimanew-project → PROJECT.md, CLAUDE.md | discuss-phase → ASSUMPTIONS.md | plan-phase → RESEARCH.md, PLAN.md | ui-phase → UI-SPEC.md | execute-phase → código + testes | verify-work → VERIFY-REPORT.md | ship → PR merged
Integração com PM
O GSD trata o PM como participante ativo do processo de desenvolvimento, não como receptor passivo de entregas. Há três pontos de contato obrigatórios onde o PM entra no ciclo.
Onde o PM entra no ciclo GSD
| Fase | Papel do PM | Artefato produzido |
|---|---|---|
discuss-phase |
Fornece critérios de aceite; responde perguntas abertas do Claude | ASSUMPTIONS.md validado |
ui-phase |
Aprova UI-SPEC.md antes de qualquer linha de código de UI | UI-SPEC.md com status "aprovado" |
verify-work |
Testa feature no preview URL; aprova ou rejeita com feedback | VERIFY-REPORT.md com decisão do PM |
O que o PM precisa ter antes de iniciar
O GSD falha ruidosamente se o PM chegar com requisitos vagos. Antes de rodar /gsd:new-project, o PM precisa ter documentado:
- Problema de negócio — por que esta feature existe (não o que, o por que)
- Critérios de aceite mensuráveis — "usuário consegue X em menos de Y segundos" é critério; "experiência fluida" não é
- Escopo negativo — o que explicitamente está fora do escopo desta entrega
- Personas afetadas — quem usa a feature e qual é o fluxo principal
- Restrições técnicas conhecidas — integrações obrigatórias, SLAs existentes
Template de PRD mínimo para GSD
# PRD: [Nome da Feature]
**Data:** YYYY-MM-DD | **PM:** [nome] | **Dev lead:** [nome]
## Problema
[1-2 parágrafos: situação atual, por que é um problema, impacto mensurável]
## Solução proposta
[Descrição de alto nível — O QUE, não COMO]
## Critérios de aceite
- [ ] CA-01: [ação do usuário] resulta em [comportamento esperado] em [tempo máximo]
- [ ] CA-02: [condição de erro] exibe [mensagem específica]
- [ ] CA-03: [caso de borda] é tratado com [comportamento]
## Escopo desta entrega (in scope)
- Item 1
- Item 2
## Fora do escopo (out of scope)
- Item A (próximo milestone)
- Item B (decisão separada)
## Métricas de sucesso
- Métrica 1: [baseline atual] → [target após entrega]
- Métrica 2: [como medir]
## Dependências e riscos
- Dependência: [sistema externo / equipe / decisão pendente]
- Risco: [o que pode dar errado] — mitigação: [como evitar]Claude vai identificar lacunas nos critérios de aceite durante o discuss-phase e gerar uma lista de perguntas abertas. O dev não deve avançar para plan-phase enquanto o PM não responder. Este atrito intencional evita que 3 dias de implementação resultem em "não era isso que eu queria".
Testing dentro do GSD
O GSD não trata testes como uma fase separada ao final. Testes são parte integrante do execute-phase, escritos na mesma wave em que o código de produção é escrito — TDD como default, não como opção.
Como o execute-phase incorpora TDD
O executor GSD recebe instrução explícita no CLAUDE.md do projeto para seguir o ciclo Red-Green-Refactor em cada task do PLAN.md:
# .gsd/CLAUDE.md — regras de execução injetadas pelo GSD
## Regras de implementação (não negociáveis)
### TDD obrigatório
Para cada task do PLAN.md:
1. RED: escreve o teste primeiro — `npm test` deve FALHAR
2. GREEN: implementa o mínimo para o teste passar — `npm test` deve PASSAR
3. REFACTOR: limpa o código sem quebrar — `npm test` ainda deve passar
NUNCA commita código sem teste correspondente.
NUNCA pula testes por "falta de tempo" — se não tem tempo, reduz escopo.
### Pirâmide de testes
- Unit: domínio isolado, sem IO, < 50ms cada — `*.unit.test.ts`
- Integration: DB real em container, sem mocks de infra — `*.integration.test.ts`
- E2E: apenas jornadas críticas do usuário — `cypress/e2e/*.cy.ts`Configurando gates de teste no GSD
Os gates são configurados no PROJECT.md e executados automaticamente pelo verify-work. Thresholds abaixo do mínimo bloqueiam ship:
# .gsd/PROJECT.md — seção quality gates
## Quality Gates (obrigatórios para /gsd:ship)
| Gate | Comando | Threshold |
|------|---------|-----------|
| Lint | `npm run lint` | zero erros |
| Types | `npx tsc --noEmit` | zero erros |
| Unit | `vitest run --coverage` | cobertura >= 80% |
| Integration | `vitest run --testPathPattern='*.integration'` | 100% pass |
| E2E | `npx cypress run --headless` | 100% pass |
| Security | `npm audit --audit-level=high` | zero high/critical |
| Load | `k6 run k6/load.js` | p95 < 500ms, error rate < 1% |Como instruir o executor GSD a respeitar a pirâmide
A pirâmide é uma restrição de arquitetura, não uma sugestão. O PLAN.md deve especificar o tipo de teste de cada task para que o executor não escolha o caminho mais fácil (sempre E2E, que é lento e frágil):
# Exemplo de task com tipo de teste explícito
### T3: Cálculo de desconto por volume
**Tipo de teste:** unit (lógica de negócio pura, sem IO)
**Arquivo:** `src/domain/pricing/discount.unit.test.ts`
**Cobertura esperada:** 100% dos branches
### T7: Busca de produtos por categoria
**Tipo de teste:** integration (requer DB com fixtures)
**Arquivo:** `src/infra/repositories/product.integration.test.ts`
**Precondição:** container PostgreSQL rodando via docker-compose
### T12: Checkout completo de pedido
**Tipo de teste:** E2E (jornada crítica de usuário)
**Arquivo:** `cypress/e2e/checkout.cy.ts`
**Precondição:** seed de dados no ambiente de stagingOWASP no GSD
Segurança no GSD é tratada de duas formas complementares: como regras transversais no CLAUDE.md (presentes em toda fase de execução) e como gate explícito no verify-work antes do ship.
CLAUDE.md do projeto com regras OWASP
O /gsd:new-project injeta um bloco de segurança padrão no CLAUDE.md, que o executor lê em toda sessão:
# .gsd/CLAUDE.md — bloco de segurança (gerado pelo new-project)
## Regras de segurança OWASP (não negociáveis)
### A01 — Broken Access Control
- Todo endpoint verifica autorização ANTES de acessar recurso
- Testes de autorização: usuário sem permissão deve receber 403, não 404
### A02 — Cryptographic Failures
- Nunca armazena senha em texto plano — bcrypt com salt rounds >= 12
- Secrets apenas em variáveis de ambiente — nunca hardcoded, nunca em logs
### A03 — Injection
- Sempre usa ORM/query builder parametrizado — nunca string concatenation
- Valida e sanitiza inputs com zod/yup antes de qualquer operação
### A04 — Insecure Design
- Arquitetura hexagonal: domínio sem dependências de infra
- Threat model revisado durante discuss-phase para features de auth
### A05 — Security Misconfiguration
- Headers de segurança: CSP, HSTS, X-Frame-Options em produção
- Desabilita endpoints de debug antes do ship
### A06 — Vulnerable Components
- `npm audit --audit-level=high` como gate obrigatório
- Dependências diretas atualizadas; indiretas auditadas
### A07 — Auth & Session Failures
- Tokens JWT com expiração curta (15min access, 7d refresh)
- Invalidação de sessão em logout e troca de senha
### A08 — Integrity Failures
- lockfile (package-lock.json) sempre commitado
- Verificar checksums de dependências críticas
### A09 — Logging & Monitoring Failures
- Logs estruturados (JSON) com correlation ID em todos os requests
- Nunca loga dados pessoais ou tokens
### A10 — SSRF
- Valida e restringe URLs de chamadas de saída a allowlist
- Nunca repassa URL de request externo diretamente para fetch internonpm audit como gate obrigatório
O verify-work bloqueia o ship se npm audit retornar vulnerabilidades de severidade alta ou crítica. Vulnerabilidades moderadas geram warning mas não bloqueiam:
# Gate de segurança no verify-work
npm audit --audit-level=high
# Se retornar vulnerabilidades high/critical:
# 1. Claude lista as dependências afetadas
# 2. Tenta atualizar automaticamente com npm audit fix
# 3. Se não for possível fix automático, documenta em BLOCKERS.md
# 4. /gsd:ship fica bloqueado até resolver
# Exemplo de output quando tudo está ok:
# found 0 vulnerabilities
# Gate SECURITY: PASSEDO GSD não cria uma "fase de segurança" separada porque isso cria o anti-pattern de "segurança como afterthought". As regras OWASP vivem no CLAUDE.md e são aplicadas durante o execute-phase. O gate do verify-work confirma que foram respeitadas — não as implementa tardiamente.
Context Window no GSD
O GSD tem gestão de contexto embutida. O problema clássico de "sessão longa que perde o fio" é tratado estruturalmente, não dependendo de disciplina individual do desenvolvedor.
Como o GSD gerencia contexto automaticamente
O execute-phase monitora o uso de tokens a cada wave. Quando o contexto ultrapassa 70K tokens, executa /compact automaticamente antes de iniciar a próxima wave:
Execute-phase — gestão de contexto por wave
Wave 1 iniciada — contexto: 12K tokens
[implementa domain core]
Wave 1 concluída — contexto: 28K tokens
Wave 2 iniciada — contexto: 28K tokens
[implementa adapters]
Wave 2 concluída — contexto: 55K tokens
Wave 3 iniciada — contexto: 55K tokens
[implementa testes]
Wave 3 concluída — contexto: 74K tokens
AVISO: contexto > 70K tokens
Executando /compact para preservar contexto essencial...
Contexto após compact: 31K tokens
Wave 4 iniciada — contexto: 31K tokens
[verificação e lint]
Wave 4 concluída — contexto: 38K tokensO que o compact preserva
O /compact do GSD é instruído a preservar sempre:
- Tasks concluídas e pendentes do PLAN.md atual
- Decisões de arquitetura e blockers documentados
- Estado atual dos testes (quais passam, quais falham)
- Regras de CLAUDE.md (reinjetadas automaticamente)
O que é descartado no compact: raciocínio intermediário, código já escrito (está em disco), logs de comandos anteriores.
Handoffs entre sessões via arquivos
Nunca in-memory. Todo estado relevante persiste em arquivos no diretório .gsd/phases/. Ao retomar trabalho em uma nova sessão, o GSD relê esses arquivos para reconstituir o contexto:
# Pausar trabalho (fim do dia)
/gsd:pause-work
# Gera .gsd/phases/current/HANDOFF.md com:
# - tasks concluídas, pendentes, bloqueadas
# - contexto necessário para continuar
# - próximo passo recomendado
# Retomar trabalho (próxima sessão)
/gsd:resume-work
# Lê HANDOFF.md e reconstitui contexto
# Não precisa re-explicar o projeto do zeroQuando intervir manualmente
Intervenha manualmente com /compact se Claude começar a contradizer decisões já tomadas, repetir código que já foi escrito, ou ignorar restrições do CLAUDE.md. Estes são sintomas de contexto degradado, não de bugs no GSD.
# Intervenção manual de contexto
/compact "mantém: tasks pendentes do PLAN.md, blockers, regras OWASP, stack técnico"
# Limites recomendados
# Orquestrador GSD: máximo 80K tokens ativos
# Subagente executor: máximo 60K tokens de contexto inicial
# Agente de review: máximo 40K tokens (apenas o diff + PLAN.md)Exemplo Concreto: Notificações em Tempo Real
Um walkthrough completo do ciclo GSD para uma feature real: sistema de notificações em tempo real via WebSocket, com preferências de usuário e marcação de leitura.
PRD mínimo (escrito pelo PM)
# PRD: Sistema de Notificações em Tempo Real
**Data:** 2026-03-29 | **PM:** Ana Costa | **Dev lead:** Bruno Lima
## Problema
Usuários perdem eventos importantes (novos comentários, menções, atualizações de
status) porque o sistema atual só notifica via e-mail, com delay de até 5 minutos.
Taxa de engajamento com notificações por e-mail: 12%. Meta: 45%.
## Solução proposta
Notificações push em tempo real no browser via WebSocket. Painel de notificações
no header com badge de contagem não lida. Preferências por tipo de notificação.
## Critérios de aceite
- [ ] CA-01: notificação aparece no browser do destinatário em < 2s após o evento
- [ ] CA-02: badge mostra contagem correta de não lidas (max "99+")
- [ ] CA-03: clicar em notificação marca como lida e navega para o contexto
- [ ] CA-04: usuário pode desabilitar tipos específicos de notificação
- [ ] CA-05: notificações persistem (usuário offline recebe ao reconectar)
## Fora do escopo
- App mobile (próximo milestone)
- Notificações por SMS
- Notificações em lote (digest diário)
## Métricas de sucesso
- Taxa de engajamento com notificações: 12% → 40%
- Latência de entrega (p95): < 2 segundos
## Dependências
- Backend: Node.js + Socket.IO (já usado em outro módulo)
- DB: PostgreSQL (schema existente)
- Risco: volume de conexões simultâneas — mitigação: Redis adapter para Socket.IOdiscuss-phase output
Claude conduziu entrevista de 12 perguntas com o dev. ASSUMPTIONS.md gerado:
# ASSUMPTIONS.md — Notificações em Tempo Real
## Entendimento
Sistema de notificações WebSocket com persistência. Usuário recebe notificações
em tempo real se online; ao reconectar, recebe as perdidas. Preferências por tipo
são salvas por usuário. Badge no header é atualizado em tempo real.
## Decisões de arquitetura
- Socket.IO com Redis adapter (já disponível na infra)
- Notificações persistidas em PostgreSQL (tabela nova: notifications)
- Frontend: React hook useNotifications() para consumo
- Tipos de notificação: enum no domínio (COMMENT, MENTION, STATUS_CHANGE)
## Critérios de aceite confirmados com PM
- CA-01 a CA-05: confirmados sem alterações
- Adição: CA-06: reconexão automática em até 3 tentativas (5s, 15s, 30s)
## Riscos identificados
- RISCO-01: N conexões simultâneas — mitigação: Redis adapter (já planejado)
- RISCO-02: notificações duplicadas em reconexão — mitigação: idempotency key por evento
## Perguntas em aberto RESOLVIDAS
- Q: quais são os tipos de notificação do MVP? → COMMENT, MENTION, STATUS_CHANGE
- Q: notificações expiram? → sim, após 30 dias
- Q: quem pode enviar notificações? → apenas o sistema (não user-to-user ainda)plan-phase output (tasks exemplo)
# PLAN.md — Fase 2.3: Notificações em Tempo Real
## Estimativa: 3 waves, ~4h de execução
### Wave 1 — Domain layer
- [ ] T1: Entidade Notification com campos e validações (unit test)
- [ ] T2: Enum NotificationType (COMMENT | MENTION | STATUS_CHANGE)
- [ ] T3: Interface NotificationRepository (port)
- [ ] T4: Interface NotificationService (port) com método broadcast()
- [ ] T5: Value Object NotificationPreference (unit test)
Critério wave: `vitest run --testPathPattern='notification.unit'` — 100% pass, cobertura >= 90%
### Wave 2 — Adapters
- [ ] T6: PostgresNotificationRepository (integration test com DB real)
- [ ] T7: Migration Prisma: tabelas notifications + notification_preferences
- [ ] T8: SocketIONotificationService com Redis adapter (integration test)
- [ ] T9: NotificationController (HTTP: GET /notifications, PATCH /notifications/:id/read)
Critério wave: `vitest run --testPathPattern='notification.integration'` — 100% pass
### Wave 3 — Frontend
- [ ] T10: Hook useNotifications() com Socket.IO client (unit test com mock)
- [ ] T11: Componente NotificationBell com badge (UI-SPEC.md aprovado)
- [ ] T12: Painel NotificationList com virtual scroll (até 100 itens sem lag)
- [ ] T13: Página de preferências /settings/notifications
Critério wave: `npx cypress run --spec 'cypress/e2e/notifications.cy.ts'` — CA-01 a CA-06 passexecute-phase com TDD (Wave 1 — exemplo)
// T1 — RED: teste escrito primeiro
// src/domain/notifications/notification.unit.test.ts
import { Notification } from './notification';
import { NotificationType } from './notification-type';
describe('Notification', () => {
it('deve criar notificação válida com todos os campos obrigatórios', () => {
const n = Notification.create({
userId: 'user-123',
type: NotificationType.COMMENT,
payload: { commentId: 'c-456', postId: 'p-789' },
});
expect(n.id).toBeDefined();
expect(n.readAt).toBeNull();
expect(n.createdAt).toBeInstanceOf(Date);
});
it('deve rejeitar payload vazio', () => {
expect(() =>
Notification.create({ userId: 'u-1', type: NotificationType.MENTION, payload: {} })
).toThrow('payload cannot be empty');
});
it('deve marcar como lida com timestamp', () => {
const n = Notification.create({
userId: 'u-1', type: NotificationType.STATUS_CHANGE, payload: { status: 'done' },
});
n.markAsRead();
expect(n.readAt).toBeInstanceOf(Date);
});
});
// npm test -- notification.unit → FALHA (Notification não existe ainda) = RED ✓
// GREEN: implementação mínima
// src/domain/notifications/notification.ts
import { randomUUID } from 'crypto';
import { NotificationType } from './notification-type';
interface NotificationProps {
userId: string;
type: NotificationType;
payload: Record<string, unknown>;
}
export class Notification {
readonly id: string;
readonly userId: string;
readonly type: NotificationType;
readonly payload: Record<string, unknown>;
readonly createdAt: Date;
readAt: Date | null = null;
private constructor(props: NotificationProps) {
if (Object.keys(props.payload).length === 0) {
throw new Error('payload cannot be empty');
}
this.id = randomUUID();
this.userId = props.userId;
this.type = props.type;
this.payload = props.payload;
this.createdAt = new Date();
}
static create(props: NotificationProps): Notification {
return new Notification(props);
}
markAsRead(): void {
this.readAt = new Date();
}
}
// npm test -- notification.unit → PASSA = GREEN ✓
// REFACTOR: extrair validação de payload para método privado (sem quebrar testes)verify-work resultado
# VERIFY-REPORT.md — Notificações em Tempo Real
## Quality Gates
| Gate | Resultado | Detalhe |
|-------------------|-----------------|--------------------------------------|
| Lint | PASSED | 0 erros, 0 warnings |
| TypeScript | PASSED | 0 erros em strict mode |
| Unit tests | PASSED | 47 testes, cobertura 94% |
| Integration tests | PASSED | 12 testes, DB PostgreSQL real |
| E2E (Cypress) | PASSED | CA-01 a CA-06 todos validados |
| Load (k6) | PASSED | p95=340ms, error rate=0.02% |
| Security audit | PASSED | 0 vulnerabilidades high/critical |
## Status: APROVADO PARA SHIP
## Preview URL
https://pr-142-notif.preview.vercel.app
## Checklist PM (Ana Costa)
- [x] CA-01: notificação em < 2s ✓ (testado no preview)
- [x] CA-02: badge com contagem correta ✓
- [x] CA-03: clique marca como lida e navega ✓
- [x] CA-04: preferências por tipo funcionando ✓
- [x] CA-05: reconexão recebe notificações perdidas ✓
- [x] CA-06: reconexão automática em 3 tentativas ✓
Aprovado por: Ana Costa — 2026-03-29 16:45
Próximo passo: /gsd:shipDiscuss → Plan → UI-Phase → Execute (3 waves, 2 compacts) → Verify → Ship. Duração: 1 sprint de 2 dias. Zero retrabalho pós-aprovação de PM. 47 testes unitários + 12 integration + 6 E2E. PR merged sem comentários de revisão bloqueantes.
Hooks neste workflow
No GSD, hooks complementam as waves do execute-phase. Enquanto o GSD organiza quando e o quê, os hooks garantem qualidade em cada arquivo escrito — independente da wave.
settings.json para W2 GSD
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [{"type": "command", "command": "node scripts/quality-gate.mjs \"$CLAUDE_TOOL_INPUT_FILE_PATH\""}]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{"type": "command", "command": "node scripts/bash-guard.mjs"}]
}
],
"Stop": [
{
"hooks": [{"type": "command", "command": "node scripts/wave-summary.mjs"}]
}
]
}
}wave-summary.mjs — resumo ao final de cada wave
#!/usr/bin/env node
// wave-summary.mjs — exibe resumo de qualidade ao final de cada resposta
import { execSync } from 'node:child_process';
try {
const result = execSync('npx vitest run --reporter=verbose 2>&1', { encoding: 'utf8' });
const passing = (result.match(/✓/g) || []).length;
const failing = (result.match(/×/g) || []).length;
console.log(`[wave-summary] Testes: ${passing} passando, ${failing} falhando`);
} catch (e) {
console.log('[wave-summary] Testes falhando — verifique antes de iniciar a próxima wave');
}Os scripts quality-gate.mjs e bash-guard.mjs estão documentados no Módulo 22 — Fundamentos.