Passo 4 · O Loop · O Loop · Loop Engineering ENPT
Módulo 2 · O Loop · Passo 2 do ciclo

ANALYZE: classifique o gap, avalie, escolha UMA unidade

LEARN te entregou um retrato fundamentado da realidade. ANALYZE transforma essa pilha de fatos em uma única decisão: classifique cada gap no balde certo, avalie o punhado que de fato é seu para fazer agora, e escolha a única unidade delimitada mais valiosa para executar em seguida. Não três. Uma.

Leia a versão simples, ou abra a camada técnica em qualquer seção.
1

A grande ideia: uma jogada ranqueada, não uma lista de tarefas


Cada volta do loop tem cinco passos — LEARN → ANALYZE → EXECUTE uma unidade delimitada → VERIFY no boundary real → DECIDE. Esta lição é o segundo passo. ANALYZE é o momento entre enxergar a realidade e mudá-la: você pega os gaps que o LEARN trouxe à tona e decide, de propósito, a única próxima coisa a fazer.

São três pequenas jogadas, em ordem. Primeiro você classifica cada gap em um de quatro baldes — é trabalho on-scope, um bloqueio do-now, algo que precisa do usuário (needs-user), ou simplesmente fora de escopo (out-of-scope)? Segundo, para os gaps que sobrevivem (os on-scope e do-now), você avalia cada unidade candidata em cinco eixos rápidos: Encaixe, Risco, Prova, Bloqueio, Próximo. Terceiro, você escolhe exatamente uma — a unidade delimitada mais valiosa — e a entrega ao EXECUTE.

A disciplina que torna isso difícil é a palavra uma. Quando você consegue ver dez coisas erradas, todo instinto diz “vou consertar tudo de uma vez já que estou aqui”. O loop proíbe isso. Uma passada executa uma única unidade delimitada para que o VERIFY possa provar aquela única mudança no boundary real, e para que o humano que observa consiga dizer exatamente o que mudou. Junte cinco correções em lote e um teste vermelho não te diz nada sobre qual delas quebrou.

Continuando o exemplo corrente da última lição: no serviço RHG, o LEARN já confirmou o gap — /search devolve todas as linhas numa query vazia, o handler está em api.py:42, e há um teste pulado test_empty_query_returns_400 esperando. O trabalho do ANALYZE agora não é achar mais gaps. É decidir qual única unidade entregar primeiro.

Pense nisso como… uma enfermeira de triagem num pronto-socorro lotado. Dez pessoas esperam e todas querem ajuda. A enfermeira ainda não trata ninguém — ela classifica. Quem é crítico e precisa ser visto agora, quem pode esperar, quem está no departamento completamente errado, quem precisa de uma decisão médica que ela mesma não pode tomar. Só depois da classificação é que um paciente atravessa a porta. Onde a analogia se rompe: a enfermeira toca várias salas ao mesmo tempo; uma passada de ANALYZE se compromete com um único paciente, porque o loop quer uma mudança provável por volta.

Por que “uma unidade delimitada” é estrutural, não estilístico

Uma unidade delimitada é a menor mudança que é independentemente verificável no boundary real. O limite é o que permite ao VERIFY (lição 6) fazer uma afirmação limpa: este teste passou de pulado para verde, este endpoint agora devolve 400, nada mais mudou. Se uma unidade junta dois comportamentos, uma falha fica ambígua — você não consegue dizer qual metade regrediu sem desfazer tudo. Escolher uma, portanto, não é conselho de produtividade; é o que mantém o proof gate significativo e o loop depurável.

ANALYZE consome a saída do LEARN e nada mais

O ANALYZE só pode raciocinar sobre fatos fundamentados — o retrato que o LEARN estabeleceu. Ele não vai olhar de novo (isso foi o LEARN) e não edita (isso é o EXECUTE). Se uma avaliação precisa de um fato que você não tem, isso é um sinal para voltar ao LEARN, não para chutar. Manter os passos separados é o que impede que “análise” vire silenciosamente “comecei a consertar”.

A saída é uma decisão somada às suas razões

Uma passada de ANALYZE concluída produz uma unidade escolhida e uma justificativa curta e legível: em qual balde cada gap caiu, como os principais candidatos foram avaliados, e por que este venceu. Essa justificativa é observabilidade — ela cai no LOOP-LOG.md para que o humano possa ler a decisão sem ter de derivá-la de novo (lição 7).

