A meia atualização no Windows: hermes.exe some e o carimbo de versão fica para trás


Você roda hermes update no Windows, vê uma tela de linhas de log passando, e a última é:

⚠ Update follow-up 'launchers' did not finish: launchers: source launcher publication failed — retry the source update (the next launch or `hermes update` retries it)

Parece que “isso se resolve sozinho na próxima vez”, então você fecha a janela. No dia seguinte, hermes --version ainda reporta a versão antiga, bin\hermes.exe sumiu e só restou hermes.cmd. Rodar a atualização de novo imprime o mesmo aviso. Dois PRs mergeados em 22-23 de outubro de 2026 desmontam esse loop.

Dois sintomas, uma única causa raiz

Essa linha de log são, na verdade, duas falhas separadas empilhadas:

  1. Um exe em execução não pode ser apagado. A atualização repinou o Python de novo (pm/lock.json passou de 3.14.7 para 3.14.9), então os launchers — bin\hermes.exe e companhia — precisam ser republicados. A publicação apaga primeiro o hermes.exe antigo para que ele não ofusque o comando novo, e o Windows se recusa a apagar uma imagem mapeada. A imagem em questão é justamente a que está rodando hermes update.
  2. A escrita do carimbo é pulada quando a publicação falha. Sem launcher, sem write_source_stamp — então install-stamp.json e .hermes-bootstrap-complete continuam dizendo v0.22.4.

E aí vem a terceira camada, que é o que faz o problema grudar: o conselho do aviso — a próxima execução ou outro hermes update tenta de novo — tenta de novo a partir desse mesmo exe. Nunca sai do lugar. Você espera que ele se cure sozinho; ele espera um exe diferente.

Por que só no Windows

No POSIX, um arquivo em execução pode ser desvinculado e o processo continua usando o inode. O Windows não permite apagar uma imagem mapeada.

O gatilho também é estreito: Windows, e só quando há troca de versão do Python. Ao atualizar de v0.22.3 para v0.22.4 o Python ficou em 3.14.7, então o exe existente batia e permanecia. É exatamente isso que torna o caso difícil de identificar — quase toda atualização dá certo.

Correção um: se não apagar, renomeie e tire da frente

#143291 adiciona _retire_exe em hermes_cli/_launchers.py: tenta apagar; quando o Windows recusa porque o arquivo está em uso, renomeia para hermes.exe.<pid>.deleteme. O Windows permite renomear uma imagem mapeada — a distlib faz o mesmo movimento. A cópia posta de lado é recolhida numa publicação posterior, quando o processo dela já terminou.

Com a publicação deixando de falhar, o carimbo volta a ser escrito. _collect_retired também varre o hermes.exe.deleteme que a própria distlib deixa para trás quando o exe da atualização é o que está sendo substituído.

Correção dois: parar de degradar para .cmd

Consertar só o apagamento não bastava. #143339 documenta a outra metade: o processo de atualização ativa apenas o ambiente de dependências, que não tem distlib, e as site-packages do Python da store (onde mora o pip) ficam de fora. Aí mint_launcher não encontra nenhum ScriptMaker e publica um .cmd — e, como a correção anterior já consegue renomear o exe em execução, esse exe foi aposentado de vez. A instalação termina com hermes.cmd e nada mais.

O instalador originalmente cunhava seu primeiro exe com o pip embutido do python-build-standalone, um caminho que a atualização nunca consultava. A correção reconecta isso: quando o processo em execução não consegue importar a distlib, mint_launcher carrega pip._vendor.distlib de ao lado do interpretador que está vinculando (<python>\Lib\site-packages\pip\_vendor\distlib, presente em toda build do PBS), sob um nome de módulo privado, para que o pip da store nunca responda a import pip dentro do processo. Um fallback para .cmd continua existindo para interpretador sem distlib nenhuma — só que agora é raro.

O que checar na sua máquina

Se você está no Windows e atravessou uma troca de versão do Python recentemente, três checagens rápidas:

hermes --version                                    # versão semântica e Python vinculado
  • O bin\hermes.exe ainda está lá, dentro do seu home do Hermes? Só hermes.cmd significa que você caiu nisso.
  • Abra install-stamp.json e .hermes-bootstrap-complete: o commit que eles indicam deve ser a build que você está rodando de fato, não a anterior.
  • Se não baterem, vá primeiro para uma build que contenha as duas correções e rode hermes update mais uma vez — só o novo código de publicação consegue tirar o exe antigo da frente enquanto ele está rodando.

Se a instalação parecer realmente quebrada em vez de meio atualizada (um worktree git sujo, comandos que às vezes existem e às vezes não), o guia de reparo de git danificado tem a lista de verificação mais completa. A semântica de canais e rollback está no guia do canal estável, e as flags ficam na referência de hermes update.

Status do release

As duas correções entraram em main em 22-23 de outubro de 2026; um terceiro PR (#143261) corrige o consumo de disco do E2E no Windows, que tinha lotado o runner — cada jornada de teste agora apaga sua instalação no teardown. As falhas foram capturadas pela execução E2E do release candidate v0.22.5 no caminho de atualização de v0.22.4 para HEAD, então a população afetada são os usuários de Windows que atualizam a partir da v0.22.4. O release mais recente continua sendo v0.22.4 (21 de outubro): essas correções ainda não chegaram ao canal estável.

Uma observação sobre por que isso não é só manutenção de CI: assim que um launcher do Windows degrada para .cmd, atalhos, tarefas agendadas e qualquer script com .exe na entrada do PATH falham em silêncio — e o único sinal é aquela linha ⚠.