# Efetividade causal — especificação v0.1

> **APROVADO v0.1** por gestão acadêmica + NAP + TI em 24/07/2026.  
> Gate `P2-001` / `P2-002` fechado no plano P2 (`docs/pesa-p2-plano-executavel.html`).  
> P2-003 (snapshots de baseline), API e painel causal estão liberados para implementação.

---

## 0. Honestidade analítica (obrigatória)

- Isto **não** é um ensaio clínico randomizado (RCT).
- O método v0.1 é **quasi-experimental**: matching / grupo de comparação por elegibilidade.
- A UI e a API devem rotular explicitamente: `metodo: "matching_heuristico_v0.1"` e limitar claims (“impacto estimado”, nunca “prova causal absoluta”).
- Sem baseline snapshot ou com `n` insuficiente: **não inventar** taxa, lift ou IC — exibir vazio / “dados insuficientes”.

---

## 1. Objetivo (P2-001)

Evoluir a efetividade atual (taxa bruta de “melhora”) para medição por **coorte**:

1. **Before / after** no grupo tratado (quem recebeu intervenção/campanha).
2. **Grupo de comparação** (elegível não atendido ou pareado).
3. **Retenção / rematrícula incremental** (lift) quando o outcome de permanência estiver observável.

Isso atende a US-04: *comparar resultado com grupo de controle para medir efetividade real*.

---

## 2. Outcomes oficiais v0.1

Cada análise declara **um outcome primário** e pode exibir secundários. O painel mensal usa os três abaixo.

| ID | Outcome | Definição positiva (sucesso) | Janela | Fonte |
|----|---------|------------------------------|--------|-------|
| **O1** | Melhora de risco | Queda do score de risco **≥ 5 pontos** **ou** redução de 1 nível de risco (ex.: alta→média), medido no fim da janela vs baseline | **30 dias** após `t0` (secundário em **15 dias**) | Score/nível em `pesaEstudantes` + snapshot |
| **O2** | Rematrícula / permanência | Label de rematrícula = 0 (“rematriculou”) conforme spec v0.1 em `modelos-e-score` (janela configurável da IES) | Janela de observação de rematrícula (`fim + diasGraca` ou fallback) | Label institucional + config período |
| **O3** | Conclusão operacional | Caso de fila ou participante de campanha em status `concluido` com ao menos 1 registro de ação | Até o encerramento do caso/campanha (SLA de referência) | `app_fila_caso` / `app_campanha_participante` |

### 2.1 Precedência e uso

- **Painel tático (quinzenal/mensal curto):** O1 (30d) + O3.
- **Painel executivo de impacto (mensal/semestral):** O2 quando a janela de rematrícula estiver fechada; senão O2 fica `pendente_janela`.
- O3 **não** substitui O1/O2: conclusão operacional sem melhora de risco continua sendo sucesso de processo, não de impacto acadêmico.

### 2.2 Classificação de resultado short-term (alinha §2.3 dos indicadores)

Para O1, no fim da janela:

| Classe | Critério |
|--------|------------------------|
| **melhora** | Δscore ≤ −5 **ou** nível de risco caiu |
| **sem_mudanca** | \|Δscore\| &lt; 5 e nível igual |
| **piora** | Δscore ≥ +5 **ou** nível de risco subiu |

`resultadoAcao` legado (quando existir) pode ser usado como evidência auxiliar, mas **não** como única fonte se houver score/nível.

### 2.3 Exclusões / censura (não entram no denominador de impacto)

Aplicar quando o campo existir na base:

- conclusão / colação prevista ou ocorrida no período;
- trancamento formal;
- transferência externa documentada;
- óbito;
- estudante removido do dataset global no período (sem baseline recuperável).

Casos censurados aparecem em contagem à parte (`n_censurados`), não em % de melhora.

---

## 3. Tempo zero (`t0`) e janelas

| Evento que define `t0` | Ordem de preferência |
|------------------------|----------------------|
| 1ª atualização de status da fila para `em_atendimento` | Preferencial para análise de fila |
| Inclusão do estudante como participante de campanha | Preferencial para análise por playbook |
| 1º registro de intervenção com data | Fallback se não houver fila/campanha |

**Janelas de observação O1**

- Curto: `t0 + 15 dias`
- Consolidação (padrão do relatório): `t0 + 30 dias`
- Recidiva (indicador já existente): resolvido que volta a alerta em **30 dias** após conclusão

**Baseline (`t0−`)**  
Snapshot capturado no momento de `t0` (ou imediatamente antes): score de risco, nível, score rematrícula (se houver), curso, flags financeiros/AVA/frequência disponíveis.

Sem snapshot: o caso **não entra** na coorte causal v0.1 (pode entrar só em métricas operacionais P1-009).

---

## 4. Coortes: tratado vs comparação (P2-002)

### 4.1 Grupo tratado (`T`)

Estudante elegível que, no período de análise `[P_ini, P_fim]`:

- teve `t0` definido (fila **ou** campanha), **e**
- possui baseline snapshot, **e**
- **não** está na lista de censura.

Subtipos (filtros do painel):

- `T_fila` — origem fila priorizada  
- `T_campanha` — origem campanha (agrupar por `playbook_key` / `tipo_risco`)  
- `T_intervencao` — só registro legado de intervenção (quando fila/campanha ausentes)

### 4.2 Grupo de comparação (`C`) — matching heurístico v0.1

**Elegível não atendido** no mesmo período, com matching 1:k (k padrão **1**, máximo **3**).

**Pool de elegíveis (`C_pool`):**

1. Mesmo **curso** (obrigatório quando o usuário não for perfil global).
2. Score de risco no baseline do tratado dentro de **±10 pontos**
   **ou** mesmo **nível de risco** se score ausente.
3. Ativo no semestre de referência `S`.
4. **Sem** `t0` de fila/campanha no período `[P_ini − 7d, P_fim + janela_O1]` (não contaminar o controle).
5. Não censurado.

**Algoritmo de pareamento:**

1. Para cada `i ∈ T`, ordenar candidatos por `|score_i − score_j|`, desempate por mesmo nível, depois por proximidade de score de rematrícula (se ambos tiverem).
2. Atribuir até `k` controles sem reutilização no mesmo relatório (matching sem reposição no corte mensal).
3. Se não houver candidato: `i` entra em `T_sem_par`; **não** forçar match — reportar cobertura de matching.

### 4.3 O que **não** é controle

- Estudante já em atendimento no período.
- Estudante de outro curso (salvo perfil global com filtro explícito “todos”).
- Média institucional sem matching (pode existir como referência descritiva, **não** como lift causal).

---

## 5. Métricas reportadas

Seja `Y` o outcome (O1/O2/O3) binário de sucesso.

| Métrica | Fórmula | Uso |
|---------|---------|-----|
| Taxa tratada | `p_T = (# sucessos em T) / n_T` | Before/after consolidado no tratado |
| Taxa comparação | `p_C = (# sucessos em C) / n_C` | Contrafactual estimado |
| **Lift / retenção incremental** | `lift = p_T − p_C` | Impacto estimado da intervenção |
| IE (legado) | `(1.0·%melhora)+(0.4·%sem_mudança)−(0.6·%piora)` | Só no tratado; não misturar com lift |
| Cobertura matching | `n_T_pareados / n_T` | Qualidade do desenho |

**Intervalo de confiança:** Wilson 95% para proporções; para `lift`, diferença de duas proporções com n mínimo.

**Regra de publicação:**

- Exibir % e lift somente se `n_T ≥ 10` **e** `n_C ≥ 10`.
- Se `5 ≤ n < 10`: exibir n e taxa **sem** IC / sem recomendação “escalar”.
- Se `n < 5`: apenas contagens.

---

## 6. Recomendação operacional (S2 / P2-007 — entregue)

Heurística de texto, só com `n_T,n_C ≥ 10`:

| Condição | Recomendação |
|----------|----------------|
| `lift ≥ 0,10` e estável em 2 cortes | **Escalar** playbook/tipo |
| `\|lift\| < 0,05` | **Manter** e revisar execução/SLA |
| `lift ≤ −0,05` | **Pausar / revisar** protocolo |

A recomendação é **sugestão de gestão**, não automação de desligamento de campanha.

API: `GET /api/metricas/efetividade-mensal` (`backend/services/efetividade_mensal.py`). UI: `efetividade.html`.

---

## 7. Contrato de API (P2-004 — entregue)

`GET /api/metricas/efetividade-coorte`

Query: `de`, `ate`, `outcome=O1|O2|O3`, `origem=fila|campanha|intervencao|todas`, `playbook_key`, `curso`, `janela_dias`, `k_match`.

Resposta mínima:

```json
{
  "status": "ok",
  "metodo": "matching_heuristico_v0.1",
  "outcome": "O1",
  "janela_dias": 30,
  "periodo": { "de": "2026-06-01", "ate": "2026-06-30" },
  "tratado": { "n": 42, "sucessos": 18, "taxa": 0.429 },
  "comparacao": { "n": 42, "sucessos": 11, "taxa": 0.262 },
  "lift": 0.167,
  "cobertura_matching": 0.95,
  "n_censurados": 3,
  "aviso": null
}
```

Implementação: `backend/services/efetividade_coorte.py` + `backend/routers/metricas.py`. Painel: `efetividade.html` (P2-005).

---

## 8. Persistência necessária (P2-003 — entregue)

Tabela `app_baseline_snapshot` (única por `estudante_id + origem + origem_ref`):

- `estudante_id`, `t0`, `origem` (`fila`|`campanha`|`intervencao`)
- `score_risco`, `nivel_risco`, `score_rematricula`
- `curso`, `playbook_key` (se campanha)
- `features_json` (subset mínimo: financeiro, AVA, frequência)

Captura automática (imutável — primeira gravação vence):

| Origem | Momento `t0` |
|--------|----------------|
| `fila` | 1ª transição para `em_atendimento` |
| `campanha` | Inclusão do participante (`origem_ref` = campanha_id) |
| `intervencao` | 1º registro em `/api/intervencoes/registrar` (fallback) |

Serviço: `backend/services/baseline_snapshot.py`.

---

## 9. RBAC e equidade

- Mesmas regras de curso/perfil da P1 (`rbac_helpers`).
- Recorte de equidade (indicador já previsto): diferença de `lift` por perfil **somente** com n mínimo por estrato; caso contrário omitir.

---

## 10. Definition of Done do gate (P2-001 / P2-002)

- [x] Outcomes O1/O2/O3 e janelas revisados e assinados (gestão acadêmica + NAP + TI).
- [x] Regras de tratado/comparação e matching aceitas, com limitações explícitas.
- [x] Limiares de n / IC / “não inventar métrica” aceitos.
- [x] Plano P2 atualizado para **APROVADO v0.1** e liberação de P2-003+.

---

## 11. Limitações conhecidas (v0.1)

- Viés de seleção: quem entra na fila pode diferir do elegível não atendido mesmo após matching.
- Contaminação: intervenções informais fora do sistema subestimam o controle.
- O2 depende do fechamento da janela de rematrícula configurada pela IES.
- Score heurístico (não ML calibrado) → Δscore é proxy, não verdade ground-truth.

---

*Documento-gate P2 · APROVADO v0.1 em 24/07/2026 · alinhado a P1 entregue (fila/campanhas/métricas operacionais).*
