---
name: falcao-default
description: Padrões universais pra TODO projeto do Falcão — workflow Git/GitHub (branches, commits, PRs, CI/CD), estrutura de documentação (CLAUDE.md raiz + agent.md por pasta), e regras de operação da LLM. Ative em qualquer trabalho dentro de `~/Projects/falcao-*` ou quando o pedido envolver "subir feature", "criar branch", "fazer PR", "merge", "deploy", "atualizar agent.md", "navegação em pastas". Esta skill é o **playbook base** — outras skills (`falcao-hetzner`, `falcao-launcher`, etc.) herdam esses padrões.
---

# falcao-default — playbook universal de projeto

Falcão tem **vários projetos** (`falcao-financas`, `falcao-tcc`, `falcao-launcher`, `falcao-questoes`, Sonar, SIGOF, etc.) e quer que **todos sigam os mesmos padrões** de Git, deploy e documentação. Essa skill é a fonte de verdade. Cada projeto pode ter especificidades em sua skill própria, mas o **default é este**.

> **Convenção de leitura:** quando esta skill mencionar **`<prod>`**, leia como **a branch de produção daquele repo** — pode ser `main` (padrão moderno) OU `master` (legacy). Falcão usa o que cada repo já tinha; **não renomeie sem pedido explícito**. Verificar com `gh repo view --json defaultBranchRef`.

---

## 1. Git workflow

### Branches

Cada projeto tem **3 tipos de branch**:

| Branch | Propósito | Quem mexe |
|---|---|---|
| **`<prod>`** (`main` ou `master`) | Produção. Sempre estável. **Deploy automático em merge.** | Ninguém pusha direto — só via PR de `development` |
| **`development`** | Integração. Onde features se juntam. **CI roda testes aqui.** | Branches de feature → PR aqui |
| **`feature/*`, `fix/*`, `chore/*`, `docs/*`, `refactor/*`** | Trabalho real. Curtas, focadas. | Onde a LLM escreve código |

**Regra de ouro:** todo trabalho começa numa branch nova **a partir de `development`**, não da `<prod>`.

```
<prod> ◄─── PR (manual, sob pedido) ◄─── development ◄─── PR ◄─── feature/X
```

### Naming de branch

| Tipo | Formato | Exemplo |
|---|---|---|
| Feature nova | `feature/<descrição-curta>` | `feature/dashboard-saldo` |
| Bug fix | `fix/<descrição-curta>` | `fix/cors-vercel` |
| Manutenção | `chore/<descrição-curta>` | `chore/bump-deps` |
| Documentação | `docs/<descrição-curta>` | `docs/api-readme` |
| Refactor | `refactor/<descrição-curta>` | `refactor/services-categorizer` |
| Hotfix urgente | `hotfix/<descrição-curta>` | `hotfix/auth-broken` (sai da `<prod>`, vai pra `<prod>` direto) |

Tudo em **kebab-case minúsculo**. Sem acentos, sem espaços.

### Conventional Commits

Toda mensagem de commit segue **Conventional Commits**:

```
<tipo>(<escopo opcional>): <descrição curta no infinitivo>

[corpo opcional explicando o porquê, não o quê]

[footer opcional, refs/closes #N]
```

**Tipos válidos:**
- `feat:` nova funcionalidade
- `fix:` correção de bug
- `chore:` manutenção (deps, config, build)
- `docs:` só documentação
- `refactor:` refactor sem mudança de comportamento
- `test:` adiciona/ajusta testes
- `style:` formatação (Biome, Prettier, sem mudança de lógica)
- `ci:` mudanças em pipeline CI/CD
- `perf:` melhoria de performance

**Exemplos bons:**
```
feat(dashboard): adiciona card de saldo total
fix(cors): aceita URL da Vercel em prod
chore: atualiza fastapi pra 0.115.4
docs(api): documenta endpoint /pierre/sync
```

