Skip to content

fix(web): stop pinning resolved permission cards to the bottom of the chat#974

Merged
tiann merged 1 commit into
tiann:mainfrom
junmo-kim:fix/resolved-permission-card-pinned
Jun 29, 2026
Merged

fix(web): stop pinning resolved permission cards to the bottom of the chat#974
tiann merged 1 commit into
tiann:mainfrom
junmo-kim:fix/resolved-permission-card-pinned

Conversation

@junmo-kim

Copy link
Copy Markdown
Contributor

Problem

After an AskUserQuestion (or other permission prompt) is answered, its card can stay pinned at the bottom of the chat — sitting just above the composer instead of resting in its place in the conversation history. Over a session with several answered prompts these cards pile up at the bottom.

The chat keeps an answered request in agentState.completedRequests. When that request's tool_use message is not in the currently loaded window, reduceChatBlocks synthesizes a stand-in card for it and appends it to the end of the timeline. There is no chronological re-sort, so the synthesized card stays at the bottom. That stand-in is meant for a pending request — so it remains answerable even before its message loads — but it also fired for already-resolved requests, pinning a stale "answered" card above the composer.

Solution

Synthesize a stand-in card only for a pending request. A resolved request (approved / denied / canceled) is history: it renders through its own tool message when that message is in the window, and no longer leaves a bottom-pinned stand-in when it isn't. Pending requests are unchanged — they still get an answerable card when their message hasn't loaded yet.

Tests

Unit tests in reducer.test.ts: a resolved request with no in-window message is no longer synthesized as a card, while a pending request with no in-window message still is. Existing reducer tests pass. Manually verified end-to-end: a session whose answered AskUserQuestion requests were pinned at the bottom no longer shows them there, while a pending question still renders its answerable card.

… chat

agentState keeps an answered permission request in completedRequests. When its
tool_use message is not in the loaded window, the permission-only synthesis
appended a card to the end of the timeline — and there is no chronological
re-sort, so the card stays pinned above the composer as a stale "answered"
card that never moves to its place in history. With several answered asks this
piles up at the bottom of the chat.

Synthesize a card only for a *pending* request (the case that needs an
answerable card when its message hasn't loaded). A resolved request is history
and renders only via its own message when that message is in the window.

@github-actions github-actions 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.

Findings
No issues found in the changed lines.

Summary
Review mode: initial
No correctness, security, data-loss, performance, or maintainability regressions found in this diff. Residual risk: I could not run the web reducer test locally because bun is not installed in this runner.

Testing
Not run (automation): bun --cwd web test src/chat/reducer.test.ts failed with bun: command not found.

HAPI Bot

@tiann tiann merged commit f51e06e into tiann:main Jun 29, 2026
2 checks passed
@junmo-kim junmo-kim deleted the fix/resolved-permission-card-pinned branch June 29, 2026 05:19
heavygee added a commit to heavygee/hapi that referenced this pull request Jun 29, 2026
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