@luanpdd/kit-mcp 1.8.1 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +39 -1
  2. package/gates/obs-agents-mcp-supabase.md +86 -0
  3. package/gates/obs-skills-frontmatter.md +76 -0
  4. package/gates/omm-no-regression.md +83 -0
  5. package/gates/skill-must-include.md +21 -19
  6. package/kit/agents/burn-rate-forecaster.md +160 -0
  7. package/kit/agents/incident-investigator.md +245 -0
  8. package/kit/agents/observability-instrumenter.md +200 -0
  9. package/kit/agents/omm-auditor.md +199 -0
  10. package/kit/agents/slo-engineer.md +224 -0
  11. package/kit/agents/supabase-architect.md +13 -0
  12. package/kit/agents/supabase-auth-bootstrapper.md +17 -0
  13. package/kit/agents/supabase-edge-fn-writer.md +22 -0
  14. package/kit/agents/supabase-migration-writer.md +18 -0
  15. package/kit/agents/supabase-realtime-implementer.md +23 -0
  16. package/kit/agents/supabase-rls-writer.md +17 -0
  17. package/kit/agents/supabase-storage-implementer.md +18 -0
  18. package/kit/commands/auditar-marco.md +22 -1
  19. package/kit/commands/auditar-observabilidade.md +103 -0
  20. package/kit/commands/burn-rate-status.md +140 -0
  21. package/kit/commands/concluir-marco.md +19 -1
  22. package/kit/commands/definir-slo.md +108 -0
  23. package/kit/commands/discutir-fase.md +26 -0
  24. package/kit/commands/forense.md +20 -1
  25. package/kit/commands/instrumentar-fase.md +200 -0
  26. package/kit/commands/investigar-producao.md +162 -0
  27. package/kit/commands/observabilidade.md +116 -0
  28. package/kit/commands/planejar-fase.md +20 -0
  29. package/kit/commands/verificar-trabalho.md +26 -0
  30. package/kit/skills/_shared-observability/glossary.md +396 -0
  31. package/kit/skills/burn-rate-alerting/SKILL.md +258 -0
  32. package/kit/skills/core-analysis-loop/SKILL.md +352 -0
  33. package/kit/skills/distributed-tracing/SKILL.md +362 -0
  34. package/kit/skills/event-based-slos/SKILL.md +274 -0
  35. package/kit/skills/observability-driven-development/SKILL.md +315 -0
  36. package/kit/skills/observability-maturity-model/SKILL.md +222 -0
  37. package/kit/skills/opentelemetry-standard/SKILL.md +351 -0
  38. package/kit/skills/structured-events/SKILL.md +265 -0
  39. package/kit/skills/telemetry-pipelines/SKILL.md +259 -0
  40. package/kit/skills/telemetry-sampling/SKILL.md +256 -0
  41. package/package.json +1 -1
package/README.md CHANGED
@@ -59,10 +59,48 @@ kit-mcp/
59
59
 
60
60
  ### About the bundled workflow
61
61
 
62
- The bundled `kit/` is an opinionated **brownfield planning workflow** in Portuguese — milestones, phases, requirements, planning, execution with atomic commits and checkpoints, retrospective auditing. Installing `@luanpdd/kit-mcp` and syncing into your IDE gives you all 60 slash-commands, 19 agents, plus the framework templates that they delegate into.
62
+ The bundled `kit/` is an opinionated **brownfield planning workflow** in Portuguese — milestones, phases, requirements, planning, execution with atomic commits and checkpoints, retrospective auditing. Installing `@luanpdd/kit-mcp` and syncing into your IDE gives you all 60+ slash-commands, 24+ agents, plus the framework templates that they delegate into.
63
63
 
64
64
  If that's not what you want, point `--kit-root` at your own folder and ignore everything under `kit/` — the infrastructure (registry, sync, gates, forensics, MCP server) works the same regardless of what kit you load.
65
65
 
