Red→Green Iterate Workflow
Ciclo testes vermelhos → user feedback → testes verdes pra resolver bug pipelines. State machine, decision tree pra AskUserQuestion, templates literais, contrato de reversibilidade total. Bootstrap autocontido pra sessão zerada replicar.
TL;DR. Quando o user pede "review feedbacks → arruma bug pipeline → testes red→green → solvable por LLM agent", siga este workflow. Não improvise estilo de commit nem ordem das fases. Resultado real: 27 feedbacks analisados, PR mergeado limpo, foundation de observabilidade no ar — sem retrabalho, sem loop infinito.
Bootstrap pra sessão zerada. Se você é um agente Claude Code começando agora:
- Leia esta página até o fim antes de tocar em código
- Estabeleça o contrato de reversibilidade (seção 3) antes de qualquer commit —
git tag session-start-<topic>-<ts>+ branch isolada - Aplique a state machine (seção 5) — não pule fases
- Copie templates literais (seção 6) — não improvise estilo de commit
- Pause em pontos do decision tree (seção 7) — não decida unilateralmente
- Responda o self-check (seção 17) — se algum item falhar, pergunta antes de seguir
Contrato de reversibilidade. Toda sessão autônoma que rode este workflow tem garantia explícita: qualquer trabalho feito pode ser desfeito, em 5 níveis de granularidade (do último commit até a sessão inteira), com 1 comando cada. Sem necessidade de --force-push, sem reset --hard, sem panic. Detalhes formais na seção 3.
1. Quando aplicar este workflow
Pré-condições obrigatórias no prompt do user (4 gatilhos). Se algum falta, provavelmente este não é o workflow certo:
- "go deep" — exploração profunda em múltiplas fontes (DB + logs + frontend + backend)
- "generate /html report" — saída tangível antes de propor mudança
- "red state → green" — testes falhando antes de qualquer fix
- "solvable by an llm agent" — pipeline reusável, não fix one-shot
Trigger phrase canônica observada na sessão fundadora:
"Do a review on what its gathered, go deep in logs, [...] generate /html report with findings, common pains, categorize, [...] develop a plan to tackle each. To solve an issue, automated tests, ensuring red state, then fix until green. Solid pipeline solvable by an llm agent."
Se o user não pediu nada parecido, ofereça este workflow só se a tarefa for complexa o suficiente. Senão, faça direto.
2. Sessão fundadora
session 72ccdb3f (arquivada localmente, não pública). Projeto interno: produto SaaS com agente conversacional + feedback tracker próprio.
Tarefa: revisar ~30 feedbacks brutos coletados pelo agente; classificar; gerar plano de correção determinístico; entregar PR mergeavel com observability foundation pra destravar o pipeline issue-tracker → bug fix.
Resultado: 1 PR mergeado limpo (PKG-00), 39 testes verdes, 4 gaps de infra fechados, retrocompatibilidade preservada por 6 baselines protegidos. Foundation destrava 10 PKGs subsequentes (geo guard, anti-sycophancy, NLP filter loss, share-link bugs, etc).
3. Contrato de reversibilidade
Conceito fundador. Sessão autônoma sem contrato de reversibilidade é uma bomba. Sessão com contrato é uma proposta — user revisa, aceita ou descarta.
3.1 Os 5 níveis de reversão
| Nível | Granularidade | Comando | Custo | Quando usar |
|---|---|---|---|---|
| L1 | Último commit | git checkout HEAD~1 -- <files> + git reset --soft HEAD~1 | Quase zero — working tree preservado | Erro óbvio no último step |
| L2 | Uma fase (red, green, etc) | git reset --soft <tag-da-fase-anterior> | Baixo — múltiplos commits viram unstaged | Toda fase precisa repensar |
| L3 | Um PKG inteiro | git revert <hash-do-merge>..HEAD ou git reset --soft <tag-pkg-NN-start> | Médio — preserva diff pra estudo | PKG inteiro foi pelo caminho errado |
| L4 | Sessão inteira | git checkout main && git branch -D red-green/<topic> + git tag -d session-start-<topic> | Alto se sessão durou 6h — mas zero risco residual | Sessão autônoma inteira falhou validação humana |
| L5 | Cherry-pick parcial | git checkout -b red-green/<topic>-v2 main && git cherry-pick <good-commits> | Médio — escolhe o que salvar | Sessão majoritariamente boa, partes ruins descartadas |
3.2 Pré-condições obrigatórias
Antes do primeiro commit da sessão, o agente garante:
- Branch isolada criada:
git checkout -b red-green/<topic>-<YYYYMMDD>— nunca commit emmain/master - Tag de início:
git tag session-start-<topic>-<ts>aplicada no commit pai (cabeça atual de main no momento de fork). Esta tag é o ponto-de-zero da sessão. - Tag de início pushada (se remote existe):
git push origin session-start-<topic>-<ts>— protege contragit tag -dacidental local. - Working tree limpo:
git status --porcelainretorna vazio antes do bootstrap. Se sujo,dirty_commitseparado (vide seção 12.2 Aider pattern).
Sem esses 4 itens, o contrato está quebrado. Sessão não inicia.
3.3 Pontos de checkpoint
A cada transição de fase do state machine, agente aplica tag adicional:
git tag phase-red-<topic>-<ts> # ao entrar em red
git tag phase-green-<topic>-<ts> # ao entrar em green
git tag phase-probe-<topic>-<ts> # ao entrar em probe_review
git tag pkg-NN-merged # ao mergear (terminal — não move)Cada tag = âncora pra reset L2. Permite "voltar pra antes do green" sem perder o trabalho do red.
3.4 Ponto-de-não-retorno
Uma vez que pkg-NN-merged foi pushada pro remote, não desfaz. Por construção:
- Tag pushada = terminal (vide Aider em 12.4)
- Reverter = abrir novo PKG com
revert(NN): undo pkg-NN — <reason>, não rewrite
Sem exceção. --force-push em sessão autônoma é violação de contrato.
3.5 Discard de sessão inteira (L4)
Sequência canônica quando user aprova descarte total:
# 1. Sair da branch
git checkout main
# 2. Apagar branch local (todo o trabalho some)
git branch -D red-green/<topic>-<YYYYMMDD>
# 3. Apagar branch remota (se foi pushada)
git push origin --delete red-green/<topic>-<YYYYMMDD>
# 4. Apagar tags de fase + session-start
for tag in $(git tag --list "phase-*-<topic>-*" "session-start-<topic>-*"); do
git tag -d "$tag"
git push origin --delete "refs/tags/$tag" 2>/dev/null || true
done
# 5. Sanity: nada da sessão sobreviveu
git log --grep "<topic>" --oneline # deve retornar vazio5 comandos. Reversibilidade L4 garantida.
3.6 Cherry-pick parcial (L5)
Quando user gostou de N de M PKGs e quer descartar o resto:
# 1. Nova branch a partir de main
git checkout -b red-green/<topic>-v2 main
# 2. Cherry-pick os PKGs aprovados (in order)
git log red-green/<topic>-<YYYYMMDD> --grep '^pkg(0[12]):' --reverse --format='%H'
# pega hashes → cherry-pick
git cherry-pick <hash-pkg-01-scaffold> <hash-pkg-01-green> <hash-pkg-02-scaffold> ...
# 3. Tag inicial da v2
git tag session-start-<topic>-v2-<ts>
# 4. Branch original pode ser apagada agora (L4)L5 é a forma de sessão autônoma "falhar parcialmente". O bom do trabalho sobrevive sem o ruim.
3.7 O contrato escrito
O agente escreve este compromisso no body do primeiro commit da sessão:
chore(<topic>): bootstrap autonomous session
Reversibility contract:
- Branch: red-green/<topic>-<YYYYMMDD>
- Session start tag: session-start-<topic>-<ts>
- L1-L5 rollback supported (see docs/agents/red-green-iterate-workflow#3)
- No force-push, no reset --hard, no rewrite of pushed history
- Terminal markers: pkg-NN-merged tags (push = irreversible)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>Este commit é a assinatura do contrato. Auditor (user, code reviewer, outro agente) lê e sabe exatamente o que está protegido.
4. Anatomia: dois cycles aninhados
OUTER cycle (por PKG):
explore → plan (n×PKG.md) → red → expand_red → green → probe_review → merged
INNER cycle (dentro de cada estado):
ação → status report ao user → AskUserQuestion se trigger bateu → próximo estadoA página inteira gira em torno da OUTER. INNER é a granularidade de cada turno.
Cada transição da OUTER aplica uma tag (vide 3.3) — a tag é o ponto de reversão L2.
5. State machine
| Estado | Critério de entrada | Critério de saída | Artefato | Tag aplicada | Reverte para |
|---|---|---|---|---|---|
session-start | Branch isolada + working tree limpo | Tag session-start-<topic>-<ts> aplicada + contrato commitado | Commit chore(<topic>): bootstrap autonomous session | session-start-<topic>-<ts> | (nada — é o piso) |
pending | PKG-NN.md criado, escopo definido | User confirmou escopo via AskUser | tasks/PKG-NN.md frontmatter status: pending | — | session-start |
exploring | Pelo menos 5 TaskCreate paralelos em fontes independentes | Findings sintetizados em HTML report | /tmp/claude-html/<topic>-<ts>.html | — | session-start |
planned | HTML report aberto + plano de N pacotes mapeado | User aprovou recorte | README.md, TEMPLATE.md, PROMPT.md | phase-planned-<topic>-<ts> | session-start |
red | Test scaffold escrito, todos falham | pytest ≥N failed + ≥1 passed (baseline) | commit pkg(NN): scaffold red ... | phase-red-<topic>-<ts> | planned |
expand_red | User pediu mais cobertura ou baseline falta | pytest ≥M failed + ≥6 passed (retrocompat) | commit pkg(NN): expand red ... | — | red |
green | Cada gap tem fix mapeado | Todos os testes do PKG passam + zero regressão lateral | commit pkg(NN): make ... green | phase-green-<topic>-<ts> | red ou expand_red |
probe_review | Migração aplicada prod + UI wired + smoke ok | User reviewou e aprovou merge | status .md → probe_review | phase-probe-<topic>-<ts> | green |
merged | PR squashed em main, tag aplicada e pushada | — (terminal) | tag pkg-NN-merged, status .md → merged | pkg-NN-merged (push) | L3 only — abrir PKG novo de revert |
Transições críticas com guard:
red → expand_redsó se user pediu cobertura extra ou falta baseline. Senão pula pragreen.green → probe_reviewexige zero regressão em suites laterais. Não é só "PKG passa".probe_review → mergedé o único ponto onde squash acontece. Antes disso, commits ficam no branch.mergedé o único estado que viola reversibilidade fácil. Push da tag = ponto-de-não-retorno.
6. Templates literais
Copy-paste ready. Anonimizados onde precisa.
6.1 Frontmatter de tasks/packages/PKG-NN-<slug>.md
---
status: pending # → red → red_expanded → green → probe_review → merged
priority: P0 # P0 P1 P2 P3 P4
gaps:
- G1: <gap description>
- G2: <gap description>
tests_failing: 0
tests_passing: 0
pr: null
refs:
- <product>.com/issues
---6.2 Bootstrap de sessão autônoma (assinatura do contrato)
# Pré-flight
git status --porcelain # MUST be empty
TOPIC="<topic>"
TS=$(date -u +%Y%m%dT%H%M%SZ)
BRANCH="red-green/${TOPIC}-$(date -u +%Y%m%d)"
# Cria branch isolada
git checkout -b "$BRANCH"
# Tag de início
git tag "session-start-${TOPIC}-${TS}" HEAD
git push origin "session-start-${TOPIC}-${TS}" || true # remote pode não existir
# Primeiro commit: contrato
git commit --allow-empty -m "$(cat <<EOF
chore(${TOPIC}): bootstrap autonomous session
Reversibility contract:
- Branch: ${BRANCH}
- Session start tag: session-start-${TOPIC}-${TS}
- L1-L5 rollback supported
- No force-push, no reset --hard, no rewrite of pushed history
- Terminal markers: pkg-NN-merged tags (push = irreversible)
EOF
)"6.3 Commit seed pipeline (planned state)
docs(packages): seed <project> issues package pipeline + Ralph runbook
Roadmap orientado a pacotes (não semanas). Cada PKG = 1 PR mergeable,
spec auto-contida, test red→green deterministico.
N pacotes seed:
- PKG-00: <foundation>
- PKG-01: <feature> (P0, feedback #X)
[...]
Setup files:
- README.md, PROMPT.md, RALPH_RUNBOOK.md, TEMPLATE.md
Refs: <product>.com/issues6.4 Commit scaffold red (entra em fase red, tag phase-red-...)
pkg(00): scaffold red test for <foundation>
Test suite confirms N infra gaps blocking the <pipeline>:
- G1 <module> <kwarg/field> missing
- G2 <module> <fn> missing
- G3 <model> <columns> missing
- G4 <model>.<field> missing + <fn> doesn't accept <param>
Current state: 10 failed, 1 passed.
Refs: <product>.com/issuesApós commit:
git tag "phase-red-<topic>-$(date -u +%Y%m%dT%H%M%SZ)" HEAD6.5 Commit expand red
pkg(00): expand red test suite (27 failed, 6 passed)
User feedback: cobrir mais cenários antes do fix — retrocompatibilidade
fica como guard contra regression.
Added coverage:
- G1 e2e: <signal> reaches HTTP payload + persists to DB
- G2 <fn>: edge cases (mapping file + fallback + plain phone)
- G3 endpoint: <verb> <path> (auth, idempotent)
[...]
Retrocompat baselines now protected (6 tests must keep passing):
- <fn> legacy 3-arg call
- POST <path> without <new_kwarg>
[...]
Refs: <product>.com/issues6.6 Commit make green (entra em fase green, tag phase-green-...)
pkg(00): make all tests green — <foundation>
Fixes for the N infra gaps:
G1 — <module> agora aceita <kwarg>. Backend já persistia.
G2 — <module>/__init__.py expõe <fn> como top-level.
G3 — <model> tem <field1>+<field2>+<field3>. <verb> <path> idempotente.
G4 — <model>.<field> column adicionada. Backfill em migração.
Test status:
test/packages/test_pkg_00.py — 33 passed in 11.12s
test/components/ — zero regressions
test/bases/ — zero regressions
Refs: <product>.com/issues6.7 Status report ao user (estilo caveman)
10 failed, 1 passed — RED confirmado. Tag phase-red aplicada. Commit + AskUser.39 passed (was 33; +6 partner). Migração Neon. phase-green tagged. Status .md → green.Padrão: [N] failed, [M] passed — <signal>. <tag aplicada>. <next>. Sem artigos.
6.8 Comandos de rollback (L1-L5)
# L1 — desfaz último commit, working tree preservado
git checkout HEAD~1 -- $(git diff-tree --no-commit-id --name-only -r HEAD)
git reset --soft HEAD~1
# L2 — volta pra fase anterior (lista tags primeiro)
git tag --list "phase-*-<topic>-*" | sort
git reset --soft "phase-red-<topic>-<ts>"
# L3 — desfaz PKG inteiro (revert preserva história)
git revert --no-commit <hash-first-pkg-commit>..<hash-last-pkg-commit>
git commit -m "revert(NN): undo PKG-NN — <reason>"
# L4 — sessão inteira sumir (vide 3.5)
# L5 — cherry-pick parcial (vide 3.6)7. Decision tree pra AskUserQuestion
Regras explícitas. Se nenhuma dispara, não pergunta — caveman + ação direta.
| Condição | Pergunta sugerida |
|---|---|
| Antes do bootstrap da sessão | "Confirma branch isolada red-green/<topic> + tag session-start? Aprovação L4 fácil depois." |
| Prestes a aplicar migração de DB em prod | "Preview SQL anexado. Aplicar agora ou gerar dry-run primeiro?" |
| Mudança altera role/permissão de usuário existente | "<role A> = founder; <role B> = partner? Ambos têm dogfood demote?" |
| RED scaffold pronto, antes de fixar | "Expandir cobertura antes do fix ou já parto pra green?" |
| Próximo PKG vai começar | "PKG-NN começa red agora ou termina docs do PKG anterior?" |
Antes de push da tag pkg-NN-merged (ponto-de-não-retorno) | "Pushar tag terminal pkg-NN-merged? Após isso, só revert via PKG novo." |
| Dúvida custaria menos de 30s mas pode dar 30min de retrabalho | "<question específica>" |
| Conflito entre dois critérios de classificação | "<X> conta como sinal real ou dogfood?" |
Pattern: 12 ocorrências na sessão fundadora + 2 novas (bootstrap, push terminal). Não mais.
Anti-regra: depois de receber resposta, execute imediatamente sem confirmar de novo.
8. Caveman mode
Workflow assume caveman mode full ativo. Skill caveman (/caveman full) ou /caveman ultra se contexto for crítico.
Status reports em fragments. Drop articles, drop pleasantries, drop hedging. Code blocks e commits ficam normais.
Não tente "ser mais claro" voltando pra verbose. Clareza vem do número concreto (27 failed vs 6 passed), não do floreio.
9. Paralelização
| Fase | Padrão | Não fazer |
|---|---|---|
exploring | 5-7 TaskCreate em paralelo + 1-2 Agent subagents | Loop sequencial de greps |
red / green | Sequencial, determinístico | Paralelizar fix de gaps interdependentes |
| Bash multi-call | Até 6 chamadas independentes num único turno | Chain com && quando podiam ser paralelas |
| Subagent (Agent tool) | Quando query é independente e respondeu pra atualizar contexto | Pra trabalho que precisa contexto contínuo |
10. Rastreabilidade
4 camadas redundantes — perde 1, ainda recupera contexto:
.md status files(tasks/packages/PKG-NN.md): frontmatterstatus: <state>evolui com cada commit.- Git tags por fase (
phase-red-<topic>-<ts>,phase-green-...,pkg-NN-merged): âncoras de rollback L1-L3. - Git tag de sessão (
session-start-<topic>-<ts>): âncora de rollback L4. - Commit metadata (
Refs: <product>/issues#N+ Co-Authored-By): foreign key + autoria-agente.
Se sessão quebrar no meio, próximo agente roda:
git tag --list "session-start-*" "phase-*" "pkg-*-merged" | sort
grep -l 'status:' tasks/packages/PKG-*.md | xargs grep '^status:'
git log --oneline -20E reconstrói o estado em menos de 1 min.
11. Git como base de dados do workflow
Insight central: git não é só versionamento, é o storage do state machine + storage da reversibilidade. Cada artefato git tem papel funcional, não cosmético.
| Artefato git | Papel no workflow | Reverte como? | Quem lê |
|---|---|---|---|
| Commit | Transição entre estados. Subject = estado novo. | L1 — git checkout HEAD~1 -- <files> + soft reset | Próximo agente, reviewer |
Branch (red-green/<topic>) | Escopo de 1 sessão autônoma. Vida curta. | L4 — git branch -D | Owner da sessão |
Tag session-start-<topic>-<ts> | Piso da sessão. Âncora L4. | (não reverte — é o piso) | Discovery + auditoria |
Tag phase-<state>-<topic>-<ts> | Checkpoint por fase. Âncora L2. | L2 — git reset --soft <tag> | Rollback de fase |
Tag pkg-NN-merged (pushed) | Terminal. Marca "estado final". | L3 only — abrir PKG de revert | Discovery "o que fechou" |
| PR review (approve) | Gate humano. Substitui AskUser quando precisa revisão estruturada. | (não reverte — é gate) | Reviewer |
| PR check (CI) | Gate automatizado. Critério de saída de green → probe_review. | (não reverte — é gate) | Pipeline CI |
Refs: <product>/issues#N | Foreign key reversa. git log --grep '#21' traz histórico. | (não reverte — é metadado) | Auditoria post-mortem |
| Co-Authored-By | Marca autoria-agente. | (não reverte — é metadado) | Análise de retrocompat |
Consequência prática: querying estado e revertendo trabalho = git calls, não scraping externo nem ferramenta extra.
# Estado atual de cada PKG sem abrir IDE
git tag --list 'pkg-*-merged' | sort # quais fecharam
git tag --list 'session-start-*' # quais sessões existiram
git tag --list 'phase-*-<topic>-*' # checkpoints da sessão atual
git log --grep '^pkg(' --oneline # commits per-package
git log --grep 'Refs: <product>.com/issues#21' # histórico do feedback #21Padrões de commit como state transitions:
| Prefix | Transição disparada | Reversível? |
|---|---|---|
chore(<topic>): bootstrap autonomous session | (nada) → session-start | L4 — sumir com tudo |
docs(packages): seed ... | pending → planned | L1 ou L2 |
pkg(NN): scaffold red ... | planned → red | L2 — volta pra phase-planned |
pkg(NN): expand red ... | red → red_expanded | L1 ou L2 |
pkg(NN): make ... green | red → green | L2 — volta pra phase-red |
pkg(NN): UI ... + propagate | green → probe_review | L2 — volta pra phase-green |
pkg(NN): finalize .md status=merged | probe_review → merged (antes do push) | L1 |
(tag pkg-NN-merged pushada) | terminal | L3 only — revert PKG novo |
Anti-pattern: commit sem prefix taxonômico, ou prefix que não bate com transição declarada no .md status. Quebra grep, auditoria e recovery.
Pra próxima sessão: se o repo segue este workflow, lê o git primeiro. Antes de qualquer Read ou Plan, roda os 5 greps acima. Estado completo do projeto em menos de 5s sem custar contexto.
12. Aider — git enforcement concreto
Aider (CLI agent open-source da Aider-AI) implementa de forma madura vários patterns desta cartilha. Leituras diretas do source confirmam decisões.
12.1 Auto-commit per edit-batch
Toda edit-batch dispara auto_commit(edited). Não é commit por arquivo nem por turn — é commit por lote coerente (aider/coders/base_coder.py:2375).
def auto_commit(self, edited, context=None):
if not self.repo or not self.auto_commits or self.dry_run:
return
res = self.repo.commit(fnames=edited, context=context, aider_edits=True, coder=self)
if res:
self.show_auto_commit_outcome(res)No red→green: cada transição é "edit-batch coerente". Commit no momento exato da transição.
12.2 Dirty commit guard — separação humano/agente
Antes de aplicar edits AI, Aider chama dirty_commit(). Mudanças pendentes do user são commitadas primeiro, separadas (aider/coders/base_coder.py:2199, 2238, 2291).
No red→green: parte da pré-condição (3.2 item 4). Garante boundary clean — L4 não joga fora trabalho do user.
12.3 Registry aider_commit_hashes — quem pode desfazer o quê
self.aider_commit_hashes = set() # base_coder.py:349
self.aider_commit_hashes.add(commit_hash) # show_auto_commit_outcome:2400cmd_undo (aider/commands.py:553) usa como gate:
if last_commit_hash not in self.coder.aider_commit_hashes:
self.io.tool_error("The last commit was not made by aider in this chat session.")
returnNo red→green: sessão mantém set similar. Rollback L1 só toca em commits da própria sessão. Commits do user passam intactos.
12.4 Refuse undo if pushed — git remote como ponto-de-não-retorno
if local_head == remote_head:
self.io.tool_error("The last commit has already been pushed to the origin. Undoing is not possible.")
returnaider/commands.py:617. Uma vez no remote, terminal. Sem --force-push.
No red→green: o estado merged (com tag pkg-NN-merged pushada) é terminal por construção. Reversão exige novo PKG de revert — L3 only.
12.5 Surgical undo — per-file checkout + soft reset
Aider undo não faz git reset --hard. Faz:
for file_path in changed_files_last_commit:
self.coder.repo.repo.git.checkout("HEAD~1", file_path)
self.coder.repo.repo.git.reset("--soft", "HEAD~1")commands.py:626-644. Restaura cada arquivo, depois solta HEAD um passo atrás sem perder working tree.
No red→green: template L1 (em 6.8) é exatamente isso. Sempre per-file checkout + soft reset. Nunca --hard.
12.6 Attribution semantics
3 flags em aider/repo.py:131:
--attribute-author: Author = "User Name (aider)"--attribute-committer: Committer = "User Name (aider)"--attribute-co-authored-by: trailerCo-authored-by: aider (<model>) <aider@aider.chat>
Default: Co-Authored-By trailer on, author/committer off. Permite git log --author='aider' mas mantém author do humano.
No red→green: Co-Authored-By: Claude Opus 4.7 em todo commit segue a convenção. git log --grep 'Claude' traz toda autoria-agente.
12.7 Branch como sandbox autônomo
Aider não isola por default, mas é o pattern recomendado: aider/<topic> branch + revisão antes de mergear. Equivalente: skill solve-issue deste agente roda em worktree isolado.
No red→green: parte do contrato (3.2 item 1). Branch isolada é a pré-condição de L4.
13. Visualizador de fases — git como UI
Se cada commit é uma fase e o trabalho é serializado em git, dá pra renderizar a sessão inteira como página HTML estática com controles de rollback embutidos. Auditor humano entende e age sem reabrir o JSONL.
13.1 Esqueleto do visualizador
Bash one-liner que produz índice navegável:
git log --grep='^pkg(\|^chore(' --reverse --format='%H|%s|%ai' "$BRANCH" | \
while IFS='|' read hash subj date; do
state=$(git show "$hash:tasks/packages/PKG-$(echo $subj | grep -oE 'pkg\([0-9]+' | tr -d 'pkg(\)')-*.md" 2>/dev/null | grep '^status:' | head -1)
echo "<li><a href='./fase-$hash.html'>$subj</a> · $date · $state</li>"
done > index.htmlCada commit vira .html page com:
- Subject + body (= o que mudou + por quê)
git show <hash>rendered como<pre>com syntax highlight- Frontmatter do
tasks/packages/PKG-NN.mdnaquele commit (status, tests_failing, tests_passing) - Link pro próximo/anterior commit do mesmo PKG
- Link "abrir worktree neste ponto" →
git worktree add /tmp/snapshot-<hash> <hash>
13.2 Controles de rollback no visualizador
Cada página .html de commit oferece 4 botões (linkando comandos copy-paste pro terminal do user):
| Botão | Comando gerado | Nível |
|---|---|---|
| Reset until here | git reset --soft <hash-anterior> | L1/L2 |
| Revert this commit | git revert <hash> | L1 inverso |
| Fork branch from here | git checkout -b red-green/<topic>-v2 <hash> | L5 setup |
Discard session (só no commit chore: bootstrap) | sequência completa de 3.5 | L4 |
O visualizador não executa nada — só gera o comando. User copia-cola, decide.
13.3 Onde mora a UI
Opção mais simples: roda script local que gera estático em /tmp/claude-html/red-green-<session>/. Hook do agente no fim da sessão dispara. Browser abre na pasta.
Opção mais densa: gera dentro do repo como docs/sessions/<topic>.mdx, commitado junto. Próximo agente lendo o repo descobre todas as sessões via find content/docs/sessions/.
13.4 Sinal de sessão autônoma bem-sucedida
Visualizador exibe:
- Sequência
red → expand_red? → green → probe_review → mergedlinear (sem zigzag) - Cada commit tem prefix taxonômico (sem
fix: xyzsolto) tests_failingdecresce monotonicamente nos commits de fixtests_passingcresce monotonicamente- Nenhum commit fora do padrão entre dois commits do PKG (no contamination)
- Toda fase tem tag
phase-<state>-...aplicada (rollback L2 funciona) session-start-<topic>-<ts>existe e aponta pro fork-point de main
Se zigzag aparece, sessão entrou em recovery — auditar trecho específico, L5 cherry-pick descarta partes ruins.
13.5 Visualizador como gate de aprovação humana assíncrono
Workflow autônomo + visualizador + reversibilidade L4 viabilizam aprovação 100% assíncrona:
- Sessão autônoma roda 6h sem human-in-loop
- Gera HTML visualizador no fim, abre browser ou notifica
- User abre, lê 10min, decide:
- Aprovado → merge da branch + push das tags
pkg-NN-merged - Rejeitado total → L4 discard (3 minutos pra zerar tudo)
- Parcial → L5 cherry-pick (15 minutos pra preservar o bom)
- Aprovado → merge da branch + push das tags
- Em todos os casos, nada irreversível foi feito durante as 6h
O HTML + contrato de reversibilidade são o substituto do AskUserQuestion síncrono em sessões longas.
14. Anti-patterns evitados
- ❌ Sessão autônoma sem branch isolada → L4 impossível, panic se algo der errado
- ❌
git reset --hardem qualquer momento → perde working tree, perde possibilidade de auditar erro - ❌
--force-pushem branch da sessão → quebra ponto-de-não-retorno, viola contrato - ❌ Bootstrap sem tag
session-start-<topic>-<ts>→ L4 vira difícil - ❌ Push de tag
pkg-NN-mergedsem AskUserQuestion → ponto-de-não-retorno cruzado sem gate humano - ❌ Loop infinito de test→fix→test sem checkpoint AskUser → cada fase tem commit + status update
- ❌ Análise paralisia: gerar relatório sem ação → HTML report sempre seguido de plano de N pacotes
- ❌ Magic fix sem RED test → cada fix validado por failing test que vira passing
- ❌ Decisão unilateral em ponto sensível (role, prod migration, push terminal) → AskUserQuestion sync
- ❌ Drift do caveman mode pra "ser claro" → mantém até o merge
- ❌ Commit genérico "fix tests" → template estruturado por gap
- ❌ Perda de contexto entre fases →
.md status+ tags + Refs no commit
15. Proposta de skill futura
Não implementada. Só descrição pra próximo agente saber o que valeria a pena criar.
Nome: red-green-iterate
Trigger phrases: "review feedbacks + arruma bug pipeline", "itera red→green", "resolve issue tracker com testes auto", "solvable by llm agent", "rola sessão autônoma reversível pra X".
Quatro jobs:
- Bootstrap + contrato — gera scaffold
tasks/packages/PKG-NN-<slug>.md+TEMPLATE.md+PROMPT.md(Ralph recurring) +README.mdmaster index. Cria branch isolada + tagsession-start-<topic>-<ts>+ commit de contrato. Recusa se working tree dirty. - State transition — wraps git workflow: cada transição valida critério de saída + atualiza .md + commita com template + aplica tag de fase. Recusa transição se critério falha.
- Decision tree advisor — quando agente prestes a tomar decisão das 8 categorias do decision tree (incluindo bootstrap e push terminal), skill injeta
AskUserQuestionantes de executar. - Session lifecycle — comandos high-level:
start <topic>,checkpoint <phase>,end approve|discard|partial.discardexecuta sequência L4 inteira (5 comandos de 3.5).partiallista commits e ajuda L5 cherry-pick.
Sub-tools necessárias: templates literais inline, validador de transição, grep helper em .md status, gerador HTML do visualizador (seção 13).
Quando criar: depois que o workflow rodou em ≥3 projetos diferentes e os templates estabilizaram. Antes disso é cedo.
16. Como esta página foi criada e como replicar
Meta-bloco pro próximo agente. Tudo que precisa pra editar/redeployar.
- Path local:
~/src/docs-fonsecagabriel/content/docs/agents/red-green-iterate-workflow.mdx - Stack: fumadocs 16 + Next 16 standalone + Docker multistage + Kamal v2 → Contabo VPS
- Skill associada:
~/.claude-pessoal/skills/my-docs/
Deploy:
~/.claude-pessoal/skills/my-docs/scripts/deploy.shScript: commit pending (prompt mensagem) → refresh GHCR token de gh auth token → kamal deploy (~150s) → probe https://docs.fonsecagabriel.com.br/docs pra 200.
Verificação pós-deploy:
curl -s https://docs.fonsecagabriel.com.br/llms.txt | grep agents
curl -s https://docs.fonsecagabriel.com.br/llms.mdx/agents/red-green-iterate-workflow
open https://docs.fonsecagabriel.com.br/docs/agents/red-green-iterate-workflowSessão original arquivada (local, não pública): ~/.claude-pessoal/projects/<project-slug>/72ccdb3f-b891-4395-a6d7-cd652d83a2bc.jsonl (~3MB, 1150 linhas). Path real fica fora do journal.
17. Self-check antes de começar
Responda mentalmente. Se algum item falhar → release control + AskUser pra confirmar escopo.
- Tenho prompt do user com os 4 gatilhos? (deep / html report / red→green / llm-solvable)
- Working tree limpo (
git status --porcelainvazio)? - Vou criar branch
red-green/<topic>-<YYYYMMDD>+ tagsession-start-<topic>-<ts>+ commit de contrato antes de qualquer outro commit? - Toda transição de fase vai gerar tag
phase-<state>-<topic>-<ts>? - Vou criar
tasks/packages/PKG-NN-<slug>.mdcom frontmatterstatus: pending? - Sei quais ≤8 sinks de AskUserQuestion devo usar (incluindo bootstrap e push terminal)?
- Vou commitar atomicamente per gap usando template literal?
- Vou manter caveman mode até o merge?
- Vou usar paralelização só em
exploring, não emred/green? - Sei executar L1-L5 rollback (templates em 6.8)?
- Nunca vou rodar
git reset --hardnemgit push --forcenesta sessão? - Sei como recuperar contexto se sessão quebrar (5 greps em seção 10)?
12 checks. Passou em todos → executa. Falhou em qualquer um → pergunta.