Skip to content

fix: Detect V2 Unity projects with file:/embedded package references or ambiguous git cache generations - #1847

Merged
hatayama merged 1 commit into
v3-betafrom
feature/v3-dispatcher-v2-detection-hardening
Jul 19, 2026
Merged

hatayama merged 1 commit into
v3-betafrom
feature/v3-dispatcher-v2-detection-hardening

Conversation

@hatayama

@hatayama hatayama commented Jul 19, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Existing V2 (uloop V1/V2 era) Unity projects that reference the package via a file: path, embed it directly under Packages/, or resolve it through a git dependency with multiple cached generations were misdetected as V3 and hit confusing pin-resolution errors instead of being delegated to the V2 CLI.
  • The dispatcher now reads the package's own package.json (name + version) directly from disk for these on-disk layouts, so detection works immediately for every existing V2 project without requiring any V2-side release.

User Impact

  • Before: file:-referenced and embedded V2 packages were not recognized as V2 at all, so commands fell through to the V3 pin-resolution path and failed with an unrelated internal error. A git-dependency project with multiple cached package generations always hit a hard "multiple package generations found" error, even when packages-lock.json already recorded which generation was actually resolved.
  • After: all three layouts are correctly detected as V2 and delegated to the matching V2 CLI version (uloop: executing in V2 mode). When multiple generations are genuinely ambiguous, the guidance now differs by cause: PackageCache ambiguity still suggests reopening Unity to refresh the lock, while duplicate embedded package directories are told to remove the duplicates instead (refreshing the lock cannot fix that case).