2

Os quatro baldes


Classificar significa colocar cada gap em exatamente uma de quatro caixas. As caixas não são sobre quão grande ou difícil é o trabalho — são sobre se cabe a você fazer, e se é agora. Aqui estão elas.

Um gap que o LEARN achou em qual caixa ele vai? ON-SCOPE parte do done-when acordado ex.: o próprio guard de query vazia → faça, na sua vez DO-NOW bloqueia a unidade atual agora mesmo ex.: os testes nem rodam → fure a fila NEEDS-USER só o humano pode decidir ex.: 400 ou 422? decisão de produto → repasse OUT-OF-SCOPE real, mas não esta meta ex.: reescrever todo o índice de busca → estacione, anote
Quatro caixas, uma regra: cada gap vai em exatamente uma. A cor é a ação — só as duas primeiras colunas alimentam o passo de avaliação.
on-scope → faça na sua vez do-now → fure a fila needs-user → repasse out-of-scope → estacione

O teste para cada balde

On-scope: o contrato done-when (lição 2) exige isso? Se sim, e não está bloqueando nada urgente, é trabalho normal na fila. Do-now: a unidade atual seria impossível ou não confiável sem isso? Um runner de testes quebrado, uma dependência faltando, um baseline vermelho que você senão confundiria com a sua própria quebra — esses passam na frente porque envenenam o VERIFY. Needs-user: existe uma bifurcação genuína que só o humano pode resolver — uma escolha de produto, uma ação irreversível, uma ambiguidade que o escopo não fixou? Então é um repasse, pronto para decisão (lição 9), não um chute. Out-of-scope: é real mas fora desta meta? Estacione onde não vai se perder, e siga em frente.

Out-of-scope é registrado, nunca descartado em silêncio

“Fora de escopo” não quer dizer “ignore”. Um item estacionado é anotado (uma nota no backlog, um ticket de follow-up) para que a trilha de observabilidade fique honesta e nada real evapore. O loop pode não fazer algo; ele não pode fingir que não viu.

Needs-user é o único balde que pode bloquear o humano

Todo o resto roda AFK. O contrato da suíte inteira é que o humano apenas observa — ele lê o log, não executa. A única exceção é uma bifurcação needs-user: o loop pausa e repassa uma pergunta pronta para decisão (nunca um chute meio construído). Esse repasse é o único ponto em que um humano está no caminho, e é deliberadamente raro.

3

Faça a triagem dos gaps nos baldes


Agora faça a classificação você mesmo. Abaixo há um quadro de triagem cujas quatro colunas são os quatro baldes. Os cartões são os gaps exatos que o LEARN confirmou na tarefa RHG, mais um par de distrações tentadoras. Arraste cada cartão — ou aperte a seta dele — para o balde onde ele pertence. Não existe “em progresso” aqui; classificar é uma ordenação, e cada gap cai em exatamente um balde.

As contagens no topo se mantêm honestas: quantos gaps são acionáveis agora (on-scope + do-now), e quantos você deixou de lado (needs-user + out-of-scope). Só os acionáveis seguem para a avaliação.

Pense nisso como… separar a correspondência da manhã em quatro bandejas antes de abrir qualquer coisa. Contas a pagar, algo urgente que não pode esperar, uma carta sobre a qual você precisa perguntar ao seu parceiro, propaganda para a reciclagem. Você não age sobre nada enquanto separa — só garante que cada peça esteja na bandeja certa. Agir vem depois, uma peça de cada vez.

Acionáveis agora: 0 · Deixados de lado: 0
On-scope0
parte do done-when → faça na sua vez
Do-now0
bloqueia a unidade → fure a fila
Needs-user0
decisão humana → repasse
Out-of-scope0
real mas não esta meta → estacione

O quadro é um classificador um-de-quatro

Cada gap é um objeto com um campo col restrito aos quatro baldes. As colunas na tela não são a fonte da verdade — o array é — então um cartão fisicamente não pode estar em dois baldes e as contagens nunca desviam. Isso espelha a disciplina exatamente: classificação é uma função de um gap para uma única categoria, não um achismo. A contagem de “acionáveis agora” soma as duas primeiras colunas, porque esses são os únicos gaps que merecem uma avaliação na próxima seção.

