Skip to content

chore: Simplify skill setup synchronization internals - #1588

Merged
hatayama merged 14 commits into
v3-betafrom
refactor/tool-skill-synchronizer-split
Jul 7, 2026
Merged

hatayama merged 14 commits into
v3-betafrom
refactor/tool-skill-synchronizer-split

Conversation

@hatayama

@hatayama hatayama commented Jul 7, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Split the large skill synchronization facade into focused internal classes for target detection, content synchronization, disabled-tool filtering, target installation, and V3 migration skill handling.
  • Keep the setup service entry points stable while adding a pre-start cancellation gate to the remaining async synchronization paths.
  • Move layout-specific tests into a dedicated fixture so synchronizer tests focus on synchronization behavior.

User Impact

  • This is an internal maintenance change; skill setup behavior is intended to remain unchanged.
  • Future changes to setup, migration, and skill installation logic should be easier to review and verify because responsibilities are separated.

Changes

  • Removed test-only wrapper overloads and renamed remaining internal entry points to avoid overload ambiguity.
  • Extracted SkillDirectoryContentSynchronizer, SkillTargetDetector, SkillDisabledToolFilter, SkillTargetInstaller, and V3MigrationSkillInstaller.
  • Moved synchronizer contract structs into a partial type file and reduced the facade to 294 lines.
  • Added CancellationToken ct parameters and start-of-operation cancellation checks for surviving async skill setup methods; loop-internal cancellation remains out of scope for this refactor.
  • Removed an unreachable disabled-tool settings wrapper left behind by the overload cleanup.

Verification

  • dist/darwin-arm64/uloop compile --project-path "$(git rev-parse --show-toplevel)"
  • dist/darwin-arm64/uloop run-tests --project-path "$(git rev-parse --show-toplevel)" --test-mode EditMode --filter-type regex --filter-value '.*(ToolSkillSynchronizerTests|SkillInstallLayoutTests).*'
  • Result: compile errors 0 / warnings 0; tests 57/57 passed

hatayama added 12 commits July 7, 2026 16:31
Drop test-only target detection wrappers so the synchronizer has fewer entry points before class extraction. Update tests to call the explicit project-root overload that preserves the existing freshness-check behavior.
Drop public install wrappers that were only exercised by tests so the synchronizer keeps one explicit install entry point for the setup service. Update tests to pass detected targets and disabled tool inputs directly.
Require callers to pass disabled tool inputs explicitly when installing skill files at a project root. This removes another set of test-only forwarding methods before splitting the synchronizer responsibilities.
Rename internal detection and per-tool install methods so their names describe layout scope and disabled-tool inputs. This removes the remaining overload pressure in ToolSkillSynchronizer without changing public setup APIs.
Move atomic skill file writes, rollback capture, stale file cleanup, and excluded-file checks into SkillDirectoryContentSynchronizer. This isolates the file-content synchronization responsibility before splitting target detection and installation flow.
Move target definitions and install-state detection into SkillTargetDetector. Keep ToolSkillSynchronizer as the setup-facing facade while tests exercise the detector directly.
Move skill-to-tool resolution and disabled-tool checks into SkillDisabledToolFilter. This separates settings-based filtering from the remaining installation orchestration.
Move target-root install, cleanup, deprecated-skill removal, and managed directory pruning into SkillTargetInstaller. This leaves ToolSkillSynchronizer focused on orchestration and result aggregation.
Move temporary v3 migration skill detection, install, removal, and specific-skill helpers into V3MigrationSkillInstaller. Keep ToolSkillSynchronizer as the service-facing facade for migration operations.
Keep the public nested SkillInstallResult and SkillTargetInfo API names unchanged while moving their definitions out of the facade file. This brings ToolSkillSynchronizer under the target size after responsibility extraction.
Add CancellationToken parameters to the remaining skill setup async paths so service-level cancellation reaches Task.Run boundaries. Update direct tests to pass CancellationToken.None through the refactored helpers.
Separate layout and catalog behavior tests from ToolSkillSynchronizerTests so the synchronizer fixture now focuses on synchronization responsibilities after the class split.
@coderabbitai

coderabbitai Bot commented Jul 7, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

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

