Skip to content

fix: Hot reload without --files no longer skips added methods because another file only adds enum members - #3034

Merged
hatayama merged 4 commits into
mainfrom
fix/hot-reload-default-selection-enum-only
Sep 30, 2026
Merged

hatayama merged 4 commits into
mainfrom
fix/hot-reload-default-selection-enum-only

Conversation

@hatayama

@hatayama hatayama commented Sep 29, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • When uloop hot-reload runs without --files and the selected files include one whose only change adds enum members, the reload now leaves that file out on its own. The added methods in the other files that pass the enum to compiled code or to an introduced type then apply instead of being skipped.

User Impact

  • Before: those added methods were reported as Skipped, and the response told the caller to rerun with the enum file left out.
  • After: they apply in the same run. A Warnings line names the left-out file and the enum members that still need uloop compile.
  • Explicit --files runs are unchanged.
  • A file that already holds active patches, or that declares a new type, stays in the reload.
  • In Edit Mode with --compile-on-skip auto, this case no longer triggers the compile fallback, because nothing the run was asked to apply stays unapplied. The enum members wait for the next compile, and the existing enum-member warning stays.

Changes

  • Worker: when an added method's body binds a compiled signature, the skip reason now also lists the run's files that build the split type from source (splitSourceFiles). Other reasons leave it null. The JSON only passes between the Editor and its own worker process, so the protocol version does not change.
  • The default selection marks the files it chose. Siblings that a run pulls in, and explicit --files inputs, stay unmarked.
  • After the first transform run of a group, a marked file is left out only when all of these hold:
    • its change adds nothing but enum members;
    • it holds no active patch;
    • it declares no new type;
    • a top-level skip row names it as a source-side file: the declaringFiles of the compiled-type row, or the splitSourceFiles of the compiled-signature row.
  • The worker then reruns once without the left-out files.
    • The left-out file keeps its first-pass per-file notices, gets one left-out warning, and reports as unapplied.
    • Results go back in the group's file order.
  • The set of files with active patches is read when the group starts, while the run is still on the main thread.
  • Docs: the scope-and-limits and output references of the hot-reload skill. The generated copies are regenerated.

Verification

  • uloop compile: 0 errors.
  • New tests: 25 classifier tests, 12 group-processor leave-out tests, 3 end-to-end tests.
  • Existing classes:
    • HotReloadGroupProcessorTests: 47/47.
    • HotReloadOrchestratorTests: 171/171.
    • HotReloadCarriedInNextStepE2ETests and TransformWorkerBindingSplitTests, run together with the new end-to-end tests: 19/19.
    • HotReloadIntroducedTypeNewFileSiblingE2ETests and HotReloadIntroducedTypeAddedMemberHintE2ETests: 10/10.
    • HotReloadSkippedNextStepResolverTests, HotReloadDefaultFileSelectorDuplicateTests, HotReloadDefaultFileSelectorKindTests and HotReloadDefaultFilesTests pass.
  • Mutations: each of these fails the expected tests:
    • removing any one classifier condition;
    • breaking the splice order;
    • ignoring the selection flag;
    • removing the worker's collection of the source-side files;
    • giving the rerun the first run's input.
  • File length and complexity checks are clean. check-skill-size and sync-tool-docs --check pass.

Closes #2968

Review in cubic

