Pular para conteúdo

Auditoria do sistema de IA da v1.9.7

Data da auditoria: 2026-07-14. Base auditada: main em 7e309076cca6aa6def73fd9fbf99796319f9f859 (v1.9.6).

Estado inicial verificável

  • HEAD, origin/main e o commit apontado pela tag anotada v1.9.6 resolviam para 7e309076cca6aa6def73fd9fbf99796319f9f859.
  • A árvore estava limpa e a branch ativa era main; v1.9.7 ainda não existia localmente nem no remoto.
  • Os workflows CI, CodeQL e Docs estavam verdes no commit inicial.
  • A extensão declarava 0.9.2 em browser-extension/manifest.json.
  • python scripts/check_data_health.py informou schema SQLite 3 saudável, com um warning preexistente de oportunidade sem referência de origem. A auditoria foi somente leitura.
  • O scan inicial de padrões Gemini/OpenAI em arquivos rastreados não encontrou segredo.
  • modules/scraping/browser_session.py e modules/scraping/connectors/authenticated_browser.py tiveram hashes SHA-256 registrados antes da implementação para conferência final.
  • As variáveis opt-in de teste Gemini e OpenAI estavam presentes. Somente a presença booleana foi verificada; nenhum valor foi impresso, persistido ou recuperado.

Superfície de IA encontrada

Chamadas estruturadas de provider estavam presentes em extração de currículo, extração de vaga, classificação de domínio, Match, ATS, Tailor, análise de repositório GitHub, importação de Lattes, importação de edital, extração de itens de Perfil, enriquecimento de fonte e duas funções do Radar (wishlist e explicação). O fallback determinístico usa MockProvider, parsers locais e regras dos módulos de domínio.

Tarefa observada Prompt em produção Consumidor principal Fallback local Career Context/RAG
currículo resume_extraction_v1 structured_resume_extractor.py sim não no payload atual
vaga job_extraction_multi_domain_v1 structured_job_extractor.py sim não no payload atual
domínio domain_classification_v1 domain_classification_service.py sim contexto explícito opcional
Match match_analysis_evidence_based_v1 structured_analysis.py sim sim, compartilhamento opt-in
ATS ats_analysis_v1 apps/api/services/analysis.py sim somente confirmado no provider
Tailor resume_tailor_v1 apps/api/services/analysis.py sim somente confirmado no provider
GitHub/repositório github_repo_analysis_v2 github_analyzer/analyzer_service.py sim itens confirmados e não sensíveis
Lattes profile_lattes_extractor_v1 academic/lattes_service.py sim não
edital public_exam_notice_extractor_v1 public_exams/service.py sim Perfil é usado na elegibilidade local
Perfil profile_items_extractor_v1 apps/api/services/profile.py sim não altera Perfil sem aprovação
fonte source_import_enrichment_v1 apps/api/services/sources.py sim não
Radar/wishlist job_wishlist_builder_v1 apps/api/services/radar.py sim Perfil permitido e filtrado
Radar/explicação job_radar_match_explanation_v1 apps/api/services/radar.py sim via resultado local/wishlist
conselho de carreira career_advice_v1 nenhum não exercitado não exercitado

Registry e governança antes da mudança

O PromptRegistry tinha 14 prompts com versão, system prompt, template, schema, temperatura e modo. Não declarava tarefa, providers suportados, política de contexto, suite de avaliação, golden cases ou métricas. A busca de consumidores demonstrou um prompt registrado sem consumidor (career_advice_v1). Três documentos de prompt não correspondiam a um contrato ativo do registry: github-profile-analysis-v1.md, portfolio-gap-analysis-v1.md e hidden-job-detection-v1.md. Os dois primeiros representam tarefas desejadas; o último fica fora do registry de tarefas da v1.9.7 e deve permanecer apenas como proposta até existir consumidor, schema e avaliação.

Não foi localizado consumidor de produção que criasse prompt ad hoc fora do loader. As chamadas encontradas resolviam o prompt com default_prompt_registry().get(...) ou recebiam um PromptRegistry injetado.

