nexus-core-v3 3.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 (232) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +134 -0
  3. package/agents/README.md +133 -0
  4. package/agents/_protocol.md +107 -0
  5. package/agents/analyst.md +138 -0
  6. package/agents/architect.md +146 -0
  7. package/agents/data-engineer.md +170 -0
  8. package/agents/dev.md +134 -0
  9. package/agents/devops.md +141 -0
  10. package/agents/nexus-master.md +147 -0
  11. package/agents/pm.md +133 -0
  12. package/agents/po.md +138 -0
  13. package/agents/qa.md +192 -0
  14. package/agents/sm.md +122 -0
  15. package/agents/squad-creator.md +121 -0
  16. package/agents/ux-design-expert.md +165 -0
  17. package/artifact-manifest.json +903 -0
  18. package/bin/nexus.mjs +37 -0
  19. package/checklists/README.md +49 -0
  20. package/checklists/architect-checklist.md +47 -0
  21. package/checklists/change-checklist.md +61 -0
  22. package/checklists/db-predeploy-checklist.md +57 -0
  23. package/checklists/design-quality-checklist.md +57 -0
  24. package/checklists/discovery-checklist.md +36 -0
  25. package/checklists/foundation-checklist.md +39 -0
  26. package/checklists/launch-checklist.md +39 -0
  27. package/checklists/pm-checklist.md +48 -0
  28. package/checklists/po-master-checklist.md +64 -0
  29. package/checklists/reality-check-checklist.md +49 -0
  30. package/checklists/story-dod-checklist.md +52 -0
  31. package/checklists/story-draft-checklist.md +36 -0
  32. package/dist/bin/dashboard.html +279 -0
  33. package/dist/bin/nexus.mjs +20008 -0
  34. package/dist/constitution.yaml +76 -0
  35. package/knowledge/README.md +57 -0
  36. package/knowledge/architecture/architectural-styles-map.md +182 -0
  37. package/knowledge/architecture/design-patterns-gof.md +192 -0
  38. package/knowledge/architecture/distributed-patterns-cheatsheet.md +201 -0
  39. package/knowledge/architecture/saas-subscription-blueprint.md +355 -0
  40. package/knowledge/architecture/system-design-tradeoffs.md +231 -0
  41. package/knowledge/architecture/t3-fullstack-typesafe-stack.md +273 -0
  42. package/knowledge/copy/landing-copy-that-converts.md +168 -0
  43. package/knowledge/data/postgres-indexing-and-tuning.md +263 -0
  44. package/knowledge/data/schema-modeling-decisions.md +273 -0
  45. package/knowledge/data/supabase-rls-patterns.md +316 -0
  46. package/knowledge/data/zero-downtime-migrations.md +308 -0
  47. package/knowledge/devops/cicd-pipeline-best-practices.md +318 -0
  48. package/knowledge/devops/production-dockerfile.md +283 -0
  49. package/knowledge/devops/twelve-factor-app.md +398 -0
  50. package/knowledge/engineering/clean-code-principles.md +429 -0
  51. package/knowledge/engineering/effective-code-review.md +204 -0
  52. package/knowledge/engineering/testing-strategy-beyond-unit.md +307 -0
  53. package/knowledge/governance/risk-matrix.md +56 -0
  54. package/knowledge/integration/mcp-server-selection-matrix.md +235 -0
  55. package/knowledge/marketing/copy-que-converte.md +43 -0
  56. package/knowledge/marketing/funil-e-jornada.md +36 -0
  57. package/knowledge/negocios/proposta-vencedora.md +38 -0
  58. package/knowledge/negocios/roi-e-unit-economics.md +46 -0
  59. package/knowledge/pipeline/1-descobrir.md +26 -0
  60. package/knowledge/pipeline/2-estrategizar.md +26 -0
  61. package/knowledge/pipeline/3-estruturar.md +27 -0
  62. package/knowledge/pipeline/4-construir.md +27 -0
  63. package/knowledge/pipeline/5-endurecer.md +28 -0
  64. package/knowledge/pipeline/6-lancar.md +27 -0
  65. package/knowledge/pipeline/7-operar.md +27 -0
  66. package/knowledge/security/lgpd-conformidade-basica.md +35 -0
  67. package/knowledge/security/owasp-secure-coding-gates.md +220 -0
  68. package/knowledge/security/owasp-top10-threat-assessment.md +287 -0
  69. package/knowledge/security/threat-modeling-stride.md +34 -0
  70. package/knowledge/web-craft/a11y-audit-checklist.md +251 -0
  71. package/knowledge/web-craft/accessible-component-patterns.md +383 -0
  72. package/knowledge/web-craft/anti-ai-look.md +114 -0
  73. package/knowledge/web-craft/design-system-from-code.md +195 -0
  74. package/knowledge/web-craft/intrinsic-css-layout.md +420 -0
  75. package/knowledge/web-craft/style-cloning.md +185 -0
  76. package/knowledge/web-craft/visual-polish-review.md +183 -0
  77. package/package.json +55 -0
  78. package/runbooks/campanha-de-conteudo.md +36 -0
  79. package/runbooks/feature-em-projeto-existente.md +37 -0
  80. package/runbooks/mvp-startup.md +38 -0
  81. package/runbooks/resposta-a-incidente.md +37 -0
  82. package/squads/exemplo-conteudo/agents/editor-chefe.md +48 -0
  83. package/squads/exemplo-conteudo/agents/pesquisador.md +44 -0
  84. package/squads/exemplo-conteudo/agents/redator.md +45 -0
  85. package/squads/exemplo-conteudo/knowledge/estilo-editorial.md +21 -0
  86. package/squads/exemplo-conteudo/squad.yaml +19 -0
  87. package/squads/exemplo-conteudo/tasks/pesquisar-fontes.md +26 -0
  88. package/squads/exemplo-conteudo/tasks/planejar-pauta.md +27 -0
  89. package/squads/exemplo-conteudo/tasks/redigir-artigo.md +26 -0
  90. package/squads/exemplo-conteudo/tasks/revisar-artigo.md +27 -0
  91. package/squads/marketing/agents/analista.md +56 -0
  92. package/squads/marketing/agents/chefe-marketing.md +65 -0
  93. package/squads/marketing/agents/conteudo.md +55 -0
  94. package/squads/marketing/agents/copy.md +55 -0
  95. package/squads/marketing/agents/growth.md +56 -0
  96. package/squads/marketing/agents/social.md +55 -0
  97. package/squads/marketing/squad.yaml +17 -0
  98. package/squads/marketing/tasks/aprovar-campanha.md +43 -0
  99. package/squads/negocios/agents/chefe-negocios.md +65 -0
  100. package/squads/negocios/agents/financas-roi.md +55 -0
  101. package/squads/negocios/agents/suporte.md +55 -0
  102. package/squads/negocios/agents/vendas-proposta.md +56 -0
  103. package/squads/negocios/squad.yaml +17 -0
  104. package/squads/negocios/tasks/aprovar-proposta.md +40 -0
  105. package/squads/security/agents/appsec-reviewer.md +59 -0
  106. package/squads/security/agents/chefe-seguranca.md +65 -0
  107. package/squads/security/agents/compliance-auditor.md +60 -0
  108. package/squads/security/agents/threat-modeler.md +60 -0
  109. package/squads/security/squad.yaml +20 -0
  110. package/squads/security/tasks/aprovar-gate-seguranca.md +42 -0
  111. package/squads/security/tasks/emitir-parecer-conformidade.md +42 -0
  112. package/tasks/README.md +72 -0
  113. package/tasks/accessibility-wcag-checklist.md +69 -0
  114. package/tasks/advanced-elicitation.md +42 -0
  115. package/tasks/analyze-performance.md +54 -0
  116. package/tasks/analyze-project-structure.md +59 -0
  117. package/tasks/apply-qa-fixes.md +57 -0
  118. package/tasks/architect-analyze-impact.md +62 -0
  119. package/tasks/archive-squad.md +52 -0
  120. package/tasks/audit-codebase.md +53 -0
  121. package/tasks/build-component.md +61 -0
  122. package/tasks/calculate-roi.md +63 -0
  123. package/tasks/ci-cd-configuration.md +51 -0
  124. package/tasks/collect-visual-evidence.md +62 -0
  125. package/tasks/compose-molecule.md +57 -0
  126. package/tasks/consolidate-patterns.md +54 -0
  127. package/tasks/create-brownfield-prd.md +54 -0
  128. package/tasks/create-competitor-analysis.md +42 -0
  129. package/tasks/create-deep-research-prompt.md +62 -0
  130. package/tasks/create-doc.md +62 -0
  131. package/tasks/create-epic.md +49 -0
  132. package/tasks/create-front-end-spec.md +56 -0
  133. package/tasks/create-migration-plan.md +57 -0
  134. package/tasks/create-next-story.md +66 -0
  135. package/tasks/create-prd.md +53 -0
  136. package/tasks/create-project-brief.md +47 -0
  137. package/tasks/create-rls-policies.md +59 -0
  138. package/tasks/create-schema.md +57 -0
  139. package/tasks/create-service.md +55 -0
  140. package/tasks/create-squad.md +100 -0
  141. package/tasks/create-suite.md +62 -0
  142. package/tasks/db-apply-migration.md +56 -0
  143. package/tasks/db-domain-modeling.md +57 -0
  144. package/tasks/db-dry-run.md +50 -0
  145. package/tasks/db-env-check.md +57 -0
  146. package/tasks/db-load-csv.md +54 -0
  147. package/tasks/db-policy-apply.md +58 -0
  148. package/tasks/db-rollback.md +51 -0
  149. package/tasks/db-run-sql.md +61 -0
  150. package/tasks/db-seed.md +52 -0
  151. package/tasks/db-smoke-test.md +51 -0
  152. package/tasks/db-snapshot.md +48 -0
  153. package/tasks/db-verify-order.md +49 -0
  154. package/tasks/deliberate.md +46 -0
  155. package/tasks/design-indexes.md +59 -0
  156. package/tasks/dev-develop-story.md +61 -0
  157. package/tasks/document-project.md +59 -0
  158. package/tasks/execute-checklist.md +57 -0
  159. package/tasks/execute-epic-plan.md +52 -0
  160. package/tasks/execute-subtask.md +51 -0
  161. package/tasks/extend-pattern.md +63 -0
  162. package/tasks/extend-squad.md +60 -0
  163. package/tasks/extract-patterns.md +64 -0
  164. package/tasks/extract-tokens.md +59 -0
  165. package/tasks/facilitate-brainstorming-session.md +42 -0
  166. package/tasks/generate-ai-frontend-prompt.md +57 -0
  167. package/tasks/generate-documentation.md +60 -0
  168. package/tasks/generate-migration-strategy.md +57 -0
  169. package/tasks/generate-shock-report.md +56 -0
  170. package/tasks/mcp-management.md +66 -0
  171. package/tasks/orchestrate.md +50 -0
  172. package/tasks/perform-market-research.md +42 -0
  173. package/tasks/plan-create-context.md +57 -0
  174. package/tasks/plan-create-implementation.md +58 -0
  175. package/tasks/po-close-story.md +60 -0
  176. package/tasks/po-manage-story-backlog.md +59 -0
  177. package/tasks/po-pull-story.md +60 -0
  178. package/tasks/po-sync-story.md +59 -0
  179. package/tasks/pr-automation.md +50 -0
  180. package/tasks/pre-push-quality-gate.md +54 -0
  181. package/tasks/push.md +53 -0
  182. package/tasks/qa-browser-console-check.md +52 -0
  183. package/tasks/qa-create-fix-request.md +58 -0
  184. package/tasks/qa-evidence-requirements.md +55 -0
  185. package/tasks/qa-false-positive-detection.md +55 -0
  186. package/tasks/qa-fix-issues.md +55 -0
  187. package/tasks/qa-gate.md +53 -0
  188. package/tasks/qa-migration-validation.md +58 -0
  189. package/tasks/qa-nfr-assess.md +45 -0
  190. package/tasks/qa-review-story.md +56 -0
  191. package/tasks/qa-risk-profile.md +45 -0
  192. package/tasks/qa-security-checklist.md +64 -0
  193. package/tasks/qa-test-design.md +47 -0
  194. package/tasks/qa-trace-requirements.md +48 -0
  195. package/tasks/release-management.md +53 -0
  196. package/tasks/repository-cleanup.md +61 -0
  197. package/tasks/route.md +44 -0
  198. package/tasks/run-tests.md +50 -0
  199. package/tasks/security-audit.md +54 -0
  200. package/tasks/setup-database.md +60 -0
  201. package/tasks/setup-design-system.md +60 -0
  202. package/tasks/shard-doc.md +60 -0
  203. package/tasks/spec-assess-complexity.md +55 -0
  204. package/tasks/spec-critique.md +64 -0
  205. package/tasks/spec-gather-requirements.md +48 -0
  206. package/tasks/spec-research-dependencies.md +42 -0
  207. package/tasks/spec-write-spec.md +50 -0
  208. package/tasks/test-as-user.md +52 -0
  209. package/tasks/ux-create-wireframe.md +54 -0
  210. package/tasks/ux-user-research.md +55 -0
  211. package/tasks/validate-next-story.md +61 -0
  212. package/tasks/validate-squad.md +55 -0
  213. package/tasks/verify-subtask.md +52 -0
  214. package/tasks/version-management.md +45 -0
  215. package/templates/README.md +47 -0
  216. package/templates/architecture-tmpl.md +115 -0
  217. package/templates/competitor-analysis-tmpl.md +87 -0
  218. package/templates/epic-tmpl.md +83 -0
  219. package/templates/front-end-spec-tmpl.md +110 -0
  220. package/templates/market-research-tmpl.md +98 -0
  221. package/templates/migration-plan-tmpl.md +92 -0
  222. package/templates/prd-tmpl.md +95 -0
  223. package/templates/project-brief-tmpl.md +100 -0
  224. package/templates/qa-verdict-tmpl.md +73 -0
  225. package/templates/rls-policies-tmpl.md +93 -0
  226. package/templates/schema-design-tmpl.md +107 -0
  227. package/templates/spec-tmpl.md +88 -0
  228. package/templates/squad/agent-dna-tmpl.md +72 -0
  229. package/templates/squad/chief-dna-tmpl.md +98 -0
  230. package/templates/squad/squad-task-tmpl.md +50 -0
  231. package/templates/squad/squad-yaml-tmpl.md +47 -0
  232. package/templates/story-tmpl.md +63 -0