Next review available in: 5 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

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.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 38334d07-6ecc-4098-9378-e3c649a74409

📥 Commits

Reviewing files that changed from the base of the PR and between 55b1743 and 53c85d9.

📒 Files selected for processing (6)
  • Assets/Tests/Editor/ToolSkillSynchronizerTests.cs
  • Packages/src/Editor/Infrastructure/SkillSetup/SkillDirectoryContentSynchronizer.cs
  • Packages/src/Editor/Infrastructure/SkillSetup/SkillDisabledToolFilter.cs
  • Packages/src/Editor/Infrastructure/SkillSetup/SkillTargetInstaller.cs
  • Packages/src/Editor/Infrastructure/SkillSetup/ToolSkillSynchronizer.cs
  • Packages/src/Editor/Infrastructure/SkillSetup/V3MigrationSkillInstaller.cs
📝 Walkthrough

Walkthrough

This PR refactors ToolSkillSynchronizer into a partial class delegating to new components: SkillTargetDetector, SkillDisabledToolFilter, SkillDirectoryContentSynchronizer, SkillTargetInstaller, and V3MigrationSkillInstaller. CancellationToken support is added to install/remove APIs. Tests are updated and a new test fixture is added.

Changes

Skill Install Pipeline Refactor

Layer / File(s) Summary
Types and target detection
Packages/src/Editor/Infrastructure/SkillSetup/ToolSkillSynchronizer.Types.cs, SkillTargetDetector.cs
Adds SkillInstallResult/SkillTargetInfo structs and SkillTargetDetector with layout-aware detection entry points and install-state resolution.
Disabled tool filtering
Packages/src/Editor/Infrastructure/SkillSetup/SkillDisabledToolFilter.cs
Adds logic to resolve a skill's tool name and check it against the disabled-tools set.
Directory sync and rollback
Packages/src/Editor/Infrastructure/SkillSetup/SkillDirectoryContentSynchronizer.cs
Adds atomic file writing, unexpected-file/empty-directory cleanup, backup snapshotting, and rollback-on-failure.
Install/remove orchestration
Packages/src/Editor/Infrastructure/SkillSetup/SkillTargetInstaller.cs
Adds orchestration for deprecated/disabled directory removal, per-skill syncing, and managed parent directory cleanup.
V3 migration installer
Packages/src/Editor/Infrastructure/SkillSetup/V3MigrationSkillInstaller.cs
Adds install-state lookup and install/remove routines for the temporary v3 migration skill.
Synchronizer refactor and service wiring
Packages/src/Editor/Infrastructure/SkillSetup/ToolSkillSynchronizer.cs, ToolSkillSetupService.cs
Converts ToolSkillSynchronizer to a partial class delegating to the new components, threads CancellationToken through APIs, and updates service call sites.
Existing test migration
Assets/Tests/Editor/ToolSkillSynchronizerTests.cs
Updates tests to call the new components directly with disabledTools/CancellationToken, removing obsolete tests and fixtures.
New layout discovery tests
Assets/Tests/Editor/SkillInstallLayoutTests.cs
Adds a new test fixture covering skill detection, layout filtering, tool description mapping, internal-skill hiding, and content normalization.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • hatayama/unity-cli-loop#980: Refactors the same target detection/installation pipeline so directory cleanup only affects removable managed/deprecated skills, preserving third-party skills.
  • hatayama/unity-cli-loop#1382: Builds on the same V3 migration skill installation pipeline (ToolSkillSynchronizer/V3MigrationSkillInstaller).
  • hatayama/unity-cli-loop#1079: Modifies the same skill setup/synchronization flow around detecting installed targets and filtering disabled tools.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Title check ✅ Passed The title clearly matches the refactor of skill setup synchronization internals.
Description check ✅ Passed The description accurately summarizes the internal refactor, test moves, and cancellation updates in the changeset.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/tool-skill-synchronizer-split

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.

@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.

🧹 Nitpick comments (3)
Assets/Tests/Editor/ToolSkillSynchronizerTests.cs (1)

1655-1681: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated test helper drifting from SkillInstallLayoutTests.cs counterpart.

