Skip to content

chore: bump version to 9.4.7#808

Merged
github-actions[bot] merged 57 commits intomainfrom
release/v9.4.7
Feb 21, 2026
Merged

chore: bump version to 9.4.7#808
github-actions[bot] merged 57 commits intomainfrom
release/v9.4.7

Conversation

@github-actions
Copy link
Contributor

Automated version bump to 9.4.7.

actions-user and others added 30 commits February 15, 2026 16:33
…39178995

chore: sync main (v9.4.6) into beta
* Fix UnityEvent wiring via manage_components set_property (#631)

UnityEventBase-derived fields set via reflection create disconnected
objects that Unity's serialization layer doesn't track, causing
m_PersistentCalls to be empty on save. Route these types through
SerializedObject/SerializedProperty instead.

Adds recursive SerializedProperty setter supporting Generic structs,
arrays, ObjectReference, and leaf types (int, bool, float, string, enum).
Includes fuzzy child property matching to handle batch_execute stripping
underscores from nested JSON keys (tracked in #756).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Fix batch_execute mangling nested value keys (#756)

batch_execute NormalizeParameterKeys recursively converted all JSON
keys to camelCase, including nested value data like Unity serialized
property paths (m_PersistentCalls to mPersistentCalls). This broke
UnityEvent wiring and any tool receiving structured nested data through
batch_execute. Stop recursing into values -- only normalize top-level
parameter keys.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Guard against null value in SerializedProperty string setter

Address Sourcery review: check value == null before accessing
value.Type to prevent NullReferenceException in the string case of
SetSerializedPropertyRecursive.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
…5939238

chore: update Unity package to beta version 9.4.7-beta.2
* Sync claude-nl-suite workflow with proven main version

* Fix preflight sys.path under Server working directory
…) (#762)

* Fix read_console reflection crash on Unity 6.5 and batch-mode test crash (#761)

- Remove unused LogEntry.instanceID reflection that fatally blocked
  read_console initialization on Unity 6000.5.0a6
- Skip Collider.GeometryHolder in GameObjectSerializer to prevent
  native PhysX SEGV in batch-mode test runs
- Fix CodexConfigHelperTests to work with both release and prerelease
  package versions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add com.unity.test-framework as package dependency

The package has a hard compile dependency on Test Framework
(RunTests, TestJobManager, TestRunnerService, etc.) but did not
declare it in package.json. Projects without Test Framework
installed would get CS0234/CS0246 errors on import.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address review: dispose SerializedObject, fix null stringValue, remove dead method

- Wrap SerializedObject in using block in SetViaSerializedProperty
- Use string.Empty instead of null for SerializedProperty.stringValue
- Remove unused GetRemappedTypeForFiltering from ReadConsole

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…7760337

chore: update Unity package to beta version 9.4.7-beta.3
…fallback (#765) (#766)

* Fix misleading 'Property not found' error for conversion failures and add SerializedProperty fallback (#765)

When setting component properties via reflection failed (e.g. array types,
UdonSharp proxies), the error message falsely reported "Property 'X' not
found. Did you mean: X?" — even though the property existed. The root cause
was that SetProperty returned a bare bool with no error detail, so the caller
interpreted every failure as "not found."

Changes:
- GameObjectComponentHelpers.SetProperty now returns error details via out
  parameter, distinguishing conversion failures from missing properties
- ComponentOps.SetProperty falls back to SetViaSerializedProperty when
  reflection-based conversion fails, handling arrays and custom serialization
- GameObjectComponentHelpers falls back to ComponentOps.SetProperty when its
  local reflection fails, gaining the same SerializedProperty support

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Include token context in SetProperty error message for debuggability

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Remove redundant local SetProperty; delegate to ComponentOps directly

Address CodeRabbit review feedback:
- Remove duplicated reflection logic from GameObjectComponentHelpers
- Route non-nested property paths directly through ComponentOps.SetProperty
- Add out string error to SetNestedProperty for proper error propagation
- Fix MaterialOps.TrySetShaderProperty call to set error on failure

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix empty array error message and support [SerializeField] in nested paths

Address CodeRabbit review round 2:
- Handle empty arrays/lists separately to avoid nonsensical "out of range (0--1)"
- Add [SerializeField] private field lookup for final segment of nested paths
- Expose FindSerializedFieldInHierarchy as internal for cross-class reuse

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…4680294

chore: update Unity package to beta version 9.4.7-beta.4
…arm (#760)

When the uvx cache already has the package, pass --offline to skip the
network dependency check that can hang for 30+ seconds on poor connections.
A lightweight probe (uvx --offline ... --help) with a 3-second timeout
determines cache warmth before building the command.

Also fixes stale LogAssert expectations in SetComponentProperties test
to match current error message format from ComponentOps refactor.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract GetUvxDevFlags() and GetUvxDevFlagsList() helpers to
AssetPathUtility, replacing duplicated if/else if/else blocks
across 6 call sites. Add 30-second TTL cache to ShouldUseUvxOffline()
to avoid redundant subprocess spawns. Simplify
ConfigureWithCapturedValues signature from two bools to a single
pre-captured flags string.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…resh calls

Address CodeRabbit nitpicks: relocate static cache fields above the
methods that use them for readability, extract GetCachedOfflineProbeResult()
so GetUvxDevFlags()/GetUvxDevFlagsList() evaluate ShouldForceUvxRefresh()
only once per call instead of twice.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When HTTP transport is enabled, skip Configure() for clients that
do not support HTTP (e.g., Claude Desktop). Previously this threw
and logged a spurious warning on every editor launch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add --offline to uvx launches for faster startup (#760)
…6530970

chore: update Unity package to beta version 9.4.7-beta.5
… (#770)

Unity internal LogEntry type does not expose timestamp data via
reflection, so the parameter was accepted but silently did nothing.
Remove it from Python, C#, and tool reference docs.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…6967023

chore: update Unity package to beta version 9.4.7-beta.6
…ion (#772)

Any tool call can now include a unity_instance parameter to route that
specific call to a target Unity instance without changing the session
default and without requiring a set_active_instance call first.

The middleware pops unity_instance from tool call arguments before
Pydantic validation runs, resolves it (port number, hash prefix, or
Name@hash), and injects it into request-scoped state for that call only.

- Port numbers resolve to the matching Name@hash via status file lookup
  rather than synthetic direct:{port} IDs, so the transport layer can
  route them correctly
- HTTP mode rejects port-based targeting with a clear error
- set_active_instance now also accepts port numbers for consistency
- Multi-instance scenarios log available instances with ports when
  auto-select cannot choose
- _discover_instances() helper DRYs up transport-aware instance
  discovery previously duplicated across the codebase
- Server instructions updated to document both routing approaches
- 18 new tests covering pop behaviour, per-call vs session routing,
  port resolution, transport modes, and edge cases

Closes #697

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…9509793

chore: update Unity package to beta version 9.4.7-beta.7
…cOS (#783)

* Fix focus nudge launching Electron instead of restoring VS Code on macOS

The focus restore used process name (e.g. "Electron") which caused macOS
to launch a standalone Electron instance instead of returning to VS Code.
Now captures bundle identifier and uses `tell application id` for precise
activation, falling back to name-based activation if bundle ID fails.

Fixes #699

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address review feedback: guard AppleScript missing value, fix escaping, improve logging

- Guard AppleScript against `missing value` bundle identifier that would crash
  osascript and silently disable the entire nudge cycle (CodeRabbit)
- Also filter "missing value" string on the Python side as belt-and-suspenders
  (Sourcery)
- Fix AppleScript string escaping: use "" (AppleScript convention) not \"
  (Python convention) for both bundle_id and app_name (CodeRabbit)
- Log AppleScript stderr when bundle_id activation fails (Sourcery)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…7691143

chore: update Unity package to beta version 9.4.7-beta.8
…ad (#787)

* Fix StdioBridgeHost zombie state after domain reload (#785)

After domain reload, the bridge could accept TCP connections but never
process commands. Three defensive fixes address the plausible failure
vectors:

1. Stale client cleanup: when a new client connects, close all other
   active clients (in stdio there is only one server). Forces hung
   ReadFrameAsUtf8Async to throw and exit cleanly.

2. ProcessCommands self-healing: track consecutive TCS timeouts. After
   2+ consecutive, force re-register ProcessCommands on
   EditorApplication.update and reset the reentrancy guard.

3. Stale command eviction: commands stuck with IsExecuting=true for
   more than 60s are evicted from the queue with an error result.

Also adds always-on diagnostic logging at client connect/disconnect
with active client counts.

Includes E2E reconnection tests that verify both abrupt disconnect
recovery and stale client cleanup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix stdio bridge stalls when Unity is backgrounded during domain reload

- Add QueuePlayerLoopUpdate after command enqueue so ProcessCommands fires
  even when Unity is backgrounded (mirrors HTTP RequestMainThreadPump)
- Keep ProcessCommands permanently registered on EditorApplication.update
  to eliminate the registration gap between Stop and Start during reload
- Replace blocking retry loop in Start() (Thread.Sleep x 10) with single
  attempt + port-switch fallback; async retries handled by reload handler
- Replace fire-and-forget TryStartBridgeImmediate with async retry loop
  (6 attempts with backoff: 0s, 1s, 3s, 5s, 10s, 30s) matching HTTP
- Fix macOS port conflict: use ExclusiveAddressUse in both the real
  listener (CreateConfiguredListener) and the port probe (IsPortAvailable)
  to prevent AssetImportWorkers from binding the same port via SO_REUSEADDR
- Add PortManager unit tests (5 tests including macOS SO_REUSEADDR case)

Fixes #785

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add resource URI reference table to unity-mcp-skill

Adds a prominent 'Do NOT Guess' section with a URI lookup table near
the top of the skill, so LLMs use exact URIs instead of fabricating
similar-looking ones.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address PR review feedback

- Collapse double lock in HandleClientAsync (add + count in one lock)
- Add CancellationToken to ResumeStdioWithRetriesAsync so retries abort
  on editor quit or subsequent domain reloads
- Fix 'gameobject' → 'GameObject' capitalization in skill URI table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address CodeRabbit review feedback

- PortManagerTests: save/restore on-disk port files in SetUp/TearDown
  to prevent DiscoverNewPort from mutating persistent state
- StdioBridgeReconnectTests: replace blocking Connect with ConnectAsync
  + Wait(ConnectTimeoutMs) so CI tests cannot hang indefinitely

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
actions-user and others added 27 commits February 20, 2026 03:49
…0502613

chore: update Unity package to beta version 9.4.7-beta.9
)

* Fix editor state always reporting stale when Unity is backgrounded

EditorStateCache.GetSnapshot() returned a cached clone with the
observed_at_unix_ms from the last OnUpdate tick. When Unity is
backgrounded, OnUpdate is throttled, so the timestamp grows stale
even though the data is current and Unity is responsive.

Now stamps the clone at serve time so the server-side staleness
check (>2s = stale) reflects when the snapshot was served, not
when the update loop last ran. This fixes ready_for_tools being
false for every backgrounded Unity editor on HTTP.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Only re-stamp editor state when Unity is backgrounded

Addresses CodeRabbit review feedback: the unconditional re-stamp
defeated the staleness check for genuinely unresponsive focused editors.
Now uses InternalEditorUtility.isApplicationActive to conditionally
re-stamp only when Unity is backgrounded.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add /mcp-source skill and fix upstream main URL

Add Claude Code skill for switching MCP package source in Unity
projects. Fix mcp_source.py upstream main URL to include required
#main branch suffix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…11319809

chore: update Unity package to beta version 9.4.7-beta.10
…792)

When Unity enters domain reload after a script edit, the retry loop in
send_command_with_retry would re-send the identical edit command up to
40 times, duplicating insert_method/anchor_insert edits. Pass
retry_on_reload=False on all script-mutating send calls since the edit
lands on disk before the reload triggers.

Also fix _flip_async coroutine in apply_text_edits that was passed as a
threading.Thread target — the coroutine was never awaited. Replace with
asyncio.create_task so the sentinel reload flip actually executes.

Fixes #790

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…33095438

chore: update Unity package to beta version 9.4.7-beta.11
)

* Fix script edit tools retrying non-idempotent commands during reload

When Unity enters domain reload after a script edit, the retry loop in
send_command_with_retry would re-send the identical edit command up to
40 times, duplicating insert_method/anchor_insert edits. Pass
retry_on_reload=False on all script-mutating send calls since the edit
lands on disk before the reload triggers.

Also fix _flip_async coroutine in apply_text_edits that was passed as a
threading.Thread target — the coroutine was never awaited. Replace with
asyncio.create_task so the sentinel reload flip actually executes.

Fixes #790

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add post-mutation wait-for-ready and reloading-rejection retry

Script-mutating tools (create_script, delete_script, apply_text_edits,
script_apply_edits) use retry_on_reload=False to avoid re-sending
non-idempotent commands during domain reload. But this meant they
returned before Unity finished reloading, causing the next tool call
to timeout.

This commit:
- Extracts wait_for_editor_ready() helper from refresh_unity.py that
  polls editor_state until Unity reports ready_for_tools
- Adds is_reloading_rejection() to detect when Unity rejected a command
  due to stale reloading state (safe to retry since command never ran)
- Calls both at all 9 mutation sites (4 in manage_script, 5 in
  script_apply_edits): retry on rejection, then wait for readiness
- Adds 9 unit tests for the new helpers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix stale socket causing mutations to silently fail after domain reload

UnityConnection reuses TCP sockets across commands. After domain reload
kills Unity TCP listener, the Python side still holds the dead socket.
With retry_on_reload=False (used for non-idempotent mutations), there are
no retries to recover -- the command is never delivered to Unity.

- Add _ensure_live_connection() to detect dead sockets via non-blocking
  MSG_PEEK before each send, allowing reconnection
- Add is_connection_lost_after_send() helper and post-mutation verification
  at all 9 mutation sites (create/delete/apply_text_edits/script_apply_edits)
  to recover when domain reload drops the TCP response
- Fix stale reloading heartbeat in C# bridge: write reloading=false at
  Start() entry and after retry exhaustion in StdioBridgeReloadHandler

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Extract send_mutation() and verify_edit_by_sha() shared helpers

Consolidates the repeated retry+wait+verify pattern from 9 inline
sites across manage_script.py and script_apply_edits.py into a
single send_mutation() helper in refresh_unity.py. Addresses
Sourcery code review feedback on PR #796.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…42593753

chore: update Unity package to beta version 9.4.7-beta.12
… detection (#798)

Fixes #795 — the HTTP/WebSocket transport path (PluginHub) now respects
retry_on_reload=False and performs pre-send liveness checks, matching
the stdio path behavior from PR #792.
…43317202

chore: update Unity package to beta version 9.4.7-beta.13
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…43507739

chore: update Unity package to beta version 9.4.7-beta.14
…52367644

chore: update Unity package to beta version 9.4.7-beta.15
…udge) (#804)

* fix: remove broken root rename assertion from prefab test

LoadAssetAtPath returns the asset filename as .name for prefab roots,
not the internally renamed root object name. Remove the rename + assert
that was causing CombinesWithOtherModifications to fail. The test still
verifies that componentProperties works alongside position changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove yield frames causing StdioBridge reconnect test flakiness

The 5-frame yield between client2 handshake and ping created a window
where the MCP Python server could reconnect and close our test client
as stale. Stale-client cleanup runs synchronously in HandleClientAsync
before the read loop, so no yield is needed after reading the handshake.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: ensure focus nudge fires and logs correctly during test polling

- Add file handler to root logger so __name__-based loggers (focus_nudge,
  run_tests) write to the log file instead of only stderr
- Add fire-and-forget nudge check on non-wait_timeout get_test_job calls
  so stalls are detected regardless of client polling style
- Add 13 unit tests for should_nudge logic, backoff reset, and gating

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR #804 review feedback

- Store asyncio.create_task reference in module-level set to prevent GC (CodeRabbit)
- Add test for _get_frontmost_app() returning None (CodeRabbit nitpick)
- Add comment explaining why prefab root rename is not tested (Sourcery)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add Claude Code to MCP client examples in README

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…62651671

chore: update Unity package to beta version 9.4.7-beta.16
data.get('progress', {}) returns None when key exists with null value.
Use 'or {}' fallback to prevent AttributeError on progress.get().

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…62768294

chore: update Unity package to beta version 9.4.7-beta.17
@github-actions github-actions bot merged commit d76a8df into main Feb 21, 2026
@github-actions github-actions bot deleted the release/v9.4.7 branch February 21, 2026 20:29
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.

2 participants