@luanpdd/kit-mcp 1.35.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 (117) hide show
  1. package/bin/cli.js +2 -2
  2. package/bin/mcp.js +6 -6
  3. package/bin/ui.js +74 -74
  4. package/gates/ai-prompt-stability.md +120 -120
  5. package/gates/budget-description.md +68 -68
  6. package/gates/confidence.md +29 -29
  7. package/gates/dependency-check.md +33 -33
  8. package/gates/dept-cycle-prevention.md +179 -179
  9. package/gates/golden-signals-coverage.md +133 -133
  10. package/gates/legacy-refactor-safety.md +178 -178
  11. package/gates/multi-tenant-rls-coverage.md +102 -102
  12. package/gates/no-personal-uuid.md +72 -72
  13. package/gates/obs-agents-mcp-supabase.md +86 -86
  14. package/gates/obs-skills-frontmatter.md +76 -76
  15. package/gates/observability-coverage.md +151 -151
  16. package/gates/omm-no-regression.md +83 -83
  17. package/gates/postmortem-template-required.md +127 -127
  18. package/gates/prr-checklist-coverage.md +128 -128
  19. package/gates/regression.md +32 -32
  20. package/gates/release-pipeline-policy.md +132 -132
  21. package/gates/secrets-scan.md +33 -33
  22. package/gates/service-role-not-in-user-facing.md +113 -113
  23. package/gates/skill-must-include.md +71 -71
  24. package/gates/sync-idempotent.md +62 -62
  25. package/gates/verify-phase-goal.md +34 -34
  26. package/kit/agents/designer-ui.md +216 -216
  27. package/kit/agents/workflow-generator.md +537 -167
  28. package/kit/commands/adicionar-backlog.md +1 -1
  29. package/kit/commands/adicionar-fase.md +1 -1
  30. package/kit/commands/adicionar-tarefa.md +1 -1
  31. package/kit/commands/auditar-observabilidade.md +103 -103
  32. package/kit/commands/auditar-toil.md +129 -129
  33. package/kit/commands/caracterizar-prompt.md +195 -195
  34. package/kit/commands/criar-workflow.md +158 -158
  35. package/kit/commands/definir-perfil.md +1 -1
  36. package/kit/commands/definir-slo.md +108 -108
  37. package/kit/commands/fio.md +1 -1
  38. package/kit/commands/golden-signals.md +142 -142
  39. package/kit/commands/instrumentar-fase.md +200 -200
  40. package/kit/commands/investigar-producao.md +162 -162
  41. package/kit/commands/observabilidade.md +118 -118
  42. package/kit/commands/postmortem.md +179 -179
  43. package/kit/commands/prr.md +205 -205
  44. package/kit/commands/publicar-rapido.md +207 -207
  45. package/kit/commands/risk-budget.md +220 -220
  46. package/kit/commands/sre.md +230 -230
  47. package/kit/file-manifest.json +424 -424
  48. package/kit/framework/references/output-style.md +22 -22
  49. package/kit/hooks/post-apply-migration.js +199 -199
  50. package/kit/hooks/sidecar-tool-publisher.js +210 -210
  51. package/kit/skills/_shared-dados-distribuidos/glossary.md +224 -224
  52. package/kit/skills/_shared-legacy/glossary.md +389 -389
  53. package/kit/skills/_shared-multi-tenant/glossary.md +186 -186
  54. package/kit/skills/_shared-observability/glossary.md +396 -396
  55. package/kit/skills/_shared-sre/glossary.md +712 -712
  56. package/kit/skills/_shared-supabase/glossary.md +234 -234
  57. package/kit/skills/blameless-postmortems/SKILL.md +340 -340
  58. package/kit/skills/burn-rate-alerting/SKILL.md +258 -258
  59. package/kit/skills/cascading-failures/SKILL.md +311 -311
  60. package/kit/skills/core-analysis-loop/SKILL.md +352 -352
  61. package/kit/skills/distributed-tracing/SKILL.md +362 -362
  62. package/kit/skills/dynamic-workflow-authoring/SKILL.md +327 -223
  63. package/kit/skills/eliminating-toil/SKILL.md +243 -243
  64. package/kit/skills/event-based-slos/SKILL.md +296 -296
  65. package/kit/skills/four-golden-signals/SKILL.md +314 -314
  66. package/kit/skills/hermetic-builds/SKILL.md +323 -323
  67. package/kit/skills/legacy-monster-methods/SKILL.md +444 -444
  68. package/kit/skills/llm-as-dependency/SKILL.md +436 -436
  69. package/kit/skills/load-shedding-graceful-degradation/SKILL.md +396 -396
  70. package/kit/skills/observability-driven-development/SKILL.md +315 -315
  71. package/kit/skills/observability-maturity-model/SKILL.md +222 -222
  72. package/kit/skills/opentelemetry-standard/SKILL.md +351 -351
  73. package/kit/skills/production-readiness-review/SKILL.md +305 -305
  74. package/kit/skills/release-engineering/SKILL.md +367 -367
  75. package/kit/skills/retry-strategies/SKILL.md +372 -372
  76. package/kit/skills/sre-risk-management/SKILL.md +221 -221
  77. package/kit/skills/structured-events/SKILL.md +265 -265
  78. package/kit/skills/supabase-cron-queues/SKILL.md +275 -275
  79. package/kit/skills/supabase-database-functions/SKILL.md +332 -332
  80. package/kit/skills/supabase-declarative-schema/SKILL.md +183 -183
  81. package/kit/skills/supabase-pgvector-rag/SKILL.md +253 -253
  82. package/kit/skills/supabase-postgres-style/SKILL.md +138 -138
  83. package/kit/skills/supabase-storage/SKILL.md +234 -234
  84. package/kit/skills/telemetry-pipelines/SKILL.md +259 -259
  85. package/kit/skills/telemetry-sampling/SKILL.md +256 -256
  86. package/kit/skills/ui-anti-padroes-ia/SKILL.md +261 -261
  87. package/kit/skills/ui-contexto-produto/SKILL.md +248 -248
  88. package/kit/skills/ui-cor-estrategia/SKILL.md +213 -213
  89. package/kit/skills/ui-critica-auditoria/SKILL.md +260 -260
  90. package/kit/skills/ui-motion-funcional/SKILL.md +264 -264
  91. package/kit/skills/ui-ritmo-espacial/SKILL.md +259 -259
  92. package/kit/skills/ui-tipografia/SKILL.md +211 -211
  93. package/package.json +1 -1
  94. package/src/cli/index.js +1114 -1114
  95. package/src/cli/render.js +194 -194
  96. package/src/cli/upgrade-check.js +135 -135
  97. package/src/core/error-redaction.js +76 -76
  98. package/src/core/failures.js +153 -153
  99. package/src/core/gate-runner.js +205 -205
  100. package/src/core/gates.js +82 -82
  101. package/src/core/logger.js +170 -170
  102. package/src/core/manifest-verify.js +174 -174
  103. package/src/core/metrics.js +268 -268
  104. package/src/core/notify.js +60 -60
  105. package/src/core/path-safety.js +141 -141
  106. package/src/core/replays.js +120 -120
  107. package/src/core/ui.js +185 -185
  108. package/src/mcp-server/install.js +149 -149
  109. package/src/mcp-server/roots.js +124 -124
  110. package/src/ui/auto-spawn.js +113 -113
  111. package/src/ui/browser.js +78 -78
  112. package/src/ui/client.js +130 -130
  113. package/src/ui/events.js +65 -65
  114. package/src/ui/lockfile.js +191 -191
  115. package/src/ui/port.js +67 -67
  116. package/src/ui/server.js +547 -547
  117. package/src/ui/wrapper.js +129 -129