**Exemplos ruins:**
```
update          # sem tipo, sem descrição
fix bug         # genérico demais
WIP             # nunca commit WIP — squash antes de PR
melhorias       # vago
```

### PRs

| Regra | Por quê |
|---|---|
| **Sempre** abrir PR pra mergear em `development` ou `<prod>` | Auditoria, CI roda, histórico claro |
| Título do PR = título do commit principal (Conventional Commits) | Histórico legível |
| Corpo do PR descreve **o que** mudou e **por quê** | Próximo dev (humano ou LLM) entende sem ler diff todo |
| **Squash merge** sempre | Mantém `<prod>`/`development` com histórico linear |
| Branch deletada após merge | Repo limpo (exceto `development`, que vive sempre) |

### A LLM (Claude) faz merge?

**SIM, mas SÓ quando o Falcão pede explicitamente.** Não é automático ao fim de uma feature.

**Pedidos que disparam merge na `<prod>`:**
- "manda pra produção"
- "faz o merge na main" / "faz o merge na master"
- "deploya isso"
- "sobe pra prod"
- "subir essa feature pra produção"

**Pedidos que NÃO disparam merge na `<prod>` (só param em `development`):**
- "termina a feature"
- "faz o PR"
- "manda pra development"

**Sempre confirmar antes** se houver dúvida — merge na `<prod>` é semi-irreversível (deploya em produção).

### CI/CD

**`development`:** roda testes (lint, unit, integration). Bloqueia merge se falhar.

**`<prod>`:** ao mergear, dispara deploy em duas frentes — backend e frontend — independentes mas em paralelo. **Cada uma tem seu canal**, não tente unificar num pipeline só.

#### Backend (VM Hetzner) — GitHub Actions

Ao mergear em `<prod>`:
1. GitHub Actions builda imagem Docker
2. SSH na VM Hetzner (ver skill `falcao-hetzner`)
3. `cd /opt/apps/<projeto> && git pull && docker compose up -d --build`
4. Healthcheck pós-deploy
5. Notifica resultado

Template de workflow em `~/.claude/skills/falcao-default/templates/deploy.yml` (criar quando primeiro projeto for ter CI/CD).

#### Frontend (Vercel) — integração GitHub nativa

**Não usar GitHub Actions pro frontend.** A Vercel tem integração GitHub nativa que cobre todo o ciclo melhor que Actions:

- Push em `<prod>` → **production deploy** automático (1-2 min)
- Push em **qualquer outra branch** (`development`, `feature/*`, ...) → **preview URL** única
- PR aberto → comment automático com a preview URL
- Rollback de produção em 1-click pelo dashboard

Setup uma vez por projeto:
1. Criar projeto Vercel: `vercel link --yes --project=<nome>`
2. Conectar repo: `printf "y\n" | vercel git connect https://github.com/Falkzera/<projeto>` (auto-confirma o prompt)
3. **Validar Production Branch via API** (default da Vercel é `main` — corrigir se o repo usa `master`):
   ```bash
   PROJECT_ID=$(jq -r '.projectId' .vercel/project.json)
   ORG_ID=$(jq -r '.orgId' .vercel/project.json)
   VERCEL_TOKEN=$(jq -r '.token' ~/.config/vercel/auth.json 2>/dev/null || jq -r '.token' ~/.local/share/com.vercel.cli/auth.json)
   curl -sS -H "Authorization: Bearer $VERCEL_TOKEN" \
     "https://api.vercel.com/v10/projects/$PROJECT_ID?teamId=$ORG_ID" \
     | jq '.link.productionBranch'
   ```
   Se retornar `"main"` mas o repo usa `master`, ajustar pelo dashboard (Settings → Git → Production Branch).

**Gotcha do `.env` local poluindo build:** Vite resolve `import.meta.env.VITE_*` em build time. Se o `.env` local tiver, por exemplo, `VITE_API_BASE_URL=http://localhost:8000/api` e o build for feito local + enviado via `vercel --prod` (em vez do Git push automático), a Vercel sobe o bundle com `localhost:8000` hardcoded — quebrando produção em silêncio.

