Skip to content

fix(app): confirm before quitting with working sessions; never stay invisible - #307

Merged
maxthomas95 merged 4 commits into
mainfrom
fix/window-lifecycle-20261109
Nov 10, 2026
Merged

maxthomas95 merged 4 commits into
mainfrom
fix/window-lifecycle-20261109

Conversation

@maxthomas95

Copy link
Copy Markdown
Owner

Summary

Review section 5.1 (docs/REVIEW_2026-11-09.md).

  • Quit guard. Closing the window used to quit and kill every local session with no question. It now asks first when a session is starting, running or waiting on a permission prompt. Idle sessions close without a prompt because they restore on the next launch. The check runs on the window close event and at the top of before-quit, so hooks and services are not torn down before the answer. The dialog is native (it works even if the renderer is hung) and has "Don't ask again".
  • Setting. Settings > General > "Confirm before quitting while sessions are working", config key confirmQuitWithActiveSessions, on by default.
  • Invisible window. The window was shown only on ready-to-show, and usage, quota, J.O.B.S. and the update check were started inside that callback. If the event never fired (wedged GPU compositor) the app ran with no window and none of those services. A run-once reveal now also fires from a 4 s fallback timer.
  • Relaunch recovery. second-instance shows the window when it is not visible.
  • Smoke test. scripts/smoke-windows.mjs unticks the new toggle on first launch, since a native dialog cannot be answered through the debugging port, and asserts the preference survives the restart.

No new IPC channels. The darwin window-all-closed behaviour is unchanged.

Test plan

  • npx tsc --noEmit
  • npx eslint on touched files
  • npx vitest run src/main/quit-guard.test.ts src/renderer/components — 156 passed
  • CI windows package + verify (exercises the smoke change; I could not run the packaged smoke locally)
  • Manual: with a running agent, click X — dialog appears; Cancel keeps everything running; Quit exits
  • Manual: with only idle sessions, X exits without a prompt
  • Manual: tick "Don't ask again", relaunch — the Settings toggle is off and X no longer asks
  • Manual: launch with the window hidden (or simulate by delaying first paint) — window appears after about 4 s; relaunching the app also brings it up

Out of scope

  • Close-to-tray.
  • A confirmation on Ctrl+W / Session > Stop (in the renderer workflow PR).

🤖 Generated with Claude Code

maxthomas95 and others added 4 commits November 9, 2026 20:41
…nvisible

Quit guard. Closing the window quit the app and killed every local PTY
without asking. Closing now asks first when a session is starting,
running or waiting on a permission prompt; idle sessions close without a
prompt, since they restore on the next launch. The check runs on the
window's close event and at the top of before-quit, so nothing is torn
down before the answer. "Don't ask again" and a new Settings > General
toggle store confirmQuitWithActiveSessions. With no window left there is
nothing to ask on, so the quit proceeds rather than leaving a windowless
app that cannot exit.

Invisible window. The window was shown only on ready-to-show, and the
update check, usage, quota and J.O.B.S. startup were scheduled inside
that callback. When the event never fired the app ran with no window and
none of those services. A run-once reveal now also fires from a 4 s
fallback timer, and a second launch shows the window if it is hidden.

The packaged smoke test unticks the new toggle during its first launch:
the confirmation is a native dialog that cannot be answered through the
debugging port, and a restored session may still be starting when the
second launch exits. It also asserts the preference survives a restart.

Tests: quit-guard predicates; renderer component suite. No change to the
darwin window-all-closed behaviour.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
The failure artifacts held only the harness's view. The app's own log from the scratch profile shows what it was doing when it exited.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
11.2% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@maxthomas95
maxthomas95 merged commit 582f37e into main Nov 10, 2026
10 of 11 checks passed
@maxthomas95
maxthomas95 deleted the fix/window-lifecycle-20261109 branch November 10, 2026 03:32
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