De onde isto retoma a partir da lição 3: o quadro do LEARN terminou com observações confirmadas; este quadro pega esses mesmos itens e atribui um balde a cada um. Confirme primeiro (LEARN), classifique depois (ANALYZE) — os dois quadros são os dois passos, em ordem.

4

Numa imagem só: classificar → avaliar → escolher


O passo inteiro é um funil. Muitos gaps entram; eles são ordenados em baldes; só os acionáveis são avaliados; e exatamente um sai por baixo como a unidade escolhida. Todo o resto é estacionado, repassado, ou colocado na fila para uma passada posterior.

1 · CLASSIFICAR 2 · AVALIAR 3 · ESCOLHER UMA muitos gaps on-scope do-now needs-user out-of-scope AVALIAR cada Encaixe · Risco · Prova Bloqueio · Próximo (só os baldes acionáveis) → repasse → estacionado UMA unidade maior valor, delimitada e provável EXECUTE próximo passo (lição 5)
Leia da esquerda → direita. O funil estreita de propósito: muitos entram, um sai. Os ramos tracejados também são desfechos reais — só não “faça agora”.

A regra única

ANALYZE sempre termina com uma única unidade escolhida. Se uma passada termina com “e também estas quatro”, ela não terminou de analisar — só fez uma lista de tarefas, e listas de tarefas não sobrevivem ao contato com o proof gate.

5

A rubrica de avaliação: cinco eixos


Uma vez que um gap está num balde acionável, você o avalia em cinco eixos rápidos. Eles foram escolhidos para que um único olhar te diga se uma unidade é uma boa próxima jogada — não só se vale a pena fazer algum dia, mas se vale a pena fazer agora, e se você conseguirá provar isso quando terminar.

ENCAIXE serve ao done-when? RISCO quebra / incha? PROVA limpo de verificar? BLOQUEIO algo impede? PRÓXIMO destrava mais? pese em conjunto valor disto como PRÓXIMO ✓ escolher agora alto encaixe, baixo risco ↦ adiar bloqueado ou baixo valor
Cinco leituras rápidas → um julgamento. Encaixe e Prova altos puxam uma unidade para cima; Risco alto e um Bloqueio ativo a empurram para baixo.

Os cinco eixos

Encaixe — quão diretamente a unidade serve ao done-when. Uma unidade que satisfaz diretamente uma linha do contrato pontua alto; um “seria legal ter” tangencial pontua baixo mesmo que seja tentador. Risco — a chance de quebrar outra coisa ou inchar além do seu limite (risco alto é ruim, então conta contra). Prova — quão limpo o VERIFY consegue confirmar isso no boundary real: uma unidade com um teste esperando pontua alto; uma cuja única prova é “parece certo” pontua baixo. Bloqueio — há algo que impede de começar agora mesmo (um fato faltando, uma bifurcação needs-user, uma suíte de testes não rodada)? Um bloqueio ativo pode vetar uma unidade que de resto seria ótima. Próximo — quanto concluí-la destrava depois; uma unidade pequena que abre o caminho para mais três pesa acima da sua categoria.

Por que Risco é o eixo que as pessoas leem errado

Iniciantes avaliam unidades por empolgação (“isso seria legal”). A rubrica força em vez disso as perguntas sem glamour: consigo provar, vai quebrar o build, está mesmo destravado. Uma unidade de Encaixe alto com um Bloqueio ativo não é a próxima jogada — o bloqueio é. Essa reordenação é a maior parte do valor de avaliar.

A rubrica é uma heurística, não uma fórmula

Você não está somando os eixos num número preciso; está usando-os para tornar o trade-off legível. Uma unidade com Encaixe estelar mas sem Prova deveria te deixar nervoso, e a rubrica é o que traz isso à tona antes que você afunde uma passada nela. O scorecard na próxima seção torna a pesagem tangível.

6

Avalie as unidades candidatas


A triagem deixou três candidatos acionáveis na tarefa RHG. Aqui estão eles como cartões, cada um avaliado pela rubrica. Pense neles como variantes de uma decisão — mesmo componente (a próxima jogada), sabores diferentes — postos lado a lado para você comparar de propósito. Use os botões para ordenar por um eixo; o cartão que vence naquele eixo se acende. O que vence no geral carrega um selo verde.

Ordenar por:
melhor próxima jogada
A

on-scope

