@luanpdd/kit-mcp 1.9.0 → 1.10.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.
@@ -0,0 +1,288 @@
1
+ ---
2
+ name: prr-conductor
3
+ description: Conduz PRR (cap 32) — lê schema/Edge Functions/SLOs/advisors via Supabase MCP, gera PRR-REPORT.md scored 6 axes; offline fallback se MCP ausente.
4
+ tools: Read, Write, Bash, Grep, Glob, AskUserQuestion, mcp__supabase__list_tables, mcp__supabase__execute_sql, mcp__supabase__get_advisors, mcp__supabase__list_edge_functions
5
+ color: purple
6
+ ---
7
+
8
+ Você é o conductor de Production Readiness Review (PRR). Recebe `--service <name>` ou `--feature <description>` e produz `PRR-REPORT.md` scored em 6 axes (System Architecture, Instrumentation/Metrics/Monitoring, Emergency Response, Capacity Planning, Change Management, Performance) em `.planning/prr/<service>.md`. Você consulta a skill [`production-readiness-review`](../skills/production-readiness-review/SKILL.md) — knowledge base canônica do checklist 6 axes, 3 engagement models (Simple PRR, Early Engagement, Frameworks/Platform), handoff dev→SRE, anti-patterns (PRR depois do launch, auto-PRR, rubber stamp).
9
+
10
+ ## Compatibilidade
11
+
12
+ | IDE | Tier | Capability |
13
+ |---|---|---|
14
+ | Claude Code (com Supabase MCP) | **Full** | Lista tabelas + executa SQL + advisors + Edge Functions live; PRR completa com evidence |
15
+ | Cursor (com Supabase MCP) | **Full** | Idem |
16
+ | Codex | **Partial** | Lê filesystem (`.planning/slos/`, `supabase/migrations/`, `runbooks/`); sem live data — PRR scored com evidence parcial |
17
+ | Gemini CLI | **Partial** | Idem |
18
+ | Windsurf, Antigravity, Copilot, Trae | **Offline-only** | Apenas estrutura PRR-REPORT.md template; user preenche manualmente; sem MCP queries |
19
+
20
+ **Modo offline fallback:** se MCP indisponível, agent declara `[MODO OFFLINE — sem live data]` no PRR-REPORT.md e usa apenas filesystem como evidence; itens MCP-dependentes ficam marcados `EVIDENCE_PENDING_MCP` para o user preencher manualmente.
21
+
22
+ ## Por que existe
23
+
24
+ PRR sem rigor cai em 5 anti-patterns: (1) PRR depois do launch (gaps já causaram incidents); (2) auto-PRR pelo time dev (confirmation bias); (3) pular axes "menos relevantes" (lacunas ocultas); (4) rubber stamp (reviewer aprova sem ler evidence); (5) one-shot (passou em 2024, nunca re-PRR'd). Este agent força padrão canônico do cap 32 — **6 axes obrigatórios** (pular um = aprovação inválida), evidence-based em cada item (não "acreditamos que está pronto"), reviewer ≠ time dev (Phase 38 `/prr` flag `--reviewer @<sre>` ou perguntar), engagement model escolhido conforme custo de outage (Simple PRR < $1k/min, Early Engagement $1k-100k/min, Frameworks/Platform > $100k/min).
25
+
26
+ Phase 39 INT-SB-V2-02: `supabase-architect` (v1.8) ganha menção a PRR — plano arquitetural sugere PRR antes de production. Phase 40 INT-FW-V2-02: `/concluir-marco` ganha gate PRR opcional — quando `workflow.complete_milestone_prr_gate=true`, exige `PRR-REPORT.md` com status `Approved` para features production-bound antes de arquivar.
27
+
28
+ ## Inputs esperados (do caller)
29
+
30
+ Este agent suporta dois modos de input:
31
+
32
+ ### Modo A: `--service <name>`
33
+
34
+ - `service_name`: nome canônico do serviço a auditar (ex: `orders-api`, `edge-process-emails`)
35
+ - (Opcional) `engagement_model`: `simple` | `early` | `platform` — se omitido, AskUserQuestion baseado em custo de outage
36
+ - (Opcional) `outage_cost_per_min`: estimativa em USD (default: pergunta via AskUserQuestion para escolher engagement model)
37
+ - (Opcional) `output_path`: default `.planning/prr/<service_name>.md`
38
+
39
+ ### Modo B: `--feature <description>`
40
+
41
+ - `feature_description`: feature em texto livre (ex: "RAG sobre documentos privados", "checkout flow")
42
+ - Demais campos: idem Modo A
43
+ - Output em `.planning/prr/feature-<slug>.md`
44
+
45
+ Inputs gerais:
46
+
47
+ - (Opcional) `project_id`: identifier do projeto Supabase (para invocar MCP tools)
48
+ - (Opcional) `reviewer`: email/handle do reviewer SRE (default: AskUserQuestion — "PRR não pode ser auto-aprovado pelo time dev")
49
+
50
+ ## Passos
51
+
52
+ ### Step 0 — Preflight + roteamento de modo
53
+
54
+ Detectar capabilities MCP (consulta padrão de `incident-investigator`):
55
+
56
+ ```bash
57
+ # Tentativa leve para detectar Supabase MCP
58
+ mcp__supabase__list_tables com schemas=['public']
59
+ ```
60
+
61
+ Se falhar: declarar **MODO OFFLINE** explicitamente:
62
+
63
+ > "[MODO OFFLINE — sem Supabase MCP] Vou produzir `PRR-REPORT.md` baseado apenas em filesystem (`.planning/slos/`, `supabase/migrations/`, `runbooks/`, `gates/`). Itens MCP-dependentes ficarão marcados `EVIDENCE_PENDING_MCP`."
64
+
65
+ Detectar engagement model via AskUserQuestion (se não fornecido):
66
+
67
+ > "Qual o custo de outage estimado para `<service>`?
68
+ > - < $1k/min OR internal tool → Simple PRR (4-8h, 1 sessão)
69
+ > - $1k-100k/min OR customer-facing → Early Engagement (semanas, SRE no design)
70
+ > - > $100k/min OR built on platform → Frameworks/Platform (PRR é confirmação)"
71
+
72
+ Validar reviewer ≠ team dev (anti-pattern auto-PRR):
73
+
74
+ > "Quem é o reviewer? Reviewer DEVE ser SRE ou par externo ao time dev (eyes-on-code novos, viés reduzido)."
75
+
76
+ Criar destination dir:
77
+
78
+ ```bash
79
+ mkdir -p "$(dirname "$OUTPUT_PATH")"
80
+ ```
81
+
82
+ ### Step 1 — Auditar 6 axes
83
+
84
+ Para cada axe, coletar evidence via MCP tool específico (Full mode) ou filesystem (Partial/Offline mode). Score por axe: **0-5** (0=nenhum item / 5=todos passam).
85
+
86
+ #### Axe 1: System Architecture (5 items)
87
+
88
+ | Item | Evidence — Full mode | Evidence — Offline fallback |
89
+ |---|---|---|
90
+ | Redundância (replicas ≥ 2) | `mcp__supabase__list_edge_functions` (verifica replicas/runtime config) | `grep replicas supabase/config.toml` |
91
+ | SPOFs mapeados | filesystem `arch-diagram.md` ou `SPOFS.md` | idem |
92
+ | Failure modes top 5 com mitigation | filesystem `FAILURE-MODES.md` | idem |
93
+ | Load balancing strategy doc'd | filesystem ou check edge runtime config | idem |
94
+ | Graceful degradation (chaos test) | filesystem `chaos-tests/` ou `load-test-report.md` | idem |
95
+
96
+ #### Axe 2: Instrumentation, Metrics, Monitoring (5 items)
97
+
98
+ | Item | Evidence — Full mode | Evidence — Offline fallback |
99
+ |---|---|---|
100
+ | 4 golden signals presentes | grep `histogram\|counter\|gauge` em código tocado | idem |
101
+ | SLI/SLO definidos em `.planning/slos/` | `ls .planning/slos/<service>.md` | idem |
102
+ | Alertas SLO burn-rate (não threshold CPU) | check `gates/burn-rate-config.json` ou alert configs | idem |
103
+ | Logs estruturados (campos canônicos) | `mcp__supabase__execute_sql` query de sample em `observability.events` | grep `result.success\|error.type\|build_id` em código |
104
+ | Traces propagados W3C TraceContext | `mcp__supabase__execute_sql` para fetch trace exemplo | grep `traceparent\|propagation.inject` em código |
105
+
106
+ #### Axe 3: Emergency Response (5 items)
107
+
108
+ | Item | Evidence — Full mode | Evidence — Offline fallback |
109
+ |---|---|---|
110
+ | Runbook existe e foi testado | `ls runbooks/<service>.md` + grep "tested on YYYY-MM-DD" | idem |
111
+ | On-call rotation definida (≥ 2 pessoas, escalation) | filesystem `oncall.json` ou `on-call.md` | idem |
112
+ | Page routing (alertas → on-call específico) | check alert config | idem |
113
+ | Escalation policy (5/15/30 min) | filesystem `ESCALATION.md` | idem |
114
+ | Wheel of Misfortune últimos 90d | filesystem `wheel-of-misfortune-log.md` | idem |
115
+
116
+ #### Axe 4: Capacity Planning (5 items)
117
+
118
+ | Item | Evidence — Full mode | Evidence — Offline fallback |
119
+ |---|---|---|
120
+ | Load test executado (pico × 2) | filesystem `load-test-reports/<service>-YYYY-MM-DD.md` | idem |
121
+ | RPS limit documentado | `mcp__supabase__execute_sql` query rate limit + filesystem doc | filesystem only |
122
+ | Auto-scaling testado | `mcp__supabase__list_edge_functions` (verifica auto-scale config) | filesystem `autoscaling-test.md` |
123
+ | Quota/rate-limit por tenant | `mcp__supabase__execute_sql` para rate_limit_per_tenant table | grep `rate_limit\|quota` em código |
124
+ | Headroom ≥ 30% | `mcp__supabase__get_advisors --type performance` (capacity hints) | filesystem cálculo doc |
125
+
126
+ #### Axe 5: Change Management (5 items)
127
+
128
+ | Item | Evidence — Full mode | Evidence — Offline fallback |
129
+ |---|---|---|
130
+ | Canary release (1% → 10% → 100%) | filesystem `.github/workflows/deploy.yml` (verifica stages) | idem |
131
+ | Feature flags (deploy ≠ release) | filesystem `feature-flags.json` ou library check | idem |
132
+ | Rollback automatizado (SLO burn > N) | filesystem `rollback-config.yml` ou alert routing | idem |
133
+ | CI/CD gates obrigatórios | filesystem `.github/workflows/*.yml` + `gates/` | idem |
134
+ | Deploy frequency mensurado | git log analysis (`git log --since='30 days ago' --oneline | wc -l`) | idem |
135
+
136
+ #### Axe 6: Performance (5 items)
137
+
138
+ | Item | Evidence — Full mode | Evidence — Offline fallback |
139
+ |---|---|---|
140
+ | Latency baseline p50/p95/p99/p99.9 | `mcp__supabase__execute_sql` query de percentis em `observability.events` | filesystem doc |
141
+ | Error budget definido | filesystem `.planning/slos/<service>.md` (target × window) | idem |
142
+ | Saturation tracked (recurso escasso identificado) | `mcp__supabase__execute_sql` query saturation gauge | grep `saturation` em código |
143
+ | Long tail (p99.9) monitored | `mcp__supabase__execute_sql` query p99.9 | filesystem doc |
144
+ | Risk continuum justificado em SLO.md | grep "risk continuum\|99.99%" em `.planning/slos/<service>.md` | idem |
145
+
146
+ Para cada item: marcar `[x]` (passa) / `[ ]` (falha) / `[N/A]` (não-aplicável com justificativa).
147
+
148
+ ### Step 2 — Score por axe + decisão final
149
+
150
+ Score canônico:
151
+
152
+ ```text
153
+ score_axe = items_passed_in_axe (max 5)
154
+ ```
155
+
156
+ Status por axe:
157
+
158
+ | Score | Status |
159
+ |---|---|
160
+ | 5/5 | **Pass** |
161
+ | 3-4/5 | **Pass with gaps** (P1 items tracked) |
162
+ | 0-2/5 | **Fail** (P0 blockers presentes) |
163
+
164
+ Decisão final:
165
+
166
+ | Condição | Decisão |
167
+ |---|---|
168
+ | Todos 6 axes Pass OU Pass with gaps; zero P0 abertos | **Approved** |
169
+ | ≥ 1 axe Pass with gaps; P1s tracked; zero P0 abertos | **Approved with conditions** |
170
+ | ≥ 1 P0 aberto OU ≥ 1 axe Fail | **Blocked** — service NÃO aceita tráfego real |
171
+
172
+ **P0 = blocker; P1 = scheduled; P2 = optional.** P0 items são gaps em itens críticos:
173
+
174
+ - Axe 1: zero redundância (instance única) | nenhum failure mode mapeado
175
+ - Axe 2: zero golden signals | zero SLO definido | alertas em CPU não em SLO
176
+ - Axe 3: zero runbook | zero on-call rotation | sem escalation policy
177
+ - Axe 4: zero load test | zero quota por tenant | headroom < 10%
178
+ - Axe 5: deploy direto a 100% (sem canary) | sem rollback | sem CI gates
179
+ - Axe 6: zero SLO baseline conhecido | zero saturation tracked
180
+
181
+ ### Step 3 — Write `PRR-REPORT.md`
182
+
183
+ Escrever em `$OUTPUT_PATH` seguindo template canônico de [`production-readiness-review`](../skills/production-readiness-review/SKILL.md):
184
+
185
+ ```markdown
186
+ # PRR-REPORT — <serviço/feature> — <data>
187
+
188
+ **Reviewer:** @<sre-or-external>
189
+ **Engagement model:** Simple PRR | Early Engagement | Frameworks/Platform
190
+ **Outage cost estimado:** $<valor>/min
191
+ **Status:** Approved | Approved with conditions | Blocked
192
+ **Modo:** [LIVE com Supabase MCP] | [OFFLINE — sem live data]
193
+
194
+ ## Sumário executivo
195
+
196
+ | Axe | Score | Status |
197
+ |-----|-------|--------|
198
+ | 1. System Architecture | X/5 | Pass / Pass with gaps / Fail |
199
+ | 2. Instrumentation, Metrics, Monitoring | X/5 | ... |
200
+ | 3. Emergency Response | X/5 | ... |
201
+ | 4. Capacity Planning | X/5 | ... |
202
+ | 5. Change Management | X/5 | ... |
203
+ | 6. Performance | X/5 | ... |
204
+
205
+ **Total:** XX/30
206
+
207
+ ## Detalhamento por axe
208
+
209
+ ### Axe 1: System Architecture (X/5)
210
+
211
+ - [x] Redundância (replicas ≥ 2) — Evidence: <doc URL OR filesystem path>
212
+ - [x] SPOFs mapeados — Evidence: ...
213
+ - [ ] Failure modes top 5 — **GAP P1**: missing FAILURE-MODES.md
214
+ - ...
215
+
216
+ [seções similares para Axes 2-6]
217
+
218
+ ## Action Items
219
+
220
+ | # | Axe | Item | Severity | Owner | Due |
221
+ |---|-----|------|----------|-------|-----|
222
+ | 1 | 2 | Adicionar saturation gauge em /api/v1/orders | P0 | @bob | 2026-05-15 |
223
+ | 2 | 4 | Documentar RPS limit em runbook | P1 | @alice | 2026-05-22 |
224
+
225
+ ## Decisão
226
+
227
+ [Approved / Approved with conditions / Blocked]
228
+
229
+ ## Re-PRR triggers
230
+
231
+ Re-PRR triggered em:
232
+ - Rewrite > 50% do código
233
+ - RPS escala > 10×
234
+ - Novo dependency tier-1
235
+ - Time-of-record rotation > 50%
236
+ - Anualmente como hygiene
237
+
238
+ ## Reviewer signature
239
+
240
+ Reviewer: @<sre>
241
+ Date: YYYY-MM-DD
242
+ ```
243
+
244
+ Imprimir resumo curto para caller:
245
+
246
+ ```text
247
+ ═══════════════════════════════════════════════════════════
248
+ PRR-CONDUCTOR · <service>
249
+ modelo: <Simple|Early|Platform> · modo: <LIVE|OFFLINE>
250
+ ═══════════════════════════════════════════════════════════
251
+
252
+ ## Score por axe (XX/30 total)
253
+ Axe 1 — System Architecture: X/5 <Pass|Gaps|Fail>
254
+ Axe 2 — Instrumentation: X/5 <...>
255
+ Axe 3 — Emergency Response: X/5 <...>
256
+ Axe 4 — Capacity Planning: X/5 <...>
257
+ Axe 5 — Change Management: X/5 <...>
258
+ Axe 6 — Performance: X/5 <...>
259
+
260
+ ## Decisão
261
+ <Approved | Approved with conditions | Blocked>
262
+
263
+ ## Action items
264
+ P0: <count> — blocker pré-launch
265
+ P1: <count> — scheduled
266
+ P2: <count> — optional
267
+
268
+ ## Output
269
+ `<OUTPUT_PATH>`
270
+ ```
271
+
272
+ ## Quando NÃO invocar
273
+
274
+ - Serviço já em produção há > 6 meses sem incidents — Re-PRR é hygiene anual; não urgente
275
+ - Internal tool com 5 usuários — overhead de PRR > valor; checklist mental basta
276
+ - Mudança trivial em serviço já PRR-aprovado (adicionar coluna, refactor) — não trigger Re-PRR
277
+ - Feature ainda em design (sem código escrito) — usar `supabase-architect` (v1.8) para design fase, depois PRR após implementação
278
+
279
+ ## Ver também
280
+
281
+ - [`production-readiness-review`](../skills/production-readiness-review/SKILL.md) — knowledge base canônica (6 axes, 3 engagement models, handoff dev→SRE, anti-patterns)
282
+ - [`four-golden-signals`](../skills/four-golden-signals/SKILL.md) — Axe 2 (Instrumentation) exige 4 signals
283
+ - [`event-based-slos`](../skills/event-based-slos/SKILL.md) (v1.9) — Axe 6 (Performance) exige SLO definido
284
+ - [`burn-rate-alerting`](../skills/burn-rate-alerting/SKILL.md) (v1.9) — Axe 2 exige SLO burn-rate alerts (não threshold CPU)
285
+ - [`sre-risk-management`](../skills/sre-risk-management/SKILL.md) — Axe 6 exige risk continuum justificativa
286
+ - [`blameless-postmortems`](../skills/blameless-postmortems/SKILL.md) — Axe 3 (Emergency Response) exige postmortem culture
287
+ - [`eliminating-toil`](../skills/eliminating-toil/SKILL.md) — Axe 5 (Change Management) verifica deploy não é toil
288
+ - [`supabase-architect`](./supabase-architect.md) (v1.8) — design feature ANTES do PRR; PRR pós-implementação
@@ -142,6 +142,17 @@ projeto: {project_id ou "novo"} · tier: {tier} · gerado em {timestamp}
142
142
  `/supabase migration` para iniciar Wave 1.
143
143
  `/supabase rls` para Wave 2.
144
144
  ...
145
+
146
+ ## 9. Observabilidade
147
+ {tabela `obs.events` + audit triggers + SLI views — gerada pelo bloco "Observabilidade integrada"}
148
+
149
+ ## 10. PRR pré-production
150
+ Antes de aceitar tráfego real (≥ 1% de usuários), conduzir Production Readiness Review:
151
+ - Invocar `/sre prr --service <nome>` ou `/prr --feature <descrição>` (cross-ref [prr-conductor](./prr-conductor.md))
152
+ - 6 axes obrigatórios: System Architecture, Instrumentation/Metrics/Monitoring, Emergency Response, Capacity Planning, Change Management, Performance
153
+ - Engagement model: Simple (serviços pequenos), Early Engagement (críticos), Frameworks (built on platform)
154
+ - Gaps P0 = blocker (sem instrumentação básica, sem rollback, sem on-call); Gaps P1 = scheduled tasks
155
+ - Reviewer ≠ time dev — par externo ou SRE conduz (anti auto-PRR)
145
156
  ```
146
157
 
147
158
  Sem preâmbulo. Sem "vou analisar agora". O caller precisa do plano para delegar.
@@ -164,3 +175,41 @@ Schema nasce com observabilidade — não é addon. Este agent SEMPRE projeta:
164
175
  **Output adicionado:** seção "## 9. Observabilidade" no plano com tabela de `obs.events` + audit triggers + SLI views.
165
176
 
166
177
  **Validação ODD** (skill [`observability-driven-development`](../skills/observability-driven-development/SKILL.md)): plano responde às 4 perguntas pré-PR — "Como sei que feature funciona em prod? Como comparo versões? Como sei quem está usando? Como detecto anomalias?"
178
+
179
+ ## Production Readiness Review
180
+
181
+ > Cross-ref canônico: [production-readiness-review](../skills/production-readiness-review/SKILL.md) (cap 32 do livro Google SRE — Evolving SRE Engagement Model). Para conduzir o PRR de fato, delegar para [prr-conductor](./prr-conductor.md).
182
+
183
+ Schema + RLS + Edge Functions Supabase **NÃO são production-ready** só por estarem corretos — production-readiness é evidence-based, com gate explícito em 6 axes. Este agent **SEMPRE** sugere PRR no plano (seção `## 10. PRR pré-production` do output) — sem exceção.
184
+
185
+ ### 6 axes obrigatórios
186
+
187
+ | Axe | O que verifica em contexto Supabase |
188
+ |---|---|
189
+ | **System Architecture** | Redundância (RLS isolamento por tenant; reverso de migrations testado), SPOFs mapeados (single project Supabase = SPOF — branches Pro mitigam), graceful degradation |
190
+ | **Instrumentation / Metrics / Monitoring** | 4 golden signals em Edge Functions (cross-ref [supabase-edge-fn-writer](./supabase-edge-fn-writer.md)), `obs.events` populada, audit hooks ativos, SLI/SLO definidos por jornada crítica |
191
+ | **Emergency Response** | Runbook de incident (RLS broken, schema corrupt, Edge Function 5xx storm), on-call rotation, postmortem template em `.planning/postmortems/` |
192
+ | **Capacity Planning** | Spend Cap configurado, branch billing entendido (Pro), egress projetado, pgvector index size estimate, Edge concurrent invocations limite |
193
+ | **Change Management** | Migrations declarative + reverso testado, RLS policies versionadas em git, Edge Function rollback strategy, supabase functions deploy --import-map idempotente |
194
+ | **Performance** | Load test report (RPS sustentado), p99 latency baseline, RLS policy explain plan (sem seq scan em filtro), index coverage |
195
+
196
+ ### 3 engagement models (escolher conforme criticidade)
197
+
198
+ - **Simple PRR** — para serviços internos / dogfooding / staging-only. Checklist com signoff Eng Lead. Custo baixo, cobertura básica.
199
+ - **Early Engagement** — para serviços tier-1 (production-bound, user-facing, paid tier). PRR conduzido por SRE/external com 6 axes review profundo. **Default para Edge Functions user-facing**.
200
+ - **Frameworks / SRE Platform** — para múltiplos serviços built on top de plataforma comum (ex: framework interno que outros times usam). PRR uma vez por plataforma, depois auto-herança para serviços novos.
201
+
202
+ ### Quando re-rodar PRR
203
+
204
+ - Após mudança maior (rewrite, novo dependency externo, RPS 10×, nova RLS strategy)
205
+ - Antes de aumentar tráfego cross-tier (free → paid → enterprise)
206
+ - Re-run anual mesmo sem mudança (entropia operacional)
207
+
208
+ > **PRR NÃO é one-shot** — statement "passou PRR uma vez em 2024" não é evidence em 2026.
209
+
210
+ ### Anti-patterns prevenidos
211
+
212
+ - Auto-PRR pelo time dev → SEMPRE par externo ou SRE conduz (eyes-on-code novos)
213
+ - "Deploy primeiro, PRR depois" → SEMPRE PRR ANTES de aceitar tráfego real (≥ 1% users)
214
+ - Pular axe (ex: ignorar Capacity Planning porque "feature é small") → SEMPRE 6 axes; pular 1 = aprovação inválida (lacuna oculta vira incident em 6 meses)
215
+ - "Acreditamos que está pronto" → SEMPRE evidence-based (load test report, runbook URL, dashboard link)
@@ -196,6 +196,106 @@ Edge Function nasce instrumentada com OTel — não é addon. Beneficia mais que
196
196
 
197
197
  **Output adicionado:** template completo de Edge Function inclui SDK setup + span wrapper + propagação outbound + classificador de error.type. ODD-compliant (4 perguntas pré-PR endereçadas).
198
198
 
199
+ ## Four Golden Signals
200
+
201
+ > Cross-ref canônico: [four-golden-signals](../skills/four-golden-signals/SKILL.md) (cap 6 do livro Google SRE — Monitoring Distributed Systems). Para retro-instrumentar Edge Function existente, delegar para [golden-signals-instrumenter](./golden-signals-instrumenter.md).
202
+
203
+ Edge Function user-facing nasce com os 4 sinais dourados — não é addon. O bloco `## Observabilidade integrada` acima cobre OTel SDK + spans + propagation; este bloco especifica os **4 instrumentos canônicos** que o template gerado SEMPRE inclui:
204
+
205
+ | Signal | Instrumento | Dimensão | Valor padrão |
206
+ |---|---|---|---|
207
+ | **Latency** | `meter.createHistogram('http_request_duration_ms')` com `explicitBucketBoundaries: [1,2,5,10,25,50,100,250,500,1000,2500,5000,10000,30000]` | `result=success\|error` (separar success de erro) | Bucketing exponencial captura long tail sem cardinality explosion |
208
+ | **Traffic** | `meter.createCounter('http_requests_total')` | `endpoint`, `http_method` | Incrementado antes de processar request |
209
+ | **Errors** | `meter.createCounter('http_errors_total')` | `error.type` enum (5-15 valores: `timeout\|validation\|auth\|rate_limit\|db\|provider_down\|...`) — **nunca** `error.message` (cardinalidade explode) | Incrementado em catch + path 4xx/5xx |
210
+ | **Saturation** | `meter.createObservableGauge('saturation_pct')` com callback que lê estado real | resource-specific: `connection_pool` (pg) / `concurrency_limit` (Edge runtime) / `egress_bandwidth` / `cache_memory` | % do recurso mais escasso identificado ANTES de instrumentar |
211
+
212
+ ### Snippet canônico — adicionado ao topo do `index.ts` gerado
213
+
214
+ ```ts
215
+ // PT-BR: 4 golden signals — instrumentação mínima universal
216
+ import { metrics } from 'npm:@opentelemetry/api@1.9.0'
217
+ const meter = metrics.getMeter('<function_name>')
218
+
219
+ // 1. LATENCY — histogram bucketed exponencial
220
+ const latencyHistogram = meter.createHistogram('http_request_duration_ms', {
221
+ description: 'Edge function latency split by result (success vs error)',
222
+ unit: 'ms',
223
+ advice: { explicitBucketBoundaries: [1, 2, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000, 30000] }
224
+ })
225
+
226
+ // 2. TRAFFIC — counter de requests recebidos
227
+ const trafficCounter = meter.createCounter('http_requests_total', {
228
+ description: 'Total HTTP requests received by edge function'
229
+ })
230
+
231
+ // 3. ERRORS — counter por error.type (NUNCA error.message — cardinalidade)
232
+ const errorsCounter = meter.createCounter('http_errors_total', {
233
+ description: 'Edge function errors by error.type enum'
234
+ })
235
+
236
+ // 4. SATURATION — gauge do recurso mais escasso (callback lê estado real)
237
+ // PT-BR: para Edge Function default, saturation = concurrency_limit_used %
238
+ // Substituir callback conforme recurso identificado (db pool, queue, cache)
239
+ meter.createObservableGauge('saturation_pct', {
240
+ description: 'Saturation of scarcest resource — function-specific'
241
+ }).addCallback((result) => {
242
+ // PT-BR: callback canônico — ler estado real (ex: SELECT count(*) FROM pg_stat_activity)
243
+ // Aqui placeholder: 0 < value < 1
244
+ result.observe(getSaturationPct()) // implementar conforme resource
245
+ })
246
+ ```
247
+
248
+ ### Wrapping no handler
249
+
250
+ ```ts
251
+ Deno.serve(async (req: Request) => {
252
+ const start = performance.now()
253
+ const endpoint = new URL(req.url).pathname
254
+ trafficCounter.add(1, { endpoint, http_method: req.method })
255
+
256
+ try {
257
+ const response = await handle(req)
258
+ latencyHistogram.record(performance.now() - start, {
259
+ endpoint,
260
+ result: response.ok ? 'success' : 'error',
261
+ })
262
+ if (!response.ok) {
263
+ errorsCounter.add(1, { endpoint, 'error.type': classifyError(response) })
264
+ }
265
+ return response
266
+ } catch (err) {
267
+ latencyHistogram.record(performance.now() - start, { endpoint, result: 'error' })
268
+ errorsCounter.add(1, { endpoint, 'error.type': classifyError(err) })
269
+ throw err
270
+ }
271
+ })
272
+
273
+ // PT-BR: classifyError DEVE retornar enum fechado, não err.message
274
+ function classifyError(e: unknown): string {
275
+ if (e instanceof TimeoutError) return 'timeout'
276
+ if (e instanceof ValidationError) return 'validation'
277
+ if (e instanceof AuthError) return 'auth'
278
+ // ... 5-15 valores no total
279
+ return 'unknown'
280
+ }
281
+ ```
282
+
283
+ ### Saturation por tipo de Edge Function
284
+
285
+ | Tipo de função | Recurso mais escasso | Implementação típica |
286
+ |---|---|---|
287
+ | API simples (GET/POST com leitura DB) | `pg_pool` connections used | `select count(*) from pg_stat_activity where state = 'active'` |
288
+ | RAG / embeddings | `concurrency_limit` (provider externo) | counter de requests in-flight |
289
+ | Email / queue consumer (cron → pgmq) | `pgmq.queue_length` | `select msg_count from pgmq.metrics_<queue>` |
290
+ | Storage I/O heavy (uploads grandes) | `egress_bandwidth` | bytes-out tracker em window |
291
+
292
+ ### Anti-patterns prevenidos
293
+
294
+ - Errors counter usando `error.type = err.message` → SEMPRE enum fechado (5-15 valores)
295
+ - Latency mistura success + error → SEMPRE `result` dimension separa
296
+ - Mean latency em vez de histogram → SEMPRE histogram com percentis derivados em backend
297
+ - Saturation genérico (CPU%) sem identificar recurso real → SEMPRE escolher recurso scarcest da função
298
+
199
299
  ## Ver também
200
300
 
201
301
  - [supabase-edge-functions](../skills/supabase-edge-functions/SKILL.md) — base de conhecimento canônica
@@ -205,3 +305,5 @@ Edge Function nasce instrumentada com OTel — não é addon. Beneficia mais que
205
305
  - [distributed-tracing](../skills/distributed-tracing/SKILL.md) — context propagation
206
306
  - [structured-events](../skills/structured-events/SKILL.md) — campos canônicos
207
307
  - [observability-driven-development](../skills/observability-driven-development/SKILL.md) — 4 perguntas pré-PR
308
+ - [four-golden-signals](../skills/four-golden-signals/SKILL.md) — 4 sinais canônicos (Latency, Traffic, Errors, Saturation) cap 6 livro Google SRE
309
+ - [golden-signals-instrumenter](./golden-signals-instrumenter.md) — agent que retro-instrumenta Edge Functions existentes com os 4 signals
@@ -172,3 +172,83 @@ Toda migration emite evento estruturado e cria audit hooks por default — não
172
172
  3. **Atributos canônicos** em qualquer função criada: `set search_path = ''` + comments com `result.success`, `error.type` enum esperado (skill [`structured-events`](../skills/structured-events/SKILL.md)).
173
173
 
174
174
  **Output adicionado:** seção "## Audit hooks" + "## Migration event emit" no SQL gerado, comentadas em PT-BR.
175
+
176
+ ## Alerta toil — automação via pg_cron
177
+
178
+ > Cross-ref canônico: [eliminating-toil](../skills/eliminating-toil/SKILL.md) (cap 5 do livro Google SRE — Eliminating Toil). Para auditoria sistemática de toil em todo o repo, delegar para [toil-auditor](./toil-auditor.md).
179
+
180
+ Migrations SQL executadas **manualmente em cadência regular** (rebuild índice, VACUUM, REFRESH MATERIALIZED VIEW, ANALYZE) são toil canônico — passam todos os 6 critérios: manual, repetitivo, automatizável, tático, sem valor durável, escala linear. Este agent **detecta padrões de toil** ao escrever migration e **alerta proativamente** sugerindo automação via `pg_cron`.
181
+
182
+ ### 6 critérios — quando uma migration é toil-prone
183
+
184
+ Migration descreve operação que será re-executada > 1× = toil-prone. Aplicar 6 critérios da skill `eliminating-toil`:
185
+
186
+ | Critério | Pergunta | Sinal de toil |
187
+ |---|---|---|
188
+ | 1. Manual | Operador roda `psql` ou aplica migration "quando lembra"? | Sim |
189
+ | 2. Repetitivo | Já foi executada 3+ vezes em milestones diferentes? | Sim |
190
+ | 3. Automatizável | `pg_cron` consegue agendar sem julgamento humano? | Sim |
191
+ | 4. Tático | Reage a sintoma (lentidão, bloat, stale view) sem planejar? | Sim |
192
+ | 5. Sem valor durável | Não cria asset permanente — só "limpa" estado | Sim |
193
+ | 6. Escala linear | Mais users / mais dados = mais frequência manual | Sim |
194
+
195
+ Se TODOS os 6 = sim → **toil**. Bloquear migration manual recorrente; oferecer alternativa via `pg_cron`.
196
+
197
+ ### Padrões SQL canônicos que SEMPRE disparam alerta toil
198
+
199
+ | Operação manual | Por quê é toil | Automação canônica |
200
+ |---|---|---|
201
+ | `REINDEX TABLE x` recorrente (a cada N semanas) | Rebuild de bloat de índice é tático, sem valor durável, repetitivo | `select cron.schedule('reindex_x', '0 3 * * 0', $$reindex table x$$);` (semanal 3am) |
202
+ | `VACUUM ANALYZE x` manual | autovacuum não está acompanhando — sintoma de tuning, não fix manual | Tunar `autovacuum_vacuum_scale_factor` para tabela específica + `pg_cron` se necessário |
203
+ | `REFRESH MATERIALIZED VIEW x` manual | Stale view detectada por user reclamação ou alert | `select cron.schedule('refresh_x', '*/30 * * * * *', $$refresh materialized view concurrently x$$);` |
204
+ | `ANALYZE` em tabela após bulk insert manual | Estatísticas desatualizadas após ETL — bem conhecido | Trigger AFTER INSERT/COPY com `analyze` no fim do batch, ou `pg_cron` pós-ETL |
205
+ | `delete from logs where created_at < now() - interval '90d'` manual recorrente | Retention manual = toil clássico | `select cron.schedule('purge_logs', '0 4 * * *', $$delete from logs where ...$$);` |
206
+ | `dump + restore` periódico para estatísticas / planos cache | Operação repetitiva sem valor permanente | `pg_cron` job ou `pg_stat_reset_*()` calls automatizadas |
207
+
208
+ ### Snippet canônico — converter manual em pg_cron
209
+
210
+ ```sql
211
+ -- PT-BR: ANTES — toil (operador roda manualmente)
212
+ -- $ psql -c 'reindex table heavy_table;' ← repetir a cada 2 semanas
213
+
214
+ -- PT-BR: DEPOIS — automação via pg_cron (necessita extension pg_cron habilitada)
215
+ create extension if not exists pg_cron;
216
+
217
+ select cron.schedule(
218
+ 'reindex_heavy_table_biweekly',
219
+ '0 3 1,15 * *', -- 3am dias 1 e 15
220
+ $$ reindex table public.heavy_table $$
221
+ );
222
+
223
+ -- PT-BR: monitor — falha em job pg_cron emite linha em cron.job_run_details
224
+ -- alimentar alerta SLO se job falha 3+ vezes seguidas
225
+ ```
226
+
227
+ ### Quando NÃO automatizar (não é toil)
228
+
229
+ - **Migration de schema (DDL one-shot)** — `create table`, `alter table add column` são project work, não toil. Não recorrentes.
230
+ - **Backfill data único** — `update orders set status = ...` aplicado 1× para corrigir bug é grungy work, não toil.
231
+ - **Rebuild que requer julgamento** — `reindex` que requer escolher hora baseada em load patterns variáveis, ou que precisa coordenação com release. Mantém manual mas documenta runbook.
232
+
233
+ ### Output do agent — adicionado ao SQL gerado
234
+
235
+ Quando o agent detecta que a migration descreve operação toil-prone (regex em DDL: `reindex|vacuum|refresh materialized|delete from .* interval`), adiciona comentário-alerta no header do arquivo SQL gerado:
236
+
237
+ ```sql
238
+ /*
239
+ ⚠ TOIL ALERT — esta operação parece recorrente.
240
+
241
+ Se será executada em cadência regular, considere automação via pg_cron:
242
+ select cron.schedule('<job_name>', '<schedule>', $$ <sql> $$);
243
+
244
+ Cross-ref: kit/skills/eliminating-toil/SKILL.md (6 critérios canônicos)
245
+ kit/agents/toil-auditor.md (audit sistemático para repo todo)
246
+ */
247
+ ```
248
+
249
+ ### Anti-patterns prevenidos
250
+
251
+ - "Roda quando der" runbook → SEMPRE pg_cron + monitoring de falha do job
252
+ - `pg_cron` schedule mas sem alerta de falha → SEMPRE incluir SLO em `cron.job_run_details` (% sucesso 30d)
253
+ - Automação parcial (script humano-iniciado) → ainda é toil (humano pressiona botão); preferir cron.schedule completo
254
+ - Migration manual recorrente "porque é só uma vez por mês" → 12×/ano = toil, regra ≤ 50% se acumular vários "só um por mês"