Regra: **builds de produção SEMPRE saem do Git push em `<prod>`**, nunca de `vercel --prod` local. Isso garante que a Vercel use as env vars de Production que ela mesma controla, ignorando o `.env` da máquina do dev.

Mitigações no código pra reduzir a explosão se alguém ainda fizer build local:
- Em vez de `VITE_API_BASE_URL` ser obrigatória, deixar **opcional com fallback condicional**:
  ```ts
  const BASE_URL =
    import.meta.env.VITE_API_BASE_URL ??
    (import.meta.env.DEV ? "http://localhost:8000/api" : "https://<prod>.duckdns.org/api");
  ```
- Manter `.env.example` com a linha **comentada**, deixando claro que é override só pra casos especiais (ex: dev contra backend remoto).

**Como confirmar que o auto-deploy está vivo:** ao pushar uma branch qualquer pela primeira vez, abrir o painel da Vercel ou rodar `vercel ls` — uma preview URL nova aparece em ~30s. Se não aparece, a integração caiu (raro) ou o push não chegou no remote.

### Resync de `development` após cada release

**Problema clássico:** após mergear `development → <prod>` via **squash**, o GitHub gera um commit novo em `<prod>` com hash diferente do squash que foi feito em `development`. Resultado: `<prod>` e `development` têm o mesmo conteúdo lógico mas histórico divergente. A próxima feature, ao tentar PR `development → <prod>`, vai dar **conflito de "add/add"** mesmo sem mudança real.

**Sintoma:** `gh pr view <N> --json mergeStateStatus` retorna `DIRTY` / `CONFLICTING` em PRs entre branches que já estão sincronizadas em conteúdo.

**Solução:** após **cada** merge `development → <prod>`, **sempre** resync local:

```bash
git checkout development
git fetch origin
git merge origin/<prod> --no-edit
# Se aparecer conflito (típico no add/add), manter versão de development:
git checkout --ours <arquivo-conflitante>
git add <arquivo-conflitante>
git commit --no-edit
git push origin development
```

Esse merge "vazio" alinha o histórico sem alterar conteúdo. Próximo PR fica clean.

**Como evitar:** usar `--ff-only` ao mergear `development → <prod>` quando possível. Mas como squash é regra, esse resync passa a fazer parte do ritual pós-release.

### Setup inicial em repo legado (com commits não pushados)

Se ao implantar este workflow num repo já existente tiver **commits locais ahead da `<prod>` ainda não pushados** (verificar com `git log origin/<prod>..HEAD`), **NÃO crie 25 PRs retroativos**. Trate como exceção única:

1. **Push direto** dos commits ahead pra `<prod>` (último push direto que esse repo vai ter)
2. Cria `development` a partir da `<prod>` atualizada e empurra
3. **Aí sim** configurar branch protection (passo seguinte)
4. **Daí em diante**, todo trabalho passa pelo fluxo `feature/* → development → <prod>`

Justificativa: branch protection bloqueia push direto, então se configurar antes, os commits ahead ficam presos local sem caminho razoável de subir. Tratar histórico legítimo retroativo como PRs é teatro — só atrasa.

### Branch protection (configurar uma vez por repo)

Toda repo de projeto tem proteções na `<prod>`:

- ✅ Requer PR antes de merge (não permite push direto)
- ✅ Bloqueia force push
- ✅ Bloqueia delete da branch
- ✅ Aplica regras pra admins também (`enforce_admins: true`)
- ⚠️ NÃO requer aprovação (Falcão é solo dev — auto-merge OK)
- ⚠️ Requer status checks (CI) passar quando CI estiver configurado

