Pular para conteúdo

Sprint Review 001 — Fundação e coleta EO

Encerrado em: 2026-08-09 Backlog: sprint-backlog.md

Separa o que foi entregue do que não foi. Nada aqui é marcado como pronto sem evidência — saída de comando, número conferido contra a origem, ou tela renderizada.

Resultado por user story

A coluna Aceito é derivada do registro de aceitação, nunca preenchida direto. Review sem registro de aceitação é afirmação sem prova.

# User story Entregável Aceito Onde
US1 Conectar ferramenta com credencial protegida D01 sim, na reavaliação aceitacao.md — não aceito na primeira avaliação por falha em AC4; corrigido por #88
US2 Conhecer pessoas e equipes D02 sim aceitacao.md — com duas ressalvas registradas
US3 Rastrear de onde veio cada informação D03 sim aceitacao.md

Entregável do sprint: composto de D01, D02 e D03 — depois da correção. Na primeira avaliação era composto só de D02 e D03, e o registro guarda os dois momentos: um sprint que precisou de correção para ficar completo é diferente de um que nasceu completo.

Tarefas executadas sem sucesso: T033 e T038. Permanecem assim — foram executadas e não produziram entregável aceito, e é isso que a medida rework.not_accepted_deliverable_ratio calcula. #88 é tarefa nova, não reabertura.

Evidência da coleta real

Executada contra a organização The-Band-Solution pelo mesmo caminho que a tela dispara — Ingestion.start_sync/2 enfileira, o Oban executa.

--- relatório da sincronização (FR-028) ---
  estado          completed
  coletados       16
  criados         9          (1 organização + 6 pessoas + 2 equipes)
  atualizados     0
  ignorados       0
  pendentes papel 7

--- checkpoints (FR-015, R5) ---
  github.organization           páginas=1 registros=1 cursor=nil
  github.team                   páginas=1 registros=2 cursor=nil
  github.team_member:the-band   páginas=1 registros=3 cursor=nil
  github.team_member:zeppelin   páginas=1 registros=4 cursor=nil
  github.user                   páginas=1 registros=6 cursor=nil

--- equipes e integrantes ---
  The Band (organizational_team) — 3 integrantes
      Adylla027       acesso=MEMBER      papel=pendente
      EduardoNFraiz   acesso=MEMBER      papel=pendente
      Paulo           acesso=MAINTAINER  papel=pendente
  Zeppelin (organizational_team) — 4 integrantes
      Felipe Becalli T.  acesso=MEMBER      papel=pendente
      Luma               acesso=MEMBER      papel=pendente
      Paulo              acesso=MAINTAINER  papel=pendente
      Sofia              acesso=MEMBER      papel=pendente

Critérios de sucesso, um a um

# Critério Situação Evidência
SC-001 Conectar e validar em menos de 2 minutos, sem documentação atendido formulário de uma tela, com validação imediata e mensagem do que faltou
SC-002 100% das pessoas e equipes da origem registradas atendido 6 pessoas e 2 equipes, conferidos contra a organização real
SC-003 Segunda sincronização cria 0 e altera 0 atendido segunda execução: criados 0, atualizados 0, contagens inalteradas
SC-004 100% dos registros exibem origem, identificador e data atendido colunas presentes em /pessoas e /equipes para todas as linhas
SC-005 Credencial não recuperável em forma utilizável atendido token ausente do HTML das 4 telas; banco devolve AES.GCM.V1$…; inspect/1 redigido
SC-006 Retomada consulta no máximo uma página a mais atendido teste de retomada: com checkpoint gravado, a execução seguinte pede a página seguinte (after: cursor-1), não a primeira
SC-007 Correção de mapeamento aplicada sem consultar a origem atendido SemanticIntegration.reprocess_mappings/2 sobre 32 payloads preservados: 0 criados, 0 atualizados, 32 sem mudança. O teste roda sem expectativa no Mox da borda HTTP, então qualquer chamada à origem o derruba
SC-008 Usuário de uma organização não vê dado de outra atendido dois tenants povoados; sessão da outra-org mostra 0 pessoas e 0 equipes
SC-009 Organização com 100 pessoas e 20 equipes conclui sem intervenção parcial o comportamento sob rate limit é testado com janela simulada: a coleta devolve {:snooze, n}, preserva o cursor e não falha. O volume de 100 pessoas não foi exercitado — a organização disponível tem 6
SC-010 Vínculos pendentes de papel apresentados explicitamente atendido 7 no relatório da sincronização e no cabeçalho de /equipes

