Repository navigation
feat: Hot reload waits for a busy Editor instead of compiling, stays fast as live patches grow, and pause points work in package scripts - #3224
Merged
Conversation
…en it looks for callers (#3204)
… assembly that is missing, and the snapshot warning says why the snapshot is unusable (#3206)
…blies that do not grant internals to the edited one (#3207)
…e cause, and ends with the step that fits the use (#3208)
…der behind its virtual path (#3209)
… source instead of warning on every run (#3211)
… hot-reload compile fallback (#3212)
…ported as a likely modal dialog (#3215)
…n its Debug recompile request is lost (#3216)
…xt reload accepts (#3218)
…only busy compiling or importing (#3219)
…h names the file (#3220)
…ckage folder outside Packages (#3223)
Contributor
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configuration
⛔ Files ignored due to path filters (44)
📒 Files selected for processing (146)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
…stead of failing as busy (#3226)
hatayama
marked this pull request as ready for review
October 7, 2026 13:56
This was referenced Oct 7, 2026
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.
Summary
Merge status
User Impact
Hot reload waits for the Editor instead of giving up
uloop hot-reloadright away often failed with "The Editor became busy before the reload could be applied". With--compile-on-skip autothe CLI then ran a fallback compile (64–78 s on the trial project), which exits Play Mode and discards every live patch; withoffthe user had to wait and rerunRetryAfterEditorReady). The CLI prints "waiting for it to settle" on stderr, polls the Editor status every second (up to 10 minutes), and applies the same files once more. The response carriesEditorReadyRetryNoteandTiming.EditorReadyWaitMs. Measured on the trial project: 44 s wait,NothingToApplybecause Unity's own compile had taken the edit, exit 0, no fallback compileRecommendedNextActionsaid "Fix the failed declarations or methods" even when nothing in the source needed a change (Editor busy, compiled assembly missing)Edits that were skipped or failed are now applied
--compile-on-skip autoran a fallback compile for itInternalsVisibleToto the edited assembly are publicized as beforefile:) package patched every method of the file and warned that the file "has no compiled method body"Speed
OtherMsstays at 1.3–2.1 s instead of climbing from 11.3 s to 43.8 s; the 12 applies took 58 s in all instead of 410 sThe response and its text
./Packages/<folder>/...), which the nextuloop hot-reload --filesdid not acceptPackages/<package-id>/..., the form the next reload acceptsPause points
enable-pause-pointfailed for a script in an embedded or local package, in every path form--filenames the package path (Packages/<package-id>/...), the path under the package's folder, or an absolute path. The markerIdalways uses the asset pathpause-point-status,await-pause-pointandclear-pause-pointbuilt the marker id from--fileas typed, so any form other than the asset path reportedNotEnabled, an await waited for a marker it could not see, and a clear left the marker armedfile:package that sits inside the project but outsidePackages/. A named marker (--id jump) is looked up as givenuloop compiledoes: a lost or rejected request is sent again under a new request ID (at most 3 sends). Measured: 90.8 s, then successLogs
ULOOP_DEBUGset, a hot-reload run wrote nothing to the CLI-side vibe log, so its entries could not be lined up against the Editor'shot-reloadalso logs the fallback decision and the editor-ready retry, all under the correlation ID of the request they followBehaviour changes to weigh before merging
--compile-on-skipas before. Two details: the second apply names the files explicitly, so a file that the default selection would have left out (an enum member added and nothing else) is applied on the retry; and the vibe-log entrycli_hot_reload_compile_fallback_decidedis not written when the retry ended the command (thecli_hot_reload_editor_ready_retry_completeentry is).<path>:<line>query id to the asset path unless that id is already registered (fix: Pause point status, await, and clear find a marker whichever path names the file #3220, fix: Pause point status, await, and clear find a marker in a local package folder outside Packages #3223). For a query path that does not start withAssets/, the status poll thatawaitrepeats every second reads the Package Manager's package list each time.ULOOP_DEBUGset, every tool command now writes two CLI-side log entries (feat: Write CLI-side vibe log entries for plain tool commands and the hot-reload compile fallback #3212). Nothing is written without it.RecommendedNextAction(fix: Hot reload's next-step advice fits an Editor that was busy or an assembly that is missing, and the snapshot warning says why the snapshot is unusable #3206), the internal-member reason (fix: Hot reload's internal-member reason leads with the member and the cause, and ends with the step that fits the use #3208), the 30-second notice (fix: A compile that keeps Unity silent for 30 seconds is no longer reported as a likely modal dialog #3215) and the Skipped row's file name (fix: Skipped hot-reload rows name a package script by the path the next reload accepts #3218). Tests that pin those strings were updated in the same pull requests.Not covered
— fixed by fix: Hot reload sent while another uloop command runs waits for it instead of failing as busy #3226 (hot reload waits for the running command on the Editor status and sends once; no busy-stall focus). Re-verified on the trial project: two runs ofuloop compilefollowed at once byuloop hot-reloadis refused withUNITY_SERVER_BUSYuloop compilefollowed two seconds later byuloop hot-reload --files … --compile-on-skip offexited 0 withNothingToApplyafter waiting 48–50 s (EditorReadyWaitMs49751 and 47529), and the Editor never came to the front (polled every 0.5 s). During the wait the CLI sent the request again twice, five seconds apart, while the compile runner's post-compile warm-up probe (execute-dynamic-code) held the Editor; both were answered busy and the wait went on, as designed.uloop launch -r, while the Debug-switch warning says the setting "reverts on every Editor restart" in the other direction. Not investigated.await-pause-pointon timeout reportsDetails.TimeoutSeconds: 30when--timeout-seconds 5was given (the message says 5 s), and itsIdechoes the typed path form rather than the marker's. Both predate this branch.main.outputPath.Included pull requests
Each pull request's description holds its own behaviour changes, input-space table, mutation checks and "Not covered" list.
Five of these did not come from the report or its re-tests. They were found while fixing the reported items: the shared path mapping (#3214), the 30-second notice (#3215), the pause-point recovery compile (#3216), the Skipped row's file name (#3218), and the local-package folder form (#3223).
Changes
RetryAfterEditorReady,SelectedFiles), reason and advice texts, the pause-point use case and status bridge, a new shared assemblyUnityCLILoop.FirstPartyTools.Common.ScriptPath.Editorfor the script path mapping, and the hot-reload and pause-point skill references.hot-reload, the pause-point recovery compile, the CLI-side vibe log entries, and the 30-second notice ofuloop compile.Packages/uloop-hotreload-package-fixture) for the package-script tests.Verification
e208b53f(manual runs, because pull requests to the integration branch do not trigger the full CI):build-and-test.yml(Go tests on Linux, macOS and Windows, and the C# build): passed.unity-editmode-tests.yml(the full EditMode suite on every Unity version, plus the Release and concurrency legs), run 37603580182: the 6000.3, 6000.5, 6000.7, Release and concurrency legs passed; the 2022.3 leg failed on one test,OnionAssemblyDependencyTests.InfrastructureAsmdef_WhenLoaded_DependsOnApplicationRuntimeAndDoesNotReferencePresentation, which pins the reference list of the Infrastructure assembly definition and did not yet list the shared script-path assembly that fix: Pause point status, await, and clear find a marker whichever path names the file #3220 added. The asmdef-policy check allows that reference; the test's expectation was updated in the test-only pull request test: Expect the shared script path assembly among the Infrastructure references #3225 (headef9991ce), and the suite was run again on that head: run 37613938244, every leg passed (2022.3, 6000.3, 6000.5, 6000.7, Release code optimization, Concurrency Unit Tests, Coverage trend).8937fd4d(perf: Hot reload reads each compiled assembly at most once per run when it looks for callers #3204 to feat: Write CLI-side vibe log entries for plain tool commands and the hot-reload compile fallback #3212): over 12 consecutive applies to a file with live patches,OtherMsstayed at 1.3–2.1 s (before: 11.3 s climbing to 43.8 s; 410 s in all, now 58 s). A getter-only edit was Applied with no Skipped row. The CS0121 failure was gone. The internal-member reason led with the cause. A one-method edit in a local package reported Patched 1 / Unchanged 19 in both path forms. A reverted file raised no warning. The CLI-side vibe log entries were present. It found that the fallback-decision entry carried a different correlation ID than its request (fixed in fix: Hot reload waits for a busy Editor and applies again instead of compiling #3221).60c9a931(adds chore: Share the script path mapping between hot reload and pause points #3214 to fix: Skipped hot-reload rows name a package script by the path the next reload accepts #3218): enabling a pause point from Release with a./Assets/...path succeeded in 90.8 s, where the previous head failed after 122.5 s. A package script was armed by its package path and by its absolute path, with the sameIdin both. The Skipped row's file name was unchanged on that project because the type lives underAssets/.6e9c8321(adds fix: Hot reload asks for a retry, not a compile, when the Editor was only busy compiling or importing #3219 to fix: Hot reload waits for a busy Editor and applies again instead of compiling #3221): auloop hot-reloadsent while the Editor compiled printed the waiting line, waited 44 s, reportedNothingToApplywithEditorReadyRetryNoteandEditorReadyWaitMs, exit 0, no fallback compile; the same shape reproduced a second time at 46 s. The vibe-log entries of the retry and the fallback decision shared the second request's correlation ID, and a plain apply's four entries shared one ID. Status by absolute path found the marker and a clear by absolute path removed it. It found that afile:package's folder inside the project but outsidePackages/was not matched without a./prefix (fixed in fix: Pause point status, await, and clear find a marker in a local package folder outside Packages #3223).e208b53f(adds fix: Pause point status, await, and clear find a marker in a local package folder outside Packages #3223): status by the project-relative folder path of the local package, without a./prefix, reported Enabled with the asset-pathId, and a clear by the same form removed the marker. No blocker remains from the four heads.