@@ -0,0 +1,429 @@
1
+ ---
2
+ id: clean-code-principles
3
+ domain: engineering
4
+ agents: [dev]
5
+ when: "ao escrever ou refatorar qualquer código, para garantir legibilidade e manutenibilidade"
6
+ ---
7
+
8
+ # Clean Code — heurísticas de legibilidade e manutenção
9
+
10
+ Código se lê muito mais vezes do que se escreve. A régua aqui é a do `clean-code-javascript`
11
+ de Ryan McDermott (adaptação do _Clean Code_ de Robert C. Martin para JS) — não um style guide,
12
+ mas um guia para produzir software **legível, reutilizável e refatorável**. Os exemplos abaixo são
13
+ os pares reais do repositório-fonte (JavaScript). A regra-mãe: **toda decisão de código tem que se
14
+ justificar** — se um nome, um argumento ou uma condicional só existe porque "saiu assim", é dívida.
15
+
16
+ > Aviso do próprio autor: nem todo princípio precisa ser seguido à risca, e poucos são unânimes. São
17
+ > diretrizes. Mas elas vêm de anos de experiência coletiva — use-as como pedra-de-toque ao avaliar a
18
+ > qualidade do código que você produz.
19
+
20
+ ## O problema / os tells
21
+
22
+ Se o diff tem 3+ destes, ele cheira a código apressado, não a craft:
23
+
24
+ 1. **Nomes não-pesquisáveis e mágicos** — `setTimeout(blastOff, 86400000)`. Ninguém sabe o que é
25
+ `86400000`, e você não consegue dar `grep` num número solto no meio do código.
26
+ 2. **Nomes não-pronunciáveis / abreviados** — `yyyymmdstr`, `l`, `d1`. Se você não consegue falar o
27
+ nome em voz alta numa code review, ele está errado.
28
+ 3. **Vocabulário inconsistente pro mesmo conceito** — `getUserInfo()`, `getClientData()`,
29
+ `getCustomerRecord()` espalhados, todos buscando a mesma coisa.
30
+ 4. **Funções com 4+ argumentos posicionais** — `createMenu("Foo", "Bar", "Baz", true)`. Na chamada,
31
+ ninguém sabe o que cada posição significa, e o `true` no fim é um enigma.
32
+ 5. **Argumento-flag booleano** — `createFile(name, temp)`. A flag denuncia que a função tem dois
33
+ caminhos, logo faz mais de uma coisa.
34
+ 6. **Função que faz várias coisas** — filtra, transforma e dispara no mesmo corpo; impossível de
35
+ testar ou reusar em pedaços.
36
+ 7. **Side effects escondidos** — função que muta uma variável global ou o objeto recebido por
37
+ parâmetro, em vez de receber e retornar.
38
+ 8. **Condicionais negativas e cruas** — `if (!isDOMNodeNotPresent(node))`: dupla negação que trava o
39
+ leitor; `if (fsm.state === "fetching" && isEmpty(listNode))` sem nome que explique a intenção.
40
+ 9. **Herança por preguiça** — `EmployeeTaxData extends Employee` quando a relação é "tem-um", não "é-um".
41
+ 10. **`catch (error) { console.log(error) }`** — engole o erro sem plano de reação.
42
+ 11. **Código morto** — `oldRequestModule` que ninguém chama, mantido "por via das dúvidas". O histórico
43
+ do git já guarda isso.
44
+
45
+ ## Os princípios (com pares bad→good reais)
46
+
47
+ ### 1. Nomes pesquisáveis (sem números mágicos)
48
+
49
+ Constantes nomeadas em vez de literais soltos — para o leitor entender e para o `grep` achar.
50
+
51
+ ```javascript
52
+ // Bad — o que diabos é 86400000?
53
+ setTimeout(blastOff, 86400000);
54
+
55
+ // Good — constante nomeada e maiúscula
56
+ const MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000; // 86400000
57
+
58
+ setTimeout(blastOff, MILLISECONDS_PER_DAY);
59
+ ```
60
+
61
+ ### 2. Nomes pronunciáveis e significativos
62
+
63
+ Você lê mais código do que escreve; abreviação economiza segundos na escrita e custa minutos na leitura.
64
+
65
+ ```javascript
66
+ // Bad
67
+ const yyyymmdstr = moment().format("YYYY/MM/DD");
68
+
69
+ // Good
70
+ const currentDate = moment().format("YYYY/MM/DD");
71
+ ```
72
+
73
+ E sem mapeamento mental: nomeie a variável do loop pelo que ela é, não `l`.
74
+
75
+ ```javascript
76
+ // Bad — "espera, o que é `l` mesmo?"
77
+ locations.forEach(l => { /* ...muitas linhas... */ dispatch(l); });
78
+
79
+ // Good
80
+ locations.forEach(location => { /* ... */ dispatch(location); });
81
+ ```
82
+
83
+ ### 3. Mesmo vocabulário pro mesmo tipo
84
+
85
+ Um conceito, um nome. Escolha um e use em todo lugar.
86
+
87
+ ```javascript
88
+ // Bad
89
+ getUserInfo();
90
+ getClientData();
91
+ getCustomerRecord();
92
+
93
+ // Good
94
+ getUser();
95
+ ```
96
+
97
+ ### 4. ≤2 argumentos — objeto quando precisar de mais
98
+
99
+ Mais de 2-3 parâmetros leva à explosão combinatória de casos de teste e some com a clareza na chamada.
100
+ Quando precisar de muitos, passe **um objeto** e desestruture — a assinatura passa a documentar quais
101
+ campos a função usa, e simula parâmetros nomeados.
102
+
103
+ ```javascript
104
+ // Bad — o que é `true`? e a ordem?
105
+ function createMenu(title, body, buttonText, cancellable) { /* ... */ }
106
+ createMenu("Foo", "Bar", "Baz", true);
107
+
108
+ // Good — campos nomeados, ordem irrelevante
109
+ function createMenu({ title, body, buttonText, cancellable }) { /* ... */ }
110
+ createMenu({ title: "Foo", body: "Bar", buttonText: "Baz", cancellable: true });
111
+ ```
112
+
113
+ ### 5. Função faz UMA coisa
114
+
115
+ A regra mais importante. Quando a função faz mais de uma coisa, é difícil compor, testar e raciocinar.
116
+ Isole cada ação.
117
+
118
+ ```javascript
119
+ // Bad — itera, busca no banco, checa estado e envia, tudo junto
120
+ function emailClients(clients) {
121
+ clients.forEach(client => {
122
+ const clientRecord = database.lookup(client);
123
+ if (clientRecord.isActive()) {
124
+ email(client);
125
+ }
126
+ });
127
+ }
128
+
129
+ // Good — cada função tem um trabalho
130
+ function emailActiveClients(clients) {
131
+ clients.filter(isActiveClient).forEach(email);
132
+ }
133
+
134
+ function isActiveClient(client) {
135
+ const clientRecord = database.lookup(client);
136
+ return clientRecord.isActive();
137
+ }
138
+ ```
139
+
140
+ ### 6. Sem flag booleana como argumento
141
+
142
+ A flag avisa que a função tem caminhos diferentes — ou seja, faz mais de uma coisa. Separe.
143
+
144
+ ```javascript
145
+ // Bad
146
+ function createFile(name, temp) {
147
+ if (temp) {
148
+ fs.create(`./temp/${name}`);
149
+ } else {
150
+ fs.create(name);
151
+ }
152
+ }
153
+
154
+ // Good
155
+ function createFile(name) {
156
+ fs.create(name);
157
+ }
158
+
159
+ function createTempFile(name) {
160
+ createFile(`./temp/${name}`);
161
+ }
162
+ ```
163
+
164
+ ### 7. Evite side effects
165
+
166
+ Uma função idealmente recebe valores e retorna valores — não muta estado global nem o objeto/array
167
+ recebido. Mutar dado compartilhado gera bugs em lugares distantes. Centralize os efeitos que forem
168
+ inevitáveis (ex.: escrever em arquivo) em um único serviço.
169
+
170
+ ```javascript
171
+ // Bad — muta uma global; outra função que use `name` quebra
172
+ let name = "Ryan McDermott";
173
+ function splitIntoFirstAndLastName() {
174
+ name = name.split(" ");
175
+ }
176
+
177
+ // Good — recebe e retorna, sem tocar no de fora
178
+ function splitIntoFirstAndLastName(name) {
179
+ return name.split(" ");
180
+ }
181
+ const newName = splitIntoFirstAndLastName(name);
182
+ ```
183
+
184
+ O mesmo vale para arrays/objetos passados por parâmetro: clone em vez de mutar.
185
+
186
+ ```javascript
187
+ // Bad — muta o cart de quem chamou
188
+ const addItemToCart = (cart, item) => {
189
+ cart.push({ item, date: Date.now() });
190
+ };
191
+
192
+ // Good — retorna um novo cart
193
+ const addItemToCart = (cart, item) => {
194
+ return [...cart, { item, date: Date.now() }];
195
+ };
196
+ ```
197
+
198
+ ### 8. Evite condicionais negativas
199
+
200
+ Negativa (ainda mais dupla) força o leitor a inverter a lógica na cabeça. Nomeie no positivo.
201
+
202
+ ```javascript
203
+ // Bad — dupla negação
204
+ function isDOMNodeNotPresent(node) { /* ... */ }
205
+ if (!isDOMNodeNotPresent(node)) { /* ... */ }
206
+
207
+ // Good
208
+ function isDOMNodePresent(node) { /* ... */ }
209
+ if (isDOMNodePresent(node)) { /* ... */ }
210
+ ```
211
+
212
+ ### 9. Encapsule condicionais
213
+
214
+ Uma expressão booleana composta vira uma função com nome que diz a intenção.
215
+
216
+ ```javascript
217
+ // Bad
218
+ if (fsm.state === "fetching" && isEmpty(listNode)) { /* ... */ }
219
+
220
+ // Good
221
+ function shouldShowSpinner(fsm, listNode) {
222
+ return fsm.state === "fetching" && isEmpty(listNode);
223
+ }
224
+ if (shouldShowSpinner(fsmInstance, listNodeInstance)) { /* ... */ }
225
+ ```
226
+
227
+ ### 10. Composição > herança
228
+
229
+ Se sua cabeça já foi pra `extends`, pare e pergunte se é "é-um" (herança) ou "tem-um" (composição).
230
+ `EmployeeTaxData` não é um tipo de `Employee` — um empregado **tem** dados fiscais.
231
+
232
+ ```javascript
233
+ // Bad — herança forçada numa relação "tem-um"
234
+ class EmployeeTaxData extends Employee {
235
+ constructor(ssn, salary) {
236
+ super();
237
+ this.ssn = ssn;
238
+ this.salary = salary;
239
+ }
240
+ }
241
+
242
+ // Good — composição
243
+ class Employee {
244
+ constructor(name, email) {
245
+ this.name = name;
246
+ this.email = email;
247
+ }
248
+ setTaxData(ssn, salary) {
249
+ this.taxData = new EmployeeTaxData(ssn, salary);
250
+ }
251
+ }
252
+ ```
253
+
254
+ ### 11. SOLID em JS — os cinco
255
+
256
+ **S — Single Responsibility.** Uma classe, uma razão para mudar. Separe autenticação de configuração.
257
+
258
+ ```javascript
259
+ // Bad — UserSettings também verifica credenciais
260
+ class UserSettings {
261
+ changeSettings(settings) {
262
+ if (this.verifyCredentials()) { /* ... */ }
263
+ }
264
+ verifyCredentials() { /* ... */ }
265
+ }
266
+
267
+ // Good — auth virou colaboradora
268
+ class UserAuth {
269
+ constructor(user) { this.user = user; }
270
+ verifyCredentials() { /* ... */ }
271
+ }
272
+ class UserSettings {
273
+ constructor(user) {
274
+ this.user = user;
275
+ this.auth = new UserAuth(user);
276
+ }
277
+ changeSettings(settings) {
278
+ if (this.auth.verifyCredentials()) { /* ... */ }
279
+ }
280
+ }
281
+ ```
282
+
283
+ **O — Open/Closed.** Aberto para extensão, fechado para modificação. Em vez de `if adapter.name === ...`,
284
+ deixe cada adapter implementar o contrato.
285
+
286
+ ```javascript
287
+ // Bad — fetch precisa mudar a cada novo adapter
288
+ fetch(url) {
289
+ if (this.adapter.name === "ajaxAdapter") { return makeAjaxCall(url).then(/*...*/); }
290
+ else if (this.adapter.name === "nodeAdapter") { return makeHttpCall(url).then(/*...*/); }
291
+ }
292
+
293
+ // Good — cada adapter tem request(); HttpRequester não muda
294
+ fetch(url) {
295
+ return this.adapter.request(url).then(response => { /* transform */ });
296
+ }
297
+ ```
298
+
299
+ **L — Liskov Substitution.** Subtipo tem que substituir o tipo base sem quebrar resultados. O clássico
300
+ Square/Rectangle: forçar `Square extends Rectangle` faz `getArea()` mentir. Modele ambos sobre `Shape`.
301
+
302
+ ```javascript
303
+ // Good — sem herança que viola contrato
304
+ class Shape { render(area) { /* ... */ } }
305
+ class Rectangle extends Shape {
306
+ constructor(width, height) { super(); this.width = width; this.height = height; }
307
+ getArea() { return this.width * this.height; }
308
+ }
309
+ class Square extends Shape {
310
+ constructor(length) { super(); this.length = length; }
311
+ getArea() { return this.length * this.length; }
312
+ }
313
+ ```
314
+
315
+ **I — Interface Segregation.** Não force o cliente a depender do que não usa. Settings opcionais em vez
316
+ de "fat interface".
317
+
318
+ ```javascript
319
+ // Good — animationModule é opcional, dentro de options
320
+ const $ = new DOMTraverser({
321
+ rootNode: document.getElementsByTagName("body"),
322
+ options: { animationModule() {} }
323
+ });
324
+ ```
325
+
326
+ **D — Dependency Inversion.** Módulo de alto nível não depende do de baixo nível — ambos dependem de
327
+ abstração. Injete a dependência em vez de instanciá-la dentro.
328
+
329
+ ```javascript
330
+ // Bad — InventoryTracker cria a dependência concreta
331
+ class InventoryTracker {
332
+ constructor(items) {
333
+ this.items = items;
334
+ this.requester = new InventoryRequester(); // acoplado
335
+ }
336
+ }
337
+
338
+ // Good — requester é injetado (qualquer um com requestItem serve)
339
+ class InventoryTracker {
340
+ constructor(items, requester) {
341
+ this.items = items;
342
+ this.requester = requester;
343
+ }
344
+ }
345
+ ```
346
+
347
+ ### 12. Lance objetos Error, não strings; e nunca ignore o erro capturado
348
+
349
+ Erros lançados são bons: o runtime te avisa que algo deu errado, com stack trace. Lance um `Error` de
350
+ verdade (carrega mensagem **e** stack), e dê um plano para o `catch` — não engula.
351
+
352
+ ```javascript
353
+ // Tell — string crua não tem stack trace
354
+ throw "Must be of type String or Number";
355
+
356
+ // Good — Error object, com stack
357
+ throw new Error("Must be of type String or Number");
358
+ ```
359
+
360
+ ```javascript
361
+ // Bad — engole o erro
362
+ try {
363
+ functionThatMightThrow();
364
+ } catch (error) {
365
+ console.log(error);
366
+ }
367
+
368
+ // Good — reaja: log de erro, notifique, ou reporte
369
+ try {
370
+ functionThatMightThrow();
371
+ } catch (error) {
372
+ console.error(error);
373
+ notifyUserOfError(error);
374
+ reportErrorToService(error);
375
+ }
376
+ ```
377
+
378
+ O mesmo vale para promises rejeitadas: trate no `.catch`, não só `console.log`.
379
+
380
+ ### 13. Remova código morto
381
+
382
+ Se ninguém chama, apague. O histórico do git guarda. `oldRequestModule` parado ao lado do `new` só
383
+ confunde quem lê.
384
+
385
+ ```javascript
386
+ // Bad — função antiga nunca chamada, mantida "por garantia"
387
+ function oldRequestModule(url) { /* ... */ }
388
+ function newRequestModule(url) { /* ... */ }
389
+ const req = newRequestModule;
390
+
391
+ // Good — só o que está em uso
392
+ function newRequestModule(url) { /* ... */ }
393
+ const req = newRequestModule;
394
+ ```
395
+
396
+ ## Checklist
397
+
398
+ Antes de marcar a task como pronta, responda — qualquer "sim" é dívida a corrigir:
399
+
400
+ - [ ] Tem número/string mágico que deveria ser constante nomeada e pesquisável?
401
+ - [ ] Algum nome é abreviado, não-pronunciável ou exige mapeamento mental (`l`, `d1`, `yyyymmdstr`)?
402
+ - [ ] O mesmo conceito aparece com nomes diferentes (`getUserInfo`/`getClientData`/...)?
403
+ - [ ] Alguma função tem mais de 2-3 argumentos posicionais sem virar objeto?
404
+ - [ ] Há argumento booleano (flag) que denuncia dois caminhos na mesma função?
405
+ - [ ] Alguma função faz mais de uma coisa (mistura busca, transformação e efeito)?
406
+ - [ ] Alguma função muta estado global ou o objeto/array recebido por parâmetro?
407
+ - [ ] Há condicional negativa (ou dupla negação) que poderia ser positiva?
408
+ - [ ] Há booleano composto cru no `if` que mereceria uma função nomeada?
409
+ - [ ] Usei `extends` numa relação "tem-um" em vez de composição?
410
+ - [ ] Lancei string em vez de `new Error(...)`? Engoli algum erro com `console.log` sem reação?
411
+ - [ ] Sobrou código morto (função/branch que ninguém chama)?
412
+
413
+ ## Tabela de decisão
414
+
415
+ | Use isto | Quando |
416
+ |---|---|
417
+ | Constante nomeada (`MILLISECONDS_PER_DAY`) | houver qualquer literal numérico/string com significado no código |
418
+ | Argumento objeto + desestruturação | a função precisar de mais de 2-3 parâmetros |
419
+ | Duas funções separadas | você fosse passar uma flag booleana para escolher o caminho |
420
+ | Receber + retornar (sem mutar) | a função tocaria estado global ou o objeto/array recebido |
421
+ | Clonar (`[...cart, item]`) | precisar "alterar" um array/objeto vindo por parâmetro |
422
+ | Função nomeada (`shouldShowSpinner`) | um `if` tiver booleano composto ou intenção não-óbvia |
423
+ | Condicional no positivo | o nome/teste estiver no negativo (ou em dupla negação) |
424
+ | Composição (`has-a`) | a relação for "tem-um" (`Employee` tem `TaxData`) |
425
+ | Herança (`is-a`) | for genuinamente "é-um", houver reuso da base e mudança global desejada |
426
+ | Injeção de dependência (DIP) | um módulo de alto nível instanciaria diretamente um concreto de baixo nível |
427
+ | Polimorfismo / contrato comum (OCP, LSP) | um `if/switch` ramificar por `type`/`name` e tender a crescer |
428
+ | `throw new Error(...)` + reação no `catch` | algo puder dar errado e você precisar de stack trace e plano |
429
+ | Apagar (confiar no git) | o código não for chamado por ninguém |
@@ -0,0 +1,204 @@
1
+ ---
2
+ id: effective-code-review
3
+ domain: engineering
4
+ agents: [dev, qa]
5
+ when: "ao revisar um pull/merge request ou preparar o próprio CL para review"
6
+ ---
7
+
8
+ # Code review eficaz — o padrão do Google
9
+
10
+ A maioria das discussões de code review trava por falta de um critério compartilhado. Sem ele, o
11
+ review vira gosto pessoal: o revisor segura o CL até ele ficar "do jeito dele", o autor responde na
12
+ defensiva, e o que era pra melhorar o código vira queda de braço. Este pack destila o padrão do Google
13
+ (`google/eng-practices`: *How to do a code review* + *The CL author guide*), porque ele resolve isso com
14
+ **um único critério-mestre** do qual todo o resto deriva.
15
+
16
+ > A fonte chama o pull request de **CL** (changelist). Aqui usamos "CL" e "PR/MR" como sinônimos.
17
+
18
+ ## O problema / os tells
19
+
20
+ Você está num review medíocre quando vê:
21
+
22
+ 1. **Review como busca pela perfeição.** O revisor segura o CL porque "dá pra ficar melhor" — sem que o
23
+ estado atual piore o código. A fonte é direta: *"there is no such thing as 'perfect' code—there is
24
+ only better code."* Perfeição não é o critério; melhoria do code health é.
25
+ 2. **CLs gigantes.** Um PR de 800 linhas espalhado por 40 arquivos. Ninguém revisa de verdade: *"important
26
+ points get missed or dropped."*
27
+ 3. **Feedback sem severidade.** Tudo no mesmo tom. O autor não sabe o que é bloqueante e o que é gosto, e
28
+ trata um typo de comentário com o mesmo peso de um bug de concorrência.
29
+ 4. **Feedback como ordem, nunca como ensino.** O revisor manda "faça X" sem dizer por quê. O autor obedece
30
+ sem aprender; o próximo CL repete o erro.
31
+ 5. **Descrição de CL inútil.** Título "Fix bug", "Phase 1", "Add patch". Daqui a um ano, o `git log` não
32
+ diz nada a ninguém.
33
+ 6. **Review parado por dias.** O CL fica encalhado porque autor e revisor não chegam a acordo, ou porque
34
+ o revisor "depois olha". A velocidade do time inteiro cai.
35
+ 7. **Autor na defensiva.** Resposta no calor, tratando crítica ao código como ataque pessoal — *"never
36
+ respond in anger to code review comments."*
37
+
38
+ ## Os princípios
39
+
40
+ ### 1. O critério-mestre: aprove quando o CL melhora a saúde do código
41
+
42
+ O propósito do review não é provar que o código é perfeito, é garantir que *"the overall code health of
43
+ the codebase is improving over time."* Daí a regra de aprovação:
44
+
45
+ > *"In general, reviewers should favor approving a CL once it is in a state where it definitely improves
46
+ > the overall code health of the system being worked on, even if the CL isn't perfect."*
47
+
48
+ Isso não é desculpa pra deixar passar lixo — a contrapartida é igualmente firme: *"Don't accept CLs that
49
+ degrade the code health of the system."* O CL não precisa ser perfeito; precisa ser **melhor**, e não pode
50
+ piorar. Quando ele claramente melhora e só restam refinamentos opcionais, aprove com comentários (o
51
+ "LGTM with comments"): você libera o autor e confia que ele endereça os nits.
52
+
53
+ ```text
54
+ # ❌ revisor segurando por perfeição
55
+ "Funciona e está mais limpo que o anterior, mas não vou aprovar até você
56
+ extrair essas 3 funções, renomear o módulo e adicionar 4 testes a mais."
57
+
58
+ # ✅ aprovar a melhoria, marcar o resto como opcional
59
+ "LGTM. Melhora clara sobre o que existia. Nit: dá pra extrair `parseHeader`
60
+ numa função à parte depois — opcional, não bloqueia o merge."
61
+ ```
62
+
63
+ ### 2. O que o revisor procura (nesta ordem de importância)
64
+
65
+ A fonte lista explicitamente o que olhar — **design vem primeiro**, não estilo:
66
+
67
+ - **Design.** A interação das peças faz sentido? A mudança pertence a este codebase ou a uma lib? É o
68
+ ponto mais importante do review.
69
+ - **Funcionalidade.** *"Does this CL do what the developer intended?"* Pensa em edge cases, concorrência,
70
+ bugs. Mudança de UI muitas vezes pede um demo pra entender o impacto real no usuário.
71
+ - **Complexidade.** Está *"more complex than it should be"*? O teste prático: se *"can't be understood
72
+ quickly by code readers"*, é complexo demais. Cuidado com over-engineering — resolva o problema que
73
+ você sabe que precisa ser resolvido **agora**, não o especulado.
74
+ - **Testes.** Há testes unit/integration/e2e adequados? Eles **falham quando o código quebra** e fazem
75
+ asserções úteis, sem complexidade desnecessária.
76
+ - **Nomes.** *"long enough to fully communicate what the item is or does, without being so long that it
77
+ becomes hard to read."*
78
+ - **Comentários.** Bons comentários *"explain why"* o código existe — a razão que o código não mostra
79
+ sozinho —, não parafraseiam o que ele faz.
80
+ - **Estilo / consistência.** Style guide é autoridade. Divergência de gosto pessoal vira `Nit:`, não
81
+ bloqueio.
82
+ - **Documentação.** README, docs e referências acompanham a mudança quando relevante.
83
+ - **Cada linha.** Revise todo o código designado — entender cada peça importa pro próximo dev.
84
+ - **Contexto.** Olhe o impacto sistêmico, não só o diff. E **elogie o que está bom**: reconheça boas
85
+ soluções, não só aponte problemas.
86
+
87
+ ### 3. CLs pequenos: o multiplicador de qualidade
88
+
89
+ Tamanho não é detalhe — é o fator que mais muda a qualidade do review. A régua da fonte:
90
+
91
+ > *"100 lines is usually a reasonable size for a CL, and 1000 lines is usually too large."*
92
+
93
+ E o tamanho é sobre **mudança lógica autocontida**, não só contagem bruta: *"A 200-line change in one file
94
+ might be okay, but spread across 50 files it would usually be too large."* O CL certo faz **uma coisa**.
95
+ Na dúvida, *"write CLs that are smaller than you think you need to write."*
96
+
97
+ Por que pequeno ganha: é revisado mais rápido (cinco minutos várias vezes), revisado a fundo (em CL
98
+ grande *"important points get missed or dropped"*), introduz menos bugs, desperdiça menos trabalho se a
99
+ direção estiver errada, dá menos conflito de merge, é mais fácil de desenhar bem e de reverter.
100
+
101
+ ```text
102
+ # ❌ um CL: "Add user profiles"
103
+ migration + model + 3 endpoints + UI + refactor do auth + rename de 12 arquivos
104
+ → 900 linhas, 40 arquivos, ninguém revisa de verdade
105
+
106
+ # ✅ sequência de CLs autocontidos
107
+ CL1: migration + model (~80 linhas)
108
+ CL2: endpoints de leitura + testes (~120 linhas)
109
+ CL3: UI de profile (~150 linhas)
110
+ → cada um revisável em minutos, mergeável e reversível sozinho
111
+ ```
112
+
113
+ ### 4. Dar feedback: severidade explícita, ensinar não impor
114
+
115
+ **Marque a severidade.** O autor precisa distinguir bloqueante de sugestão. Prefixos da fonte:
116
+
117
+ - `Nit:` — *"a minor thing. Technically you should do it, but it won't hugely impact things."*
118
+ - `Optional (ou Consider):` — *"I think this may be a good idea, but it's not strictly required."*
119
+ - `FYI:` — *"I don't expect you to do this in this CL, but you may find this interesting."*
120
+
121
+ **Ensine, não mande.** *"Pointing out problems and letting the developer make a decision often helps the
122
+ developer learn."* Explique o **porquê**. E quando o código está complexo demais, *"encourage developers
123
+ to simplify code or add code comments instead of just explaining the complexity to you"* — o ganho fica
124
+ no código, não na conversa do review. Sempre: *"courteous and respectful while also being very clear and
125
+ helpful."*
126
+
127
+ ```text
128
+ # ❌ ordem sem razão, severidade ambígua
129
+ "Use um map aqui."
130
+
131
+ # ✅ aponta o problema, ensina, marca severidade
132
+ "Este loop aninhado é O(n²); com a lista de pedidos crescendo isso vira gargalo.
133
+ Um map de id→pedido resolve em O(n). Required."
134
+
135
+ # nit de verdade, marcado como tal:
136
+ "Nit: `d` poderia ser `daysUntilDue` pra ficar autoexplicativo. Opcional."
137
+ ```
138
+
139
+ ### 5. O guia do AUTOR
140
+
141
+ - **Descrição do CL.** Primeira linha = resumo curto, no **imperativo** ("Delete the FizzBuzz RPC and
142
+ replace it with the new system"), dizendo **o que** muda. Corpo = **o quê e por quê**, com números de
143
+ bug, benchmarks e links de design. Ruins (da fonte): "Fix bug", "Fix build", "Add patch", "Phase 1",
144
+ "kill weird URLs" — *"do not provide enough useful information."* Bom: *"RPC: Remove size limit on RPC
145
+ server message freelist. Servers like FizzBuzz have very large messages and would benefit from reuse."*
146
+ - **Responder a reviews.** *"Don't take it personally"* — a crítica é ao código, não a você. Nunca
147
+ responda com raiva. Se o revisor não entendeu, **conserte o código** primeiro; se não dá pra clarear,
148
+ adicione um comentário no código explicando o porquê; explicar só no review tool é último recurso (o
149
+ próximo leitor não vê a thread do PR).
150
+ - **Discordar bem.** Pense em colaboração, não defesa: *"I went with X because of [these pros/cons]... Are
151
+ you suggesting that Y better serves the original tradeoffs?"*
152
+
153
+ ### 6. Resolver conflitos e velocidade
154
+
155
+ Conflito entre autor e revisor se resolve por **fatos, não preferências**: *"Technical facts and data
156
+ overrule opinions and personal preferences."* Style guide é autoridade no estilo. Busquem consenso; se
157
+ não houver, apliquem os princípios deste padrão e, persistindo, escalem pra liderança técnica. Acima de
158
+ tudo: *"Don't let a CL sit around because the author and the reviewer can't come to an agreement."*
159
+
160
+ **Velocidade:** o que importa é o **tempo de resposta**, não o tempo total do CL. A régua: *"One business
161
+ day is the maximum time it should take to respond to a code review request."* Se você não está no meio de
162
+ uma tarefa focada, revise logo que o CL chega; se está codando concentrado, *"don't interrupt yourself"*
163
+ — responda num ponto natural de pausa. Review lento derruba a velocidade do time inteiro.
164
+
165
+ ## Checklist
166
+
167
+ Antes de **aprovar** um CL:
168
+
169
+ - [ ] O CL **melhora** a saúde do código e **não a piora**? (critério-mestre — não exija perfeição)
170
+ - [ ] O **design** faz sentido e a mudança pertence a este codebase?
171
+ - [ ] Faz o que o autor pretendeu, incluindo edge cases e concorrência?
172
+ - [ ] Não está mais complexo que o necessário, sem over-engineering pra o futuro?
173
+ - [ ] Tem testes que **falham quando o código quebra**, com asserções úteis?
174
+ - [ ] Nomes claros, comentários que explicam o **porquê**, docs atualizadas?
175
+ - [ ] Revisei **cada linha** designada e elogiei o que está bom?
176
+ - [ ] Marquei a **severidade** (`Nit:`/`Optional:`/`FYI:`) e expliquei o **porquê** de cada comentário?
177
+ - [ ] Respondi em até **um dia útil**?
178
+
179
+ Antes de **enviar** o próprio CL:
180
+
181
+ - [ ] É **uma mudança autocontida** (~100 linhas; 1000 é grande demais; cuidado com o espalhamento)?
182
+ - [ ] A descrição tem primeira linha no imperativo + corpo com **o quê e por quê** (não "Fix bug")?
183
+ - [ ] Vou responder ao review sobre o **código**, sem levar pro pessoal?
184
+
185
+ ## Tabela de decisão
186
+
187
+ | Situação | O que fazer |
188
+ |---|---|
189
+ | CL melhora o código mas não está perfeito | **Aprove** (LGTM with comments); marque refinamentos como `Nit:`/`Optional:` |
190
+ | CL piora a saúde do código | **Não aprove**; aponte o problema com o porquê |
191
+ | Comentário é gosto pessoal / estilo | `Nit:`; não bloqueie o merge por isso |
192
+ | Comentário é design/funcionalidade/segurança | Required; bloqueie e explique o porquê |
193
+ | CL > ~1000 linhas ou espalhado por dezenas de arquivos | Peça pra **quebrar** em CLs autocontidos |
194
+ | Código complexo demais de entender | Peça **simplificar ou comentar no código** — não aceite explicação só no PR |
195
+ | Quer que o dev aprenda | Aponte o **problema** e deixe ele decidir, em vez de dar a ordem pronta |
196
+ | Autor e revisor não chegam a acordo | Decida por **fatos/dados** e pelo style guide; persistindo, **escale** — não deixe o CL parado |
197
+ | Chegou um review e você não está focado em outra coisa | Revise **logo** (alvo: resposta em ≤ 1 dia útil) |
198
+ | Chegou um review e você está codando concentrado | Não se interrompa; responda numa **pausa natural** |
199
+ | Revisor não entendeu seu código | **Conserte o código** ou comente nele o porquê; explicar só no PR é último recurso |
200
+
201
+ ---
202
+
203
+ **Fonte:** Google Engineering Practices — `google.github.io/eng-practices`
204
+ (*How to do a code review* e *The CL author guide*).