@@ -1,315 +1,315 @@
1
- ---
2
- name: observability-driven-development
3
- description: Use ao bundlear telemetria com nova feature — 4 perguntas pré-PR, instrumentação shift-left, auto-page do autor por 30-60min após merge. Análogo TDD para produção.
4
- ---
5
-
6
- # Observabilidade — Observability-Driven Development (ODD)
7
-
8
- ## Quando usar
9
-
10
- LLM carrega esta skill ao escrever nova feature, planejar fase, ou code review. Trigger phrases:
11
-
12
- - "ODD", "observability-driven development"
13
- - "como sei que essa feature funciona em prod?"
14
- - "instrumentar antes do PR"
15
- - "shift-left observability"
16
- - "auto-page do autor"
17
- - "bundle telemetry com feature"
18
-
19
- ## As 4 perguntas pré-PR (canônicas)
20
-
21
- Antes de submeter PR, todo autor responde EM CÓDIGO:
22
-
23
- | # | Pergunta | Como instrumentar |
24
- |---|----------|-------------------|
25
- | **1** | **Faz o que esperei?** | `result.success` boolean por evento + atributos do happy path (`order.id`, `user.id`) |
26
- | **2** | **Compara à versão anterior?** | `build_id` em todo evento — permite `WHERE build_id = X vs build_id = Y` |
27
- | **3** | **Usuários estão usando?** | Atributo de identidade (`user.id`, `tenant_id`, `customer.tier`) e do path do request (`endpoint`, `feature_flag.<name>`) |
28
- | **4** | **Anomalias emergem?** | `error.type` enumerado + `duration_ms` + capturar todos os branches de código (try/catch + early returns) |
29
-
30
- **Sem isso, o PR não é mergeável.** Não é regra burocrática — é a diferença entre "funciona em testes" e "funciona em produção".
31
-
32
- ## Regras absolutas
33
-
34
- - **Bundle telemetria com a feature** — instrumentação não é fase separada. Mesmo PR adiciona feature + spans + atributos.
35
- - **Auto-page o autor por 30-60min após merge** — feedback loop curto. "Fui eu, eu sei o que era e eu posso reverter." NUNCA pular essa janela.
36
- - **Decouple deploy de release** — feature flag por default. Deploy = código em prod desligado; release = liga aos poucos.
37
- - **Test em prod com subset** — 1% de tráfego com flag ativada > 100% rollout em horário de baixa.
38
- - **Rollback < rollforward em duvida** — observabilidade rica mostra o que está errado em segundos, mas só se você não rolou-back o evidência primeiro. Pause primeiro, investigue, então decida.
39
- - **Toda code branch = atributo** — `if (x) { ... } else { ... }` precisa emitir atributo de qual branch foi tomada (`branch_taken: 'fast_path'` vs `'slow_path'`).
40
- - **Tighten do feedback loop é o objetivo** — minutos do commit ao prod, não dias. Cada hora de delay multiplica custo de debug.
41
-
42
- ## Patterns canônicos
43
-
44
- ### Pattern: feature instrumentada nasce ODD-compliant
45
-
46
- ```ts
47
- // PT-BR: feature nova "novo método de pagamento" — instrumentação BUNDLED
48
- import { trace, SpanStatusCode } from '@opentelemetry/api'
49
-
50
- const tracer = trace.getTracer('payments')
51
-
52
- export async function processPaymentV2(req: PaymentRequest) {
53
- return tracer.startActiveSpan('process_payment_v2', async (span) => {
54
- // PT-BR: Pergunta 3 — quem está usando?
55
- span.setAttribute('user.id', req.user.id)
56
- span.setAttribute('customer.tier', req.user.tier)
57
- span.setAttribute('tenant_id', req.user.tenant)
58
- span.setAttribute('endpoint', '/api/v2/payments')
59
-
60
- // PT-BR: Pergunta 2 — qual versão?
61
- span.setAttribute('build_id', process.env.BUILD_ID ?? 'dev')
62
- span.setAttribute('feature_flag.payments_v2', true) // PT-BR: assumed via flag
63
- span.setAttribute('payment.method', req.method) // novo: 'pix' | 'crypto' | 'card'
64
-
65
- // PT-BR: Pergunta 4 — atributo por branch
66
- if (req.amount > 1_000_00) {
67
- span.setAttribute('branch_taken', 'high_value')
68
- span.setAttribute('requires_3ds', true)
69
- } else {
70
- span.setAttribute('branch_taken', 'standard')
71
- span.setAttribute('requires_3ds', false)
72
- }
73
-
74
- try {
75
- const result = await chargeProvider(req)
76
-
77
- // PT-BR: Pergunta 1 — fez o que esperei?
78
- span.setAttribute('result.success', true)
79
- span.setAttribute('payment.id', result.id)
80
- span.setAttribute('payment.processor_response', result.processorCode)
81
- span.setStatus({ code: SpanStatusCode.OK })
82
- return result
83
- } catch (e) {
84
- // PT-BR: Pergunta 4 — anomalia identificada com type enum
85
- span.setAttribute('result.success', false)
86
- span.setAttribute('error.type', classify(e)) // 'provider_down' | 'declined' | 'fraud_block'
87
- span.setAttribute('error.processor_code', e.code)
88
- span.setStatus({ code: SpanStatusCode.ERROR })
89
- throw e
90
- } finally {
91
- span.end()
92
- }
93
- })
94
- }
95
- ```
96
-
97
- ### Pattern: auto-page autor (config CI/CD)
98
-
99
- ```yaml
100
- # PT-BR: GitHub Actions ou equivalente — paginar autor após merge
101
- # .github/workflows/post-merge-watch.yml
102
- name: post-merge-watch
103
- on:
104
- push:
105
- branches: [main]
106
- jobs:
107
- page-author:
108
- runs-on: ubuntu-latest
109
- steps:
110
- - name: Page commit author for 30-60min
111
- run: |
112
- AUTHOR_EMAIL="${{ github.event.head_commit.author.email }}"
113
- PAGER_TOKEN="${{ secrets.PAGERDUTY_TOKEN }}"
114
- # PT-BR: criar policy temporária — alertas SLO route para AUTHOR_EMAIL
115
- # por 45 minutos. Após, retorna ao on-call normal.
116
- curl -X POST https://api.pagerduty.com/oncall_overrides \
117
- -H "Authorization: Token token=$PAGER_TOKEN" \
118
- -d "{
119
- \"override\": {
120
- \"start\": \"$(date -u +%FT%TZ)\",
121
- \"end\": \"$(date -u -d '+45 minutes' +%FT%TZ)\",
122
- \"user\": {\"email\": \"$AUTHOR_EMAIL\"}
123
- }
124
- }"
125
- ```
126
-
127
- ### Pattern: deploy ≠ release (feature flag)
128
-
129
- ```ts
130
- // PT-BR: deploy do código com flag DESLIGADA
131
- const isV2Enabled = (req: Request): boolean => {
132
- // PT-BR: 0% inicialmente — deploy = código em prod, mas dormente
133
- if (!flags.isEnabled('payments_v2', { user_id: req.user.id })) {
134
- return false
135
- }
136
- return true
137
- }
138
-
139
- export async function processPayment(req: PaymentRequest) {
140
- if (isV2Enabled(req)) {
141
- return processPaymentV2(req)
142
- }
143
- return processPaymentV1(req)
144
- }
145
-
146
- // PT-BR: depois do deploy, release gradual:
147
- // 1. flag.set('payments_v2', { user_id: 'me' }) — só dev
148
- // 2. flag.set('payments_v2', { customer.tier: 'free' }, 1%) — 1% free users
149
- // 3. observe SLO + error rate; se OK, sobe para 10%, 50%, 100%
150
- ```
151
-
152
- ### Pattern: comparar versão antes/depois (Pergunta 2)
153
-
154
- ```sql
155
- -- PT-BR: SLI antes vs depois do deploy do build_id `abc123`
156
- -- Mostra error_rate per build, agrupado por versão
157
- select
158
- build_id,
159
- count(*) as total,
160
- sum(case when result_success = false then 1 else 0 end) as errors,
161
- 100.0 * sum(case when result_success = false then 1 else 0 end) / count(*) as error_pct,
162
- percentile_cont(0.99) within group (order by duration_ms) as p99_ms
163
- from observability.spans
164
- where
165
- service_name = 'payments'
166
- and timestamp > '2026-05-06 10:00'
167
- and build_id in ('v1.5.2', 'v1.5.3') -- versão anterior + atual
168
- group by build_id;
169
-
170
- -- PT-BR: se v1.5.3 tem error_pct ou p99_ms > v1.5.2 → regressão. Rollback ou fix.
171
- ```
172
-
173
- ### Pattern: instrumentação shift-left no PLAN.md de fase
174
-
175
- ```markdown
176
- # PLAN: Fase 42 — Novo método de pagamento
177
-
178
- ## Tarefas
179
-
180
- | # | Task | Output |
181
- |---|------|--------|
182
- | 1 | Implementar `processPaymentV2` em `src/payments/v2.ts` | função |
183
- | 2 | **Instrumentação OTel — bundled** | spans + atributos |
184
- | 3 | Adicionar feature flag `payments_v2` | flag config |
185
- | 4 | Tests unitários | tests/v2.spec.ts |
186
- | 5 | **ODD — 4 perguntas validadas** | comments no PR |
187
-
188
- ## ODD — Validação das 4 perguntas
189
-
190
- 1. **Faz o que esperei?**
191
- - Span `process_payment_v2` com atributo `result.success`
192
- - Query: `SELECT count(*) WHERE result_success=true / count(*)` deve ser ≥ 99% após release
193
-
194
- 2. **Compara à versão anterior?**
195
- - `build_id` em todo span permite cross-version
196
- - Query: ver "Pattern: comparar versão" acima
197
-
198
- 3. **Usuários estão usando?**
199
- - `customer.tier`, `payment.method` permitem slice & dice
200
- - Query: `SELECT customer.tier, payment.method, count(*) FROM ... WHERE feature_flag.payments_v2=true GROUP BY 1,2`
201
-
202
- 4. **Anomalias emergem?**
203
- - `error.type` enum: `'provider_down'`, `'declined'`, `'fraud_block'`
204
- - `branch_taken` para code paths
205
- - Alert: SLO burn rate > 2 sobre `WHERE feature_flag.payments_v2=true`
206
- ```
207
-
208
- ## Anti-patterns
209
-
210
- ### ANTI: instrumentação como fase separada
211
-
212
- ```text
213
- ANTI: "Vamos shipá-la primeiro, instrumentar na próxima sprint."
214
-
215
- PROBLEMA: você está em prod cego. Quando algo quebrar, você não tem dados para
216
- investigar. Adicionar instrumentação depois requer redeploy, que é
217
- arriscado durante incident.
218
-
219
- CERTO: instrumentação NO MESMO PR da feature. Não-negociável.
220
- ```
221
-
222
- ### ANTI: glass castle (medo de mexer em prod)
223
-
224
- ```text
225
- ANTI: "Não deploy hoje, é véspera de feriado."
226
- "Não deploy depois das 17h."
227
- "Vamos esperar a próxima janela de manutenção."
228
- (Equipe deploya 1× por semana, em batches grandes)
229
-
230
- PROBLEMA: deploys raros = deploys grandes = mais código mudando = mais risco.
231
- Cada deploy fica mais perigoso por sua raridade. Cycle vicioso.
232
-
233
- CERTO: deploy frequente (várias vezes ao dia) com features pequenas atrás de flags.
234
- Cada deploy quase nada. Reverter quase nada se quebra. Confiança aumenta.
235
- ```
236
-
237
- ### ANTI: rollback antes de investigar
238
-
239
- ```text
240
- ANTI: alerta dispara → rollback automático → "voltou ao normal" → ninguém
241
- investiga porque "tá funcionando agora"
242
-
243
- PROBLEMA: você perdeu a evidência. Próximo incident similar começa do zero.
244
- Padrão de regressão acumula tech debt invisível.
245
-
246
- CERTO: pause feature flag (não rollback do deploy) → investigue com observability →
247
- fix root cause → re-release. Rollback só se investigation tomar > 30min.
248
- ```
249
-
250
- ### ANTI: testar com 100% rollout em horário de baixa
251
-
252
- ```text
253
- ANTI: "Faz deploy 4h da manhã quando ninguém usa."
254
-
255
- PROBLEMA: você está rodando com 100% de risk em condições não-realistas.
256
- 0 tráfego = 0 sinal. Quando bug aparecer no horário de pico, você
257
- não terá dados.
258
-
259
- CERTO: deploy a qualquer hora atrás de feature flag em 1% → observe → 10% → 100%.
260
- Bugs aparecem no progressive rollout, não no horário de pico.
261
- ```
262
-
263
- ### ANTI: paginar on-call em vez do autor
264
-
265
- ```text
266
- ANTI: alerta dispara 2h após merge → on-call (que não escreveu o código) é paginado
267
-
268
- PROBLEMA: on-call não tem contexto. Vai procurar "que mudou ultimamente" — toma 30min.
269
- Autor está dormindo / fora do contexto. Feedback loop quebrado.
270
-
271
- CERTO: por 30-60min após merge, alertas vão para o AUTOR. Ele tem o contexto fresco,
272
- sabe o que mudou, pode reverter ou fix em 5min. Após janela, volta para on-call.
273
- ```
274
-
275
- ### ANTI: instrumentação só em happy path
276
-
277
- ```text
278
- ANTI: span com atributos só no `try` block; catch sem instrumentação
279
-
280
- PROBLEMA: você não sabe nada sobre falhas. Pergunta 4 (anomalias) impossível de responder.
281
-
282
- CERTO: cada `catch` adiciona `error.type` enum + `error.message` + `result.success=false`.
283
- Cada early return adiciona `branch_taken: 'short_circuit_validation'` etc.
284
- ```
285
-
286
- ## Verificação
287
-
288
- Antes de mergear PR, verificar as 4 perguntas:
289
-
290
- | # | Pergunta | Validação |
291
- |---|----------|-----------|
292
- | 1 | **Faz o que esperei?** | Existe atributo `result.success` em algum span do código tocado? |
293
- | 2 | **Compara à versão anterior?** | `build_id` é setado no span? (geralmente em SDK setup, validar uma vez) |
294
- | 3 | **Usuários estão usando?** | Existe `user.id` ou `tenant_id` ou `customer.tier` no span? |
295
- | 4 | **Anomalias emergem?** | `catch` blocks emitem `error.type` enum? branches if/else emitem `branch_taken`? |
296
-
297
- Se qualquer pergunta = NÃO → PR não mergeable. Adicione instrumentação.
298
-
299
- Após merge:
300
- - ✅ Feature flag desligada por default? (deploy ≠ release)
301
- - ✅ Auto-page do autor configurado por 30-60min?
302
- - ✅ SLI/SLO baseline sabido para comparação pré/pós release?
303
-
304
- ---
305
-
306
- ## Ver também
307
-
308
- - `kit/skills/_shared-observability/glossary.md` — termos canônicos, ODD, glass castle
309
- - `kit/skills/structured-events/SKILL.md` — campos canônicos
310
- - `kit/skills/distributed-tracing/SKILL.md` — instrumentação cross-service
311
- - `kit/skills/event-based-slos/SKILL.md` *(Phase 32)* — SLI para baseline pré/pós release
312
- - `kit/agents/observability-instrumenter.md` — agente que gera instrumentação
313
- - `kit/commands/instrumentar-fase.md` — comando que aplica ODD em fases
314
-
315
- *Material-fonte: Observability Engineering (O'Reilly, 2022) — Cap 11: "Observability-Driven Development".*
1
+ ---
2
+ name: observability-driven-development
3
+ description: Use ao bundlear telemetria com nova feature — 4 perguntas pré-PR, instrumentação shift-left, auto-page do autor por 30-60min após merge. Análogo TDD para produção.
4
+ ---
5
+
6
+ # Observabilidade — Observability-Driven Development (ODD)
7
+
8
+ ## Quando usar
9
+
10
+ LLM carrega esta skill ao escrever nova feature, planejar fase, ou code review. Trigger phrases:
11
+
12
+ - "ODD", "observability-driven development"
13
+ - "como sei que essa feature funciona em prod?"
14
+ - "instrumentar antes do PR"
15
+ - "shift-left observability"
16
+ - "auto-page do autor"
17
+ - "bundle telemetry com feature"
18
+
19
+ ## As 4 perguntas pré-PR (canônicas)
20
+
21
+ Antes de submeter PR, todo autor responde EM CÓDIGO:
22
+
23
+ | # | Pergunta | Como instrumentar |
24
+ |---|----------|-------------------|
25
+ | **1** | **Faz o que esperei?** | `result.success` boolean por evento + atributos do happy path (`order.id`, `user.id`) |
26
+ | **2** | **Compara à versão anterior?** | `build_id` em todo evento — permite `WHERE build_id = X vs build_id = Y` |
27
+ | **3** | **Usuários estão usando?** | Atributo de identidade (`user.id`, `tenant_id`, `customer.tier`) e do path do request (`endpoint`, `feature_flag.<name>`) |
28
+ | **4** | **Anomalias emergem?** | `error.type` enumerado + `duration_ms` + capturar todos os branches de código (try/catch + early returns) |
29
+
30
+ **Sem isso, o PR não é mergeável.** Não é regra burocrática — é a diferença entre "funciona em testes" e "funciona em produção".
31
+
32
+ ## Regras absolutas
33
+
34
+ - **Bundle telemetria com a feature** — instrumentação não é fase separada. Mesmo PR adiciona feature + spans + atributos.
35
+ - **Auto-page o autor por 30-60min após merge** — feedback loop curto. "Fui eu, eu sei o que era e eu posso reverter." NUNCA pular essa janela.
36
+ - **Decouple deploy de release** — feature flag por default. Deploy = código em prod desligado; release = liga aos poucos.
37
+ - **Test em prod com subset** — 1% de tráfego com flag ativada > 100% rollout em horário de baixa.
38
+ - **Rollback < rollforward em duvida** — observabilidade rica mostra o que está errado em segundos, mas só se você não rolou-back o evidência primeiro. Pause primeiro, investigue, então decida.
39
+ - **Toda code branch = atributo** — `if (x) { ... } else { ... }` precisa emitir atributo de qual branch foi tomada (`branch_taken: 'fast_path'` vs `'slow_path'`).
40
+ - **Tighten do feedback loop é o objetivo** — minutos do commit ao prod, não dias. Cada hora de delay multiplica custo de debug.
41
+
42
+ ## Patterns canônicos
43
+
44
+ ### Pattern: feature instrumentada nasce ODD-compliant
45
+
46
+ ```ts
47
+ // PT-BR: feature nova "novo método de pagamento" — instrumentação BUNDLED
48
+ import { trace, SpanStatusCode } from '@opentelemetry/api'
49
+
50
+ const tracer = trace.getTracer('payments')
51
+
52
+ export async function processPaymentV2(req: PaymentRequest) {
53
+ return tracer.startActiveSpan('process_payment_v2', async (span) => {
54
+ // PT-BR: Pergunta 3 — quem está usando?
55
+ span.setAttribute('user.id', req.user.id)
56
+ span.setAttribute('customer.tier', req.user.tier)
57
+ span.setAttribute('tenant_id', req.user.tenant)
58
+ span.setAttribute('endpoint', '/api/v2/payments')
59
+
60
+ // PT-BR: Pergunta 2 — qual versão?
61
+ span.setAttribute('build_id', process.env.BUILD_ID ?? 'dev')
62
+ span.setAttribute('feature_flag.payments_v2', true) // PT-BR: assumed via flag
63
+ span.setAttribute('payment.method', req.method) // novo: 'pix' | 'crypto' | 'card'
64
+
65
+ // PT-BR: Pergunta 4 — atributo por branch
66
+ if (req.amount > 1_000_00) {
67
+ span.setAttribute('branch_taken', 'high_value')
68
+ span.setAttribute('requires_3ds', true)
69
+ } else {
70
+ span.setAttribute('branch_taken', 'standard')
71
+ span.setAttribute('requires_3ds', false)
72
+ }
73
+
74
+ try {
75
+ const result = await chargeProvider(req)
76
+
77
+ // PT-BR: Pergunta 1 — fez o que esperei?
78
+ span.setAttribute('result.success', true)
79
+ span.setAttribute('payment.id', result.id)
80
+ span.setAttribute('payment.processor_response', result.processorCode)
81
+ span.setStatus({ code: SpanStatusCode.OK })
82
+ return result
83
+ } catch (e) {
84
+ // PT-BR: Pergunta 4 — anomalia identificada com type enum
85
+ span.setAttribute('result.success', false)
86
+ span.setAttribute('error.type', classify(e)) // 'provider_down' | 'declined' | 'fraud_block'
87
+ span.setAttribute('error.processor_code', e.code)
88
+ span.setStatus({ code: SpanStatusCode.ERROR })
89
+ throw e
90
+ } finally {
91
+ span.end()
92
+ }
93
+ })
94
+ }
95
+ ```
96
+
97
+ ### Pattern: auto-page autor (config CI/CD)
98
+
99
+ ```yaml
100
+ # PT-BR: GitHub Actions ou equivalente — paginar autor após merge
101
+ # .github/workflows/post-merge-watch.yml
102
+ name: post-merge-watch
103
+ on:
104
+ push:
105
+ branches: [main]
106
+ jobs:
107
+ page-author:
108
+ runs-on: ubuntu-latest
109
+ steps:
110
+ - name: Page commit author for 30-60min
111
+ run: |
112
+ AUTHOR_EMAIL="${{ github.event.head_commit.author.email }}"
113
+ PAGER_TOKEN="${{ secrets.PAGERDUTY_TOKEN }}"
114
+ # PT-BR: criar policy temporária — alertas SLO route para AUTHOR_EMAIL
115
+ # por 45 minutos. Após, retorna ao on-call normal.
116
+ curl -X POST https://api.pagerduty.com/oncall_overrides \
117
+ -H "Authorization: Token token=$PAGER_TOKEN" \
118
+ -d "{
119
+ \"override\": {
120
+ \"start\": \"$(date -u +%FT%TZ)\",
121
+ \"end\": \"$(date -u -d '+45 minutes' +%FT%TZ)\",
122
+ \"user\": {\"email\": \"$AUTHOR_EMAIL\"}
123
+ }
124
+ }"
125
+ ```
126
+
127
+ ### Pattern: deploy ≠ release (feature flag)
128
+
129
+ ```ts
130
+ // PT-BR: deploy do código com flag DESLIGADA
131
+ const isV2Enabled = (req: Request): boolean => {
132
+ // PT-BR: 0% inicialmente — deploy = código em prod, mas dormente
133
+ if (!flags.isEnabled('payments_v2', { user_id: req.user.id })) {
134
+ return false
135
+ }
136
+ return true
137
+ }
138
+
139
+ export async function processPayment(req: PaymentRequest) {
140
+ if (isV2Enabled(req)) {
141
+ return processPaymentV2(req)
142
+ }
143
+ return processPaymentV1(req)
144
+ }
145
+
146
+ // PT-BR: depois do deploy, release gradual:
147
+ // 1. flag.set('payments_v2', { user_id: 'me' }) — só dev
148
+ // 2. flag.set('payments_v2', { customer.tier: 'free' }, 1%) — 1% free users
149
+ // 3. observe SLO + error rate; se OK, sobe para 10%, 50%, 100%
150
+ ```
151
+
152
+ ### Pattern: comparar versão antes/depois (Pergunta 2)
153
+
154
+ ```sql
155
+ -- PT-BR: SLI antes vs depois do deploy do build_id `abc123`
156
+ -- Mostra error_rate per build, agrupado por versão
157
+ select
158
+ build_id,
159
+ count(*) as total,
160
+ sum(case when result_success = false then 1 else 0 end) as errors,
161
+ 100.0 * sum(case when result_success = false then 1 else 0 end) / count(*) as error_pct,
162
+ percentile_cont(0.99) within group (order by duration_ms) as p99_ms
163
+ from observability.spans
164
+ where
165
+ service_name = 'payments'
166
+ and timestamp > '2026-05-06 10:00'
167
+ and build_id in ('v1.5.2', 'v1.5.3') -- versão anterior + atual
168
+ group by build_id;
169
+
170
+ -- PT-BR: se v1.5.3 tem error_pct ou p99_ms > v1.5.2 → regressão. Rollback ou fix.
171
+ ```
172
+
173
+ ### Pattern: instrumentação shift-left no PLAN.md de fase
174
+
175
+ ```markdown
176
+ # PLAN: Fase 42 — Novo método de pagamento
177
+
178
+ ## Tarefas
179
+
180
+ | # | Task | Output |
181
+ |---|------|--------|
182
+ | 1 | Implementar `processPaymentV2` em `src/payments/v2.ts` | função |
183
+ | 2 | **Instrumentação OTel — bundled** | spans + atributos |
184
+ | 3 | Adicionar feature flag `payments_v2` | flag config |
185
+ | 4 | Tests unitários | tests/v2.spec.ts |
186
+ | 5 | **ODD — 4 perguntas validadas** | comments no PR |
187
+
188
+ ## ODD — Validação das 4 perguntas
189
+
190
+ 1. **Faz o que esperei?**
191
+ - Span `process_payment_v2` com atributo `result.success`
192
+ - Query: `SELECT count(*) WHERE result_success=true / count(*)` deve ser ≥ 99% após release
193
+
194
+ 2. **Compara à versão anterior?**
195
+ - `build_id` em todo span permite cross-version
196
+ - Query: ver "Pattern: comparar versão" acima
197
+
198
+ 3. **Usuários estão usando?**
199
+ - `customer.tier`, `payment.method` permitem slice & dice
200
+ - Query: `SELECT customer.tier, payment.method, count(*) FROM ... WHERE feature_flag.payments_v2=true GROUP BY 1,2`
201
+
202
+ 4. **Anomalias emergem?**
203
+ - `error.type` enum: `'provider_down'`, `'declined'`, `'fraud_block'`
204
+ - `branch_taken` para code paths
205
+ - Alert: SLO burn rate > 2 sobre `WHERE feature_flag.payments_v2=true`
206
+ ```
207
+
208
+ ## Anti-patterns
209
+
210
+ ### ANTI: instrumentação como fase separada
211
+
212
+ ```text
213
+ ANTI: "Vamos shipá-la primeiro, instrumentar na próxima sprint."
214
+
215
+ PROBLEMA: você está em prod cego. Quando algo quebrar, você não tem dados para
216
+ investigar. Adicionar instrumentação depois requer redeploy, que é
217
+ arriscado durante incident.
218
+
219
+ CERTO: instrumentação NO MESMO PR da feature. Não-negociável.
220
+ ```
221
+
222
+ ### ANTI: glass castle (medo de mexer em prod)
223
+
224
+ ```text
225
+ ANTI: "Não deploy hoje, é véspera de feriado."
226
+ "Não deploy depois das 17h."
227
+ "Vamos esperar a próxima janela de manutenção."
228
+ (Equipe deploya 1× por semana, em batches grandes)
229
+
230
+ PROBLEMA: deploys raros = deploys grandes = mais código mudando = mais risco.
231
+ Cada deploy fica mais perigoso por sua raridade. Cycle vicioso.
232
+
233
+ CERTO: deploy frequente (várias vezes ao dia) com features pequenas atrás de flags.
234
+ Cada deploy quase nada. Reverter quase nada se quebra. Confiança aumenta.
235
+ ```
236
+
237
+ ### ANTI: rollback antes de investigar
238
+
239
+ ```text
240
+ ANTI: alerta dispara → rollback automático → "voltou ao normal" → ninguém
241
+ investiga porque "tá funcionando agora"
242
+
243
+ PROBLEMA: você perdeu a evidência. Próximo incident similar começa do zero.
244
+ Padrão de regressão acumula tech debt invisível.
245
+
246
+ CERTO: pause feature flag (não rollback do deploy) → investigue com observability →
247
+ fix root cause → re-release. Rollback só se investigation tomar > 30min.
248
+ ```
249
+
250
+ ### ANTI: testar com 100% rollout em horário de baixa
251
+
252
+ ```text
253
+ ANTI: "Faz deploy 4h da manhã quando ninguém usa."
254
+
255
+ PROBLEMA: você está rodando com 100% de risk em condições não-realistas.
256
+ 0 tráfego = 0 sinal. Quando bug aparecer no horário de pico, você
257
+ não terá dados.
258
+
259
+ CERTO: deploy a qualquer hora atrás de feature flag em 1% → observe → 10% → 100%.
260
+ Bugs aparecem no progressive rollout, não no horário de pico.
261
+ ```
262
+
263
+ ### ANTI: paginar on-call em vez do autor
264
+
265
+ ```text
266
+ ANTI: alerta dispara 2h após merge → on-call (que não escreveu o código) é paginado
267
+
268
+ PROBLEMA: on-call não tem contexto. Vai procurar "que mudou ultimamente" — toma 30min.
269
+ Autor está dormindo / fora do contexto. Feedback loop quebrado.
270
+
271
+ CERTO: por 30-60min após merge, alertas vão para o AUTOR. Ele tem o contexto fresco,
272
+ sabe o que mudou, pode reverter ou fix em 5min. Após janela, volta para on-call.
273
+ ```
274
+
275
+ ### ANTI: instrumentação só em happy path
276
+
277
+ ```text
278
+ ANTI: span com atributos só no `try` block; catch sem instrumentação
279
+
280
+ PROBLEMA: você não sabe nada sobre falhas. Pergunta 4 (anomalias) impossível de responder.
281
+
282
+ CERTO: cada `catch` adiciona `error.type` enum + `error.message` + `result.success=false`.
283
+ Cada early return adiciona `branch_taken: 'short_circuit_validation'` etc.
284
+ ```
285
+
286
+ ## Verificação
287
+
288
+ Antes de mergear PR, verificar as 4 perguntas:
289
+
290
+ | # | Pergunta | Validação |
291
+ |---|----------|-----------|
292
+ | 1 | **Faz o que esperei?** | Existe atributo `result.success` em algum span do código tocado? |
293
+ | 2 | **Compara à versão anterior?** | `build_id` é setado no span? (geralmente em SDK setup, validar uma vez) |
294
+ | 3 | **Usuários estão usando?** | Existe `user.id` ou `tenant_id` ou `customer.tier` no span? |
295
+ | 4 | **Anomalias emergem?** | `catch` blocks emitem `error.type` enum? branches if/else emitem `branch_taken`? |
296
+
297
+ Se qualquer pergunta = NÃO → PR não mergeable. Adicione instrumentação.
298
+
299
+ Após merge:
300
+ - ✅ Feature flag desligada por default? (deploy ≠ release)
301
+ - ✅ Auto-page do autor configurado por 30-60min?
302
+ - ✅ SLI/SLO baseline sabido para comparação pré/pós release?
303
+
304
+ ---
305
+
306
+ ## Ver também
307
+
308
+ - `kit/skills/_shared-observability/glossary.md` — termos canônicos, ODD, glass castle
309
+ - `kit/skills/structured-events/SKILL.md` — campos canônicos
310
+ - `kit/skills/distributed-tracing/SKILL.md` — instrumentação cross-service
311
+ - `kit/skills/event-based-slos/SKILL.md` *(Phase 32)* — SLI para baseline pré/pós release
312
+ - `kit/agents/observability-instrumenter.md` — agente que gera instrumentação
313
+ - `kit/commands/instrumentar-fase.md` — comando que aplica ODD em fases
314
+
315
+ *Material-fonte: Observability Engineering (O'Reilly, 2022) — Cap 11: "Observability-Driven Development".*