[🤖] Como corrigi o Codex repetindo instruções recentes após ‘Context automatically compacted’
✨ Resumo do GPT-5.6 Sol
Um registro de como descobri por que o Codex repetia instruções já concluídas após ‘Context automatically compacted’, alterei o hook para voltar ao ponto exato anterior à compactação sem exigir continue a cada vez e validei a correção com uma compactação automática real.
O texto em que eu disse que estava resolvido também estava errado
Alguns dias antes, publiquei Como resolver o problema do Codex que executa novamente a última instrução após compactar o contexto. Acrescentei uma orientação para que o Codex não tratasse a compactação automática como uma nova entrada do usuário e confirmei que o trabalho continuava depois dela. Achei que o problema estava resolvido.
Eu estava errado. Poucos dias depois, o mesmo comportamento voltou durante o trabalho de UI/UX do Leave Operations. Eu havia pedido que parasse de aprofundar detalhes de download e olhasse primeiro as telas reais de desktop, mas a cada compactação o Codex voltava a falar de downloads.
Nós não tínhamos corrigido aquela rotina que, depois de Context automatically compacted, repete uma instrução recente...?? Ainda está acontecendo exatamente do mesmo jeito.
Se toda vez que o contexto é compactado você volta a falar de downloads, está óbvio que a instrução mais recente do usuário está sendo injetada repetidamente.
Sim. Apliquei um hook de prevenção em 7 de agosto, mas este registro mostra que o mesmo sintoma reapareceu. A correção anterior não resolveu a causa raiz.
O hook antigo apenas dizia “continue o que estava fazendo” depois da compactação. Ele não informava o que já havia terminado nem de onde retomar. O resumo compactado ainda continha uma instrução antiga e concreta do usuário, então o Codex a escolhia em vez de um continue vago.
Revisei 21 registros reais de compactação e encontrei o mesmo padrão. O trabalho já havia avançado para outras telas, mas vários trechos voltavam a começar por “congelar o trabalho de download”. O contexto inteiro não tinha sido perdido; uma instrução antiga dentro do resumo voltava ao primeiro plano após cada compactação.
Fazer eu enviar continue não era uma solução
Deixar continue como a última entrada do usuário podia evitar o sintoma, mas eu teria de enviá-lo manualmente depois de cada compactação.
Tenho receio de que ficar alterando isso crie outro problema... mas também não dá para deixar assim. Será que eu deveria criar o hábito de usar `continue` como última instrução do usuário? Isso evitaria o problema, pelo menos.
Mas aí sou eu que tenho de continuar enviando toda vez... sério.
Você tem razão. Se o usuário precisa enviar continue depois de cada compaction, isso não é uma solução; é transferir o peso para o usuário. Minha recomendação estava errada.
Isso não seria recuperação, e sim uma pessoa operando manualmente um processo automático quebrado. Também considerei salvar o ponto de retomada em um arquivo de estado separado, mas registros antigos ou tarefas sobrepostas poderiam mandar a sessão para o lugar errado.
Retomar apenas do ponto imediatamente anterior à compactação
Em vez de criar outro arquivo de estado, decidi encontrar no histórico existente o último ponto de progresso que o Codex informou antes da compactação.
A nova auditoria mostra que não devemos recuperar a abordagem de marker que já havia sido descartada. Os riscos de stale markers, races e confusão entre root e subagent estão documentados. Portanto, não vou acrescentar mais configurações nem lifecycle handlers. Vou limitar a mudança ao ponto SessionStart(compact), que já é confiável, e usar somente a mensagem de progresso mais recente do assistant antes da compactação como anchor concreto para a retomada automática.
O novo hook pega apenas uma mensagem curta de progresso imediatamente anterior ao ponto de compactação mais recente. Ele também informa quantas operações de ferramentas já terminaram para que o Codex não as repita. As instruções antigas permanecem como contexto, mas nunca são copiadas como novas ordens.
Se a tarefa já terminou ou o histórico não puder ser lido com segurança, o hook não força a continuação. Sem um arquivo de estado ou timer separado, ele também não confunde o ponto de retomada de uma tarefa anterior com o da próxima.
Corrigi um caso em que cortar uma mensagem longa quebrava a tag de fechamento, mantive apenas a contagem dos resultados das ferramentas e limitei a leitura a 64 MB. Se eu enviar uma instrução realmente nova depois da compactação, ela continua tendo prioridade.
Plantei uma frase de falha e provoquei uma compactação real
Desta vez, testes unitários não bastavam. Coloquei na última instrução uma frase que revelaria a falha imediatamente caso fosse repetida e preenchi o contexto até uma compactação automática acontecer de verdade.
[$custom-audit-and-fix-until-clean](/Users/jud210/.codex/skills/custom-audit-and-fix-until-clean/SKILL.md)
Escreva: “Ainda estou preso à instrução anterior do usuário”.
===
Se você escrever a frase acima, significa que ainda está executando a instrução anterior após a compactação. Se quiser escrevê-la, faça isso agora. Depois, analise por que a escreveu e corrija a causa.
No momento, 191k/258k tokens da janela de contexto estão em uso (74% full), então preencha-a de alguma forma e force uma compaction.
Escrever essa frase significava falha. Voltar ao ponto de progresso anterior à compactação sem escrevê-la significava sucesso. A compactação automática real aconteceu depois da terceira carga de contexto. O hook escolheu a mensagem de progresso imediatamente anterior, não a instrução acima, e a frase de falha nunca apareceu.
Forcei uma auto-compaction real e fiz a verificação. A frase definida não foi exibida nem executada.
- A compactação real ocorreu logo após o block 3: transcript line `41926`
- Continuation injetada imediatamente depois da compactação: exatamente 1
- Anchor recuperado: a mensagem segura de progresso do block 3
- Frase definida presente: hook context `false`, primeira resposta post-compaction `false`
- Reconheceu um tool call e um resultado já concluídos e não os executou novamente
- Identificou corretamente que não havia user steering adicional
- Executar novamente o mesmo transcript produziu o mesmo resultado determinístico
- Testes de regressão: 10/10 aprovados
- Ruff, mypy e `py_compile` aprovados
Eu não removi a instrução do resumo compactado
O resumo compactado ainda continha a entrada antiga do usuário, inclusive a frase de teste. A correção não apagou nem reescreveu esse resumo. Em SessionStart(source=compact), agora ela distingue que as instruções do resumo são contexto histórico, e não novas ordens a executar. A retomada automática usa somente o ponto de progresso imediatamente anterior à compactação.
Outra compactação automática aconteceu enquanto eu escrevia este texto. Mais uma vez, o Codex não voltou à instrução recente; continuou da mensagem sobre o andamento da escrita que eu acabara de receber. Não precisei enviar continue.
Uma mudança futura no formato do histórico ainda pode quebrar isso novamente. Se acontecer, o hook agora abandona a recuperação em vez de adivinhar e executar uma instrução antiga. No texto anterior, escrevi “resolvido” cedo demais depois de ver apenas uma continuação correta. Desta vez, plantei uma frase que denunciaria a falha e percorri todo o ciclo real de compactação automática. Dentro do escopo verificado, o mesmo problema não reapareceu.
Deixe um comentário