Adicionar o guard de query vazia

Devolver 400 quando q está ausente ou vazio; tirar o skip do teste que espera.

Encaixe
92
Risco
18
Prova
95
veredito · escolher agora
B

meio out-of-scope

Reescrever a camada do índice de busca

Fazer index.lookup rejeitar queries curtas na camada de dados também.

Encaixe
40
Risco
78
Prova
35
BloqueioToca muitos chamadores; sem teste esperando.
veredito · estacionar
C

needs-user

Escolher o status code: 400 vs 422

Uma decisão de produto sobre qual código de erro a API deve devolver.

Encaixe
55
Risco
22
Prova
50
BloqueioDecisão humana — não dá para chutar.
veredito · repassar

Dois eixos independentes, como variante × tamanho

Cada cartão carrega suas avaliações cruas em atributos data (data-fit, data-risk, data-proof). Ordenar reordena os cartões pelo eixo escolhido e acende o líder — exatamente como uma galeria de componentes deixa você comparar uma variante ao longo de um eixo de tamanho. A ordenação “geral” usa uma pontuação simples e legível: Encaixe e Prova somam, Risco subtrai, e um Bloqueio ativo limita o resultado. O cartão A vence não por ser o mais ambicioso, mas por ser o mais entregável agora: Encaixe alto, Prova alta, Bloqueio zero.

Os cartões perdedores não estão errados — estão em outro lugar

O cartão B é a clássica armadilha de scope-creep: uma melhoria real que incha o risco e não prova nada que o guard já não prove. O cartão C é genuinamente valioso mas vive em needs-user — é um repasse, não a unidade desta passada. Avaliar não só acha o vencedor; te diz por que cada perdedor é estacionado ou repassado, que é a justificativa que cai no log.

7

Pontue uma unidade você mesmo


Os cartões mostraram avaliações fixas. Agora é você que gira os botões. Arraste os três sliders para avaliar uma unidade em Encaixe, Risco e Prova; o medidor e o veredito atualizam ao vivo. Experimente os presets para sentir como um candidato real pontua — e veja o que um Bloqueio ativo faz até com uma unidade de Encaixe alto.

Pense nisso como… uma mesa de som. Empurre Encaixe e Prova para cima e o nível sobe para o verde; empurre Risco para cima e ele cai de volta para o vermelho. Um bloqueio é o botão de mudo — acione-o e não importa quão boa esteja a mixagem, nada sai até você liberá-lo.

Experimente um candidato:
Encaixeserve ao done-when
90/100
Riscoquebra / incha
20/100
Provalimpo de verificar
90/100
Bloqueioimpede de começar
livre
0
adiartalvezescolher agora
adiar

Uma ponderação legível, não uma caixa-preta

A pontuação é deliberadamente simples para você poder prevê-la: value = Fit + Proof − Risk, limitada a 0–100. Acima de ~120 cru ela lê “escolher agora” (verde), no meio “talvez”, e baixo “adiar”. O slider de Bloqueio é especial — acione-o e o veredito é forçado a adiar independente do resto, porque um bloqueio ativo significa que a unidade literalmente não pode começar. Esse veto duro codifica a regra mais afiada da rubrica: um bloqueio vence uma pontuação alta toda vez.

function score(fit, risk, proof, blocked) {
  if (blocked) return { v: 0, verdict: 'defer' };  // hard veto
  const v = clamp(fit + proof - risk, 0, 200);
  return { v, verdict: v >= 120 ? 'go' : v >= 70 ? 'maybe' : 'defer' };
}

Mova os botões para o preset do guard e você cairá fundo no verde; mova para o preset da reescrita do índice e Risco alto somado a Prova baixa o arrastam para adiar — os mesmos vereditos que os cartões alcançaram, agora pelas suas próprias mãos.

8

Unidades concorrentes, lado a lado


Às vezes a decisão não é “qual gap” mas “qual o tamanho da mordida”. Para a correção de query vazia há pelo menos três unidades razoáveis, cada uma um tamanho diferente da mesma mudança. Nenhuma está errada; cada uma faz uma barganha diferente entre quão rápido entrega, quanto prova, e quanto risco carrega. Coloque-as lado a lado e escolha o limite de propósito. Passe o mouse ou foque um cartão para trazê-lo à frente.

A

Só o guard

