SAC — As 3 Ramificações do sacNode

SAC — As 3 Ramificações do sacNode

Para future Claude

Esta nota é um aprofundamento da seção "② As 3 ramificações do sacNode" do canvas Excalidraw (Mercado Livre Jornada) e da seção 4 do Mapa Geral. O sacNode recebe o evento já resolvido (productContext incluído, ver Diagrama 4a) e decide o que fazer de acordo com state.eventType. Cada ramo tem regra própria — só CUSTOMER_QUESTION pode chegar ao verde.


O diagrama

↳ detalhe da Parte 4 (SAC) · ramo decidido por state.eventType — ver Diagramas 4a (gatilho) e 4b (decisão CUSTOMER_QUESTION) sacNode (agent.ts) branch por state.eventType CQS CUSTOMER_QUESTION único ramo que pode responder sozinho (state.eventType) 1 · LLM responde ctx.llm.complete() → answer, confident, detectedPattern 2 · Parse válido? JSON + schema ok? · falha → draft (llm_parse_failed) 3 · Compliance ok? palavrão · URL · CPF/CNPJ/e-mail bloqueia → draft (compliance_block) 4 · Confiante? confident === true? · não → draft (low_confidence) VERDE answerQuestion() applied:true DRAFT (humano) queueSacDraft() SAC_QUESTION_DRAFT PSM POST_SALE_MESSAGE nunca envia sozinho (decisão de design D1) 1 · Gera resposta draftPostSaleMessage() → LLM + compliance · trunc >350 chars 2 · Sempre rascunho queueSacDraft → reason: post_sale_draft (ou erro) AMARELO · sempre rascunho SAC_POST_SALE_DRAFT na inbox humano edita e envia (ExecuteSacDraft) CLM CLAIM_OPENED sempre TIER_3 nunca age sozinho 1 · Gera sugestão recommendedAction + rationale (apenas sugestão, não decide) 2 · Approval pendente createPendingApproval() CLAIM_REVIEW · applied:false VERMELHO · sempre TIER_3 humano age direto no ML claim-action endpoints (BUN-122) · sem inbox LEGENDA Identificação do ramo (header) Etapa do ramo Ponto de decisão (state.eventType) Verde · responde sozinho (applied:true) Amarelo · rascunho na inbox (humano edita/envia) Vermelho · TIER_3, sem inbox (humano age no ML)


CUSTOMER_QUESTION — único ramo que pode responder sozinho

  1. ctx.llm.complete(){ answer, confident, detectedPattern }.
  2. JSON + schema válidos? Falha → draft (llm_parse_failed).
  3. Compliance ok? (palavrão · URL · CPF/CNPJ/e-mail) Bloqueia → draft (compliance_block).
  4. confident === true? Não → draft (low_confidence).

Se passar pelas 4 perguntas: answerQuestion(qId, answer) + audit SAC_ANSWERED, applied: true. Se o envio ao ML falhar (meli_answer_failed), não é mais auto — vira draft mesmo assim. Em qualquer outro caso (parse, compliance ou confiança), queueSacDraft cria um SAC_QUESTION_DRAFT.

POST_SALE_MESSAGE — nunca envia sozinho (decisão de design D1)

  1. draftPostSaleMessage() → LLM gera answer (roda compliance; marca truncated se passar de 350 caracteres).
  2. Sempre queueSacDraftSAC_POST_SALE_DRAFT, com reason igual a post_sale_draft (ou compliance_block / llm_parse_failed se algo falhar antes).

Todo resultado vira rascunho na inbox; o humano edita e envia via ExecuteSacDraftmeli.sendMessage. Não existe caminho em que essa ramificação responda sozinha.

CLAIM_OPENED — sempre TIER_3, nunca age sozinho

  1. reviewClaim()generateClaimSuggestion(): gera recommendedAction + rationale — é só sugestão, a IA não decide.
  2. createPendingApproval(CLAIM_REVIEW), TIER_3, applied: false. Nenhuma ação chega a tocar o Mercado Livre.

Claim não passa pela inbox de rascunho (ExecuteSacDraft): não existe "enviar texto" pra um claim. O humano resolve direto no Mercado Livre pelos endpoints de claim (BUN-122); a IA só aconselha.

Pra quem não é dev

sacNode é o ponto do código onde o agente de SAC decide o que fazer com cada evento. state.eventType é o campo que diz qual dos 3 tipos de evento chegou. Draft é um rascunho que espera revisão humana antes de ir pro Mercado Livre. TIER_3 é o nível de aprovação mais alto, sempre obrigatório pra claims — a IA nunca age sozinha nesse caso.