Sprint 002 — Escopo por organização¶
Período: 2026-08-10 a 2026-08-16 (7 dias — cadência semanal) Feature: 002-escopo-por-organizacao Plano: plan.md Análise ontológica: ontology-analysis.md
Objetivo do sprint¶
Cada pessoa e cada equipe passam a dizer de qual organização vieram, e o esquema volta a corresponder ao modelo derivado da ontologia.
Herança do sprint 001¶
Nenhuma tarefa deste sprint começa antes de o que sobrou do anterior ter
destino. É a regra que a skill product-owner passou a exigir no planejamento,
e ela existe porque escopo aberto sem destino não é trabalho, não é decisão e não
é descarte — é pendência que aparece para sempre.
Estado do sprint 001, avaliado em 2026-08-10 no registro de aceitação: os três entregáveis foram aceitos, D01 depois da correção de #88. Aceitação não é merge, e não é revisão de código — o que sobrou está abaixo, item por item.
| O que sobrou | Tipo | Destino |
|---|---|---|
| T073 — abrir o pull request · #78 | não executada | concluída na Fase 0: PR #89, com a tabela de mapeamentos semânticos. Mergeado em 45d21a0 |
| Revisão independente do código — princípio VII | era bloqueio estrutural; destravado em 2026-08-10 | A causa era permissão: o repositório tinha um colaborador só, o autor. Concedido pull à equipe the-band, o pedido de revisão passou a funcionar — feito no PR #91, e quem revisa é Adylla027 ou EduardoNFraiz. Resíduo irrecuperável: o #89 foi mergeado sem revisão e não há como pedir revisão de PR mergeado. Lição L15 |
| T072 — evidência do quickstart · #77 | executada em parte | encerrada com a limitação declarada: V3, V4 e V8 estão provados por teste e não por ocorrência real. Já aceito assim no aceitacao.md, com a ressalva escrita |
| Volume de SC-009 — 100 pessoas e 20 equipes | não executável | descartada, com motivo: exigiria uma organização de origem que não existe. O comportamento sob limite de uso está coberto por teste |
Estimate das issues |
não executada | devolvida: depende de estimativa feita com o time. Número inventado produziria métrica de fluxo apoiada em ficção |
mix knowledge.test, knowledge.docs, knowledge.information_model |
diferida por decisão registrada | não entra aqui. O plan.md da 001 declara: portar as três é trabalho comparável ao da feature inteira, e elas viram feature própria ligada à extração da biblioteca. O CI segue rodando os scripts Python, então o gate existe — muda o executor, não a exigência |
A exceção, assumida — e o que o merge mudou nela¶
Este sprint parte do código da 001 sem a revisão independente, e a regra que o parágrafo acima instituiu admite isso num caso só: quando o trabalho novo corrige um defeito do antigo. É exatamente este caso — F3 conserta colunas escritas à mão na 001.
2026-08-10: o PR #89
foi mergeado na main em 45d21a0, por decisão da pessoa mantenedora, com o CI
verde e sem nenhuma aprovação registrada — pulls/89/reviews devolve lista
vazia.
Isso não reduziu o risco; mudou o lugar dele. Antes era código não revisado fora da linha principal, visível como branch pendente. Agora é código não revisado dentro da linha principal, indistinguível do resto. É a forma mais difícil de lembrar que a dívida existe, e é a razão de este parágrafo existir.
A causa da revisão nunca ter acontecido foi encontrada, e era outra. Não era
agenda: o repositório tinha um colaborador só, paulossjunior, e nenhuma equipe
com acesso. Revisão só pode ser pedida a colaborador, e o autor não pode ser revisor —
então havia zero revisores possíveis. A exigência atravessou o sprint 001 inteiro
como "revisão pendente", indistinguível de item que só precisava de tempo. Registrado
em L14 e L15.
Destravado em 2026-08-10, com duas chamadas de API: pull concedido à equipe
the-band — o mínimo que revisão exige — e o pedido de revisão feito à equipe em vez
de a uma pessoa. Pedir à equipe é o que produz a independência: o pedido fica
aberto a qualquer membro, e o autor, sendo membro, não pode atendê-lo. Quem revisa é
Adylla027 ou EduardoNFraiz.
Correção do próprio registro. Este documento afirmava que a revisão da 001 não havia acontecido. A pessoa mantenedora corrigiu: "eu olhei e concordei, por isso não coloquei comentário." A leitura ocorreu; falta a prova, não a revisão.
A conclusão errada vinha de ler o campo author do GitHub como se nomeasse quem
implementou. Não nomeia: quem implementou é o agente, cujos commits trazem
Co-Authored-By: Claude Opus 5 e que não tem conta. O 422 é artefato de ferramenta,
não conflito de interesse. Registrado como L16.
O que fecha a lacuna de vez é abrir os PRs com identidade de agente — bot ou GitHub
App. Aí o implementador é o autor de fato, e paulossjunior pode aprovar formalmente o
que não escreveu. Enquanto isso, #89, #90 e #91 ficam com o atestado datado no
aceitacao.md, porque PR mergeado não recebe review.
Lições aplicadas¶
Do registro acumulado — dezoito lições, L01 a L18. Doze se aplicam diretamente:
| Lição | O que muda neste sprint |
|---|---|
| L03 — teste com dado inválido acha o que o caminho feliz esconde | Três tarefas têm o teste escrito como violação: T016 (um tenant pede a organização do outro), T007 (equipe organizacional sem organização) e T022 (derivada gravada como observada). É o que a L03 mandou fazer |
| L08 — contrato escrito junto com o código descreve, não decide | Os quatro contratos foram escritos antes de qualquer código, e cada tarefa que cria API pública tem "o contrato existe" no Pronta quando |
| L09 — um contrato pode contradizer a si mesmo | O contrato de reprocessamento da 001 se contradizia e só a implementação revelou. Aqui, cláusula inalcançável durante a implementação será tratada como sintoma de contrato errado, não como código a apagar |
| L02 — servidor no ar duplica o efeito de job disparado por script | O retrofito (T011) roda por Oban. Nenhuma verificação vai chamar perform/1 à mão com o servidor no ar |
| L11 — configurar iterations do ProjectV2 recria as existentes | Aplicada na prática, ao mudar a cadência para 7 dias: snapshot de todos os 97 itens antes, reatribuição por item id e não por número de issue, e conferência contra o snapshot depois. Os 97 ficaram órfãos, como a lição previu, e os 87 voltaram ao lugar |
| L12 — PR não aberto na hora passa a carregar outra feature | Foi por isso que a Fase 0 existe, e é a lição que criou a regra de não puxar trabalho novo. O PR da 002 é aberto quando a tarefa pedir, não no fim |
| L13 — secret referenciado e não cadastrado chega como string vazia | Onde a ausência tem tratamento, vazio recebe o mesmo. Vale para toda leitura de ambiente que esta feature acrescentar |
L14 — gh engole o pedido de revisão recusado |
Ao abrir o PR desta feature, conferir gh pr view <n> --json reviewRequests. Lista vazia significa que ninguém foi pedido, não importa o que o comando disse |
| L16 — o autor do PR não é quem implementou | Ao registrar a revisão, distinguir "não ocorreu" de "sem prova". Aplicada no aceitacao.md deste sprint |
| L17 — a derivação do esquema não era função da ontologia | Descoberta neste sprint, ao executar a regressão de T004. Consertada, com gate de reprodutibilidade no CI |
| L18 — um critério atendido não é um critério suficiente | Descoberta neste sprint: V9 passou com a equipe derivada acolhendo o tenant inteiro. A aceitação percorre todos os critérios, e foi SC-009 que expôs |
| L15 — não há revisor possível num repositório de um colaborador só | A revisão independente era pendência de permissão, não de agenda. Destravada neste sprint: pull à equipe the-band, e pedido de revisão à equipe. Todo PR desta feature nasce com team_reviewers[]=the-band |
As demais foram consideradas e não se aplicam: L01 (não há gerador nesta feature), L04 (nenhuma consulta nova ao GitHub), L05 e L07 (correções já incorporadas), L06 (disciplina de caminho absoluto, já em uso), L10 (não há rotação de chave aqui).
Sprint no GitHub¶
Iteration: Sprint 002 — Escopo por organização · 2026-08-10 a 2026-08-16 · 7 dias Projeto: The Band
Primeira ocorrência. Ao criar a iteration do sprint 002, a API do
ProjectV2 recriou a do sprint 001 com identificador novo, e os 77 itens dele
ficaram órfãos — updateProjectV2Field substitui o conjunto de iterations e não
aceita id nas existentes. Os itens foram reatribuídos, e no caminho 10 itens de
outros repositórios (eo_lib, theband-frontend, theband-backend e um
pull request) foram atribuídos por engano ao sprint 001 e depois limpos. Virou a
L11.
Segunda ocorrência, esta deliberada. Mudar a cadência para 7 dias exige mexer na mesma configuração, então a L11 foi aplicada como procedimento:
| Passo | Resultado |
|---|---|
| snapshot antes — item, repositório, número e iteration de cada um | 97 itens: 76 no sprint 001, 11 no sprint 002, 10 sem iteration |
updateProjectV2Field com duration: 7 |
as duas iterations recriadas, 97 itens órfãos |
reatribuição pelo item id do snapshot |
87 reatribuídos, 0 falhas |
| conferência contra o snapshot | 76 · 11 · 10 sem iteration, e os 10 sem são de outros repositórios |
Duas coisas fizeram diferença. Reatribuir pelo item id, que não muda quando a
iteration é recriada, em vez de casar por número de issue — número não é único num
projeto que agrega vários repositórios, e foi o segundo erro da primeira vez. E ter
o snapshot antes: sem ele a informação de qual item pertencia a qual sprint
simplesmente não existiria em lugar nenhum.
Descoberta nova. A iteration do sprint 001, com data no passado, saiu de
iterations e apareceu em completedIterations — com identificador próprio,
2849580c. Um script que leia só iterations não a encontra e conclui que ela
deixou de existir. Está em L11.
Duração — como foi dimensionada¶
Escopo: 27 tarefas em 8 fases · 5 níveis de dependência Caminho crítico:
nível 1 Ontologia (T001–T003)
nível 2 Transformação (T004) ── só depois de a relação existir
nível 3 Esquema (T005–T008) ── só depois de a derivação produzir a coluna
nível 4 US1 (T009–T012) ‖ Equipe derivada (T020–T024)
nível 5 US2 (T013–T017) ‖ US3 (T018–T019) ‖ Polish (T025–T027)
Cinco níveis, não oito fases: US1 e a equipe derivada dependem ambas do esquema e não uma da outra, então ocupam um nível. O mesmo vale para US2, US3 e Polish.
Vazão usada: nenhuma. Não é premissa declarada nem dado — é ausência, e a razão está abaixo.
Piso de fatia vertical: nível 4. Os três primeiros níveis são ontologia,
transformação e esquema — infraestrutura sem consumidor visível. O primeiro
entregável que materializa user story é US1, no nível 4. Um sprint de três níveis
fecha na aritmética e não produz sro.sprint_deliverable.
Duração proposta: 4 dias para o MVP (níveis 1 a 4), 5 dias para a feature inteira.
Confiança: baixa. Um dia por nível é premissa, não observação.
Duração decidida: 7 dias — uma semana, por decisão da pessoa mantenedora em 2026-08-10, como cadência padrão do projeto.
A decisão é de cadência, não deste sprint: sprint de duração fixa é o que torna a
vazão comparável entre sprints, e comparabilidade é condição declarada da
flow.throughput.rate. Cadência variável por sprint tornaria a série ilegível — foi
por isso que a proposta de 2 a 3 dias sob demanda foi descartada em favor de uma
semana fixa.
Sete dias acomodam a feature inteira com folga sobre os 5 dias do caminho crítico. A folga não é escopo disponível: é onde caberá o nível 3, que remove colunas com migração e reconferência e é o mais provável de estourar.
Por que 2 ou 3 dias não cabem nesta feature¶
Não é conservadorismo: é a cadeia. Os três primeiros níveis são rígidos — coluna antes de relação foi exatamente o erro que criou este trabalho —, e o primeiro consumidor visível está no quarto. Três dias comprariam os três níveis de infraestrutura e nenhuma tela.
Encurtar teria de vir de cortar escopo, e o escopo que sobraria não é entregável. Duração é a maior entre volume, caminho crítico e piso vertical — aqui o piso vertical é que manda.
A partir da 003, sprints de 2 a 3 dias são viáveis. O que os impede aqui é esta feature começar por três níveis de correção estrutural. Uma feature cujo primeiro nível já toca tela cabe em dois dias.
Por que a vazão não entrou na conta¶
Três razões, e as três estão declaradas na própria flow.throughput.rate:
| Razão | O que a medida diz |
|---|---|
| histórico de um sprint | "um sprint isolado não descreve o fluxo" — há uma observação, não uma vazão |
| a janela do sprint 001 não continha as tarefas dele | corrigido neste planejamento: a iteration passou a 2026-08-03 → 08-09, que contém 09/08. Antes a vazão dele era zero; agora é 76 tarefas em 7 dias. Um valor, não uma série |
| a duração era desigual | "comparar sprints exige duração constante". Com 14 dias no 001 e 7 no 002 a comparação não existiria. A cadência semanal resolve isso a partir daqui — e o 001 só é comparável porque sua janela foi reescrita para 7 dias, o que é ajuste de registro, não de trabalho realizado |
Há ainda a armadilha que a medida nomeia: "usar a vazão como meta a bater a torna alvo, e alvo deixa de ser medida". Dimensionar duração pela vazão é legítimo; escolher a duração para atingir uma vazão produz tarefa fechada no board antes de o trabalho terminar.
Consequência prática: corrigir as datas da iteration deixou de ser cosmético. Enquanto o sprint 001 tiver janela que não contém as próprias tarefas, a vazão dele é zero, e nenhum sprint seguinte pode ser dimensionado por série. A decisão 1 do planejamento virou pré-requisito de todo dimensionamento futuro.
O que invalida esta conta¶
- granularidade mudar: 27 tarefas aqui e 76 no sprint 001 não são a mesma unidade. Decompor mais fino eleva a vazão sem mais trabalho feito;
- um nível levar mais de um dia: o nível 3 remove colunas com migração e reconferência, e é o mais provável de estourar;
- as três primeiras fases não serem rígidas de fato: se a derivação já emitisse a chave, o nível 2 sairia e a cadeia encurtaria um dia;
- trabalho que não virou tarefa: revisão, apoio, espera por terceiro. A medida declara que isso consome capacidade e não aparece na contagem.
Planejamento — sro.planning_meeting¶
Realizado em 2026-08-10. A ordem seguida é a que a skill product-owner passou
a exigir: herança antes de escopo novo, e importância só depois.
| Passo | Resultado |
|---|---|
| 1. listar o que está aberto do sprint anterior | 6 itens, na tabela de herança acima |
| 2. dar destino a cada um | 6 destinos: 2 concluídos, 1 encerrado com limitação, 1 descartado com motivo, 1 devolvido, 1 bloqueado com bloqueador nomeado |
| 3. herança em primeiro lugar | Fase 0, antes de F1 |
| 4. selecionar escopo novo por importância | as 9 issues abaixo, com o MVP declarado |
Conclusão: F1 está liberada. Nenhum item do sprint 001 permanece sem destino, o que é a condição da regra — e não é o mesmo que dizer que tudo do 001 ficou pronto. A revisão independente segue pendente, com bloqueador nomeado.
Duas decisões que o planejamento levou ao papel, e que foram tomadas¶
1. Cadência semanal, e as datas corrigidas. As datas da iteration contradiziam o que aconteceu, e a contradição zerava as medidas de fluxo:
| Antes | Agora | |
|---|---|---|
| Sprint 001 | início 2026-08-10, 14 dias → terminaria 2026-08-23 | 2026-08-03 a 2026-08-09, 7 dias |
| Sprint 002 | início 2026-08-24, 14 dias | 2026-08-10 a 2026-08-16, 7 dias |
O defeito era que as tarefas do sprint 001 foram executadas antes da data em que a
iteration dizia que ele começou — 2026-08-09, fora da janela. flow.throughput.rate
e flow.wip.count atribuem tarefa a sprint por janela de datas, então os dois
devolviam zero para o sprint 001: um sprint que produziu 76 tarefas aparecia sem
trabalho algum. Resíduo da L11, onde os itens foram
consertados e a data não.
Agora a janela 03→09/08 contém 09/08, e o sprint 002 começa hoje, sem as duas semanas vazias que a configuração anterior deixava.
A correção custou o que a L11 previu, e a mitigação funcionou. Mudar duration
de 14 para 7 recriou as duas iterations e deixou todos os 97 itens órfãos. O
snapshot tirado antes — item, repositório, número e iteration de cada um — permitiu
reatribuir os 87 que tinham iteration: 76 no sprint 001, 11 no sprint 002, e os 10
sem iteration ficaram sem, porque são de outros repositórios. Reatribuir pelo
item id do snapshot, e não pelo número da issue, é o que evitou repetir o segundo
erro da L11.
2. Épico #79 recebeu importância P0 — a da parte mais importante, entre US1 (P0),
US2 (P1) e US3 (P2). É decisão do papel, não derivação, e por isso foi tomada por
quem desempenha o papel em vez de gravada por conveniência. As tarefas #83 a #87
seguem sem Priority, o que é o correto: tarefa herda a da user story que
atende.
Escopo — 9 issues em vez de 27¶
Decisão da pessoa mantenedora: ser mais econômico que na feature 001, onde foram
77 issues. As 27 tarefas do tasks.md vivem como checklist no corpo de cada
issue, então a granularidade não se perde e o progresso continua visível.
Épico¶
| Issue | Título |
|---|---|
| #79 | Pessoas e equipes separadas por organização observada |
User stories¶
| # | User story | Tipo | Issue | Priority | Estimate | Critérios |
|---|---|---|---|---|---|---|
| US1 | Saber de qual organização veio cada registro | Feature | #80 | P0 | — | 5 cenários |
| US2 | Consultar uma organização de cada vez | Feature | #81 | P1 | — | 5 cenários |
| US3 | Enxergar quem atravessa organizações | Feature | #82 | P2 | — | 3 cenários |
Priority é a importance da SRO — valor para a organização. Estimate é a
complexity, e está em branco de propósito: nenhuma estimativa foi feita com
o time, e preencher com número inventado produziria métrica de fluxo apoiada em
ficção. Campo em branco significa desconhecido, não zero.
A escala do projeto é P0/P1/P2 e a da spec é P1/P2/P3 — o mapeamento preserva a ordem, não o rótulo. Ler "P0" como "a mais importante das três".
Tarefas¶
| # | Tarefa | Atende | Tipo | Issue | Tarefas do tasks.md |
Estado |
|---|---|---|---|---|---|---|
| F0 | Abrir o pull request da 001 | herança | Task | #78 | T073 da 001 | feito |
| F0 | Encerrar a evidência do quickstart | herança | Task | #77 | T072 da 001 | feito, com limitação declarada |
| F1 | Declarar o vínculo na ontologia | épico | Task | #83 | T001–T003 | feito |
| F2 | Gerar chave estrangeira a partir de associação | épico | Task | #84 | T004 | feito |
| F3 | Corrigir o esquema escrito à mão | épico | Task | #85 | T005–T008 | feito |
| — | Tarefas da US1 | US1 | checklist em #80 | — | T009–T012 | feito |
| — | Tarefas da US2 | US2 | checklist em #81 | — | T013–T017 | não feito — volta ao backlog |
| — | Tarefas da US3 | US3 | checklist em #82 | — | T018–T019 | não feito — volta ao backlog |
| F7 | Criar a equipe derivada | épico | Task | #86 | T020–T024 | feito |
| F8 | Fechar a feature | épico | Task | #87 | T025–T027 | feito |
Tarefa não recebe Priority: herda a da user story que atende.
Estados: a fazer · em andamento · feito · bloqueado · não iniciado
A ordem não é negociável¶
F0 Herança → F1 Ontologia → F2 Transformação → F3 Esquema → US1 → US2 → US3
└────→ F7 Equipe derivada → F8
F0 vem antes por regra, não por conveniência. Herança colocada no fim da lista é herança que não entra: quando o sprint aperta, o que fica para depois é o que está no fim. Por isso o que sobrou do sprint anterior é a primeira coisa a receber destino, e só depois o escopo novo é selecionado por importância.
A cadeia das três seguintes é rígida, e é a lição do achado F1 da análise:
coluna escrita antes de a relação existir foi exatamente o erro que criou
este trabalho. Nenhuma tarefa que dependa de eo_teams.organization_id começa
antes de a derivação produzi-la.
MVP¶
F1, F2, F3, US1 e F7. A equipe derivada não é opcional no MVP, e a primeira
versão do tasks.md errava ao dizer que podia ficar para depois.
A razão é o critério SC-003a: nenhuma pessoa conhecida pode ficar sem
organização. Sem a equipe derivada, as 18 pessoas que não estão em equipe alguma
continuam sem — inclusive as 5 de ifesserra-lab, que não tem nenhum time.
Entregar sem ela corrigiria o defeito para 54 das 72 pessoas e o manteria para as
outras 18, sem a tela dizer por quê.
Fora do escopo deste sprint¶
| O quê | Por quê |
|---|---|
| Papéis organizacionais | o vínculo segue sendo evidência; promovê-lo a alocação é feature própria |
| Reconciliação de identidade | duas contas da mesma pessoa continuam dois registros |
| Medidas por organização | o vínculo passa a existir; as medidas vêm depois |
| Hierarquia entre organizações observadas | parent_organization_id existe e nada a preenche |
Vínculo de eo.project_team com projeto |
achado F8 da análise; o destino é SPO e a direção de dependência precisa ser conferida antes |
| Autenticação com senha | continua sendo feature própria, como no sprint 001 |
Riscos e dependências¶
| Risco | Mitigação |
|---|---|
| A revisão independente da 001 nunca acontecer | deixou de ser risco de atraso e passou a ser impedimento estrutural: uma conta só não pode revisar o próprio PR. Fechar exige duas identidades — decisão de infraestrutura, fora deste sprint. Até então, todo entregável carrega a lacuna declarada |
O código não revisado estar na main |
mergeado em 45d21a0 sem aprovação registrada. O risco não diminuiu com o merge: ficou indistinguível do resto do código, e é por isso que está escrito na herança e aqui |
| As medidas de fluxo devolverem zero para o sprint 001 | as datas da iteration não correspondem ao que ocorreu, e a correção não foi feita porque mexer em iterations causou a L11. Decisão pendente, registrada no planejamento |
O mix knowledge.validate passar onde o validador Python reprova |
ocorreu no sprint 001: depois do rename de eo.sector, o validador Elixir passou e o Python reprovou por proveniência de conceito sem source_type. O Elixir tem 4 verificações, o Python tem 11 — os dois gates não são equivalentes. Neste sprint a T003 fecha uma delas (mapeamento declarando relação inexistente). Enquanto as outras não forem portadas, o gate Python é o que decide, e ele roda no CI |
| A regra nova do derivador alterar a derivação de outra ontologia | T004 exige que a saída de todas as demais saia idêntica; é regressão obrigatória, não verificação opcional |
| Remover coluna com dado dentro | T005 reconfere antes de T006 migrar; se a contagem não der zero, a tarefa para e vira decisão |
| A equipe derivada ser lida como observada | três tarefas a protegem — T022 é o teste da violação |
updateProjectV2Field recriar iterations de novo |
não mexer na configuração de iterations enquanto houver sprint aberto; a correção deste sprint já custou uma reatribuição de 96 itens |
Definition of Done do sprint¶
- [x] cada item aberto do sprint 001 tem destino registrado — concluído, devolvido, descartado com motivo, ou bloqueado com bloqueador nomeado
- [ ] quality gates verdes:
mix format --check-formatted,compile --warnings-as-errors,credo --strict,dialyzer,test - [ ]
mix knowledge.validateemix knowledge.graphverdes, mais o validador Python - [ ] a derivação das demais ontologias sai idêntica à de antes
- [ ] V1 a V10 do quickstart executados, com evidência de cada um
- [ ] V9 devolve zero pessoas sem equipe
- [ ] issues encerradas ou repriorizadas com justificativa
- [ ]
sprint-review.mdescrito, separando feito de não feito - [ ]
licoes-aprendidas.mdatualizado - [ ] revisão independente — a mesma lacuna do sprint 001; declarada, nunca marcada como cumprida por quem implementa