Outputs, warnings e fallbacks

  • Resume e job validavam o output estruturado, mas a API devolvia o resultado do parser local; o output rico do provider era usado para confidence/warnings e depois descartado da resposta.
  • ATS e Tailor aproveitavam apenas subconjuntos do output estruturado. Campos adicionais do schema não tinham armazenamento próprio.
  • Erros de ATS e Tailor eram capturados por except Exception e convertidos em warning genérico; tipo de erro, latência e tentativa do provider não eram persistidos.
  • Lattes, edital, Perfil, Radar e enriquecimento tinham fallback e warning no domínio, mas não gravavam AiRun pelo caminho comum.
  • O fallback era visível nas respostas principais da API, porém inexistia um painel agregado para detectar taxa ou motivo de fallback.
  • analysis_snapshots persistia resultados completos por desenho da v1.9.6; ai_runs era separado e guardava somente metadados. A v1.9.7 deve manter traces sem conteúdo integral.

AiRunStore antes da mudança

AiRunStore existia no schema 3 e era chamado apenas por _trace_metadata em cinco fluxos: currículo, vaga, Match, ATS, Tailor e GitHub compartilham a função, mas não havia uso equivalente nas demais chamadas estruturadas. O store tinha provider/modelo solicitado e usado, prompt, modo, fallback, schema, token_usage, custo opcional, hash, fontes, refs, evidências, warnings e revisão. Não tinha task_id, versões de schema, propósito/contagem de contexto, timestamps de início/fim, tokens normalizados, erro sanitizado, benchmark/parent run, paginação por offset, retenção nem política configurável de conteúdo.

Embora existissem campos para tokens, custo e latência, nenhum dos providers propagava essas métricas até _trace_metadata; portanto os runs de produção ficavam sem esses valores. O provider solicitado e o usado eram expostos nas respostas, mas falhas internas podiam registrar modelo solicitado como modelo usado quando o fallback era local.

Evidência, contexto e confiança

O CareerContextEngine já era aplicado a Match, ATS, Tailor e GitHub. Para providers externos, o envio de memória era opt-in; itens sensíveis eram omitidos e ATS/Tailor formatavam apenas evidência confirmada. Esse comportamento é uma boa base de segurança. Não existia, porém, benchmark A/B entre ausência de Perfil, Perfil confirmado, Perfil + RAG e contexto não confirmado.

Confidence de currículo e vaga era uma soma heurística de presença de campos. Schemas estruturados guardavam confidence por campo, mas não havia golden labels, reliability bins, Brier score ou erro de calibração. Match possuía confidence_score, também sem calibração medida. Afirmações sem evidence podiam atravessar schemas válidos, pois schema validation não equivale a validação de suporte factual.

Riscos priorizados e correções da v1.9.7

  1. Criar AiTaskRegistry comum e ligar cada prompt de produção a exatamente uma tarefa.
  2. Completar tracing secret-free em todos os fluxos e normalizar provider/modelo/fallback/erro.
  3. Criar golden datasets multiárea, métricas determinísticas e benchmark reproduzível.
  4. Tratar texto de currículo, vaga, edital e README como conteúdo não confiável delimitado.
  5. Validar claims proibidos e referências de evidência depois do schema.
  6. Capturar feedback humano apagável ligado ao run_id.
  7. Relacionar outcomes manuais do Tracker sem inferir causalidade ou alterar Perfil/pesos.
  8. Expor agregados com regras explícitas de amostra e sem texto pessoal integral.
  9. Testar local/mock sempre e providers externos somente pelas variáveis temporárias permitidas.
  10. Conservar fallback local, JSON/JSONL legado e toda a superfície authenticated-browser.

Limites desta auditoria

As métricas de qualidade não são declaradas aqui porque não existia dataset executável na base inicial. Valores de schema validity, evidence precision, unsupported claim rate, hallucination, calibração, latência, tokens e custo só podem ser publicados após a implementação e execução dos benchmarks. A presença das chaves opt-in não é evidência de uma chamada bem-sucedida.