feat: hidden Claude — hookless native prompts (#29) and tool-call provenance (#30) - #51
Conversation
…29) The hidden Claude PTY now feeds a private vt100 screen model. Without a SessionStart hook in 5 s the Bee names the likely native screen (trust, login, initial setup) without copying its text, and Ctrl+O explicitly opens the original Claude to finish setup. Turns without hooks for 20 s get a single hint. Ctrl+Q no longer types /exit into a possible native dialog: before SessionStart it ends the process, mid-turn it interrupts and exits after Stop. Refs #29 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUyLMVv9GbqWRByEZ7LgEb
Tool results in the Bee now say whether the user approved them once in the Bee panel or Claude ran them without a PermissionRequest under its own rules. The review panel closes at 85 s, before the hook's 90 s denial, so a late `y` can no longer be reported as approved; undelivered replies and concurrent requests are reported as denied. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUyLMVv9GbqWRByEZ7LgEb
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes Revisei o único commit do PR, incluindo o fluxo PTY, os estados de bloqueio/interrupção, o teste sintético e os contratos/documentos afetados.
- Tela nativa sob demanda: a saída do PTY alimenta um parser privado e só é exibida após
Ctrl+O; entrada e colagem são encaminhadas ao Claude enquanto essa tela está aberta. - Prompts sem hook: a Bee detecta ausência de
SessionStartem cinco segundos e falta de eventos durante um turno em 20 segundos, sem copiar o conteúdo da tela para a conversa. - Saída segura:
Ctrl+Qencerra diretamente antes deSessionStart; nos demais estados evita enviar/exita um diálogo nativo e mantém o fallback de encerramento. - Cobertura e limitações: o teste PTY sintético cobre confiança sem hook, abertura do Claude, saída segura e restauração do terminal; o ensaio real de confiança/login continua corretamente registrado como pendente.
GPT Luna | 𝕏
On macOS the PTY buffer is small: after Ctrl+Q the script stopped reading and the Bee blocked on its final redraw, timing out the untrusted-project scenario. Keep reading until the process exits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUyLMVv9GbqWRByEZ7LgEb
Non-permission hooks returned before the Bee queued their event, so a tool result or Stop sent just before Claude exited could be lost (seen on macOS CI as a missing "aprovada" line). The hook now waits up to 5 s for a queue acknowledgement, and the Bee drains and redraws before leaving. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUyLMVv9GbqWRByEZ7LgEb
Each hook uses its own connection, so a PermissionRequest could be queued before its PreToolUse and the approved call was then reported as running without a request (seen on Ubuntu CI). A request without a matching call now records one that the later PreToolUse adopts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUyLMVv9GbqWRByEZ7LgEb
There was a problem hiding this comment.
Important
O commit novo pode atribuir uma aprovação da Bee à chamada de ferramenta errada quando chamadas paralelas têm o mesmo nome e entrada. Isso torna a proveniência exibida incorreta justamente no fluxo que o commit pretende esclarecer.
Reviewed changes Revisei o delta do commit 79a86c4 desde a revisão anterior, focando no vínculo entre hooks de ferramenta, decisão de permissão e resultado.
- Proveniência de ações: novos registros associam
PreToolUse,PermissionRequeste o resultado para distinguir aprovação na Bee de liberação pelas regras do Claude. - Expiração de revisão: o painel encerra pedidos sem resposta em 85 segundos, antes do timeout de 90 segundos do hook; pedidos concorrentes são negados.
- Cobertura: testes unitários e PTY sintético cobrem chamadas com ID, aprovação, concorrência e expiração; não cobrem chamadas idênticas paralelas sem ID no evento de permissão.
Technical details
# Associação ambígua da decisão de permissão
## Affected sites
- `src/tui/claude_native.rs:857` — sem `tool_use_id`, `find_tool` escolhe o último registro com nome e entrada iguais.
- `src/tui/claude_native.rs:948-949` — a decisão fica vinculada à sequência escolhida.
- `src/tui/claude_native.rs:924-940` — o resultado posterior pode atribuir a aprovação ao registro errado.
A referência oficial diz que o payload de `PermissionRequest` não contém `tool_use_id`: https://code.claude.com/docs/en/hooks#permissionrequest. Assim, se dois `PreToolUse` idênticos já estiverem registrados, uma permissão referente à chamada anterior pode ser associada à mais recente; os resultados com IDs depois exibem uma origem trocada.
## Required outcome
- Não afirmar uma origem específica quando a correspondência por nome e entrada não é única; representar a proveniência como ambígua/desconhecida.
- Cobrir o caso com duas chamadas `PreToolUse` de mesma ferramenta/entrada e IDs distintos, um `PermissionRequest` sem ID e resultados posteriores para ambos.GPT Luna | 𝕏
The official PermissionRequest payload has no tool_use_id. When a request matched several identical unanswered calls, the approval was attributed to the latest one, possibly the wrong call. Such calls now show an uncertain origin instead of a specific Bee approval. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUyLMVv9GbqWRByEZ7LgEb
There was a problem hiding this comment.
Important
Os commits novos corrigem a correlação quando um único PermissionRequest chega antes de PreToolUse e evitam perder eventos no encerramento. A proveniência ainda pode ser atribuída à chamada errada para chamadas paralelas idênticas, pois a permissão continua sem identificador que desambigue qual PreToolUse corresponde a ela.
Reviewed changes Revisei os três commits novos desde a revisão anterior: reconciliação de hooks fora de ordem, entrega de eventos antes do encerramento e drenagem do PTY nos testes.
- Reconciliação de hooks: um pedido sem
tool_use_idcria um registro provisório, que o novo ramo dePreToolUseassocia por nome e entrada. - Entrega antes da saída: hooks sem permissão aguardam confirmação de enfileiramento, e a Bee drena eventos pendentes antes do último redesenho.
- Teste PTY: a espera pela saída agora continua lendo a saída do terminal, evitando bloqueio por buffer cheio.
Technical details
# Correlação ainda ambígua para chamadas idênticas
## Affected sites
- `src/tui/claude_native.rs:938-941` — associa o primeiro registro provisório com nome/entrada iguais ao novo `PreToolUse`.
- `src/tui/claude_native.rs:972-975` — um `PermissionRequest` sem ID cria esse registro provisório.
- `src/tui/claude_native.rs:948-964` — resultados posteriores usam o ID associado para exibir a origem.
## Reproduction condition
1. Duas chamadas paralelas têm a mesma ferramenta e entrada, mas IDs distintos.
2. O `PermissionRequest` da chamada A chega primeiro, sem `tool_use_id`, e cria o registro provisório.
3. O `PreToolUse` da chamada B é processado antes do `PreToolUse` de A; o novo código atribui o ID de B ao registro de A.
4. Depois da decisão da Bee, o resultado B aparece aprovado e o resultado A aparece sem pedido, invertendo a proveniência.
A referência oficial confirma que `PermissionRequest` não fornece `tool_use_id`: https://code.claude.com/docs/en/hooks#permissionrequest. Não há como escolher um registro único por nome/entrada quando há candidatos idênticos.
## Required outcome
- Não vincular aprovação a uma chamada específica se a correspondência por nome/entrada for ambígua; exibir origem desconhecida/ambígua em vez de alegar qual chamada foi aprovada.
- Adicionar teste com dois `PreToolUse` idênticos, IDs distintos e `PermissionRequest` sem ID em ordem concorrente.GPT Luna | 𝕏
A PermissionRequest carries no tool_use_id. If it arrived before any matching PreToolUse, the first identical call adopted the approval and a later identical call showed "no request", possibly inverting provenance. Such requests and any identical call seen while they are open now show an uncertain origin; tool records are dropped at the end of each turn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUyLMVv9GbqWRByEZ7LgEb
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes Revisei o delta do commit e7baf84 desde a revisão anterior, que trata da ambiguidade na origem das aprovações.
- Chamadas idênticas: quando um
PermissionRequestsemtool_use_idcorresponde a mais de uma chamada ainda sem decisão, todas são marcadas como ambíguas e os resultados não alegam qual foi aprovada. - Pedido antes de
PreToolUse: a associação continua funcionando quando há apenas um candidato correspondente. - Teste de regressão: novo teste cobre chamadas paralelas com entrada idêntica, IDs distintos e resultado com origem incerta.
GPT Luna | 𝕏