Changes

  • Resolve file: manifest dependency values against Packages/ (normalizing \ to / first for Windows-authored manifests) and read the target package.json directly when the lock has no usable version for it.
  • Scan Packages/ for embedded packages when manifest.json has no dependency entry at all, matching by package.json name rather than directory naming.
  • Disambiguate multiple cached git package generations by matching packages-lock.json's resolved commit hash as a prefix of each PackageCache directory's suffix (verified against a real example already present in this repository's own Packages/packages-lock.json / Library/PackageCache).
  • Detection priority is unchanged where it already worked: a valid semver in packages-lock.json still wins first; the new disk-based and hash-based paths only apply where the previous heuristics had no answer.
  • No change to protocolVersion / CliConstants.REQUIRED_CLI_PROTOCOL_VERSION — this only changes how the dispatcher classifies a project locally; the IPC wire format between the CLI and Unity package is untouched.

Verification

  • go test ./internal/dispatcher/... in cli/dispatcher: all detection/dispatch tests pass, including new cases for file: references, embedded packages, embedded-ambiguity guidance, and git-hash disambiguation (including a non-default suffix length case).
  • scripts/check-go-cli.sh: fmt/vet/lint/test pass for cli/common, cli/release-automation, and cli/project-runner; verify-go-cli-dist.sh (native binary build) passes. One unrelated pre-existing failure, TestCommandHelpUsesWatchToolSchemaForDefaultWatchCommands in cli/dispatcher, was confirmed to reproduce identically on origin/v3-beta before this change (verified via git stash) and is unaffected by this PR.
  • Manual verification: built the dev binary (dist/darwin-arm64/uloop) and ran it against disposable Unity project layouts using the real V2 package.json (io.github.hatayama.uloopmcp 2.2.0, from origin/main) as a file: reference and as an embedded package under Packages/. Both reached uloop: executing in V2 mode; the same binary built from before this change failed both with an unrelated internal pin-resolution error.

Review in cubic

…uous-cache layouts

The V3 dispatcher's V2 detection relied on manifest.json + packages-lock.json +
PackageCache heuristics, which missed file: references, embedded packages
(no manifest.json entry at all), and left git-dependency PackageCache
ambiguity unresolved even though packages-lock.json records a git hash.

Since Unity loads file:/embedded packages directly from their on-disk
directory rather than a PackageCache mirror, that directory's own
package.json (name + version) is the authoritative source for those
layouts, while registry/git dependencies keep using the resolved lock
version as before. This requires no V2-side release and fixes detection
for every existing V2 project immediately.

- Resolve file: manifest dependencies against Packages/ (normalizing
  backslashes for Windows-authored manifests) and read the target
  package.json directly when the lock has no usable version.
- Scan Packages/ for embedded packages when manifest.json has no
  dependency entry at all; flag multi-candidate embedded matches
  distinctly so recovery guidance can point at removing duplicate
  directories instead of refreshing packages-lock.json.
- Disambiguate multiple cached git package generations by matching
  packages-lock.json's resolved commit hash as a prefix of each
  PackageCache directory's suffix.
@coderabbitai

coderabbitai Bot commented Jul 19, 2026 •

Copy link
Copy Markdown
Contributor

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: 96750b90-0f06-496f-818e-7a39fce14e82

📥 Commits

Reviewing files that changed from the base of the PR and between 8454000 and 61b0a74.

📒 Files selected for processing (3)
  • cli/dispatcher/internal/dispatcher/dispatcher_v2_detect.go
  • cli/dispatcher/internal/dispatcher/dispatcher_v2_detect_test.go
  • cli/dispatcher/internal/dispatcher/dispatcher_v2_run.go

📝 Walkthrough

Walkthrough

V2 dispatcher detection now resolves file: dependencies, embedded packages, and PackageCache generations. It validates package names and versions, disambiguates cache entries using lockfile Git hashes, tracks embedded-package ambiguity, and emits matching recovery guidance.

Changes

Unity V2 detection and guidance

Layer / File(s) Summary
Embedded and file-based package detection
cli/dispatcher/internal/dispatcher/dispatcher_v2_detect.go, cli/dispatcher/internal/dispatcher/dispatcher_v2_detect_test.go
Detection reads dispatcher package metadata from file: targets and embedded Packages/ directories, handles Windows paths, excludes V3 packages, and records ambiguous V2 candidates.
PackageCache hash disambiguation
cli/dispatcher/internal/dispatcher/dispatcher_v2_detect.go, cli/dispatcher/internal/dispatcher/dispatcher_v2_detect_test.go
PackageCache entries retain directory suffixes and match packages-lock.json Git hash prefixes to select a resolved V2 version, with candidate fallback when no hash matches.
Ambiguity state and recovery guidance
cli/dispatcher/internal/dispatcher/dispatcher_v2_run.go, cli/dispatcher/internal/dispatcher/dispatcher_v2_detect_test.go
Ambiguous embedded packages produce duplicate-directory recovery guidance instead of PackageCache lockfile guidance, while preventing delegation.

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

Sequence Diagram(s)

sequenceDiagram
  participant UnityProject
  participant DispatcherDetector
  participant PackageMetadata
  participant DispatcherRunner
  UnityProject->>DispatcherDetector: Provide manifest, Packages, PackageCache, and lockfile
  DispatcherDetector->>PackageMetadata: Read package names and versions
  PackageMetadata-->>DispatcherDetector: Return V2 candidates and ambiguity state
  DispatcherDetector-->>DispatcherRunner: Return detected project metadata
  DispatcherRunner-->>UnityProject: Emit version or embedded-duplication guidance
Loading

Possibly related issues

  • hatayama/unity-cli-loop issue 1806: The PackageCache hash-prefix disambiguation and related regression coverage directly implement this issue’s objective.

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: improved V2 Unity project detection for file, embedded, and git cache cases.
Description check ✅ Passed The description is directly related and accurately explains the detection hardening, user impact, changes, and verification.
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.
✨ 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/v3-dispatcher-v2-detection-hardening

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 85509a8 into v3-beta Jul 19, 2026
11 checks passed
@hatayama
hatayama deleted the feature/v3-dispatcher-v2-detection-hardening branch July 19, 2026 09:13
@github-actions github-actions Bot mentioned this pull request Jul 19, 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