Setup via `gh` CLI (substituir `<prod>` pelo nome real, `main` ou `master`):
```bash
gh api -X PUT repos/Falkzera/<projeto>/branches/<prod>/protection \
  --input - <<EOF
{
  "required_status_checks": null,
  "enforce_admins": true,
  "required_pull_request_reviews": {
    "dismiss_stale_reviews": false,
    "require_code_owner_reviews": false,
    "required_approving_review_count": 0
  },
  "restrictions": null,
  "allow_force_pushes": false,
  "allow_deletions": false
}
EOF
```

### Workflow completo passo a passo

Quando Falcão pede uma feature:

1. `git checkout development && git pull`
2. `git checkout -b feature/<nome>`
3. Implementar mudanças
4. `git add <arquivos> && git commit -m "feat: ..."` (Conventional Commits)
5. `git push -u origin feature/<nome>`
6. `gh pr create --base development --title "feat: ..." --body "..."`
7. Aguardar CI passar (quando configurado)
8. `gh pr merge --squash --delete-branch`

Quando Falcão pede pra subir pra produção:

1. `gh pr create --base <prod> --head development --title "release: <descrição>" --body "<changelog das features>"`
2. `gh pr merge --squash --delete-branch=false` (mantém `development` viva)
3. Aguardar GitHub Actions deployar
4. Validar healthcheck no endpoint público

---

## 2. Documentação de projeto

### CLAUDE.md (raiz do repo)

Todo projeto tem `CLAUDE.md` na raiz. **Este arquivo é a primeira coisa que outra LLM lê.**

Conteúdo obrigatório:
- **O que é o projeto** (1-2 parágrafos)
- **Stack** (tabela com versões reais)
- **Comandos** (npm/pnpm scripts, dev, build, test)
- **Estrutura de pastas** (top level)
- **Regras de código** (linting, padrões, convenções)
- **Regra do agent.md** (referência abaixo)
- **Pendências/fases** (roadmap curto)
- **Link pra skills relevantes** (ex: "Ver `falcao-default` pro workflow Git e `falcao-hetzner` pro deploy")

Estilo: técnico, denso, sem encheção. Outra LLM precisa ler em 30s e entender o terreno.

### agent.md (em cada pasta)

**Toda pasta com código** (não só raiz) tem um `agent.md`. **Excluindo:**
- `node_modules/`, `.venv/`, `dist/`, `build/`, `.next/`, `target/`
- Pastas geradas (cache, build artifacts)
- Pastas com 1-2 arquivos triviais (ex: `public/` com só favicon)

Template padrão:

```markdown
# <nome-da-pasta> — agent.md

## Propósito
<1 parágrafo: pra que essa pasta existe nesse projeto>

## Arquivos
- `arquivo1.ts` — <o que faz, em 1 linha>
- `arquivo2.ts` — <o que faz, em 1 linha>
- `subpasta/` — <propósito da subpasta, link pro agent.md dela>

## Padrões
<convenções específicas dessa pasta — não duplicar do CLAUDE.md root>
<exemplos: "todo hook retorna { data, isLoading, error }">

## Decisões recentes
<bullet list de decisões arquiteturais, não commits — só o que outra LLM precisa saber>
- <data ISO>: <decisão e motivo>

## Pendências conhecidas
- <bug ou TODO>
- <refactor planejado>
```

Mantém **curto**: 30-100 linhas. Se passar de 150, é sinal de que parte deveria virar arquivo separado ou ir pro CLAUDE.md.

### Quando atualizar agent.md

A LLM **deve atualizar agent.md** sempre que:

1. **Entrar numa pasta pra trabalhar** — leia o agent.md (se existir) antes de mexer; se não existir, **crie**
2. **Adicionar/remover/renomear arquivo** — atualizar a lista
3. **Mudar o propósito** de algum arquivo significativamente
4. **Tomar decisão arquitetural** — adicionar em "Decisões recentes" com data
5. **Resolver/criar pendência** — atualizar "Pendências conhecidas"

A LLM NÃO atualiza agent.md quando:
- Mudança trivial (typo, formatação, comentário)
- Bump de versão de dependência sem mudança de API
- Refactor interno que não afeta interface da pasta