CreateFakeSourceSkill here has grown a sourceMetaFileRelativePath parameter that the near-identical helper in SkillInstallLayoutTests.cs (Lines 317-338) lacks. Both files also duplicate WriteSkillFile and CreateTemporaryProjectRoot. Consider extracting a shared test fixture/helper class (e.g., under Assets/Tests/Editor/) now that the layout tests were split out, to avoid silent divergence between the two suites going forward.

🤖 Prompt for 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.

In `@Assets/Tests/Editor/ToolSkillSynchronizerTests.cs` around lines 1655 - 1681,
The test helper `CreateFakeSourceSkill` has diverged from its duplicate in
`SkillInstallLayoutTests.cs`, which risks the two suites drifting apart. Update
the shared test support by extracting the duplicated helpers
(`CreateFakeSourceSkill`, `WriteSkillFile`, and `CreateTemporaryProjectRoot`)
into a common editor test utility/fixture under `Assets/Tests/Editor/`, then
have both `ToolSkillSynchronizerTests` and `SkillInstallLayoutTests` use that
shared implementation so the new `sourceMetaFileRelativePath` behavior stays
consistent.
Packages/src/Editor/Infrastructure/SkillSetup/SkillTargetDetector.cs (2)

128-134: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing precondition assert for consistency.

DetectTargetsAcrossLayoutsAtProjectRoot (line 46) and DetectTargetsForLayoutStateAtProjectRoot (line 86) both assert !string.IsNullOrEmpty(projectRoot), but DetectTargetsWithSkillsDirectory skips this check. If called with an empty/null projectRoot, it will silently combine with an empty base path instead of failing fast during development.

