fix(sessions): stale-conversation cost warning is a blocking prompt-input state#3152
Conversation
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
|
Reviews (1): Last reviewed commit: "fix(sessions): cap the story's fake thre..." | Re-trigger Greptile |
pauldambra
left a comment
There was a problem hiding this comment.
Note
🤖 Automated comment by QA Swarm — not written by a human
QA Swarm review complete. See inline comments.
|
Note 🤖 Automated comment by QA Swarm — not written by a human Multi-perspective review: qa-team (specialists + generalists), paul-reviewer, xp-reviewer, security-audit Verdict: 💬 APPROVE WITH NITS (round 2 @ 92a819f)The round-1 fixes are faithfully implemented with no regressions; the delta's new dynamism opens two narrow edge cases worth closing. Nothing blocks. Key findings
ConvergenceNone this round — each finding came from a single reviewer. Reviewer summaries
Previous rounds (1)round 1 @ f05d8c5 — 💬 APPROVE WITH NITS: 3 MEDIUM (compact/permission double reload, ack-before-send, mid-reconnect actionability), 5 LOW, 2 NIT; all fixed in Automated by QA Swarm — not a human review |
There was a problem hiding this comment.
The PR exceeded the automated size gate (504 lines vs 500-line ceiling). The changes themselves appear well-reasoned — all 22 inline review comments are resolved, including substantive issues around permission prompt ordering, offline guards, and Escape key swallowing. Request a human reviewer to confirm the fix is complete before merging.
|
Reviews (2): Last reviewed commit: "fix: address qa-swarm review on the stal..." | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 92a819fe2d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
pauldambra
left a comment
There was a problem hiding this comment.
Note
🤖 Automated comment by QA Swarm — not written by a human
QA Swarm round 2 complete. See inline comments.
The staff-only warning for continuing a large, idle conversation was an AlertDialog that flashed and immediately vanished: opening a stale session reconnects the agent, which re-emits usage/handshake notifications stamped ts=Date.now() in the workspace-server, so the reactive staleness check flipped back off before the user could read the warning. Latch the gate in the view-state store (with the last-activity time observed at engagement) so only an explicit choice releases it, and replace the modal with an overlay covering the chat window - thread, permission prompt, and composer - so the user must choose "Continue anyway" or "Start a new session" before continuing. Generated-By: PostHog Code Task-Id: 1ec8e82e-b126-48b8-8fd4-54edcaf041d5
"Compact and continue" (the recommended, solid action) acknowledges the gate and sends /compact: the reload is paid once, then every later turn runs on the summarized, smaller thread. "Continue anyway" and "Start a new session" remain as the full-context and zero-cost choices. Generated-By: PostHog Code Task-Id: 1ec8e82e-b126-48b8-8fd4-54edcaf041d5
Drop the floating overlay: when the gate engages, the composer slot renders an ActionSelector (the same primitive as permission prompts) with the three choices - compact and continue, continue anyway, start a new session. It takes precedence over a pending permission, since answering one also resumes the costly turn. Adds a Storybook story, and the ActionSelector footer only advertises Esc when onCancel is actually wired. Generated-By: PostHog Code Task-Id: 1ec8e82e-b126-48b8-8fd4-54edcaf041d5
The full-width backdrop rows made the notice look narrower than the prompt input; in SessionView both share the same mx-auto 750px wrapper. Generated-By: PostHog Code Task-Id: 1ec8e82e-b126-48b8-8fd4-54edcaf041d5
- suppress "Compact and continue" while a permission is pending (a queued /compact would land after the permission resumes the costly turn, paying the reload twice) - guard the compact choice on connectivity so the gate is not released when the send cannot happen - wait for isRunning before showing the notice so choices cannot fire into a session that is still reconnecting - track which of the three options staff pick (typed analytics event) - let Escape bubble out of ActionSelector when there is no onCancel - explicit new-session branch in the notice dispatch, cost parenthetical moved next to the pricing sentence, comment on the active derivation Generated-By: PostHog Code Task-Id: 1ec8e82e-b126-48b8-8fd4-54edcaf041d5
- remount the notice when the option set changes so ActionSelector's highlighted index can't dereference past the list or fire a different option than the one shown - keep the gate covering the composer slot while reconnecting (handoff can leave pendingPermissions set; the connecting state shows instead of an answerable permission prompt) - derive the choice union from StaleConversationGateChoiceProperties - handleStaleNewSession is a useCallback like its siblings, with the undefined guard at the call site - story for the two-option permission-pending layout Generated-By: PostHog Code Task-Id: 1ec8e82e-b126-48b8-8fd4-54edcaf041d5
- clamp selectedIndex in useActionSelectorState when options change, replacing the consumer-level remount key (fixes the primitive for every consumer with live-changing options) - extract ComposerSlot/ComposerWidth and ConnectingToAgent in SessionView, collapsing three copies of the composer-slot wrapper and two copies of the connecting spinner - reuse formatUsd instead of hand-rolled toFixed(2) - plain functions instead of useCallbacks for the gate handlers (the notice isn't memoized and the closed-over usage values change per streamed event anyway); single guard on onNewSession - flatten the gate store's engagement Map to number | null and keep the Map reference stable when acknowledge has nothing to release Generated-By: PostHog Code Task-Id: 1ec8e82e-b126-48b8-8fd4-54edcaf041d5
c404d6b to
0a8bdca
Compare

Problem
The staff-only warning for continuing a large, idle conversation (#3122) was an
AlertDialogthat flashed up and immediately disappeared.Root cause: the gate was purely reactive on "newest event
tsolder than 60 min". Opening a stale session reconnects the agent, which immediately re-emits notifications (usage update, SDK handshake) that the workspace-server stamps withts: Date.now()— so the conversation instantly looked active again and the dialog closed itself before it could be read.Change
ActionSelectorused by permission prompts, so you must choose before continuing:/compact; pays the reload once, every later turn is cheaperActionSelector's footer now only advertises "Esc to cancel" whenonCancelis actually wired (this selector has no cancel; permission prompts are unaffected).Sessions/StaleConversationCostNotice(thread backdrop capped at the realCHAT_CONTENT_MAX_WIDTH, same 750px wrapper the composer uses — the notice renders at exactly the prompt input's width).Testing
staleConversationGateStore.test.ts(engage snapshots, idempotence, acknowledged sessions can't re-engage)pnpm --filter @posthog/ui typecheck, Biome cleanCreated with PostHog Code