Análise Local de Arquivos
Objetivo
Analisar arquivos tabulares, documentos, PDFs e imagens sem enviar o arquivo ou seu conteúdo para qualquer serviço em nuvem, e mascarar dados pessoais — nomes, detalhes de contato, endereços, números de identidade — em todos os modos. Os arquivos fonte são abertos somente leitura na máquina local, a extração e as estatísticas são executadas por scripts locais, e todo artefato permanece dentro de um diretório de trabalho local.
Passo 1 — Solicitar o caminho local primeiro (obrigatório, nunca ignorado)
A primeira frase após esta skill ser ativada deve solicitar um caminho local, não começar a análise. Use o texto abaixo, adaptado ao contexto, mantendo quatro pontos: nada é enviado para nuvem, um caminho absoluto é necessário, como copiar um caminho e o seletor de arquivos opcional.
Analisarei este arquivo apenas nesta máquina — nada vai para nenhum serviço em nuvem, e nomes, telefones, endereços e números de identidade são mascarados no relatório. Por favor, forneça o caminho absoluto local, ex.:
/Users/voce/Documentos/ledger.xlsxouD:\dados\ledger.xlsx; separe vários arquivos com novas linhas. Para copiar um caminho: clique com o botão direito no arquivo → "Copiar como caminho" (Windows), ou arraste o arquivo para um terminal / use ⌥⌘C no Finder (macOS). Ou apenas diga "selecione os arquivos para mim" e abrirei um diálogo de arquivos local.
Acompanhamento:
- Usuário diz "selecionar / mostrar um diálogo" → execute
python "<skill_dir>/scripts/pick_path.py"(multi-seleção), ou com--single. Use os caminhos impressos como entrada. Código de saída 2 significa nenhuma sessão gráfica — volte a pedir que o usuário cole os caminhos. - Usuário diz "está anexado" mas existe apenas um card de anexo, sem caminho → trate conforme a próxima seção. Não leia o anexo silenciosamente.
- Após receber os caminhos, valide: caminho existe, extensão suportada, contagem de arquivos razoável (agrupe por tipo acima de ~10 arquivos).
Quando o usuário já enviou um anexo
Declare o risco antes de aceitar qualquer coisa:
Um ponto a destacar: um arquivo arrastado para o chat pode já estar armazenado nos servidores da plataforma, então esse caminho não é mais puramente local. Se este arquivo for confidencial ou contiver dados pessoais, envie-me seu caminho local e o lerei do disco — nada sai desta máquina.
Se o usuário ainda quiser o anexo, prossiga, mas identifique a entrega honestamente: "a entrada veio de um anexo do chat, que pode ter alcançado os servidores da plataforma" — nunca chame um anexo de "totalmente local".
Passo 2 — Deixar o usuário escolher um modo
Duas opções; o usuário deve escolher. Se não especificado, use Normal e declare o modo na primeira linha da resposta.
| Normal (padrão) | Strict | |
|---|---|---|
| Conteúdo do relatório | Estrutura + estatísticas + visualização mascarada (primeiras N linhas, trechos do corpo) | Apenas métricas agregadas: linhas/colunas, tipos, taxa de não-nulos, contagem distinta, intervalo, média |
| Texto bruto | Texto mascarado entra no relatório, visível para o modelo | Nunca aparece; o modelo vê apenas métricas |
| Adequado para | Dados internos gerais, interpretação semântica, conclusões escritas | Registros de clientes, folha de pagamento, dados médicos, contratos, material classificado |
| Custo | Conteúdo mascarado entra no contexto de inferência | Nenhum julgamento semântico possível, respostas apenas estatísticas |
Texto:
Escolha um modo: ① Normal — estrutura, estatísticas e uma prévia mascarada para que eu possa ler o conteúdo e tirar conclusões; ② Strict — apenas métricas, nenhum texto original em qualquer parte do relatório. O padrão é Normal.
Mascaramento obrigatório (todos os modos, não pode ser desabilitado)
O mascaramento não é uma opção, é o comportamento padrão. O script não tem uma chave de desligamento, e --mode strict não significa "o mascaramento é opcional" — strict empilha "nenhum texto original" sobre o mascaramento.
| Categoria | Campos cobertos | Resultado |
|---|---|---|
| Nome | nome, titular da conta, contato, representante legal, proprietário, responsável, gerente de conta, candidato, beneficiário, portador do cartão, acionista | [NOME#1] |
| Contato | celular, telefone fixo (com código de área), fax, e-mail | [TELEFONE#1] / [EMAIL#1] |
| Endereço | endereço, residência, endereço de correspondência, endereço registrado, domicílio | Província/cidade mantidos, resto torna-se [ENDERECO#1]; --mask-region oculta também a região |
| Identidade | RG (11 dígitos), CPF (11 dígitos), passaporte, carteira de trabalho, CNH, CNPJ | [ID#1] |
| Financeiro | cartão bancário, número de conta, número do cartão | [CONTA#1] |
| Outros identificadores | placa de veículo, código de cliente, código de funcionário, código de membro, código de estudante, PIS/NIS, código de apólice | [PLACA#1] / [IDNUM#1] |
Três princípios de implementação, citáveis na nota de entrega:
- Pseudônimos estáveis. O mesmo valor de origem sempre mapeia para o mesmo pseudônimo dentro de uma execução. "João aparece 3 vezes" torna-se "
[NOME#1]aparece 3 vezes" — contagem, deduplicação e junções ainda funcionam, a identidade não sobrevive. - Sem mapeamento em disco. O mapa valor-para-pseudônimo vive apenas na memória. Nem
report.mdnemmanifest.jsono contêm; apenas contagens de ocorrência são escritas. - Heurísticas para texto livre. Tabelas estruturadas são classificadas pelo cabeçalho da coluna e mascaradas por coluna inteira. Texto livre em corpos, PDFs e slides depende de regex mais um léxico de sobrenomes ("contato: João Silva", "Sr. João"). Heurísticas erram — especialmente nomes isolados sem pista contextual. Diga isso claramente; nunca afirme "tudo é detectado".
Manter província/cidade é intencional: suporta análise em nível regional sem expor o endereço completo. Use --mask-region quando a própria região for sensível.
Passo 3 — Extrair localmente
python "<skill_dir>/scripts/local_extract.py" "/caminho/para/ledger.xlsx" "/caminho/para/relatorio.docx" \
--workspace ".analise_local"
Adicione --mode strict para modo estrito; --mask-region para ocultar regiões; --redact "EMP\d{6}" (repetível) para padrões personalizados.
Saídas (todas dentro de --workspace):
report.md— perfil estrutural mascarado + estatísticas + prévia; a única entrada para o resto da análisemanifest.json— lista de arquivos, SHA-256, modo,masking.enabled=true, contagens de ocorrência do mascaramento,network_used: false
O console imprime por arquivo: tipo, tamanho, campos mascarados, contagens de ocorrência e "requisições de rede: 0". Leia report.md com o leitor de arquivos local depois; não substitua por capturas de tela ou OCR online.
Passo 4 — Computar localmente, nunca mentalmente
Somas, razões, contagens distintas, ordenação, agrupamento, variações período-a-período: sempre calculados por um script local. Sem ver os dados completos, as estimativas do modelo estão quase sempre erradas. Reutilize parse_xlsx / parse_delimited / Masker de local_extract.py em um script descartável, compute, depois escreva os números no relatório. Pseudônimos podem ser agrupados e contados diretamente — não é necessário revertê-los.
Passo 5 — Produzir uma folha de auditoria
python "<skill_dir>/scripts/local_audit.py" ".analise_local" --note "processado localmente, nada enviado"
A folha de auditoria tem cinco partes: integridade do arquivo fonte (reverificação do hash provando somente leitura, sem cópias), execução do mascaramento (estado das chaves, categorias, ocorrências nesta execução), inventário de artefatos, verificação linha por linha, conclusão. Código de saída 0 = aprovado, 1 = um arquivo fonte mudou durante o processamento.
Passo 6 — Relatório
Conclusão primeiro, dados depois, uma declaração final:
Esta análise foi executada inteiramente nesta máquina, sem envolvimento de serviço em nuvem; os arquivos fonte foram somente leitura e inalterados, e o relatório mascara nomes, telefones, endereços e números de identidade (pseudônimos estáveis). Os artefatos estão em
.analise_local/, folha de auditoria emaudit.md.
Linhas vermelhas (nunca acionadas)
| Categoria | Proibido | Ferramentas típicas |
|---|---|---|
| Documentos em nuvem | Criar, importar ou "editar" uma planilha/documento online | Conectores Tencent Docs, Kingsoft Docs, Feishu Docs |
| Drives / armazenamento em nuvem | Fazer upload de arquivos ou artefatos | Tencent Drive, WeDrive, armazenamento de arquivos em nuvem |
| Bases de conhecimento | Escrever em uma biblioteca, ingerir URLs | upload de biblioteca, base de conhecimento ima |
| Busca externa | Usar texto fonte ou fragmentos como consulta | busca na web, scraping de página |
| Conversão / OCR online | Conversão de PDF online, descompactação online, reconhecimento de imagem online | qualquer ferramenta online, API de compreensão de imagem |
| Envio externo | Postar arquivos ou resumos em chat, e-mail, bots | mensagens WeCom, e-mail, upload de notas de reunião |
Apenas uma exceção: o usuário explicitamente diz "este pode ser enviado / transmitido". Mesmo assim, repita e obtenha uma segunda confirmação antes de agir.
Caminho local por tipo de arquivo
| Tipo | Rota local preferida | Notas |
|---|---|---|
.xlsx .xlsm | local_extract.py (zip + XML diretamente) | Multi-abas, mascaramento por coluna; datas podem aparecer como números de série |
.csv .tsv .txt .md .json .html | local_extract.py | Detecta UTF-8 / GB18030 e delimitador; CSV mascarado pelo cabeçalho |
.docx .pptx | local_extract.py (zip + XML diretamente) | Parágrafos, esboço de cabeçalhos, tabelas, marcadores por slide; corpo via mascaramento de texto livre |
.pdf | local_extract.py | Usa um CLI local workbuddy-pdf quando presente, fallback zlib embutido caso contrário |
.png .jpg .gif .bmp .webp | local_extract.py | Apenas formato, dimensões, hash; OCR local somente se tesseract existir |
.xls .doc .ppt binários legados | Peça ao usuário para salvar novamente localmente, ou abrir em um editor local | Nunca envie para um conversor online para extrair conteúdo |
| PDF scaneado / texto dentro de imagens | OCR local, ou o usuário dita o conteúdo | Se não houver OCR, declare a lacuna honestamente — não roteie para a nuvem |
Imagens em particular: sem tesseract, trate-as apenas como metadados e diga "o conteúdo da imagem não foi reconhecido", oferecendo duas rotas locais (instalar OCR e executar novamente / usuário descreve). Não "dê uma olhada" com um modelo de visão — isso empurra a imagem para o caminho de inferência e contradiz a solicitação do usuário.
Regras de degradação
- Script local pode analisá-lo → use a saída do script.
- Nenhum texto extraível (scan, formato legado, criptografado) → explique por que, ofereça alternativas locais (salvar novamente localmente, OCR local, ditado do usuário).
- Usuário insiste por "resultados agora" → retorne à pergunta do modo: "dado o estado atual, só posso responder estatisticamente — aceitável?"
Erros comuns
- Pular a solicitação de caminho e analisar um anexo do chat diretamente: viola o Passo 1.
- Colar todo o
report.mdna resposta: o relatório é o documento de trabalho; as respostas trazem conclusões e números-chave. - Acreditar que o modo strict torna o mascaramento desnecessário: as duas dimensões são independentes.
- Imprimir valores não mascarados no console ou em um arquivo temporário "para ver os dados": o mascaramento deve acontecer antes que qualquer coisa seja escrita.
- Estimar em vez de computar localmente: estimativas estão quase sempre erradas em escala de dados completos.
- Enviar
.xlspara um conversor online "por conveniência": viola uma linha vermelha; salve novamente localmente. - Ignorar codificação: ler um CSV GB18030 como UTF-8 produz mojibake que polui o perfil da coluna. O script lida com isso; código escrito à mão também deve.
Nota sobre idiomas
As regras de detecção visam formatos de dados em português/inglês (CPF, RG, CEP, telefones, endereços completos, e-mails, cartões bancários, placas) mais padrões genéricos. Relatórios e saída do console estão atualmente em português; a lógica de detecção é agnóstica a idiomas onde os padrões permitem. Para documentos apenas em inglês, o mascaramento de tabelas estruturadas ainda funciona via cabeçalhos de coluna, mas a detecção de nomes em texto livre é fraca — diga isso em vez de prometer demais.