66
+ ### Observability suite (v1.9)
67
+
68
+ A complete observability layer derived from *Observability Engineering* (Charity Majors, Liz Fong-Jones, George Miranda — O'Reilly, 2022) ships in the kit. It integrates deeply with the Supabase suite (v1.8) — every Supabase agent now consults observability skills, and the new `incident-investigator` agent uses `mcp__supabase__get_logs` / `execute_sql` / `get_advisors` to apply the **Core Analysis Loop** on real incidents.
69
+
70
+ **11 skills** in `kit/skills/`:
71
+ - `_shared-observability/glossary.md` — canonical bilingual vocabulary (PT-BR↔EN)
72
+ - `structured-events`, `distributed-tracing`, `opentelemetry-standard`, `core-analysis-loop` — foundationals
73
+ - `observability-driven-development` — the 4 pre-PR questions ("Does it do what I expected? Compare to previous version? Are users using? Anomalies emerge?")
74
+ - `event-based-slos`, `burn-rate-alerting` — SLO definition + predictive burn alerts
75
+ - `telemetry-sampling`, `telemetry-pipelines`, `observability-maturity-model` — scale + culture
76
+
77
+ **5 agents** in `kit/agents/`:
78
+ - `observability-instrumenter` — generates OTel + canonical attribute patches
79
+ - `incident-investigator` — Core Analysis Loop with persistent state in `.planning/investigations/`
80
+ - `slo-engineer` — generates `SLO.md` + SQL migrations to materialize SLI events
81
+ - `burn-rate-forecaster` — calculates burn rate, ETA exhaustion, alert config
82
+ - `omm-auditor` — scores 5 OMM capabilities (resilience, code quality, complexity, release cadence, user behavior)
83
+
84
+ **6 commands**:
85
+ - `/observabilidade <subcommand>` — single orchestrator (analog to `/supabase`) — dispatches to the 5 agents above with PT/EN synonyms
86
+ - `/instrumentar-fase` — generates `INSTRUMENTATION.md` per plan after `/planejar-fase`
87
+ - `/investigar-producao` — guided Core Analysis Loop with persistent state
88
+ - `/definir-slo` — creates SLO definition + SQL materialized view
89
+ - `/burn-rate-status` — table `[SLO | budget burned | ETA | action]`, also runnable in `/loop`
90
+ - `/auditar-observabilidade` — generates OMM-REPORT.md scored
91
+
92
+ **Quick start example:**
93
+ ```bash
94
+ # Define an SLO for a critical journey
95
+ /observabilidade slo "checkout"
96
+
97
+ # Investigate a production incident with Core Analysis Loop
98
+ /observabilidade investigar "checkout SLO burn rate = 8 às 14:32"
99
+
100
+ # Score project against Observability Maturity Model
101
+ /observabilidade omm
102
+ ```
103
+
66
104
  ---
67
105
 
68
106
  ## Prerequisites
@@ -0,0 +1,86 @@
1
+ ---
2
+ id: obs-agents-mcp-supabase
3
+ stage: pre-verify
4
+ blocking: true
5
+ description: Valida que agents observability que precisam de MCP Supabase declaram tools mcp__supabase__* no frontmatter (incident-investigator, slo-engineer, burn-rate-forecaster, omm-auditor).
6
+ ---
7
+
8
+ # Observability agents MCP Supabase declaration gate
9
+
10
+ **When to run:** pre-verify.
11
+
12
+ ## Check
13
+
14
+ ```bash
15
+ #!/usr/bin/env bash
16
+ # PT-BR: agents que usam MCP Supabase devem declarar tools mcp__supabase__* no frontmatter.
17
+ # Anti-pitfall: declaração ausente faz Claude Code não autorizar tool, agent falha em runtime.
18
+ set -e
19
+
20
+ VIOLATIONS=0
21
+
22
+ # PT-BR: agents que DEVEM declarar mcp__supabase__*
23
+ declare_required() {
24
+ local agent="$1"
25
+ local required_tools="$2" # tools separados por |
26
+ local file="kit/agents/$agent.md"
27
+
28
+ if [ ! -f "$file" ]; then
29
+ echo "FAIL: $file — agent ausente"
30
+ VIOLATIONS=$((VIOLATIONS + 1))
31
+ return
32
+ fi
33
+
34
+ # PT-BR: extrair frontmatter tools field (multi-line possível)
35
+ local in_frontmatter=0
36
+ local in_tools=0
37
+ local tools_block=""
38
+ while IFS= read -r line; do
39
+ if [ "$line" = "---" ]; then
40
+ if [ "$in_frontmatter" -eq 0 ]; then
41
+ in_frontmatter=1
42
+ else
43
+ break
44
+ fi
45
+ elif [ "$in_frontmatter" -eq 1 ]; then
46
+ tools_block="$tools_block $line"
47
+ fi
48
+ done < "$file"
49
+
50
+ local IFS='|'
51
+ for tool in $required_tools; do
52
+ if ! echo "$tools_block" | grep -qF "$tool"; then
53
+ echo "FAIL: $file — não declara '$tool' em frontmatter tools"
54
+ VIOLATIONS=$((VIOLATIONS + 1))
55
+ fi
56
+ done
57
+ }
58
+
59
+ # PT-BR: incident-investigator usa get_logs/execute_sql/get_advisors
60
+ declare_required "incident-investigator" "mcp__supabase__get_logs|mcp__supabase__execute_sql|mcp__supabase__get_advisors"
61
+
62
+ # PT-BR: slo-engineer usa execute_sql + apply_migration
63
+ declare_required "slo-engineer" "mcp__supabase__execute_sql|mcp__supabase__apply_migration"
64
+
65
+ # PT-BR: burn-rate-forecaster usa execute_sql
66
+ declare_required "burn-rate-forecaster" "mcp__supabase__execute_sql"
67
+
68
+ # PT-BR: omm-auditor usa execute_sql (queries SLI)
69
+ declare_required "omm-auditor" "mcp__supabase__execute_sql"
70
+
71
+ if [ "$VIOLATIONS" -eq 0 ]; then
72
+ echo "PASS: 4 agents observability declaram mcp__supabase__* corretamente"
73
+ exit 0
74
+ else
75
+ echo "FAIL: $VIOLATIONS violação(ões)"
76
+ exit 1
77
+ fi
78
+ ```
79
+
80
+ ## Why
81
+
82
+ Agents observability que aplicam Core Analysis Loop ou queries SLI dependem de `mcp__supabase__*`. Sem declaração no frontmatter `tools`, Claude Code não autoriza o tool em runtime e o agent falha (precedente: anti-pitfall identificado em v1.8 com supabase-* agents).
83
+
84
+ ## REQ
85
+
86
+ QA-02.
@@ -0,0 +1,76 @@
1
+ ---
2
+ id: obs-skills-frontmatter
3
+ stage: pre-verify
4
+ blocking: true
5
+ description: Valida que skills observability têm frontmatter completo (name + description ≤ 200 chars) e seções obrigatórias do template.
6
+ ---
7
+
8
+ # Observability skills frontmatter gate
9
+
10
+ **When to run:** pre-verify.
11
+
12
+ ## Check
13
+
14
+ ```bash
15
+ #!/usr/bin/env bash
16
+ # PT-BR: validar que cada skill em kit/skills/{structured-events,distributed-tracing,opentelemetry-standard,core-analysis-loop,observability-driven-development,event-based-slos,burn-rate-alerting,telemetry-sampling,telemetry-pipelines,observability-maturity-model}/SKILL.md
17
+ # tem frontmatter completo + seções obrigatórias.
18
+ # Portable bash 3.2+ (macOS default).
19
+ set -e
20
+
21
+ VIOLATIONS=0
22
+ SKILLS="structured-events distributed-tracing opentelemetry-standard core-analysis-loop observability-driven-development event-based-slos burn-rate-alerting telemetry-sampling telemetry-pipelines observability-maturity-model"
23
+
24
+ for skill in $SKILLS; do
25
+ file="kit/skills/$skill/SKILL.md"
26
+ if [ ! -f "$file" ]; then
27
+ echo "FAIL: $file — skill ausente"
28
+ VIOLATIONS=$((VIOLATIONS + 1))
29
+ continue
30
+ fi
31
+
32
+ # PT-BR: frontmatter name presente
33
+ if ! grep -qE '^name:' "$file"; then
34
+ echo "FAIL: $file — frontmatter 'name:' ausente"
35
+ VIOLATIONS=$((VIOLATIONS + 1))
36
+ fi
37
+
38
+ # PT-BR: frontmatter description presente
39
+ if ! grep -qE '^description:' "$file"; then
40
+ echo "FAIL: $file — frontmatter 'description:' ausente"
41
+ VIOLATIONS=$((VIOLATIONS + 1))
42
+ else
43
+ desc=$(grep -E '^description:' "$file" | head -1 | sed 's/description: //')
44
+ len=${#desc}
45
+ if [ "$len" -gt 200 ]; then
46
+ echo "FAIL: $file — description=$len chars (limite 200, anti-pitfall A2)"
47
+ VIOLATIONS=$((VIOLATIONS + 1))
48
+ fi
49
+ fi
50
+
51
+ # PT-BR: 4+ seções H2 (Quando usar, Regras absolutas, Patterns canônicos, Anti-patterns OU Verificação)
52
+ h2_count=$(grep -cE '^## ' "$file")
53
+ if [ "$h2_count" -lt 4 ]; then
54
+ echo "FAIL: $file — só $h2_count seções H2 (mínimo 4 — Quando usar, Regras absolutas, Patterns canônicos, Anti-patterns/Verificação)"
55
+ VIOLATIONS=$((VIOLATIONS + 1))
56
+ fi
57
+ done
58
+
59
+ if [ "$VIOLATIONS" -eq 0 ]; then
60
+ echo "PASS: 10 skills observability com frontmatter completo + 4+ seções H2"
61
+ exit 0
62
+ else
63
+ echo "FAIL: $VIOLATIONS violação(ões)"
64
+ exit 1
65
+ fi
66
+ ```
67
+
68
+ ## Why
69
+
70
+ - Skills sem `description` não aparecem em `listKit` (LLM não acha o trigger)
71
+ - `description > 200 chars` infla CLAUDE.md desnecessariamente (anti-pitfall A2)
72
+ - Skills sem template fixo geram outputs inconsistentes — gate força padrão.
73
+
74
+ ## REQ
75
+
76
+ QA-01.
@@ -0,0 +1,83 @@
1
+ ---
2
+ id: omm-no-regression
3
+ stage: pre-conclude
4
+ blocking: false
5
+ description: Valida que nenhuma das 5 capacidades OMM regrediu vs marco anterior. Rodável em /concluir-marco. Não-bloqueante (warn) por default; configurável via workflow.omm_no_regression.
6
+ ---
7
+
8
+ # OMM no-regression gate
9
+
10
+ **When to run:** pre-conclude (antes de `/concluir-marco` arquivar marco).
11
+
12
+ ## Check
13
+
14
+ ```bash
15
+ #!/usr/bin/env bash
16
+ # PT-BR: validar que OMM-REPORT.md atual não tem capacidade regredida vs marco anterior.
17
+ # Estratégia: comparar scores no OMM-REPORT.md atual vs último arquivado.
18
+ set -e
19
+
20
+ CURRENT=".planning/OMM-REPORT.md"
21
+
22
+ if [ ! -f "$CURRENT" ]; then
23
+ echo "WARN: $CURRENT ausente — rodar /auditar-observabilidade primeiro. Pulando gate."
24
+ exit 0
25
+ fi
26
+
27
+ # PT-BR: encontrar OMM-REPORT.md anterior em milestones arquivados
28
+ PREVIOUS=$(find .planning/milestones -name "OMM-REPORT.md" -type f 2>/dev/null | sort -r | head -1)
29
+
30
+ if [ -z "$PREVIOUS" ] || [ ! -f "$PREVIOUS" ]; then
31
+ echo "INFO: sem OMM-REPORT anterior arquivado (primeiro marco com OMM). Pulando regression check."
32
+ exit 0
33
+ fi
34
+
35
+ # PT-BR: extrair scores do OMM-REPORT.md atual e anterior
36
+ # Formato esperado: "| 1 | Resiliência | 3 | ... |"
37
+
38
+ REGRESSIONS=0
39
+ for cap in 1 2 3 4 5; do
40
+ current_score=$(grep -E "^\| $cap \| " "$CURRENT" 2>/dev/null | awk -F'|' '{print $4}' | tr -d ' ' | head -1)
41
+ previous_score=$(grep -E "^\| $cap \| " "$PREVIOUS" 2>/dev/null | awk -F'|' '{print $4}' | tr -d ' ' | head -1)
42
+
43
+ if [ -z "$current_score" ] || [ -z "$previous_score" ]; then
44
+ continue
45
+ fi
46
+
47
+ if [ "$current_score" -lt "$previous_score" ]; then
48
+ cap_name=$(grep -E "^\| $cap \| " "$CURRENT" | awk -F'|' '{print $3}' | xargs)
49
+ echo "REGRESSION: Capacidade $cap ($cap_name) regrediu de $previous_score → $current_score"
50
+ REGRESSIONS=$((REGRESSIONS + 1))
51
+ fi
52
+ done
53
+
54
+ if [ "$REGRESSIONS" -eq 0 ]; then
55
+ echo "PASS: nenhuma das 5 capacidades OMM regrediu vs $PREVIOUS"
56
+ exit 0
57
+ else
58
+ echo "WARN: $REGRESSIONS capacidade(s) regredida(s)"
59
+ # PT-BR: blocking=false por default. Para tornar bloqueante:
60
+ # workflow.omm_no_regression=true
61
+ if [ "$(node ./.claude/framework/bin/tools.cjs config-get workflow.omm_no_regression 2>/dev/null || echo false)" = "true" ]; then
62
+ exit 1
63
+ fi
64
+ exit 0
65
+ fi
66
+ ```
67
+
68
+ ## Why
69
+
70
+ OMM regression alerta o time que algo deteriorou apesar do esforço do marco. Sem este gate, regressions silenciam e accumulate como tech debt invisível.
71
+
72
+ Default não-bloqueante para evitar ruído inicial; flag `workflow.omm_no_regression=true` opt-in quando time confiante.
73
+
74
+ ## REQ
75
+
76
+ QA-03 + INT-FW-04 + INT-FW-05.
77
+
78
+ ## Configuração
79
+
80
+ ```bash
81
+ # PT-BR: tornar bloqueante (recomendado depois de 2-3 marcos consecutivos sem regression)
82
+ node ./.claude/framework/bin/tools.cjs config-set workflow.omm_no_regression true
83
+ ```
@@ -14,41 +14,43 @@ description: Valida que skills supabase-* contêm strings obrigatórias verbatim
14
14
  ```bash
15
15
  #!/usr/bin/env bash
16
16
  # PT-BR: cada skill deve incluir strings obrigatórias verbatim para prevenir anti-patterns
17
+ # Portable: bash 3.2+ (macOS default), sem associative arrays
17
18
  set -e
18
19
 
19
20
  VIOLATIONS=0
20
21
 
21
- # PT-BR: mapeamento skill → must-include strings (delimitadas por |)
22
- declare -A MUST_INCLUDE
23
- MUST_INCLUDE["supabase-rls-policies"]="(select auth.uid())|user_metadata|TO authenticated"
24
- MUST_INCLUDE["supabase-database-functions"]="set search_path = ''|SECURITY INVOKER"
25
- MUST_INCLUDE["supabase-auth-ssr"]="getAll|setAll|auth-helpers-nextjs|@supabase/ssr"
26
- MUST_INCLUDE["supabase-realtime"]="broadcast|private: true|realtime.broadcast_changes|removeChannel"
27
- MUST_INCLUDE["supabase-edge-functions"]="npm:|jsr:|Deno.serve|EdgeRuntime.waitUntil|/tmp"
28
- MUST_INCLUDE["supabase-declarative-schema"]="supabase/schemas/|supabase stop|supabase db diff -f"
29
- MUST_INCLUDE["supabase-migrations"]="YYYYMMDDHHmmss|RLS|granular"
30
- MUST_INCLUDE["supabase-postgres-style"]="snake_case|ISO 8601|lowercase"
31
- MUST_INCLUDE["supabase-storage"]="signed URL|storage.objects|multi-tenant"
32
- MUST_INCLUDE["supabase-pgvector-rag"]="HNSW|IVFFlat|<=>|RAG with permissions"
33
- MUST_INCLUDE["supabase-cron-queues"]="pg_cron|pgmq|pg_net"
22
+ check_skill() {
23
+ local skill="$1"
24
+ local required="$2" # strings separadas por |
25
+ local file="kit/skills/$skill/SKILL.md"
34
26
 
35
- for skill in "${!MUST_INCLUDE[@]}"; do
36
- file="kit/skills/$skill/SKILL.md"
37
27
  if [ ! -f "$file" ]; then
38
28
  echo "FAIL: $file — skill ausente"
39
29
  VIOLATIONS=$((VIOLATIONS + 1))
40
- continue
30
+ return
41
31
  fi
42
32
 
43
33
  # PT-BR: testa cada string (separada por |)
44
- IFS='|' read -ra REQUIRED <<< "${MUST_INCLUDE[$skill]}"
45
- for str in "${REQUIRED[@]}"; do
34
+ local IFS='|'
35
+ for str in $required; do
46
36
  if ! grep -qF "$str" "$file"; then
47
37
  echo "FAIL: $file — must-include ausente: '$str'"
48
38
  VIOLATIONS=$((VIOLATIONS + 1))
49
39
  fi
50
40
  done
51
- done
41
+ }
42
+
43
+ check_skill "supabase-rls-policies" "(select auth.uid())|user_metadata|TO authenticated"
44
+ check_skill "supabase-database-functions" "set search_path = ''|SECURITY INVOKER"
45
+ check_skill "supabase-auth-ssr" "getAll|setAll|auth-helpers-nextjs|@supabase/ssr"
46
+ check_skill "supabase-realtime" "broadcast|private: true|realtime.broadcast_changes|removeChannel"
47
+ check_skill "supabase-edge-functions" "npm:|jsr:|Deno.serve|EdgeRuntime.waitUntil|/tmp"
48
+ check_skill "supabase-declarative-schema" "supabase/schemas/|supabase stop|supabase db diff -f"
49
+ check_skill "supabase-migrations" "YYYYMMDDHHmmss|RLS|granular"
50
+ check_skill "supabase-postgres-style" "snake_case|ISO 8601|lowercase"
51
+ check_skill "supabase-storage" "signed URL|storage.objects|multi-tenant"
52
+ check_skill "supabase-pgvector-rag" "HNSW|IVFFlat|<=>|RAG with permissions"
53
+ check_skill "supabase-cron-queues" "pg_cron|pgmq|pg_net"
52
54
 
53
55
  if [ "$VIOLATIONS" -gt 0 ]; then
54
56
  echo "Total violations: $VIOLATIONS"
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: burn-rate-forecaster
3
+ description: Calcula burn rate atual + ETA exhaustão + alert config (page vs ticket) — usa lookahead/baseline windows fator 4×, mcp__supabase__execute_sql para queries SLI.
4
+ tools: Read, Bash, Grep, mcp__supabase__execute_sql, mcp__supabase__list_tables
5
+ color: orange
6
+ ---
7
+
8
+ Você é o forecaster de burn rate. Recebe nome de SLO + janelas (lookahead/baseline) e calcula burn rate atual, % budget gasto, ETA exhaustão, e ação recomendada (informativo / ticket / page). Você consulta a skill [`burn-rate-alerting`](../skills/burn-rate-alerting/SKILL.md) — conhecimento autoritativo sobre fórmulas de extrapolação.
9
+
10
+ ## Compatibilidade
11
+
12
+ | IDE | Tier | Capability |
13
+ |---|---|---|
14
+ | Claude Code (com Supabase MCP) | **Full** | Queries live em SLI views via execute_sql |
15
+ | Cursor (com Supabase MCP) | **Full** | Idem |
16
+ | Codex | **Partial** | Apresenta SQL ao user, parsea resultado colado |
17
+ | Gemini CLI | **Partial** | Idem |
18
+ | Windsurf, Antigravity, Copilot, Trae | **Offline-only** | SQL como text, sem execução |
19
+
20
+ ## Por que existe
21
+
22
+ Burn rate calculado errado é pior que não calculado — false positives geram alert fatigue, false negatives perdem incidents. Este agent aplica fórmula canônica do livro Cap 13 (lookahead ≤ 4× baseline, target burn 14.4× para page, 1× para ticket) consistentemente.
23
+
24
+ ## Inputs esperados (do caller)
25
+
26
+ - `slo_name`: nome do SLO (ex: `checkout_success`) — view materializada deve existir em `obs.sli_<slo_name>`
27
+ - (Opcional) `lookahead`: `4h` (default short-term) | `3d` (long-term) | custom
28
+ - (Opcional) `baseline`: `1h` (default short-term) | `18h` (long-term) | custom
29
+ - (Opcional) `target`: target % do SLO (default: lê de `.planning/slos/<slo_name>.md`)
30
+
31
+ ## Passos
32
+
33
+ ### Step 0 — Preflight
34
+
35
+ 1. Verificar que `.planning/slos/<slo_name>.md` existe — extrair `target` e `window`.
36
+ 2. Verificar que `obs.sli_<slo_name>` existe via `mcp__supabase__list_tables --schemas=['obs']`.
37
+
38
+ Se algo faltando, abortar com mensagem clara: "SLO {name} não definido. Rode `/definir-slo {feature}` primeiro."
39
+
40
+ ### Step 1 — Validar lookahead ≤ 4× baseline
41
+
42
+ ```text
43
+ if lookahead_seconds > 4 × baseline_seconds:
44
+ warn "lookahead 4h é confiável apenas com baseline ≥ 1h. Sua config: lookahead=Xh, baseline=Yh — fora da regra 4×."
45
+ Sugerir ajustar baseline ou usar context-aware burn rate.
46
+ ```
47
+
48
+ ### Step 2 — Query burn rate atual (baseline window)
49
+
50
+ ```sql
51
+ -- PT-BR: burn rate em janela baseline
52
+ with baseline as (
53
+ select
54
+ sum(good) as good,
55
+ sum(bad) as bad,
56
+ sum(total) as total
57
+ from obs.sli_{slo_name}
58
+ where bucket > now() - interval '{baseline}'
59
+ )
60
+ select
61
+ total as events_in_baseline,
62
+ bad as bad_in_baseline,
63
+ bad::float / nullif(total, 0) as error_rate,
64
+ (bad::float / nullif(total, 0)) / (1 - {target_decimal}) as burn_rate
65
+ from baseline;
66
+ ```
67
+
68
+ Invoke via `mcp__supabase__execute_sql` (Full) ou apresentar ao user (Offline).
69
+
70
+ ### Step 3 — Query budget gasto e remanescente (window inteira)
71
+
72
+ ```sql
73
+ -- PT-BR: budget gasto e remaining em window inteira do SLO (default 30d)
74
+ with full_window as (
75
+ select
76
+ sum(bad) as burned,
77
+ sum(total) as total_events
78
+ from obs.sli_{slo_name}
79
+ where bucket > now() - interval '30 days'
80
+ )
81
+ select
82
+ (1 - {target_decimal}) * total_events as budget_events,
83
+ burned,
84
+ (1 - {target_decimal}) * total_events - burned as remaining_events,
85
+ 100.0 * burned / nullif((1 - {target_decimal}) * total_events, 0) as budget_burned_pct
86
+ from full_window;
87
+ ```
88
+
89
+ ### Step 4 — Predictive forecast — ETA exhaustão
90
+
91
+ ```text
92
+ projected_remaining_at_lookahead = remaining_events_now - (burn_per_baseline × lookahead/baseline)
93
+
94
+ ETA seconds = remaining_events_now / (burn_per_baseline / baseline_seconds)
95
+ ETA hours = ETA seconds / 3600
96
+ ```
97
+
98
+ ### Step 5 — Determinar status
99
+
100
+ ```text
101
+ if burn_rate >= 14.4 (sustained 4h+):
102
+ status = "PAGE"
103
+ action = "Page on-call imediato — invocar `/investigar-producao`"
104
+ elif burn_rate >= 1.0:
105
+ status = "TICKET"
106
+ action = "Criar ticket de eng — investigar antes do budget esgotar (ETA={ETA}h)"
107
+ elif budget_burned_pct >= 80:
108
+ status = "WARN"
109
+ action = "Budget acima 80% — proteger contra deploys arriscados"
110
+ else:
111
+ status = "OK"
112
+ action = "Informativo apenas"
113
+ ```
114
+
115
+ ### Step 6 — Output
116
+
117
+ Tabela canônica:
118
+
119
+ ```
120
+ ═══════════════════════════════════════════════════════════
121
+ BURN-RATE-FORECASTER · {slo_name}
122
+ ═══════════════════════════════════════════════════════════
123
+
124
+ ## Snapshot — {timestamp}
125
+
126
+ | Metric | Value |
127
+ |---|---|
128
+ | SLO target | {target}% |
129
+ | Window | 30d sliding |
130
+ | Budget total | {budget_events} events |
131
+ | Budget gasto | {burned_events} events ({burned_pct}%) |
132
+ | Budget remaining | {remaining_events} events ({remaining_pct}%) |
133
+ | Baseline ({baseline}) error rate | {error_rate}% |
134
+ | Burn rate atual | {burn_rate}× |
135
+ | ETA exhaustão | {ETA} (se burn_rate sustained) |
136
+
137
+ ## Status: **{status}**
138
+
139
+ {action}
140
+
141
+ ## Comparação — burn rate threshold
142
+
143
+ | Threshold | Burn rate | Action |
144
+ |---|---|---|
145
+ | Page on-call | ≥ 14.4× | acordar engineer |
146
+ | Ticket | ≥ 1.0× | abrir Jira/Linear |
147
+ | Warn | budget > 80% gasto | rever cadência de deploy |
148
+
149
+ {Se status = PAGE ou TICKET:}
150
+ ## Próximos passos
151
+ 1. `/investigar-producao "{slo_name} burn rate = {burn_rate}× às {timestamp}"`
152
+ 2. (Após root cause identificada) Decidir: rollback / hotfix / mitigação parcial
153
+ 3. Atualizar runbook do SLO com lessons learned
154
+ ```
155
+
156
+ ## Quando NÃO invocar
157
+
158
+ - SLO sem materialized view — invoke `slo-engineer` primeiro
159
+ - Métrica informativa sem target — use dashboard
160
+ - Verificação ad hoc rápida — query direto via `mcp__supabase__execute_sql` se já sabe a fórmula