on-scope
Adicionar o guard de query vazia
Devolver 400 quando q está ausente ou vazio; tirar o skip do teste que espera.
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.
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.
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.
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”.
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).
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.
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.
“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.
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.
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.
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.
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.
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.
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 — 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.
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.
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.
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.
on-scope
Adicionar o guard de query vazia
Devolver 400 quando q está ausente ou vazio; tirar o skip do teste que espera.
meio out-of-scope
Reescrever a camada do índice de busca
Fazer index.lookup rejeitar queries curtas na camada de dados também.
needs-user
Escolher o status code: 400 vs 422
Uma decisão de produto sobre qual código de erro a API deve devolver.
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.
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.
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.
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.
À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.
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
Contras
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
Contras
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
Contras
Para esta passada eu mais preciso…
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 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.
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.
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.
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.
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.
O guard são três linhas no topo de /search. A mudança mora exatamente onde está o seu único efeito.
Um wrapper @require_query guarda a checagem; você inclui as rotas uma de cada vez. Reúso sem um raio de impacto global.
A validação roda em toda requisição antes de qualquer rota. Poderoso — e exatamente por isso arriscado: ele toca endpoints que não têm q nenhum.
/upload que não deviam ser tocadas.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.
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.
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.
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.
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.
GET /search?q= e confirme que devolve todas as linhaspytest -q para confirmar que o baseline está verde (11 passaram)test_empty_query_returns_400Meta: Um early return em api.py que rejeita um q ausente ou vazio com um 400 — e nada mais.
q com um default e .strip() — pegue tanto None quanto ""400 com um corpo de erro curto quando estiver vazioif q is None deixa ?q= passar. Mitigação: o fato fundamentado do LEARN — faça strip e teste por falsy.
Meta: Transformar a spec que espera numa checagem ativa, para que a mudança tenha um boundary real contra o qual ser julgada.
@skip de test_empty_query_returns_400?q= (string vazia) ao lado do caso de parâmetro ausenteq vazio quanto ausente são cobertosMeta: Entregar ao VERIFY uma unidade que se prova no boundary real — o gate mensurável que diz “pronto”, não “parece pronto”.
test_empty_query_returns_400 vai de pulado → verde/search?q= devolve 400, não todas as linhasNote 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.
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.
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.
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.
# 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.
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.
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.
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.
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.
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.
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.
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
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?