@luanpdd/kit-mcp 1.9.0 → 1.11.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.
- package/CHANGELOG.md +86 -0
- package/README.md +58 -0
- package/gates/ai-prompt-stability.md +120 -0
- package/gates/golden-signals-coverage.md +133 -0
- package/gates/legacy-refactor-safety.md +178 -0
- package/gates/observability-coverage.md +151 -0
- package/gates/postmortem-template-required.md +127 -0
- package/gates/prr-checklist-coverage.md +128 -0
- package/gates/release-pipeline-policy.md +132 -0
- package/kit/COMANDOS.md +15 -0
- package/kit/agents/ai-mutation-tester.md +298 -0
- package/kit/agents/cascading-failures-auditor.md +306 -0
- package/kit/agents/executor.md +13 -0
- package/kit/agents/golden-signals-instrumenter.md +241 -0
- package/kit/agents/legacy-characterizer.md +378 -0
- package/kit/agents/load-shedding-instrumenter.md +297 -0
- package/kit/agents/observability-coverage-auditor.md +325 -0
- package/kit/agents/omm-auditor.md +99 -0
- package/kit/agents/payload-capture-instrumenter.md +283 -0
- package/kit/agents/planner.md +29 -0
- package/kit/agents/postmortem-writer.md +282 -0
- package/kit/agents/prr-conductor.md +296 -0
- package/kit/agents/refactor-safety-auditor.md +414 -0
- package/kit/agents/release-pipeline-auditor.md +360 -0
- package/kit/agents/seam-finder.md +367 -0
- package/kit/agents/shotgun-surgery-detector.md +359 -0
- package/kit/agents/storytelling-analyst.md +309 -0
- package/kit/agents/supabase-architect.md +49 -0
- package/kit/agents/supabase-edge-fn-writer.md +114 -0
- package/kit/agents/supabase-migration-writer.md +80 -0
- package/kit/agents/supabase-storage-implementer.md +156 -0
- package/kit/agents/toil-auditor.md +277 -0
- package/kit/agents/verifier.md +30 -0
- package/kit/commands/auditar-cascading.md +111 -0
- package/kit/commands/auditar-marco.md +124 -1
- package/kit/commands/auditar-observabilidade-cobertura.md +183 -0
- package/kit/commands/auditar-refactor.md +219 -0
- package/kit/commands/auditar-release.md +109 -0
- package/kit/commands/auditar-toil.md +129 -0
- package/kit/commands/capturar-payloads.md +193 -0
- package/kit/commands/caracterizar-prompt.md +195 -0
- package/kit/commands/caracterizar.md +212 -0
- package/kit/commands/concluir-marco.md +95 -1
- package/kit/commands/detectar-duplicacao.md +197 -0
- package/kit/commands/discutir-fase.md +41 -0
- package/kit/commands/encontrar-seams.md +136 -0
- package/kit/commands/forense.md +103 -1
- package/kit/commands/golden-signals.md +142 -0
- package/kit/commands/legacy.md +263 -0
- package/kit/commands/load-shedding.md +117 -0
- package/kit/commands/observabilidade.md +2 -0
- package/kit/commands/postmortem.md +179 -0
- package/kit/commands/prr.md +205 -0
- package/kit/commands/refactor-seguro.md +321 -0
- package/kit/commands/risk-budget.md +220 -0
- package/kit/commands/sre.md +230 -0
- package/kit/commands/storytelling.md +179 -0
- package/kit/skills/_shared-legacy/glossary.md +389 -0
- package/kit/skills/_shared-sre/glossary.md +712 -0
- package/kit/skills/ai-prompt-characterization/SKILL.md +335 -0
- package/kit/skills/blameless-postmortems/SKILL.md +340 -0
- package/kit/skills/cascading-failures/SKILL.md +307 -0
- package/kit/skills/eliminating-toil/SKILL.md +243 -0
- package/kit/skills/event-based-slos/SKILL.md +22 -0
- package/kit/skills/four-golden-signals/SKILL.md +314 -0
- package/kit/skills/hermetic-builds/SKILL.md +323 -0
- package/kit/skills/legacy-api-only-applications/SKILL.md +358 -0
- package/kit/skills/legacy-characterization-tests/SKILL.md +330 -0
- package/kit/skills/legacy-effect-analysis/SKILL.md +331 -0
- package/kit/skills/legacy-extract-class/SKILL.md +203 -0
- package/kit/skills/legacy-monster-methods/SKILL.md +444 -0
- package/kit/skills/legacy-programming-by-difference/SKILL.md +252 -0
- package/kit/skills/legacy-seams-and-test-harness/SKILL.md +460 -0
- package/kit/skills/legacy-shotgun-surgery/SKILL.md +286 -0
- package/kit/skills/legacy-sprout-wrap-techniques/SKILL.md +434 -0
- package/kit/skills/legacy-storytelling-naked-crc/SKILL.md +270 -0
- package/kit/skills/llm-as-dependency/SKILL.md +436 -0
- package/kit/skills/load-shedding-graceful-degradation/SKILL.md +396 -0
- package/kit/skills/pre-refactor-characterization/SKILL.md +421 -0
- package/kit/skills/production-readiness-review/SKILL.md +305 -0
- package/kit/skills/release-engineering/SKILL.md +367 -0
- package/kit/skills/retry-strategies/SKILL.md +372 -0
- package/kit/skills/sre-risk-management/SKILL.md +221 -0
- package/package.json +2 -2
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cascading-failures
|
|
3
|
+
description: Use ao desenhar/auditar serviços com deps externas — cap 22 livro Google SRE. Triggers de cascade, loops de feedback, prevenção via timeout/jitter/deadline/circuit breaker, immediate response.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# SRE — Addressing Cascading Failures
|
|
7
|
+
|
|
8
|
+
## Quando usar
|
|
9
|
+
|
|
10
|
+
LLM carrega esta skill ao analisar serviço com risco de cascade, ou durante incident em progresso onde failure se amplifica. Trigger phrases:
|
|
11
|
+
|
|
12
|
+
- "cascading failure", "falha em cascata"
|
|
13
|
+
- "retry storm", "thundering herd"
|
|
14
|
+
- "outage propagando", "serviço caindo um após outro"
|
|
15
|
+
- "como prevenir cascade?", "circuit breaker"
|
|
16
|
+
- "cap 22 Google SRE"
|
|
17
|
+
- "deadline propagation", "load shedding"
|
|
18
|
+
|
|
19
|
+
## Regras absolutas
|
|
20
|
+
|
|
21
|
+
- **Cascade tem 5 triggers canônicos:** server overload, resource exhaustion, service unavailability, latency spike sem timeout, retry sem jitter. Memorize-os.
|
|
22
|
+
- **Prevenção custa 1×, recuperação custa 100×.** Toda dep crítica DEVE ter timeout + retry com jitter + circuit breaker + deadline propagation. Sem isso, cascade é questão de tempo.
|
|
23
|
+
- **Saturation (cap 6 v1.10) é early warning de cascade.** Quando saturation > 80%, ainda há tempo. Quando hit 100%, já está em cascade.
|
|
24
|
+
- **Retry SEMPRE com jitter.** Full jitter por default (`delay = random(0, base × 2^attempt)`). Sem jitter = thundering herd garantido.
|
|
25
|
+
- **Retry SEMPRE com deadline.** Retry sem timeout amplifica cascade — call de 30s vira 90s vira 270s. Deadline propagation evita work zumbi.
|
|
26
|
+
- **Circuit breaker DEFAULT em qualquer dep externa.** Estados closed/open/half-open. Open dispara após N failures consecutivas; half-open permite 1 probe; closed após probe verde.
|
|
27
|
+
- **Load shedding > 503 graceful > queue overflow.** Server saturated DEVE retornar 503 com Retry-After ANTES de aceitar request que vai falhar. Aceitar e cair = pior que rejeitar.
|
|
28
|
+
- **Slow start em recovery.** Após outage, ramp-up gradual (10% → 25% → 50% → 100%). Full blast em recovery = falha de novo (caches frios, conn pools).
|
|
29
|
+
|
|
30
|
+
## Patterns canônicos
|
|
31
|
+
|
|
32
|
+
### Pattern 1: 5 triggers canônicos de cascade (cap 22)
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
1. SERVER OVERLOAD
|
|
36
|
+
Sintoma: load > capacity → latency p99 sobe 10× → errors 5xx → crashes
|
|
37
|
+
Trigger upstream: traffic spike, outage de cache, batch job rodou em horário ruim
|
|
38
|
+
Detect: Saturation gauge (cap 6) > 80% por > 5 min
|
|
39
|
+
Resposta: load shedding + escalação manual
|
|
40
|
+
|
|
41
|
+
2. RESOURCE EXHAUSTION
|
|
42
|
+
Tipos: CPU, memory, file descriptors, threads, connection pool
|
|
43
|
+
Sintoma específico:
|
|
44
|
+
CPU 100% → latency sobe; FDs esgotados → "too many open files"
|
|
45
|
+
Memory OOM → process kill; threads → deadlock; conn pool empty → wait
|
|
46
|
+
Detect: monitor por recurso específico; alarmes em 80% de cada
|
|
47
|
+
Resposta: configure limits; circuit breaker; rate limit caller
|
|
48
|
+
|
|
49
|
+
3. SERVICE UNAVAILABILITY (DEP DOWN)
|
|
50
|
+
Sintoma: dep externa retorna 5xx ou timeout. Sem circuit breaker:
|
|
51
|
+
N clients × M retries × T deadline = explosão de calls
|
|
52
|
+
Detect: error rate de dep > 50% por 1 min; latency dep > p99 normal × 5
|
|
53
|
+
Resposta: circuit breaker abre; fallback (cache, default value, degraded mode)
|
|
54
|
+
|
|
55
|
+
4. LATENCY SPIKE SEM TIMEOUT
|
|
56
|
+
Sintoma: dep responde lento mas não falha. Caller fica esperando.
|
|
57
|
+
Conn pool de caller esgota; novos requests também ficam pendurados.
|
|
58
|
+
Detect: dep latency p99 > baseline × 5
|
|
59
|
+
Resposta: timeout AGRESSIVO (ex: p99.9 baseline + 50%); circuit breaker
|
|
60
|
+
|
|
61
|
+
5. RETRY SEM JITTER
|
|
62
|
+
Sintoma: 1000 clients retentam ao mesmo tempo após dep recovery.
|
|
63
|
+
Server recém-recuperado é matado pelo wake-up.
|
|
64
|
+
Detect: traffic spike no momento exato de recovery
|
|
65
|
+
Resposta: full jitter; retry budget global; slow start
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Pattern 2: Defesa em camadas (cap 22)
|
|
69
|
+
|
|
70
|
+
Cada chamada externa precisa de **5 camadas de defesa**:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
// Camada 1: Timeout agressivo
|
|
74
|
+
const TIMEOUT_MS = 2000 // p99.9 baseline + 50%
|
|
75
|
+
|
|
76
|
+
// Camada 2: Retry com jitter + deadline
|
|
77
|
+
async function callDep(input: Input, deadline: number): Promise<Output> {
|
|
78
|
+
const startMs = performance.now()
|
|
79
|
+
let attempt = 0
|
|
80
|
+
let lastError: Error | undefined
|
|
81
|
+
|
|
82
|
+
while (true) {
|
|
83
|
+
const remaining = deadline - performance.now()
|
|
84
|
+
if (remaining <= 0) throw new DeadlineExceededError(lastError)
|
|
85
|
+
|
|
86
|
+
const callTimeoutMs = Math.min(TIMEOUT_MS, remaining)
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
// Camada 3: Circuit breaker
|
|
90
|
+
if (circuitBreaker.isOpen()) throw new CircuitOpenError()
|
|
91
|
+
|
|
92
|
+
const result = await withTimeout(
|
|
93
|
+
depClient.call(input),
|
|
94
|
+
callTimeoutMs
|
|
95
|
+
)
|
|
96
|
+
circuitBreaker.recordSuccess()
|
|
97
|
+
return result
|
|
98
|
+
} catch (e) {
|
|
99
|
+
lastError = e as Error
|
|
100
|
+
circuitBreaker.recordFailure()
|
|
101
|
+
|
|
102
|
+
// Camada 4: Não retentar erros não-retentáveis
|
|
103
|
+
if (!isRetryable(e)) throw e
|
|
104
|
+
|
|
105
|
+
// Camada 5: Retry budget global
|
|
106
|
+
if (!retryBudget.tryAcquire()) throw new RetryBudgetExhaustedError(e)
|
|
107
|
+
|
|
108
|
+
attempt++
|
|
109
|
+
if (attempt >= MAX_RETRIES) throw e
|
|
110
|
+
|
|
111
|
+
// Full jitter
|
|
112
|
+
const baseMs = 100 * Math.pow(2, attempt - 1)
|
|
113
|
+
const jitterMs = Math.random() * baseMs * 2
|
|
114
|
+
await sleep(Math.min(jitterMs, remaining))
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function isRetryable(e: any): boolean {
|
|
120
|
+
// 4xx (validation, auth, not_found) → não retry
|
|
121
|
+
// 5xx, timeout, connection reset → retry
|
|
122
|
+
if (e.statusCode >= 400 && e.statusCode < 500) return false
|
|
123
|
+
if (e.statusCode === 429) return true // rate limited — retry com backoff
|
|
124
|
+
return true
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Pattern 3: Circuit breaker — estados canônicos
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
┌────────────────────┐
|
|
132
|
+
│ CLOSED (normal) │
|
|
133
|
+
│ request flows OK │
|
|
134
|
+
└─────────┬──────────┘
|
|
135
|
+
│ N consecutive failures
|
|
136
|
+
▼
|
|
137
|
+
┌────────────────────┐
|
|
138
|
+
│ OPEN │
|
|
139
|
+
│ fail fast for T │
|
|
140
|
+
│ no calls to dep │
|
|
141
|
+
└─────────┬──────────┘
|
|
142
|
+
│ T elapsed
|
|
143
|
+
▼
|
|
144
|
+
┌────────────────────┐
|
|
145
|
+
│ HALF-OPEN │
|
|
146
|
+
│ allow 1-N probes │
|
|
147
|
+
└────┬───────────┬───┘
|
|
148
|
+
success │ │ failure
|
|
149
|
+
▼ ▼
|
|
150
|
+
CLOSED OPEN
|
|
151
|
+
|
|
152
|
+
Configuração canônica:
|
|
153
|
+
N (failures-to-open): 5-10 consecutive
|
|
154
|
+
T (open duration): 30-60s
|
|
155
|
+
half-open probe count: 1-5
|
|
156
|
+
failure detection window: 30-60s rolling
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Pattern 4: Deadline propagation across hops
|
|
160
|
+
|
|
161
|
+
```text
|
|
162
|
+
Client → Service A (deadline=30s) → Service B (deadline=?) → Service C (deadline=?)
|
|
163
|
+
|
|
164
|
+
WRONG (cascade amplification):
|
|
165
|
+
A: receives deadline=30s, calls B with timeout=30s
|
|
166
|
+
B: receives no deadline, default 30s, calls C with timeout=30s
|
|
167
|
+
C: takes 30s
|
|
168
|
+
Total: 30s in C, plus parent overhead. Client gone at 30s, A-B-C still working.
|
|
169
|
+
|
|
170
|
+
RIGHT (deadline propagation):
|
|
171
|
+
A: receives TTL=30s; takes 100ms processing; calls B with TTL=29.9s
|
|
172
|
+
B: receives TTL=29.9s; takes 50ms; calls C with TTL=29.85s
|
|
173
|
+
C: receives TTL=29.85s; works until that limit, no more
|
|
174
|
+
When TTL hits 0, ALL hops fail fast. No zombie work.
|
|
175
|
+
|
|
176
|
+
Implementação:
|
|
177
|
+
- HTTP: header `Deadline-Ms` ou similar (custom)
|
|
178
|
+
- gRPC: built-in `grpc-timeout` header
|
|
179
|
+
- JS/TS: AbortSignal.timeout(remainingMs)
|
|
180
|
+
- Each hop: deadline = received_deadline - elapsed_local; abort se ≤ 0
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Pattern 5: Defesas server-side
|
|
184
|
+
|
|
185
|
+
Server protege a si próprio (não confia em clientes):
|
|
186
|
+
|
|
187
|
+
| Defesa | Técnica | Exemplo |
|
|
188
|
+
|---|---|---|
|
|
189
|
+
| **Rate limit per-client** | Token bucket no proxy/gateway | Kong/Envoy rate limit; 100 req/s/client |
|
|
190
|
+
| **Concurrency limit** | Semaphore no handler | Máx 1000 in-flight; reject 503 if cheio |
|
|
191
|
+
| **Queue depth limit** | Bound + drop policy | Queue máx 10k msgs; drop oldest > 5k |
|
|
192
|
+
| **Resource budget** | Cgroups / container limits | CPU 4 cores, memory 8GB hard cap |
|
|
193
|
+
| **Slow start na recovery** | Gradual ramp | Aceita 10% → 25% → 50% → 100% por 5 min |
|
|
194
|
+
|
|
195
|
+
### Pattern 6: Testing for cascading failures
|
|
196
|
+
|
|
197
|
+
Antes de prod, exercitar cascade scenarios:
|
|
198
|
+
|
|
199
|
+
```text
|
|
200
|
+
1. Game day exercise
|
|
201
|
+
- Cap 1 dep crítica em 50% errors via fault injection
|
|
202
|
+
- Observar: caller circuit breakers abrem? Latency caller estável?
|
|
203
|
+
- Métrica: zero impacto a clientes (degraded mode kicks in)
|
|
204
|
+
|
|
205
|
+
2. Load test até saturação
|
|
206
|
+
- Ramp traffic até 1.5× expected peak
|
|
207
|
+
- Confirmar: load shedding ativa antes de crash
|
|
208
|
+
- Métrica: error rate sob 1% mesmo em 1.5× load
|
|
209
|
+
|
|
210
|
+
3. Chaos engineering
|
|
211
|
+
- Random kill de instâncias (Chaos Monkey)
|
|
212
|
+
- Confirmar: retries com jitter espalham wake-up
|
|
213
|
+
- Métrica: SLO mantido durante 10 kills/hour
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Anti-patterns
|
|
217
|
+
|
|
218
|
+
### ANTI: timeout otimista
|
|
219
|
+
|
|
220
|
+
```text
|
|
221
|
+
ANTI: timeout = p99 baseline. "Maioria das requests fica abaixo".
|
|
222
|
+
|
|
223
|
+
PROBLEMA: tail latency (1%) sempre estoura. Cada 100 requests, 1
|
|
224
|
+
consome timeout inteiro. Conn pool acumula slow requests.
|
|
225
|
+
|
|
226
|
+
CERTO: timeout = p99.9 baseline + 50% margem. Aceita que 0.1% será
|
|
227
|
+
cancelado. Tail é problema de dep, não cliente.
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### ANTI: retry infinito com backoff "razoável"
|
|
231
|
+
|
|
232
|
+
```text
|
|
233
|
+
ANTI: retry até sucesso, com 1s/2s/4s/8s/... exponencial sem cap.
|
|
234
|
+
|
|
235
|
+
PROBLEMA: durante outage de 30 min, último retry seria após 30 min
|
|
236
|
+
esperando. Conn fica pendurada. Memory leak.
|
|
237
|
+
|
|
238
|
+
CERTO: max retries = 3-5; max backoff = 30s; deadline global
|
|
239
|
+
(request terminada após T segundos não importa quantos
|
|
240
|
+
retries). Após max, fallback ou error final.
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### ANTI: circuit breaker per-instance (não compartilhado)
|
|
244
|
+
|
|
245
|
+
```text
|
|
246
|
+
ANTI: cada instância de service A tem seu próprio circuit breaker
|
|
247
|
+
pra dep B. Quando B fica lenta, instância 1 abre circuito,
|
|
248
|
+
mas instâncias 2-100 ainda pingam B até abrirem.
|
|
249
|
+
|
|
250
|
+
PROBLEMA: 100× mais carga em B doente. B nunca recupera.
|
|
251
|
+
|
|
252
|
+
CERTO: circuit breaker compartilhado (e.g., via Redis/Memcached para
|
|
253
|
+
state) OR lib que detecta failure rate cross-instance via
|
|
254
|
+
gossip/coordination. Open = cluster all stop.
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### ANTI: load shedding via reject ao invés de 503 + Retry-After
|
|
258
|
+
|
|
259
|
+
```text
|
|
260
|
+
ANTI: server saturated → drop conn TCP-level (RST).
|
|
261
|
+
|
|
262
|
+
PROBLEMA: client não sabe que precisa esperar. Retry imediato.
|
|
263
|
+
Mais carga. Retry storm.
|
|
264
|
+
|
|
265
|
+
CERTO: 503 Service Unavailable + Retry-After: 30 (segundos).
|
|
266
|
+
Client aware retry com delay. Backoff respeitado.
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### ANTI: graceful degradation só em prod
|
|
270
|
+
|
|
271
|
+
```text
|
|
272
|
+
ANTI: degraded mode só liga durante incident; nunca exercitado.
|
|
273
|
+
|
|
274
|
+
PROBLEMA: quando precisa, descobre bug no degraded mode. Outage
|
|
275
|
+
piora.
|
|
276
|
+
|
|
277
|
+
CERTO: degraded mode é PATH PRINCIPAL em alguma fração de tráfego
|
|
278
|
+
(1%) por padrão. Sempre exercitado. Quando dep cai, ramp pra
|
|
279
|
+
100% degraded é tested transition.
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Verificação
|
|
283
|
+
|
|
284
|
+
Antes de aceitar serviço em prod:
|
|
285
|
+
|
|
286
|
+
1. Toda chamada a dep externa tem timeout < p99.9 baseline + 50%
|
|
287
|
+
2. Toda retry tem jitter (full jitter default)
|
|
288
|
+
3. Toda chamada respeita deadline propagation
|
|
289
|
+
4. Circuit breaker ativo em deps críticas (estados closed/open/half-open)
|
|
290
|
+
5. Server-side: rate limit + concurrency limit + queue depth bound
|
|
291
|
+
6. Slow start configurado em deploy/recovery
|
|
292
|
+
7. Game day exercise rodado nos últimos 90 dias
|
|
293
|
+
8. Saturation gauge (cap 6) instrumentado e alertado em 80%
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Ver também
|
|
298
|
+
|
|
299
|
+
- [`_shared-sre/glossary.md`](../_shared-sre/glossary.md) — vocabulário cap 22 (cascading failure, retry storm, etc.)
|
|
300
|
+
- [`retry-strategies`](../retry-strategies/SKILL.md) (v1.11) — detalhes de jitter + deadline propagation
|
|
301
|
+
- [`load-shedding-graceful-degradation`](../load-shedding-graceful-degradation/SKILL.md) (v1.11) — defesas server-side
|
|
302
|
+
- [`four-golden-signals`](../four-golden-signals/SKILL.md) (v1.10) — Saturation como early warning de cascade
|
|
303
|
+
- [`production-readiness-review`](../production-readiness-review/SKILL.md) (v1.10) — PRR Axe 4 verifica defesas
|
|
304
|
+
- [`omm-auditor`](../../agents/omm-auditor.md) (v1.9) — Capacidade 1 (Resilience) consume cascading-failures-auditor
|
|
305
|
+
- [`cascading-failures-auditor`](../../agents/cascading-failures-auditor.md) (v1.11) — agent que detecta gaps automaticamente
|
|
306
|
+
|
|
307
|
+
*Material-fonte: Site Reliability Engineering — Beyer/Jones/Petoff/Murphy (Google/O'Reilly, 2016) — Cap 22: "Addressing Cascading Failures".*
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eliminating-toil
|
|
3
|
+
description: Use ao identificar/eliminar toil — 6 critérios canônicos (manual, repetitivo, automatizável, tático, sem valor durável, escala linear), regra ≤ 50%, automação como invariante.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# SRE — Eliminating Toil
|
|
7
|
+
|
|
8
|
+
## Quando usar
|
|
9
|
+
|
|
10
|
+
LLM carrega esta skill ao auditar tarefas operacionais, classificar trabalho como toil/non-toil, ou propor automação. Trigger phrases:
|
|
11
|
+
|
|
12
|
+
- "toil", "trabalho operacional"
|
|
13
|
+
- "eliminar toil", "reduzir toil"
|
|
14
|
+
- "≤ 50% toil", "regra 50%"
|
|
15
|
+
- "automation", "automatizar tarefa repetitiva"
|
|
16
|
+
- "isso é toil ou overhead?"
|
|
17
|
+
- "Google SRE cap 5"
|
|
18
|
+
- "TOIL-AUDIT"
|
|
19
|
+
|
|
20
|
+
## Regras absolutas
|
|
21
|
+
|
|
22
|
+
- **Toil tem 6 critérios canônicos** — uma tarefa É toil se TODOS os 6 valem: (1) **Manual** — humano executa cada vez; (2) **Repetitivo** — você já fez isso 3+ vezes; (3) **Automatizável** — script/cron resolve sem julgamento humano; (4) **Tático** — reage a evento, não planeja; (5) **Sem valor durável** — não cria asset permanente; (6) **Escala linear** — mais users = mais trabalho. Se QUALQUER um dos 6 = não, NÃO é toil (é overhead ou grungy work).
|
|
23
|
+
- **Regra ≤ 50%** — SRE não pode gastar mais que 50% do tempo em toil; restante é engineering (automação, capacity planning, instrumentation, postmortems). Se medindo > 50% por 1+ trimestre, é red flag — peça ajuda à liderança.
|
|
24
|
+
- **Toil ≠ overhead** — reuniões, RH, planejamento de quarter, performance review são **overhead** — necessários, não-elimináveis, NÃO contam para a regra ≤ 50%. Confundir overhead com toil = sub-medir.
|
|
25
|
+
- **Toil ≠ grungy work** — refactor de código legado, security cleanup, DB rebuild para reduzir bloat são **grungy work** — necessários, têm valor durável, são engineering trabalho. NÃO contam como toil.
|
|
26
|
+
- **Automação é o objetivo, não o meio** — automatizar parcialmente (humano clica botão A, depois B, depois C) ainda é toil. Automação completa (cron + script + alert se falhar) elimina toil. Meias-medidas perpetuam.
|
|
27
|
+
- **Toil tax cresce com produto** — cada feature nova adiciona toil potencial: deploy manual, migration manual, feature flag rotation, customer-specific config. Prevenir > remediar — design feature considerando "como auto-operar isso?".
|
|
28
|
+
- **Quantificar toil em horas-pessoa** — "TOIL-AUDIT.md" deve ter coluna `hours_per_week_per_person` para cada item. Sem quantificação, "muito toil" é subjetivo e não-acionável.
|
|
29
|
+
- **Priorizar por (frequency × pain) / automation_effort** — P0 = alto frequency + alto pain + baixo effort. P2 = baixa frequency OU alto effort. Não automatizar tudo de uma vez — começar pelo P0.
|
|
30
|
+
|
|
31
|
+
## Patterns canônicos
|
|
32
|
+
|
|
33
|
+
### Pattern: decision tree para classificar trabalho
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
Tarefa repetitiva detectada → aplicar 6 critérios canônicos:
|
|
37
|
+
|
|
38
|
+
1. Manual? (humano executa cada vez) ┐
|
|
39
|
+
2. Repetitiva? (já fiz isso 3+ vezes) │
|
|
40
|
+
3. Automatizável? (script/cron resolve sem julgamento) │── Se TODOS sim → TOIL
|
|
41
|
+
4. Tática? (reage a evento, não planeja) │ → automatizar / eliminar
|
|
42
|
+
5. Sem valor durável? (não cria asset permanente) │ → contar em ≤ 50% rule
|
|
43
|
+
6. Escala linear? (mais users = mais trabalho) ─┘
|
|
44
|
+
|
|
45
|
+
Se NÃO for toil mas repetitivo, classificar:
|
|
46
|
+
- OVERHEAD (reuniões, RH, planning) → não-eliminável; NÃO conta em ≤ 50%
|
|
47
|
+
- GRUNGY WORK (refactor, sec cleanup) → necessário, valor durável → projeto engineering
|
|
48
|
+
- PROJECT WORK (criar novo serviço) → engineering trabalho ≠ toil
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Pattern: template `TOIL-AUDIT.md`
|
|
52
|
+
|
|
53
|
+
Formato canônico que `toil-auditor` (Phase 37) gera:
|
|
54
|
+
|
|
55
|
+
```markdown
|
|
56
|
+
# TOIL-AUDIT — <projeto> — <data>
|
|
57
|
+
|
|
58
|
+
## Métrica agregada
|
|
59
|
+
|
|
60
|
+
- Toil estimado: X.X horas-pessoa/semana (Y% do tempo do time)
|
|
61
|
+
- **Status vs ≤ 50% rule:** [GREEN: < 30%] | [YELLOW: 30-50%] | [RED: > 50%]
|
|
62
|
+
- Top 3 áreas: <lista>
|
|
63
|
+
|
|
64
|
+
## Itens identificados
|
|
65
|
+
|
|
66
|
+
| # | Item | Frequência | Hours/week | Pain (1-5) | Automation effort | Priority |
|
|
67
|
+
|---|------|------------|------------|------------|-------------------|----------|
|
|
68
|
+
| 1 | Reset DB seed manual antes de cada test run | 2×/dia | 1.5 h | 4 | M (3 dias) | P0 |
|
|
69
|
+
| 2 | Rotation de access_token de Edge Function | 1×/semana | 0.5 h | 2 | S (1 dia) | P1 |
|
|
70
|
+
| 3 | Rebuild de índice fts_search após batch import | 1×/mês | 0.5 h | 3 | M (2 dias) | P1 |
|
|
71
|
+
| 4 | Limpeza manual de orphan rows em audit_log | 1×/semana | 0.3 h | 1 | S (1 dia) | P2 |
|
|
72
|
+
|
|
73
|
+
## P0 (automatizar agora)
|
|
74
|
+
|
|
75
|
+
### Item 1: Reset DB seed manual
|
|
76
|
+
|
|
77
|
+
**Por que é toil:** atende 6 critérios canônicos (manual, repetitivo 2×/dia, automatizável via script + pg_cron, tática reativa, sem valor durável, escala com #devs).
|
|
78
|
+
|
|
79
|
+
**Automação proposta:** `make db-reset` que invoca `supabase db reset && pnpm run seed`. Adicionar pre-test hook em CI.
|
|
80
|
+
|
|
81
|
+
**Esforço estimado:** 3 dias (Med — script existe parcialmente, falta seed deterministic).
|
|
82
|
+
|
|
83
|
+
**Owner sugerido:** @dev-tools-team
|
|
84
|
+
|
|
85
|
+
## P1 / P2 (escalonar)
|
|
86
|
+
|
|
87
|
+
...
|
|
88
|
+
|
|
89
|
+
## Não-toil identificado
|
|
90
|
+
|
|
91
|
+
- **Overhead:** sprint planning (2h × semana × 5 pessoas = 10h/semana) — NÃO conta no ≤ 50%
|
|
92
|
+
- **Grungy work:** refactor de `legacy_orders_service` (8h × semana × 1 pessoa = 8h/semana) — projeto, não toil
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Pattern: estágios de automação (níveis Google)
|
|
96
|
+
|
|
97
|
+
| Estágio | Descrição | Exemplo |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| **L0: Manual** | 100% humano | "Cada deploy: SSH no host, copy binary, kill+restart" |
|
|
100
|
+
| **L1: Documented** | Runbook escrito; humano segue passos | "Doc passo-a-passo de deploy em wiki" |
|
|
101
|
+
| **L2: Tooled** | Script executa passos; humano invoca | "`./deploy.sh prod`" |
|
|
102
|
+
| **L3: Self-service** | UI/CLI trigger; humano clica | "GitHub Actions deploy on PR merge" |
|
|
103
|
+
| **L4: Autonomous** | Sem humano; só fail-state intervenção | "Auto-rollback se SLO burn rate > 4 nos primeiros 5 min após deploy" |
|
|
104
|
+
|
|
105
|
+
Meta SRE é mover toda toil de L0/L1 para L3/L4. L2 é meio-passo aceitável quando L3+ requer investimento maior. **L1 (apenas runbook) é toil disfarçado** — runbook é manual com passo extra de "ler doc".
|
|
106
|
+
|
|
107
|
+
### Pattern: identificação de toil via git log + scripts
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# PT-BR: scripts shell em runbooks/ ou docs/runbooks/
|
|
111
|
+
find . -name "*.sh" -path "*runbook*" -o -path "*ops*" | head -20
|
|
112
|
+
|
|
113
|
+
# PT-BR: "manual steps" em README/docs (heurística — frase canônica)
|
|
114
|
+
grep -rn "manually\|por favor\|run this\|every week\|cada semana" --include="*.md" .
|
|
115
|
+
|
|
116
|
+
# PT-BR: tarefas repetitivas via git log — commits de mesmo tipo
|
|
117
|
+
git log --since="3 months ago" --pretty=format:"%s" | sort | uniq -c | sort -rn | head -20
|
|
118
|
+
# Ex: "20× Re-run failed migration in prod" → TOIL candidato
|
|
119
|
+
# Ex: "15× Bump deploy-token" → TOIL candidato
|
|
120
|
+
|
|
121
|
+
# PT-BR: cron jobs já automatizados (saída esperada)
|
|
122
|
+
crontab -l 2>/dev/null
|
|
123
|
+
cat /etc/cron.d/* 2>/dev/null
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Pattern: "toil tax" — prevenir feature nascer com toil
|
|
127
|
+
|
|
128
|
+
```text
|
|
129
|
+
Antes de mergear PR de nova feature, perguntar:
|
|
130
|
+
|
|
131
|
+
1. "Como auto-operar isso em prod?" → instrumentação ODD
|
|
132
|
+
2. "Como auto-monitorar?" → 4 golden signals
|
|
133
|
+
3. "Como auto-recuperar de fail comum?" → retry, circuit breaker
|
|
134
|
+
4. "Como auto-rotacionar credenciais?" → vault + cron rotation
|
|
135
|
+
5. "Como auto-limpar dados históricos?" → retention policy + scheduled cleanup
|
|
136
|
+
6. "Como onboarding de novo cliente?" → self-service signup, não Slack ping
|
|
137
|
+
|
|
138
|
+
Se QUALQUER resposta = "humano fará isso" → toil tax. Bloqueie ou descontar do release budget.
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Anti-patterns
|
|
142
|
+
|
|
143
|
+
### ANTI: confundir overhead com toil
|
|
144
|
+
|
|
145
|
+
```text
|
|
146
|
+
ANTI: contar reuniões, RH, planning, performance review como toil — toda
|
|
147
|
+
atividade não-codificadora vira "toil" no audit.
|
|
148
|
+
|
|
149
|
+
PROBLEMA: métrica inflada (e.g., 60% "toil" falso); ações erradas — cortar
|
|
150
|
+
reunião não diminui toil real; equipe perde tempo em automação
|
|
151
|
+
de overhead (que é não-eliminável por design).
|
|
152
|
+
|
|
153
|
+
CERTO: overhead é categoria separada; ≤ 50% rule conta APENAS toil estrito
|
|
154
|
+
(6 critérios canônicos). Audit lista overhead em seção própria,
|
|
155
|
+
fora do total.
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### ANTI: hero culture (toil mascara via heroísmo)
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
ANTI: engineer fica 2h por dia executando deploys manuais e é "celebrado
|
|
162
|
+
por dedicação" / "salvador" — toil nunca aparece em métrica.
|
|
163
|
+
|
|
164
|
+
PROBLEMA: toil invisível para liderança; investimento em automação adiado
|
|
165
|
+
indefinidamente; engineer pede demissão; sucessor herda toil sem
|
|
166
|
+
context — incidente garantido. Ciclo se repete.
|
|
167
|
+
|
|
168
|
+
CERTO: TOIL-AUDIT trimestral mandatório; quantificar em hours/week por
|
|
169
|
+
pessoa; tornar visível em dashboards de produtividade. Heroísmo
|
|
170
|
+
sustentado = sinal de underinvestment, não de mérito.
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### ANTI: documentar runbook em vez de automatizar
|
|
174
|
+
|
|
175
|
+
```text
|
|
176
|
+
ANTI: "Vamos só escrever um doc detalhado de como fazer isso passo-a-passo"
|
|
177
|
+
— runbook de 30 passos no wiki, sem script.
|
|
178
|
+
|
|
179
|
+
PROBLEMA: L1 (Documented) ainda é toil — humano lê doc, segue passos,
|
|
180
|
+
falha em algum, doc desatualiza em 3 meses; primeira pessoa que
|
|
181
|
+
segue após drift quebra prod; ninguém atualiza doc retroativamente.
|
|
182
|
+
|
|
183
|
+
CERTO: doc como passo intermediário (L1); meta é L3/L4 (autonomous);
|
|
184
|
+
marcar runbook com TODO de automação + owner + due date; sprint
|
|
185
|
+
seguinte transforma em script (L2) ou melhor.
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### ANTI: automatizar parcialmente
|
|
189
|
+
|
|
190
|
+
```text
|
|
191
|
+
ANTI: script faz 3 dos 5 passos; humano completa os outros 2 — "execute
|
|
192
|
+
primeiro ./step1.sh, depois manualmente faça X em prod, depois
|
|
193
|
+
./step3.sh".
|
|
194
|
+
|
|
195
|
+
PROBLEMA: ainda é toil (humano envolvido); contexto-switch entre script e
|
|
196
|
+
humano dobra tempo total; script raramente atualizado por estar
|
|
197
|
+
"incompleto"; degrada para chain frágil que ninguém quer mexer.
|
|
198
|
+
|
|
199
|
+
CERTO: automação completa OU não automatizar — meias-medidas perpetuam.
|
|
200
|
+
Se faltam 2 passos manuais, gastar mais 1 dia para fechar o loop;
|
|
201
|
+
resultado é L3/L4 autônomo, não L1.5 frankenstein.
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### ANTI: ignorar toil de baixa frequência
|
|
205
|
+
|
|
206
|
+
```text
|
|
207
|
+
ANTI: "Só faço isso 1× por trimestre, não vale automatizar" — descartar
|
|
208
|
+
tarefas raras do audit.
|
|
209
|
+
|
|
210
|
+
PROBLEMA: cumulative impact alto (10 tarefas trimestrais × 4 trimestres ×
|
|
211
|
+
30 min = 20h/ano); cada vez que retorna, pessoa esquece passos;
|
|
212
|
+
documentação envelhece entre execuções; DR exercises e migrations
|
|
213
|
+
raras são exatamente onde erro humano custa mais.
|
|
214
|
+
|
|
215
|
+
CERTO: priorizar por (frequency × pain) / effort; baixa frequência +
|
|
216
|
+
alto pain (e.g., DR exercise, schema migration crítica) = ainda
|
|
217
|
+
P1. Frequência baixa ≠ toil baixo — soma de raras é alta.
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Verificação
|
|
221
|
+
|
|
222
|
+
Antes de marcar audit de toil como completo:
|
|
223
|
+
|
|
224
|
+
1. **Aplicado os 6 critérios canônicos** — cada item passou pelo decision tree (manual, repetitivo, automatizável, tático, sem valor durável, escala linear)
|
|
225
|
+
2. **Quantificado em hours/week** — não "muito toil" mas "3.5h/week por pessoa"
|
|
226
|
+
3. **% do tempo do time** computado — comparado contra ≤ 50% rule
|
|
227
|
+
4. **Priorização por (frequency × pain) / effort** — P0/P1/P2 atribuído
|
|
228
|
+
5. **Owner nomeado** para cada item P0
|
|
229
|
+
6. **Overhead identificado separadamente** — não conta para ≤ 50%
|
|
230
|
+
7. **Grungy work identificado separadamente** — projeto engineering, não toil
|
|
231
|
+
8. **Pelo menos 1 item P0 escalonado** com automação proposta + esforço estimado
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Ver também
|
|
236
|
+
|
|
237
|
+
- [`_shared-sre/glossary.md`](../_shared-sre/glossary.md) — termos canônicos toil, overhead, grungy work, automation
|
|
238
|
+
- [`observability-maturity-model`](../observability-maturity-model/SKILL.md) (v1.9) — Capacidade 3 (Complexidade/Tech Debt) consome toil score
|
|
239
|
+
- [`production-readiness-review`](../production-readiness-review/SKILL.md) — PRR axis "Change Management" verifica deploy não é toil
|
|
240
|
+
- [`blameless-postmortems`](../blameless-postmortems/SKILL.md) — postmortems de toil-induced incidents alimentam audit
|
|
241
|
+
- [`sre-risk-management`](../sre-risk-management/SKILL.md) — toil reduz tempo para reduzir risk
|
|
242
|
+
|
|
243
|
+
*Material-fonte: Site Reliability Engineering — Beyer, Jones, Petoff, Murphy (Google/O'Reilly, 2016) — Cap 5: "Eliminating Toil".*
|
|
@@ -26,6 +26,28 @@ LLM carrega esta skill ao definir/avaliar SLOs ou substituir alertas threshold p
|
|
|
26
26
|
- **Owner explícito** — cada SLO tem dono nomeado. Sem owner = sem ação = sem valor.
|
|
27
27
|
- **Substituir alertas threshold gradualmente** — após SLO comprovar valor (1+ incident detectado por SLO antes de threshold), DELETAR threshold antigo.
|
|
28
28
|
|
|
29
|
+
## Risk continuum — SLO target é decisão explícita
|
|
30
|
+
|
|
31
|
+
> Cross-ref canônico: [sre-risk-management](../sre-risk-management/SKILL.md) (cap 3 do livro Google SRE — Embracing Risk).
|
|
32
|
+
|
|
33
|
+
SLO target NÃO é meta arbitrária ("queremos 99.99% porque soa bom"). É uma escolha consciente no **continuum risk × innovation**: cada nove adicional **multiplica custo** mas **divide benefício marginal** percebido pelo cliente.
|
|
34
|
+
|
|
35
|
+
| Target | Tolerância 30d | User-perceptible? | Quando faz sentido |
|
|
36
|
+
|---|---|---|---|
|
|
37
|
+
| 99% | 7.2 h | Sim, notável | Tier free, beta features, internal tools |
|
|
38
|
+
| 99.5% | 3.6 h | Notável em paths críticos | Tier free de produção |
|
|
39
|
+
| 99.9% | 43.2 min | Aceitável para maior parte de UX | Tier paid default |
|
|
40
|
+
| 99.95% | 21.6 min | Quase imperceptível | Tier enterprise / mission-critical |
|
|
41
|
+
| 99.99% | 4.3 min | Imperceptível em smartphone (~99% no canal do user) | Apenas se justificado por user perception (raro) |
|
|
42
|
+
|
|
43
|
+
**Sabedoria 99.99%** — cliente final acessa via smartphone (~99% disponibilidade) com ISP residencial (~99%). Serviço 99.99% **não é distinguível** de 99.999% nesse contexto: ambos parecem "sempre funcionando". Esforço além de 99.95% para serviço user-facing é tipicamente desperdício.
|
|
44
|
+
|
|
45
|
+
**Error budget é o instrumento contábil dessa decisão.** Para SLO 99.9% em 30d com 10M eventos: budget = `0.001 × 10M = 10k bad events`. Esse 10k é orçamento explícito para gastar em deploys arriscados, experimentos, refactors. Quando esgota, releases freezam até regenerar — não como punição, mas como **balanço explícito risk × innovation**.
|
|
46
|
+
|
|
47
|
+
**Diferentes tiers, diferentes targets** — `customer.tier='enterprise'` pode justificar 99.95%; `tier='free'` pode operar em 99.5%. Tratar todos como tier-1 desperdiça budget; tratar todos como tier-3 frustra clientes pagantes. A skill `sre-risk-management` documenta o framework completo de decisão.
|
|
48
|
+
|
|
49
|
+
> Em resumo: a regra `Target ≤ 99.95%` desta skill (acima) é **consequência** do risk continuum, não restrição arbitrária. Para 99.99%+ trate como métrica informativa (dashboard), NÃO como SLO acionável (alerts).
|
|
50
|
+
|
|
29
51
|
## Patterns canônicos
|
|
30
52
|
|
|
31
53
|
### Pattern: SLI event-based vs time-based
|