Adicionar um early return para q vazio, tirar o skip do único teste que espera. A menor unidade provável.

# api.py — the whole change
if not (q := request.args.get("q", "").strip()):
    return jsonify(error="empty query"), 400

Prós

  • +Minúscula: um guard, um teste sem skip.
  • +Prova de forma limpa — a spec já existe.

Contras

  • Deixa os outros endpoints sem guard.
Escolha esta quando Você quer a jogada de maior valor e menor risco que o VERIFY consiga provar nesta passada. O padrão.
B

Guard + helper compartilhado

Extrair um helper require_query() e chamá-lo de /search agora, pronto para os irmãos depois.

def require_query(args):
    q = args.get("q", "").strip()
    if not q: abort(400, "empty query")
    return q

Prós

  • +Um guard reutilizável para endpoints futuros.
  • +Ainda verificável pelo mesmo teste.

Contras

  • Superfície maior; abstração antes de um 2º chamador.
  • Mistura “correção” com “refatoração” numa unidade.
Escolha esta quando Dois ou mais endpoints já precisam do mesmo guard hoje — o reúso é real, não especulativo.
C

Guard em todo endpoint

Varrer todos os seis endpoints de query e adicionar validação a cada um numa passada só.

# touches 6 handlers + 6 new tests
for ep in (search, suggest, facet,
           related, recent, popular):
    add_guard(ep)   # one big unit

Prós

  • +Corrige a classe inteira do bug de uma vez.

Contras

  • Sem limite: um teste vermelho não diz qual deles.
  • Cinco de seis ainda não têm spec — Prova baixa.
Escolha esta quando Quase nunca como uma unidade. Divida-a: entregue o guard, depois enfileire cada irmão como sua própria passada delimitada.

Para esta passada eu mais preciso…

Delimitar pela provabilidade, não pela ambição

As três unidades melhorariam o RHG. O desempate é o proof gate: a unidade A mapeia um-para-um num teste existente, então o VERIFY consegue fazer uma afirmação inequívoca. A unidade C junta seis comportamentos, então uma falha é um mistério e o humano que observa não consegue dizer o que mudou. A preferência do loop pela menor mordida provável não é timidez — é o que mantém cada passada depurável e cada afirmação honesta. A unidade C não é rejeitada; ela é re-moldada em seis unidades enfileiradas, uma por endpoint irmão, cada uma sua própria passada futura.

A abstração tem uma “regra do dois”

A unidade B extrai um helper antes de existir um segundo chamador, o que é generalidade especulativa — risco sem retorno presente. Se o LEARN tivesse mostrado dois endpoints já precisando do guard hoje, o reúso de B seria real e sua avaliação subiria. A rubrica só dá crédito ao reúso que você consegue apontar, não ao reúso que você imagina.

9

A matriz Encaixe / Risco


Dois dos cinco eixos fazem a maior parte da escolha, então ajuda plotar só eles. Ponha Encaixe de um lado e Risco do outro e você tem quatro quadrantes. O que você quer é o canto superior esquerdo: alto encaixe, baixo risco — alto valor, improvável de morder. É ali que o guard de query vazia cai.

ESCOLHER AGORA alto encaixe · baixo risco DIVIDA PRIMEIRO alto encaixe · alto risco PREENCHIMENTO baixo encaixe · baixo risco EVITAR baixo encaixe · alto risco Encaixe ↑ Risco → A · o guard ← a unidade escolhida C · decisão do status code needs-user → repasse B · reescrita do índice estacionar
Plote Encaixe contra Risco e a decisão quase se faz sozinha: o círculo no canto superior esquerdo é a sua próxima jogada.

O que fazer em cada quadrante

Superior esquerdo (alto encaixe, baixo risco) — escolha agora; este é o ponto ideal. Superior direito (alto encaixe, alto risco) — o trabalho importa mas a mordida é grande demais ou perigosa demais; divida em unidades menores e prováveis e escolha a fatia mais segura. Inferior esquerdo (baixo encaixe, baixo risco) — preenchimento inofensivo; é seguro mas não move o done-when, então espera. Inferior direito (baixo encaixe, alto risco) — evite; muito perigo por pouco valor. A matriz é uma primeira passada rápida; Prova, Bloqueio e Próximo depois desempatam entre os sobreviventes.

Por que a reescrita do índice fica no inferior direito

