Finance Audit — Relatório CFO Pessoal
Transforme uma pasta de arquivos de extrato brutos em um Relatório CFO Pessoal: dados verificados mais uma camada narrativa que responde O que aconteceu? Por quê? O que devo fazer a seguir?
Primeiro a precisão: os valores são lidos literalmente e reconciliados com o saldo corrente — nada é inventado.
Agnóstico a bancos. Funciona com qualquer banco ou exportação de conta, desde que haja uma lista de transações. Colunas, linhas de cabeçalho e ordem de data (DMY/MDY/YMD) são auto-detetadas por arquivo; o limpador de contraparte/merchant é independente de canal (UPI, POS, ACH, SEPA, cartão, TED, …). Nada é codificado para um banco específico — você confirma o mapeamento auto-detetado e ajusta as palavras-chave de categoria.
Pipeline (5 estágios)
ingest -> parse -> categorize (loop até >=99%) -> analyze -> report (serve + hot reload)
Os scripts estão neste skill. Execute-os na pasta de auditoria do usuário (a pasta que contém os arquivos de extrato). Defina duas variáveis primeiro:
SKILL="<caminho absoluto para este diretório do skill>" # a pasta que contém este SKILL.md
ROOT="<caminho absoluto para a pasta de auditoria>" # onde estão os arquivos de extrato
Privacidade — nunca enviar dados reais
Todos os arquivos de extrato, saldos, narrações e saída gerada permanecem locais
em ROOT/. O repositório do skill só envia modelos, configuração de exemplo e dummy
fixtures (assets/fixtures/sample_analysis.json).
Gitignored (nunca enviar): output/ (incluindo report.html, analysis.json,
audit.db), arquivos de extrato e config/mapping.json / overrides ativos.
Rótulos opcionais em config/mapping.json: account_label ou account_last4 para o
rodapé da barra lateral (padrão: "Conta principal"). Nome de exibição comercial em
config/business.json → display_name (padrão: "Negócio").
Assuma que os arquivos de extrato já foram baixados em ROOT (PDF / XLSX / XLS / CSV / TXT).
Escolha o runtime (o usuário prefere Node.js):
- Use Node quando
nodeestiver disponível E nenhuma entrada for PDF. - Use Python quando qualquer entrada for um PDF (caminho Node não consegue parsear PDF) ou
nodenão estiver disponível.
Detecte e instale dependências:
# Caminho Node (preferido)
command -v node && node --version # precisa Node >= 22 para sqlite nativo
( cd "$ROOT" && npm install xlsx ) # SOMENTE para .xls/.xlsx; CSV/TXT não precisam de nada
# Caminho Python (fallback / necessário para PDF)
python3 --version
pip install openpyxl "xlrd==2.0.1" pdfplumber pandas # + pandas para o estágio analyze
Defina como você invocará um estágio ($STAGE = ingest|parse|categorize|analyze|report):
# Node: node "$SKILL/scripts/node/$STAGE.mjs" --root "$ROOT" [args]
# Python: python3 "$SKILL/scripts/python/$STAGE.py" --root "$ROOT" [args]
Passo 1 — Ingestão e detecção
node "$SKILL/scripts/node/ingest.mjs" --root "$ROOT" # ou python3 .../ingest.py --root "$ROOT"
Isso pré-visualiza cada arquivo e escreve config/mapping.json com uma linha de cabeçalho
auto-detetada, papéis de coluna e um date_format explícito. Leia a pré-visualização e
verifique mapping.json — bancos diferem. Se uma entrada tiver um _date_note, a ordem da data
era ambígua (ex.: 03/04/2024); confirme date_format com o usuário.
Cada entrada de arquivo precisa de: header_row, data_start_row, date_format (um padrão strptime
como %d/%m/%Y, ou auto), columns (papel → índice 0-based), e
amount_mode:
debit_credit— colunas separadas de saque + depósito (mais comum)signed— uma colunaamountcujo sinal indica direçãoamount_type— uma colunaamountmais uma colunatypecontendo DR/CR
Corrija quaisquer índices errados antes do parse.
Passo 2 — Parse, normalizar, deduplicar, validar
node "$SKILL/scripts/node/parse.mjs" --root "$ROOT" # ou .../parse.py
Escreve output/audit.db (SQLite). A divisão débito/crédito é derivada do
valor com sinal para que sempre corresponda à cadeia de saldo (tratando corretamente reembolsos
codificados como saques negativos). Exija que a verificação de integridade PASSE (ou
n/a quando não houver coluna de saldo). Se FALHAR:
- Re-verifique as colunas /
data_start_row/date_formatemmapping.json. - Re-leia a saída stdout da ingestão (re-execute ingest se necessário); confirme que você não incluiu linhas de cabeçalho/rodapé.
chain_issues > 0por arquivo aponta para as linhas exatas que foram mal parseadas.
Não prossiga para a categorização até que o parse reconcilie.
Passo 3 — Categorizar (loop até >= 99% por valor)
cp "$SKILL/config/categories.example.json" "$ROOT/config/categories.json" # apenas na primeira execução
# Para uma conta comercial/autônomo, também:
cp "$SKILL/config/business.example.json" "$ROOT/config/business.json" # então edite-o
node "$SKILL/scripts/node/categorize.mjs" --root "$ROOT" # ou .../categorize.py
Precedência de regras: overrides.json > business.json > categories.json; maior
priority vence. A categorização é script-primeiro; atinja 99% assim:
- Execute categorize. Leia o resumo de cobertura e
output/uncategorized.csv(mercados agrupados, maior valor primeiro). - Para mercados cuja identidade é óbvia a partir da narração, adicione regras a
config/overrides.jsonvocê mesmo (veja formato abaixo) — não precisa perguntar. - Para mercados ambíguos (não está claro quem/o que é, ou pessoal-vs-comercial), faça uma pergunta concisa ao usuário e depois adicione a regra.
- Re-execute categorize. Repita até que a cobertura de valor ≥ 99%.
Formato config/overrides.json:
{ "rules": [
{ "keywords": ["ACME", "ACME CORP"], "primary": "Income", "sub": "Acme retainer", "when": "credit" },
{ "keywords": ["BIGRENT"], "primary": "Housing", "sub": "Rent", "is_business": 0 }
] }
Almeje que toda transação tenha um primary_cat e sub_cat. O fallback factual
contraparte P2P rotula transferências mas conta como "precisa de revisão" — converta
as importantes em regras reais.
Passo 4 — Analisar (construir output/analysis.json)
python3 "$SKILL/scripts/python/analyze.py" --root "$ROOT"
Calcula fatias de ano fiscal, relatórios de categoria, narrativa CFO, motor de receita, resumo de queima,
áreas problemáticas e pós-mortem comercial a partir de output/audit.db. Escreve
output/analysis.json (e opcionalmente findings.md localmente — nunca enviar).
Requer pandas. Ajuste config/business.json → display_name para o rótulo da seção
comercial (padrão "Negócio").
Passo 5 — Gerar o relatório (servir + recarregar a quente + abrir automaticamente)
python3 "$SKILL/scripts/python/report.py" --root "$ROOT" --serve
Constrói output/report.html a partir de analysis.json + linhas do razão embutidas inline.
Com --serve, abre http://127.0.0.1:8765/ e recarrega a quente quando o banco de dados/configuração mudar
(re-executa analyze + re-renderiza). Use --refresh-analysis para forçar re-análise em um
build único.
UI do Relatório (output/report.html) — Dashboard híbrido Money.Audit
Estrutura: moldura de app arredondada, barra lateral leve com lista de anos fiscais + navegação por seção (scroll-spy), coluna principal de largura total. Título: O que importa sobre seu dinheiro.
Aparência: Fraunces serif + Spline Sans UI; fundo creme quente (#f7f6f3), destaque
dourado. Não é genérico SaaS cinza.
Seções (barra lateral): Instantâneo, Motor de receita, Queima mensal, Áreas problemáticas, Pós-mortem comercial, Caixa e movimentação, Plano de ação, Todas as categorias, Razão (busca + filtros).
Dados embutidos: const ANALYSIS = … e const LEDGER = … — sem fetch externo.
Rodapé da barra lateral mostra account_label do mapeamento (nunca codificar números de conta no
template).
Movimento: emil-design-eng — :active scale(0.98), transições de largura de barra, seguro para
movimento reduzido. Guia de estilo: references/ui_style_guide.md.
Template: assets/report_template.html. Fixture dummy para docs:
assets/fixtures/sample_analysis.json.
Ao alterar a UI do relatório: edite o template + guia de estilo; nunca enviar
output/report.html real. Regere localmente via analyze → report.
Conteúdo do Relatório
- Instantâneo — pontuação de saúde, métricas, três coisas que o CFO citaria.
- Receita / queima / problemas — seções focadas em decisão com drill-down para categorias.
- Revisão comercial — quando
config/business.jsonestá presente. - Razão — evidência de transação pesquisável (primeiras 350 correspondências mostradas).
Flags: --port N, --no-open, --refresh-analysis. Sem --serve, escreve
output/report.html uma vez (executa analyze primeiro se analysis.json estiver faltando).
Metodologia: references/financial_frameworks.md.
Nota: A UI híbrida Money.Audit usa o caminho Python analyze + report. Node
report.mjs ainda renderiza o template CFO legado para auditorias básicas sem analyze.
Layout produzido na pasta de auditoria
ROOT/
├── <arquivos de extrato> # entrada (PDF/XLSX/XLS/CSV/TXT)
├── config/
│ ├── mapping.json # mapeamento de colunas (verificar após ingest)
│ ├── categories.json # regras de categoria (do exemplo)
│ ├── business.json # opcional: receita/folha/infra comercial
│ └── overrides.json # seus rótulos adicionados durante o loop
└── output/
├── audit.db # Fonte da verdade SQLite
├── analysis.json # estágio analyze (apenas local — PII)
├── uncategorized.csv # fila de revisão (regenerada a cada execução de categorize)
└── report.html # Dashboard Money.Audit (apenas local — PII)
O skill só escreve o necessário: configuração editável, o banco de dados SQLite que carrega
o estado entre os estágios, a fila de revisão e o relatório final. Dumps intermediários
(a pré-visualização da ingestão, o JSON do relatório) são impressos/embutidos, não escritos como
arquivos extras. mapping.json e audit.db devem persistir em disco porque cada estágio é executado
como um processo separado.
Notas
- O mesmo
mapping.json/config/ esquema SQLite funcionam em ambos os runtimes; você pode trocar de runtime no meio da auditoria. - Mantenha arquivos de extrato brutos fora do controle de versão (eles contêm PII).
- Para esquema completo, matemática de validação e referência de configuração, veja reference.md.
- Para frameworks de análise (taxa de poupança, 50/30/20, benchmarks, lógica de recomendação), veja references/financial_frameworks.md.
Solicitações comuns que este skill lida
- "Auditar / categorizar meus extratos bancários e fazer um relatório" — pipeline completo.
- "Qual é meu relatório CFO Pessoal para o ano fiscal 2024-25?" — use seletor de período após o relatório.
- "Qual é minha taxa de poupança e como posso melhorá-la?" — sumário executivo + plano de ação.
- "Onde estou gastando demais?" — inteligência de gastos + contrafactuais.
- "O que devo parar/iniciar/continuar?" — seção de plano de ação.
- "Pergunte ao meu CFO sobre runway / dívida / investimentos" — use prompts 'Pergunte ao seu CFO' com seu agente.
- "Melhorar a UI do relatório / torná-la largura total / corrigir o layout" — edite
assets/report_template.htmlconforme references/ui_style_guide.md; regere localmente com analyze → report. Nunca envieoutput/report.html.