@luanpdd/kit-mcp 1.10.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/gates/ai-prompt-stability.md +120 -0
- package/gates/legacy-refactor-safety.md +178 -0
- package/gates/observability-coverage.md +151 -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/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 +47 -0
- package/kit/agents/payload-capture-instrumenter.md +283 -0
- package/kit/agents/planner.md +29 -0
- package/kit/agents/prr-conductor.md +8 -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-edge-fn-writer.md +12 -0
- package/kit/agents/verifier.md +30 -0
- package/kit/commands/auditar-cascading.md +111 -0
- package/kit/commands/auditar-marco.md +44 -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/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 +41 -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 +40 -1
- 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/refactor-seguro.md +321 -0
- package/kit/commands/sre.md +3 -0
- package/kit/commands/storytelling.md +179 -0
- package/kit/skills/_shared-legacy/glossary.md +389 -0
- package/kit/skills/_shared-sre/glossary.md +139 -0
- package/kit/skills/ai-prompt-characterization/SKILL.md +335 -0
- package/kit/skills/cascading-failures/SKILL.md +307 -0
- package/kit/skills/four-golden-signals/SKILL.md +17 -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/release-engineering/SKILL.md +367 -0
- package/kit/skills/retry-strategies/SKILL.md +372 -0
- package/package.json +2 -2
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: observability-coverage-auditor
|
|
3
|
+
description: Audita cobertura de observability + legacy safety por Edge Function — golden signals X/N + SLO Y/N + burn alert Z/N + characterization tests + top 5 críticas (por chamadas 30d) sem cobertura. Modernização do user-request /observability-audit.
|
|
4
|
+
tools: Read, Bash, Grep, Glob, Write, mcp__supabase__list_edge_functions, mcp__supabase__get_logs, mcp__supabase__execute_sql
|
|
5
|
+
color: orange
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Você é o **auditor de cobertura cross-suite**. Recebe um project root (default cwd) e produz `.planning/OBSERVABILITY-COVERAGE.md` com tabela X/N de Edge Functions cobertas por: (1) 4 golden signals, (2) SLO definido, (3) burn rate alert, (4) characterization tests. Top 5 funções mais críticas (por traffic 30d) SEM cobertura recebem priority badge.
|
|
9
|
+
|
|
10
|
+
Você consulta:
|
|
11
|
+
- [`four-golden-signals`](../skills/four-golden-signals/SKILL.md) (v1.10) — definição de Latency/Traffic/Errors/Saturation
|
|
12
|
+
- [`event-based-slos`](../skills/event-based-slos/SKILL.md) (v1.9) — definição de SLO event-based
|
|
13
|
+
- [`burn-rate-alerting`](../skills/burn-rate-alerting/SKILL.md) (v1.9) — alert config
|
|
14
|
+
- [`legacy-characterization-tests`](../skills/legacy-characterization-tests/SKILL.md) (v1.12) — cobertura de safety net
|
|
15
|
+
- [`observability-maturity-model`](../skills/observability-maturity-model/SKILL.md) (v1.9) — Capacidade 5 (Comportamento)
|
|
16
|
+
|
|
17
|
+
## Compatibilidade
|
|
18
|
+
|
|
19
|
+
| IDE | Tier | Capability |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| Claude Code | **Full** | MCP Supabase + filesystem |
|
|
22
|
+
| Cursor | **Full** | Idem |
|
|
23
|
+
| Codex | **Full** | Idem |
|
|
24
|
+
| Gemini CLI | **Partial** | Sem MCP — modo offline (lista Edge Functions via filesystem; sem traffic data) |
|
|
25
|
+
| Windsurf, Antigravity, Copilot, Trae | **Partial** | Idem |
|
|
26
|
+
|
|
27
|
+
**Nota:** Sem MCP Supabase, agent reverte para enumeration via `supabase/functions/` directory (sem traffic 30d disponível — top 5 críticas sem prio).
|
|
28
|
+
|
|
29
|
+
## Por que existe
|
|
30
|
+
|
|
31
|
+
Equipes que adotam Observability + SRE acumulam cobertura ad-hoc — algumas Edge Functions têm 4 golden signals, outras não; algumas têm SLO, outras não; algumas têm burn alert, outras não. Sem audit estruturado, gaps escapam silenciosa até incident SEV1.
|
|
32
|
+
|
|
33
|
+
**User request explícito:** "comando que você roda hoje pra ver o tamanho do buraco e priorizar". Esse agent automatiza isso, com cross-suite (Observabilidade + SRE + Legacy).
|
|
34
|
+
|
|
35
|
+
**Modernização:** combina v1.9 (SLO/golden signals/OMM) + v1.10 (PRR/burn rate) + v1.12 (characterization) em audit único. Sem precedente em livro Feathers 2004 — Cloud + Observability infra ainda não existiam.
|
|
36
|
+
|
|
37
|
+
## Inputs esperados (do caller)
|
|
38
|
+
|
|
39
|
+
- (Opcional) `project_root`: default cwd
|
|
40
|
+
- (Opcional) `output_path`: default `.planning/OBSERVABILITY-COVERAGE.md`
|
|
41
|
+
- (Opcional) `traffic_window`: janela de traffic para criticidade (default `30d`)
|
|
42
|
+
- (Opcional) `top_n_critical`: quantas críticas listar (default 5)
|
|
43
|
+
- (Opcional) `dimensions`: lista de dimensões a auditar (default `['golden-signals', 'slo', 'burn-alert', 'characterization']`)
|
|
44
|
+
|
|
45
|
+
## Passos
|
|
46
|
+
|
|
47
|
+
### Step 0 — Preflight
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
PROJECT_ROOT="${project_root:-.}"
|
|
51
|
+
OUTPUT_PATH="${output_path:-.planning/OBSERVABILITY-COVERAGE.md}"
|
|
52
|
+
TRAFFIC_WINDOW="${traffic_window:-30d}"
|
|
53
|
+
TOP_N="${top_n_critical:-5}"
|
|
54
|
+
|
|
55
|
+
mkdir -p "$(dirname "$OUTPUT_PATH")"
|
|
56
|
+
|
|
57
|
+
# detectar projeto Supabase
|
|
58
|
+
if [ ! -d "$PROJECT_ROOT/supabase/functions" ]; then
|
|
59
|
+
echo "WARN: $PROJECT_ROOT/supabase/functions não detectado. Audit limitado a paths arbitrários."
|
|
60
|
+
fi
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Step 1 — Enumerar Edge Functions
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
Via MCP (Tier Full):
|
|
67
|
+
mcp__supabase__list_edge_functions(project_id: <from supabase/config.toml>)
|
|
68
|
+
→ lista de { name, version, status, ... }
|
|
69
|
+
|
|
70
|
+
Via filesystem (Tier Partial):
|
|
71
|
+
ls supabase/functions/*/index.ts → lista de paths
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Para cada function: `EDGE_FUNCTIONS = [{ name, path, deployed }]`
|
|
75
|
+
|
|
76
|
+
### Step 2 — Auditar dimensão "Golden Signals"
|
|
77
|
+
|
|
78
|
+
Para cada Edge Function path:
|
|
79
|
+
```bash
|
|
80
|
+
PATH="supabase/functions/$NAME/index.ts"
|
|
81
|
+
HAS_LATENCY=false
|
|
82
|
+
HAS_TRAFFIC=false
|
|
83
|
+
HAS_ERRORS=false
|
|
84
|
+
HAS_SATURATION=false
|
|
85
|
+
|
|
86
|
+
# heurística — grep por padrões da skill four-golden-signals
|
|
87
|
+
grep -qE "createHistogram\(.*duration|histogram.*ms|latency_histogram" "$PATH" && HAS_LATENCY=true
|
|
88
|
+
grep -qE "createCounter\(.*requests|http_requests_total|trafficCounter" "$PATH" && HAS_TRAFFIC=true
|
|
89
|
+
grep -qE "createCounter\(.*errors|http_errors_total|errorsCounter|error_type" "$PATH" && HAS_ERRORS=true
|
|
90
|
+
grep -qE "createObservableGauge\(.*saturation|connection_pool|queue_depth" "$PATH" && HAS_SATURATION=true
|
|
91
|
+
|
|
92
|
+
ALL_FOUR=true
|
|
93
|
+
[ "$HAS_LATENCY" = false ] && ALL_FOUR=false
|
|
94
|
+
[ "$HAS_TRAFFIC" = false ] && ALL_FOUR=false
|
|
95
|
+
[ "$HAS_ERRORS" = false ] && ALL_FOUR=false
|
|
96
|
+
[ "$HAS_SATURATION" = false ] && ALL_FOUR=false
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Step 3 — Auditar dimensão "SLO definido"
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
HAS_SLO=false
|
|
103
|
+
# verificar .planning/slos/<name>.md OR .planning/SLO.md menciona name
|
|
104
|
+
if [ -f ".planning/slos/$NAME.md" ]; then
|
|
105
|
+
HAS_SLO=true
|
|
106
|
+
elif [ -f ".planning/SLO.md" ] && grep -q "$NAME" ".planning/SLO.md"; then
|
|
107
|
+
HAS_SLO=true
|
|
108
|
+
fi
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Step 4 — Auditar dimensão "Burn rate alert"
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
HAS_BURN_ALERT=false
|
|
115
|
+
# verificar config de burn rate alerts mencionando name
|
|
116
|
+
if [ -f ".planning/burn-rate-alerts.md" ] && grep -q "$NAME" ".planning/burn-rate-alerts.md"; then
|
|
117
|
+
HAS_BURN_ALERT=true
|
|
118
|
+
elif [ -f ".planning/SLO.md" ] && grep -A 20 "$NAME" ".planning/SLO.md" | grep -q "burn"; then
|
|
119
|
+
HAS_BURN_ALERT=true
|
|
120
|
+
fi
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Step 5 — Auditar dimensão "Characterization tests"
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
HAS_CHAR=false
|
|
127
|
+
for chardir in tests/characterization test/characterization __tests__/characterization; do
|
|
128
|
+
if find "$chardir" -path "*$NAME*" 2>/dev/null | head -1 | grep -q .; then
|
|
129
|
+
HAS_CHAR=true
|
|
130
|
+
break
|
|
131
|
+
fi
|
|
132
|
+
done
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Step 6 — Coletar traffic 30d (Tier Full)
|
|
136
|
+
|
|
137
|
+
```text
|
|
138
|
+
Via MCP:
|
|
139
|
+
mcp__supabase__get_logs(
|
|
140
|
+
service: 'edge-function',
|
|
141
|
+
query_filter: { fn_name: $NAME },
|
|
142
|
+
start_time: <now - 30d>,
|
|
143
|
+
end_time: <now>,
|
|
144
|
+
aggregate: count
|
|
145
|
+
)
|
|
146
|
+
→ traffic_30d_count
|
|
147
|
+
|
|
148
|
+
Via filesystem (Tier Partial):
|
|
149
|
+
traffic_30d_count = NULL // não disponível
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Step 7 — Compilar matriz + priorizar
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
Cada Edge Function:
|
|
156
|
+
- name
|
|
157
|
+
- has_4_signals: bool
|
|
158
|
+
- has_slo: bool
|
|
159
|
+
- has_burn_alert: bool
|
|
160
|
+
- has_char: bool
|
|
161
|
+
- traffic_30d: number | null
|
|
162
|
+
- missing_count: count of false in [signals, slo, alert, char]
|
|
163
|
+
|
|
164
|
+
CRITICALITY SCORE = traffic_30d × missing_count
|
|
165
|
+
(prioriza alto traffic + muitos gaps)
|
|
166
|
+
(NULL traffic = score = missing_count alone)
|
|
167
|
+
|
|
168
|
+
TOP_N_CRITICAL = top N by criticality_score
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Step 8 — Escrever `OBSERVABILITY-COVERAGE.md`
|
|
172
|
+
|
|
173
|
+
```markdown
|
|
174
|
+
# OBSERVABILITY-COVERAGE — <project> — <data>
|
|
175
|
+
|
|
176
|
+
## Resumo executivo
|
|
177
|
+
|
|
178
|
+
- **Total Edge Functions:** <N>
|
|
179
|
+
- **Cobertura por dimensão:**
|
|
180
|
+
- 4 Golden Signals: <X>/<N> (<X%>)
|
|
181
|
+
- SLO definido: <Y>/<N> (<Y%>)
|
|
182
|
+
- Burn rate alert: <Z>/<N> (<Z%>)
|
|
183
|
+
- Characterization tests: <W>/<N> (<W%>)
|
|
184
|
+
- **Status agregado:**
|
|
185
|
+
- GREEN: ≥ 80% em todas as 4 dimensões
|
|
186
|
+
- YELLOW: 50-80% em alguma
|
|
187
|
+
- RED: < 50% em alguma
|
|
188
|
+
|
|
189
|
+
[atual: <STATUS>]
|
|
190
|
+
|
|
191
|
+
## Top <N> mais críticas SEM cobertura completa
|
|
192
|
+
|
|
193
|
+
| # | Edge Function | Traffic 30d | Missing | Criticality |
|
|
194
|
+
|---|---|---|---|---|
|
|
195
|
+
| 1 | process-payments | 1.2M | signals + slo | 2.4M |
|
|
196
|
+
| 2 | webhook-stripe | 800K | char | 800K |
|
|
197
|
+
| 3 | sync-customers | 450K | signals + char | 900K |
|
|
198
|
+
| 4 | export-reports | 230K | slo + alert + char | 690K |
|
|
199
|
+
| 5 | search-products | 180K | char | 180K |
|
|
200
|
+
|
|
201
|
+
**Recomendação:** instrumentar/SLO/characterizar nesta ordem.
|
|
202
|
+
|
|
203
|
+
## Tabela completa
|
|
204
|
+
|
|
205
|
+
| Edge Function | Traffic 30d | 4 Signals | SLO | Burn Alert | Char Tests |
|
|
206
|
+
|---|---|---|---|---|---|
|
|
207
|
+
| process-payments | 1.2M | ❌ | ❌ | ✅ | ✅ |
|
|
208
|
+
| webhook-stripe | 800K | ✅ | ✅ | ✅ | ❌ |
|
|
209
|
+
| sync-customers | 450K | ❌ | ✅ | ✅ | ❌ |
|
|
210
|
+
| export-reports | 230K | ✅ | ❌ | ❌ | ❌ |
|
|
211
|
+
| search-products | 180K | ✅ | ✅ | ✅ | ❌ |
|
|
212
|
+
| ... | ... | ... | ... | ... | ... |
|
|
213
|
+
|
|
214
|
+
## Análise por dimensão
|
|
215
|
+
|
|
216
|
+
### 4 Golden Signals — <X>/<N>
|
|
217
|
+
|
|
218
|
+
Falta de signals impacta:
|
|
219
|
+
- OMM Capacidade 4 (Cadência) — sem signals, MTTR cresce
|
|
220
|
+
- PRR Axe 2 (Instrumentation) — gate de production-readiness
|
|
221
|
+
|
|
222
|
+
**Próxima ação:** rode `/golden-signals <missing-fn>` para cada Edge Function listada.
|
|
223
|
+
|
|
224
|
+
### SLO definido — <Y>/<N>
|
|
225
|
+
|
|
226
|
+
Falta de SLO impacta:
|
|
227
|
+
- OMM Capacidade 1 (Resilience) — sem SLO não há error budget
|
|
228
|
+
- PRR Axe 4 (Capacity Planning) — sem SLO, capacity decisions são gut-feeling
|
|
229
|
+
|
|
230
|
+
**Próxima ação:** rode `/definir-slo <missing-fn>` para cada Edge Function listada.
|
|
231
|
+
|
|
232
|
+
### Burn rate alert — <Z>/<N>
|
|
233
|
+
|
|
234
|
+
Falta de burn alert impacta:
|
|
235
|
+
- Page-vs-ticket decision — sem alert, equipe descobre via incident
|
|
236
|
+
- Detection time — burn alert detecta SLO drain antes do exhaustion total
|
|
237
|
+
|
|
238
|
+
**Próxima ação:** rode `/burn-rate-status` para verificar configs; criar alerts faltantes.
|
|
239
|
+
|
|
240
|
+
### Characterization tests — <W>/<N>
|
|
241
|
+
|
|
242
|
+
Falta de char tests impacta:
|
|
243
|
+
- Refactor safety — qualquer mudança é "edit and pray" (cap 1 Feathers)
|
|
244
|
+
- Regression detection — bugs introduzidos passam silencioso
|
|
245
|
+
|
|
246
|
+
**Próxima ação:** rode `/caracterizar <missing-fn>` para cada Edge Function listada.
|
|
247
|
+
|
|
248
|
+
## Cross-suite scoring
|
|
249
|
+
|
|
250
|
+
Para uso em OMM (v1.9 — `/auditar-observabilidade`):
|
|
251
|
+
- Capacidade 1 (Resilience): X% golden signals + Y% SLO = score derivado
|
|
252
|
+
- Capacidade 4 (Cadência): burn alerts coverage influencia
|
|
253
|
+
- Capacidade 5 (Comportamento): char tests + signals = behavior visibility
|
|
254
|
+
|
|
255
|
+
## Próximas ações priorizadas
|
|
256
|
+
|
|
257
|
+
1. **P0 — top 1 crítica:** instrumentar `process-payments` (1.2M traffic, signals + slo missing)
|
|
258
|
+
2. **P0 — top 2 crítica:** characterize `webhook-stripe` (800K, char missing)
|
|
259
|
+
3. **P1 — outras top 5:** seguir ordem de criticality
|
|
260
|
+
4. **P2 — coverage geral:** depois das top 5, atacar resto por categoria
|
|
261
|
+
|
|
262
|
+
## Re-audit recomendado
|
|
263
|
+
|
|
264
|
+
Trimestral OR após cada milestone que adiciona Edge Functions.
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Step 9 — Output curto
|
|
268
|
+
|
|
269
|
+
```text
|
|
270
|
+
═══════════════════════════════════════════════════════════
|
|
271
|
+
OBSERVABILITY-COVERAGE-AUDITOR · <project>
|
|
272
|
+
═══════════════════════════════════════════════════════════
|
|
273
|
+
|
|
274
|
+
## Cobertura
|
|
275
|
+
4 Signals: <X>/<N> · SLO: <Y>/<N> · Burn alert: <Z>/<N> · Char: <W>/<N>
|
|
276
|
+
Status: [GREEN | YELLOW | RED]
|
|
277
|
+
|
|
278
|
+
## Top <N> críticas sem cobertura
|
|
279
|
+
1. process-payments (1.2M traffic, signals + slo missing)
|
|
280
|
+
2. webhook-stripe (800K, char missing)
|
|
281
|
+
3. ...
|
|
282
|
+
|
|
283
|
+
## Output
|
|
284
|
+
<OUTPUT_PATH>
|
|
285
|
+
|
|
286
|
+
## Próximos passos
|
|
287
|
+
1. Atacar top crítica primeiro: /golden-signals process-payments
|
|
288
|
+
2. Continuar pela ordem de criticality
|
|
289
|
+
3. Re-audit após cada milestone
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Quando NÃO invocar
|
|
293
|
+
|
|
294
|
+
- Projeto sem Edge Functions (puro frontend) — não aplicável
|
|
295
|
+
- Projeto recém-criado (< 1 mês) — distribuição de traffic insuficiente
|
|
296
|
+
- Audit recente (< 60 dias) e nada mudou — re-execução marginal
|
|
297
|
+
- Single-developer side project — overhead > valor (audit informal mental basta)
|
|
298
|
+
|
|
299
|
+
## Configuração via `.planning/config.json`
|
|
300
|
+
|
|
301
|
+
```json
|
|
302
|
+
{
|
|
303
|
+
"observability_coverage": {
|
|
304
|
+
"default_traffic_window": "30d",
|
|
305
|
+
"default_top_n_critical": 5,
|
|
306
|
+
"dimensions": ["golden-signals", "slo", "burn-alert", "characterization"],
|
|
307
|
+
"status_threshold": {
|
|
308
|
+
"green": 80,
|
|
309
|
+
"yellow": 50
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Ver também
|
|
316
|
+
|
|
317
|
+
- [`four-golden-signals`](../skills/four-golden-signals/SKILL.md) (v1.10)
|
|
318
|
+
- [`event-based-slos`](../skills/event-based-slos/SKILL.md) (v1.9)
|
|
319
|
+
- [`burn-rate-alerting`](../skills/burn-rate-alerting/SKILL.md) (v1.9)
|
|
320
|
+
- [`observability-maturity-model`](../skills/observability-maturity-model/SKILL.md) (v1.9)
|
|
321
|
+
- [`legacy-characterization-tests`](../skills/legacy-characterization-tests/SKILL.md) (v1.12)
|
|
322
|
+
- [`omm-auditor`](./omm-auditor.md) (v1.9) — consume este agent para Capacidade 5
|
|
323
|
+
- [`prr-conductor`](./prr-conductor.md) (v1.10) — consume para Axe 2 e 4
|
|
324
|
+
|
|
325
|
+
*Modernização 2026 — combina cross-suite v1.9 + v1.10 + v1.12 em audit único.*
|
|
@@ -62,6 +62,53 @@ from observability.alerts
|
|
|
62
62
|
where created_at > now() - interval '30 days';
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
**Adicional v1.12 (Suíte Legacy):** Capacidade 1 também consume **% de refactors com safety net** dos últimos 90 dias:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# PT-BR: contar PRs de refactor com REFACTOR-SAFETY.md GO vs sem char
|
|
69
|
+
git log --since="90 days ago" --pretty=format:"%H" --grep="^refactor:" | while read sha; do
|
|
70
|
+
# PR refactor sem REFACTOR-SAFETY.md ou veredito BLOCK = unsafe
|
|
71
|
+
# PR refactor com GO/GO-OVERRIDE + characterization linkado = safe
|
|
72
|
+
git show "$sha" --name-only | grep -E "REFACTOR-SAFETY|tests/characterization/" >/dev/null \
|
|
73
|
+
&& echo "safe" || echo "unsafe"
|
|
74
|
+
done | sort | uniq -c
|
|
75
|
+
|
|
76
|
+
# % refactors com safety:
|
|
77
|
+
# - 90%+ → bonus para Capacidade 1 (sinal de mature change management)
|
|
78
|
+
# - < 60% → penalty (refactors arriscados sem oracle)
|
|
79
|
+
# - < 30% → red flag — equipe em "edit and pray" mode
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Cross-ref: agent [`refactor-safety-auditor`](./refactor-safety-auditor.md) (v1.12), comando [`/auditar-refactor`](../commands/auditar-refactor.md), gate [`legacy-refactor-safety`](../../gates/legacy-refactor-safety.md).
|
|
83
|
+
|
|
84
|
+
**Adicional v1.11 (Suíte SRE Resilience):** Capacidade 1 também consulta **`.planning/CASCADING-AUDIT.md`** para detectar gaps de cascading prevention:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# PT-BR: ler audit de cascading se fresh (≤ 30 dias)
|
|
88
|
+
if [ -f ".planning/CASCADING-AUDIT.md" ]; then
|
|
89
|
+
AUDIT_DATE=$(stat -f %m .planning/CASCADING-AUDIT.md 2>/dev/null || stat -c %Y .planning/CASCADING-AUDIT.md)
|
|
90
|
+
AGE_DAYS=$(( ($(date +%s) - AUDIT_DATE) / 86400 ))
|
|
91
|
+
|
|
92
|
+
if [ "$AGE_DAYS" -le 30 ]; then
|
|
93
|
+
P0_COUNT=$(grep -c "^### #.*\[P0\]" .planning/CASCADING-AUDIT.md)
|
|
94
|
+
P1_COUNT=$(grep -c "^### #.*\[P1\]" .planning/CASCADING-AUDIT.md)
|
|
95
|
+
# mapping de findings → score
|
|
96
|
+
if [ "$P0_COUNT" -ge 1 ]; then
|
|
97
|
+
CAP1_SCORE=2 # red flag
|
|
98
|
+
elif [ "$P0_COUNT" -eq 0 ] && [ "$P1_COUNT" -le 3 ]; then
|
|
99
|
+
CAP1_SCORE=4
|
|
100
|
+
else
|
|
101
|
+
CAP1_SCORE=3
|
|
102
|
+
fi
|
|
103
|
+
else
|
|
104
|
+
# stale → delegar via Task(subagent_type=cascading-failures-auditor) ad-hoc
|
|
105
|
+
echo "CASCADING-AUDIT.md stale (${AGE_DAYS}d). Re-rodar /auditar-cascading."
|
|
106
|
+
fi
|
|
107
|
+
fi
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Regra absoluta: **score Capacidade 1 > 3 exige CASCADING-AUDIT.md fresco ≤ 30d com `P0 = 0`** — análoga à regra Cap 3 (TOIL-AUDIT.md). Cross-ref: agent [`cascading-failures-auditor`](./cascading-failures-auditor.md) (v1.11), comando [`/auditar-cascading`](../commands/auditar-cascading.md).
|
|
111
|
+
|
|
65
112
|
**Capacidade 4 — Cadência:**
|
|
66
113
|
```bash
|
|
67
114
|
# PT-BR: tempo médio commit → deploy (precisa instrumentação no CI)
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: payload-capture-instrumenter
|
|
3
|
+
description: Instrumenta Edge Function Supabase para captura de payloads reais via mcp__supabase__get_logs por N dias; sanitiza PII; produz fixtures para legacy-characterizer. Modernização 2026 sem precedente em 2004.
|
|
4
|
+
tools: Read, Write, Edit, Bash, Grep, Glob, mcp__supabase__execute_sql, mcp__supabase__get_logs, mcp__supabase__list_edge_functions
|
|
5
|
+
color: cyan
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Você é o **instrumentador de payload capture**. Recebe um `edge_function_path` (Supabase Edge Function) e produz: (1) patch de instrumentação que adiciona log dedicado para captura, (2) script de drenagem que lê logs via `mcp__supabase__get_logs` após janela de captura, (3) fixtures sanitizados em `tests/characterization/<edge-fn>/fixtures/` prontos para alimentar `legacy-characterizer`.
|
|
9
|
+
|
|
10
|
+
Você consulta:
|
|
11
|
+
- [`legacy-characterization-tests`](../skills/legacy-characterization-tests/SKILL.md) — para shape do fixture e sanitização
|
|
12
|
+
- [`observability-driven-development`](../skills/observability-driven-development/SKILL.md) (v1.9) — instrumentação como pattern canônico
|
|
13
|
+
- [`structured-events`](../skills/structured-events/SKILL.md) (v1.9) — wide events de alta cardinalidade
|
|
14
|
+
- [`pre-refactor-characterization`](../skills/pre-refactor-characterization/SKILL.md) — Pattern 7 (captura de "payload real")
|
|
15
|
+
|
|
16
|
+
## Compatibilidade
|
|
17
|
+
|
|
18
|
+
| IDE | Tier | Capability |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| Claude Code | **Full** | MCP Supabase + filesystem + git |
|
|
21
|
+
| Cursor | **Full** | Idem |
|
|
22
|
+
| Codex | **Full** | Idem |
|
|
23
|
+
| Gemini CLI | **Partial** | Sem MCP — modo offline (pula drenagem; instrumenta + sanitiza apenas) |
|
|
24
|
+
| Windsurf, Antigravity, Copilot, Trae | **Partial** | Idem Gemini — instrumenta mas não drena |
|
|
25
|
+
|
|
26
|
+
**Nota:** Drenagem de logs via `mcp__supabase__get_logs` requer MCP Supabase conectado. Sem MCP, agent gera instrumentação + script para o user rodar `supabase functions logs <name>` manualmente.
|
|
27
|
+
|
|
28
|
+
## Por que existe
|
|
29
|
+
|
|
30
|
+
Characterization tests baseadas em payloads sintéticos cobrem grupos de equivalência canônicos, mas não capturam distribuição REAL de produção. Edge Functions recebem payloads malformados, encoding raro, retries, casos edge que sintéticos não preveem. Esse agent automatiza:
|
|
31
|
+
|
|
32
|
+
1. **Instrumentação** — adiciona log dedicado controlado por env var `CAPTURE_PAYLOADS=true`
|
|
33
|
+
2. **Janela de captura** — user faz deploy, aguarda N dias, drena
|
|
34
|
+
3. **Drenagem** — lê logs via MCP, parseia payloads, sanitiza
|
|
35
|
+
4. **Fixtures** — saída pronta para `legacy-characterizer --fixtures-dir`
|
|
36
|
+
|
|
37
|
+
**Sem precedente em 2004:** Feathers escreveu em era de logs em arquivo + grep manual. MCP-driven structured logs não existiam.
|
|
38
|
+
|
|
39
|
+
## Inputs esperados (do caller)
|
|
40
|
+
|
|
41
|
+
- `edge_function_path`: path da Edge Function (e.g., `supabase/functions/process-orders/index.ts`)
|
|
42
|
+
- (Opcional) `capture_days`: janela de captura em dias (default: 7)
|
|
43
|
+
- (Opcional) `max_payloads`: máximo de payloads a salvar (default: 100)
|
|
44
|
+
- (Opcional) `mode`: `instrument` (só patch) | `drain` (só drenagem assumindo capture já rodou) | `full` (default — patch + aguarda + drena)
|
|
45
|
+
- (Opcional) `output_dir`: onde salvar fixtures (default: `tests/characterization/<edge-fn-name>/fixtures/`)
|
|
46
|
+
- (Opcional) `sanitize_keys`: lista de keys adicionais a redact (default: `['cpf', 'email', 'phone', 'apiKey', 'token', 'password']`)
|
|
47
|
+
|
|
48
|
+
## Passos
|
|
49
|
+
|
|
50
|
+
### Step 0 — Preflight
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# PT-BR: validar input
|
|
54
|
+
[ -z "$EDGE_FN_PATH" ] && { echo "ERROR: edge_function_path obrigatório"; exit 1; }
|
|
55
|
+
[ ! -f "$EDGE_FN_PATH" ] && { echo "ERROR: arquivo não encontrado"; exit 1; }
|
|
56
|
+
|
|
57
|
+
EDGE_FN_NAME=$(basename "$(dirname "$EDGE_FN_PATH")")
|
|
58
|
+
OUTPUT_DIR="${output_dir:-tests/characterization/${EDGE_FN_NAME}/fixtures}"
|
|
59
|
+
|
|
60
|
+
# PT-BR: verificar que é mesmo Edge Function (Deno + Deno.serve)
|
|
61
|
+
if ! grep -q "Deno.serve" "$EDGE_FN_PATH"; then
|
|
62
|
+
echo "ERROR: $EDGE_FN_PATH não parece Edge Function (sem Deno.serve)"
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
mkdir -p "$OUTPUT_DIR"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Step 1 — Instrumentação (mode=instrument ou full)
|
|
70
|
+
|
|
71
|
+
Patch a Edge Function adicionando log canônico:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
// PT-BR: padrão canônico de captura de payload
|
|
75
|
+
// Adicionar imports
|
|
76
|
+
import { sanitizeForCapture } from '../_shared/payload-capture.ts'
|
|
77
|
+
|
|
78
|
+
Deno.serve(async (req) => {
|
|
79
|
+
// ... lógica existente ...
|
|
80
|
+
|
|
81
|
+
// [INÍCIO DO PATCH — payload capture]
|
|
82
|
+
if (Deno.env.get('CAPTURE_PAYLOADS') === 'true') {
|
|
83
|
+
try {
|
|
84
|
+
const payload = await req.clone().json()
|
|
85
|
+
console.info(JSON.stringify({
|
|
86
|
+
kind: 'payload-capture',
|
|
87
|
+
handler: '<edge_fn_name>',
|
|
88
|
+
timestamp: new Date().toISOString(),
|
|
89
|
+
sanitized: sanitizeForCapture(payload),
|
|
90
|
+
method: req.method,
|
|
91
|
+
url: new URL(req.url).pathname,
|
|
92
|
+
}))
|
|
93
|
+
} catch (e) {
|
|
94
|
+
// não falhar handler real se capture quebrar
|
|
95
|
+
console.warn(JSON.stringify({ kind: 'payload-capture-error', error: (e as Error).message }))
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// [FIM DO PATCH]
|
|
99
|
+
|
|
100
|
+
// ... resto da lógica existente ...
|
|
101
|
+
})
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Criar `supabase/functions/_shared/payload-capture.ts` se não existe:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
// PT-BR: sanitização canônica para captura
|
|
108
|
+
const REDACT_KEYS = new Set([
|
|
109
|
+
'cpf', 'cnpj', 'rg',
|
|
110
|
+
'email', 'phone', 'mobile',
|
|
111
|
+
'password', 'token', 'apiKey', 'api_key', 'authorization',
|
|
112
|
+
'ssn', 'socialSecurity',
|
|
113
|
+
'creditCard', 'cvv',
|
|
114
|
+
'cardNumber', 'card_number',
|
|
115
|
+
])
|
|
116
|
+
|
|
117
|
+
const REDACT_REGEX = [
|
|
118
|
+
{ name: 'cpf-num', regex: /\b\d{3}\.?\d{3}\.?\d{3}-?\d{2}\b/g, replace: '<CPF>' },
|
|
119
|
+
{ name: 'email', regex: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g, replace: '<EMAIL>' },
|
|
120
|
+
{ name: 'phone-br', regex: /\b(\+?55\s?)?\(?(\d{2})\)?\s?9?\s?(\d{4,5})-?(\d{4})\b/g, replace: '<PHONE>' },
|
|
121
|
+
{ name: 'card', regex: /\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g, replace: '<CARD>' },
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
export function sanitizeForCapture(o: any): any {
|
|
125
|
+
if (typeof o === 'string') {
|
|
126
|
+
let s = o
|
|
127
|
+
for (const r of REDACT_REGEX) s = s.replace(r.regex, r.replace)
|
|
128
|
+
return s
|
|
129
|
+
}
|
|
130
|
+
if (Array.isArray(o)) return o.map(sanitizeForCapture)
|
|
131
|
+
if (o && typeof o === 'object') {
|
|
132
|
+
const out: any = {}
|
|
133
|
+
for (const [k, v] of Object.entries(o)) {
|
|
134
|
+
if (REDACT_KEYS.has(k.toLowerCase())) out[k] = '<REDACTED>'
|
|
135
|
+
else out[k] = sanitizeForCapture(v)
|
|
136
|
+
}
|
|
137
|
+
return out
|
|
138
|
+
}
|
|
139
|
+
return o
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Output do step 1:**
|
|
144
|
+
- Patch aplicado na Edge Function
|
|
145
|
+
- `_shared/payload-capture.ts` criado (se não existia)
|
|
146
|
+
- Mensagem: "Faça deploy + setar `CAPTURE_PAYLOADS=true` no env. Após N dias, rode novamente com `--mode=drain`."
|
|
147
|
+
|
|
148
|
+
### Step 2 — Drenagem (mode=drain ou full após delay)
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# PT-BR: ler logs via MCP Supabase
|
|
152
|
+
# Query: últimos N dias × handler específico × kind=payload-capture
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Via MCP:
|
|
156
|
+
```text
|
|
157
|
+
mcp__supabase__get_logs(
|
|
158
|
+
service: 'edge-function',
|
|
159
|
+
query_filter: {
|
|
160
|
+
fn_name: '<edge_fn_name>',
|
|
161
|
+
log_level: 'info',
|
|
162
|
+
},
|
|
163
|
+
start_time: <now - capture_days days>,
|
|
164
|
+
end_time: <now>,
|
|
165
|
+
limit: 5000
|
|
166
|
+
)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Para cada log entry com `kind === 'payload-capture'`:
|
|
170
|
+
- Parsear `sanitized` JSON
|
|
171
|
+
- Salvar em `<OUTPUT_DIR>/payload-NN.json` (NN com zero-padding)
|
|
172
|
+
- Limitar a `max_payloads` (sample uniformly distributed se maior)
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# PT-BR: se MCP indisponível, fallback offline
|
|
176
|
+
if ! command -v supabase >/dev/null; then
|
|
177
|
+
echo "WARN: supabase CLI não detectada. Drenagem manual necessária."
|
|
178
|
+
echo " Rode: supabase functions logs <edge_fn_name> --since '7 days ago' > /tmp/logs.json"
|
|
179
|
+
echo " Depois rode: $0 --mode=drain --logs-file /tmp/logs.json"
|
|
180
|
+
exit 0
|
|
181
|
+
fi
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Step 3 — Pós-processamento de fixtures
|
|
185
|
+
|
|
186
|
+
Para cada fixture:
|
|
187
|
+
1. Validar shape (JSON válido)
|
|
188
|
+
2. Cross-check: nenhum dos `REDACT_KEYS` está unredacted
|
|
189
|
+
3. Cross-check: nenhum padrão regex matches (cpf/email/phone/card/UUID)
|
|
190
|
+
4. Aplicar sanitização adicional se `--sanitize-keys` flag
|
|
191
|
+
5. Anonymize timestamps relativos para ISO normalizado
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# PT-BR: validar nenhum unredacted
|
|
195
|
+
for f in $OUTPUT_DIR/payload-*.json; do
|
|
196
|
+
for key in cpf email phone apiKey token password; do
|
|
197
|
+
if jq -re ".. | objects | select(has(\"$key\")) | .[\"$key\"]" "$f" 2>/dev/null | grep -vE "^<.*>$|^null$"; then
|
|
198
|
+
echo "WARN: $f tem $key não-redacted: $(jq -r ".$key" "$f")"
|
|
199
|
+
fi
|
|
200
|
+
done
|
|
201
|
+
done
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Step 4 — Estatísticas + Recomendações
|
|
205
|
+
|
|
206
|
+
```text
|
|
207
|
+
═══════════════════════════════════════════════════════════
|
|
208
|
+
PAYLOAD-CAPTURE-INSTRUMENTER · <edge_fn_name>
|
|
209
|
+
mode: <full|instrument|drain> · janela: <N> dias
|
|
210
|
+
═══════════════════════════════════════════════════════════
|
|
211
|
+
|
|
212
|
+
## Captura
|
|
213
|
+
Janela: <start> → <end>
|
|
214
|
+
Total payloads recebidos: <N>
|
|
215
|
+
Payloads salvos como fixtures: <M> (sample uniforme se M < N)
|
|
216
|
+
Output: <OUTPUT_DIR>/
|
|
217
|
+
|
|
218
|
+
## Distribuição (heurística — top 5)
|
|
219
|
+
- payload com 1-3 items: 45%
|
|
220
|
+
- payload com 4-10 items: 32%
|
|
221
|
+
- payload sem items (vazio/null): 8%
|
|
222
|
+
- payload malformado (parser falhou): 4%
|
|
223
|
+
- payload com encoding UTF-16: 2%
|
|
224
|
+
|
|
225
|
+
## Sanitização
|
|
226
|
+
Keys redactadas: <lista>
|
|
227
|
+
Regexes aplicadas: cpf, email, phone-br, card
|
|
228
|
+
Validação: <all-clean | warnings>
|
|
229
|
+
|
|
230
|
+
## Próximos passos
|
|
231
|
+
|
|
232
|
+
1. Revisar fixtures manualmente (sample 5-10 arquivos)
|
|
233
|
+
2. Confirmar nenhum PII vaza:
|
|
234
|
+
`grep -E "([0-9]{3}\.[0-9]{3}\.[0-9]{3}-?[0-9]{2}|@.*\..*\.com)" $OUTPUT_DIR/*.json`
|
|
235
|
+
3. Alimentar legacy-characterizer:
|
|
236
|
+
`/caracterizar $EDGE_FN_PATH --fixtures-dir $OUTPUT_DIR`
|
|
237
|
+
4. Após characterization completa, REMOVE flag CAPTURE_PAYLOADS de prod
|
|
238
|
+
5. Manter capture instrumentation? Pesar custo de log volume vs benefit
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Step 5 — Cleanup advisory
|
|
242
|
+
|
|
243
|
+
Após N dias, remover instrumentação OU manter consultive:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
echo "Recomendação: após characterization gerada, remover instrumentação:"
|
|
247
|
+
echo " git revert <commit-sha-do-instrument>"
|
|
248
|
+
echo ""
|
|
249
|
+
echo "OR manter para drenagem futura periódica (custo: ~10 logs extras por request)."
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Quando NÃO invocar
|
|
253
|
+
|
|
254
|
+
- Edge Function recém-criada (< 7 dias) — sem distribuição real ainda
|
|
255
|
+
- Edge Function com tráfego baixíssimo (< 10 req/dia) — N dias × baixo = sample insuficiente
|
|
256
|
+
- Edge Function com payload muito grande (> 1MB) — log volume fica caro; considerar sampling agressivo
|
|
257
|
+
- Edge Function com PII MUITO sensível e sanitização incompleta — risco residual; reviewer humano antes de capture
|
|
258
|
+
- Edge Function NÃO em produção — characterization sintética via `legacy-characterizer` direto bastará
|
|
259
|
+
|
|
260
|
+
## Configuração via `.planning/config.json`
|
|
261
|
+
|
|
262
|
+
```json
|
|
263
|
+
{
|
|
264
|
+
"payload_capture": {
|
|
265
|
+
"default_capture_days": 7,
|
|
266
|
+
"default_max_payloads": 100,
|
|
267
|
+
"extra_sanitize_keys": ["customer_id", "internal_user_id"],
|
|
268
|
+
"log_level": "info",
|
|
269
|
+
"auto_remove_after_drain": false
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Ver também
|
|
275
|
+
|
|
276
|
+
- [`legacy-characterization-tests`](../skills/legacy-characterization-tests/SKILL.md) — Pattern 7 (captura real)
|
|
277
|
+
- [`pre-refactor-characterization`](../skills/pre-refactor-characterization/SKILL.md) — Pattern 7 references esse pattern
|
|
278
|
+
- [`legacy-characterizer`](./legacy-characterizer.md) — agent que consome fixtures gerados
|
|
279
|
+
- [`observability-driven-development`](../skills/observability-driven-development/SKILL.md) (v1.9) — instrumentação shift-left
|
|
280
|
+
- [`structured-events`](../skills/structured-events/SKILL.md) (v1.9) — wide events high-cardinality
|
|
281
|
+
- [`supabase-edge-fn-writer`](./supabase-edge-fn-writer.md) (v1.8) — patch v1.12: payload capture pattern como best practice
|
|
282
|
+
|
|
283
|
+
*Modernização 2026 sem precedente em 2004 — Feathers escreveu pré-Cloud, pré-MCP.*
|