Ela pontuou Encaixe baixo (o guard já satisfaz a linha do contrato) e Risco alto (toca todo chamador sem teste esperando). Esse é o quadrante de evitar — não porque seja uma má ideia para sempre, mas porque como a unidade desta passada é a pior troca no quadro.

10

Uma unidade, três abordagens


Você escolheu a unidade: adicionar o guard de query vazia. Mas até uma unidade pode ser construída de mais de um jeito, e o ANALYZE também é onde você escolhe a abordagem. Alterne entre três jeitos de implementar o guard; o diagrama e a nota de avaliação atualizam juntos para você sentir cada trade-off antes de o EXECUTE tocar uma linha.

Requisição GET /search handler /search checa q inline vazio → 400 index guard mora junto do seu único uso @require_query decorator vazio → 400 /search fica limpo idx reutilizável, opt-in por rota middleware roda em TODA requisição /search /suggest /upload ?! também atinge rotas sem q — risco ↑
Leia da esquerda → direita: a requisição chega ao handler, que checa a query ele mesmo antes do índice.

Inline no handler

O guard são três linhas no topo de /search. A mudança mora exatamente onde está o seu único efeito.

+Menor diff; mapeia 1:1 no teste que espera.
+Raio de impacto zero — toca um handler.
Se um irmão precisar depois, você copia.
Encaixealto
Riscobaixo
Provalimpa

A abordagem é parte do ANALYZE, não do EXECUTE

Escolher como construir a unidade ainda é análise — muda Risco e Prova, então pertence antes de qualquer código ser escrito. Os três diagramas vêm em um único SVG inline; a tablist troca qual <g data-diagram> é mostrado e reescreve a legenda e o aria-label, com foco itinerante por setas conforme o padrão de abas do WAI-ARIA. Para o RHG, a abordagem A vence do mesmo jeito que a unidade A venceu: maior Encaixe e Prova, menor Risco. O decorator só vira a decisão certa quando um segundo chamador real existe; o middleware exagera o escopo e arrasta rotas que não têm query nenhuma.

11

Uma unidade por vez vs juntar tudo em lote


Este é o hábito que o ANALYZE existe para impor, então encare-o de frente. À esquerda, o jeito do loop: escolha uma unidade, prove-a, depois vá de novo. À direita, o jeito tentador: agarre tudo de uma vez. Eles parecem semelhantes no começo e divergem completamente no proof gate.

UMA UNIDADE POR VEZ escolha 1 unidade o guard execute-a uma mudança verify ✓ teste → verde, claro faça o loop de novo próxima unidade, do zero cada passada: uma mudança provável que você sabe nomear vs JUNTAR TUDO EM LOTE agarre 5 unidades "já que estou aqui" execute todas 5 mudanças emaranhadas verify ✗ vermelho — qual das 5? uma falha que você não localiza → desfaça o lote inteiro
Mesmo começo, extremos opostos. Uma unidade dá ao VERIFY um sim/não limpo; um lote lhe dá um mistério.

Por que uma vence

Uma unidade delimitada é a maior mudança sobre a qual o VERIFY ainda consegue fazer uma afirmação inequívoca. Cruze essa linha e um resultado vermelho para de te dizer qualquer coisa — e o humano que observa o log não consegue mais ver o que mudou. “Escolha uma” é o preço de um proof gate significativo.

12

A unidade escolhida, como um plano


A decisão está tomada: entregar o guard de query vazia. O último ato do ANALYZE é moldar essa única unidade num plano minúsculo que o EXECUTE possa seguir — o que ela faz, os passos, os riscos, e a barra de saída que prova que está pronta. Clique pela faixa para ler cada fase. Note que o plano inteiro é para uma unidade; esta é uma mudança delimitada, não um projeto.

Pense nisso como… um cartão de receita para um único prato, não o jantar inteiro. Ingredientes, três passos, o único jeito de saber que está pronto (o teste fica verde). Você não planeja o cardápio inteiro — você planeja o único prato que sai em seguida.

Unidade Guard de query vazia em /search Balde on-scope Veredito escolher agora (Encaixe 92 · Risco 18 · Prova 95)

Clique num passo — ou foque a barra e use — para abri-lo.

Passo 1 · faça primeiro

Reproduza o gap

~2 min

Meta: Ver o bug com seus próprios olhos antes de corrigir, para que o EXECUTE comece de uma falha confirmada, não de uma crença.