The skip reason for an added method whose body binds a compiled signature
named only the files of the compiled API, which the Editor places from the
compiled assembly's debug data. Nothing told the Editor which of the run's
own files built the split type from source, so it could not tell which
file to leave out. A default-selection run needs exactly that to drop a
file whose only edit adds enum members (#2968).

- Collect the source copy's files for the same-assembly split the same way
  the introduced-type split already does, and report them on that reason
  as splitSourceFiles; every other reason leaves the field null.
- The Editor compiles the worker from source at run time and the JSON only
  passes between the Editor and its own worker process, so no protocol
  version changes.
With --files omitted, the default selection could pick up a file whose
only edit adds enum members. Keeping it made the worker build the enum
from source, so the added methods of other files that pass the enum to
compiled code or an introduced type were skipped, and the response asked
the caller to rerun with that file left out (#2968). A default selection
is the tool's own choice, so the tool now leaves the file out itself.

- The selection marks the files it chose; siblings a run pulls in and
  every explicit --files input stay unmarked, so explicit runs keep their
  behavior.
- After the first transform, a marked file is left out only when its edit
  adds nothing but enum members, it holds no active patch, it declares no
  new type, and a skip row for a compiled type or a compiled signature
  names it as a file that builds the split from source.
- The left-out file keeps its first-pass notices, gets one warning naming
  the enum members that still need uloop compile, and reports as
  unapplied; the worker reruns once without it and the results go back
  in the group's order.
- The active set is read when the group starts, while the run is still on
  the main thread, because the patch ledgers must not be read after the
  worker await.
- In Edit Mode, --compile-on-skip auto no longer compiles for this case:
  the other files apply, so nothing unapplied remains.

Tests cover the classifier conditions one by one, the group split and
splice, a failed or canceled rerun, and three end-to-end runs; mutating
each condition fails the tests that name it.
The enum paragraph of the scope reference still implied that an enum
member added beside other edits always blocks the added members that use
it, which is no longer true when --files is omitted: the reload now
leaves an enum-only file out and applies the other files. The paragraph
states that, what the Warnings line names, and that a file with active
patches or a new type stays in; the output reference lists the left-out
entry among the Warnings kinds. SKILL.md is unchanged, and the generated
copies are regenerated from the sources.
@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Repository: hatayama/unity-cli-loop/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: eec0d1da-149e-4fd3-aa2c-d3ec59413cd1

📥 Commits

Reviewing files that changed from the base of the PR and between b042f96 and 2dea8cc.

⛔ Files ignored due to path filters (6)
  • Assets/Tests/Editor/HotReload/HotReloadDefaultFileSelectorKindTests.cs.meta is excluded by none and included by none
  • Assets/Tests/Editor/HotReload/HotReloadDefaultSelectionEnumLeaveOutE2ETests.cs.meta is excluded by none and included by none
  • Assets/Tests/Editor/HotReload/HotReloadEnumMemberOnlyLeaveOutTests.cs.meta is excluded by none and included by none
  • Assets/Tests/Editor/HotReload/HotReloadGroupProcessorLeaveOutTests.cs.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadEnumMemberOnlyLeaveOut.cs.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadGroupLeaveOutSplit.cs.meta is excluded by none and included by none
📒 Files selected for processing (17)
  • .agents/skills/uloop-hot-reload/references/output.md
  • .agents/skills/uloop-hot-reload/references/scope-and-limits.md
  • .claude/skills/uloop-hot-reload/references/output.md
  • .claude/skills/uloop-hot-reload/references/scope-and-limits.md
  • Assets/Tests/Editor/HotReload/HotReloadDefaultFilesTests.cs
  • Assets/Tests/Editor/HotReload/HotReloadServicesTestScope.cs
  • Assets/Tests/Editor/HotReload/TransformWorkerBindingSplitTests.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadDefaultFileSelection.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadGroupFile.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadGroupProcessor.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadOrchestrator.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadTools.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/Shared/TransformWorkerDtos.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/Skill/references/output.md
  • Packages/src/Editor/FirstPartyTools/HotReload/Skill/references/scope-and-limits.md
  • Packages/src/Editor/FirstPartyTools/HotReload/TransformWorker~/CompiledSignatureSplitCollector.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/TransformWorker~/MethodTransformDecider.cs
 _______________________________________________________________
< You're one `console.log` away from enlightenment. Keep going. >
 ---------------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: hatayama/unity-cli-loop/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: c0d3a5b2-08cb-4c42-99fa-1bb996c3ea01

📥 Commits

Reviewing files that changed from the base of the PR and between 143838a and b042f96.

⛔ Files ignored due to path filters (6)
  • Assets/Tests/Editor/HotReload/HotReloadDefaultFileSelectorKindTests.cs.meta is excluded by none and included by none
  • Assets/Tests/Editor/HotReload/HotReloadDefaultSelectionEnumLeaveOutE2ETests.cs.meta is excluded by none and included by none
  • Assets/Tests/Editor/HotReload/HotReloadEnumMemberOnlyLeaveOutTests.cs.meta is excluded by none and included by none
  • Assets/Tests/Editor/HotReload/HotReloadGroupProcessorLeaveOutTests.cs.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadEnumMemberOnlyLeaveOut.cs.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadGroupLeaveOutSplit.cs.meta is excluded by none and included by none
📒 Files selected for processing (25)
  • .agents/skills/uloop-hot-reload/references/output.md
  • .agents/skills/uloop-hot-reload/references/scope-and-limits.md
  • .claude/skills/uloop-hot-reload/references/output.md
  • .claude/skills/uloop-hot-reload/references/scope-and-limits.md
  • Assets/Tests/Editor/HotReload/HotReloadDefaultFileSelectorKindTests.cs
  • Assets/Tests/Editor/HotReload/HotReloadDefaultFilesTests.cs
  • Assets/Tests/Editor/HotReload/HotReloadDefaultSelectionEnumLeaveOutE2ETests.cs
  • Assets/Tests/Editor/HotReload/HotReloadEnumMemberOnlyLeaveOutTests.cs
  • Assets/Tests/Editor/HotReload/HotReloadGroupProcessorLeaveOutTests.cs
  • Assets/Tests/Editor/HotReload/HotReloadServicesTestScope.cs
  • Assets/Tests/Editor/HotReload/TransformWorkerBindingSplitTests.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadDefaultFileSelection.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadEnumMemberOnlyLeaveOut.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadGroupFile.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadGroupLeaveOutSplit.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadGroupProcessor.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadOrchestrator.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/HotReloadTools.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/IHotReloadOrchestrator.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/Shared/TransformWorkerDtos.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/Skill/references/output.md
  • Packages/src/Editor/FirstPartyTools/HotReload/Skill/references/scope-and-limits.md
  • Packages/src/Editor/FirstPartyTools/HotReload/TransformWorker~/CompiledSignatureSplitCollector.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/TransformWorker~/MethodTransformDecider.cs
  • Packages/src/Editor/FirstPartyTools/HotReload/TransformWorker~/WorkerReason.cs

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

Default hot reload now tracks whether files were selected implicitly. When an eligible enum-member-only file contributes to a split-type skip, the processor leaves it out, retries the other files, and reports a warning for the omitted file.

Changes

Default-selection enum-file reload

Layer / File(s) Summary
Track default file selection
Packages/src/Editor/FirstPartyTools/HotReload/HotReloadDefaultFileSelection.cs, Packages/src/Editor/FirstPartyTools/HotReload/IHotReloadOrchestrator.cs, Packages/src/Editor/FirstPartyTools/HotReload/HotReloadOrchestrator.cs, Packages/src/Editor/FirstPartyTools/HotReload/HotReloadTools.cs, Packages/src/Editor/FirstPartyTools/HotReload/HotReloadGroupFile.cs, Assets/Tests/Editor/HotReload/HotReloadDefaultFileSelectorKindTests.cs, Assets/Tests/Editor/HotReload/HotReloadDefaultFilesTests.cs, Assets/Tests/Editor/HotReload/HotReloadServicesTestScope.cs
The selector marks explicit-file selections as non-default and changed-file selections as default. The tool and orchestrator pass that status to group files. Tests cover selection and propagation.
Report split source paths
Packages/src/Editor/FirstPartyTools/HotReload/Shared/TransformWorkerDtos.cs, Packages/src/Editor/FirstPartyTools/HotReload/TransformWorker~/CompiledSignatureSplitCollector.cs, Packages/src/Editor/FirstPartyTools/HotReload/TransformWorker~/WorkerReason.cs, Packages/src/Editor/FirstPartyTools/HotReload/TransformWorker~/MethodTransformDecider.cs, Assets/Tests/Editor/HotReload/TransformWorkerBindingSplitTests.cs
The worker reports source files for split types separately from files declaring compiled APIs. A test checks both path fields in a compiled-signature skip reason.
Select and partition enum-only files
Packages/src/Editor/FirstPartyTools/HotReload/HotReloadEnumMemberOnlyLeaveOut.cs, Packages/src/Editor/FirstPartyTools/HotReload/HotReloadGroupLeaveOutSplit.cs, Assets/Tests/Editor/HotReload/HotReloadEnumMemberOnlyLeaveOutTests.cs
The leave-out helper selects eligible default-selected, inactive files with only added enum members when supported split reasons name them. Retry input omits those paths, and group results retain their original order.
Retry remaining group and combine results
Packages/src/Editor/FirstPartyTools/HotReload/HotReloadGroupProcessor.cs, Assets/Tests/Editor/HotReload/HotReloadGroupProcessorLeaveOutTests.cs, Assets/Tests/Editor/HotReload/HotReloadDefaultSelectionEnumLeaveOutE2ETests.cs, .agents/skills/uloop-hot-reload/references/*, .claude/skills/uloop-hot-reload/references/*, Packages/src/Editor/FirstPartyTools/HotReload/Skill/references/*
The processor retries the worker with eligible files removed, applies the retry output, and combines it with first-run results for omitted files. Tests cover retry outcomes. Skill references describe the behavior and warning.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant HotReloadTools
  participant HotReloadOrchestrator
  participant HotReloadGroupProcessor
  participant TransformWorker
  participant ApplyGate
  HotReloadTools->>HotReloadOrchestrator: pass selected files and default-selection status
  HotReloadOrchestrator->>HotReloadGroupProcessor: process group files
  HotReloadGroupProcessor->>TransformWorker: run first transform
  TransformWorker-->>HotReloadGroupProcessor: return split reasons and file results
  HotReloadGroupProcessor->>TransformWorker: retry with eligible enum files removed
  TransformWorker-->>HotReloadGroupProcessor: return retry results
  HotReloadGroupProcessor->>ApplyGate: apply retry output
  HotReloadGroupProcessor-->>HotReloadOrchestrator: combine retry and left-out file results
Loading

Merge Risk: ⚪ Minimal · up to b042f

Default hot reload now leaves out enum-only files that would block other changes, and warns that those enum members still need a compile. Explicit file runs are unchanged. No actionable merge-blocking risk was identified in the supplied change.

Security Architecture Review

Security architecture risk: 🔵 Low · up to b042f

The retry remains within the existing hot-reload operation and retains checks before applying code. No security boundary bypass was identified. One concurrency question remains about whether another run can change patch ownership while the retry decision is in progress.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The changed retry is subtractive over files already admitted to a local Editor hot-reload group; the inspected path does not add a service, credential, tenant boundary, or new file input.

Trust Boundaries and Controls

  • observed — Caller-provided explicit paths do not receive default-selection provenance. Worker-supplied source-side paths alone cannot cause leave-out: the candidate must be a selected group file satisfying the active-ownership and enum-only checks.

Resilience and Maintainability Implications

  • inferred — Active ownership is checked from a snapshot taken before asynchronous preparation and transformation. Groups are sequential within one run, but the inspected code does not establish whether overlapping runs are serialized or ownership is rechecked before omission.

Hardening Proposals

  • proposed — Establish the cross-run serialization contract or revalidate active ownership immediately before leave-out selection so the inactive-file decision remains valid across worker awaits.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.24% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 116 functions across 19 files. (6 skipped… 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 describes the main change: default hot reload no longer skips added methods when another selected file only adds enum members.
Description check ✅ Passed The description directly explains the behavior change, implementation conditions, user impact, documentation updates, and verification results.
Linked Issues check ✅ Passed The changes implement #2968. Default file selection now marks omitted-file runs, carries split source files from the worker, identifies eligible enum-member-only files, retries without those files, an…
Out of Scope Changes check ✅ Passed The changed production code, tests, worker metadata, and hot-reload documentation support #2968. The documentation updates describe the new omitted-file warning and compile fallback. No unrelated chan…
Full details: Docstring Coverage

Explanation

Docstring coverage is 42.24% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 116 functions across 19 files. (6 skipped: 6 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

@hatayama
hatayama merged commit 63bbefa into main Sep 30, 2026
15 of 16 checks passed
@hatayama
hatayama deleted the fix/hot-reload-default-selection-enum-only branch September 30, 2026 00:11
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.

hot-reload: default file selection picks an enum-member-only file and then skips its users

1 participant