### Como a regra do agent.md aparece no CLAUDE.md

Em todo `CLAUDE.md` raiz, incluir esta seção (literal):

```markdown
## Documentação por pasta (agent.md)

Toda pasta com código deste projeto tem um `agent.md` que outra LLM lê antes de mexer ali. Ver regras completas em `~/.claude/skills/falcao-default/SKILL.md` (seção "agent.md").

Resumo: ao entrar numa pasta pra trabalhar, leia o `agent.md`; ao sair com mudanças significativas, atualize-o.
```

---

## 3. Boas práticas adicionais

### Estrutura de docs (3 níveis)

| Arquivo | Audiência | Conteúdo |
|---|---|---|
| `README.md` | Humano externo (GitHub) | Pitch, screenshot, instalação, link pra docs |
| `CLAUDE.md` | LLM trabalhando no repo | Stack, regras, comandos, gotchas |
| `agent.md` (por pasta) | LLM trabalhando numa pasta | Propósito, arquivos, decisões locais |

**Não duplicar.** README diz **o que é**, CLAUDE.md diz **como trabalhar**, agent.md diz **o que tem aqui**.

### Secrets

- `.env` **NUNCA** commit — sempre em `.gitignore`
- `.env.example` **sempre** commitado, com chaves vazias ou exemplos
- Secrets de produção: GitHub Secrets (CI/CD) e arquivo `.env` direto na VM (chmod 600)
- Nunca colar secrets em mensagens, logs, comentários

### Versionamento

- Usar **tags semver** ao deployar pra produção: `v0.1.0`, `v0.2.0`, etc.
- Tag criada **automaticamente** pelo workflow de deploy quando merge cair na `<prod>`
- `CHANGELOG.md` opcional mas recomendado pra projetos com vários users (Sonar, SIGOF)

### Issue tracking

- Issues no GitHub do projeto são a fonte de verdade pra TODOs
- Não usar "// TODO" no código pra coisas grandes — vira issue
- "// TODO" só pra micro-tarefas dentro do mesmo arquivo

### Code review (mesmo solo)

Mesmo Falcão sendo solo dev, abrir PR e olhar o diff antes de merge. Forçar essa pausa evita bugs óbvios. Tempo extra: 1 minuto. Bugs evitados: muitos.

**Como resumir um code review pro Falcão (estilo de comunicação dele):**

Quando ele pergunta "em resumo, o que fizemos?" depois de uma rodada longa de fixes, **não despeje a punch list** — ele já leu nos PRs. O que ele quer é **uma frase que descreva o efeito no produto**, no idioma dele:

> "Deixamos o app mais seguro, mais rápido e mais correto — fechamos o invariante X, blindamos Y contra spoof de Z, e cortamos o bundle em 40x."

Fórmula:
- 1 sentença topo descrevendo o **impacto agregado** (segurança / performance / correção / UX).
- 2-3 cláusulas curtas com o **resultado concreto** de cada eixo (invariante fechado, race travada, bundle X→Y, latência cai, etc.), não os nomes de função.
- Sem lista granular, sem severidade, sem "batch N entregou A, B, C". Esse detalhe vive nos PRs, não no resumo.

Se ele quiser mais profundidade, ele pergunta. Confirmado em 2026-05-23 após code review batches 1-4.

### Testes

- Cada projeto define cobertura mínima e tipos de teste
- CI **deve** rodar testes antes de permitir merge em `development`
- Testes rodam de novo em `<prod>` antes do deploy (gate final)

### Hotfix urgente

Se produção quebrar e precisar de fix imediato:

1. Branch `hotfix/<descrição>` saindo da **`<prod>`** (não development)
2. Fix mínimo, testes locais
3. PR pra `<prod>` (não passa por development)
4. Merge → deploy automático
5. **Depois:** mergear hotfix de volta em `development` pra não perder o fix

### Gestão de secrets — quando migrar de `.env` pra cofre

