Skip to content

feat: Pause points are easier to drive: unified naming, embedded logs, diagnosis hints, and frame stepping#1309

Merged
hatayama merged 31 commits into
v3-betafrom
feature/hatayama/improve-debug-break-usability
Jun 11, 2026
Merged

feat: Pause points are easier to drive: unified naming, embedded logs, diagnosis hints, and frame stepping#1309
hatayama merged 31 commits into
v3-betafrom
feature/hatayama/improve-debug-break-usability

Conversation

@hatayama

Copy link
Copy Markdown
Owner

Summary

  • The breakpoint workflow is now consistently called pause point everywhere (commands, runtime API, responses, skills) — the old debug-break naming is gone, including the stale generated copies that made agents call commands that no longer existed.
  • PlayMode E2E verification needs fewer round trips and fewer guesses: matching logs come back embedded, timeouts explain themselves, input responses report whether the game observed the press, and a new Step action advances exactly one frame.

User Impact

  • Before: the concept was called pause point but commands were named debug-break, and stale generated skills still advertised retired flags — agents routinely guessed wrong command names. Now every command, error code, response field, and skill uses the same pause-point vocabulary (enable-pause-point, wait-for-pause-point, UloopPausePoint.Pause("id"), …).
  • wait-for-pause-point always embeds the marker-matching log entries (MatchingLogs) in hit responses and timeout details, so a separate get-logs call while paused is unnecessary.
  • Timeout and expired errors now carry a diagnosis hint that distinguishes PlayMode not running, Unity already paused, a never-hit marker, or fast-progressing game state that moved past the marker.
  • clear-pause-point explains why nothing was cleared (already hit, expired, already cleared) instead of a bare ClearedCount: 0.
  • simulate-keyboard/simulate-mouse-input responses interrupted by a pause point now include PressEdgeObserved (did the game actually see the press edge?) and a PausePointHits list covering every marker hit during the simulation.
  • control-play-mode --action Step advances exactly one frame and stays paused (the Editor's Next Frame button), independent of Time.timeScale. The pause point skill now teaches a Pause → arrange → Step → Play recipe for fast-progressing games instead of the timeScale freeze pattern, which silently leaks into the next PlayMode session and does not stop unscaled-time projects.
  • uloop skills install auto-refreshes every target that already has uloop skills installed, even when its flag is omitted — stale generated skill copies can no longer drift out of sync with the CLI.
  • COMPILE_WAIT_TIMEOUT and the busy envelope no longer read as a frozen Editor; they explain the single-flight contract and suggest probing with a light command before restarting Unity.
  • execute-dynamic-code --code-file accepts long code from a file instead of a shell string.
  • Editor-window screenshots no longer trigger "Releasing render texture that is set as Camera.targetTexture" warnings (RenderTexture.active is saved before Blit and restored before release).
  • Launch falls back to a project IPC probe when the process scan fails, and server-busy responses are retried inside the bounded connection retry window.

Changes

  • Go CLI: command/error/field renames, embedded MatchingLogs fetch, timeout hint mapping, skills-install auto-refresh detection, busy retry, launch probe fallback, --code-file.
  • Unity package: PlayModeAction.Step via EditorApplication.Step() with a PlayMode guard, pause point hit snapshot registry exposed as PausePointHits, PressEdgeObserved carried through pause-point interruptions, state-aware clear messages, screenshot RenderTexture.active handling.
  • Skills: pause point skill rewritten around the new naming, embedded logs, timeout hints, and the Pause/Step/Play recipe; generated copies under .claude/ and .agents/ regenerated.
  • Bridge command names changed (get-pause-point-status, clear-pause-point-status), so MINIMUM_REQUIRED_CLI_VERSION was raised.

Verification

  • scripts/check-go-cli.sh and scripts/build-go-cli.sh pass; Go unit tests cover the rename, hints, embedded logs, and auto-refresh.
  • uloop compile: 0 errors / 0 warnings. EditMode and PlayMode test suites pass (4 EditMode failures verified pre-existing on origin/v3-beta and untouched).
  • Live E2E in the dev project: Play → Pause → Step ("Stepped one frame; play mode is paused.") → Stop; pause point hit with embedded MatchingLogs; timeout hint observed in error details.
  • Field-tested across three scripted Codex agent runs building Unity games end-to-end with this branch's binary: two full runs with zero crashes, zero freezes, and zero supervisor interventions.

hatayama added 26 commits June 11, 2026 01:10
AI-agent usability feedback from three independent E2E sessions showed the
mixed naming between the "pause point" concept and the "debug-break" command
family caused real failures (agents guessed clear-pause-point and got Unknown
tool). Unify every user-facing name on pause-point with no backward
compatibility:

- CLI commands: enable/clear/wait-for-pause-point, pause-point-status, and
  the internal bridge commands get/clear-pause-point-status
- Error codes: PAUSE_POINT_NOT_ENABLED / WAIT_TIMEOUT / EXPIRED / CLEARED
- Response fields: InterruptedByPausePoint, PausePointId, PausePointHitCount
- Runtime marker API: UnityCliLoopDebug.Break(id) -> UloopPausePoint.Pause(id)
- Skill renamed to uloop-wait-for-pause-point; regenerated copies updated
- Bump cli contract and MINIMUM_REQUIRED_CLI_VERSION to 3.0.0-beta.29 because
  the Unity package now depends on the renamed bridge commands
Agents reported that clearing an already-hit one-shot marker returned
ClearedCount: 0 with the message "cleared.", which read as a contradiction.
Clear now resolves expiry first and reports a state-specific message for
already-hit, expired, and already-cleared markers, and bulk clear says
"No active pause points to clear." when nothing was armed.
Agents found timeout root-causing hard: the same error covers a missed code
path, a stopped PlayMode, and an already-paused Editor. The timeout error now
carries details.hint with a deterministic diagnosis for those three states so
the next action is obvious without extra status probing.
After a hit, agents always followed up with get-logs --search-text <marker-id>
to read the values logged next to the marker, and that extra call could race a
busy paused Editor. With --include-matching-logs (and an optional
--matching-logs-max-count, default 10), the wait response now embeds the
matching log entries directly; timeouts attach them best-effort under
details.matchingLogs. Log fetch failures are ignored so a hit never turns
into an error.
…skill

Fold the new --include-matching-logs flag into the quick check template so the
standard loop needs one less paused-Editor call, and point timeout debugging
at error.details.hint and error.details.matchingLogs first.
A marker whose enable-pause-point timeout window ends before the wait
deadline surfaces as PAUSE_POINT_EXPIRED instead of a wait timeout, and
that error carried no hint at all. An AI-agent E2E session hit exactly
this: the agent saw repeated expired errors with no guidance and could
not tell an id mismatch from an exhausted enable window. Reuse the
PlayMode/paused diagnoses and add an expired-specific hint that points
at the enable-side --timeout-seconds.
Two AI agents independently asked for a clear-all command that already
exists, so the discoverability gap is in the skill doc, not the CLI.
Also explain that PAUSE_POINT_EXPIRED now carries the same diagnosis
hint and what an expired marker means for the enable-side timeout.
In two supervised AI-agent E2E sessions, agents attached
--include-matching-logs to nearly every wait call (44 of ~57 waits)
and one explicitly asked for it to be the default, so the opt-in flag
only added friction. Retire the flag, keep --matching-logs-max-count,
and make the empty/absent distinction explicit: an empty MatchingLogs
array means no matching log exists, while an absent field means the
best-effort fetch itself failed.
The timeout error detail used camelCase matchingLogs while the hit
response used PascalCase MatchingLogs for the same data, which an
AI-agent E2E session flagged as confusing. One spelling now covers both
surfaces. Also state explicitly in the skill that log embedding is
always on and the old opt-in flag no longer exists, because all three
agents tripped over stale flag docs before self-recovering.
Codex-sandboxed agents cannot exec /bin/ps, so launch died at process
detection even though Unity was running and every other command worked.
All three supervised agents had to discover by hand that the Editor was
reachable. When the scan errors on a plain launch, probe the project
IPC instead: a response proves Unity is running, so report
AlreadyRunning with an unfocused-window note. Restart and quit still
fail because killing requires a process id.
Supervised AI agents reported that shell-quoting long multi-line C#
snippets for --code is error-prone. --code-file reads the source from a
file CLI-side and forwards it as the Code parameter, so no Unity schema
change is needed. Combining it with --code is rejected to avoid one
silently shadowing the other.
Agents running back-to-back uloop commands hit UNITY_SERVER_BUSY and
had to hand-roll retries even though the error is marked SafeToRetry: a
busy response means Unity never executed the request. Reuse the
existing 10s retry window to poll until the running tool frees the
slot, and surface the original busy envelope unchanged if it never
does.
Agents saw Press/KeyDown return Success while gameplay never observed
wasPressedThisFrame, and had to rewrite game code to hand-rolled edge
detection to cope. The response now carries PressEdgeObserved: a
monitor on InputSystem.onAfterUpdate checks the edge inside gameplay
input updates (editor updates excluded, since presses consumed there
are invisible to gameplay polling). Editor-tick polling was tried first
and reproduced the exact miss, which confirms the monitor placement.
…dates

Generated copies under .claude/ and .agents/ follow the source skill
edits: launch IPC-probe fallback, execute-dynamic-code --code-file,
PressEdgeObserved, and the MatchingLogs naming note.
The IPC-probe fallback pushed launch.go past the 500-line architecture
limit, so the cohesive focus-logging block moves to launch_focus_log.go.
Supervised agents repeatedly ran uloop commands in parallel without
knowing the CLI is single-flight by design, and per-skill documentation
would be redundant and easily skipped. The busy message is the one
guaranteed touchpoint, so it now states the contract and that the CLI
already retried. Also prefer reporting a busy response over a transport
error cut short by the expiring retry window, because busy is the truer
diagnosis of why the request never ran.
Block-breaker E2E sessions showed fast-progressing games can leave the
marker code path behind (state returns to Ready/GameOver) before the
wait starts, so the never-hit timeout hint now tells agents to
re-trigger the code path instead of only re-checking the marker id.
An agent terminated a whole session after misreading this timeout as an
Editor freeze, even though Unity answered the next command instantly.
The message now states the Editor is not necessarily frozen, and the
next actions walk through a responsiveness probe (get-logs) before
retrying compile, with launch -r only as the last resort.
Two experiment runs in a row hit the same failure mode: .codex/skills
was installed once, later installs only passed --claude/--agents, and
Codex agents kept reading retired flags from the stale copy. Install
now detects any known target that already holds a uloop skill and
refreshes it even when its flag is omitted, and the install help
documents this behavior.
Graphics.Blit (and the internal window-capture call) leave the
destination assigned to RenderTexture.active, so saving the "previous"
target after them captured the temporary itself. Restoring that value
and then releasing the temporary emitted "Releasing render texture
that is set to be RenderTexture.active\!" warnings, which polluted the
zero-warning check agents run at the end of E2E sessions. All three
capture paths now save before the call and restore before release.
Pause-point interruption is the most common path in marker-driven E2E
sessions, yet the interrupted result dropped PressEdgeObserved and
agents saw null exactly where they wanted the edge evidence. Press and
KeyDown now carry their observation into the interrupted result, and
the skill doc spells out when the field is null (KeyUp and timeouts
only).
One key press or mouse action can hit several markers in the same
frame, but the response only named the latest one, so agents had to
issue extra status calls to find the rest. The registry now keeps all
hit snapshots (cleared alongside the existing latest-hit bookkeeping),
and keyboard/mouse interruption responses expose them as a
PausePointHits array of {Id, HitCount} in hit order.
Block-breaker style games advance state during E2E setup, so agents
asked for a way to arrange scenarios before the marker is overrun. The
pause point skill now shows the execute-dynamic-code Time.timeScale
freeze/restore pattern as a setup aid, with an explicit caveat that it
is not paused-frame proof.
Propagates the PausePointHits field docs, the PressEdgeObserved null
conditions, and the fast-progressing-game time-freeze pattern into the
generated .claude/.agents copies via uloop skills install.
Time.timeScale = 0 is unreliable for E2E setup: projects that read
unscaled time keep advancing, and the value silently leaks into the
next PlayMode session (an agent hit exactly this). control-play-mode
now exposes Step - the Editor's Next Frame button
(EditorApplication.Step) - which advances one frame and stays paused
independent of timeScale. The pause point skill now teaches
Pause/Step/Play for fast-progressing games instead of freezing time.
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

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

More reviews will be available in 5 minutes. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

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.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 49f78715-59f8-41ef-8b3d-c665604e8803

📥 Commits

Reviewing files that changed from the base of the PR and between f4d3c18 and 5ebc51b.

📒 Files selected for processing (1)
  • cli/internal/cli/connection_retry.go
📝 Walkthrough

Walkthrough

Migrates debug-break workflows to pause-point semantics across runtime, editor, CLI, telemetry, tests, and documentation; adds CLI pause-point wait/status, dynamic --code-file support, PlayMode Step action, launch IPC fallback, server_busy retry logic, and related tests and docs.

Changes

Pause-point and CLI support

Layer / File(s) Summary
Runtime marker API and registry
Packages/src/Runtime/PausePoints/*
Replaces UnityCliLoopDebug.Break with UloopPausePoint.Pause, registry records multiple hit snapshots, and snapshot/clear messages updated.
Pause-point tool contracts and bridge wiring
Packages/src/Editor/ToolContracts/UnityCliLoopConstants.cs, Packages/src/Editor/FirstPartyTools/PausePoint/*, Packages/src/Editor/Infrastructure/Api/*, cli/internal/cli/*
Adds pause-point tool/command constants, updates tool bindings and internal bridge routing, and replaces debug-break constants with pause-point equivalents.
Pause-point wait/status CLI and tests
cli/internal/cli/pause_point_*, cli/internal/cli/run.go, cli/internal/cli/error_envelope*, cli/internal/cli/command_*, cli/internal/cli/native_tool_settings.go
Implements wait-for-pause-point and pause-point-status commands with option parsing, polling, matching-log fetch, classified errors, and comprehensive tests.
Simulation telemetry and tests
Packages/src/Editor/FirstPartyTools/Common/InputSimulation/*, Packages/src/Editor/FirstPartyTools/SimulateKeyboard/*, Packages/src/Editor/FirstPartyTools/SimulateMouseInput/*, Assets/Tests/PlayMode/*
Keyboard/mouse simulation DTOs and responses now include pause-point interruption fields, per-hit lists, and PressEdgeObserved; use-cases and PlayMode tests updated accordingly.
PlayMode Step action and docs
Packages/src/Editor/FirstPartyTools/ControlPlayMode/*, *.agents/skills/*
Adds PlayModeAction.Step handling calling EditorApplication.Step(), documents Step semantics across SKILL docs, and adds test coverage for stepping outside PlayMode.
Dynamic code file & run integration
cli/internal/cli/dynamic_code_file.go, cli/internal/cli/run.go, cli/internal/cli/dynamic_code_file_test.go, Packages/src/Editor/FirstPartyTools/ExecuteDynamicCode/Skill/SKILL.md
Adds --code-file flag extraction, file-read injection into tool params, tests for parsing/conflicts/error cases, and docs updated to require exactly one of --code or --code-file.
Launch fallback, busy retry, and utilities
cli/internal/cli/launch*, cli/internal/cli/connection_retry*, cli/internal/cli/busy_status.go, cli/contract.json, Packages/src/Editor/Domain/CliConstants.cs, Packages/src/Editor/FirstPartyTools/Screenshot/EditorWindowCaptureUtility.cs
uloop launch gains project-IPC fallback when process scanning is blocked, connection retry now recognizes server_busy, busy/compile timeout messages expanded, CLI contract version bumped, and screenshot capture preserves/restores RenderTexture.active.
Skill docs and help text
*.agents/skills/*, Packages/src/Editor/CliOnlyTools~/PausePoint/Skill/SKILL.md, Packages/src/Editor/FirstPartyTools/*/Skill/SKILL.md
Skill guides converted from debug-break to pause-point workflows, linked to uloop-wait-for-pause-point, and updated examples/evidence guidance.
Skills install UX
cli/internal/cli/skills*
runSkillsInstall auto-detects and refreshes previously installed targets; help text and tests added.

Sequence Diagram(s)

sequenceDiagram
  participant RunProjectLocal
  participant PausePointWait
  participant UnityIPC
  participant UloopPausePointRegistry
  RunProjectLocal->>PausePointWait: run wait-for-pause-point --id <id>
  PausePointWait->>UnityIPC: query pause-point status (poll)
  UnityIPC-->>PausePointWait: status (Enabled / Hit / Expired / Cleared)
  PausePointWait->>UloopPausePointRegistry: best-effort clear on timeout
  PausePointWait-->>RunProjectLocal: JSON hit payload (MatchingLogs) or classified error
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/hatayama/improve-debug-break-usability

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

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

Re-trigger cubic

Comment thread cli/internal/cli/connection_retry.go Outdated

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
Packages/src/Editor/FirstPartyTools/ControlPlayMode/Skill/SKILL.md (1)

9-9: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the one-line capability summary to include Step.

The short description still says (play/stop/pause) although Step is now a first-class action. Keeping this line aligned avoids mixed guidance in quick scans.

Also applies to: 21-21

🤖 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/FirstPartyTools/ControlPlayMode/Skill/SKILL.md` at line
9, The one-line capability summary in SKILL.md still lists "(play/stop/pause)"
but the Skill now supports the Step action; update that short description to
include "step" (for example "(play/stop/pause/step)") so quick scans are
accurate, and make the same change where the summary appears a second time in
the file to keep both occurrences consistent.
Packages/src/Runtime/PausePoints/UloopPausePointRegistry.cs (1)

61-78: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

ClearAll() should check for expiry before clearing to match Clear(id) behavior.

Clear(string id) at line 48 calls ExpireIfNeeded(now) before determining the appropriate message, allowing it to distinguish between Enabled, Expired, and Hit entries. However, ClearAll() does not call ExpireIfNeeded() on any entries before marking them as cleared.

This creates an inconsistency: an entry that was enabled with a 30-second timeout and hasn't been hit after 35 seconds will be in the Enabled state when ClearAll() is called (because ExpireIfNeeded() hasn't been invoked). ClearAll() will mark it as Cleared with the default message, when it should first transition to Expired and potentially provide a different treatment.

Suggested fix
 public static UloopPausePointClearAllResult ClearAll()
 {
     DateTime now = NowUtc();
     int clearedCount = 0;
     foreach (UloopPausePointEntry entry in Entries.Values)
     {
+        entry.ExpireIfNeeded(now);
         if (entry.Status == UloopPausePointStatus.Cleared)
         {
             continue;
         }

         entry.MarkCleared();
         clearedCount++;
     }
🤖 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/Runtime/PausePoints/UloopPausePointRegistry.cs` around lines 61
- 78, ClearAll() currently marks every UloopPausePointEntry as cleared without
first evaluating time-based expiry; update ClearAll() to call
entry.ExpireIfNeeded(now) (using the same DateTime now = NowUtc()) for each
entry before checking entry.Status and calling entry.MarkCleared(), so entries
that should transition to UloopPausePointStatus.Expired are handled the same way
as Clear(string id) does; keep clearedCount and ClearLatestHitSnapshot()
behavior unchanged.
🤖 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.

Inline comments:
In `@Assets/Tests/PlayMode/SimulateKeyboardTests.cs`:
- Around line 228-231: The test configures a global pause provider with
InputSystemUpdateHelper.ConfigurePauseProviderForTests(...) but doesn't
guarantee ResetPauseProviderForTests() runs if an assertion or yield fails; wrap
the section that sets the provider and waits (the
UloopPausePoint.Pause("space-press"); ConfigurePauseProviderForTests(() =>
true); yield return WaitForTask(task); sequence) in a try/finally so that
InputSystemUpdateHelper.ResetPauseProviderForTests() is always called in the
finally block; apply the same try/finally pattern to the similar block around
lines 267-271.

In `@cli/internal/cli/execution_errors.go`:
- Line 7: The message in the error struct contains a hardcoded "180000ms"
duration; change it to derive from the existing constant by using
compileWaitTimeout.Milliseconds() (or toolReadinessTimeout.Milliseconds()) so
the string is built from the constant instead of a magic number; locate the
Message assignment in execution_errors.go for the relevant error (the entry
using compileWaitTimeout) and format the message to include the computed
milliseconds value.

In `@Packages/src/Editor/FirstPartyTools/SimulateMouseUi/Skill/SKILL.md`:
- Around line 81-85: The paragraph mixes CLI invocation styles (e.g.,
uloop-wait-for-pause-point, uloop-get-logs vs. bare get-logs/get-hierarchy and
simulate-mouse-ui); normalize all CLI commands to a single canonical prefix (use
the "uloop-" prefix) and update occurrences in this block to
uloop-wait-for-pause-point, uloop-get-logs, uloop-get-hierarchy,
uloop-find-game-objects, uloop-execute-dynamic-code, and uloop-simulate-mouse-ui
(and any other bare CLI names) so examples and references are consistent and
copy/paste-safe; ensure surrounding prose reflects the renamed commands and
update any inline examples or lists that mention those commands.

---

Outside diff comments:
In `@Packages/src/Editor/FirstPartyTools/ControlPlayMode/Skill/SKILL.md`:
- Line 9: The one-line capability summary in SKILL.md still lists
"(play/stop/pause)" but the Skill now supports the Step action; update that
short description to include "step" (for example "(play/stop/pause/step)") so
quick scans are accurate, and make the same change where the summary appears a
second time in the file to keep both occurrences consistent.

In `@Packages/src/Runtime/PausePoints/UloopPausePointRegistry.cs`:
- Around line 61-78: ClearAll() currently marks every UloopPausePointEntry as
cleared without first evaluating time-based expiry; update ClearAll() to call
entry.ExpireIfNeeded(now) (using the same DateTime now = NowUtc()) for each
entry before checking entry.Status and calling entry.MarkCleared(), so entries
that should transition to UloopPausePointStatus.Expired are handled the same way
as Clear(string id) does; keep clearedCount and ClearLatestHitSnapshot()
behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 549f7baf-c75b-4808-af6a-6fd23bff3ac0

📥 Commits

Reviewing files that changed from the base of the PR and between 7498397 and fe0c918.

⛔ Files ignored due to path filters (1)
  • Packages/src/Runtime/PausePoints/UloopPausePoint.cs.meta is excluded by none and included by none
📒 Files selected for processing (78)
  • .agents/skills/uloop-control-play-mode/SKILL.md
  • .agents/skills/uloop-execute-dynamic-code/SKILL.md
  • .agents/skills/uloop-get-logs/SKILL.md
  • .agents/skills/uloop-launch/SKILL.md
  • .agents/skills/uloop-simulate-keyboard/SKILL.md
  • .agents/skills/uloop-simulate-mouse-input/SKILL.md
  • .agents/skills/uloop-simulate-mouse-ui/SKILL.md
  • .agents/skills/uloop-wait-for-debug-break/SKILL.md
  • .agents/skills/uloop-wait-for-pause-point/SKILL.md
  • .claude/skills/uloop-control-play-mode/SKILL.md
  • .claude/skills/uloop-execute-dynamic-code/SKILL.md
  • .claude/skills/uloop-get-logs/SKILL.md
  • .claude/skills/uloop-launch/SKILL.md
  • .claude/skills/uloop-simulate-keyboard/SKILL.md
  • .claude/skills/uloop-simulate-mouse-input/SKILL.md
  • .claude/skills/uloop-simulate-mouse-ui/SKILL.md
  • .claude/skills/uloop-wait-for-debug-break/SKILL.md
  • .claude/skills/uloop-wait-for-pause-point/SKILL.md
  • Assets/Tests/Editor/ControlPlayModeUseCaseTests.cs
  • Assets/Tests/Editor/PausePointTests.cs
  • Assets/Tests/Editor/ToolSettingsUseCaseTests.cs
  • Assets/Tests/Editor/UnityCliLoopToolRegistryTests.cs
  • Assets/Tests/PlayMode/SimulateKeyboardTests.cs
  • Assets/Tests/PlayMode/SimulateMouseInputTests.cs
  • Packages/src/Editor/Application/UseCases/ToolSettingsUseCase.cs
  • Packages/src/Editor/CliOnlyTools~/Launch/Skill/SKILL.md
  • Packages/src/Editor/CliOnlyTools~/PausePoint/Skill/SKILL.md
  • Packages/src/Editor/Domain/CliConstants.cs
  • Packages/src/Editor/FirstPartyTools/Common/InputSimulation/UnityCliLoopInputSimulationTypes.cs
  • Packages/src/Editor/FirstPartyTools/ControlPlayMode/ControlPlayModeSchema.cs
  • Packages/src/Editor/FirstPartyTools/ControlPlayMode/ControlPlayModeUseCase.cs
  • Packages/src/Editor/FirstPartyTools/ControlPlayMode/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/ExecuteDynamicCode/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/GetLogs/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/PausePoint/PausePointTools.cs
  • Packages/src/Editor/FirstPartyTools/Screenshot/EditorWindowCaptureUtility.cs
  • Packages/src/Editor/FirstPartyTools/SimulateKeyboard/SimulateKeyboardResponse.cs
  • Packages/src/Editor/FirstPartyTools/SimulateKeyboard/SimulateKeyboardTool.cs
  • Packages/src/Editor/FirstPartyTools/SimulateKeyboard/SimulateKeyboardUseCase.cs
  • Packages/src/Editor/FirstPartyTools/SimulateKeyboard/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/SimulateMouseInput/SimulateMouseInputResponse.cs
  • Packages/src/Editor/FirstPartyTools/SimulateMouseInput/SimulateMouseInputTool.cs
  • Packages/src/Editor/FirstPartyTools/SimulateMouseInput/SimulateMouseInputUseCase.cs
  • Packages/src/Editor/FirstPartyTools/SimulateMouseInput/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/SimulateMouseUi/Skill/SKILL.md
  • Packages/src/Editor/Infrastructure/Api/InternalBridgeCommandRouter.cs
  • Packages/src/Editor/Infrastructure/Api/PausePointStatusBridgeCommand.cs
  • Packages/src/Editor/ToolContracts/UnityCliLoopConstants.cs
  • Packages/src/Runtime/PausePoints/UloopPausePoint.cs
  • Packages/src/Runtime/PausePoints/UloopPausePointRegistry.cs
  • cli/contract.json
  • cli/internal/cli/busy_status.go
  • cli/internal/cli/command_help.go
  • cli/internal/cli/command_registry.go
  • cli/internal/cli/completion_options.go
  • cli/internal/cli/connection_retry.go
  • cli/internal/cli/connection_retry_test.go
  • cli/internal/cli/debug_break_wait.go
  • cli/internal/cli/debug_break_wait_test.go
  • cli/internal/cli/dynamic_code_file.go
  • cli/internal/cli/dynamic_code_file_test.go
  • cli/internal/cli/error_envelope.go
  • cli/internal/cli/error_envelope_test.go
  • cli/internal/cli/execution_errors.go
  • cli/internal/cli/launch.go
  • cli/internal/cli/launch_focus_log.go
  • cli/internal/cli/launch_ready.go
  • cli/internal/cli/launch_test.go
  • cli/internal/cli/native_tool_settings.go
  • cli/internal/cli/pause_point_errors.go
  • cli/internal/cli/pause_point_logs.go
  • cli/internal/cli/pause_point_wait.go
  • cli/internal/cli/pause_point_wait_test.go
  • cli/internal/cli/run.go
  • cli/internal/cli/skills.go
  • cli/internal/cli/skills_display.go
  • cli/internal/cli/skills_test.go
  • cli/internal/tools/default-tools.json
💤 Files with no reviewable changes (4)
  • .agents/skills/uloop-wait-for-debug-break/SKILL.md
  • .claude/skills/uloop-wait-for-debug-break/SKILL.md
  • cli/internal/cli/debug_break_wait.go
  • cli/internal/cli/debug_break_wait_test.go

Comment thread Assets/Tests/PlayMode/SimulateKeyboardTests.cs
Comment thread cli/internal/cli/execution_errors.go Outdated
Comment thread Packages/src/Editor/FirstPartyTools/SimulateMouseUi/Skill/SKILL.md Outdated
A failure during capture, blit, or pixel read previously leaked the
temporary RenderTexture and left RenderTexture.active pointing at it.
try/finally is the repository-approved pattern for resource release,
so all three capture paths now restore the caller's active target and
release the temporary even when the capture work throws.
hatayama added 2 commits June 11, 2026 21:21
The expired-window busy masking applied to every final error, so a
request that actually reached Unity and failed with a real RPC error
could be overwritten by a stale server_busy seen earlier in the retry
window. The mask now requires the final attempt to be undispatched,
which matches its intent of explaining window-expiry transport errors.

Also derive the compile wait timeout message from compileWaitTimeout
instead of hardcoding 180000ms; the envelope test keeps the literal
expectation as a regression pin.
The pause point inspection sections mixed skill-style names
(uloop-get-logs) with bare command names (get-logs), which invited
copy/paste mistakes. All command references now use the runnable
form (uloop get-logs), matching the examples sections. Installed
copies regenerated.

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

Actionable comments posted: 1

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

Inline comments:
In `@cli/internal/cli/connection_retry_test.go`:
- Around line 518-560: The test uses tight sleeps to exercise the retry window
(serverConnectionRetryTimeout/serverConnectionRetryPoll) and can be flaky;
replace the implicit timing with explicit synchronization: add a channel (e.g.,
acceptedCh) that the connection-handling goroutine closes/signals immediately
after unityipc.Write(conn, []byte(accepted)) succeeds, then in the caller wait
on that channel before proceeding to the failure/timeout path instead of the
hard-coded time.Sleep(80 * time.Millisecond); compute any additional delay
relative to serverConnectionRetryTimeout (e.g., wait accepted signal then sleep
serverConnectionRetryTimeout*2 or a fixed larger margin) so the second request
is guaranteed accepted before the retry deadline is evaluated—update the
goroutine handling listener.Accept, the place that writes the accepted JSON, and
the subsequent sleep to use the channel-based coordination (referencing
serverConnectionRetryTimeout, serverConnectionRetryPoll, unityipc.Read/Write,
busy, failure, and the accepted JSON variable).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9a470f10-83eb-4649-8b17-537e3af2e102

📥 Commits

Reviewing files that changed from the base of the PR and between fe0c918 and c2b02d1.

📒 Files selected for processing (13)
  • .agents/skills/uloop-simulate-keyboard/SKILL.md
  • .agents/skills/uloop-simulate-mouse-input/SKILL.md
  • .agents/skills/uloop-simulate-mouse-ui/SKILL.md
  • .claude/skills/uloop-simulate-keyboard/SKILL.md
  • .claude/skills/uloop-simulate-mouse-input/SKILL.md
  • .claude/skills/uloop-simulate-mouse-ui/SKILL.md
  • Packages/src/Editor/FirstPartyTools/Screenshot/EditorWindowCaptureUtility.cs
  • Packages/src/Editor/FirstPartyTools/SimulateKeyboard/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/SimulateMouseInput/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/SimulateMouseUi/Skill/SKILL.md
  • cli/internal/cli/connection_retry.go
  • cli/internal/cli/connection_retry_test.go
  • cli/internal/cli/execution_errors.go
✅ Files skipped from review due to trivial changes (2)
  • .claude/skills/uloop-simulate-mouse-ui/SKILL.md
  • .agents/skills/uloop-simulate-keyboard/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (10)
  • Packages/src/Editor/FirstPartyTools/SimulateMouseInput/Skill/SKILL.md
  • Packages/src/Editor/FirstPartyTools/SimulateMouseUi/Skill/SKILL.md
  • cli/internal/cli/execution_errors.go
  • Packages/src/Editor/FirstPartyTools/Screenshot/EditorWindowCaptureUtility.cs
  • .agents/skills/uloop-simulate-mouse-input/SKILL.md
  • .claude/skills/uloop-simulate-keyboard/SKILL.md
  • Packages/src/Editor/FirstPartyTools/SimulateKeyboard/Skill/SKILL.md
  • .agents/skills/uloop-simulate-mouse-ui/SKILL.md
  • cli/internal/cli/connection_retry.go
  • .claude/skills/uloop-simulate-mouse-input/SKILL.md

Comment thread cli/internal/cli/connection_retry_test.go Outdated

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

1 issue found across 13 files (changes from recent commits).

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

Re-trigger cubic

Comment thread cli/internal/cli/connection_retry_test.go Outdated
The 40ms retry window left only ~30ms for the second request to dial
and receive its accepted ack, which could flake under CI scheduler
jitter. The window is now 150ms, and the failure response is held for
twice the window starting only after the accepted ack is written, so
the window has always expired when the failure arrives.
CI exposed a race in the expired-window busy masking: the connection
read/write deadline shares its wall-clock instant with the retry
context, and the i/o timeout can fire microseconds before the context
reports expiry, so the raw transport error leaked through both the
terminal branch and the no-process probe branch.

The mask no longer compares against the window deadline: after a busy
response in the window, any terminal non-RPC transport error reports
busy (parent cancellation still wins). Real RPC answers are recognized
with errors.As instead of the dispatch flag, which also fixes the
dispatched read-timeout case the flag-based guard regressed.
@hatayama hatayama merged commit 875fd91 into v3-beta Jun 11, 2026
8 checks passed
@hatayama hatayama deleted the feature/hatayama/improve-debug-break-usability branch June 11, 2026 13:04
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