Skip to content

[METRIC] Flow Load — WIP simultâneo de engenharia, por janela e por intent #16

@trentas

Description

@trentas

Hipótese

Essa métrica nos ajuda a entender como IA muda software delivery porque o aumento de produtividade individual com assistentes de IA tende a se traduzir em mais trabalho aberto em paralelo, não necessariamente em ciclo mais curto. Sem medir WIP simultâneo, confundimos throughput (PRs/semana) com fluxo saudável. O cruzamento Flow Load × Flow Distribution (WIP por intent) é uma medida que Kersten propõe e quase ninguém do mercado expõe — e que pode mostrar, por exemplo, que IA está empurrando o time pra abrir mais features em paralelo enquanto o WIP de fixes/refactors fica estagnado.

Definição

Métrica principal — Flow Load por janela:

Para cada bucket temporal (default: semana ISO), contar quantos PRs estavam em estado aberto em algum momento dentro do bucket.

Um PR conta no bucket [t_start, t_end] se:

  • created_at < t_end E
  • (merged_at é nulo OU merged_at > t_start) E
  • (closed_at é nulo OU closed_at > t_start)

Resultado: série temporal {week → wip_count}.

Quebra por intent — Flow Load × Flow Distribution:

Mesma contagem, segmentada por intent do PR: feature, fix, refactor, config, unknown. Resultado: série temporal {week → {intent → wip_count}}.

Intent do PR: classificar pelo título do PR usando as regras de intent_classifier.py (mesmas heurísticas já validadas pra commits). Opção alternativa — classificar agregando o intent dos commits do PR — fica como decisão de implementação a validar contra dados reais.

Proxies complementares:

  1. Branch concurrency por janela — branches ativos (com commits) em algum momento do bucket. Pra dados retroativos, reconstruir via referências em merge commits (Merge pull request #N from owner/branch) e via git for-each-ref pro snapshot atual. Limitação documentada: branches deletados sem deixar marca em merge commit ficam invisíveis.

  2. Author concurrency por janela — número de autores distintos com commits no bucket. Captura paralelismo real de trabalho (inclui código ainda sem PR aberto). Fonte: git log direto, já disponível.

Janela default: semana ISO. Bucket parametrizável (dia/semana/mês) via config.

Edge cases:

  • PR ainda aberto na data de execução → conta em todos os buckets desde created_at
  • PR criado e fechado no mesmo bucket → conta nesse bucket
  • Buckets sem PRs em curso → entrada explícita wip_count: 0 (não omite)

Fonte do sinal

múltiplas fontes

(PR open/merge/close timestamps via GitHub API; commits + autores + datas via git log; títulos de PR pro intent classifier; merge commits pra reconstrução retroativa de branches)

Risco de ranqueamento individual

Baixo, com uma ressalva. As três séries são agregados de sistema (contagens por janela), não atribuem WIP a pessoas. Princípio #2 preservado por construção.

Ressalva — Author concurrency. A métrica exposta é quantos autores distintos por janela. Implementação NÃO deve persistir nem expor a lista de autores por janela, mesmo intermediariamente no schema, pra remover qualquer caminho que permita derivar "Fulano teve WIP alto na semana X". Documentar isso no docstring do módulo. Code review da PR de implementação deve checar isso explicitamente.

Chain checklist (releasa completa)

Pré-requisito (sai do escopo do flow_load.py puro, mas bloqueia a métrica):

  • Estender iris/models/pull_request.py — tornar merged_at opcional, adicionar closed_at: datetime | None, state: Literal["open", "closed", "merged"]
  • Estender iris/ingestion/github_reader.py — buscar também PRs abertos e PRs fechados-sem-merge na janela; ajustar consumidores existentes (pr_lifecycle.py filtra state == "merged" na entrada)

Chain da métrica:

  • iris/analysis/flow_load.py — função analyze_flow_load(prs, commits, *, bucket="week") -> FlowLoadResult retornando as 3 séries (wip total, wip por intent, branch/author concurrency)
  • iris/metrics/aggregator.py — wiring + emissão dos campos no payload agregado
  • iris/models/metrics.py — schemas das séries (tipo: dict[str (ISO week), int | dict[intent, int]])
  • iris/reports/writer.py — saída em JSON/markdown
  • iris/reports/narrative.py — finding threshold-based (sugestão: "WIP de features cresceu Y% em N semanas sem ganho proporcional em throughput"; thresholds a calibrar com 3-5 repos)
  • platform/src/types/metrics.ts — TS types das séries
  • Platform UI — visualização temporal (área stacked por intent + linhas de branch/author concurrency); tela /repos/[id] e card resumo na home
  • docs/METRICS.md — entrada nova com definição, edge cases e limitações de cobertura

Notas / prior art

Prior art:

  • Mik Kersten, Project to Product — Flow Framework (Flow Load, Flow Distribution, Flow Time, Flow Velocity, Flow Efficiency)
  • Pluralsight Flow / LinearB expõem WIP, mas sem o cruzamento por intent

Limitação honesta a comunicar no produto: Flow Load via PR/git mede WIP de engenharia, não WIP de produto. Backlog, discovery, design, e trabalho em branches privadas locais não aparecem. O memo executivo e a UI devem deixar isso explícito pra não criar a impressão de "WIP total da empresa".

Pontos abertos pra resolver no PR de implementação (não nesta proposta):

  1. Intent do PR via título vs via agregação de commits — escolher a abordagem mais robusta empiricamente. Custo de implementar as duas e medir desvio é baixo.
  2. Backfill de PRs abertos antigos — primeira sincronização pode ter custo de API alto. Definir limite de janela de backfill (sugestão: 180 dias) e backfill incremental nas seguintes.
  3. Reconstrução retroativa de branches — confirmar quão confiável é o pattern de merge commit em repos reais antes de incluir a proxy. Se cobertura for <50%, considerar deprecar e ficar só com Flow Load + author concurrency.
  4. Estimativa de tamanho da entrega: proposta original sugeria 150-200 linhas. Com o pré-requisito de model+reader+propagação aos consumidores, faixa realista é 400-600 linhas. Vale split em 2 PRs (1: model/reader, 2: flow_load + chain).

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: metricNova métrica ou alteração de métrica existente

    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