Skip to content

[FEAT] Sinais Cruzados — correlações entre métricas do engine e DORA #18

@trentas

Description

@trentas

Context

O Iris hoje reporta dois conjuntos de sinais em paralelo, mas desconectados:

Cada conjunto, isolado, conta metade da história. O valor maior — e quase ninguém no mercado expõe — está nas correlações entre os dois: usar sinais do código (que mudam rápido, antes da produção) como indicadores antecedentes de sinais de produção (que mudam devagar, depois do dano feito).

Isso é o terceiro bloco da reorganização proposta pra seção de evidência da visão (Velocidade & Confiabilidade / Durabilidade & AI Leverage / Sinais Cruzados) e fecha o loop da tese: como IA muda software delivery só faz sentido quando a evidência de engenharia conversa com a evidência de produção.

Stage: 3 (depende da capacidade de cross-system correlation listada no roadmap de Stage 3 no CLAUDE.md).

Problem

Três perguntas estratégicas que o Iris hoje não responde mesmo tendo todos os dados brutos:

  1. Cascade está prevendo Change Failure Rate? Cascade detector mede instabilidade no repo; CFR mede instabilidade em produção. Empiricamente, cascade subindo costuma preceder CFR subindo em semanas. Se confirmado nos dados, vira capacidade de aviso prévio — algo que o cliente paga.
  2. Código AI-assisted está mudando Lead Time, e o trade-off de durabilidade compensa? Sinais de estabilização por origem já existem no engine (cobertos por origin_metrics + stability_map). Lead Time vem do DORA. Cruzar os dois responde a uma das perguntas mais valiosas que executivo recebe na era atual e quase ninguém responde com dado.
  3. Deploy rápido é produtividade ou thrashing? Deployment frequency alta pode ser sinal de time saudável OU sinal de "fix em cima de fix do que acabou de deployar" (o AI trap clássico — volume sem qualidade). Cruzar deploy freq com new_code_churn_rate distingue os dois cenários.

Sem essas correlações, o Iris narrativamente fica preso em "qualidade do código" + "qualidade da entrega" como duas histórias separadas. A tese da plataforma exige conectar.

Proposal

Novo módulo de análise transversal que computa correlações entre séries temporais do engine e séries do DORA, e nova seção "Sinais Cruzados" no dashboard.

Módulo

iris/analysis/cross_correlations.py — função compute_correlation(series_a, series_b, *, max_lag_weeks=8) -> CorrelationResult. Retorna:

  • coeficiente de correlação (Pearson e Spearman)
  • lag onde a correlação é máxima (em semanas)
  • p-value
  • N de pontos usados (transparência de amostra)
  • flag actionable baseado em thresholds (ver acceptance)

Três correlações no escopo inicial

# Série A (engine) Série B (DORA) Hipótese a validar
1 cascade rate (semanal) Change Failure Rate (semanal) Cascade lidera CFR por 2-6 semanas
2 stabilization rate by origin (AI-assisted) Lead Time (semanal) Lead time menor em PRs AI, com penalty de durabilidade
3 new_code_churn_rate (semanal) Deployment Frequency (semanal) Deploy freq alta + churn alto = thrashing; deploy freq alta + churn baixo = saudável

Saída

  • Cada correlação como CrossCorrelationResult no payload agregado
  • Nova seção "Sinais Cruzados" no dashboard com 3 cards (um por correlação): coeficiente, lag, sample size, mini-gráfico das duas séries sobrepostas
  • iris/reports/narrative.py ganha findings condicionais quando correlação é forte E amostra é suficiente (ex: "Nos últimos 6 meses, picos de cascade rate precederam picos de CFR em mediana 3 semanas. Vale monitorar cascade como leading indicator.")

Acceptance criteria

  • iris/analysis/cross_correlations.py implementado com Pearson + Spearman + lag analysis + p-value
  • Thresholds documentados pra flag actionable: |r| ≥ 0.5, p ≤ 0.05, N ≥ 12 semanas. Calibrar empiricamente nos primeiros 3-5 repos
  • Três correlações do escopo computadas e expostas no payload agregado
  • Schema (iris/models/metrics.py) + TS types + report writer + narrative findings — chain completa
  • Seção "Sinais Cruzados" no dashboard com 3 cards (1 por correlação)
  • Quando amostra insuficiente (N < 12 semanas, ou um dos lados ausente), UI mostra estado "amostra insuficiente" explicitamente — nunca um número falsamente preciso
  • Narrative finding só dispara quando correlação cruza thresholds; nunca declara causalidade, sempre "associado a" / "precedeu em mediana N semanas"
  • docs/METRICS.md ganha entrada explicando o método e as 3 correlações
  • docs/VISION.md (ou doc de posicionamento equivalente) reorganizado em 3 blocos (Velocidade & Confiabilidade, Durabilidade & AI Leverage, Sinais Cruzados) — opcional, mas alinhado com a tese

Non-goals / out of scope

  • Outras correlações além das 3. Cada par novo é proposta própria (ou um upgrade futuro desta). Sem "engine genérico de correlações" agora — YAGNI.
  • Causal inference. O módulo computa correlação e lag, não causalidade. Narrative e UI nunca dizem "X causa Y", só "X precedeu Y em média N semanas com correlação r".
  • Streaming / near-real-time. Roda no batch de análise normal do engine.
  • Business outcomes ingestion (ex.: revenue, métricas de produto vindas de SaaS externos como Amplitude / Stripe). Atualmente fora de escopo do Iris (princípio de "Iris não é tracker de produtividade nem ingestion universal"); se mudar, abrir ADR em docs/DECISIONS.md antes.
  • Detecção automática de novos pares correlacionáveis. Tentação tem (rodar correlação cega entre todas as séries), risco de falsos positivos é grande. Manter curado.

Risks & open questions

Riscos:

  • Correlação fraca ou nula nos dados reais. Plausível pra org pequena com pouco deploy. Mitigação: threshold de amostra explícito, UI honesta sobre "amostra insuficiente", não forçar narrativa quando dado não suporta.
  • Lag detection é instável com séries curtas. max_lag_weeks=8 exige pelo menos ~20 semanas pra ser confiável. Documentar e travar narrative pra repos com histórico curto.
  • "Leading indicator" é uma hipótese, não fato. Mesmo com r alto e p baixo, declarar "cascade prevê CFR" no produto é uma afirmação forte. Linguagem do narrative precisa ser conservadora: "associado a", "precedeu em mediana", nunca "prevê".
  • Princípio build(deps): Bump actions/setup-node from 4 to 6 #4 (métricas são hipóteses, não verdades) vale especialmente aqui. A flag actionable é uma sugestão pro cliente investigar, não uma conclusão.

Dependências:

Perguntas em aberto:

  1. Janela default — semanal parece certo pra deploy/CFR/lead time, mas alguns repos têm deploy diário e mereceriam diário. Decidir se janela é fixa ou adaptativa.
  2. Como agregar quando o cliente tem múltiplos repos no Datadog (1 service vs N services por repo). Provável: correlacionar por repo individual + agregar no nível da org com peso.
  3. Validar Pearson vs Spearman empiricamente — se as séries têm outliers fortes (incidentes raros e grandes), Spearman é mais robusto. Pode ser que Spearman seja o default e Pearson o auxiliar.
  4. O par 2 (stabilization × Lead Time) tem duas dimensões (origin AI vs HUMAN). Decidir se reporta como duas correlações separadas ou como uma única "diferença AI menos HUMAN" cruzada com Lead Time.

Target release / date

A definir — depende do landing date de #15. Estimativa: 4-6 semanas após #15 chegar em prod com 30+ dias de dados.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions