Skip to content

fix: Slow Unity responses now bring the Editor forward - #1353

Merged
hatayama merged 2 commits into
v3-betafrom
fix/auto-front-window
Jun 16, 2026
Merged

hatayama merged 2 commits into
v3-betafrom
fix/auto-front-window

Conversation

@hatayama

@hatayama hatayama commented Jun 16, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Unity is brought to the foreground when a connected Editor becomes slow, stalled, or times out unexpectedly.
  • Windows focus restore now returns to the previous window reliably without resizing maximized windows.

User Impact

  • Before, automatic focus recovery only ran for connection failures before dispatch, so accepted but stalled Unity requests could remain hidden in the background.
  • After this change, abnormal slow-response paths try to surface the Editor, recoverable retries restore the original window, and terminal timeout failures leave Unity visible so the user can see what needs attention.

Changes

  • Classify slow-response focus triggers for pre-accept timeouts, heartbeat-reported main-thread stalls, heartbeat silence, and abnormal final-response timeouts.
  • Report main-thread stalls from IPC heartbeats and include focus reasons in recovery logs.
  • Update Windows focus restore to use thread input attachment while preserving maximized foreground windows.

Verification

  • From cli/: go test ./internal/cli ./internal/unityipc -run 'Focus|ConnectionRetry|Heartbeat|Compile' -count=1
  • From repo root: ./scripts/check-go-cli.sh
  • Codex review against v3-beta with check-go-cli.sh: clean, no accepted/actionable findings.
  • Manual Windows focus probes confirmed minimized Unity is restored/focused and foreground focus can return to the original window.

Review in cubic

Focus recovery previously only ran after undispatched connection failures, so accepted-but-stalled Unity requests never triggered the Windows focus warmup path.

- Add typed main-thread stall reporting from IPC heartbeats.

- Focus once for pre-accept timeouts, heartbeat stalls, heartbeat silence, and abnormal final response timeouts while skipping server_busy and intentional compile polling timeouts.

- Restore Windows foreground focus with AttachThreadInput after recoverable focus attempts, preserve maximized windows, and leave Unity visible after terminal timeout failures.
@coderabbitai

coderabbitai Bot commented Jun 16, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@hatayama, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 12 minutes and 10 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 28623905-2508-4342-af3c-475b0ddafb95

📥 Commits

Reviewing files that changed from the base of the PR and between e89cfc5 and 16e1a4e.

📒 Files selected for processing (2)
  • cli/internal/cli/connection_retry.go
  • cli/internal/cli/connection_retry_test.go
📝 Walkthrough

Walkthrough

Introduces a connectionRetryFocusController with a typed connectionRetryFocusReason enum to centralize Unity focus state, deferred restoration, and error classification during connection retries. Adds a WithMainThreadStallHandler callback to the IPC client to route stall events into the controller. Rewrites the Windows foreground-window restore script to use thread-attach/minimize-aware Win32 operations.

Changes

Connection Retry Focus Controller, IPC Stall Handler, and Windows Restore

Layer / File(s) Summary
IPC client mainThreadStallHandler hook
cli/internal/unityipc/client.go, cli/internal/unityipc/client_heartbeat_test.go
Adds mainThreadStallHandler func(float64) field to Client, the WithMainThreadStallHandler fluent setter, and invocation of the callback at the heartbeat stall threshold alongside the existing progress message; test asserts handler fires once with the expected stall duration.
Focus reason enum and connectionRetryFocusController
cli/internal/cli/connection_retry.go
Defines connectionRetryFocusReason constants and the connectionRetryFocusController struct with methods for construction, deferred restoration, one-shot focus guarding, tryFocus/tryFocusProcess, and stall-triggered focusing; adds connectionRetryFocusReasonForError classification; updates three Vibe log helpers to include the reason field.
Retry loop wiring
cli/internal/cli/connection_retry.go
Updates sendWithTransientConnectionRetry to instantiate the controller up-front, defer focus restoration, attach the IPC stall handler to the controller, route errors through connectionRetryFocusReasonForError, and replace inline focus logic with controller calls.
Focus reason and retry integration tests
cli/internal/cli/connection_retry_test.go
Unit tests for connectionRetryFocusReasonForError across all timeout and exclusion cases; updated Vibe log assertions adding the reason field; TCP-injection integration test asserting focus-without-restore on pre-accept timeout.
Windows restore script: thread-aware Win32 interop
cli/internal/cli/focus.go, cli/internal/cli/focus_test.go
Adds includeThreadFocus parameter to buildWindowsFocusInteropTypeDefinition with conditional P/Invoke declarations; rewrites buildRestoreWindowsForegroundWindowScript to attach thread input, handle minimized windows, and detach in a finally block; updates callers and adds/updates tests for the new PowerShell substrings.