**Estado atual:** cada projeto tem seu `.env` (gitignored), GitHub Secrets para CI/CD, Vercel envs para frontend. Funciona pra 1-2 projetos.

**Quando migrar pra cofre centralizado:** quando tiver **3+ projetos** ativos compartilhando secrets (ex: mesma key Supabase entre projetos pessoais, mesma chave de API entre Sonar/SIGOF) OU quando rotacionar secret virar dor (ter que editar `.env` em N repos).

**Ferramentas que rodam via CLI e funcionam bem com LLM como Claude:**

| Ferramenta | Plano grátis | Self-host | LLM-friendly | Quando escolher |
|---|---|---|---|---|
| **Doppler** ⭐ | 5 users, 100 secrets/config, 3 envs | ❌ | Sim — CLI clara, JSON output, docs sólidas | Padrão solo/pequeno time, fácil de começar |
| **Infisical** ⭐ | Unlimited users (cloud) ou self-host | ✅ open source | Sim — CLI espelha Doppler | Quem prefere open source / quer hospedar na VM Hetzner |
| **Pulumi ESC** | 500 envs/mês | ❌ | Sim — nova mas API limpa | Quem já usa Pulumi pra IaC |
| **HashiCorp Vault** | Self-host grátis | ✅ | Médio — CLI complexa, muita policy | Empresa grande, overkill solo |
| **1Password Secrets** | Não tem free real (~$8/user/mês) | ❌ | Médio — `op://vault/item/field` | Quem já paga 1Password |
| **Bitwarden Secrets Mgr** | 3 users, 200 secrets | ❌ | Médio | Quem já usa Bitwarden |
| **Cloud nativo** (AWS/GCP/Azure) | Limites por cloud | ❌ | Sim — CLI dos providers | Vendor lock-in já existente |

**Recomendação pro Falcão quando o momento chegar:**

1ª opção — **Doppler**: setup mais rápido, CLI limpa, sync nativo com Vercel + GitHub Actions. LLM resolve em ~10min.

2ª opção — **Infisical self-hosted na VM Hetzner**: zero custo, controle total, LLM configura via Docker compose ali mesmo. Vale se quiser consolidar tudo na Hetzner.

**Setup típico** (Doppler como exemplo):
```bash
brew install dopplerhq/cli/doppler   # ou snap, scoop
doppler login                          # auth via browser
doppler setup                          # liga repo atual ao projeto Doppler
doppler secrets set SUPABASE_URL=xxx   # salva secret
doppler run -- npm run dev             # roda app com secrets injetados
doppler integrations create vercel ... # sync automático
```

Mantém `.gitignore` cobrindo `.env*` por hábito mesmo após migrar.

### Migração / breaking changes

- Toda mudança breaking precisa de PR com **título prefixado `BREAKING:`** e corpo explicando migração
- Se afeta consumers (frontend → backend), coordenar deploy: backend primeiro com retrocompatibilidade, frontend depois

---

## 4. Quando essa skill se aplica

Esta skill é o **default**. Se uma skill específica de projeto contradiz, a skill específica vence — mas é raro acontecer. Hierarquia:

- **`falcao-default`:** workflow, branches, commits, agent.md (este arquivo)
- **`falcao-hetzner`:** infra, deploy, VM, Caddy
- **`falcao-launcher` / `falcao-tcc` / etc.:** detalhes específicos do projeto

Quando começar trabalho em projeto novo, ler `falcao-default` + `falcao-hetzner` + skill do projeto se existir.

---

## 5. Ao trabalhar nesta skill

Atualizar quando:
- Workflow Git mudar (ex: adicionar `staging` branch)
- Convenção de commits/branches mudar
- Boas práticas novas surgirem (ex: pre-commit hooks padronizados)
- Falcão der feedback corretivo no fluxo

NÃO atualizar:
- Coisas específicas de um projeto (vai pra skill do projeto)
- Detalhes de infra (vai pra `falcao-hetzner`)
- Status atual de algum projeto (vai pra skill do projeto)
