Repository navigation
fix(jetbrains): recover pending question/permission after reconnect - #14440
Merged
Merged
Conversation
A completed plan's follow-up question (or any permission/question) asked while the backend SSE/chat stream reconnects can be lost, since those streams do not replay. The session then shows Busy indefinitely even though the CLI's pending-list endpoints still report it. SessionController.recoverPending() already rehydrates pending prompts after history load, but was never invoked on reconnect despite its own comment claiming to do so. Trigger it on a subsequent non-READY -> READY app-state edge for an already-loaded session, guarded by a monotonic prompt revision so a stale snapshot can never overwrite a fresher live question/permission or resurrect one that was just answered/rejected. Also fix session.status "idle" to preserve AwaitingQuestion, matching the existing session.idle handler, so an idle status between turns cannot hide a blocking question.
Contributor
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (2 files)
Previous Review Summary (commit 0800c04)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 0800c04)Status: 4 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (5 files)
Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0 Review guidance: REVIEW.md from base branch |
zfralish
approved these changes
Sep 22, 2026
5 tasks done
This was referenced Sep 23, 2026
4 of 5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue
Fixes #
Context
After a plan finishes and calls
plan_exit, the CLI intentionally stays busy while it asks a blocking follow-up question ("Ready to implement?"). If thatquestion.askedevent is lost during a backend SSE/chat-stream reconnect (those streams do not replay), the JetBrains session shows a generic "Considering next steps" busy state forever, even though the CLI's pending-question endpoint still reports it. The only known workaround was stopping the session and sending "continue".Implementation
SessionController.recoverPending()already rehydrates pending permissions/questions/status after history load, but despite its own doc comment claiming to also cover "reconnect", it was never invoked on reconnect.lastAppStatus). On a subsequent non-READY -> READY transition for an already-loaded local session (not the very first connect, not aREADY -> READYconfig/profile refresh), call newrecoverOnReconnect(), which re-runsrecoverPending().promptRevisioncounter, bumped whenever a live permission/question ask/reply/reject is handled. The recovery snapshot captures the revision before its suspending REST calls and discards the result if the revision changed before the EDT commit — so a stale reconnect snapshot can never overwrite a fresher live question/permission, or resurrect one that was just answered/rejected.session.status "idle"preservedAwaitingPermissionbut notAwaitingQuestion, unlike the existingsession.idlehandler. An idle status between turns could otherwise hide a blocking question card.No CLI, backend RPC, or DTO changes were needed — the pending-list endpoints already existed and were already used for history-load recovery.
Screenshots / Video
N/A — no visual/UI change, only session-state recovery timing.
How to Test
Manual/local verification
./gradlew typecheckand the full:frontend:testsuite frompackages/kilo-jetbrains/(agent-run) — all green.Reviewer test steps
./gradlew runIdeSplitModeorrunIde), start a Plan-mode session and let it callplan_exit.question.askedevent is dropped.Blocked checks and substitute verification
SessionRecoveryTest.ktthat simulate the same race via a gated fake RPC (pendingGate) and explicit app-state transitions, plus theListenerLifecycleTest.ktidle-status regression test.Checklist
Get in Touch