Resumo
Refs #29 e #30, parte de código. Os ensaios humanos continuam pendentes no item 52 do roteiro.
#29 — telas nativas sem hook (b6d68dd)
vt100). Esse modelo responde às consultas de cursor/estado e só é desenhado a pedido do usuário.SessionStartem 5 s, a Bee informa que o Claude aguarda uma ação nativa e nomeia o tipo: confiança, login, configuração inicial ou tela sem evento. O texto da tela não é copiado.Ctrl+Oabre explicitamente o Claude original para concluir a preparação. Pedidos de permissão sempre voltam ao painel Bee.Ctrl+Qnão digita mais/exit+ Enter num diálogo nativo:SessionStart, encerra o processo;Ctrl+Ce só digita/exitapós oStop;/exit.#30 — origem das ações e expiração (79a86c4, d3ddf4b, e7baf84)
Ação: Bash · <comando>). O resultado diz uma de três coisas:tool_use_idcorresponde a mais de uma chamada idêntica. O payload oficial doPermissionRequestnão traz esse ID.PreToolUse.ytardio ou uma resposta que não chega ao hook é informado como não aprovado. Um pedido concorrente é negado e registrado.Correções vindas do CI (01cc2ad, dcf7813)
Validação
cargo fmt --all -- --check,cargo clippy --locked --all-targets -- -D warnings,cargo test --lockedecargo build --lockedpassaram.check_bundle.pypassaram localmente e no CI (macOS e Linux) eme7baf84.Ctrl+O→1→ Bee →/exit, eCtrl+Qsem digitar no diálogo;PreToolUse, as chamadas idênticas paralelas, a expiração, o pedido concorrente e a aprovação tardia.Ctrl+Oexibiu a tela eCtrl+Qsaiu em 0,27 s com o terminal restaurado.Limitações
Documentos atualizados:
docs/specs/workspace.md,docs/MANUAL_TESTS.md,docs/EXECUTION.mdeROADMAP.md.🤖 Generated with Claude Code
https://claude.ai/code/session_01MUyLMVv9GbqWRByEZ7LgEb