Files
SLACK_COORD_RELATORIO/docs/superpowers/specs/2026-08-24-coordenador-glpi-v2-design.md
T
GustavoandClaude Sonnet 5 de147107d5 docs: add V2 design spec (approved)
docs/superpowers/specs/2026-08-24-coordenador-glpi-v2-design.md
Covers Etapa 0 recovery findings, architecture, data model, AI schema,
scoring, message format, shadow mode. Approved by user in chat.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 15:00:34 -03:00

9.9 KiB
Raw Blame History

Coordenador GLPI V2 — Seleção acionável por IA + regras determinísticas

Status: aprovado pelo usuário em 2026-08-24. Implementação em DEV, shadow mode.

Contexto (Etapa 0 — o que existe hoje)

Projeto 100% n8n, sem backend tradicional:

  • Coordenador GLPI - Chamados Abertos Slack.n8n.json: workflow importável (V1).
  • sql/top_10_chamados_abertos_glpi.sql: query base (duplicada dentro do node Code - Montar SQL Top 10).
  • docker-compose.yml + .env(.example): n8n local (Docker Desktop indisponível neste ambiente de execução; não foi possível subir localmente).
  • tools/: pasta vazia, reservada — reaproveitada nesta V2 para o script de build do workflow.
  • Repositório git local sem nenhum commit (tudo untracked). Nada a preservar de histórico.

Lógica V1 (comprovada, reduziu backlog de ~167 para ~90)

  • Trigger: Schedule Trigger cron 0 8 * * 1-5 (+ Manual Trigger para teste).
  • Node Config - Coordenador GLPI (Set): slack_webhook_url, glpi_base_url, dias_sem_interacao_alerta (default 2), horas_sla_risco (default 8).
  • Node Code - Montar SQL Top 10 monta a query com esses parâmetros e executa via node MySQL (credencial MySQL GLPI, nunca configurada em nenhum ambiente acessível a mim).
  • SQL: filtra is_deleted=false AND status NOT IN (5,6) e exclui categorias ADMINISTRATIVO%, DESENVOLVIMENTO%, INFRA% (via completename/name). Calcula dias_aberto, dias_sem_interacao (maior data entre followups públicos, tarefas, date_mod, date — nunca negativo), sla_vencido, sla_em_risco, sem_tecnico. Score: SLA vencido +100, SLA em risco +45, sem interação (+35/+25/+10 por faixa), idade até +30, prioridade×8, urgência×5, impacto×5, sem técnico +25. Seleção final em blocos (3 SLA vencido, 3 sem interação, 2 sem técnico, 2 prioridade alta recente, complemento pelo ranking geral), sem repetir chamado entre blocos, LIMIT 10.
  • Node Code - Reincidencia e mensagem curta: reincidência via $getWorkflowStaticData('global') (chamado apareceu N dias seguidos: 1 normal, 2 reincidente, 3+ escalar). Monta mensagem determinística e um prompt_ia.
  • AI Agent - Revisar mensagem (LangChain agent + Z IA Chat Model, GLM-4.5-flash via endpoint compatível OpenAI): só revisa clareza/reduz texto, proibido inventar fato/motivo/ação/prazo.
  • Code - Preparar mensagem Slack: valida que a saída da IA preserva todos os #id e links e não contém campos proibidos (motivo/ação/prazo); se falhar, usa o texto determinístico puro (fallback já existente e funcional).
  • HTTP - Slack enviar mensagem: POST no webhook configurado no Config node.

Causa técnica do "loop" (chamados repetindo o Top 10 sem ação real)

O score é dominado por sinais que só crescem com o tempo (dias_sem_interacao, SLA vencido, idade) e a reincidência do V1 é só um contador informativo — não penalizada no score nem interrompida por cooldown. Um chamado com SLA vencido há semanas e sem ação prática do suporte continua pontuando alto todos os dias e reentra nos blocos "SLA vencido"/"sem interação", empurrando candidatos com ação real (mas sinais mais baixos) para fora do Top 10.

