agent-engineering-skills 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/AGENTS.md +249 -0
  2. package/LICENSE +21 -0
  3. package/README.md +113 -0
  4. package/bin/cli.js +223 -0
  5. package/docs/agent-integration.md +200 -0
  6. package/docs/philosophy.md +131 -0
  7. package/docs/reference-authoring.md +117 -0
  8. package/docs/skill-authoring.md +126 -0
  9. package/examples/authorization-bypass.md +191 -0
  10. package/examples/frontend-review.md +244 -0
  11. package/examples/race-condition.md +128 -0
  12. package/examples/xp-reward-loop.md +123 -0
  13. package/package.json +45 -0
  14. package/references/engineering.yaml +88 -0
  15. package/references/frontend.yaml +139 -0
  16. package/references/product.yaml +54 -0
  17. package/references/research.yaml +88 -0
  18. package/references/security.yaml +85 -0
  19. package/references/ux.yaml +37 -0
  20. package/scripts/validate.py +454 -0
  21. package/skills/audit/adversarial-review/SKILL.md +190 -0
  22. package/skills/audit/business-logic-audit/SKILL.md +182 -0
  23. package/skills/audit/edge-case-hunter/SKILL.md +159 -0
  24. package/skills/audit/error-flow-audit/SKILL.md +184 -0
  25. package/skills/audit/state-consistency-audit/SKILL.md +174 -0
  26. package/skills/audit/user-flow-audit/SKILL.md +161 -0
  27. package/skills/frontend/accessibility-review/SKILL.md +186 -0
  28. package/skills/frontend/animation-review/SKILL.md +171 -0
  29. package/skills/frontend/interaction-design/SKILL.md +162 -0
  30. package/skills/frontend/ux-review/SKILL.md +172 -0
  31. package/skills/frontend/visual-quality-review/SKILL.md +160 -0
  32. package/skills/meta/research-router/SKILL.md +184 -0
  33. package/skills/meta/skill-router/SKILL.md +206 -0
  34. package/skills/product/gamification-audit/SKILL.md +213 -0
  35. package/skills/reliability/data-integrity-audit/SKILL.md +187 -0
  36. package/skills/reliability/idempotency-audit/SKILL.md +191 -0
  37. package/skills/reliability/race-condition-hunter/SKILL.md +181 -0
  38. package/skills/research/github-reference-research/SKILL.md +197 -0
  39. package/skills/research/implementation-research/SKILL.md +181 -0
  40. package/skills/research/market-research/SKILL.md +202 -0
  41. package/skills/research/reference-research/SKILL.md +186 -0
  42. package/skills/security/api-abuse-audit/SKILL.md +178 -0
  43. package/skills/security/authorization-audit/SKILL.md +176 -0
  44. package/skills/security/input-trust-audit/SKILL.md +178 -0
  45. package/templates/audit-report.md +89 -0
  46. package/templates/bug-report.md +107 -0
  47. package/templates/design-review.md +122 -0
  48. package/templates/research-report.md +96 -0
