Skip to content

fix: Unity commands recover reliably after editor reloads#1182

Merged
hatayama merged 2 commits into
v3-betafrom
feature/hatayama/fix-launch-readiness-timeout
May 22, 2026
Merged

fix: Unity commands recover reliably after editor reloads#1182
hatayama merged 2 commits into
v3-betafrom
feature/hatayama/fix-launch-readiness-timeout

Conversation

@hatayama
Copy link
Copy Markdown
Owner

@hatayama hatayama commented May 22, 2026

Summary

  • Unity CLI Loop now recovers the bridge server during Editor startup and domain reload recovery, even when no previous server session was recorded.
  • CLI commands now wait through transient recovery states instead of failing early on stale stopped state.

Closes #1175

User Impact

  • Opening Unity from Unity Hub, launch-unity, or uloop launch can recover the bridge automatically, unless Stop Server was explicitly used.
  • Commands issued while Unity is starting or reloading avoid premature server stopped failures and keep working once recovery finishes.

Changes

  • Align readiness state publishing with automatic recovery, including no-server reloads and explicit manual-stop preservation.
  • Track explicit Stop Server intent in SessionState and keep restart cleanup from being treated as a manual stop.
  • Update native CLI readiness waiting and regenerate the checked-in native CLI binaries.
  • Add focused EditMode and Go tests for recovery, stopped-state waiting, and manual-stop behavior.

Verification

  • scripts/check-go-cli.sh
  • Packages/src/Cli~/dist/darwin-arm64/uloop run-tests --project-path <PROJECT_ROOT> --test-mode EditMode --filter-type regex --filter-value ".*(DomainReloadRecoveryUseCaseTests|DomainReloadDetectionServiceTests|UnityCliLoopEditorSessionStateRepositoryTests|UnityCliLoopServerControllerRecoveryTests|UnityCliLoopEditorSettingsRecoveryTests).*" (37 tests passed)
  • Packages/src/Cli~/dist/darwin-arm64/uloop compile --project-path <PROJECT_ROOT>
  • ~/.codex/skills/codex-review/scripts/codex-review v3-beta

Start server recovery even when a reload reports no previous bridge session, so launch and restart can recover from cold startup state instead of leaving server-state stopped.

Also stop launch readiness from waiting until the full timeout when stopped state remains unchanged after a short recovery grace period.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e46cee60-2e8c-47ab-ae97-42f33703ae1d

📥 Commits

Reviewing files that changed from the base of the PR and between e1fdeca and 3ef7714.

⛔ Files ignored due to path filters (3)
  • Packages/src/Cli~/dist/darwin-amd64/uloop is excluded by !**/dist/** and included by none
  • Packages/src/Cli~/dist/darwin-arm64/uloop is excluded by !**/dist/** and included by none
  • Packages/src/Cli~/dist/windows-amd64/uloop.exe is excluded by !**/dist/**, !**/*.exe and included by none
📒 Files selected for processing (4)
  • Assets/Tests/Editor/UnityCliLoopServerControllerStartupLockTests.cs
  • Packages/src/Cli~/internal/cli/tool_readiness.go
  • Packages/src/Cli~/internal/cli/tool_readiness_test.go
  • Packages/src/Editor/Infrastructure/Server/UnityCliLoopServerController.cs

📝 Walkthrough

Walkthrough

This PR introduces server manual-stop tracking to gate recovery on user intent rather than server running state. A new session-state flag (IsServerManuallyStopped) distinguishes manual shutdown from automatic restart cleanup. Recovery now skips when manually stopped. Go-side readiness logic detects stale stopped states by checking process presence.

Changes

Manual Stop State Tracking and Recovery Control