Ambiente DEV confirmado

Instância n8n real e acessível via MCP: https://devn8n.gtigrupo.com.br (73 workflows). Não existe lá nenhum workflow do "Coordenador GLPI - Top 10"; o que existe de GLPI é um chatbot de abertura de chamados via WhatsApp ([DEV] GTI - GLPI x WhatsApp (Z-PRO) v7, ativo, 52 nodes) e um sub-workflow arquivado de lock/unlock de entidade (Enforcer - GLPI). Ambos fora de escopo — não serão alterados. Não há credencial MySQL do GLPI nem de IA "Z IA" nesse ambiente.

Decisões do usuário (2026-08-24):

  • Credencial MySQL: nome MySQL GLPI - Coordenador, criada pelo usuário diretamente no n8n DEV.
  • Credencial IA: nova credencial OpenAI - Coordenador GLPI (id WUGriAn5FgCiLza2, tipo openAiApi) criada por mim com chave-placeholder óbvia; o usuário substitui o valor real direto na UI do n8n. Provedor: OpenAI (GPT), não Z IA, não reaproveitar credencial existente de outro workflow.
  • Nenhum envio real (Slack/WhatsApp) sem destino seguro definido — por padrão, shadow mode só grava/loga, nunca publica externamente.

Objetivo da V2

Trocar "quais chamados são mais problemáticos" por "quais chamados têm ação concreta que o suporte consegue executar agora", mantendo Top 10, mensagem curta (mais curta que hoje) e todas as regras já comprovadas (exclusão administrativa, SLA, prioridade).

Arquitetura

Workflow novo e separado no n8n DEV — V1 permanece intocado (local e não importado em nenhum ambiente acessível):

[DEV] Coordenador GLPI - Chamados Abertos v2 (Shadow), inativo por padrão, disparado por Manual Trigger durante a validação.