@@ -0,0 +1,174 @@
1
+ ---
2
+ name: state-consistency-audit
3
+ description: Compares state across database, API, server state, cache, client state, and URL state, and looks for divergences where the layers disagree about what is true.
4
+ category: audit
5
+ triggers:
6
+ - "audit state consistency"
7
+ - "find cache and database divergence"
8
+ - "client and server state out of sync"
9
+ - "url state vs server state"
10
+ - "stale cache bugs"
11
+ priority: high
12
+ ---
13
+
14
+ # State Consistency Audit
15
+
16
+ ## Objective
17
+
18
+ Ensinar o agente a tratar o "estado do sistema" não como uma coisa única, mas como
19
+ **várias cópias que devem concordar** — e a procurar os pontos onde elas divergem.
20
+
21
+ ```text
22
+ database API response server (in-memory) cache client state URL state
23
+ ```
24
+
25
+ Um bug de consistência acontece quando duas camadas afirmam coisas diferentes sobre o
26
+ messe fato (ex: cache diz "saldo 100", banco diz "50") e o sistema age sobre a errada.
27
+
28
+ ## When to Use
29
+
30
+ * Quando o sistema tem cache (CDN, Redis, in-memory, SWR/React Query no cliente).
31
+ * Quando o estado é refletido na URL (filtros, paginação, tabs, modais via querystring).
32
+ * Quando o cliente mantém estado (otimistic UI, estado local vs servidor).
33
+ * Quando há read replicas, eventual consistency, ou mensagens assíncronas.
34
+ * Quando o pedido menciona "stale", "out of sync", "cache", "refresh shows wrong",
35
+ "desync".
36
+ * **Composição:** pareia com `user-flow-audit` (refresh/back-button causam desync),
37
+ `data-integrity-audit` (o banco como fonte de verdade), `error-flow-audit` (estado
38
+ parcial após falha), `edge-case-hunter` (stale data como edge).
39
+
40
+ ## Mental Model
41
+
42
+ O "estado" não é uma variável — é um **conjunto de representações** que o sistema
43
+ mantém em diferentes latências e locais por performance/UX. Cada representação tem um
44
+ TTL, um caminho de invalidação, e um caminho de leitura. Bugs nascem quando:
45
+
46
+ 1. **Invalidação ausente** — o estado muda no banco mas o cache não é invalidado.
47
+ 2. **Ordem de invalidação errada** — escreve no cache antes do banco (e falha), ou
48
+ invalida depois de servir a leitura stale.
49
+ 3. **Otimistic UI não revertida** — o cliente assume sucesso, atualiza a UI, o servidor
50
+ falha, a UI fica inconsistente com o servidor.
51
+ 4. **URL como fonte de verdade sem servidor** — a URL diz um estado que o servidor não
52
+ conhece (deep link para estado que expirou/foi revogado).
53
+ 5. **Read replica lag** — escreve no primário, lê da replica antes da replicação, vê
54
+ estado antigo.
55
+
56
+ A pergunta central para cada fato do sistema: **qual camada é a fonte de verdade, e
57
+ todas as outras convergiram para ela?**
58
+
59
+ ## Investigation Procedure
60
+
61
+ 1. **Inventariar as camadas de estado** para o componente/fluxo. Nem todos os fluxos
62
+ usam todas as seis; liste só as que existem.
63
+ 2. **Para cada fato relevante** (saldo, status do recurso, permissão, contador), rotule
64
+ a **fonte de verdade** (geralmente o banco) e as **cópias** (cache, cliente, URL).
65
+ 3. **Traçar o caminho de escrita** — onde o fato é mutado, e em que ordem as camadas
66
+ são atualizadas.
67
+ 4. **Traçar o caminho de leitura** — qual camada é lida em cada ponto, e se há fallback.
68
+ 5. **Procurar invalidação ausente ou tardia** — quando o fato muda, cada cópia é
69
+ invalidada/atualizada? Antes ou depois de servir leituras?
70
+ 6. **Testar desyncs concretos:**
71
+ * Mutar + ler imediatamente de cache (stale read).
72
+ * Mutar no primário + ler de replica (lag).
73
+ * Otimistic update + falha de servidor (UI não revertida).
74
+ * Deep link via URL para estado revogado (URL ≠ servidor).
75
+ * Duas abas / dois clientes mutando (um vê estado do outro?).
76
+ 7. **Confirmar com evidência** — mostre as duas camadas discordando.
77
+ 8. **Reportar** via `templates/audit-report.md`.
78
+
79
+ ## Questions to Ask
80
+
81
+ * Quais camadas de estado existem neste fluxo? Qual é a fonte de verdade?
82
+ * Quando o fato muda no banco, o cache é invalidado? Quando — antes ou depois de servir?
83
+ * Há read replicas? A leitura após escrita vai para a replica ou o primário?
84
+ * A UI atualiza otimisticamente? Se o servidor falha, a UI reverte?
85
+ * A URL reflete estado? Esse estado é validado contra o servidor no carregamento?
86
+ * Dois clientes (duas abas, dois dispositivos) mutam o mesmo recurso — um vê a mudança
87
+ do outro? Quando?
88
+ * Há TTL de cache maior que a janela de mutação esperada?
89
+ * O cache é populado por quem? E invalidado por quem? (populador ≠ invalidador = bug)
90
+
91
+ ## Attack Patterns
92
+
93
+ ```text
94
+ stale cache read
95
+ write db: balance 50 (was 100)
96
+ read cache: balance 100 ← invalidação faltou ou é assíncrona
97
+ → age sobre 100, permite gastar além do real
98
+
99
+ read replica lag
100
+ write primary: status "paid"
101
+ read replica (imediatamente): status "pending" ← replicação não convergiu
102
+ → trata como pendente, reprocessa, duplica efeito
103
+
104
+ optimistic UI not reverted
105
+ user clicks "like" → UI: liked ✓ (optimistic)
106
+ server: 401/500 ← falha
107
+ UI permanece liked ✓ ← não reverteu
108
+ → UI ≠ servidor
109
+
110
+ URL ≠ server state
111
+ url: /doc/123?mode=edit
112
+ server: doc 123 was deleted / permission revoked
113
+ → carrega modo edit de recurso inacessível?
114
+
115
+ two-client divergence
116
+ client A: edits resource, saves → server updated
117
+ client B: still showing old version (no realtime/poll)
118
+ → B edita sobre estado antigo, sobrescreve A
119
+
120
+ cache populated by A, invalidated by nobody
121
+ service A writes cache on read (populate-on-miss)
122
+ service B writes db directly, never invalidates cache
123
+ → cache perpetuamente stale até TTL
124
+
125
+ in-memory server state across instances
126
+ instance 1: local cache of "rate limit count"
127
+ instance 2: separate local cache
128
+ → limit bypassable by rotating instance (round-robin)
129
+ ```
130
+
131
+ ## Evidence Requirements
132
+
133
+ * **Nomear as duas camadas que discordam** e o fato específico.
134
+ * **Mostrar o estado em cada camada** (valor no banco vs valor no cache/cliente/URL).
135
+ * **Mostrar o mecanismo da divergência** — qual caminho de escrita não invalidou, qual
136
+ lag, qual otimistic não revertido.
137
+ * **Escalar confiança:**
138
+ * `CONFIRMED` — reproduziu e capturou os dois valores discordando (ex: resposta da
139
+ API vs query no banco).
140
+ * `HIGH CONFIDENCE` — código mostra invalidação ausente ou ordem errada, sem
141
+ reprodução manual.
142
+ * `POSSIBLE` — caminho plausível de desync, não confirmado.
143
+ * `SPECULATIVE` — "pode ficar stale" sem rastrear o mecanismo.
144
+ * Desyncs que permitem **agir sobre estado errado** (gastar saldo stale) são mais
145
+ graves que desyncs puramente visuais.
146
+
147
+ ## False Positives
148
+
149
+ * **Stale visual aceitável** — alguns caches são *desenhados* para ser stale (ex:
150
+ contagem de likes aproximada, eventual consistency por produto). Se o sistema
151
+ tolera stale por design, não é bug. Marcar `POSSIBLE` e levantar como decisão de
152
+ produto se duvidar.
153
+ * **Invalidação existe mas é assíncrona por design** — invalidação eventual dentro de
154
+ uma janela documentada é aceitável; bug é só se a janela é indefinida ou não
155
+ garantida.
156
+ * **URL é puramente de UI** — se a URL só controla view state (tab aberta) sem claims
157
+ sobre dados, "URL ≠ servidor" não aplica.
158
+ * **Optimistic revert existe** — se há rollback no `onError`, não reportar. Confirmar
159
+ a ausência antes.
160
+ * **Read replica com read-your-writes guarantee** — se a leitura pós-escrita vai ao
161
+ primário (ou replica com lag < janela crítica), lag não é problema.
162
+
163
+ ## Output Format
164
+
165
+ Para cada par de camadas que discorda com consequência, um finding via
166
+ `templates/audit-report.md`. Em **Affected component**, nomeie as camadas e o fato. Em
167
+ **Reproduction**, mostre a sequência (write → read) que produz a divergência e os dois
168
+ valores observados. Em **Root cause**, diga qual invalidação/ordem/lag/revert falta.
169
+ Em **Recommendation**, indique a estratégia (write-through, invalidação síncrona,
170
+ read-your-writes para o primário, rollback de optimistic, validação de URL no load).
171
+
172
+ Apresente um mapa de camadas por fato (fato | fonte de verdade | cópias | caminho de
173
+ invalidação | ✓/✗), marcando os desyncs. Desyncs que permitem agir sobre estado errado
174
+ primeiro; desyncs visuais depois.
@@ -0,0 +1,161 @@
1
+ ---
2
+ name: user-flow-audit
3
+ description: Maps a user flow as entry → preconditions → action → state change → feedback → next state and detects dead ends, impossible states, skippable steps, refresh and back-button problems, and duplicate operations.
4
+ category: audit
5
+ triggers:
6
+ - "audit a user flow"
7
+ - "map the states of a feature"
8
+ - "find dead ends in a flow"
9
+ - "review onboarding or checkout flow"
10
+ - "what happens on refresh or back button"
11
+ priority: high
12
+ ---
13
+
14
+ # User Flow Audit
15
+
16
+ ## Objective
17
+
18
+ Ensinar o agente a modelar um fluxo de usuário como uma **máquina de estados** e a
19
+ procurar estados dos quais o usuário não consegue sair, estados impossíveis, passos que
20
+ podem ser pulados, e desyncs causados por refresh/back-button.
21
+
22
+ A skill trata o fluxo como uma sequência canônica:
23
+
24
+ ```text
25
+ entry → preconditions → action → state change → feedback → next state
26
+ ```
27
+
28
+ ## When to Use
29
+
30
+ * Ao auditar qualquer fluxo multi-passo (onboarding, checkout, criação de personagem,
31
+ publicação, convites, setup).
32
+ * Quando o pedido menciona "flow", "steps", "wizard", "onboarding", "checkout".
33
+ * Quando há risco de o usuário ficar preso em um estado intermediário.
34
+ * **Composição:** frequentemente junto com `state-consistency-audit` (fluxo vs estado
35
+ do servidor), `error-flow-audit` (o que acontece quando um passo do fluxo falha),
36
+ `business-logic-audit` (pré-condições do fluxo = regras de negócio), e
37
+ `edge-case-hunter` (entrances anômalas no fluxo).
38
+
39
+ ## Mental Model
40
+
41
+ Um fluxo não é uma lista de telas. É uma **máquina de estados**: cada nó é um estado
42
+ persistido (no servidor, no cliente, ou na URL), e cada transição é uma ação que move
43
+ de um estado a outro. Bugs vivem nas transições e nos estados, não nas telas.
44
+
45
+ As duas falhas mais comuns:
46
+
47
+ 1. **Estados sem saída** — o usuário chega a um estado do qual nenhuma ação legítima o
48
+ tira. Dead end.
49
+ 2. **Transições implícitas** — o fluxo assume que o estado anterior foi atingido, mas
50
+ nada o impede de pular direto a um estado posterior. Passo pulável.
51
+
52
+ O modelo força a pergunta: *de cada estado, para onde o usuário pode ir — e o que o
53
+ impede de ir para onde não deveria?*
54
+
55
+ ## Investigation Procedure
56
+
57
+ 1. **Desenhar o fluxo nominal** como `entry → preconditions → action → state change →
58
+ feedback → next state`. Um nó por estado.
59
+ 2. **Rotular onde cada estado vive** — servidor, cliente, URL, ou cache. (Isto
60
+ conecta com `state-consistency-audit`.)
61
+ 3. **Para cada transição, listar a pré-condição** que deve ser verdadeira para ela
62
+ ocorrer.
63
+ 4. **Testar pulabilidade:** a pré-condição é *verificada no servidor* ou *assumida*? Se
64
+ assumida, o passo é pulável via chamada direta ao endpoint do passo seguinte.
65
+ 5. **Testar estados sem saída:** para cada estado, existe uma ação legítima que leva a
66
+ um próximo estado útil? Se não, é dead end.
67
+ 6. **Testar refresh:** em cada estado, o que acontece se o usuário recarregar? O estado
68
+ é reconstruído a partir do servidor, ou perdido/resetado?
69
+ 7. **Testar back-button:** o que acontece ao voltar? O usuário reexecuta uma ação
70
+ não-idempotente? Volta a um estado que não deveria mais ser acessível?
71
+ 8. **Testar duplicação:** o usuário pode executar a mesma ação duas vezes (duplo submit,
72
+ double click) e causar dois efeitos?
73
+ 9. **Listar estados impossíveis** — combinações que a máquina deveria proibir mas que
74
+ podem ser alcançadas por pulo, refresh, ou back.
75
+ 10. **Reportar** findings via `templates/audit-report.md`.
76
+
77
+ ## Questions to Ask
78
+
79
+ * Quais são todos os estados do fluxo? Onde cada um é persistido?
80
+ * Para cada transição, qual a pré-condição? Ela é checada no servidor?
81
+ * Existe um estado do qual nenhuma ação leva a lugar útil? (dead end)
82
+ * Posso pular direto para um estado avançado sem passar pelos anteriores?
83
+ * O que o refresh faz em cada estado? O estado é recuperado do servidor ou perdido?
84
+ * O back-button reexecuta uma ação? Volta a um estado obsoleto?
85
+ * Um duplo-submit cria dois recursos / duas recompensas?
86
+ * Existem combinações de estado que deveriam ser impossíveis mas são alcançáveis?
87
+ * O feedback dado ao usuário reflete o estado real do servidor?
88
+
89
+ ## Attack Patterns
90
+
91
+ ```text
92
+ skip preconditions
93
+ POST /step-final (pulando /step-1 e /step-2)
94
+ → efeito concedido sem pré-condições?
95
+
96
+ dead end
97
+ state: "payment_failed"
98
+ → existe botão "retry"? "cancel"? ou o usuário fica preso?
99
+
100
+ refresh mid-flow
101
+ state: "form partially submitted"
102
+ refresh → estado reconstruído? ou volta ao início perdendo dados?
103
+
104
+ back-button after submit
105
+ submit → state: "created"
106
+ back → volta ao form → submit novamente
107
+ → criação duplicada?
108
+
109
+ duplicate operation
110
+ double click em "Submit"
111
+ → dois requests, dois efeitos?
112
+
113
+ impossible state reachable
114
+ resource marcado "deleted" mas ainda listado e editável
115
+ → combinação proibida alcançada por caminho indireto
116
+
117
+ stale feedback
118
+ UI mostra "success" mas servidor reverteu por erro interno
119
+ → feedback ≠ estado real
120
+ ```
121
+
122
+ ## Evidence Requirements
123
+
124
+ * **Nomear o estado e a transição** problemáticos (ex: "do estado `submitted` via
125
+ back-button de volta a `form`").
126
+ * **Mostrar onde o estado vive** (server/client/URL/cache) e onde a pré-condição é (ou
127
+ não é) verificada.
128
+ * **Reproduzir ou apontar o mecanismo** — sequência de passos/requests, ou o código que
129
+ assume a pré-condição sem checá-la.
130
+ * **Escalar confiança:**
131
+ * `CONFIRMED` — reproduziu o dead end / o pulo / o desync.
132
+ * `HIGH CONFIDENCE` — mecanismo claro no código (ex: handler não checa etapa
133
+ anterior), sem reprodução manual.
134
+ * `POSSIBLE` — fluxo parece permitir, caminho plausível, não confirmado.
135
+ * `SPECULATIVE` — "acho que refresh pode quebrar" sem rastrear o mecanismo.
136
+
137
+ ## False Positives
138
+
139
+ * **Pré-condição verificada no servidor** — se o handler do passo final valida que os
140
+ anteriores ocorreram, o "pulo" não produz efeito. Confirmar antes de reportar.
141
+ * **Estado é puramente de UI** — alguns estados "intermediários" são só feedback visual
142
+ sem estado persistido; "perdê-los" no refresh é aceitável se o servidor é a verdade.
143
+ * **Back-button em fluxo idempotente** — se reexecutar é seguro (idempotência real),
144
+ não é bug (relacionado a `idempotency-audit`).
145
+ * **Dead end é intencional** — alguns estados terminais são deliberados (ex: "conta
146
+ banida"). Reportar como tal, não como defeito, ou marcar como `POSSIBLE` para decisão
147
+ de produto.
148
+ * **Duplicação protegida por disable de botão + server idempotency** — defesa em
149
+ profundidade; se ambas existem, não reportar.
150
+
151
+ ## Output Format
152
+
153
+ Para cada estado/transição problemática, um finding via
154
+ `templates/audit-report.md`. Em **Reproduction**, dê a sequência exata de estados
155
+ visitados (incluindo refresh/back) que leva ao defeito. Em **Affected flow**, nomeie o
156
+ fluxo. Em **Recommendation**, indique *onde* corrigir (validação server-side no handler
157
+ do passo final; bloqueio de estado obsoleto; reconstrução de estado no refresh).
158
+
159
+ Anexe um diagrama da máquina de estados com os estados/transições problemáticos
160
+ marcados. Estados sem saída e transições puláveis são os mais graves — liste-os
161
+ primeiro.
@@ -0,0 +1,186 @@
1
+ ---
2
+ name: accessibility-review
3
+ description: Evaluates keyboard navigation, screen readers, focus management, semantic HTML, contrast, touch targets, reduced motion, forms, and error handling against WCAG standards.
4
+ category: frontend
5
+ triggers:
6
+ - "audit accessibility"
7
+ - "check keyboard navigation"
8
+ - "review screen reader support"
9
+ - "semantic html and aria"
10
+ - "wcag compliance"
11
+ - "touch targets and focus"
12
+ - "reduced motion and forms"
13
+ priority: high
14
+ ---
15
+
16
+ # Accessibility Review
17
+
18
+ ## Objective
19
+
20
+ Ensinar o agente a avaliar uma interface contra padrões de acessibilidade (WCAG):
21
+ keyboard, screen readers, focus, semantic HTML, contrast, touch targets, reduced
22
+ motion, forms, e erros. Como define o `plan.md` §10: acessibilidade não é extra — é
23
+ parte da definição de qualidade.
24
+
25
+ ## When to Use
26
+
27
+ * Em qualquer tela que será usada por pessoas reais.
28
+ * Antes de lançar features que envolvem formulários, navegação, modal, interação
29
+ complexa, ou conteúdo dinâmico.
30
+ * Quando o pedido menciona "accessibility", "a11y", "WCAG", "keyboard", "screen
31
+ reader", "aria", "focus", "contrast", "touch target", "reduced motion".
32
+ * **Composição:** roda com todas as frontend skills. Pareia especialmente com
33
+ `interaction-design` (focus, keyboard, feedback), `animation-review` (reduced
34
+ motion), `ux-review` (clareza, erro, feedback), e `visual-quality-review` (contrast).
35
+
36
+ ## Mental Model
37
+
38
+ Acessibilidade não é sobre "adicionar ARIA". É sobre **garantir que o sistema funciona
39
+ independente de como o usuário acessa**. A regra prática: se uma funcionalidade não
40
+ funciona só com teclado, ou se o conteúdo não é legível por um screen reader, a
41
+ funcionalidade está quebrada para uma parcela dos usuários.
42
+
43
+ Eixos (do `plan.md` §10):
44
+
45
+ ```text
46
+ keyboard — cada ação é alcançável com Tab/Enter/Esc (sem mouse trap)
47
+ screen readers — conteúdo é legível com SR (alt text, labels, aria-live)
48
+ focus — focus ring visível, ordem lógica, não removido, gerenciado em modais
49
+ semantic HTML — elementos > divs genéricas (button, heading, nav, main, form)
50
+ contrast — texto ≥ 4.5:1 (body) / 3:1 (large) / 3:1 (UI components)
51
+ touch targets — ≥ 44x44px (48x48 recomendado)
52
+ reduced motion — animações respeitam prefers-reduced-motion
53
+ forms — labels, errors, hints, e focus sequence
54
+ errors — comunicados por texto + aria-live, não só cor
55
+ ```
56
+
57
+ ## Investigation Procedure
58
+
59
+ 1. **Testar keyboard** — Tab por toda a tela. Todos os elementos interativos são
60
+ alcançáveis? A ordem de tab é lógica? Há `tabindex` quebrado? (positivo que
61
+ não é 0, negativo que esconde)
62
+ 2. **Testar focus** — O focus ring é visível? Foi removido com `outline: none`? Ao
63
+ abrir modal, focus vai para dentro? Ao fechar, volta ao trigger? O focus não fica
64
+ preso em um elemento (focus trap quebrado)?
65
+ 3. **Testar screen reader** — Há `alt` text em imagens? Há `aria-label` em ícones
66
+ semânticos? `aria-live` para conteúdo dinâmico? O conteúdo é legível sem contexto
67
+ visual? (testar com um leitor real ou simulando: fechar os olhos e ouvir)
68
+ 4. **Testar semantic HTML** — `<button>` vs `<div onclick>`? `<nav>` vs `<div>`?
69
+ `<h1-h6>` para hierarquia? `<form>` com `<label>`?
70
+ 5. **Testar contrast** — texto body ≥ 4.5:1 (WCAG AA). Texto large ≥ 3:1. UI
71
+ components (bordas, ícones) ≥ 3:1. Modo escuro?
72
+ 6. **Testar touch targets** — botões, links, inputs ≥ 44x44px. Elementos próximos têm
73
+ espaço entre eles? (touch não preciona o adjacente)
74
+ 7. **Testar reduced motion** — animações desligam com `prefers-reduced-motion: reduce`?
75
+ (ver `animation-review` para detalhe)
76
+ 8. **Testar forms** — cada input tem `<label>` (não só placeholder)? Erros são
77
+ comunicados por texto (não só cor)? Hints/tooltips são acessíveis (não só hover)?
78
+ Focus sequence entre campos é lógica?
79
+ 9. **Sintetizar** — referenciar `references/frontend.yaml` (Impeccable, WCAG docs)
80
+ quando apropriado.
81
+
82
+ ## Questions to Ask
83
+
84
+ * Toda ação é alcançável com Tab/Enter/Esc? (sem mouse trap)
85
+ * O focus ring é visível? Foi removido com `outline: none`? (se sim, todo o resto
86
+ falha para teclado)
87
+ * Ao abrir modal, focus vai para dentro? Ao fechar, volta? (focus trap correto?)
88
+ * Imagens têm `alt` text descritivo? (não só "image", vazio, ou o filename)
89
+ * Ícones semânticos têm `aria-label`? (não só decorative)
90
+ * Conteúdo dinâmico (loading, erro, toast) tem `aria-live` / `role="alert"`?
91
+ * A estrutura de headings é hierárquica? (h1 → h2 → h3, não pula)
92
+ * `<button>` é usado para ações, não `<div onclick>`?
93
+ * Contraste de texto ≥ 4.5:1? (WCAG AA)
94
+ * Touch targets ≥ 44x44px? (especialmente mobile)
95
+ * Cada input tem `<label>` visível? (não só placeholder)
96
+ * Erros são comunicados por texto + aria-live, não só por cor?
97
+
98
+ ## Attack Patterns
99
+
100
+ ```text
101
+ keyboard trap
102
+ modal aberto, Tab não sai do modal (correto). Mas não volta ao fechar (erro).
103
+ dropdown com itens não acessíveis por teclado (só mouse)
104
+
105
+ focus removed
106
+ `*:focus { outline: none !important }` — o maior crime de acessibilidade
107
+ → usuário de teclado não vê onde está
108
+
109
+ no alt text
110
+ <img src="chart.png"> sem alt → screen reader lê "chart.png"
111
+ ícone de like sem aria-label → "button" sem contexto
112
+
113
+ heading hierarchy broken
114
+ h1 → h3 (pula h2) → conteúdo perde estrutura
115
+ tudo é h1 (sem hierarquia)
116
+
117
+ div as button
118
+ <div onclick="submit()"> vs <button type="submit">
119
+ → não acessível por teclado, não tem role, não tem estado
120
+
121
+ contrast insufficient
122
+ gray-400 (#9CA3AF) em white (#FFFFFF) → 2.9:1, falha WCAG AA
123
+
124
+ touch target too small
125
+ link de 20×20px no mobile → impossível acertar com o dedo
126
+
127
+ label absent
128
+ placeholder="Username" como único label → perde contexto quando preenchido
129
+ → <label> necessário
130
+
131
+ error by color only
132
+ input com borda vermelha sem texto de erro → daltônico não vê
133
+ → precisa de texto + aria-live
134
+
135
+ reduced motion ignored
136
+ parallax e flutuação constantes sem `prefers-reduced-motion`
137
+ → desconforto vestibular
138
+
139
+ skip navigation absent
140
+ <main> sem "Skip to content" → usuário de teclado tab pelos 20 links do nav
141
+ toda vez que carrega
142
+ ```
143
+
144
+ ## Evidence Requirements
145
+
146
+ * **Nomear o eixo** (keyboard/focus/screen reader/semantic/contrast/touch/reduced
147
+ motion/forms/errors).
148
+ * **Mostrar o elemento exato** e a violação (ex: `*:focus { outline: none !important }`,
149
+ `alt=""` em imagem informativa, `<div onclick>` para ação, contraste 2.9:1).
150
+ * **Referenciar o critério WCAG** quando aplicável (ex: "WCAG 1.4.3 Contrast Minimum",
151
+ "2.1.1 Keyboard", "2.4.7 Focus Visible").
152
+ * **Escalar confiança (Accessibility):**
153
+ * `CONFIRMED` — violação mensurável (contraste < 4.5:1, focus removido, keyboard
154
+ trap, no alt text, label ausente, touch target < 44px).
155
+ * `HIGH CONFIDENCE` — padrão claramente violado.
156
+ * `POSSIBLE` — violação marginal (ex: contraste 4.3:1, touch target 40px).
157
+ * `SPECULATIVE` — necessidade não confirmada (ex: "talvez precise de aria-live aqui").
158
+
159
+ ## False Positives
160
+
161
+ * **Decorative image** — `alt=""` é *correto* para imagens decorativas. Não reportar
162
+ como "alt ausente". (Reportar quando é informativa sem alt.)
163
+ * **Focus visible por outro sinal** — se o `outline: none` tem substituto (border,
164
+ background, box-shadow) em todos os estados, é aceitável. Confirmar antes de
165
+ reportar.
166
+ * **Touch target tem espaço extra** — se o target visual é 30px mas o padding faz
167
+ o hit area ≥ 44px, é ok. Avaliar pelo hit area real, não só pelo visual.
168
+ * **Label oculto mas acessível** — `aria-label`/`<label class="sr-only">` é válido
169
+ se o screen reader lê. Não exigir label visível se o SR tem contexto suficiente.
170
+ * **Skip navigation em app SPA** — em apps de página única, skip to content pode ser
171
+ substituído por rota/foco gerenciado. Avaliar o contexto.
172
+ * **Reduced motion com fallback** — se o app respeita reduced motion, as animações
173
+ que ainda rodam precisam ser avaliadas individualmente, não como "não respeita".
174
+
175
+ ## Output Format
176
+
177
+ Para cada violação, um finding via `templates/audit-report.md`. Em **Affected
178
+ component**, nomeie o elemento. Em **Reproduction**, descreva o comportamento (ex:
179
+ "Tab 3×: focus vai do header para o footer, pulando todo o conteúdo principal"). Em
180
+ **Root cause**, aponte o eixo e o critério WCAG. Em **Recommendation**, dê a correção
181
+ (adicionar focus ring, `alt` text, `<label>`, contraste, touch target, ARIA, skip
182
+ navigation, reduzir motion).
183
+
184
+ Apresente por eixo, ordem de severidade: keyboard traps e focus removido (= bloqueante
185
+ para usuário de teclado) primeiro; contrast e labels depois; semantic HTML e touch
186
+ targets em seguida; forms e reduced motion por último.