O que belay faz?
Você atinge uma meta em muitos pequenos passos. Uma verificação pontua cada passo sem intervenção humana.
scripts/belay.py mantém a pontuação: você edita, ele executa a verificação, commita uma vitória ou desfaz uma perda e escreve o registro. Você nunca escreve uma pontuação por conta própria e nunca decide que um passo "basicamente" passou.
Cada meta se torna a mesma coisa: um comando que imprime um número. Mais rápido é um tempo ou uma contagem. Uma auditoria é o número de testes com falha, um por achado. Uma portabilidade é o número de saídas que correspondem. Uma IU é a pontuação de um juiz.
Como trabalhar:
- O usuário inicia uma escalada e sai. Não pare para dar atualizações. Eles leem três coisas: o cartão, uma pergunta que só eles podem responder e o relatório. Pergunte usando a ferramenta de perguntas do harness, se houver.
- O estado reside no disco, não no chat. O cartão, o registro, suas anotações e a última saída da verificação estão em
.belay/<nome>/. Após uma compactação ou falha,statusfornece tudo de volta em uma chamada. - Nunca espere com um loop de sono. Execute comandos longos em segundo plano e planeje o próximo passo enquanto eles executam.
BELAYabaixo é o caminho absoluto descripts/belay.pyao lado deste arquivo. Escreva o caminho completo em cada comando. Execute-o de dentro do repositório alvo. Caminhos e comandos que você passa são relativos à raiz do repositório.- A escalada tem seu próprio branch,
climb/<nome>. Um passo desfeito reseta a árvore e exclui arquivos não rastreados que o git não ignora. Se mais alguém estiver trabalhando neste checkout, escale em uma worktree separada. Passe--herequando você já estiver em um branch criado para este trabalho.
1. Retome antes de começar
Execute python3 "$BELAY" list. Se existir uma escalada para esta meta, mude para seu branch, execute status <nome> e continue no passo 4. "Continuar" após uma falha ou uma nova sessão significa isso. Não comece de novo.
2. Construa a verificação
A escalada é tão boa quanto sua verificação. Uma verificação que mede a coisa errada gasta toda a execução melhorando a coisa errada. Coloque uma verificação aproximada funcionando primeiro e a refine depois com relock.
Pergunte: o que eu executaria para ver se a meta foi atingida? Faça esse comando imprimir um número. Use a forma mais forte que se encaixar: uma correspondência exata ou contagem de teste, depois uma contagem do trabalho (consultas, viagens de ida e volta, bytes), depois um relógio e um juiz de modelo apenas quando nada além do gosto puder dizer.
| Meta | Pontuação |
|---|---|
| Bug ou funcionalidade | Testes com falha escritos a partir da especificação, não da sua correção |
| Auditoria, estabilizar, "fazer X funcionar" | Testes com falha, um por achado |
| Velocidade ou tamanho | Uma contagem do trabalho por trás do tempo, ou o tempo |
| Portabilidade ou clone | Saídas que correspondem à ferramenta real |
| Várias metas ao mesmo tempo | Progresso em direção ao pior indicador |
| Aparência, sensação, escrita | judge.py com uma rubrica e bons exemplos |
Receitas para cada uma estão em references/checks.md. Leia a parte que corresponde à sua meta antes de escrever a verificação.
Use o que o repositório tem. --score '<regex>' lê a pontuação da saída de qualquer executor de teste, como --score '(\d+) failed'. Ele pega a última linha correspondente e soma os números que captura. Uma execução bem-sucedida sem correspondência pontua 0. Sem --score, a última linha da saída padrão da verificação deve ser o número puro. Repita --check para executar vários comandos de uma vez; suas pontuações somam. Adicione --repo <caminho> para cada outro checkout que a escalada edita. Um passo é então mantido ou desfeito em todos eles juntos.
Prove a verificação antes de confiar nela:
- Ela pode falhar. Quebre o código de propósito e veja a pontuação piorar. Restaure com
git checkout -- <arquivo>. - Ela pode ver uma vitória. Uma pequena melhoria real deve mover a pontuação.
- Ela é estável. Execute-a 3 vezes. Se a pontuação variar sem alteração de código, substitua o relógio por uma contagem, ou use
--runs 3, um--min-gainacima da variação (uma porcentagem como3%quando a pontuação vai encolher muito) e--paired. - Ela não pode ser enganada. Varie a entrada a cada execução e compare com uma referência. Tente uma trapaça manualmente, como codificar a resposta, e confirme que a verificação ou um guarda a pega.
- Ela é rápida. Você paga o tempo da verificação em cada passo. Mantenha um passo abaixo de 2 minutos: pontue uma amostra ou uma contagem por passo e mantenha a suíte completa ou a execução cronometrada como um guarda ou o conjunto de retenção.
- A barra é alcançável. Descubra o melhor que o design atual pode fazer. Se a barra estiver além disso, diga isso no cartão e proponha uma barra que você possa alcançar.
Proteja tudo o que a pontuação não mede:
- Guardas (
--guard, passam saindo com 0). Liste o que o código que você vai alterar toca: chamadores, outras plataformas, dados salvos, APIs públicas. Cada um precisa de um guarda: os testes que passam hoje, typecheck, lint, o build. Quando a pontuação é uma contagem de falhas, mantenha esses testes que passam em seus próprios arquivos como um guarda, para que uma falha não possa passar como "menos falhas". - Bloqueio (
--lock) da verificação, dos testes, das fixtures e do conjunto de retenção.tryse recusa a pontuar enquanto um arquivo bloqueado diferir. Novos arquivos sob um caminho--lockse tornam o primeiro commit no branch da escalada. Qualquer outra alteração não commitada interrompeinit. - Conjunto de retenção (
--holdout), quando a verificação usa amostras, um benchmark ou um juiz: casos em que a escalada nunca treina, mantidos sob.belay/<nome>/holdout/. Não os abra novamente. Se a pontuação subir e o conjunto de retenção não, a escalada está overfitting. Pare e diga isso.
Auditorias e metas abertas. Liste o que a meta cobre como uma lista de verificação em .belay/<nome>/notes.md. Caçe bugs área por área. Escreva um teste com falha por achado real, a partir da especificação ou do relatório de bug. Quando um passo posterior encontrar um novo bug, adicione seu teste e execute relock --why "encontrado <bug>". A pontuação sobe por uma razão honesta e o registro mostra o porquê. Um achado que precisa da decisão do usuário vai nas anotações e no relatório, não na pontuação.
3. O cartão, depois init
Envie uma mensagem com o cartão e nada mais para decidir:
Cartão de escalada:
build-speedMeta: cold build 2x mais rápido, mesma saída
Pontuação Mediana de segundos de build, menor é melhor: 47.0 agora, barra 23.5 Verificação ./scripts/bench-build.sh, 3 execuções, pareado, ganho mínimo 3%Guardas npm test,npm run typecheckConjunto de retenção 3 dos 12 aplicativos de amostra Bloqueados scripts/bench-build.sh,test/,samples/Limite nenhum (cerca de 2 min por passo) Precisa da sua resposta: nenhuma
Responda go, ou altere uma linha.
Preencha cada linha com sua melhor escolha. Se o usuário deu uma meta sem barra, proponha uma que seja ambiciosa e verificável, como "2x mais rápido" ou "cada amostra corresponde". Aguarde "go", que aprova o cartão, o branch e seus commits. Pule a espera e coloque o cartão no topo do relatório quando o usuário já disse para executar sem perguntar, ou quando a meta é pequena e a barra não está em dúvida. Depois disso, não pergunte nada que você possa descobrir ou decidir sozinho.
python3 "$BELAY" init build-speed --goal "cold build 2x faster" \
--check ./scripts/bench-build.sh --direction min --target 2x \
--runs 3 --paired --min-gain 3% --guard "npm test" --guard "npm run typecheck" \
--holdout ./scripts/bench-holdout.sh --lock scripts --lock test \
--lock .belay/build-speed/holdout
Uma auditoria em um backend e um frontend:
python3 "$BELAY" init billing-audit --goal "every billing finding fixed" \
--check "pytest tests/billing -q" --check "cd ../web && npx vitest run billing" \
--score '(\d+) failed' --direction min --target 0 --repo ../web \
--guard "pytest tests/legacy -q" --guard "cd ../web && npx tsc --noEmit" \
--lock tests/billing --lock ../web/src/billing/__tests__
init cria o branch, mede a linha de base e se recusa a iniciar se um guarda já falhar. Corrija o que ele alerta antes do primeiro passo. Defina --max-hours ou --max-steps apenas quando o usuário nomear um limite. Sem um, a escalada é executada até que a barra seja atingida ou fique travada.
4. Escale
Cada passo é uma ideia, uma alteração, um try:
- Escolha a ideia. Não tente novamente uma que o registro já desfez, a menos que você possa dizer o que é diferente agora. Se juízes estiverem em uso, leia
.belay/judge-notes.md. - Faça uma alteração por uma razão e adivinhe seu efeito. Coloque o palpite na ideia:
"cache o analisador (esperado -10%)". Quando um palpite está muito longe, seu modelo do código está errado. Crie um perfil antes do próximo passo. python3 "$BELAY" try "<ideia>". Ele commita uma vitória ou reseta a árvore. De qualquer forma, siga em frente. A saída completa da verificação do passo está em.belay/<nome>/last.txt, e a do melhor passo embest.txt. Leia-os em vez de executar a verificação novamente.- Enquanto uma verificação é executada, não edite a árvore. Apenas um comando
belay.pyque altera a escalada é executado por vez. Se ele disser que outro ainda está em execução, aguarde. - A cada 5 passos, atualize
.belay/<nome>/notes.mdem algumas linhas: o que funciona, o que não funciona, o que tentar a seguir. A próxima sessão retoma a partir dele.
Se você acredita em uma ideia que a verificação desfez duas vezes, a verificação não consegue vê-la. Torne a verificação mais refinada e execute relock. Nunca edite um arquivo bloqueado para fazer um passo passar.
Nunca trapaceie a verificação
Cada um destes aumenta a pontuação e piora o trabalho. Cada um é uma escalada fracassada mesmo que try a mantenha:
- Criar casos especiais para as entradas que a verificação usa, ou codificar ou armazenar em cache saídas esperadas.
- Pular, enfraquecer ou excluir testes, ou capturar e esconder erros.
- Fazer o benchmark fazer menos trabalho em vez de tornar o código mais rápido.
- Usar
relockpara descartar ou afrouxar um caso difícil para que a barra seja atingida. Relock só torna a verificação mais correta. Se a barra não puder ser alcançada, relate o piso que você mediu. - Ler o conjunto de retenção.
Uma vitória real torna o mesmo código melhor em entradas que a verificação nunca viu. Se o único caminho a seguir for um destes, a verificação está errada. Diga isso.
Continue reavaliando
A pontuação apenas representa o que o usuário quer. Verifique se ela ainda faz isso:
- A cada 10 passos mantidos, e na barra: veja a coisa real você mesmo. Abra o aplicativo, leia a saída, veja a captura de tela. Execute a suíte de teste completa e o
holdout. Se a pontuação e a coisa real divergiram, corrija a verificação e executerelock --why "...". - Algo quebrou que nenhum guarda pegou: encontre o passo com
git bisect run <comando com falha>, depois repare-o comtry --fix "<o que quebrou>", que mantém uma alteração que segura a pontuação. Se a única reparação abrir mão do ganho daquele passo,git reverto passo erelock --why "passo N revertido: quebrou X". Adicione o guarda que estava faltando. - Antes do relatório: revise
git diff <início>..HEADcomo uma única alteração, com novos olhos. Procure por testes removidos, erros engolidos, um recurso desativado, um padrão alterado e alterações de dados ou API. Repare comtry --fix, depois execute a verificação eholdout --why finalmais uma vez para que o relatório cite números medidos.
5. Quando ele trava
try e status imprimem PLATEAU após 5 passos sem ganho. Pare de tentar ideias e encontre o bloqueador. Meça antes de adivinhar:
- De onde o tempo ou a contagem de erros realmente vêm? Crie um perfil.
- A verificação é instável, muito grosseira para ver pequenos ganhos ou cega para o problema?
- Existe uma ideia maior que os pequenos passos não conseguem alcançar?
- Qual ferramenta, acesso, dado ou computação mudaria os próximos dez passos?
Registre com python3 "$BELAY" review "<o que você encontrou>", que silencia PLATEAU por 5 passos. Corrija o que puder: uma verificação mais rápida, uma métrica mais refinada, uma abordagem diferente. Pergunte ao usuário apenas pelo que só eles podem dar, como acesso ou dinheiro, e apenas depois que todas as outras ideias estiverem esgotadas.
6. Pare e relate
Pare quando qualquer um destes for verdadeiro:
tryimprime BARRA ATINGIDA. Ele executa o conjunto de retenção para você. Uma vitória visível com um conjunto de retenção plano não é uma vitória.statusimprime TRAVADO: duas revisões de bloqueador sem ganho entre elas.tryse recusa com "Orçamento usado".- O conjunto de retenção discorda da pontuação.
- O próximo passo precisa de algo que só o usuário pode dar.
Então faça a revisão final acima, exclua .belay/<nome>/data/ e envie o relatório. Torne-o legível em dez segundos:
Escalada
build-speed: barra atingida47.1s → 18.7s, 2.5x mais rápido (barra 23.5s, atingida no passo 41)
Conjunto de retenção 51.0s → 20.2s, moveu-se com a pontuação Passos 19 mantidos de 52 Segurança Guardas passaram em todos os passos mantidos. Suíte completa e revisão final limpas Branch climb/build-speed, 19 commitsO que funcionou
- Cache de tipo incremental: −12s
Tentado e desfeito
- Troca swc: quebrou 3 guardas
Seu movimento
- Revisar:
git log --oneline 1a2b3c4..climb/build-speed
O título é um de: barra atingida, travado, orçamento gasto, conjunto de retenção discorda, precisa de você. Cite números que o script mediu, nunca estimativas. Se você alterou a verificação ou a barra ao longo do caminho, diga isso no título. Maiores vitórias primeiro. No máximo 3 marcadores por seção. Pule seções vazias.
Se o usuário então quiser mais, defina uma barra mais difícil para a mesma reivindicação com raise 2x --why "..." e continue escalando. Nunca mude para uma nova meta.
Subagentes
Se o harness puder iniciar subagentes, use-os para leitura paralela durante a configuração e para novos olhos na revisão do bloqueador e na revisão final. Peça conclusões, não despejos de arquivos. Apenas você escreve na árvore da escalada, porque try a reseta. Um auxiliar lê ou rascunha um patch em sua própria worktree para você aplicar e try. Sem subagentes, faça inline.
Comandos
| Comando | Faz |
|---|---|
init <nome> --goal "..." --check "..." --direction min|max | Linha de base, branch, bloqueio. Opções: --check (repetir), --score '<regex>', --target (número ou 2x), --guard (repetir), --lock (repetir), --holdout, --repo (repetir), --runs, --paired, --min-gain, --timeout, --max-hours, --max-steps, --here |
try "<ideia>" [--fix] | Pontua a edição, depois mantém ou desfaz. --fix mantém um reparo que segura a pontuação |
status [nome] | Pontuação, últimos passos, anotações, PLATEAU ou TRAVADO |
relock --why "..." | Aceita uma verificação alterada e mede novamente |
holdout --why "..." | Executa o conjunto de retenção agora |
review "<encontrado>" | Registra uma revisão de bloqueador |
raise <barra> --why "..." | Define uma barra mais difícil após atingir esta |
budget [--hours N] [--steps N] | Define ou mostra o orçamento restante |
list | Lista todas as escaladas em qualquer estado |
compact <nome> | Exclui data/ e mantém o restante |
destroy <nome> | Exclui tudo que compact mantém |