Pipeline (7 estágios):

  1. Seleção inicial: SQL reaproveita a base V1 (mesmas tabelas, mesmo dias_sem_interacao, mesma exclusão administrativa) mas remove o corte de blocos/LIMIT 10 — devolve até CANDIDATE_POOL_SIZE (padrão configurável, começar em 60) candidatos ordenados pelo score_criticidade barato atual. Este número é o tamanho do funil, não o volume que vai para a IA.
  2. Filtros determinísticos: elegibilidade por status, administrativo (já no SQL), duplicidade.
  3. Memória/cache: n8n Data Table coordenador_glpi_memoria (não staticData — resolve a fragilidade documentada no README do V1 de perder histórico ao reimportar o workflow). Colunas: ticket_id, last_analyzed_at, last_sent_at, last_context_hash, last_meaningful_change_at, ai_classification, ai_confidence, blocker_type, waiting_for, next_action, next_review_at, times_sent, times_sent_30d, consecutive_days_sent, last_score, last_ai_reason, updated_at.
  4. Hash de contexto: função JS pura (sem crypto do Node — mais portável em Code node) sobre campos que só mudam por evento real (status, técnico, grupo, último followup/tarefa por id+data, solução, pendência, aprovação, vínculos). Nunca inclui dias_aberto/dias_sem_interacao.
  5. Coleta de contexto: só para candidatos sem cache válido (hash mudou ou passou next_review_at). Usa tabelas já confirmadas (glpi_itilfollowups, glpi_tickettasks, glpi_tickets_users, glpi_users, glpi_entities, glpi_itilcategories). Tabelas adicionais candidatas (soluções, aprovações, chamados vinculados) só entram depois de confirmadas por introspecção real no banco (SHOW TABLES/DESCRIBE) quando a credencial MySQL estiver disponível — nunca assumidas de antemão. Cada fonte opcional é isolada com fallback gracioso (se a tabela não existir/,divergir, o pipeline continua sem ela e registra isso no log).
  6. Classificação IA: só os candidatos sem cache válido chegam aqui (estágio 4), até o teto AI_MAX_CANDIDATES (padrão 30 — proteção de custo/latência por execução; se sobrarem mais candidatos elegíveis que o teto, prioriza por score_criticidade e deixa o resto para a próxima execução via next_review_at). HTTP direto à API da OpenAI (Chat Completions com response_format: json_schema) — mesmo padrão já usado no workflow [DEV] GTI - GLPI x WhatsApp v7 deste n8n (não o AI Agent/LangChain do V1, que só polia texto). Classes: ACTIONABLE_NOW, UNASSIGNED_ACTIONABLE, WAITING_REQUESTER, WAITING_VENDOR, WAITING_APPROVAL, SCHEDULED, DEPENDENCY_BLOCKED, NEEDS_COORDINATION, PROJECT_LONG_TERM, DUPLICATE_OR_OBSOLETE, INSUFFICIENT_CONTEXT. Schema conforme o documento do usuário (classification, actionable_today, confidence, blocker_type, waiting_for, next_action, suggested_action_type, business_risk, reason, evidence). Validação estrita em código; JSON inválido/timeout/erro → fallback determinístico (log explícito de fallback, memória não corrompida).
  7. Regras determinísticas + score + ranking: acionabilidade IA como fator dominante; SLA/idade continuam pesando mas não dominam sozinhos; penalidade forte para bloqueio externo/WAITING_*/NEEDS_COORDINATION/reenvio sem mudança (cooldown crescente); exceção permite prioridade crítica furar cooldown. Diversidade leve entre grupos conceituais. Top 10 fixo (não mexe no volume nesta fase).
  8. Mensagem final: formato curto (exemplo no design aprovado), sem score/confiança/justificativa longa. Envio real desligado por padrão (SHADOW_MODE=true): grava em Data Table/log, não publica em canal nenhum até haver destino seguro confirmado pelo usuário.
  9. Bloqueados/coordenação: saída separada, só com novidades/mudanças desde a última vez (não repete lista idêntica).
  10. INSUFFICIENT_CONTEXT: telemetria própria (quais chamados, por quê, o que falta).

Configuração (env vars no estilo já usado no n8n desta org, padrão env(K, default))

AI_ENABLED, AI_PROVIDER=openai, AI_MODEL, CANDIDATE_POOL_SIZE=60, AI_MAX_CANDIDATES=30, TOP_N=10, COOLDOWN_DAYS, AI_CONFIDENCE_THRESHOLD, AI_MAX_CONTEXT_CHARS, DEV_MODE=true, SHADOW_MODE=true.

Testes

Sem framework de testes no projeto hoje. Lógica determinística pura (hash, cooldown, score, elegibilidade, diversidade, formatação de mensagem) extraída para logic/*.js, testada com o runner nativo do Node (node:test, zero dependência nova). Script em tools/ monta o JSON do workflow a partir desses módulos (fonte única, sem divergência entre o testado e o que roda no n8n). Cobrir os 17 casos do documento do usuário (seção 22).

Shadow mode

Mesma execução manual roda a query legado (V1, sem corte) e a lógica nova lado a lado, grava os dois rankings e o diff (quem entrou/saiu e por quê) em Data Table + endpoint de debug (mesmo padrão Debug - Ver Log/Debug - Montar Painel já usado no workflow de WhatsApp desse n8n).

Fora de escopo / não fazer

Produção; qualquer workflow do n8n DEV não relacionado a este projeto (WhatsApp GLPI, Enforcer, Klingo, ClinicAll, SysLife, ZPRO, Asaas etc.); reduzir o Top 10 para menos de 10; aumentar o tamanho da mensagem; deixar a IA decidir sozinha; reprocessar todo dia sem necessidade; escrever diretamente em tabelas do GLPI.