@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.
- package/README.md +39 -1
- package/gates/obs-agents-mcp-supabase.md +86 -0
- package/gates/obs-skills-frontmatter.md +76 -0
- package/gates/omm-no-regression.md +83 -0
- package/gates/skill-must-include.md +21 -19
- package/kit/agents/burn-rate-forecaster.md +160 -0
- package/kit/agents/incident-investigator.md +245 -0
- package/kit/agents/observability-instrumenter.md +200 -0
- package/kit/agents/omm-auditor.md +199 -0
- package/kit/agents/slo-engineer.md +224 -0
- package/kit/agents/supabase-architect.md +13 -0
- package/kit/agents/supabase-auth-bootstrapper.md +17 -0
- package/kit/agents/supabase-edge-fn-writer.md +22 -0
- package/kit/agents/supabase-migration-writer.md +18 -0
- package/kit/agents/supabase-realtime-implementer.md +23 -0
- package/kit/agents/supabase-rls-writer.md +17 -0
- package/kit/agents/supabase-storage-implementer.md +18 -0
- package/kit/commands/auditar-marco.md +22 -1
- package/kit/commands/auditar-observabilidade.md +103 -0
- package/kit/commands/burn-rate-status.md +140 -0
- package/kit/commands/concluir-marco.md +19 -1
- package/kit/commands/definir-slo.md +108 -0
- package/kit/commands/discutir-fase.md +26 -0
- package/kit/commands/forense.md +20 -1
- package/kit/commands/instrumentar-fase.md +200 -0
- package/kit/commands/investigar-producao.md +162 -0
- package/kit/commands/observabilidade.md +116 -0
- package/kit/commands/planejar-fase.md +20 -0
- package/kit/commands/verificar-trabalho.md +26 -0
- package/kit/skills/_shared-observability/glossary.md +396 -0
- package/kit/skills/burn-rate-alerting/SKILL.md +258 -0
- package/kit/skills/core-analysis-loop/SKILL.md +352 -0
- package/kit/skills/distributed-tracing/SKILL.md +362 -0
- package/kit/skills/event-based-slos/SKILL.md +274 -0
- package/kit/skills/observability-driven-development/SKILL.md +315 -0
- package/kit/skills/observability-maturity-model/SKILL.md +222 -0
- package/kit/skills/opentelemetry-standard/SKILL.md +351 -0
- package/kit/skills/structured-events/SKILL.md +265 -0
- package/kit/skills/telemetry-pipelines/SKILL.md +259 -0
- package/kit/skills/telemetry-sampling/SKILL.md +256 -0
- 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,
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
30
|
+
return
|
|
41
31
|
fi
|
|
42
32
|
|
|
43
33
|
# PT-BR: testa cada string (separada por |)
|
|
44
|
-
IFS='|'
|
|
45
|
-
for str in
|
|
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
|
-
|
|
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
|