Quality gates

Gate Resultado
mix format --check-formatted passou
mix compile --warnings-as-errors passou
mix credo --strict passou — found no issues
mix dialyzer passou — Total errors: 0
mix test passou — 81 testes
mix knowledge.validate passou — 84 artefatos
mix knowledge.graph passou — 24 módulos, dependências íntegras
scripts/validate_knowledge_base.py passou — base válida

O que não foi entregue

Declarado explicitamente. Nenhum destes está marcado como pronto em lugar nenhum.

Item Tarefas Por quê
Autenticação com senha — A sessão é aberta por escolha de usuário, sem senha. O que está implementado é o escopo por tenant, que atravessa toda consulta e é testado com dois tenants percorrendo a interface. Autenticação é feature própria, e não foi silenciosamente incorporada a esta
Volume de SC-009 — O comportamento sob rate limit é testado; o volume de 100 pessoas e 20 equipes exigiria uma organização que não temos
mix knowledge.test, knowledge.docs, knowledge.information_model — Continuam como scripts Python, chamados pelo CI. Dívida declarada no plan.md
Estimate das issues — Nenhuma estimativa foi feita com o time. Preencher com número inventado produziria métrica de fluxo apoiada em ficção
Revisão independente do PR T073 A constituição exige revisor diferente de quem implementou. Esta condição não foi satisfeita e não pode ser marcada como cumprida por quem escreveu o código. O PR foi aberto no sprint 002, o que torna a revisão possível — não a substitui
Ocorrência real de três verificações — Automação classificada, pausa por limite de uso e ausência-não-é-remoção estão provadas por teste, não por ocorrência. A última exigiria remover alguém de uma equipe real na organização da pessoa mantenedora, e isso não deve ser feito para validar software

Correção após o /speckit-analyze

O /speckit-analyze rodado ao fim do sprint encontrou dois CRITICAL e dois HIGH. Três foram corrigidos ainda neste sprint; o quarto é procedimento e permanece aberto.

Achado O que era Resolução
G1 — FR-017 sem tarefa de implementação só existia o teste (T060); RawData.list_for_reprocessing/2 não tinha chamador contrato reprocessing.md escrito antes do código, T060a–T060c acrescentadas, TheBand.SemanticIntegration + worker Oban + botão em /sincronizacoes implementados, 8 testes
C1 — assinatura divergente o contrato pedia lista de ids; o código recebe DateTime contrato corrigido: a plataforma não recebe evento de remoção, ela percebe a ausência por comparação entre coletas — quem chama não teria como saber quais vínculos sumiram
C2 — opts divergentes contrato prometia :order_by, ausente no código; :only_observed existia sem estar no contrato contrato corrigido com tabela por opção, e :order_by removido: ordenação parametrizável reintroduziria a divergência entre list_* e count_* que a regra existe para impedir
G2 — revisão independente não satisfeita continua aberta; nenhum entregável pode ser aceito sem ela

Uma terceira correção de contrato apareceu durante a implementação: o contrato de reprocessamento prometia {:error, {:unknown_mapping, id}} e dizia que um mapeamento quebrado não derruba o lote. Contradizia a si mesmo. Prevaleceu a segunda regra — derrubar o lote por um registro tornaria a correção refém do pior dado da base, o oposto do que FR-017 existe para permitir.

Prática que passa a valer: o contrato da API é escrito antes da primeira função pública, e corrigido no mesmo commit quando a implementação mostra que ele errou. Registrado em AGENTS.md §12 e na constituição, princípio VI, por emenda 1.1.0.

Segunda rodada de correções

Depois do /speckit-analyze, os pendentes que sobraram foram fechados.