Layer / File(s) Summary
Session state persistence and flag definition
Packages/src/Editor/Infrastructure/Settings/UnityCliLoopEditorSessionStateRepository.cs, Assets/Tests/Editor/UnityCliLoopEditorSessionStateTestFactory.cs, Assets/Tests/Editor/UnityCliLoopEditorSessionStateRepositoryTests.cs
New IsServerManuallyStopped key and getter/setter persist the flag in session state. Test snapshot captures and restores the flag. Tests verify the flag defaults to false, persists across service recreation, and is cleared by ClearAll().
Session state service domain logic and transitions
Packages/src/Editor/Domain/UnityCliLoopEditorSessionStateService.cs
Port interface and service expose the flag via wrapper methods. New transition helpers MarkServerStarted() (sets running, clears manual-stop) and MarkServerManuallyStopped() (clears session, sets manual-stop). Domain-reload startup clears the flag and ClearAll resets it.
Recovery control flow gating on manual-stop state
Packages/src/Editor/Application/SessionRecoveryService.cs, Packages/src/Editor/Infrastructure/Server/DomainReloadDetectionFileService.cs
Recovery skips early when GetIsServerManuallyStopped() returns true. Domain-reload completion writes recovery state based on manual-stop inverse instead of prior running state; uses "manual-stop" reason when recovery is skipped. Legacy migration marks server started via MarkServerStarted().
Server shutdown intent plumbing and manual-stop marking
Packages/src/Editor/Application/UnityCliLoopServerStartupService.cs, Packages/src/Editor/Infrastructure/Server/UnityCliLoopServerController.cs
New ServerStopIntent enum distinguishes manual stop from restart cleanup. Shutdown refactored through intent-based flow that updates session state differently per intent; SaveRunningServerState now uses MarkServerStarted(). StartServerWithUseCaseAsync and RestoreServerStateIfNeeded visibilities adjusted to internal.
Go-side stopped-server state detection and staleness checking
Packages/src/Cli~/internal/cli/tool_readiness.go, Packages/src/Cli~/internal/cli/tool_readiness_test.go
New polling-based waitForStoppedServerStateChange detects stopped-state transitions after a grace period. Staleness checked via process finder; returns serverStoppedError when stopped state is stale, or continues polling when Unity runs. Tests cover immediate stop, stale-but-running, recovery transition detection, and internal timeout mapping.
Test coverage for recovery gating and stop intent
Assets/Tests/Editor/DomainReloadDetectionServiceTests.cs, Assets/Tests/Editor/DomainReloadRecoveryUseCaseTests.cs, Assets/Tests/Editor/UnityCliLoopServerControllerStartupLockTests.cs
Domain-reload tests updated to expect recovering phase instead of stopped for migrated/legacy scenarios. Recovery tests assert StartRecovery call counts for not-running vs manually-stopped cases. Controller tests add manual-stop preservation and simulate restart-cleanup start/stop failures.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.44% 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 clearly summarizes the main change: fixing Unity command recovery after editor reloads by improving how the system handles server restart and recovery scenarios.
Description check ✅ Passed The description is directly related to the changeset, providing clear context about recovery behavior, manual stop tracking, and readiness waiting improvements reflected in the code changes.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/hatayama/fix-launch-readiness-timeout

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@Packages/src/Cli`~/internal/cli/tool_readiness.go:
- Around line 124-126: The stopped-state wait path is returning
context.DeadlineExceeded because it calls toolReadinessDoneError(ctx) using the
derived/internal timeout context; change the call so it passes the original
user-facing context (the parent/original context that carries the user-visible
deadline) instead of the derived internal ctx when handling the
graceTimer.C/timeout path so the same user-facing timeout message is returned;
update the branch handling case <-graceTimer.C (and any other place that uses
the derived ctx for error mapping) to call toolReadinessDoneError with the
original context variable rather than the internal ctx.

In `@Packages/src/Editor/Infrastructure/Server/UnityCliLoopServerController.cs`:
- Around line 218-220: The restart path must abort if cleanup fails: update the
code that calls StopServerForRestartAsync and the subsequent
useCase.ExecuteAsync call (the block around _bridgeServer and StartServer logic)
to inspect the shutdown result and return early when shutdown/cleanup did not
succeed; specifically, have StopServerForRestartAsync propagate a
success/failure (or have it return the useCase.ExecuteAsync result) and then
check that result after calling StopServerForRestartAsync (and after
useCase.ExecuteAsync) and skip starting a new server when Success == false so
you don't proceed to create/Start a fresh bridge server; apply the same
check/update to the other restart path mentioned (the block covering lines
266-315).
🪄 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: 45a05100-3874-4d33-b81d-5a9bf4ec2b21

📥 Commits

Reviewing files that changed from the base of the PR and between 78b5b22 and e1fdeca.

⛔ Files ignored due to path filters (3)
  • Packages/src/Cli~/dist/darwin-amd64/uloop is excluded by !**/dist/** and included by none
  • Packages/src/Cli~/dist/darwin-arm64/uloop is excluded by !**/dist/** and included by none
  • Packages/src/Cli~/dist/windows-amd64/uloop.exe is excluded by !**/dist/**, !**/*.exe and included by none
📒 Files selected for processing (13)
  • Assets/Tests/Editor/DomainReloadDetectionServiceTests.cs
  • Assets/Tests/Editor/DomainReloadRecoveryUseCaseTests.cs
  • Assets/Tests/Editor/UnityCliLoopEditorSessionStateRepositoryTests.cs
  • Assets/Tests/Editor/UnityCliLoopEditorSessionStateTestFactory.cs
  • Assets/Tests/Editor/UnityCliLoopServerControllerStartupLockTests.cs
  • Packages/src/Cli~/internal/cli/tool_readiness.go
  • Packages/src/Cli~/internal/cli/tool_readiness_test.go
  • Packages/src/Editor/Application/SessionRecoveryService.cs
  • Packages/src/Editor/Application/UnityCliLoopServerStartupService.cs
  • Packages/src/Editor/Domain/UnityCliLoopEditorSessionStateService.cs
  • Packages/src/Editor/Infrastructure/Server/DomainReloadDetectionFileService.cs
  • Packages/src/Editor/Infrastructure/Server/UnityCliLoopServerController.cs
  • Packages/src/Editor/Infrastructure/Settings/UnityCliLoopEditorSessionStateRepository.cs

Comment thread Packages/src/Cli~/internal/cli/tool_readiness.go Outdated
Comment thread Packages/src/Editor/Infrastructure/Server/UnityCliLoopServerController.cs Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 16 files

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

Re-trigger cubic

Comment thread Packages/src/Cli~/internal/cli/tool_readiness.go Outdated
Normalize stopped-state readiness timeout mapping so internal timeout expiry keeps the same user-facing error as other readiness paths. Also abort manual restart startup when pre-start cleanup fails, preserving the original shutdown failure instead of hiding it behind a second bind attempt.
@hatayama hatayama merged commit 7c035ec into v3-beta May 22, 2026
8 checks passed
@hatayama hatayama deleted the feature/hatayama/fix-launch-readiness-timeout branch May 22, 2026 07:59
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