# Coordenador GLPI Automação n8n que analisa os chamados abertos no GLPI todo dia útil, classifica cada um com IA (contexto real do chamado, não só metadados) e envia no Slack os 10 chamados que realmente precisam de ação humana hoje. O repositório tem duas gerações do workflow: - **V2** (`n8n/`, `logic/`) — versão atual, em produção. Todo este README descreve o V2. - **V1** (`Coordenador GLPI - Chamados Abertos Slack.n8n.json`, na raiz) — versão legada, mantida apenas como rollback. Nunca foi importada nem ativada na instância n8n de produção; existe só como referência histórica e plano B. ## Estado atual (verificado em 2026-08-25) ``` Workflow: [DEV] Coordenador GLPI - Chamados Abertos v2 (Shadow) (id y6JFEnp7Z2IJEUe2) active: true SEND_ENABLED: true ENVIRONMENT: production FORCE_SEND: false (execução manual nunca envia de verdade sem essa flag) Schedule: seg-sex 08:00, timezone America/Sao_Paulo (cron "0 8 * * 1-5") Testes: 171/171 (node --test) ``` O nome do workflow no n8n ainda carrega o prefixo histórico `[DEV]` / `(Shadow)` — isso é só rótulo visual, não reflete mais o estado real (ativo, `SEND_ENABLED=true`, `ENVIRONMENT=production`). Renomear é seguro a qualquer momento, mas não foi feito para não gerar um diff de auditoria sem função. Se essa seção estiver desatualizada, o estado de verdade é sempre o que o n8n responde (`n8n_get_workflow` / `n8n_manage_datatable`), nunca este arquivo. ## Arquitetura ``` GLPI (MySQL, somente leitura) -> candidatos (pool configurável, sem corte artificial) -> normalização de texto (decodifica HTML/entities do GLPI) -> cache de classificação (Data Table, chave = hash do contexto + versão do classificador) -> IA (OpenAI) classifica só quem mudou de contexto ou nunca foi analisado -> score determinístico + seleção Top 10 com diversidade por grupo -> guard de envio (SEND_ENABLED, FORCE_SEND, idempotência por hash da mensagem) -> Slack (mensagem real, sem rodapé de atribuição do n8n) -> shadow-diff contra a query legada do V1 (auditoria, não bloqueia envio) ``` Cada etapa grava em uma Data Table do n8n (`coordenador_glpi_memoria`, `coordenador_glpi_envios_digest`, `coordenador_glpi_shadow_runs`) — não há escrita nenhuma no banco do GLPI. Toda query GLPI é somente leitura; isso é testado (`tools/build-workflow.test.js` varre `sql/*.sql` e o SQL gerado procurando `INSERT/UPDATE/DELETE/ALTER/DROP/CREATE/TRUNCATE`). ### Por que a IA classifica o chamado, não só pontua Cada chamado recebe uma classificação semântica (`ACTIONABLE_NOW`, `UNASSIGNED_ACTIONABLE`, `WAITING_REQUESTER`, `WAITING_VENDOR`, `WAITING_APPROVAL`, `SCHEDULED`, `DEPENDENCY_BLOCKED`, `NEEDS_COORDINATION`, `PROJECT_LONG_TERM`, `DUPLICATE_OR_OBSOLETE`, `INSUFFICIENT_CONTEXT`) mais um `next_action` concreto (nunca frases genéricas tipo "revisar chamado" — isso é validado e rejeitado, ver `logic/classification.js`). O prompt (`n8n/nodes/prepare-ai-prompt.node.js`) trata cronologia dos apontamentos como obrigatória e distingue "precisa contatar alguém" (acionável agora) de "já contatou e está esperando resposta" (`WAITING_*`). ### Determinismo do Top 10 `logic/diversity.js` desempata candidatos com score igual por `ticket.id` (ascendente) — sem isso, ordens de chegada diferentes entre execuções produziam Top10 diferentes para o mesmo dia, o que já causou um envio real duplicado em teste (ver `docs/superpowers/notes/2026-08-25-relatorio-correcao-final.md`, seção 5). Regressão coberta em `logic/diversity.test.js`. ## Arquivos ``` logic/*.js Lógica pura, testável com node:test (sem I/O, sem n8n) n8n/nodes/*.node.js Drivers finos que rodam dentro de Code nodes do n8n (cabeçalho "// @requires a.js b.js" declara quais módulos de logic/ precisam ser inlinados) n8n/workflow.template.json Fonte de verdade da estrutura do workflow (marcadores __BUILD__:arquivo.js são substituídos pelo conteúdo de logic/ na hora do build) n8n/deployed/coordenador-glpi-v2.n8n.json Artefato gerado, importável no n8n tools/build-workflow.js Inlina logic/ + n8n/nodes/ dentro do template tools/build-workflow.test.js Regressões de build (dependência transitiva, alwaysOutputData, columns.mappingMode, etc.) sql/ Queries GLPI usadas como referência/validação manual docs/superpowers/ Specs, planos e relatórios de execução (histórico, não é para reescrever — cada nota é um registro de um momento específico do projeto) ``` ## Build ```bash node tools/build-workflow.js node --test ``` O build só precisa rodar de novo quando `logic/*.js`, `n8n/nodes/*.node.js` ou `n8n/workflow.template.json` mudarem. O artefato gerado (`n8n/deployed/coordenador-glpi-v2.n8n.json`) **não é a fonte de verdade do ambiente de produção** — o workflow ativo no n8n foi promovido diretamente via API (`n8n_update_partial_workflow`) e hoje diverge do template em 3 valores de configuração de propósito: | campo | template (default de deploy limpo) | live (produção) | |---|---|---| | `ENVIRONMENT` | `dev` | `production` | | `SEND_ENABLED` | `false` | `true` | | `FORCE_SEND` | `false` | `false` | Isso é intencional: o template continua "seguro por padrão" para qualquer reimportação futura (nunca envia sozinho), e a promoção para produção é um ato explícito e auditável via `n8n_update_partial_workflow`, não algo que um rebuild acidental possa reverter. Se um dia o workflow live for recriado do zero a partir do template, repita a promoção manualmente (ver comando na nota `2026-08-25-relatorio-finalizacao-producao.md`). ## Rollback O V1 (`Coordenador GLPI - Chamados Abertos Slack.n8n.json`) nunca foi importado no n8n de produção — não há nada para "reverter para V1", ele continua disponível como plano B caso seja necessário abandonar o V2. Para desativar o V2 sem tocar em nada mais: `SEND_ENABLED=false` no node `Config - Coordenador GLPI v2` e/ou desativar o workflow. ## Credenciais e segredos Nenhum segredo vive neste repositório. Tudo (Slack bot token, OpenAI API key, credencial MySQL do GLPI) é gerenciado pelo credential store do próprio n8n e referenciado nos nodes só por `{id, name}`.