Tarefas
  • Bata em GET /search?q= e confirme que devolve todas as linhas
  • Rode pytest -q para confirmar que o baseline está verde (11 passaram)
  • Localize a spec pulada test_empty_query_returns_400
Pronto quando
  • O bug de query vazia é reproduzido no serviço em execução
  • O teste que espera é encontrado e lido
Riscos & mitigações
Baixo Não consegue rodar o serviço localmente Ambiente não configurado. Mitigação: o teste pulado já codifica o bug — leia-o em vez de fazer curl.

O plano é moldado em torno do proof gate

Note que a última fase não é “entregue” — é “passe na barra de saída”. A barra de saída é um gate mensurável: um teste específico indo de pulado para verde, o resto da suíte permanecendo verde, o endpoint devolvendo 400. “Parece certo” não é um gate. Moldar a unidade assim no momento do ANALYZE significa que o EXECUTE sabe precisamente o que é sucesso, e o VERIFY (lição 6) tem uma coisa inequívoca para provar. A barra de marcos é uma pequena tablist conduzida por estado por passo; numa execução real esses estados refletiriam o tracker ao vivo, não o plano como escrito.

Uma unidade, quatro pequenos passos — ainda uma unidade

Reproduzir → adicionar guard → tirar skip do teste → provar não são quatro unidades; é a forma interna de uma mudança delimitada. Cada passo é uma leitura ou uma edição mínima que constrói rumo a um único desfecho provável. Essa é a diferença entre um plano para uma unidade e um plano de projeto.

13

Onde o ANALYZE se encaixa no loop


ANALYZE é a dobradiça entre olhar e fazer. Ele só roda depois que o LEARN fundamentou os fatos, e precisa terminar antes de o EXECUTE tocar qualquer coisa — porque o EXECUTE precisa de exatamente uma unidade escolhida para agir. Aqui está o ciclo inteiro com o ANALYZE aceso, e a única coisa que ele precisa repassar adiante.

LEARN feito (lição 3) ANALYZE você está aqui EXECUTE a seguir (lição 5) VERIFY o proof gate DECIDE de novo ou parar fatos 1 unidade DECIDE → "de novo" reentra no LEARN; a próxima passada reclassifica o novo estado
ANALYZE transforma os fatos do LEARN em exatamente uma unidade para o EXECUTE. Sua única saída — a unidade escolhida — é todo o sentido do passo.
entra: fatos fundamentados classificar → avaliar → escolher sai: UMA unidade delimitada sem edição aqui
14

No código: a decisão, capturada


Uma passada de ANALYZE não muda um único arquivo — ela produz uma decisão e a anota. Aqui está como isso aparece como a nota que cai no log de observabilidade: o balde de cada gap, as avaliações dos candidatos ativos, e a única unidade escolhida, com sua razão. O humano pode ler isto e saber a próxima jogada sem ter de derivá-la de novo.

LOOP-LOG.md — uma passada de ANALYZE, fix/empty-query
# ANALYZE — classify, rate, pick

classify:
  empty-q guard ................. on-scope     # done-when line
  tests don't run? (they do) .... n/a          # baseline green
  400 vs 422 status code ........ needs-user   # product call → handoff
  rewrite search index .......... out-of-scope # parked: backlog#214

rate (Fit / Risk / Proof):
  A · add guard ................. 92 / 18 / 95   # blocker: none
  B · index rewrite ............ 40 / 78 / 35   # blocker: many callers
  C · status-code call ......... 55 / 22 / 50   # blocker: human-only

pick: A — add the empty-query guard (inline)
  # highest Fit + Proof, zero blocker, maps to the waiting test.
  # C handed off as decision-ready; B parked. no files changed.

Acesse você mesmo

A justificativa do ANALYZE vive no arquivo de observabilidade da execução — tipicamente LOOP-LOG.md na raiz do repo. Leia-o com sed -n '1,40p' LOOP-LOG.md ou salte para a última passada com grep -n "ANALYZE" LOOP-LOG.md | tail -1. Ele é append-only: cada passada adiciona seu bloco de classificar / avaliar / escolher para que o histórico de decisões seja auditável.