Item Resolução
Rotação da chave mestra (FR-005b) contrato credential-rotation.md escrito antes, e mix the_band.rotate_key implementada. Verificada de ponta a ponta: rótulo do valor cifrado mudou de 1ff8e241 para 1ddcd36a, segredo intacto com a chave nova
Teste de retomada (SC-006) com checkpoint gravado, a execução pede after: cursor-1 — a página seguinte, não a primeira
Teste de rate limit (SC-009) janela simulada apertada devolve {:snooze, n}, preserva cursor, não falha
Testes de interface 9 testes de LiveView, incluindo os três que não são fazíveis por teste unitário: segredo ausente do HTML, isolamento percorrendo a interface, e cabeçalho concordando com a listagem
Base de conhecimento e o campo email o mapeamento declarava um atributo que a consulta deixou de pedir. Agora está registrado como limitação, com a razão — o campo exigiria escopo read:user, mais amplo do que a coleta precisa
Redação de T005 e T019 as tarefas prometiam mais do que foi entregue; corrigidas para descrever o que de fato cobrem

Um defeito sério encontrado ao testar a rotação

A rotação não funcionava, e teria falhado em silêncio. Os dois ciphers — o da chave nova e o da antiga — usavam rótulos fixos, e o Cloak escolhe qual chave usar pelo rótulo gravado no início do valor cifrado. Com rótulos que não identificavam a chave, ele escolhia pela ordem da configuração e usava a errada.

O sintoma seria "não consigo decifrar esta credencial", sem dizer por quê, e só no momento de usá-la — no meio de uma coleta.

A correção deriva o rótulo da própria chave, por oito caracteres do SHA-256: cada valor cifrado passa a carregar qual chave o cifrou, as duas convivem sem ambiguidade durante a rotação, e depois dela os registros novos já apontam para a nova. Coberto por test/the_band/vault_test.exs.

Isso só apareceu porque a rotação foi executada, não apenas implementada.

Defeitos encontrados durante o sprint

Todos corrigidos, e cada um virou lição.

Defeito Onde apareceu Correção
Gerador sobrescreveu AGENTS.md mix phx.new em diretório povoado restaurado do git; virou L01
Coleta executada em dobro script chamando perform/1 com o servidor no ar script passou a usar o caminho real; L02
Proveniência ausente derrubava a query find_by_application_reference/3 comparando com nil validação antes da consulta; L03
INSUFFICIENT_SCOPES por campo opcional email nas queries GraphQL exige read:user campo removido; L04
Erro real trocado por erro de banco syncs.error_reason em varchar(255) coluna virou text; L05
Arquivos escritos no diretório errado cd persistindo entre comandos caminhos absolutos; L06
Struct devolvido sem id autogenerate: false em chave binary_id autogenerate: true; L07
Validador rejeitava todos os mapeamentos proveniência tem duas formas na base, e o código só conhecia uma provenance_problems/1 por tipo de artefato
Bug de YAML preexistente flow_wip_count.yaml com : sem aspas virava mapa item entre aspas

Divergências entre artefatos, resolvidas

# Divergência Resolução
D-1 research.md R7 chamava a tabela de eo_observed_team_links; a regra da base declara team_membership_evidence prevaleceu a base de conhecimento: eo_team_membership_evidence
D-2 R7 acrescenta colunas que a regra não nomeia as duas se somam; a evidência guarda chaves internas e identificadores externos
— research.md R1 fixou PostgreSQL 16; o ambiente roda 17 compose.yaml alinhado ao 17, com a razão escrita no próprio arquivo
— spec usa P1/P2/P3; o projeto oferece P0/P1/P2 ordem preservada, rótulo remapeado, registrado no backlog

Estado das issues

Atualizado em 2026-08-10, depois do registro de aceitação.

Situação Issues
encerradas, com entregável aceito #1 a #76 e #88 — 75 no total
fechada como not planned #2 — duplicata órfã da US1, criada por uma execução do script de materialização que falhou depois de a issue já existir
encerrada com limitação declarada #77 — evidência do quickstart; V3, V4 e V8 provados por teste e não por ocorrência real
concluída no sprint 002 #78 — abertura do pull request, T073. PR #89. Ver a herança

O fechamento das issues não substitui a revisão independente. São perguntas diferentes: a issue fecha quando a tarefa foi executada e o entregável aceito; a revisão pergunta se o código está correto, seguro e conforme, e o princípio VII exige que quem responda não seja quem implementou. O pull request existe e a revisão continua pendente — nada da 001 entra na main antes dela.