Sequence Diagram(s)

sequenceDiagram
  participant RetryLoop as sendWithTransientConnectionRetry
  participant Controller as connectionRetryFocusController
  participant IPCClient as unityipc.Client
  participant FocusScript as focusUnityProcess

  RetryLoop->>Controller: newConnectionRetryFocusController(...)
  RetryLoop->>IPCClient: WithMainThreadStallHandler(controller.onMainThreadStall)
  IPCClient-->>Controller: onMainThreadStall(stallSeconds) [on threshold]
  Controller->>FocusScript: tryFocus(main_thread_stall, ...)
  RetryLoop->>RetryLoop: error occurs → connectionRetryFocusReasonForError
  RetryLoop->>Controller: tryFocus(reason, ...) + keepUnityFocusedAfterReturn
  RetryLoop->>Controller: doRestoreFocus [deferred on return]
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • hatayama/unity-cli-loop#1199: Modifies the same connection retry and focus-with-restore paths in connection_retry.go and focus.go, directly overlapping with the controller and focus logic introduced here.
  • hatayama/unity-cli-loop#1215: Adds structured Vibe logging to the same focus helpers in connection_retry.go and focus.go that this PR extends with the reason field.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 56.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and concisely summarizes the main change: enabling automatic focus recovery when Unity Editor responses are slow, which is the core objective of this PR.
Description check ✅ Passed The description is detailed and clearly related to the changeset, explaining the user impact, specific changes made, and verification steps performed.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/auto-front-window

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 and usage tips.

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cli/internal/cli/connection_retry.go`:
- Around line 107-109: The issue is that in the tryFocus function at lines
107-109, setting controller.attempted = true when process discovery fails or
returns nil permanently marks the focus attempt as complete, preventing the
terminal-timeout path at lines 232-235 from retrying focus recovery on the same
reused controller. When process discovery fails transiently, this overly
aggressive flag prevents the final recovery attempt from succeeding. Fix this by
not setting controller.attempted = true in the error case where runningProcess
discovery fails or returns nil, allowing the later terminal-timeout path to
still attempt focus recovery if needed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bd1cd2af-f595-4c8b-8f9c-b673b3a2b3d3

📥 Commits

Reviewing files that changed from the base of the PR and between 2ee34eb and e89cfc5.

📒 Files selected for processing (6)
  • cli/internal/cli/connection_retry.go
  • cli/internal/cli/connection_retry_test.go
  • cli/internal/cli/focus.go
  • cli/internal/cli/focus_test.go
  • cli/internal/unityipc/client.go
  • cli/internal/unityipc/client_heartbeat_test.go

Comment thread cli/internal/cli/connection_retry.go

@cubic-dev-ai cubic-dev-ai 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.

2 issues found across 6 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread cli/internal/cli/focus_test.go
Comment thread cli/internal/cli/connection_retry.go Outdated
A transient Unity process lookup failure should not consume the one focus attempt for a command. Leave the controller retryable until a real process focus attempt runs, and cover the later terminal-timeout recovery path with a focused test.
@hatayama
hatayama merged commit 0e5ee2c into v3-beta Jun 16, 2026
9 checks passed
@hatayama
hatayama deleted the fix/auto-front-window branch June 16, 2026 03:03
@github-actions github-actions Bot mentioned this pull request Jun 16, 2026
RyanXie123 pushed a commit to RyanXie123/unity-cli-loop that referenced this pull request Sep 22, 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.

1 participant