Skip to content

Redigir tokens na saída do completion TG-273 - #17

Merged
cedric-lamalle merged 7 commits into
mainfrom
TG-273
Oct 4, 2026
Merged

cedric-lamalle merged 7 commits into
mainfrom
TG-273

Conversation

@cedric-lamalle

@cedric-lamalle cedric-lamalle commented Oct 4, 2026 •

Copy link
Copy Markdown
Member

US #273 (épico #242, fase 4).

Problema

O Cobra relata erro de completion com CompErrorln, que escreve direto em os.Stderr e faz append no arquivo de BASH_COMP_DEBUG_FILE. Isso fica fora dos writers do App e, portanto, da redação. As mensagens (unable to find a command for arguments: [...], Error while parsing flags from args [...]: <erro do pflag> e Subcommand 'x' does not support flag 'y') ecoam as palavras digitadas. No main, taiga __complete nope?token=X '' grava token=X cru, e um bidi (U+202E) sai cru também.

O que muda

  • O __complete recebe as palavras já redigidas (taiga.RedactTokens) e com controles e bidi escapados (output.Quote, sem as aspas externas, para que --flag… continue sendo flag). O código está em internal/cli/completion.go e é ligado no PersistentPreRunE.
  • Por que contornar a API do Cobra: CompErrorln usa globais (os.Stderr, os.Getenv) e nenhum writer do comando chega a ele. As mensagens só juntam texto fixo, nomes de comando e flag e as palavras digitadas. Por isso, redigir a entrada cobre stderr e o arquivo de debug sem mexer em globais. Os candidatos e a diretiva não mudam para palavras sem token nem caractere inseguro (28 entradas comparadas byte a byte com o main).
  • O completion nunca chama o Taiga, então nenhum dado do servidor chega a ele. O guarda estrutural (TestOutputGoesThroughPresent) passa a barrar ValidArgsFunction, RegisterFlagCompletionFunc, cobra.CompDebug*/CompError* e o import com ponto do cobra.
  • Debug do shell silenciado por redefinição (decisão do Cedric, rodadas 1 e 4). Os scripts do Cobra gravam no BASH_COMP_DEBUG_FILE a linha digitada, token incluído. O taiga completion bash|zsh|fish|powershell mantém ajuda e flags do Cobra e imprime o script do Cobra com um único bloco acrescentado: __taiga_debug redefinido para não fazer nada (__taiga_debug() { :; } em bash/zsh, function __taiga_debug; end em fish, function __taiga_debug { } em PowerShell), logo depois da definição original e antes de qualquer completion. Isso vale também para o zsh carregado por fpath/autoload, que roda o arquivo no primeiro uso e chama _taiga no fim. Nada do script do Cobra é removido. Sem a declaração do escritor, a geração é recusada. O debug do processo Go, já redigido, continua.
  • README e guia descrevem o comportamento e pedem para gerar de novo um script salvo por versão anterior.

Testes

  • TestCompletionHidesTokens: sentinela em comando desconhecido, nome de flag, valor de flag tipada, chave codificada, bidi e quebra de linha. Cobre __complete e __completeNoDesc, e confere stdout, App.Err, os.Stderr do processo e o arquivo de debug. Falha no main.
  • TestCompletionCandidatesUnchanged e TestCompletionNeverCallsTaiga (servidor fake com sentinela; zero requisições).
  • TestCompletionScriptsOnlyAddTheQuietWriter (o script é o do Cobra mais o bloco, nos 4 shells com e sem descrições), TestCompletionScriptRefusedWithoutTheWriter, TestCompletionScriptsQuietWriter (status 0, sem saída nem escrita, em cada shell), TestCompletionScriptsParse e TestCompletionScriptsKeepTokensOutOfTheDebugFile. Este último carrega o script em bash, zsh, zsh por fpath/autoload, fish e pwsh, completa com token, controle e bidi, com e sem descrições, e exige que toda linha do arquivo de debug venha do binário. Também compara os candidatos com o script do Cobra.
  • CI: o job unit instala zsh e fish e roda go test -v -run ^TestCompletionScripts ./internal/cli com TAIGA_TEST_SHELLS=bash,zsh,fish,pwsh, então um shell ausente falha em vez de ser pulado.
  • go test -race ./..., go vet e golangci-lint, com e sem integration.

O Cobra relata erro de completion com CompErrorln, que escreve direto em
os.Stderr e no arquivo de BASH_COMP_DEBUG_FILE, fora dos writers do App.
A mensagem só junta texto fixo, nomes de comando e flag e as palavras
digitadas; o __complete passa a receber essas palavras já redigidas e com
controles e bidi escapados. Um guarda estrutural impede funções de
completion e chamadas cobra.Comp* no CLI.
completionArg só tira as aspas que o Quote pôs: um valor de token redigido
leva o caractere de controle junto, e a palavra não pode virar flag nem
perder bytes. O guarda pega import com ponto do cobra e deixa de barrar
CompletionOptions. Docs mais exatas sobre o que o completion completa.
Os scripts do Cobra gravam no BASH_COMP_DEBUG_FILE a linha digitada,
token incluído. O comando completion mantém ajuda e flags do Cobra, mas
gera os quatro scripts sem o escritor de debug e sem as chamadas a ele,
trocadas por no-op. O debug do processo Go, já redigido, continua.
O filtro falha fechado quando a chamada ao escritor divide a linha com
outra instrução. O teste estático exige o no-op exato no lugar de cada
chamada, os scripts passam pelo parser de cada shell instalado e o
harness roda também sem descrições. Docs pedem para gerar de novo um
script salvo por versão anterior.
Um fechamento indentado do escritor fazia o filtro seguir até o fim da
função seguinte e apagá-la sem erro. Agora qualquer linha na margem
dentro do escritor, fora o fechamento, recusa a geração. Os candidatos
são comparados com e sem descrições, e a CI instala zsh e fish e exige
os quatro shells no teste dos scripts.
O corte do debug segue o texto e uma mudança de formato do Cobra podia
fazê-lo levar a função seguinte. Agora a saída é conferida sem depender
do formato: toda função declarada, fora o escritor, continua declarada,
e só mudam o trecho do escritor e as chamadas trocadas por no-op.
Qualquer outra diferença recusa a geração.
O filtro textual voltava a consumir código quando o formato do Cobra
mudava. O comando completion agora só acrescenta ao script do Cobra uma
redefinição do escritor de debug que não faz nada, logo depois da
definição dele e antes de qualquer completion (o zsh por autoload roda o
arquivo no primeiro uso). Sem a declaração do escritor, a geração é
recusada. Saem o filtro, a invariante, a guarda de margem e os testes
deles; entram o teste do zsh por fpath e o do status do escritor.
@cedric-lamalle
cedric-lamalle merged commit 369bf02 into main Oct 4, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant