Text Share Online

d1

Após uma análise minuciosa do documento **Pipeline de Curação de Vagas — v5.12**, posso afirmar que ele representa um trabalho de engenharia de altíssima qualidade, com cobertura impressionante de detalhes operacionais, de concorrência, versionamento, tratamento de erros e governança. A evolução desde versões anteriores é notável e a especificação está madura para implementação.

Abaixo, apresento uma síntese dos pontos fortes e, em seguida, algumas observações que podem ser refinadas para garantir ainda mais robustez e clareza.

## Pontos Fortes

– **Rastreabilidade total**: Uso combinado de `curate_runs`, `curate_run_items`, `job_runs.metadata`, `events` e `ai_usage_logs` permite auditoria completa.
– **Controle de concorrência**: `FOR UPDATE SKIP LOCKED`, upserts atômicos, locks na promoção de canônicos e transição de circuit breaker resolvem race conditions típicas de sistemas paralelos.
– **Versionamento inteligente**: Pré-rotina de hash com armazenamento em `job_runs.metadata` elimina a necessidade de versionamento manual e permite decisões baseadas em mudanças reais.
– **Tratamento de falhas**: Distinção clara entre erros transitórios e permanentes, quarentena com rate limit, e liberação condicional por mudança de versão.
– **Embeddings bem arquitetados**: Uso de `pgvector`, HNSW, função RPC com `set_config`, e trigger de reset garantem performance e consistência.
– **Governança prática**: Rotinas diárias e mensais bem definidas, com queries de alerta e critérios de go/no-go.
– **Documentação exaustiva**: Quase todos os cenários estão cobertos, com notas para desenvolvedores e justificativas para decisões.

## Pontos de Atenção e Sugestões de Melhoria

Apesar da excelência, alguns pontos podem ser esclarecidos ou ajustados para evitar ambiguidades na implementação.

### 1. Atualização de `confidence_median`
O campo `confidence_median` em `job_canonical_roles` é mencionado, mas não está claro como e quando ele é atualizado. A auto-promoção exige `confidence_median ≥ 0.80`, e a query de exemplo usa `PERCENTILE_CONT` com `HAVING COUNT(*) >= 5`. No entanto, essa consulta precisa ser executada em algum momento – seja durante a auto-promoção (sob demanda) ou em um job periódico.
**Sugestão:** Especificar que a auto-promoção calculará a mediana diretamente no banco a cada avaliação, e que o campo na tabela pode ser dispensado ou atualizado por um job mensal. Se for mantido, documentar o mecanismo de atualização (ex.: no PASSO 4 do CRON).

### 2. Definição de `curation_status` para `curated_fallback`
O pipeline atualiza `job_postings` ao final do processamento, mas o documento não explicita que, quando `pipeline_stage = ‘fallback’`, o `curation_status` deve ser `’curated_fallback’`.
**Sugestão:** Incluir uma nota no fluxo de upsert: “Se `pipeline_stage = ‘fallback’`, setar `curation_status = ‘curated_fallback’`; caso contrário, se `canonical_role_id` resolvido, setar `curation_status = ‘curated’`.”

### 3. Inconsistência na orquestração do CRON
Há uma menção a “Vercel Cron 2x/dia” na seção de rate limit, mas a implementação usa `pg_cron` para agendar a função SQL `run_daily_pipeline_maintenance`. Isso pode confundir.
**Sugestão:** Substituir a referência a “Vercel Cron” por “pg_cron” ou esclarecer que o agendamento é feito via `pg_cron` e que o código TypeScript (quando necessário) é chamado pela função SQL via `supabase.rpc()`.

### 4. Papel do campo `retry_count` em `curate_run_items`
O documento utiliza `retry_count` em `curate_run_items` e também `llm_parse_fail_count` em `job_postings`. O propósito de `retry_count` não está claro – ele conta tentativas dentro de um mesmo run? Como o batch é processado uma única vez, esse campo pode ser redundante.
**Sugestão:** Esclarecer se `retry_count` é usado para retries de itens dentro do mesmo batch (ex.: após `item_output_parse_error`) e como ele se relaciona com `llm_parse_fail_count`. Ou, se for desnecessário, removê-lo para simplificar.

### 5. Lógica de rate limit do PASSO 3
O rate limita as liberações de quarentena a 100 por execução, verificando `quarantine_released_at >= CURRENT_DATE`. Essa verificação é feita no TypeScript antes de gerar a lista de IDs elegíveis.
**Sugestão:** Deixar explícito que o TypeScript executa essa consulta e, se o limite não foi atingido, prossegue com a comparação de hashes e geração da lista, chamando então a função SQL com os IDs. Atualmente a descrição está um pouco fragmentada entre texto e código.

### 6. Atualização de `distinct_sources_count`
O PASSO 2 do CRON recalcula `distinct_sources_count` com base em `job_canonical_role_sources` e `job_postings` ativas. Isso é suficiente para manter o campo preciso. Porém, a auto-promoção pode ocorrer antes do próximo CRON, usando um valor ligeiramente desatualizado. Como a auto-promoção exige 14 dias de observação, o CRON terá rodado muitas vezes, então o impacto é mínimo.
**Sugestão:** Manter como está, mas documentar que `distinct_sources_count` pode ter até 24h de atraso.

### 7. Uso de `job_runs` para versionamento
A FK `curate_runs.job_run_id` aponta para `job_runs`, que é uma tabela genérica. É importante garantir que:
– `job_runs` possua um índice eficiente em `(job_name, started_at)`.
– O campo `metadata` seja JSONB e suporte o tamanho esperado (conteúdo dos arquivos pode ser grande).
**Sugestão:** Adicionar uma nota sobre a necessidade de monitorar o tamanho do metadata e considerar armazenar apenas hashes e versões, não o conteúdo integral dos arquivos, para evitar crescimento excessivo.

### 8. Trigger de reset de embedding e reindexação
O trigger reseta `embedding` para NULL em mudanças semânticas. O documento menciona que o rebuild de embeddings detecta NULL e recalcula.
**Sugestão:** Incluir no CRON diário um passo para recalcular embeddings de canônicos com `embedding IS NULL`, garantindo que canônicos editados não fiquem invisíveis por mais de 24h.

### 9. `is_internship` no payload do extrator
A flag `is_internship` é detectada, mas não está claro se ela é passada ao extrator no XML de entrada.
**Sugestão:** Explicitar que o campo será incluído como atributo `<job is_internship=”true”>` para que o modelo possa usá-lo na inferência (ex.: priorizar senioridade “Estágio”).

### 10. Pequenos ajustes de nomenclatura
– Em alguns lugares, `curated_fallback` é escrito como `’fallback’` (ex.: na query do backfill). Isso já foi corrigido na maior parte, mas vale uma revisão final.
– O termo “Vercel Cron” aparece em comentários; uniformizar para “pg_cron” na seção de CRON.

## Conclusão

A versão **v5.12** está **praticamente impecável**. As observações acima são refinamentos que podem ser endereçados durante a implementação ou em uma revisão final do documento. Nenhuma delas compromete a viabilidade do sistema, e todas são de fácil ajuste.

O documento reflete um amadurecimento excepcional do projeto, com atenção a detalhes que vão desde a modelagem de dados até estratégias de resiliência em produção. Parabéns pelo trabalho!

Share This: