Base: anatomia do loop|INEMA.CLUB-PRO

Aula 5 · 16 min

Estado fora do modelo: arquivos e git como memória

Num loop longo, o contexto do modelo vai ser compactado, resetado ou trocado por uma sessão nova. O que só existia na conversa some ou volta como resumo, misturando fato e palpite. A saída: sessão descartável, estado em arquivos e no git, e todo ciclo começa relendo. Você monta um ciclo assim e o interrompe de propósito.

Começar a aula
Pastas de papel e um disco externo ao lado de um notebook, ligados por cabos finos que se ramificam.

Nesta aula você vai

  1. 1Por que a memória do modelo não aguenta um loop longo
  2. 2A lista de itens com passes, o arquivo de progresso e o git log
  3. 3Interromper e retomar sem refazer nem pular
  4. 4Git como desfazer e como histórico do loop

Objetivo: montar um ciclo descartável que relê o estado em arquivo, faz um item, verifica e commita, e retomar depois de interromper sem refazer nada.

01Uma sessão descartável, um estado que fica

Clique em cada passo do ciclo: o que ele lê e o que deixa gravado.

Role a página: cada etapa abaixo acende a sua parte do diagrama.

  1. 1/6

    Sessão nova

    Pode ser um /clear, uma compactação, um codex exec novo, o Ralph chamando de novo ou outra pessoa assumindo. O desenho parte do pior caso: a sessão não lembra de nada e pode ser interrompida no meio.

  2. 2/6

    Relê o estado

    No harness de longa duração da Anthropic (26/11/2025), toda sessão começa assim: onde estou (pwd), o que foi feito (git log e o arquivo de progresso), qual o próximo item, e um teste básico antes de codar. A lista de itens é JSON com o campo passes; o post diz que o modelo sobrescreve JSON menos que Markdown.

  3. 3/6

    Faz um item

    Escolhe o primeiro item pendente e faz só ele. No post da Anthropic, as sessões seguintes só podem mudar o campo passes; não reescrevem nem apagam itens da lista.

  4. 4/6

    Verifica e marca

    O item só vira passes: true se a verificação daquele item passou. A linha no progresso diz quando e o resultado. Se falhou, o item continua pendente e o motivo fica registrado.

  5. 5/6

    Commit

    O commit é o checkpoint: se a próxima sessão cair, nada do que foi verificado se perde; se um item saiu errado, git revert desfaz. O LOOP-R usa o mesmo princípio para versões do processo ("git é o mecanismo de promoção e rollback"; detalhe no curso 5).

  6. 6/6

    Relê a pasta, não a conversa

    A sessão é descartável; o estado não. O que precisa sobreviver a uma compactação, a um reset ou a uma troca de modelo vai para arquivo e commit antes do fim do ciclo.

O kit execucao-longa leva a ideia para sete arquivos (goal, plan, state, progress, failures, decisions, canal): é a aula 1 do curso 2.

02Um ciclo descartável em Python

Cada execução é uma "sessão" que não lembra de nada: relê, faz um item, verifica, grava e commita. Sem modelo: a ação é escrever um arquivo.

Terminal · preparar a pasta
mkdir -p ~/ensaio-loop/estado && cd ~/ensaio-loop/estado && git init -q
cat > features.json <<'EOF'
[
 {"id":"f1","descricao":"ler o CSV","passes":false},
 {"id":"f2","descricao":"contar linhas","passes":false},
 {"id":"f3","descricao":"gravar o resumo","passes":false}
]
EOF
git add -A && git commit -qm inicio
ciclo.py
#!/usr/bin/env python3
"""Um ciclo que começa do zero toda vez: relê o estado nos arquivos, faz UM item, grava e commita."""
import json, subprocess, sys, datetime, pathlib

estado = pathlib.Path("features.json")
itens = json.loads(estado.read_text())
pendentes = [i for i in itens if not i["passes"]]
if not pendentes:
    print("nada pendente: objetivo cumprido")
    sys.exit(0)
item = pendentes[0]
print(f"releu features.json: {len(itens) - len(pendentes)} feitos, {len(pendentes)} pendentes")
print(f"faz: {item['id']} ({item['descricao']})")
pathlib.Path(f"{item['id']}.txt").write_text(item["descricao"] + "\n")   # a "ação"
item["passes"] = pathlib.Path(f"{item['id']}.txt").exists()                # a "verificação"
estado.write_text(json.dumps(itens, ensure_ascii=False, indent=2) + "\n")
agora = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
with open("progress.md", "a") as f:
    f.write(f"| {agora} | {item['id']} | passes={item['passes']} |\n")
subprocess.run(["git", "add", "-A"], check=True)
subprocess.run(["git", "commit", "-qm", f"feito: {item['id']}"], check=True)
print(f"commit: feito: {item['id']}")
Terminal · rodar, "cair" e retomar
python3 ciclo.py
# feche o terminal aqui, abra outro e volte para a pasta
cd ~/ensaio-loop/estado
python3 ciclo.py && python3 ciclo.py && python3 ciclo.py
git log --oneline
Exemplo do repositório
$ python3 ciclo.py
releu features.json: 0 feitos, 3 pendentes
faz: f1 (ler o CSV)
commit: feito: f1
--- (sessão descartada; outra começa do zero)
$ python3 ciclo.py
releu features.json: 1 feitos, 2 pendentes
faz: f2 (contar linhas)
commit: feito: f2
$ python3 ciclo.py
releu features.json: 2 feitos, 1 pendentes
faz: f3 (gravar o resumo)
commit: feito: f3
$ python3 ciclo.py
nada pendente: objetivo cumprido

$ git log --oneline
58d590c feito: f3
16ff9e9 feito: f2
7345668 feito: f1
7f9664d inicio

Os hashes mudam na sua máquina; a ordem e as mensagens não.

03Interrompa no meio e veja a retomada

Cada tarefa é um ciclo. Rode, interrompa e rode de novo: o que já tem commit não é refeito.

pendentes (passes: false)

nesta sessão

passes: true + commit

verificação falhou

Simulação ilustrativa no navegador. A falha é proposital: item sem prova não vira passes: true.

04Prática

Na sua máquina. Não gasta cota: não há modelo no ciclo.

E1 · Três sessões, três commits

10 min

Prepare a pasta, cole o ciclo.py e rode uma vez. Feche o terminal, abra outro e rode até aparecer "nada pendente".

Pronto quando: A última rodada imprime nada pendente: objetivo cumprido, e git log --oneline | wc -l → 4.

E2 · A verificação que reprova

15 min

Acrescente o item f4 "arquivo vazio" e mude a verificação para exigir arquivo não vazio (stat().st_size > 0). Faça a ação do f4 gravar um arquivo vazio e rode.

Pronto quando: python3 -c "import json;print([i['passes'] for i in json.load(open('features.json'))])" → [True, True, True, False], e tail -1 progress.md termina com passes=False |.

E3 · A lista de um trabalho seu

15 min

Escolha uma tarefa real de várias horas e quebre em pelo menos 5 itens verificáveis num features.json, todos com passes: false, numa pasta de projeto com git.

Pronto quando: python3 -c "import json;d=json.load(open('features.json'));print(len(d)>=5, any(i['passes'] for i in d))" → True False, e git log --oneline -1 -- features.json mostra o commit da lista.

05Teste da aula

Pergunta 1 de 4

Depois de uma compactação, o resumo diz "f3 concluído", mas features.json mostra f3 com passes: false e não há commit de f3. O que vale?competência

06Em três frases

Sessão descartávelDesenhe para o pior caso: a próxima sessão não lembra de nada e pode cair no meio.
Releia antes de agirLista com passes, arquivo de progresso e git log dizem onde parou; o resumo da conversa não.
Um item, uma prova, um commitpasses só vira true com verificação, e cada item verificado vira um ponto de retomada.

Para ir além

Aula anteriorPróxima aula