# Alertas e pendências críticas do ciclo (Etapa 77)

## Visão geral

A **Etapa 77** cria a **base de alertas e pendências críticas** do ciclo completo, para que o dashboard consolidado destaque **riscos**, **bloqueios** e **travas** comerciais e operacionais de forma clara. A camada é **agregadora**: usa os mesmos dados já usados pelo dashboard e aplica regras heurísticas para gerar alertas; não substitui nem duplica a lógica dos módulos específicos.

| Conceito | Descrição |
|----------|-----------|
| **Alerta** | **EventCycleAlert**: AlertId, CycleId, Title, Summary, Severity, Category, IsBlocking, RelatedSectionKey, SuggestedAction, CreatedAt, IsResolved. |
| **Severidade** | **EventCycleAlertSeverity**: Info, Warning, High, Critical. |
| **Categoria** | **EventCycleAlertCategory**: Commercial, QuestSession, Handoff, Producer, Scope, Preparation, Execution, FinalAcceptance, General. |
| **Estado agregado** | **EventCycleAlertState**: CycleId, Alerts, TotalAlerts, BlockingAlerts, HighSeverityAlerts, LastEvaluatedAt. |
| **Controller** | **EventCycleAlertController**: EvaluateAllAlerts, EvaluateAlertsForCycle, MarkAlertResolved, ClearResolvedForCycle, ClearAllResolved, GetTotals. |
| **Store** | **ResolvedCycleAlertStore**: MarkResolved(alertId), IsResolved(alertId), ClearResolvedForCycle, ClearAllResolved (em memória). |

## Regras de detecção (heurísticas)

Cada regra gera no máximo um alerta por ciclo; o AlertId é determinístico (CycleId + Category + slug do título) para permitir "marcar como resolvido" de forma estável.

| Condição | Título | Severidade | Bloqueante | Categoria | Secção relacionada |
|----------|--------|------------|------------|-----------|---------------------|
| Sessão Quest não associada ou sem SessionId | Sessão Quest não realizada | Warning | Não | QuestSession | SessaoQuest |
| Sessão com resultado Unknown ou ExplorationOnly | Sessão Quest inconclusiva | Warning | Não | QuestSession | SessaoQuest |
| Follow-up não concluído com prioridade High/Urgent (na oportunidade do ciclo) | Follow-up pendente com prioridade alta | High | Não | Commercial | Comercial |
| Pedido sem aceite do produtor | Pedido sem aceite do produtor | Critical | Sim | Producer | Handoff |
| Escopo não confirmado (readiness) | Escopo não confirmado | High | Sim | Scope | Produtor |
| Checklist com itens obrigatórios por concluir | Checklist com pendências obrigatórias | High | Não | Preparation | Produtor |
| Execução em estado Paused | Execução pausada | Warning | Não | Execution | Execucao |
| Execução em estado Blocked | Execução bloqueada | Critical | Sim | Execution | Execucao |
| Execução concluída mas relatório final não gerado/concluído | Relatório final pendente | High | Não | Execution | Execucao |
| Relatório concluído pelo produtor mas hotel ainda em PendingReview | Aceite final do hotel pendente | High | Não | FinalAcceptance | AceiteFinal |
| Hotel solicitou ajuste final | Ajuste final solicitado | Warning | Não | FinalAcceptance | AceiteFinal |

## Resolvidos (mock)

- **ResolvedCycleAlertStore** guarda em memória o conjunto de AlertIds marcados como resolvidos.
- **MarkAlertResolved(alertId)** adiciona o id ao conjunto; na próxima avaliação o alerta é filtrado e não aparece.
- **ClearResolvedForCycle(cycleId)** remove todos os resolvidos desse ciclo; **ClearAllResolved()** limpa tudo.
- "Resolvido" é apenas visual/gestão local: não altera o estado real do pedido (ex.: marcar "Escopo não confirmado" como resolvido não confirma o escopo).

## UI

- **EventCycleAlertsStripView** — Faixa: "Alertas: N | Críticos: X | Bloqueantes: Y | Avaliado: …". Cor vermelha quando há críticos ou bloqueantes. Inscrita em OnDataChanged.
- **EventCycleAlertsPanel** — Lista de alertas por ciclo; por alerta: título, resumo, severidade, categoria, acção sugerida, secção relacionada; botão "Marcar resolvido"; botões "Atualizar" e "Limpar resolvidos". Destaque em vermelho/laranja para Critical/High.
- **EventCycleDashboardPanel** — Para cada ciclo, bloco adicional: "Alertas: N (críticos: X, bloqueantes: Y)" e até dois títulos com acção sugerida quando há alertas. Cor vermelha se há bloqueantes.

## Ações

- **Atualizar alertas** — Refresh no painel ou strip (reavaliação ao reabrir/OnDataChanged).
- **Marcar alerta como resolvido** — Botão por alerta no EventCycleAlertsPanel; guarda no ResolvedCycleAlertStore; próximo refresh não mostra o alerta.
- **Limpar resolvidos** — Botão "Limpar resolvidos" no painel; limpa o store; todos os alertas voltam a ser reavaliados na próxima avaliação.
- **Navegar para a secção relacionada** — O campo RelatedSectionKey indica a secção do dashboard (ex.: Handoff, Execucao, AceiteFinal); o utilizador pode fazer scroll até essa secção no mesmo CRM (sem deep-link automático).

## Como isto ajuda gestão comercial e operacional

- **Visibilidade** — Riscos e travas aparecem num único sítio (strip + painel de alertas + resumo no dashboard por ciclo).
- **Priorização** — Críticos e bloqueantes destacam-se; acção sugerida e secção relacionada orientam o próximo passo.
- **Follow-up** — Alertas de follow-up pendente com prioridade alta e de aceite final pendente ajudam a não deixar oportunidades paradas.
- **Operacional** — Escopo não confirmado, checklist obrigatório, execução pausada/bloqueada e relatório final pendente ficam explícitos.

## Limitações actuais

- Sem persistência real: ResolvedCycleAlertStore e alertas são em memória.
- Sem automação real: não há notificações, lembretes nem integração com calendário.
- Sem integrações externas: dados apenas da camada Web e Producer (mock).
- "Marcar como resolvido" é mock: não altera o estado subjacente do ciclo.