🛡️ Proposed fix
 internal static List<ToolSkillSynchronizer.SkillTargetInfo> DetectTargetsWithSkillsDirectory(string projectRoot)
 {
+    Debug.Assert(!string.IsNullOrEmpty(projectRoot), "projectRoot must not be null or empty");
+
     List<ToolSkillSynchronizer.SkillTargetInfo> targets = new();

Based on learnings, this repo follows a contract-programming convention using Debug.Assert to enforce preconditions and fail fast on programmer errors.

🤖 Prompt for 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.

In `@Packages/src/Editor/Infrastructure/SkillSetup/SkillTargetDetector.cs` around
lines 128 - 134, Add the missing precondition assert in
DetectTargetsWithSkillsDirectory to match the contract-programming pattern used
by DetectTargetsAcrossLayoutsAtProjectRoot and
DetectTargetsForLayoutStateAtProjectRoot. Before using projectRoot in the
Path.Combine logic, assert that it is not null or empty with Debug.Assert so the
method fails fast on invalid input instead of silently proceeding with an empty
base path.

Source: Learnings


42-78: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove DetectTargetsAcrossLayoutsAtProjectRoot if it’s no longer used. No call sites remain in Packages/src, so this looks like dead code after the refactor.

🤖 Prompt for 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.

In `@Packages/src/Editor/Infrastructure/SkillSetup/SkillTargetDetector.cs` around
lines 42 - 78, Remove the now-unused DetectTargetsAcrossLayoutsAtProjectRoot
method from SkillTargetDetector, since there are no remaining call sites in
Packages/src after the refactor. Verify any related references in
ToolSkillSynchronizer or SkillInstallLayout are not relying on it, and delete
the dead code rather than keeping an unused helper around.
🤖 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.

Nitpick comments:
In `@Assets/Tests/Editor/ToolSkillSynchronizerTests.cs`:
- Around line 1655-1681: The test helper `CreateFakeSourceSkill` has diverged
from its duplicate in `SkillInstallLayoutTests.cs`, which risks the two suites
drifting apart. Update the shared test support by extracting the duplicated
helpers (`CreateFakeSourceSkill`, `WriteSkillFile`, and
`CreateTemporaryProjectRoot`) into a common editor test utility/fixture under
`Assets/Tests/Editor/`, then have both `ToolSkillSynchronizerTests` and
`SkillInstallLayoutTests` use that shared implementation so the new
`sourceMetaFileRelativePath` behavior stays consistent.

In `@Packages/src/Editor/Infrastructure/SkillSetup/SkillTargetDetector.cs`:
- Around line 128-134: Add the missing precondition assert in
DetectTargetsWithSkillsDirectory to match the contract-programming pattern used
by DetectTargetsAcrossLayoutsAtProjectRoot and
DetectTargetsForLayoutStateAtProjectRoot. Before using projectRoot in the
Path.Combine logic, assert that it is not null or empty with Debug.Assert so the
method fails fast on invalid input instead of silently proceeding with an empty
base path.
- Around line 42-78: Remove the now-unused
DetectTargetsAcrossLayoutsAtProjectRoot method from SkillTargetDetector, since
there are no remaining call sites in Packages/src after the refactor. Verify any
related references in ToolSkillSynchronizer or SkillInstallLayout are not
relying on it, and delete the dead code rather than keeping an unused helper
around.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0f99c3c2-1765-4f25-8ba6-c717ee2a6962

📥 Commits

Reviewing files that changed from the base of the PR and between 5dac688 and 55b1743.

⛔ Files ignored due to path filters (7)
  • Assets/Tests/Editor/SkillInstallLayoutTests.cs.meta is excluded by none and included by none
  • Packages/src/Editor/Infrastructure/SkillSetup/SkillDirectoryContentSynchronizer.cs.meta is excluded by none and included by none
  • Packages/src/Editor/Infrastructure/SkillSetup/SkillDisabledToolFilter.cs.meta is excluded by none and included by none
  • Packages/src/Editor/Infrastructure/SkillSetup/SkillTargetDetector.cs.meta is excluded by none and included by none
  • Packages/src/Editor/Infrastructure/SkillSetup/SkillTargetInstaller.cs.meta is excluded by none and included by none
  • Packages/src/Editor/Infrastructure/SkillSetup/ToolSkillSynchronizer.Types.cs.meta is excluded by none and included by none
  • Packages/src/Editor/Infrastructure/SkillSetup/V3MigrationSkillInstaller.cs.meta is excluded by none and included by none
📒 Files selected for processing (10)
  • Assets/Tests/Editor/SkillInstallLayoutTests.cs
  • Assets/Tests/Editor/ToolSkillSynchronizerTests.cs
  • Packages/src/Editor/Infrastructure/SkillSetup/SkillDirectoryContentSynchronizer.cs
  • Packages/src/Editor/Infrastructure/SkillSetup/SkillDisabledToolFilter.cs
  • Packages/src/Editor/Infrastructure/SkillSetup/SkillTargetDetector.cs
  • Packages/src/Editor/Infrastructure/SkillSetup/SkillTargetInstaller.cs
  • Packages/src/Editor/Infrastructure/SkillSetup/ToolSkillSetupService.cs
  • Packages/src/Editor/Infrastructure/SkillSetup/ToolSkillSynchronizer.Types.cs
  • Packages/src/Editor/Infrastructure/SkillSetup/ToolSkillSynchronizer.cs
  • Packages/src/Editor/Infrastructure/SkillSetup/V3MigrationSkillInstaller.cs

@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 17 files

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

Re-trigger cubic

Comment thread Packages/src/Editor/Infrastructure/SkillSetup/V3MigrationSkillInstaller.cs Outdated
hatayama added 2 commits July 7, 2026 17:39
Delete GetCurrentDisabledTools after the synchronizer facade no longer calls it, keeping the extracted filter free of unreachable wrapper code.
Poll the synchronization CancellationToken inside target and file loops so a started sync can stop before continuing writes or deletes. Also fail fast when the packaged V3 migration skill source declares an unexpected skill name.
@hatayama
hatayama merged commit fd9f989 into v3-beta Jul 7, 2026
10 checks passed
@hatayama
hatayama deleted the refactor/tool-skill-synchronizer-split branch July 7, 2026 08:58
hatayama added a commit that referenced this pull request Aug 11, 2026
- The skill target example named Cursor, which was removed as a target
  in #1983; use Codex CLI, a target that actually exists.
- The naming-debt list cited ToolSkillSynchronizer.SkillTargetDefinition,
  which no longer exists: #1588 moved it into SkillTargetDetector as a
  private struct, so it is not a public identifier kept by policy.
- The complexity threshold is declared in three places, not two: the
  code-complexity workflow's artifact step hardcodes --max-complexity 15
  and bypasses check-code-complexity.sh entirely.
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