Skip to content

fix(native-chat): open a New Chat's composer at once, before its host answers - #29358

Merged
brennanb2025 merged 33 commits into
mainfrom
brennankb5/native-chat-draft-first-send
Oct 20, 2026
Merged

brennanb2025 merged 33 commits into
mainfrom
brennankb5/native-chat-draft-first-send

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 21 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​639 $\color{#cf222e}{\Huge{\mathbf{−}}}$​143 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​496
Prod 43 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​617 $\color{#cf222e}{\Huge{\mathbf{−}}}$​181 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​436

ELI5

New Chat used to wait for the computer or paired server running the chat before its text box existed. Typing during that wait could reach the previous chat or another control. The new chat now opens and focuses its ordinary composer first, giving input a destination while its host answers.

What Changed

Eligible foreground New Chat actions open the real chat tab before host admission finishes. The existing conversation identity and saved draft remain in use. The empty host conversation is created in the background; modern hosts start the agent on the first Send. Automatic, resume, background and immediately submitted prompt launches retain their existing admission path.

Typing stays available during startup. Send waits for the host conversation, model and effort changes wait for the host defaults, and paired uploads wait for publication. Local attachment staging remains available. Permission refusal uses one notice with the requested agent's permission default. Host notices now wrap so the full recovery instruction stays visible in a narrow pane. An unverified permission result offers the existing Check again action.

A dismissed menu could move focus back to itself during its closing animation, leaving only the first typed character in the new composer. Shared dropdown and context menu items now skip that pointer-focus action while their own menu is closed.

Explicit Chat requests stay chats when refused. For a generic agent launch that cannot use structured chat, terminal fallback waits for an actual terminal before replacing an empty composer. The replacement keeps its position, pin, and any explicitly chosen title and colour. If text, images or pending attachments have arrived, the chat and its content stay and the terminal opens in the background. Completion does not navigate back after the user switches away or closes the source.

Split Right and Split Down relocate an existing chat in this head. Fresh-chat Split is a separate consumer tracked in #28950. A separate immediate-typing order race also occurs on main and is tracked in STA-11369; this PR does not correct that race.

Why

The structural problem was making the local editing destination depend on an asynchronous host answer. Opening the existing composer first removes that dependency without adding a second draft lifecycle. Conversation creation, process startup, saved drafts and terminal launch ownership are reused rather than adding saved state or remote operations.

The common pattern gives local editing its own destination before remote work completes. Intended differences are ordinary empty host-record creation at open, the existing provider-at-open behavior on older paired servers, and retaining a composer containing user content beside a fallback terminal. No new saved fields, wire operations, capabilities or minimum server version are introduced. Issued-close retirement remains tracked in #27583 and #27561.

Linked Issue

Continues the focus work tracked in #28987 and integrates the menu routing from #29074. The separate typing-order race is tracked in STA-11369.

Visual Proof

Current branch captures are fb898ea on the admitted M4Air. Main controls are pinned f884b9f.

The complete old-host warning now wraps. Main cannot create the refused chat or show its inline notice with the same diagnostic; this is the explicitly permitted “main cannot show it” control, not a clipping comparison. Both normal old-host menus lack Chat, so this case uses the real production Chat entrypoint against a genuine 1.4.189 server.

Main: refused Chat produces no composer or inline warning
Branch: complete warning and update instruction wrap over two lines

The unchanged New Tab menu fixture kept its complete prompt and received a real Codex reply:

Branch: literal 38-character prompt after New Tab menu selection
Branch: actual Send receives OK_Q1_MENU

One uninterrupted direct paired-Claude run retained all 41 characters and received a real reply. These images show ready and reply, respectively; the earlier disabled Send/Attach pending state is established by the passive trace, not these images.

Branch: full Q5 prompt intact when ready
Branch: same paired Claude session replies OK_Q5_PENDING

Matched existing-chat Split Right/Down: race reproduced on both heads

Same machine, settings and per-trial prerequisites, with no draft repair. These are moves of existing chats, not fresh-chat Split creation. Representative reordered drafts below are main then branch.

Right:

Main Right trial 2: early letters moved to end
Branch Right trial 1: early letter moved to end

Down:

Main Down trial 1: early letters moved to end
Branch Down trial 1: early letter moved to end

Right trial 1 on each head uses the original Attach-ready prerequisite. Right trials 2–10 add waiting for the real launch promise and a normal tab left-click on both heads; both Down runs use that same amended script. One branch menu detached before direction selection and before any burst; that prerequisite failure is retained outside the 40 measured trials. No wait or focus action is inserted between final direction selection and typing.

Current menu dismissal and navigation evidence

Both actual New Tab and tab right-click surfaces use DropdownMenu. Hover changed the highlight; ArrowDown then rendered Grok and Close respectively:

New Tab: ArrowDown reaches Grok
Tab right-click: ArrowDown reaches Close

After outside mouse clicks through an inert Projects label locator, both menus are absent:

New Tab: outside mouse click removes menu
Tab right-click: outside mouse click removes menu

Escape also removes each menu:

New Tab: Escape removes menu
Tab right-click: Escape removes menu

Historical 2a18d27, accepted only for the unchanged unsupported-host fallback and placement paths:

Historical: empty pinned titled coloured replacement
Historical: invested chat retained beside background terminal

Testing

Exact-head full PR workflow and its PR checks passed aggregate succeeded. Workflow identity is .github/workflows/pr.yml; all five unit shards, selected layout/relay checks and both packaging jobs passed.

Current bounded Electron QA ran on the M4Air admitted by qa-gate, ticket 830, with real Codex and Claude through their load balancers under dedicated test homes:

  • Q4: one complete 147-character older-host refusal warning, visibly wrapped over two lines; paragraph width/scroll width both 566 px, height/scroll height both 42 px. Main produced no composer or notice through the same actual refusal path.
  • Q5: one uninterrupted direct paired-Claude run without relay or held transport. Three passive samples captured nonempty pending text with Send and Attach disabled before the host receipt; the full 41-character prompt remained intact when ready, and Send received OK_Q5_PENDING in the same session.
  • New Tab and tab right-click menus: outside mouse click and Escape remove the menus after their closing animation; hover and arrow navigation work.
  • Exact original New Tab fixture: unchanged bytes, once on this head, all 38 literal characters retained, actual Send received OK_Q1_MENU.
  • STA-11369: 40 matched literal MENU38 bursts after moving an existing chat Right/Down, ten per direction per head. All keydown streams were ordered and no characters were lost. Rendered drafts reordered at the rates below.
Head Right reordered Down reordered Lost characters
This branch, fb898ea 9/10 6/10 0
Pinned main, f884b9f 4/10 4/10 0

The supplied finishing criterion passes because main reproduces at least once in each direction. These observations do not establish equal failure rates. The race is tracked in STA-11369 and the caret-restoration code is unchanged by this PR. The prior two-byte warm-relay accounting discrepancy was traced to the test relay dropping a held chunk when a connection closes; that is not a current product failure.

Unsupported-host fallback and placement (Q3/Q6) retain explicitly accepted historical 2a18d27 evidence on unchanged paths, rather than being relabelled as current-head runs. All 55 recorded test processes exited, configured ports were clear, Playwright was closed, the old disk image was detached, real config hashes were unchanged, and the QA worktree was restored to the exact branch head with no tracked changes.

Strict 0–30 ms timing, cold start/cancel, reload/Retry, tours and image contents were outside this finishing scope. The short pending state is evidenced by a passive event/DOM trace; its later screenshot shows the ready state. Both tested tab menus use DropdownMenu; ContextMenuItem has source review only. Physical touch/pen and checkbox/radio/subtrigger variants were not certified.

Review

Full path: lifecycle, asynchronous completion, ordering and mixed client/server behavior. Six design rounds and their rulings remain binding. The final one-commit review and proportional readiness follow-up found no new source defect. Production changes total 798 lines against pinned main, within the 800-line cap. No code changed during this finishing pass.

Agent skill upstream boundary

  • Not applicable: no upstream skill-installer source is copied.

Notes

Folder workspaces and execution-host ownership remain supported by the source design. Direct SSH and WSL retain their existing routes; this finish does not certify their rendered behavior. Saved schemas and mobile protocols are unchanged. No new minimum paired-server version is introduced.

…er focus

The redesign opens the new chat's editor at the action and lets the ordinary at-rest create run in the background, so the local draft record, saved first submission, reserved first-Send sender and pre-session upload capability are no longer needed.
… answers

The new chat's tab and composer waited for the host to admit the chat, so keys typed right after New Chat went to whatever had focus. A New Chat the user asked for now opens its chat tab immediately on the host it was routed to, with focus in the composer. Its ordinary launch asks the host in the background, the same probe it already ran before create, and the chat shows that launch's starting, failed and Retry states.

- A launch that carries a prompt still asks first, so a refusal hands the prompt to a terminal as before.
- A refused chat nobody typed in closes and its terminal opens in its place; a chat with typing keeps it.
- A paired host that would run the chat with more access than asked for gets no create; the chat's permission notice is the only one shown.
- A chat closed while its host was being asked issues no create.
- While the chat starts on a paired server, uploads wait and the model picker stays disabled until the server names what it seeds.
@brennanb2025 brennanb2025 changed the title Draft native chats locally until their first Send fix(native-chat): open a New Chat's composer at once, before its host answers Oct 16, 2026
…t-draft-first-send

# Conflicts:
#	src/renderer/src/components/native-chat/use-native-chat-external-attachments.ts
#	src/renderer/src/lib/structured-agent-launch-settlement.ts
#	src/renderer/src/lib/structured-agent-session-launch.ts
#	src/renderer/src/lib/structured-agent-session-provisional-tab.ts
…s chat rows

- The + menu hands focus to the new chat's composer when it closes, instead of a frame later.
- A chat picked by name that its host refuses stays a chat and says why, including the WSL or SSH reason; it never becomes a terminal.
- A chat the user typed in before its host refused keeps its text, and the agent's terminal opens behind it rather than taking the screen; a paired server's refusal says a terminal opened.
- The paired permission check runs once, right before create, for every launch; the chat's own permission notice is the only message.
- A chat closed while its host was being asked shares the existing pre-create gate, so nothing is created.
- Session attachment notice copy lives with its only caller; tests that mirrored the implementation are trimmed.
@brennanb2025
brennanb2025 marked this pull request as ready for review October 19, 2026 08:09
@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 29ae5e43-b77d-4aa1-8e7c-ee0591d764b6
📥 Commits

Reviewing files that changed from the base of the PR and between 3b4777d and 2a18d27.

📒 Files selected for processing: 2
  • src/renderer/src/components/native-chat/NativeChatComposer.test.tsx
  • src/renderer/src/components/native-chat/NativeChatComposer.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.

📝 Walkthrough

Structured chat launches now track pending host seed options, check paired-host permissions, and carry activation and terminal-completion results. The launch flow supports provisional chat tabs and terminal fallbacks, including tab-state transfer after eligible refusals. Composer handling now reports pending-session attachment notices and supports immediate focus handoff. Tab color and pin actions can suppress feature-interaction recording.

Priority: ⬇️ Low

Merge Risk: 🔵 Low · up to 2a18d

Some delayed launches may open without automatically focusing the composer; this is localized and recoverable by clicking the composer.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 53.45% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 58 functions across 52 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the primary change: opening a New Chat composer before the host responds.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The pull request description is detailed and covers the required ELI5, changes, rationale, issue references, visual proof, testing, review, scope boundary, and compatibility notes. It does not include…
Full details: Description check

Explanation

The pull request description is detailed and covers the required ELI5, changes, rationale, issue references, visual proof, testing, review, scope boundary, and compatibility notes. It does not include the template’s explicit Checklist section or a Fixes #... line, but it provides issue references and substantial validation evidence, so the description is mostly complete.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 13fd60d8-a5fd-45b3-b8fa-3785da1b52fc
📥 Commits

Reviewing files that changed from the base of the PR and between 2db7d5a and 1838f9a.

📒 Files selected for processing: 57
  • src/renderer/src/components/native-chat/NativeChatStructuredSession.tsx
  • src/renderer/src/components/native-chat/native-chat-attachment-upload.ts
  • src/renderer/src/components/native-chat/native-chat-composer-reveal-focus.test.tsx
  • src/renderer/src/components/native-chat/native-chat-composer-types.ts
  • src/renderer/src/components/native-chat/native-chat-pending-attachment-cache.ts
  • src/renderer/src/components/native-chat/native-chat-structured-session-notices.ts
  • src/renderer/src/components/native-chat/structured-agent-session-status-bridge-unconfirmed-start.test.tsx
  • src/renderer/src/components/native-chat/use-native-chat-composer-paste.ts
  • src/renderer/src/components/native-chat/use-native-chat-composer-reveal-focus.ts
  • src/renderer/src/components/native-chat/use-native-chat-external-attachments.test.tsx
  • src/renderer/src/components/native-chat/use-native-chat-external-attachments.ts
  • src/renderer/src/components/native-chat/use-native-chat-host-permission-gate.ts
  • src/renderer/src/components/native-chat/use-native-chat-provisional-launch.test.tsx
  • src/renderer/src/components/native-chat/use-native-chat-provisional-launch.ts
  • src/renderer/src/components/native-chat/use-native-chat-structured-composer-transport.test.tsx
  • src/renderer/src/components/native-chat/use-native-chat-structured-composer-transport.ts
  • src/renderer/src/components/native-chat/use-structured-agent-session-options.ts
  • src/renderer/src/components/native-chat/use-structured-native-chat-submit-reveal.test.ts
  • src/renderer/src/components/tab-bar/QuickLaunchButton.tsx
  • src/renderer/src/components/tab-bar/use-tab-bar-create-menu-controller.ts
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/lib/launch-agent-in-new-tab-structured-route.ts
  • src/renderer/src/lib/launch-agent-in-new-tab-web-runtime.test.ts
  • src/renderer/src/lib/launch-agent-in-new-tab.test.ts
  • src/renderer/src/lib/launch-agent-in-new-tab.ts
  • src/renderer/src/lib/launch-agent-structured-chat-guard.test.ts
  • src/renderer/src/lib/launch-agent-web-host-tab.ts
  • src/renderer/src/lib/launch-structured-agent-session.test.ts
  • src/renderer/src/lib/launch-structured-agent-session.ts
  • src/renderer/src/lib/structured-agent-launch-settlement.ts
  • src/renderer/src/lib/structured-agent-session-action-launch.ts
  • src/renderer/src/lib/structured-agent-session-launch-admission.test.ts
  • src/renderer/src/lib/structured-agent-session-launch-admission.ts
  • src/renderer/src/lib/structured-agent-session-launch-callers.ts
  • src/renderer/src/lib/structured-agent-session-launch-create-call.ts
  • src/renderer/src/lib/structured-agent-session-launch-create-message.test.ts
  • src/renderer/src/lib/structured-agent-session-launch-errors.ts
  • src/renderer/src/lib/structured-agent-session-launch-failure.ts
  • src/renderer/src/lib/structured-agent-session-launch-options.ts
  • src/renderer/src/lib/structured-agent-session-launch-permission-notice.ts
  • src/renderer/src/lib/structured-agent-session-launch-probe-outage.test.ts
  • src/renderer/src/lib/structured-agent-session-launch-recovery.ts
  • src/renderer/src/lib/structured-agent-session-launch-reload.test.ts
  • src/renderer/src/lib/structured-agent-session-launch-reload.ts
  • src/renderer/src/lib/structured-agent-session-launch.test.ts
  • src/renderer/src/lib/structured-agent-session-launch.ts
  • src/renderer/src/lib/structured-agent-session-provisional-tab.test.ts
  • src/renderer/src/lib/structured-agent-session-provisional-tab.ts
  • src/renderer/src/runtime/structured-chat-host-permission.test.ts
  • src/renderer/src/runtime/structured-chat-host-permission.ts
  • src/renderer/src/runtime/web-runtime-session-terminal-workspace-routing.test.ts
  • src/renderer/src/store/slices/tabs-label-and-pin-state.test.ts
  • src/renderer/src/store/slices/tabs/tabs-label-actions.ts
  • src/renderer/src/store/slices/tabs/tabs-slice-contract.ts
  • src/renderer/src/store/terminals/terminal-actions.ts
  • src/renderer/src/store/terminals/terminal-tab-appearance.ts
  • src/renderer/src/store/terminals/terminal-tab-layout-owner-actions.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review.

@brennanb2025

brennanb2025 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor Author

Opening New Chat used to wait for its host before its composer existed, so typing during that wait could reach the previous surface. This PR opens and focuses the ordinary composer first. It also prevents a dismissed menu from taking focus back during its closing animation. The final correction makes older-host warnings wrap, keeping their full update instruction visible in a narrow pane.

Review and bounded finishing QA complete on fb898ea. One reviewer checked only the final warning-wrap commit and found no new source defect; proportional readiness, performance, compatibility and platform follow-up were clear. Six design rounds and their rulings remain binding. No source changes, new design round or main sync occurred during this finish. Production changes total 798 lines against pinned main, within the 800-line cap.

Fixed: composer availability before host admission; the closing-menu focus takeover; full visibility of the host warning. Kept intentionally: older hosts retain their existing launch path; an invested composer survives unsupported-host fallback beside a background terminal. Existing Split Right/Down moves an existing chat; fresh-chat Split remains the separate consumer tracked in #28950. Deferred: the immediate-typing order race in STA-11369, reproduced on main, and issued-close retirement tracked in #27583/#27561. No open P0/P1 or newly proved source defect remains in this bounded finish.

Exact-head full PR workflow and its PR checks passed aggregate succeeded. Workflow identity is .github/workflows/pr.yml; all five unit shards, selected layout/relay checks and both packaging jobs passed.

Current bounded Electron QA ran on the M4Air admitted by qa-gate, ticket 830, with real Codex and Claude through their load balancers under dedicated test homes:

  • Q4: one complete 147-character older-host refusal warning, visibly wrapped over two lines; paragraph width/scroll width both 566 px, height/scroll height both 42 px. Main produced no composer or notice through the same actual refusal path.
  • Q5: one uninterrupted direct paired-Claude run without relay or held transport. Three passive samples captured nonempty pending text with Send and Attach disabled before the host receipt; the full 41-character prompt remained intact when ready, and Send received OK_Q5_PENDING in the same session.
  • New Tab and tab right-click menus: outside mouse click and Escape remove the menus after their closing animation; hover and arrow navigation work.
  • Exact original New Tab fixture: unchanged bytes, once on this head, all 38 literal characters retained, actual Send received OK_Q1_MENU.
  • STA-11369: 40 matched literal MENU38 bursts after moving an existing chat Right/Down, ten per direction per head. All keydown streams were ordered and no characters were lost. Rendered drafts reordered at the rates below.
Head Right reordered Down reordered Lost characters
This branch, fb898ea 9/10 6/10 0
Pinned main, f884b9f 4/10 4/10 0

The supplied finishing criterion passes because main reproduces at least once in each direction. These observations do not establish equal failure rates. The race is tracked in STA-11369 and the caret-restoration code is unchanged by this PR. The prior two-byte warm-relay accounting discrepancy was traced to the test relay dropping a held chunk when a connection closes; that is not a current product failure.

Unsupported-host fallback and placement (Q3/Q6) retain explicitly accepted historical 2a18d27 evidence on unchanged paths, rather than being relabelled as current-head runs. All 55 recorded test processes exited, configured ports were clear, Playwright was closed, the old disk image was detached, real config hashes were unchanged, and the QA worktree was restored to the exact branch head with no tracked changes.

Not exercised in this finish: strict 0–30 ms timing, cold cancel, reload/Retry, tours, image contents, fresh-chat Split creation, rendered direct SSH/WSL behavior, touch/pen or checkbox/radio/subtrigger variants. Standalone ContextMenuItem has source review only; both tested real menus use DropdownMenu. The Q4 diagnostic needed normal terminal layout established first on branch and the same actual folder recreated through its production owner after old-host restart on main; these setup observations are retained without claiming normal-menu Chat coverage on the old host. Both heads logged listener-count warnings; this is an observation, not a proven leak. Original branch launch isolation was preserved in the fixture but its live process environment was not separately audited before shutdown; corrected main/peer audits and unchanged real-config hashes are retained.

For Brennan's review

Current branch captures are fb898ea on the admitted M4Air. Main controls are pinned f884b9f.

The complete old-host warning now wraps. Main cannot create the refused chat or show its inline notice with the same diagnostic; this is the explicitly permitted “main cannot show it” control, not a clipping comparison. Both normal old-host menus lack Chat, so this case uses the real production Chat entrypoint against a genuine 1.4.189 server.

Main: refused Chat produces no composer or inline warning
Branch: complete warning and update instruction wrap over two lines

The unchanged New Tab menu fixture kept its complete prompt and received a real Codex reply:

Branch: literal 38-character prompt after New Tab menu selection
Branch: actual Send receives OK_Q1_MENU

One uninterrupted direct paired-Claude run retained all 41 characters and received a real reply. These images show ready and reply, respectively; the earlier disabled Send/Attach pending state is established by the passive trace, not these images.

Branch: full Q5 prompt intact when ready
Branch: same paired Claude session replies OK_Q5_PENDING

Matched existing-chat Split Right/Down: race reproduced on both heads

Same machine, settings and per-trial prerequisites, with no draft repair. These are moves of existing chats, not fresh-chat Split creation. Representative reordered drafts below are main then branch.

Right:

Main Right trial 2: early letters moved to end
Branch Right trial 1: early letter moved to end

Down:

Main Down trial 1: early letters moved to end
Branch Down trial 1: early letter moved to end

Right trial 1 on each head uses the original Attach-ready prerequisite. Right trials 2–10 add waiting for the real launch promise and a normal tab left-click on both heads; both Down runs use that same amended script. One branch menu detached before direction selection and before any burst; that prerequisite failure is retained outside the 40 measured trials. No wait or focus action is inserted between final direction selection and typing.

Current menu dismissal and navigation evidence

Both actual New Tab and tab right-click surfaces use DropdownMenu. Hover changed the highlight; ArrowDown then rendered Grok and Close respectively:

New Tab: ArrowDown reaches Grok
Tab right-click: ArrowDown reaches Close

After outside mouse clicks through an inert Projects label locator, both menus are absent:

New Tab: outside mouse click removes menu
Tab right-click: outside mouse click removes menu

Escape also removes each menu:

New Tab: Escape removes menu
Tab right-click: Escape removes menu

Accepted historical Q3/Q6 evidence, unchanged paths only

These captures are 2a18d27, not current-head QA. The empty replacement keeps explicit pin/title/colour; a composer with user content remains beside the fallback terminal.

Historical Q3/Q6: empty pinned titled coloured replacement
Historical Q3/Q6: invested chat retained beside background terminal

Two source locations for judgment:

…t-draft-first-send

# Conflicts:
#	src/renderer/src/runtime/structured-chat-host-permission.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

⚠️ Outside diff range comments (1)

🟡 Minor · Retire the terminal created after cancellation. · structured-agent-session-action-launch.ts:79-87

src/renderer/src/lib/structured-agent-session-action-launch.ts:79-87
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Retire the terminal created after cancellation.

If the provisional chat closes while openDeclinedTerminal is awaiting its dynamic import, the opener can create a terminal after cancellation. The cancellation path does not retain that tab ID. The current branch then continues without closing the terminal, which leaves an unwanted terminal tab.

Close terminal.tabId immediately after the opener resolves when the launch was cancelled. Do not await its completion after closing it.

Suggested fix
  const terminal = await openDeclinedTerminal(args, worktreeId, target, false)
+ if (launchState?.cancelled || args.hooks.signal?.aborted) {
+   if (terminal.tabId) {
+     useAppStore.getState().closeUnifiedTab(terminal.tabId, { recordInteraction: false })
+   }
+   return settlement
+ }
  const completed = terminal.completion

ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 87ef1b04-ef58-4696-9a91-d28708ac8c5d
📥 Commits

Reviewing files that changed from the base of the PR and between dcafde9 and 3b4777d.

📒 Files selected for processing: 3
  • src/renderer/src/components/native-chat/use-native-chat-composer-reveal-focus.ts
  • src/renderer/src/components/native-chat/use-native-chat-provisional-launch.test.tsx
  • src/renderer/src/lib/structured-agent-session-launch-recovery.ts
🚧 Files skipped from review as they are similar to previous changes: 3
  • src/renderer/src/lib/structured-agent-session-launch-recovery.ts
  • src/renderer/src/components/native-chat/use-native-chat-composer-reveal-focus.ts
  • src/renderer/src/components/native-chat/use-native-chat-provisional-launch.test.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 3 remain after this review.

…tem opened

A New Chat chosen from the New Tab menu kept only the first typed key: the
menu stays mounted while it animates out, and Radix focuses its content when
the pointer leaves an item, so the remaining keys went to the closed menu.
Dropdown and context menu items now cancel that pointer focus while their
menu is closing. Trims three hunks back to main's form to stay in budget.
…ructions

The paired-permission notice now shows on a New Chat as soon as it opens, and
its "Update Orca on this host" instruction was cut off with an ellipsis and no
tooltip. Host notices now wrap like every other composer notice.
…t-draft-first-send

# Conflicts:
#	src/renderer/src/lib/structured-agent-session-launch-options.ts
@brennanb2025
brennanb2025 merged commit 821ab37 into main Oct 20, 2026
41 checks passed
@zpyoung zpyoung mentioned this pull request Oct 21, 2026
1 of 2 tasks
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