name: cidadao-ai-conventions description: Use ao editar, testar ou deployar Cidadão.AI. Carrega convenções não-óbvias do projeto — env vars obrigatórias mesmo em testes (JWT_SECRET_KEY, SECRET_KEY), comandos make, padrões pytest-asyncio "auto", cobertura mínima, RLS, Alembic. Ative em qualquer modificação de código, antes de rodar testes ou de criar migration/PR.
Cidadão.AI — Convenções
Convenções não-óbvias ao olhar o código. Ler antes de mexer.
Variáveis de ambiente obrigatórias
JWT_SECRET_KEY=test SECRET_KEY=test
Mesmo para testes. Sem essas variáveis, a pydantic-settings em src/core/config.py falha no import. Toda invocação de pytest precisa delas. Toda invocação de make run-dev também.
Outras env vars críticas:
MARITACA_API_KEY— primary LLMANTHROPIC_API_KEY— fallback LLMDATABASE_URL— PostgreSQL (asyncpg). Default fallback: SQLiteREDIS_URL— cache + Celery broker
Comandos make
make run-dev # uvicorn com --reload na porta 8000
make lint # ruff check src/ tests/
make format # black + isort + ruff --fix
make check # lint + type-check + test (full quality gate)
Pytest
Sempre
JWT_SECRET_KEY=test SECRET_KEY=test pytest tests/ -v
Por arquivo
JWT_SECRET_KEY=test SECRET_KEY=test pytest tests/unit/test_agents/test_zumbi.py -v
Por marker
JWT_SECRET_KEY=test SECRET_KEY=test pytest tests/ -v -m unit
JWT_SECRET_KEY=test SECRET_KEY=test pytest tests/ -v -m integration
Coverage
JWT_SECRET_KEY=test SECRET_KEY=test pytest tests/ -v --cov=src --cov-report=term-missing
Pytest-asyncio "auto" mode
pyproject.toml tem asyncio_mode = "auto" — não precisa decorar com @pytest.mark.asyncio. Funções async def viram async tests automaticamente.
Categorias de teste
| Diretório | Conteúdo |
|---|---|
tests/unit/ |
Unit tests, mocks de DB/Redis/LLM |
tests/integration/ |
Integration tests (DB real opcional) |
tests/e2e/ |
End-to-end |
tests/multiagent/ |
Workflows com múltiplos agentes |
tests/performance/ |
Carga, benchmarks |
Cobertura
- Atual: ~76.29%
- Target: >80%
- 1.514 testes em 149 arquivos
- Coverage com
branch coverageativo nopyproject.toml - Mocks ficam em
tests/conftest.pyetests/fixtures/
Lint & format
- black — line length 88
- ruff — linting + auto-fix
- isort — import sorting
- Hooks pre-commit configurados em
.pre-commit-config.yaml
Banco e migrations
- SQLAlchemy async + asyncpg (PostgreSQL prod) ou aiosqlite (dev opcional)
- Alembic para migrations
- Migrations rodam no startup (lifespan function de
app.py), não no Procfile release phase - Migrations devem ser backwards-compatible (zero-downtime deploy no Railway)
- RLS (Row Level Security) em tabelas com escopo por usuário
Convenções de schema
- Tabelas em snake_case plural (
investigations,chat_messages) - Colunas em snake_case
- PK:
uuidcom defaultgen_random_uuid() - Sempre incluir:
id,created_at,updated_at - Soft delete via
deleted_atquando precisar - Não hardcodar IDs gerados em migration
Deploy
- Railway: prod em
cidadao-api-production.up.railway.app - Procfile:
web(uvicorn),worker(Celery),beat(Celery scheduler) - Builder: Nixpacks (railway.json)
- Branch:
main— push triggers deploy
GitHub
- Repo:
anderson-ntlabs/cidadao.ai-backend - Default branch:
main - 8 repos relacionados na org/usuário: backend, frontend, dashboard, hub, models, docs, technical-docs, presentations
Commits
- Inglês, conventional commits
- Foco no "why", não no "what"
- Nunca mencionar IA / Claude / ChatGPT em mensagens de commit
- Exemplos:
feat(agents): add cultural context routing for ayrton_sennafix(llm): correct fallback when maritaca rate-limitsrefactor(api): extract investigation lifecycle to dedicated service
Documentação
- Docs em
docs/(não na raiz) - Frontmatter obrigatório em
.mddentro dedocs/ - CHANGELOG segue Keep a Changelog 1.1.0
- Atualizar
[Unreleased]em todo commit relevante
Anti-patterns
- ❌ Rodar
pytestsemJWT_SECRET_KEY=test SECRET_KEY=test— vai falhar no import - ❌ Migration que não é backwards-compatible
- ❌ Hardcoded UUID em migration
- ❌ Comentário em commit explicando "what" — explica "why"
- ❌ Skip de pre-commit hooks (
--no-verify) - ❌ Rodar lint sem rodar format depois (lint vê problemas que format resolve)
- ❌ Documentação em
.mdna raiz — sempre emdocs/ - ❌ Decorator
@pytest.mark.asynciodesnecessário — auto mode já cuida