Skip to content

feat: hidden Claude — hookless native prompts (#29) and tool-call provenance (#30) - #51

Merged
lippdev merged 7 commits into
mainfrom
claude/quirky-lovelace-pybgg3
Sep 28, 2026
Merged

lippdev merged 7 commits into
mainfrom
claude/quirky-lovelace-pybgg3

Conversation

@lippdev

@lippdev lippdev commented Sep 28, 2026 •

Copy link
Copy Markdown
Owner

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)

  • A saída do PTY alimenta um modelo de tela privado (vt100). Esse modelo responde às consultas de cursor/estado e só é desenhado a pedido do usuário.
  • Sem SessionStart em 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+O abre explicitamente o Claude original para concluir a preparação. Pedidos de permissão sempre voltam ao painel Bee.
  • Ctrl+Q não digita mais /exit + Enter num diálogo nativo:
    • antes do SessionStart, encerra o processo;
    • com um turno ativo, envia Ctrl+C e só digita /exit após o Stop;
    • no prompt ocioso, mantém /exit.
  • Um turno sem hooks por 20 s gera um aviso único.

#30 — origem das ações e expiração (79a86c4, d3ddf4b, e7baf84)

  • Cada ação aparece com um resumo (Ação: Bash · <comando>). O resultado diz uma de três coisas:
    • aprovada por você na Bee, uma vez;
    • sem pedido de permissão, quando o Claude liberou pelas próprias regras ou modo;
    • origem incerta, quando um pedido sem tool_use_id corresponde a mais de uma chamada idêntica. O payload oficial do PermissionRequest não traz esse ID.
  • O vínculo funciona mesmo se o pedido chegar antes do PreToolUse.
  • O painel fecha em 85 s, antes de o hook negar sozinho em 90 s, e registra a negação. Um y tardio 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)

  • O teste PTY agora continua lendo a saída enquanto espera a Bee sair. No macOS, o buffer pequeno do PTY bloqueava o redesenho final.
  • Hooks sem permissão agora esperam até 5 s pela confirmação de que o evento entrou na fila, e a Bee drena os eventos antes de sair. Antes, eventos emitidos logo antes de o Claude sair podiam se perder.

Validação

  • cargo fmt --all -- --check, cargo clippy --locked --all-targets -- -D warnings, cargo test --locked e cargo build --locked passaram.
  • Os quatro scripts PTY e o check_bundle.py passaram localmente e no CI (macOS e Linux) em e7baf84.
  • Testes PTY com CLI falsa cobrem:
    • confiança sem hook: Ctrl+O → 1 → Bee → /exit, e Ctrl+Q sem digitar no diálogo;
    • leitura liberada pelo Claude e Bash com pedido de permissão.
  • Testes unitários cobrem a heurística, a máquina de estados, a origem, o pedido antes do PreToolUse, as chamadas idênticas paralelas, a expiração, o pedido concorrente e a aprovação tardia.
  • Com o Claude Code 2.1.283 real, sem login: a configuração inicial foi sinalizada, Ctrl+O exibiu a tela e Ctrl+Q saiu em 0,27 s com o terminal restaurado.

Limitações

  • Este ambiente não tem um Claude autenticado pelo usuário. A confiança real, o login e as ferramentas/permissões reais ficam para o item 52.
  • A detecção de telas nativas é heurística (tempo e palavras-chave em inglês).
  • Houve autorrevisão. O Pullfrog, revisor automatizado, apontou a ambiguidade de chamadas paralelas, já corrigida em e7baf84.

Documentos atualizados: docs/specs/workspace.md, docs/MANUAL_TESTS.md, docs/EXECUTION.md e ROADMAP.md.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MUyLMVv9GbqWRByEZ7LgEb

…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
@lippdev lippdev changed the title feat: surface hookless native Claude prompts in hidden Bee workspace (#29) feat: hidden Claude — hookless native prompts (#29) and tool-call provenance (#30) Sep 28, 2026

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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 SessionStart em 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+Q encerra diretamente antes de SessionStart; nos demais estados evita enviar /exit a 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.

Pullfrog  | View workflow run | Using 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

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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, PermissionRequest e 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.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using GPT Luna | 𝕏

Comment thread src/tui/claude_native.rs
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

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_id cria um registro provisório, que o novo ramo de PreToolUse associa 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.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using GPT Luna | 𝕏

Comment thread src/tui/claude_native.rs Outdated
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

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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 PermissionRequest sem tool_use_id corresponde 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.

Pullfrog  | View workflow run | Using GPT Luna | 𝕏

@lippdev
lippdev merged commit 6b7fe2b into main Sep 28, 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.

2 participants