@luanpdd/kit-mcp 1.34.0 → 1.36.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 (118) hide show
  1. package/README.md +1 -1
  2. package/bin/cli.js +2 -2
  3. package/bin/mcp.js +6 -6
  4. package/bin/ui.js +74 -74
  5. package/gates/ai-prompt-stability.md +120 -120
  6. package/gates/budget-description.md +68 -68
  7. package/gates/confidence.md +29 -29
  8. package/gates/dependency-check.md +33 -33
  9. package/gates/dept-cycle-prevention.md +179 -179
  10. package/gates/golden-signals-coverage.md +133 -133
  11. package/gates/legacy-refactor-safety.md +178 -178
  12. package/gates/multi-tenant-rls-coverage.md +102 -102
  13. package/gates/no-personal-uuid.md +72 -72
  14. package/gates/obs-agents-mcp-supabase.md +86 -86
  15. package/gates/obs-skills-frontmatter.md +76 -76
  16. package/gates/observability-coverage.md +151 -151
  17. package/gates/omm-no-regression.md +83 -83
  18. package/gates/postmortem-template-required.md +127 -127
  19. package/gates/prr-checklist-coverage.md +128 -128
  20. package/gates/regression.md +32 -32
  21. package/gates/release-pipeline-policy.md +132 -132
  22. package/gates/secrets-scan.md +33 -33
  23. package/gates/service-role-not-in-user-facing.md +113 -113
  24. package/gates/skill-must-include.md +71 -71
  25. package/gates/sync-idempotent.md +62 -62
  26. package/gates/verify-phase-goal.md +34 -34
  27. package/kit/agents/designer-ui.md +216 -216
  28. package/kit/agents/workflow-generator.md +537 -0
  29. package/kit/commands/adicionar-backlog.md +1 -1
  30. package/kit/commands/adicionar-fase.md +1 -1
  31. package/kit/commands/adicionar-tarefa.md +1 -1
  32. package/kit/commands/auditar-observabilidade.md +103 -103
  33. package/kit/commands/auditar-toil.md +129 -129
  34. package/kit/commands/caracterizar-prompt.md +195 -195
  35. package/kit/commands/criar-workflow.md +158 -0
  36. package/kit/commands/definir-perfil.md +1 -1
  37. package/kit/commands/definir-slo.md +108 -108
  38. package/kit/commands/fio.md +1 -1
  39. package/kit/commands/golden-signals.md +142 -142
  40. package/kit/commands/instrumentar-fase.md +200 -200
  41. package/kit/commands/investigar-producao.md +162 -162
  42. package/kit/commands/observabilidade.md +118 -118
  43. package/kit/commands/postmortem.md +179 -179
  44. package/kit/commands/prr.md +205 -205
  45. package/kit/commands/publicar-rapido.md +207 -207
  46. package/kit/commands/risk-budget.md +220 -220
  47. package/kit/commands/sre.md +230 -230
  48. package/kit/file-manifest.json +5 -2
  49. package/kit/framework/references/output-style.md +22 -22
  50. package/kit/hooks/post-apply-migration.js +199 -199
  51. package/kit/hooks/sidecar-tool-publisher.js +210 -210
  52. package/kit/skills/_shared-dados-distribuidos/glossary.md +224 -224
  53. package/kit/skills/_shared-legacy/glossary.md +389 -389
  54. package/kit/skills/_shared-multi-tenant/glossary.md +186 -186
  55. package/kit/skills/_shared-observability/glossary.md +396 -396
  56. package/kit/skills/_shared-sre/glossary.md +712 -712
  57. package/kit/skills/_shared-supabase/glossary.md +234 -234
  58. package/kit/skills/blameless-postmortems/SKILL.md +340 -340
  59. package/kit/skills/burn-rate-alerting/SKILL.md +258 -258
  60. package/kit/skills/cascading-failures/SKILL.md +311 -311
  61. package/kit/skills/core-analysis-loop/SKILL.md +352 -352
  62. package/kit/skills/distributed-tracing/SKILL.md +362 -362
  63. package/kit/skills/dynamic-workflow-authoring/SKILL.md +327 -0
  64. package/kit/skills/eliminating-toil/SKILL.md +243 -243
  65. package/kit/skills/event-based-slos/SKILL.md +296 -296
  66. package/kit/skills/four-golden-signals/SKILL.md +314 -314
  67. package/kit/skills/hermetic-builds/SKILL.md +323 -323
  68. package/kit/skills/legacy-monster-methods/SKILL.md +444 -444
  69. package/kit/skills/llm-as-dependency/SKILL.md +436 -436
  70. package/kit/skills/load-shedding-graceful-degradation/SKILL.md +396 -396
  71. package/kit/skills/observability-driven-development/SKILL.md +315 -315
  72. package/kit/skills/observability-maturity-model/SKILL.md +222 -222
  73. package/kit/skills/opentelemetry-standard/SKILL.md +351 -351
  74. package/kit/skills/production-readiness-review/SKILL.md +305 -305
  75. package/kit/skills/release-engineering/SKILL.md +367 -367
  76. package/kit/skills/retry-strategies/SKILL.md +372 -372
  77. package/kit/skills/sre-risk-management/SKILL.md +221 -221
  78. package/kit/skills/structured-events/SKILL.md +265 -265
  79. package/kit/skills/supabase-cron-queues/SKILL.md +275 -275
  80. package/kit/skills/supabase-database-functions/SKILL.md +332 -332
  81. package/kit/skills/supabase-declarative-schema/SKILL.md +183 -183
  82. package/kit/skills/supabase-pgvector-rag/SKILL.md +253 -253
  83. package/kit/skills/supabase-postgres-style/SKILL.md +138 -138
  84. package/kit/skills/supabase-storage/SKILL.md +234 -234
  85. package/kit/skills/telemetry-pipelines/SKILL.md +259 -259
  86. package/kit/skills/telemetry-sampling/SKILL.md +256 -256
  87. package/kit/skills/ui-anti-padroes-ia/SKILL.md +261 -261
  88. package/kit/skills/ui-contexto-produto/SKILL.md +248 -248
  89. package/kit/skills/ui-cor-estrategia/SKILL.md +213 -213
  90. package/kit/skills/ui-critica-auditoria/SKILL.md +260 -260
  91. package/kit/skills/ui-motion-funcional/SKILL.md +264 -264
  92. package/kit/skills/ui-ritmo-espacial/SKILL.md +259 -259
  93. package/kit/skills/ui-tipografia/SKILL.md +211 -211
  94. package/package.json +1 -1
  95. package/src/cli/index.js +1114 -1114
  96. package/src/cli/render.js +194 -194
  97. package/src/cli/upgrade-check.js +135 -135
  98. package/src/core/error-redaction.js +76 -76
  99. package/src/core/failures.js +153 -153
  100. package/src/core/gate-runner.js +205 -205
  101. package/src/core/gates.js +82 -82
  102. package/src/core/logger.js +170 -170
  103. package/src/core/manifest-verify.js +174 -174
  104. package/src/core/metrics.js +268 -268
  105. package/src/core/notify.js +60 -60
  106. package/src/core/path-safety.js +141 -141
  107. package/src/core/replays.js +120 -120
  108. package/src/core/ui.js +185 -185
  109. package/src/mcp-server/install.js +149 -149
  110. package/src/mcp-server/roots.js +124 -124
  111. package/src/ui/auto-spawn.js +113 -113
  112. package/src/ui/browser.js +78 -78
  113. package/src/ui/client.js +130 -130
  114. package/src/ui/events.js +65 -65
  115. package/src/ui/lockfile.js +191 -191
  116. package/src/ui/port.js +67 -67
  117. package/src/ui/server.js +547 -547
  118. package/src/ui/wrapper.js +129 -129
@@ -1,389 +1,389 @@
1
- # Glossário Legacy Code — Termos, Técnicas e Patterns Canônicos
2
-
3
- > Arquivo de referência compartilhado pelas skills `legacy-*` e `pre-refactor-characterization`. **NÃO é skill** — não tem `description:` triggerável; não aparece em `listKit`. Cross-referenciado pelas skills via Markdown link relativo.
4
-
5
- > **Material-fonte:** *Working Effectively with Legacy Code* — Michael C. Feathers (Prentice Hall / Robert C. Martin Series, 2004). ISBN 978-0-13-117705-5.
6
-
7
- ---
8
-
9
- ## (a) Termos PT-BR ↔ EN
10
-
11
- ### Definições fundacionais
12
-
13
- > Vocabulário do prefácio + cap 1 (Changing Software). A definição de Feathers é deliberadamente operacional, não emocional — "legacy code" não significa "código antigo" ou "código feio", significa **código sem testes**. Essa redefinição muda completamente a estratégia: o problema é falta de cobertura comportamental, não estética.
14
-
15
- | EN | PT-BR / Significado |
16
- |---|---|
17
- | **legacy code** | Código legado — para Feathers: **código sem testes**, independente de idade ou qualidade. Sem testes, qualquer mudança é "edit and pray" — você modifica e reza. |
18
- | **edit and pray** | Editar e rezar — o modo default em legacy code. Você muda, lê o diff, deploya, espera. Confiança vem de inspeção visual + sorte. |
19
- | **cover and modify** | Cobrir e modificar — o modo desejado. Primeiro adicione cobertura (tests), depois modifique. Confiança vem do safety net. |
20
- | **change point** | Ponto de mudança — local específico onde a alteração será feita. Tipicamente uma linha, método ou bloco. |
21
- | **inflection point** | Ponto de inflexão — junção estreita por onde os efeitos da mudança fluem. Testar aqui cobre múltiplos change points downstream. |
22
- | **pinch point** | Funil estreito (sinônimo de inflection point usado em cap 11) — interface natural na qual concentrar testes. |
23
- | **safety net** | Rede de segurança — suite de testes que detecta regressão imediatamente após edição. Cap 1 é todo sobre construir isso. |
24
- | **legacy code dilemma** | Dilema do código legado — para mudar com segurança preciso testar; para testar preciso refatorar; para refatorar preciso testar. Quebrado por **dependency-breaking techniques** (cap 25). |
25
-
26
- ### Seams e Test Harness
27
-
28
- > Vocabulário do cap 4 (The Seam Model). Conceito central. Seam = lugar onde você pode alterar comportamento **sem editar naquele lugar**. Sem seams, o código está "fundido" — toda mudança requer modificação direta, sem possibilidade de substituição em teste.
29
-
30
- | EN | PT-BR / Significado |
31
- |---|---|
32
- | **seam** | Costura — local onde se pode alterar comportamento sem editar ali. Tipicamente onde existe ponto de extensibilidade que pode ser exercitado por testes. |
33
- | **enabling point** | Ponto habilitador — mecanismo concreto que ativa a substituição naquela costura (subclasse, link table, build flag, parâmetro). |
34
- | **preprocessing seam** | Costura de pré-processamento — substituição via macros/preprocessor (C/C++). Raríssima em runtimes modernos. |
35
- | **link seam** | Costura de link — substituição via linker (DLL/object/jar) ou loader (require/import shim). Útil em código sem orientação a objetos. |
36
- | **object seam** | Costura de objeto — substituição via polimorfismo (interface, classe abstrata, duck typing). A mais comum e poderosa em OO. |
37
- | **test harness** | Arnês de teste — infraestrutura mínima para fazer um pedaço de código rodar isolado em testes. Cap 9-10 inteiro é sobre construir isso. |
38
- | **dependency** | Dependência — qualquer entidade externa que o código sob teste invoca. Bloqueia testes quando incontrolável (DB real, rede, clock, FS). |
39
- | **collaborator** | Colaborador — instância concreta de uma dependência. Ex.: `EmailSender` vs concept "envio de email". |
40
- | **fake** | Fake — implementação substituta de uma dependência que satisfaz a interface mas não faz o trabalho real (ex: `FakeEmailSender` que só salva em lista). |
41
- | **sensing** | Sensoriamento — observar via testes que algo aconteceu (assertion sobre `fake.sentEmails.length`). |
42
- | **separation** | Separação — quebrar a dependência para que o código rode sem o colaborador real. Pré-requisito de sensing. |
43
- | **break dependencies** | Quebrar dependências — aplicar uma das ~24 técnicas do cap 25 para tornar testável o que não era. |
44
-
45
- ### Characterization Tests
46
-
47
- > Vocabulário do cap 13 (Characterization Tests). **A skill foundacional**. Characterization test não verifica se o código está certo — verifica **o que o código atualmente faz**. É um snapshot comportamental que vira oracle imutável durante o refactor.
48
-
49
- | EN | PT-BR / Significado |
50
- |---|---|
51
- | **characterization test** | Teste de caracterização — teste que captura o comportamento **atual** do código (não o desejado). Não pergunta "está certo?" — pergunta "o que faz?". |
52
- | **golden master** | Mestre dourado — output capturado de uma execução real, salvo em arquivo, que vira oracle. Subsequentes execuções comparam contra ele (snapshot test). |
53
- | **golden snapshot** | Snapshot dourado — sinônimo de golden master, terminologia mais comum em frameworks modernos (Jest, Vitest, Pytest). |
54
- | **expected behavior trap** | Armadilha do "comportamento esperado" — escrever testes do que o código **deveria** fazer em vez do que **faz**. Resultado: teste falha imediatamente porque o bug atual é o estado atual. Sempre comece pelo atual. |
55
- | **bug preservation** | Preservação de bug — characterization tests preservam bugs existentes. Refactor não muda comportamento, então o bug deve continuar reproduzível. Bug fix é outra mudança, separada. |
56
- | **observation point** | Ponto de observação — saída capturada (return value, side effect, log, DB write). Cada ponto vira uma asserção. |
57
- | **input enumeration** | Enumeração de entradas — cobrir caminhos via grupos de equivalência: input nulo, vazio, válido típico, válido extremo, inválido recoverable, inválido fatal. |
58
- | **behavioral coverage** | Cobertura comportamental — não % de linhas executadas, mas % de **branches** + observation points. Métrica para liberar refactor é cobertura comportamental, não code coverage. |
59
- | **edit-then-characterize** | Editar-então-caracterizar — anti-pattern. Você muda, depois escreve teste do "novo" comportamento. Não há baseline para detectar quebra. |
60
-
61
- ### Sprout / Wrap Techniques
62
-
63
- > Vocabulário do cap 6 (I Don't Have Much Time and I Have to Change It). Quando você não tem tempo para colocar legado em test harness, mas precisa adicionar comportamento novo. Estratégia: adicionar código novo **isolado** e testado, conectado ao legado por chamada mínima.
64
-
65
- | EN | PT-BR / Significado |
66
- |---|---|
67
- | **sprout method** | Método broto — extrair a nova lógica para método novo (tipicamente `static` ou injetável), testar isolado, chamar do método legado em 1 linha. |
68
- | **sprout class** | Classe broto — quando o sprout method cresce, externalize para classe nova com test harness próprio. |
69
- | **wrap method** | Método invólucro — renomeie o método legado (`foo` → `fooLegacy`), crie `foo` novo que chama `fooLegacy` + nova lógica. Novo `foo` é testável. |
70
- | **wrap class** | Classe invólucro — análogo ao wrap method em escala de classe. Decorator pattern aplicado pragmaticamente. |
71
- | **boy scout rule (sprout edition)** | Regra do escoteiro (versão sprout) — deixe o código mais limpo do que encontrou ao **adicionar** novo, mesmo sem refatorar o velho. Sprout/wrap concretiza isso. |
72
-
73
- ### Effect Analysis
74
-
75
- > Vocabulário do cap 11 (I Need to Make a Change. What Methods Should I Test?) e cap 12 (I Need to Make Many Changes in One Area). Sem testes, qual é o subset mínimo de coisas a testar para sentir-se seguro? Resposta: rastreie efeitos do change point para fora, encontre inflection points, teste lá.
76
-
77
- | EN | PT-BR / Significado |
78
- |---|---|
79
- | **effect sketch** | Esboço de efeitos — diagrama (papel mesmo) com setas do change point para tudo que muda. Variáveis afetadas, retornos, side effects, callbacks. |
80
- | **effect propagation** | Propagação de efeito — como um change ripple através do código. Cap 11 lista 4 vetores: return value, parâmetros mutados, globals, side effects via colaborador. |
81
- | **interception point** | Ponto de interceptação — local onde inserir teste para observar efeitos. Idealmente coincide com inflection point. |
82
- | **effect-narrowing** | Estreitamento de efeito — refatorar para reduzir o número de pontos afetados (encapsular variáveis, eliminar globals). Pré-trabalho para tornar effect sketch menor. |
83
- | **shotgun surgery** | Cirurgia espalhada — anti-pattern (cap 21): mesma mudança espalhada em N lugares; cada incidência é um change point separado. Effect sketch detecta. |
84
-
85
- ### Monster Methods
86
-
87
- > Vocabulário do cap 22 (I Need to Change a Monster Method and I Can't Write Tests for It). Métodos absurdamente longos (> 200 linhas) onde você não consegue nem entender o que faz, muito menos testar. Estratégia: scratch refactoring + single-goal editing + extrair pedacinhos sem mudar comportamento.
88
-
89
- | EN | PT-BR / Significado |
90
- |---|---|
91
- | **monster method** | Método monstro — método com várias páginas de código, múltiplos níveis de aninhamento, múltiplas responsabilidades. Heurística: > 100 linhas ou > 5 níveis de indent. |
92
- | **bulleted method** | Método com bullets — variante: linhas longas mas planas (sem nesting). Mais fácil de domar. |
93
- | **snarled method** | Método emaranhado — variante: nesting profundo, condicionais aninhadas, control flow espaguete. Mais difícil. |
94
- | **scratch refactoring** | Refactor de rascunho — quebra estética sem commitar. Use uma branch lixo, refatore para entender, descarte. Conhecimento adquirido vai para a refatoração real. |
95
- | **single-goal editing** | Edição com objetivo único — mudar UMA coisa por vez. Renomear OU extrair OU mover, nunca os 3 juntos. Cada mudança é um diff legível. |
96
- | **safe extraction** | Extração segura — extrair método sem mover lógica entre escopos. Apenas levantar bloco contíguo + capturar variáveis usadas como parâmetros. |
97
- | **method blob** | Blob de método — sinônimo informal de monster method. |
98
-
99
- ### Dependency-Breaking Techniques
100
-
101
- > Vocabulário do cap 25 (Dependency-Breaking Techniques) — o catálogo principal. ~24 técnicas para tornar testável o que não era. Cada técnica tem trade-offs diferentes (segurança, custo, mecanização).
102
-
103
- | EN | PT-BR / Significado |
104
- |---|---|
105
- | **subclass and override method** | Subclassificar e sobrescrever método — criar subclasse de teste que substitui método problemático. Funciona em qualquer linguagem com herança virtual. |
106
- | **extract interface** | Extrair interface — criar interface a partir da classe concreta, fazer cliente depender da interface, fornecer fake implementation em teste. |
107
- | **adapt parameter** | Adaptar parâmetro — quando parâmetro tem tipo difícil de criar (ex: `HttpServletRequest`), envolver em interface mais simples e fazer cliente depender dela. |
108
- | **introduce static setter** | Introduzir setter estático — adicionar setter para singleton/global; teste injeta fake; teardown restaura. **Risk: thread safety** — só em ambientes single-threaded de teste. |
109
- | **encapsulate global references** | Encapsular referências globais — substituir acesso direto a variáveis globais por método de instância da classe. Permite override em teste. |
110
- | **expose static method** | Expor método estático — promover método de instância a estático para testar sem instanciar a classe inteira (quando construtor é caro). |
111
- | **break out method object** | Quebrar para method object — extrair método grande para classe com `run()`. Variáveis locais viram fields, fácil de testar. |
112
- | **parameterize constructor** | Parametrizar construtor — passar dependência via construtor (DI manual) em vez de criar dentro. Default constructor mantém retrocompatibilidade. |
113
- | **parameterize method** | Parametrizar método — passar dependência como argumento da chamada. Útil quando dependency só é usada num método específico. |
114
- | **pull up feature** | Subir feature — mover método/field para superclasse para que subclasse de teste possa override. |
115
- | **push down dependency** | Empurrar dependência — mover dependência problemática para subclasse, fazer base abstrata sem ela; teste usa subclasse de teste sem dependência real. |
116
- | **replace function with function pointer** | Substituir função por ponteiro de função — em C, substituir chamada estática por ponteiro que teste pode reapontar. |
117
- | **introduce instance delegator** | Introduzir delegador de instância — método estático vira fino wrapper que chama método de instância injetada. Permite mock. |
118
- | **link substitution** | Substituição de link — providenciar `.so`/`.dll`/`.jar` alternativo em test classpath/library path. |
119
- | **definition completion** | Completar definição (C/C++) — fornecer `.cpp` alternativo no link de teste para sobrescrever função declarada em `.h`. |
120
-
121
- ---
122
-
123
- ## (b) Patterns canônicos
124
-
125
- ### Pattern: Algoritmo de mudança em legacy code (cap 1)
126
-
127
- ```text
128
- 1. Identify change points (onde mudar)
129
- 2. Find test points (onde testar — idealmente nas inflection points)
130
- 3. Break dependencies (cap 25 — aplicar técnica adequada)
131
- 4. Write characterization tests (cap 13 — congelar comportamento atual)
132
- 5. Make changes and refactor (cover and modify, não edit and pray)
133
- ```
134
-
135
- **Insight central:** os passos 1-4 são **investimento prévio à mudança**. Quem pula direto ao passo 5 está em "edit and pray" — pode ter sorte 9 vezes em 10 mas a 10ª vez é incident SEV1.
136
-
137
- ### Pattern: identificar legacy code via critérios
138
-
139
- ```text
140
- Um arquivo/módulo é "legacy" no sentido Feathers se:
141
-
142
- 1. Cobertura de testes < 60%? → SIM → legacy
143
- 2. Existem branches sem teste algum? → SIM → legacy
144
- 3. Mudanças recentes (último mês) não tiveram teste novo correspondente? → SIM → legacy
145
- 4. Faz parte de contrato externo (webhook, API pública, integração)? → SIM → legacy MESMO COM testes (porque consumer breakage é pior)
146
- 5. Tem mais de 500 linhas em arquivo único? → SIM → legacy candidate (pelo menos suspeito)
147
- 6. Tem métodos > 100 linhas? → SIM → monster methods, candidato a cap 22
148
-
149
- Heurística agregada: se 2+ critérios = legacy → exigir characterization tests antes de qualquer refactor.
150
- ```
151
-
152
- ### Pattern: decision tree para escolher técnica de quebra de dependência
153
-
154
- ```text
155
- Posso modificar o código? (acesso write?)
156
- ├─ Não → preprocessing seam (C/C++) ou link seam (qualquer linguagem)
157
- └─ Sim →
158
- ├─ Linguagem tem herança/polimorfismo? (Java, C#, Python, Ruby, TS...)
159
- │ ├─ Sim → object seam (preferred)
160
- │ │ ├─ Dependência é classe? → extract interface OU subclass and override
161
- │ │ ├─ Dependência é singleton/global? → encapsulate global references OU introduce static setter
162
- │ │ ├─ Dependência é tipo de framework? (HttpServletRequest, Context) → adapt parameter
163
- │ │ └─ Dependência é construído internamente? → parameterize constructor / parameterize method
164
- │ └─ Não (C, COBOL, código procedural) → link seam OU function pointer substitution
165
- └─ Construtor da classe é caro? → expose static method (testar sem instanciar)
166
- ```
167
-
168
- ### Pattern: Sprout decision tree (cap 6)
169
-
170
- ```text
171
- Tenho que adicionar comportamento a método não testado.
172
-
173
- Tenho tempo para colocar o método inteiro sob test harness primeiro?
174
- ├─ Sim → técnicas do cap 25 (preferencial)
175
- └─ Não →
176
- ├─ Comportamento novo é coeso e separável? → SPROUT METHOD
177
- │ 1. Escrever método novo (static ou de classe nova) — testável
178
- │ 2. Chamar do método legado em 1 linha
179
- │ 3. Test do sprout via test harness próprio
180
- │ 4. Método legado permanece untested mas o NOVO comportamento está coberto
181
- ├─ Comportamento novo é grande (>30 linhas)? → SPROUT CLASS
182
- │ 1. Criar classe nova encapsulando o novo comportamento
183
- │ 2. Construir + chamar a classe do método legado
184
- │ 3. Test class isoladamente
185
- └─ Preciso modificar pré ou pós-condição do método legado? → WRAP METHOD
186
- 1. Renomear `foo` → `fooLegacy` (apenas mecânico)
187
- 2. Criar novo `foo` que chama `fooLegacy` + adiciona comportamento
188
- 3. Testes do `foo` cobrem composição; `fooLegacy` ainda untested mas chamável
189
- ```
190
-
191
- ### Pattern: characterization tests workflow (cap 13)
192
-
193
- ```text
194
- 1. Escolher input typical → rodar código → capturar output
195
- 2. Escrever teste assertando output capturado (mesmo se output for um bug)
196
- 3. Repetir para 5-10 inputs cobrindo grupos de equivalência:
197
- - null/vazio
198
- - válido típico
199
- - válido extremo (boundaries)
200
- - inválido recoverable
201
- - inválido fatal
202
- 4. Rodar todos verde → BASELINE estabelecido
203
- 5. AGORA refactor pode começar — qualquer test que vire vermelho = regressão real
204
- ```
205
-
206
- **Anti-pattern:** começar a "consertar" o teste para o output "correto". Isso destrói o oracle. Bug → preserve, fix em commit separado depois do refactor.
207
-
208
- ### Pattern: 6 níveis de "está testável?" (cap 9-10)
209
-
210
- | Nível | Sintoma | Solução |
211
- |---|---|---|
212
- | **L0** | Não consigo construir a classe (construtor irritado, faz I/O, throws) | Cap 9 técnicas — fake constructor parameters, expose static method |
213
- | **L1** | Classe constrói mas método não roda isolado (depende de globals) | Encapsulate global references |
214
- | **L2** | Método roda mas dependências reais (DB, rede, clock) executam | Inject collaborator OR subclass and override |
215
- | **L3** | Dependências stubadas mas effects spread (DB grava, email envia) | Sense via fake (verify-no-side-effect) |
216
- | **L4** | Roda isolado, mas saída não-determinística (random, datetime.now) | Inject clock/random como dependência |
217
- | **L5** | Roda isolado e determinístico mas eu não entendo o que testa | Characterization tests para descobrir |
218
-
219
- Meta é L5+. Antes de refatorar, código deve estar em L4 ou melhor.
220
-
221
- ---
222
-
223
- ## (c) Anti-patterns canônicos
224
-
225
- ### ANTI: refactor sem characterization tests
226
-
227
- ```text
228
- ANTI: "vou refatorar esse método de 200 linhas, depois adiciono testes do
229
- novo design".
230
-
231
- PROBLEMA: você não sabe o que está preservando. O método tem branches que
232
- você não sabe que existem. Bugs antigos que clientes dependem
233
- (Hyrum's Law) somem silenciosamente. Resultado típico: incident
234
- em prod 2 semanas depois quando edge case dispara.
235
-
236
- CERTO: characterize first (cap 13), refactor second. Pelo menos 5-10
237
- inputs cobrindo grupos de equivalência ANTES de mover qualquer
238
- linha. Se o método é de 200 linhas, esse trabalho leva 1-2 dias.
239
- Aceite o custo — alternativa é o incident.
240
- ```
241
-
242
- ### ANTI: edit and pray (cap 1)
243
-
244
- ```text
245
- ANTI: "vou modificar essa linha, rodar smoke test, dar push e ver no
246
- monitoring".
247
-
248
- PROBLEMA: smoke test cobre golden path. Branches raras (1% do tráfego)
249
- escapam silenciosamente. Bugs em borda manifestam horas/dias
250
- depois. Forensics fica difícil porque change set tem N edits
251
- no mesmo PR.
252
-
253
- CERTO: cover and modify. Antes de modificar, encontre o seam e adicione
254
- teste que exercita a branch específica. Se não há seam, primeiro
255
- adicione um (cap 25). Investimento de 1-4h vs incident de 4-40h.
256
- ```
257
-
258
- ### ANTI: fix bug ANTES do characterization
259
-
260
- ```text
261
- ANTI: "ah, esse método tem um bug óbvio na linha 42, vou consertar
262
- enquanto refatoro".
263
-
264
- PROBLEMA: characterization test capturou o bug como comportamento
265
- esperado. Você consertou → teste fica vermelho → você
266
- "atualiza o teste" → oracle morto → não há baseline mais.
267
-
268
- CERTO: 2 commits separados. (1) characterize + refactor preservando
269
- bug. (2) bug fix com teste novo do comportamento correto. Aplique
270
- o fix DEPOIS, com seu próprio test antes (TDD agora possível
271
- porque você tem test harness funcionando).
272
- ```
273
-
274
- ### ANTI: golden master sem revisão humana
275
-
276
- ```text
277
- ANTI: rodar code → capturar output → commitar como `expected.txt` sem
278
- ler. "É o que o código produz, deve estar certo".
279
-
280
- PROBLEMA: output captura inclui bugs já existentes. Sem revisão, você
281
- congela bugs como contrato. Se o output incluir PII, secret,
282
- UUID local — você acabou de commitar dado sensível.
283
-
284
- CERTO: ler o output capturado linha por linha antes de salvar. Marcar
285
- expectativas conhecidas-buggy com comentário inline (`// BUG #123:
286
- deveria ser X, é Y`). Redact PII/secret/UUID via post-processing
287
- deterministic (hash, mask). Commit do golden é uma decisão, não
288
- um copy-paste.
289
- ```
290
-
291
- ### ANTI: monster method "limpado" em 1 PR
292
-
293
- ```text
294
- ANTI: PR com 800 linhas de diff: extract method × 12, rename × 5, move
295
- logic × 3, fix off-by-one × 2 — tudo junto.
296
-
297
- PROBLEMA: PR não-revisável. Reviewer não consegue separar refactor
298
- (nullable) de fix (semântico). Se algo quebra, bisect aponta
299
- para o PR inteiro. CI verde não significa nada — branch
300
- coverage caiu silenciosa.
301
-
302
- CERTO: 1 PR por single-goal edit (cap 22). Sequência típica:
303
- PR1 — extract method (3 helpers, mecânico, comportamento idêntico)
304
- PR2 — extract class (mover helpers para nova classe)
305
- PR3 — invert dependency (constructor injection)
306
- PR4 — fix bug X (com teste novo, semântico)
307
- Cada PR ≤ 100 linhas. Cada um é revisável e revertível.
308
- ```
309
-
310
- ### ANTI: substituir testes "falhos" sem investigar
311
-
312
- ```text
313
- ANTI: characterization test virou vermelho após refactor. "Provavelmente
314
- o teste estava errado, vou atualizar o expected".
315
-
316
- PROBLEMA: você acabou de pintar "Vermelho → verde" em cima de regressão
317
- real. Comportamento mudou e você passou por cima da rede de
318
- segurança. Próximo bug em prod vem por essa porta.
319
-
320
- CERTO: vermelho de characterization test = regressão até prova ao
321
- contrário. Investigue: o que no refactor mudou comportamento?
322
- Reverte aquele pedaço, refatore de outra forma. Só atualize o
323
- golden APÓS confirmar que o novo comportamento É o desejado e
324
- documentar no commit (`// behavior change: rounds half-up; was
325
- half-even`).
326
- ```
327
-
328
- ### ANTI: confiar em coverage % como proxy de safety
329
-
330
- ```text
331
- ANTI: "linha de coverage está em 85%, posso refatorar tranquilo".
332
-
333
- PROBLEMA: coverage % = "linha foi executada", não "comportamento foi
334
- observado". Teste pode entrar na linha sem assertar. 85%
335
- line coverage com 10% behavioral coverage é frágil mesmo.
336
-
337
- CERTO: behavioral coverage = % de branches × observation points
338
- cobertos por characterization tests. Pelo menos 70-80% antes de
339
- refactor pesado. Use mutation testing (stryker, mutmut, pitest)
340
- para confirmar — survived mutants = pontos cegos não cobertos.
341
- ```
342
-
343
- ---
344
-
345
- ## (d) Mapa de capítulos do livro
346
-
347
- > Capa-índice para localizar qual skill consultar dado um sintoma específico. Skills cobrem capítulos do livro Feathers.
348
-
349
- | Capítulo | Tema | Skill no kit |
350
- |---|---|---|
351
- | Cap 1 | Changing Software (edit and pray vs cover and modify) | `legacy-characterization-tests` (intro) |
352
- | Cap 2 | Working with Feedback | `legacy-characterization-tests` (rationale) |
353
- | Cap 3 | Sensing and Separation | `legacy-seams-and-test-harness` |
354
- | Cap 4 | The Seam Model | `legacy-seams-and-test-harness` (foundation) |
355
- | Cap 5 | Tools | (tooling — não é skill, mencionado em refs) |
356
- | Cap 6 | I Don't Have Much Time and I Have to Change It | `legacy-sprout-wrap-techniques` |
357
- | Cap 7-8 | It Takes Forever / How Do I Add a Feature | (gerais — disseminados em skills) |
358
- | Cap 9-10 | I Can't Get This Class/Method into a Test Harness | `legacy-seams-and-test-harness` |
359
- | Cap 11 | What Methods Should I Test? | `legacy-effect-analysis` |
360
- | Cap 12 | Many Changes in One Area | `legacy-effect-analysis` |
361
- | Cap 13 | What Tests to Write — **Characterization Tests** | `legacy-characterization-tests` ⭐ |
362
- | Cap 14-15 | Libraries / API Calls | (caso especial — refs em sprout-wrap) |
363
- | Cap 16 | I Don't Understand the Code | `legacy-effect-analysis` (sketches) |
364
- | Cap 17 | Application Has No Structure | (refactor de larga escala — fora de scope) |
365
- | Cap 18-21 | Test code in the way / Procedural / Big classes / Shotgun | (referências) |
366
- | Cap 22 | Monster Method | `legacy-monster-methods` |
367
- | Cap 23 | How Do I Know I'm Not Breaking Anything | `legacy-characterization-tests` |
368
- | Cap 24 | Overwhelmed | (cultural — refs em commands) |
369
- | Cap 25 | **Dependency-Breaking Techniques** (catálogo) | `legacy-seams-and-test-harness` |
370
-
371
- ---
372
-
373
- ## (e) Cross-references
374
-
375
- - [`legacy-characterization-tests`](../legacy-characterization-tests/SKILL.md) — cap 13 + 23, foundational
376
- - [`legacy-seams-and-test-harness`](../legacy-seams-and-test-harness/SKILL.md) — cap 3-4 + 9-10 + 25
377
- - [`legacy-sprout-wrap-techniques`](../legacy-sprout-wrap-techniques/SKILL.md) — cap 6
378
- - [`legacy-effect-analysis`](../legacy-effect-analysis/SKILL.md) — cap 11-12 + 16
379
- - [`legacy-monster-methods`](../legacy-monster-methods/SKILL.md) — cap 22
380
- - [`pre-refactor-characterization`](../pre-refactor-characterization/SKILL.md) — auto-trigger gate (workflow integration)
381
-
382
- ### Cross-suite
383
-
384
- - [`event-based-slos`](../event-based-slos/SKILL.md) (v1.9) — characterization tests defendem SLO durante refactor; behavioral diff = budget burn
385
- - [`production-readiness-review`](../production-readiness-review/SKILL.md) (v1.10) — PRR Axe 5 (Change Management) consume characterization status
386
- - [`blameless-postmortems`](../blameless-postmortems/SKILL.md) (v1.10) — postmortems pós-refactor sem characterization viram lesson learned canônica
387
- - [`observability-driven-development`](../observability-driven-development/SKILL.md) (v1.9) — characterization + ODD instrumentation = safety + visibility durante refactor
388
-
389
- *Material-fonte: Working Effectively with Legacy Code — Feathers, 2004. ISBN 978-0-13-117705-5.*
1
+ # Glossário Legacy Code — Termos, Técnicas e Patterns Canônicos
2
+
3
+ > Arquivo de referência compartilhado pelas skills `legacy-*` e `pre-refactor-characterization`. **NÃO é skill** — não tem `description:` triggerável; não aparece em `listKit`. Cross-referenciado pelas skills via Markdown link relativo.
4
+
5
+ > **Material-fonte:** *Working Effectively with Legacy Code* — Michael C. Feathers (Prentice Hall / Robert C. Martin Series, 2004). ISBN 978-0-13-117705-5.
6
+
7
+ ---
8
+
9
+ ## (a) Termos PT-BR ↔ EN
10
+
11
+ ### Definições fundacionais
12
+
13
+ > Vocabulário do prefácio + cap 1 (Changing Software). A definição de Feathers é deliberadamente operacional, não emocional — "legacy code" não significa "código antigo" ou "código feio", significa **código sem testes**. Essa redefinição muda completamente a estratégia: o problema é falta de cobertura comportamental, não estética.
14
+
15
+ | EN | PT-BR / Significado |
16
+ |---|---|
17
+ | **legacy code** | Código legado — para Feathers: **código sem testes**, independente de idade ou qualidade. Sem testes, qualquer mudança é "edit and pray" — você modifica e reza. |
18
+ | **edit and pray** | Editar e rezar — o modo default em legacy code. Você muda, lê o diff, deploya, espera. Confiança vem de inspeção visual + sorte. |
19
+ | **cover and modify** | Cobrir e modificar — o modo desejado. Primeiro adicione cobertura (tests), depois modifique. Confiança vem do safety net. |
20
+ | **change point** | Ponto de mudança — local específico onde a alteração será feita. Tipicamente uma linha, método ou bloco. |
21
+ | **inflection point** | Ponto de inflexão — junção estreita por onde os efeitos da mudança fluem. Testar aqui cobre múltiplos change points downstream. |
22
+ | **pinch point** | Funil estreito (sinônimo de inflection point usado em cap 11) — interface natural na qual concentrar testes. |
23
+ | **safety net** | Rede de segurança — suite de testes que detecta regressão imediatamente após edição. Cap 1 é todo sobre construir isso. |
24
+ | **legacy code dilemma** | Dilema do código legado — para mudar com segurança preciso testar; para testar preciso refatorar; para refatorar preciso testar. Quebrado por **dependency-breaking techniques** (cap 25). |
25
+
26
+ ### Seams e Test Harness
27
+
28
+ > Vocabulário do cap 4 (The Seam Model). Conceito central. Seam = lugar onde você pode alterar comportamento **sem editar naquele lugar**. Sem seams, o código está "fundido" — toda mudança requer modificação direta, sem possibilidade de substituição em teste.
29
+
30
+ | EN | PT-BR / Significado |
31
+ |---|---|
32
+ | **seam** | Costura — local onde se pode alterar comportamento sem editar ali. Tipicamente onde existe ponto de extensibilidade que pode ser exercitado por testes. |
33
+ | **enabling point** | Ponto habilitador — mecanismo concreto que ativa a substituição naquela costura (subclasse, link table, build flag, parâmetro). |
34
+ | **preprocessing seam** | Costura de pré-processamento — substituição via macros/preprocessor (C/C++). Raríssima em runtimes modernos. |
35
+ | **link seam** | Costura de link — substituição via linker (DLL/object/jar) ou loader (require/import shim). Útil em código sem orientação a objetos. |
36
+ | **object seam** | Costura de objeto — substituição via polimorfismo (interface, classe abstrata, duck typing). A mais comum e poderosa em OO. |
37
+ | **test harness** | Arnês de teste — infraestrutura mínima para fazer um pedaço de código rodar isolado em testes. Cap 9-10 inteiro é sobre construir isso. |
38
+ | **dependency** | Dependência — qualquer entidade externa que o código sob teste invoca. Bloqueia testes quando incontrolável (DB real, rede, clock, FS). |
39
+ | **collaborator** | Colaborador — instância concreta de uma dependência. Ex.: `EmailSender` vs concept "envio de email". |
40
+ | **fake** | Fake — implementação substituta de uma dependência que satisfaz a interface mas não faz o trabalho real (ex: `FakeEmailSender` que só salva em lista). |
41
+ | **sensing** | Sensoriamento — observar via testes que algo aconteceu (assertion sobre `fake.sentEmails.length`). |
42
+ | **separation** | Separação — quebrar a dependência para que o código rode sem o colaborador real. Pré-requisito de sensing. |
43
+ | **break dependencies** | Quebrar dependências — aplicar uma das ~24 técnicas do cap 25 para tornar testável o que não era. |
44
+
45
+ ### Characterization Tests
46
+
47
+ > Vocabulário do cap 13 (Characterization Tests). **A skill foundacional**. Characterization test não verifica se o código está certo — verifica **o que o código atualmente faz**. É um snapshot comportamental que vira oracle imutável durante o refactor.
48
+
49
+ | EN | PT-BR / Significado |
50
+ |---|---|
51
+ | **characterization test** | Teste de caracterização — teste que captura o comportamento **atual** do código (não o desejado). Não pergunta "está certo?" — pergunta "o que faz?". |
52
+ | **golden master** | Mestre dourado — output capturado de uma execução real, salvo em arquivo, que vira oracle. Subsequentes execuções comparam contra ele (snapshot test). |
53
+ | **golden snapshot** | Snapshot dourado — sinônimo de golden master, terminologia mais comum em frameworks modernos (Jest, Vitest, Pytest). |
54
+ | **expected behavior trap** | Armadilha do "comportamento esperado" — escrever testes do que o código **deveria** fazer em vez do que **faz**. Resultado: teste falha imediatamente porque o bug atual é o estado atual. Sempre comece pelo atual. |
55
+ | **bug preservation** | Preservação de bug — characterization tests preservam bugs existentes. Refactor não muda comportamento, então o bug deve continuar reproduzível. Bug fix é outra mudança, separada. |
56
+ | **observation point** | Ponto de observação — saída capturada (return value, side effect, log, DB write). Cada ponto vira uma asserção. |
57
+ | **input enumeration** | Enumeração de entradas — cobrir caminhos via grupos de equivalência: input nulo, vazio, válido típico, válido extremo, inválido recoverable, inválido fatal. |
58
+ | **behavioral coverage** | Cobertura comportamental — não % de linhas executadas, mas % de **branches** + observation points. Métrica para liberar refactor é cobertura comportamental, não code coverage. |
59
+ | **edit-then-characterize** | Editar-então-caracterizar — anti-pattern. Você muda, depois escreve teste do "novo" comportamento. Não há baseline para detectar quebra. |
60
+
61
+ ### Sprout / Wrap Techniques
62
+
63
+ > Vocabulário do cap 6 (I Don't Have Much Time and I Have to Change It). Quando você não tem tempo para colocar legado em test harness, mas precisa adicionar comportamento novo. Estratégia: adicionar código novo **isolado** e testado, conectado ao legado por chamada mínima.
64
+
65
+ | EN | PT-BR / Significado |
66
+ |---|---|
67
+ | **sprout method** | Método broto — extrair a nova lógica para método novo (tipicamente `static` ou injetável), testar isolado, chamar do método legado em 1 linha. |
68
+ | **sprout class** | Classe broto — quando o sprout method cresce, externalize para classe nova com test harness próprio. |
69
+ | **wrap method** | Método invólucro — renomeie o método legado (`foo` → `fooLegacy`), crie `foo` novo que chama `fooLegacy` + nova lógica. Novo `foo` é testável. |
70
+ | **wrap class** | Classe invólucro — análogo ao wrap method em escala de classe. Decorator pattern aplicado pragmaticamente. |
71
+ | **boy scout rule (sprout edition)** | Regra do escoteiro (versão sprout) — deixe o código mais limpo do que encontrou ao **adicionar** novo, mesmo sem refatorar o velho. Sprout/wrap concretiza isso. |
72
+
73
+ ### Effect Analysis
74
+
75
+ > Vocabulário do cap 11 (I Need to Make a Change. What Methods Should I Test?) e cap 12 (I Need to Make Many Changes in One Area). Sem testes, qual é o subset mínimo de coisas a testar para sentir-se seguro? Resposta: rastreie efeitos do change point para fora, encontre inflection points, teste lá.
76
+
77
+ | EN | PT-BR / Significado |
78
+ |---|---|
79
+ | **effect sketch** | Esboço de efeitos — diagrama (papel mesmo) com setas do change point para tudo que muda. Variáveis afetadas, retornos, side effects, callbacks. |
80
+ | **effect propagation** | Propagação de efeito — como um change ripple através do código. Cap 11 lista 4 vetores: return value, parâmetros mutados, globals, side effects via colaborador. |
81
+ | **interception point** | Ponto de interceptação — local onde inserir teste para observar efeitos. Idealmente coincide com inflection point. |
82
+ | **effect-narrowing** | Estreitamento de efeito — refatorar para reduzir o número de pontos afetados (encapsular variáveis, eliminar globals). Pré-trabalho para tornar effect sketch menor. |
83
+ | **shotgun surgery** | Cirurgia espalhada — anti-pattern (cap 21): mesma mudança espalhada em N lugares; cada incidência é um change point separado. Effect sketch detecta. |
84
+
85
+ ### Monster Methods
86
+
87
+ > Vocabulário do cap 22 (I Need to Change a Monster Method and I Can't Write Tests for It). Métodos absurdamente longos (> 200 linhas) onde você não consegue nem entender o que faz, muito menos testar. Estratégia: scratch refactoring + single-goal editing + extrair pedacinhos sem mudar comportamento.
88
+
89
+ | EN | PT-BR / Significado |
90
+ |---|---|
91
+ | **monster method** | Método monstro — método com várias páginas de código, múltiplos níveis de aninhamento, múltiplas responsabilidades. Heurística: > 100 linhas ou > 5 níveis de indent. |
92
+ | **bulleted method** | Método com bullets — variante: linhas longas mas planas (sem nesting). Mais fácil de domar. |
93
+ | **snarled method** | Método emaranhado — variante: nesting profundo, condicionais aninhadas, control flow espaguete. Mais difícil. |
94
+ | **scratch refactoring** | Refactor de rascunho — quebra estética sem commitar. Use uma branch lixo, refatore para entender, descarte. Conhecimento adquirido vai para a refatoração real. |
95
+ | **single-goal editing** | Edição com objetivo único — mudar UMA coisa por vez. Renomear OU extrair OU mover, nunca os 3 juntos. Cada mudança é um diff legível. |
96
+ | **safe extraction** | Extração segura — extrair método sem mover lógica entre escopos. Apenas levantar bloco contíguo + capturar variáveis usadas como parâmetros. |
97
+ | **method blob** | Blob de método — sinônimo informal de monster method. |
98
+
99
+ ### Dependency-Breaking Techniques
100
+
101
+ > Vocabulário do cap 25 (Dependency-Breaking Techniques) — o catálogo principal. ~24 técnicas para tornar testável o que não era. Cada técnica tem trade-offs diferentes (segurança, custo, mecanização).
102
+
103
+ | EN | PT-BR / Significado |
104
+ |---|---|
105
+ | **subclass and override method** | Subclassificar e sobrescrever método — criar subclasse de teste que substitui método problemático. Funciona em qualquer linguagem com herança virtual. |
106
+ | **extract interface** | Extrair interface — criar interface a partir da classe concreta, fazer cliente depender da interface, fornecer fake implementation em teste. |
107
+ | **adapt parameter** | Adaptar parâmetro — quando parâmetro tem tipo difícil de criar (ex: `HttpServletRequest`), envolver em interface mais simples e fazer cliente depender dela. |
108
+ | **introduce static setter** | Introduzir setter estático — adicionar setter para singleton/global; teste injeta fake; teardown restaura. **Risk: thread safety** — só em ambientes single-threaded de teste. |
109
+ | **encapsulate global references** | Encapsular referências globais — substituir acesso direto a variáveis globais por método de instância da classe. Permite override em teste. |
110
+ | **expose static method** | Expor método estático — promover método de instância a estático para testar sem instanciar a classe inteira (quando construtor é caro). |
111
+ | **break out method object** | Quebrar para method object — extrair método grande para classe com `run()`. Variáveis locais viram fields, fácil de testar. |
112
+ | **parameterize constructor** | Parametrizar construtor — passar dependência via construtor (DI manual) em vez de criar dentro. Default constructor mantém retrocompatibilidade. |
113
+ | **parameterize method** | Parametrizar método — passar dependência como argumento da chamada. Útil quando dependency só é usada num método específico. |
114
+ | **pull up feature** | Subir feature — mover método/field para superclasse para que subclasse de teste possa override. |
115
+ | **push down dependency** | Empurrar dependência — mover dependência problemática para subclasse, fazer base abstrata sem ela; teste usa subclasse de teste sem dependência real. |
116
+ | **replace function with function pointer** | Substituir função por ponteiro de função — em C, substituir chamada estática por ponteiro que teste pode reapontar. |
117
+ | **introduce instance delegator** | Introduzir delegador de instância — método estático vira fino wrapper que chama método de instância injetada. Permite mock. |
118
+ | **link substitution** | Substituição de link — providenciar `.so`/`.dll`/`.jar` alternativo em test classpath/library path. |
119
+ | **definition completion** | Completar definição (C/C++) — fornecer `.cpp` alternativo no link de teste para sobrescrever função declarada em `.h`. |
120
+
121
+ ---
122
+
123
+ ## (b) Patterns canônicos
124
+
125
+ ### Pattern: Algoritmo de mudança em legacy code (cap 1)
126
+
127
+ ```text
128
+ 1. Identify change points (onde mudar)
129
+ 2. Find test points (onde testar — idealmente nas inflection points)
130
+ 3. Break dependencies (cap 25 — aplicar técnica adequada)
131
+ 4. Write characterization tests (cap 13 — congelar comportamento atual)
132
+ 5. Make changes and refactor (cover and modify, não edit and pray)
133
+ ```
134
+
135
+ **Insight central:** os passos 1-4 são **investimento prévio à mudança**. Quem pula direto ao passo 5 está em "edit and pray" — pode ter sorte 9 vezes em 10 mas a 10ª vez é incident SEV1.
136
+
137
+ ### Pattern: identificar legacy code via critérios
138
+
139
+ ```text
140
+ Um arquivo/módulo é "legacy" no sentido Feathers se:
141
+
142
+ 1. Cobertura de testes < 60%? → SIM → legacy
143
+ 2. Existem branches sem teste algum? → SIM → legacy
144
+ 3. Mudanças recentes (último mês) não tiveram teste novo correspondente? → SIM → legacy
145
+ 4. Faz parte de contrato externo (webhook, API pública, integração)? → SIM → legacy MESMO COM testes (porque consumer breakage é pior)
146
+ 5. Tem mais de 500 linhas em arquivo único? → SIM → legacy candidate (pelo menos suspeito)
147
+ 6. Tem métodos > 100 linhas? → SIM → monster methods, candidato a cap 22
148
+
149
+ Heurística agregada: se 2+ critérios = legacy → exigir characterization tests antes de qualquer refactor.
150
+ ```
151
+
152
+ ### Pattern: decision tree para escolher técnica de quebra de dependência
153
+
154
+ ```text
155
+ Posso modificar o código? (acesso write?)
156
+ ├─ Não → preprocessing seam (C/C++) ou link seam (qualquer linguagem)
157
+ └─ Sim →
158
+ ├─ Linguagem tem herança/polimorfismo? (Java, C#, Python, Ruby, TS...)
159
+ │ ├─ Sim → object seam (preferred)
160
+ │ │ ├─ Dependência é classe? → extract interface OU subclass and override
161
+ │ │ ├─ Dependência é singleton/global? → encapsulate global references OU introduce static setter
162
+ │ │ ├─ Dependência é tipo de framework? (HttpServletRequest, Context) → adapt parameter
163
+ │ │ └─ Dependência é construído internamente? → parameterize constructor / parameterize method
164
+ │ └─ Não (C, COBOL, código procedural) → link seam OU function pointer substitution
165
+ └─ Construtor da classe é caro? → expose static method (testar sem instanciar)
166
+ ```
167
+
168
+ ### Pattern: Sprout decision tree (cap 6)
169
+
170
+ ```text
171
+ Tenho que adicionar comportamento a método não testado.
172
+
173
+ Tenho tempo para colocar o método inteiro sob test harness primeiro?
174
+ ├─ Sim → técnicas do cap 25 (preferencial)
175
+ └─ Não →
176
+ ├─ Comportamento novo é coeso e separável? → SPROUT METHOD
177
+ │ 1. Escrever método novo (static ou de classe nova) — testável
178
+ │ 2. Chamar do método legado em 1 linha
179
+ │ 3. Test do sprout via test harness próprio
180
+ │ 4. Método legado permanece untested mas o NOVO comportamento está coberto
181
+ ├─ Comportamento novo é grande (>30 linhas)? → SPROUT CLASS
182
+ │ 1. Criar classe nova encapsulando o novo comportamento
183
+ │ 2. Construir + chamar a classe do método legado
184
+ │ 3. Test class isoladamente
185
+ └─ Preciso modificar pré ou pós-condição do método legado? → WRAP METHOD
186
+ 1. Renomear `foo` → `fooLegacy` (apenas mecânico)
187
+ 2. Criar novo `foo` que chama `fooLegacy` + adiciona comportamento
188
+ 3. Testes do `foo` cobrem composição; `fooLegacy` ainda untested mas chamável
189
+ ```
190
+
191
+ ### Pattern: characterization tests workflow (cap 13)
192
+
193
+ ```text
194
+ 1. Escolher input typical → rodar código → capturar output
195
+ 2. Escrever teste assertando output capturado (mesmo se output for um bug)
196
+ 3. Repetir para 5-10 inputs cobrindo grupos de equivalência:
197
+ - null/vazio
198
+ - válido típico
199
+ - válido extremo (boundaries)
200
+ - inválido recoverable
201
+ - inválido fatal
202
+ 4. Rodar todos verde → BASELINE estabelecido
203
+ 5. AGORA refactor pode começar — qualquer test que vire vermelho = regressão real
204
+ ```
205
+
206
+ **Anti-pattern:** começar a "consertar" o teste para o output "correto". Isso destrói o oracle. Bug → preserve, fix em commit separado depois do refactor.
207
+
208
+ ### Pattern: 6 níveis de "está testável?" (cap 9-10)
209
+
210
+ | Nível | Sintoma | Solução |
211
+ |---|---|---|
212
+ | **L0** | Não consigo construir a classe (construtor irritado, faz I/O, throws) | Cap 9 técnicas — fake constructor parameters, expose static method |
213
+ | **L1** | Classe constrói mas método não roda isolado (depende de globals) | Encapsulate global references |
214
+ | **L2** | Método roda mas dependências reais (DB, rede, clock) executam | Inject collaborator OR subclass and override |
215
+ | **L3** | Dependências stubadas mas effects spread (DB grava, email envia) | Sense via fake (verify-no-side-effect) |
216
+ | **L4** | Roda isolado, mas saída não-determinística (random, datetime.now) | Inject clock/random como dependência |
217
+ | **L5** | Roda isolado e determinístico mas eu não entendo o que testa | Characterization tests para descobrir |
218
+
219
+ Meta é L5+. Antes de refatorar, código deve estar em L4 ou melhor.
220
+
221
+ ---
222
+
223
+ ## (c) Anti-patterns canônicos
224
+
225
+ ### ANTI: refactor sem characterization tests
226
+
227
+ ```text
228
+ ANTI: "vou refatorar esse método de 200 linhas, depois adiciono testes do
229
+ novo design".
230
+
231
+ PROBLEMA: você não sabe o que está preservando. O método tem branches que
232
+ você não sabe que existem. Bugs antigos que clientes dependem
233
+ (Hyrum's Law) somem silenciosamente. Resultado típico: incident
234
+ em prod 2 semanas depois quando edge case dispara.
235
+
236
+ CERTO: characterize first (cap 13), refactor second. Pelo menos 5-10
237
+ inputs cobrindo grupos de equivalência ANTES de mover qualquer
238
+ linha. Se o método é de 200 linhas, esse trabalho leva 1-2 dias.
239
+ Aceite o custo — alternativa é o incident.
240
+ ```
241
+
242
+ ### ANTI: edit and pray (cap 1)
243
+
244
+ ```text
245
+ ANTI: "vou modificar essa linha, rodar smoke test, dar push e ver no
246
+ monitoring".
247
+
248
+ PROBLEMA: smoke test cobre golden path. Branches raras (1% do tráfego)
249
+ escapam silenciosamente. Bugs em borda manifestam horas/dias
250
+ depois. Forensics fica difícil porque change set tem N edits
251
+ no mesmo PR.
252
+
253
+ CERTO: cover and modify. Antes de modificar, encontre o seam e adicione
254
+ teste que exercita a branch específica. Se não há seam, primeiro
255
+ adicione um (cap 25). Investimento de 1-4h vs incident de 4-40h.
256
+ ```
257
+
258
+ ### ANTI: fix bug ANTES do characterization
259
+
260
+ ```text
261
+ ANTI: "ah, esse método tem um bug óbvio na linha 42, vou consertar
262
+ enquanto refatoro".
263
+
264
+ PROBLEMA: characterization test capturou o bug como comportamento
265
+ esperado. Você consertou → teste fica vermelho → você
266
+ "atualiza o teste" → oracle morto → não há baseline mais.
267
+
268
+ CERTO: 2 commits separados. (1) characterize + refactor preservando
269
+ bug. (2) bug fix com teste novo do comportamento correto. Aplique
270
+ o fix DEPOIS, com seu próprio test antes (TDD agora possível
271
+ porque você tem test harness funcionando).
272
+ ```
273
+
274
+ ### ANTI: golden master sem revisão humana
275
+
276
+ ```text
277
+ ANTI: rodar code → capturar output → commitar como `expected.txt` sem
278
+ ler. "É o que o código produz, deve estar certo".
279
+
280
+ PROBLEMA: output captura inclui bugs já existentes. Sem revisão, você
281
+ congela bugs como contrato. Se o output incluir PII, secret,
282
+ UUID local — você acabou de commitar dado sensível.
283
+
284
+ CERTO: ler o output capturado linha por linha antes de salvar. Marcar
285
+ expectativas conhecidas-buggy com comentário inline (`// BUG #123:
286
+ deveria ser X, é Y`). Redact PII/secret/UUID via post-processing
287
+ deterministic (hash, mask). Commit do golden é uma decisão, não
288
+ um copy-paste.
289
+ ```
290
+
291
+ ### ANTI: monster method "limpado" em 1 PR
292
+
293
+ ```text
294
+ ANTI: PR com 800 linhas de diff: extract method × 12, rename × 5, move
295
+ logic × 3, fix off-by-one × 2 — tudo junto.
296
+
297
+ PROBLEMA: PR não-revisável. Reviewer não consegue separar refactor
298
+ (nullable) de fix (semântico). Se algo quebra, bisect aponta
299
+ para o PR inteiro. CI verde não significa nada — branch
300
+ coverage caiu silenciosa.
301
+
302
+ CERTO: 1 PR por single-goal edit (cap 22). Sequência típica:
303
+ PR1 — extract method (3 helpers, mecânico, comportamento idêntico)
304
+ PR2 — extract class (mover helpers para nova classe)
305
+ PR3 — invert dependency (constructor injection)
306
+ PR4 — fix bug X (com teste novo, semântico)
307
+ Cada PR ≤ 100 linhas. Cada um é revisável e revertível.
308
+ ```
309
+
310
+ ### ANTI: substituir testes "falhos" sem investigar
311
+
312
+ ```text
313
+ ANTI: characterization test virou vermelho após refactor. "Provavelmente
314
+ o teste estava errado, vou atualizar o expected".
315
+
316
+ PROBLEMA: você acabou de pintar "Vermelho → verde" em cima de regressão
317
+ real. Comportamento mudou e você passou por cima da rede de
318
+ segurança. Próximo bug em prod vem por essa porta.
319
+
320
+ CERTO: vermelho de characterization test = regressão até prova ao
321
+ contrário. Investigue: o que no refactor mudou comportamento?
322
+ Reverte aquele pedaço, refatore de outra forma. Só atualize o
323
+ golden APÓS confirmar que o novo comportamento É o desejado e
324
+ documentar no commit (`// behavior change: rounds half-up; was
325
+ half-even`).
326
+ ```
327
+
328
+ ### ANTI: confiar em coverage % como proxy de safety
329
+
330
+ ```text
331
+ ANTI: "linha de coverage está em 85%, posso refatorar tranquilo".
332
+
333
+ PROBLEMA: coverage % = "linha foi executada", não "comportamento foi
334
+ observado". Teste pode entrar na linha sem assertar. 85%
335
+ line coverage com 10% behavioral coverage é frágil mesmo.
336
+
337
+ CERTO: behavioral coverage = % de branches × observation points
338
+ cobertos por characterization tests. Pelo menos 70-80% antes de
339
+ refactor pesado. Use mutation testing (stryker, mutmut, pitest)
340
+ para confirmar — survived mutants = pontos cegos não cobertos.
341
+ ```
342
+
343
+ ---
344
+
345
+ ## (d) Mapa de capítulos do livro
346
+
347
+ > Capa-índice para localizar qual skill consultar dado um sintoma específico. Skills cobrem capítulos do livro Feathers.
348
+
349
+ | Capítulo | Tema | Skill no kit |
350
+ |---|---|---|
351
+ | Cap 1 | Changing Software (edit and pray vs cover and modify) | `legacy-characterization-tests` (intro) |
352
+ | Cap 2 | Working with Feedback | `legacy-characterization-tests` (rationale) |
353
+ | Cap 3 | Sensing and Separation | `legacy-seams-and-test-harness` |
354
+ | Cap 4 | The Seam Model | `legacy-seams-and-test-harness` (foundation) |
355
+ | Cap 5 | Tools | (tooling — não é skill, mencionado em refs) |
356
+ | Cap 6 | I Don't Have Much Time and I Have to Change It | `legacy-sprout-wrap-techniques` |
357
+ | Cap 7-8 | It Takes Forever / How Do I Add a Feature | (gerais — disseminados em skills) |
358
+ | Cap 9-10 | I Can't Get This Class/Method into a Test Harness | `legacy-seams-and-test-harness` |
359
+ | Cap 11 | What Methods Should I Test? | `legacy-effect-analysis` |
360
+ | Cap 12 | Many Changes in One Area | `legacy-effect-analysis` |
361
+ | Cap 13 | What Tests to Write — **Characterization Tests** | `legacy-characterization-tests` ⭐ |
362
+ | Cap 14-15 | Libraries / API Calls | (caso especial — refs em sprout-wrap) |
363
+ | Cap 16 | I Don't Understand the Code | `legacy-effect-analysis` (sketches) |
364
+ | Cap 17 | Application Has No Structure | (refactor de larga escala — fora de scope) |
365
+ | Cap 18-21 | Test code in the way / Procedural / Big classes / Shotgun | (referências) |
366
+ | Cap 22 | Monster Method | `legacy-monster-methods` |
367
+ | Cap 23 | How Do I Know I'm Not Breaking Anything | `legacy-characterization-tests` |
368
+ | Cap 24 | Overwhelmed | (cultural — refs em commands) |
369
+ | Cap 25 | **Dependency-Breaking Techniques** (catálogo) | `legacy-seams-and-test-harness` |
370
+
371
+ ---
372
+
373
+ ## (e) Cross-references
374
+
375
+ - [`legacy-characterization-tests`](../legacy-characterization-tests/SKILL.md) — cap 13 + 23, foundational
376
+ - [`legacy-seams-and-test-harness`](../legacy-seams-and-test-harness/SKILL.md) — cap 3-4 + 9-10 + 25
377
+ - [`legacy-sprout-wrap-techniques`](../legacy-sprout-wrap-techniques/SKILL.md) — cap 6
378
+ - [`legacy-effect-analysis`](../legacy-effect-analysis/SKILL.md) — cap 11-12 + 16
379
+ - [`legacy-monster-methods`](../legacy-monster-methods/SKILL.md) — cap 22
380
+ - [`pre-refactor-characterization`](../pre-refactor-characterization/SKILL.md) — auto-trigger gate (workflow integration)
381
+
382
+ ### Cross-suite
383
+
384
+ - [`event-based-slos`](../event-based-slos/SKILL.md) (v1.9) — characterization tests defendem SLO durante refactor; behavioral diff = budget burn
385
+ - [`production-readiness-review`](../production-readiness-review/SKILL.md) (v1.10) — PRR Axe 5 (Change Management) consume characterization status
386
+ - [`blameless-postmortems`](../blameless-postmortems/SKILL.md) (v1.10) — postmortems pós-refactor sem characterization viram lesson learned canônica
387
+ - [`observability-driven-development`](../observability-driven-development/SKILL.md) (v1.9) — characterization + ODD instrumentation = safety + visibility durante refactor
388
+
389
+ *Material-fonte: Working Effectively with Legacy Code — Feathers, 2004. ISBN 978-0-13-117705-5.*