Crucialmente não há comandos de edição aqui — uma passada de ANALYZE é decisão pura. Se você algum dia vir uma mudança de arquivo atribuída ao ANALYZE, o passo vazou para o EXECUTE; esse é o boundary que o loop mantém limpo (lição 5). E qualquer fato externo em que uma avaliação se apoiou é fundamentado do único jeito permitido — o Bright Data CLI (lição 11), nunca a memória, nunca WebSearch/WebFetch.

15

Exemplo resolvido: de dez gaps a uma unidade


Amarre tudo na tarefa RHG, do início ao fim — só a parte do ANALYZE. O LEARN entregou um retrato fundamentado com vários fios soltos. Veja uma passada cuidadosa de ANALYZE transformar essa pilha numa única próxima jogada defensável.

classificarColoque cada gap num balde

O guard de query vazia é claramente on-scope — é a própria linha do done-when. “Qual status code, 400 ou 422?” é uma decisão de produto, então é needs-user. “Reescrever o índice de busca” é real mas não relacionado a esta meta, então é out-of-scope — estacionado como nota de backlog, não descartado. O baseline estar verde significa que não há bloqueio do-now. Quatro gaps, quatro caixas.

avaliarPontue os candidatos acionáveis

Só o guard on-scope realmente sobrevive como unidade nesta passada. Avaliado: Encaixe 92 (ele é a linha do contrato), Risco 18 (um handler, nenhum chamador afetado), Prova 95 (um teste esperando torna a verificação trivial), Bloqueio nenhum, Próximo alto (fecha o gap central). A reescrita do índice pontua ao contrário e a decisão do status code é um repasse — nenhum é a unidade desta passada.

escolherEscolha exatamente uma

O guard vence em todo eixo que importa para uma próxima jogada: alto valor, baixo risco, trivialmente provável, destravado. Escolha-o — e resista ao puxão de também corrigir os cinco endpoints irmãos “já que estou aqui”. Esses viram suas próprias unidades enfileiradas. Uma unidade vai para o EXECUTE.

repassarEncaminhe o resto, não o perca

A pergunta do status code vai para o humano como um repasse pronto para decisão (400 vs 422, com o trade-off declarado) para que o EXECUTE não fique travado chutando. A reescrita do índice é estacionada no backlog. Nada real é descartado; tudo é escolhido, repassado, ou registrado.

O que o ANALYZE produziu

Uma unidade escolhida (o guard inline de query vazia), três gaps encaminhados (um repassado, um estacionado, um baseline já em ordem), e uma justificativa de um parágrafo no log. Zero arquivos mudados. O EXECUTE agora tem uma única coisa delimitada e provável para fazer — e o humano consegue ver exatamente por quê. Isso é uma passada de ANALYZE bem feita.

A passada, como ela cai para o humano observar

Todo o sentido é uma decisão legível que o humano lê sem refazê-la (a observabilidade sobre a qual a suíte roda — lição 7). Só decisão; cada avaliação tem uma razão, cada gap encaminhado tem um destino.

# ANALYZE result — fix/empty-query
chosen unit : add empty-query guard (inline, /search)
rationale   : Fit 92 · Risk 18 · Proof 95 · blocker none
handoff     : status code 400 vs 422 → decision-ready to user
parked      : index-layer rewrite → backlog#214
deferred    : 5 sibling endpoints → one unit each, later passes
files changed: 0   # ANALYZE never edits
16

Verificação rápida: ficou na cabeça?


Lembrar vence reler. Responda cada uma de memória antes de espiar — a opção que você escolher é corrigida na hora, com uma nota do porquê. Sem pistas na formatação; as respostas estão espalhadas de propósito.

Q1Quais são as três jogadas de uma passada de ANALYZE, em ordem?

Q2Um gap é uma decisão de produto real que só o humano pode tomar. Qual balde?

Q3Por que uma passada de ANALYZE escolhe apenas uma unidade delimitada?

Q4Uma unidade tem Encaixe alto mas um Bloqueio ativo. O que a rubrica diz?

Q5O que uma passada de ANALYZE concluída muda no repo?

Pontuação: 0 / 5
Seu agente é seu professor. Quer rodar uma passada real de ANALYZE no seu próprio backlog, ou está em dúvida sobre como delimitar uma unidade para o VERIFY conseguir prová-la? Pergunte. A seguir — agora que você escolheu exatamente uma unidade — é fazê-la sem scope creep: EXECUTE: uma unidade delimitada, bem feita.