Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
3799d95
Rename debug-break naming to pause-point across CLI, package, and skills
hatayama Jun 10, 2026
a552826
Make clear results explain why nothing was cleared
hatayama Jun 10, 2026
70d6c9a
Add a diagnosis hint to pause point wait timeouts
hatayama Jun 10, 2026
60035e5
Embed marker-matching logs in wait-for-pause-point output
hatayama Jun 10, 2026
e0ebb06
Document matching-log embedding and timeout hints in the pause point …
hatayama Jun 10, 2026
f420b07
Add a diagnosis hint to pause point expired errors
hatayama Jun 10, 2026
a7ec5c3
Document clear-pause-point --all and the expired-error hint in the skill
hatayama Jun 10, 2026
f2ecb52
Always embed matching logs in wait-for-pause-point responses
hatayama Jun 11, 2026
5aeca46
Unify MatchingLogs naming across hit responses and timeout details
hatayama Jun 11, 2026
d06e07b
Fall back to a project IPC probe when the launch process scan fails
hatayama Jun 11, 2026
7bc7ea8
Add --code-file input to execute-dynamic-code
hatayama Jun 11, 2026
6929738
Retry server-busy responses inside the bounded connection retry window
hatayama Jun 11, 2026
985ac72
Report press-edge observability from simulate-keyboard
hatayama Jun 11, 2026
b535e13
Regenerate skill copies for the launch, dynamic-code, and keyboard up…
hatayama Jun 11, 2026
feb8961
Move launch focus logging into its own file
hatayama Jun 11, 2026
7dc8409
Teach the single-flight contract in the busy envelope
hatayama Jun 11, 2026
5ee55fa
Hint that game state may have moved past an unhit pause point marker
hatayama Jun 11, 2026
2f2dbd0
Stop COMPILE_WAIT_TIMEOUT from reading as a frozen Editor
hatayama Jun 11, 2026
63abee1
Auto-refresh previously installed skill targets on skills install
hatayama Jun 11, 2026
303e8f3
Save RenderTexture.active before Blit in screenshot capture paths
hatayama Jun 11, 2026
e13d2f2
Report PressEdgeObserved on pause-point interrupted keyboard input
hatayama Jun 11, 2026
6f3fa9b
List every pause point hit on interrupted input simulation responses
hatayama Jun 11, 2026
d2efd6c
Document a time-freeze setup pattern for fast-progressing games
hatayama Jun 11, 2026
3d94018
Regenerate installed skill copies from updated sources
hatayama Jun 11, 2026
3a741f6
Add a Step action and replace the timeScale freeze guidance with it
hatayama Jun 11, 2026
fe0c918
Regenerate installed skill copies for the Step action
hatayama Jun 11, 2026
7bca19f
Release screenshot temporaries in finally blocks
hatayama Jun 11, 2026
495b3f6
Stop busy masking from hiding dispatched RPC failures
hatayama Jun 11, 2026
c2b02d1
Use the uloop command form consistently in simulate skill docs
hatayama Jun 11, 2026
f4d3c18
Remove timing race from the dispatched-failure retry test
hatayama Jun 11, 2026
5ebc51b
Make busy masking immune to connection-deadline timer races
hatayama Jun 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .agents/skills/uloop-control-play-mode/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ uloop control-play-mode [options]

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `--action` | string | `Play` | Action to perform: `Play`, `Stop`, `Pause` |
| `--action` | string | `Play` | Action to perform: `Play`, `Stop`, `Pause`, `Step` |
| `--timeout-seconds` | integer | `180` | Maximum seconds to wait for the requested play mode state |

## Global Options
Expand All @@ -41,6 +41,9 @@ uloop control-play-mode --action Stop

# Pause play mode
uloop control-play-mode --action Pause

# Advance exactly one frame while paused (Next Frame button)
uloop control-play-mode --action Step
```

## Output
Expand All @@ -57,5 +60,6 @@ Returns JSON with the current play mode state:
- Play action starts the game in the Unity Editor (also resumes from pause)
- Stop action exits play mode and returns to edit mode. If Play Mode was already stopped, `Changed` is `false`, `WasAlreadyStopped` is `true`, and `Message` is `Play mode was already stopped`.
- Pause action pauses the game while remaining in play mode
- Step action advances exactly one frame and leaves play mode paused (the Editor's Next Frame button; independent of Time.timeScale). Requires PlayMode to be running; repeat to walk transitions frame by frame
- Useful for automated testing workflows
- The command waits for the requested state before returning. Increase `--timeout-seconds` for projects with slow PlayMode entry.
9 changes: 6 additions & 3 deletions .agents/skills/uloop-execute-dynamic-code/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: uloop-execute-dynamic-code
toolName: execute-dynamic-code
description: "Execute C# with Unity APIs when existing uloop tools cannot inspect or edit enough. Use for scene, prefab, SerializedObject, AssetDatabase refresh/.meta generation, menu, or PlayMode automation."
description: "Execute C# with Unity APIs when existing uloop tools cannot inspect or edit enough. Use for reachable scene/component state, scene/prefab/menu automation, and PlayMode checks"
context: fork
---

Expand All @@ -11,6 +11,8 @@ Execute the following request using `uloop execute-dynamic-code`: $ARGUMENTS

For basic selected GameObject discovery or property inspection, use `find-game-objects --search-mode Selected` before this tool. Use this tool after the built-in inspection tools are not enough or when you need to modify Unity state.

This tool can inspect reachable Unity state, such as GameObjects, components, public properties, static values, and method results. It cannot directly read local variables or intermediate calculations inside an already-running method. When those values matter, add a focused `Debug.Log` immediately before `UloopPausePoint.Pause("<id>")`, then run `get-logs --search-text <id>` while Unity is paused. Do not replace that log read with execute-dynamic-code.

## Workflow

1. Read the relevant reference file(s) from the Code Examples section below
Expand All @@ -21,8 +23,9 @@ For basic selected GameObject discovery or property inspection, use `find-game-o

## Parameters

- `--code '<code>'` (required): Inline C# statements to execute. Use direct statements only; `return` is optional, and `using` directives may appear at the top of the snippet.
- **Shell quoting**: bash/zsh uses single quotes, for example `uloop execute-dynamic-code --code 'using UnityEngine; return Mathf.PI;'`. PowerShell doubles inner quotes (`'Debug.Log(""Hello!"");'`).
- `--code '<code>'`: Inline C# statements to execute. Use direct statements only; `return` is optional, and `using` directives may appear at the top of the snippet.
- `--code-file <path>`: Read the C# statements from a file instead of `--code`. Prefer this for long or multi-line snippets because it removes shell quoting entirely. Exactly one of `--code` or `--code-file` is required; combining them is an error.
- **Shell quoting**: bash/zsh uses single quotes, for example `uloop execute-dynamic-code --code 'using UnityEngine; return Mathf.PI;'`. PowerShell doubles inner quotes (`'Debug.Log(""Hello!"");'`). With `--code-file` no quoting is needed.
- `--parameters {}` (advanced, optional): Pass an object when reusing a snippet with varying data or when keeping values outside the code. Values are exposed as `parameters["param0"]`, `parameters["param1"]`, and so on. Omit this flag for most snippets, and pass an object instead of a JSON string.
- `--no-wait-for-domain-reload` (optional): Return without waiting for Domain Reload recovery. Omit this for normal editor mutation workflows.

Expand Down
4 changes: 3 additions & 1 deletion .agents/skills/uloop-get-logs/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
---
name: uloop-get-logs
toolName: get-logs
description: "Read current Unity Console entries from a running Editor. Use during bug investigation after compile, tests, PlayMode, or dynamic code to inspect logs, warnings, errors, and stack traces."
description: "Read current Unity Console entries from a running Editor. Use during bug investigation after compile, tests, PlayMode, dynamic code, or immediately after `uloop-wait-for-pause-point`."
---

# uloop get-logs

Retrieve logs from Unity Console.

When a pause-point marker pauses Unity and the value you need is a method local, intermediate calculation, or branch reason, read the focused `Debug.Log` entry added immediately before the marker before resuming PlayMode. Use `--search-text <marker-or-id>` so the marker and its log are checked as one breakpoint-style proof.

## Usage

```bash
Expand Down
1 change: 1 addition & 0 deletions .agents/skills/uloop-launch/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ uloop launch --quit
- Prints detected Unity version
- Prints project path
- If Unity is already running, focuses the existing window and verifies tool readiness
- If the process scan is blocked by the environment (e.g. sandboxed `ps`), plain launch falls back to probing the project IPC; when Unity responds it reports `AlreadyRunning: true` without focusing the window instead of failing. `--restart` and `--quit` still fail because they need the process id
- If launching or restarting, prints when it is waiting for Unity CLI Loop server readiness
- If launching or restarting, waits until Unity finishes startup and the CLI can connect to the project
- Successful launch, restart, existing-process, and quit paths return JSON with:
Expand Down
40 changes: 22 additions & 18 deletions .agents/skills/uloop-simulate-keyboard/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ Simulate keyboard input on Unity PlayMode: $ARGUMENTS
## Workflow

1. Ensure Unity is in PlayMode (use `uloop control-play-mode --action Play` if not)
2. Execute the appropriate `uloop simulate-keyboard` command
3. Take a screenshot to verify the result: `uloop screenshot --capture-mode rendering`
4. If the screenshot cannot prove the gameplay state, place and enable a `UnityCliLoopDebug.Break("<id>")` marker with `uloop enable-debug-break`, run the input again, then inspect while Unity is paused
5. Report what happened
2. Execute the needed `uloop simulate-keyboard` commands
3. Inspect the result with the lightest useful evidence: runtime state, logs, or a screenshot
4. If exact-frame proof would reduce uncertainty, treat Pause Point inspection as an optional follow-up using the section below
5. Report what happened and which evidence was used

## Tool Reference

Expand All @@ -39,17 +39,19 @@ uloop simulate-keyboard --action <action> --key <key> [options]
| `KeyDown` | KeyDown only (held until KeyUp) | Start continuous movement, hold sprint |
| `KeyUp` | KeyUp only (release held key) | Stop movement, release sprint |

Use `Press` for edge-triggered gameplay code such as `Keyboard.current.spaceKey.wasPressedThisFrame`.
Use `Press` for edge-triggered keyboard code such as `Keyboard.current.spaceKey.wasPressedThisFrame`.
`KeyDown` emits one initial press edge, then only keeps the key held. It does not keep `wasPressedThisFrame` true while the key remains held.
If a successful `Press` or `KeyDown` leaves `Keyboard.current.<key>.isPressed` true but the game state does not change, do not immediately rewrite the user's gameplay code to `isPressed`. First verify that the gameplay component is active during the command, that it polls input in the configured Input System update phase, and that a missed `KeyDown` edge is followed by `KeyUp` before retrying.
If a successful `Press` or `KeyDown` leaves `Keyboard.current.<key>.isPressed` true but runtime state does not change, do not immediately rewrite the user's runtime code to `isPressed`. First verify that the target component is active during the command, that it polls input in the configured Input System update phase, and that a missed `KeyDown` edge is followed by `KeyUp` before retrying.
Use `KeyDown` / `KeyUp` when the scenario intentionally needs a held key.

### Debug Break verification
### Pause Point Inspection (Standard for E2E)

- Use `UnityCliLoopDebug.Break("<id>")` when a screenshot cannot prove that the keyboard input changed gameplay state, such as jump, sprint, or interaction.
- Put the marker at a natural state transition after the game consumed the key, such as after jump velocity is applied, not immediately after sending `simulate-keyboard`.
- If the response has `InterruptedByDebugBreak: true`, Unity is paused for inspection and the tool released its held input bookkeeping. If a `UnityCliLoopDebug.Break` marker caused the pause, `DebugBreakId` and `DebugBreakHitCount` identify it. Use `get-logs`, `get-hierarchy`, `find-game-objects`, or `execute-dynamic-code` before resuming.
- Use distinct marker ids for strict phases, for example `jump-key-read` and `jump-velocity-applied`.
- Use `UloopPausePoint.Pause("<id>")` with `uloop-wait-for-pause-point` as the standard frame proof when this input drives a state transition you are verifying. Final logs, screenshots, and durable state supplement the paused-frame check but do not replace it.
- Put the marker at a natural state transition after the app consumed the key, such as after a command is accepted, a state mutation is committed, an evaluation step resolves, or a dependent component is updated. Do not place it immediately after sending `simulate-keyboard`.
- If the key handler has local variables, intermediate calculations, or branch reasons that `execute-dynamic-code` cannot inspect after the fact, log just those values near `UloopPausePoint.Pause("<id>")` and read them with `uloop-get-logs` while Unity is paused. A pause point hit proves the line was reached, not the frame-local values.
- Treat `simulate-keyboard Success=true`, generic action logs, and final durable counters as useful evidence, but not as paused-frame proof.
- If the response has `InterruptedByPausePoint: true`, Unity is paused for inspection and the tool released its held input bookkeeping. If a `UloopPausePoint.Pause` marker caused the pause, `PausePointId` and `PausePointHitCount` identify it. Use `uloop get-logs`, `uloop get-hierarchy`, `uloop find-game-objects`, or `uloop execute-dynamic-code` before resuming.
- Use distinct marker ids for strict phases, for example `input-read`, `state-updated`, and `result-committed`.

### KeyDown/KeyUp Rules

Expand All @@ -68,16 +70,16 @@ Use `KeyDown` / `KeyUp` when the scenario intentionally needs a held key.
## Examples

```bash
# One-shot key press (tap W once)
# One-shot key press
uloop simulate-keyboard --action Press --key W

# Jump (tap Space)
# One-shot action key
uloop simulate-keyboard --action Press --key Space

# Hold W for 2 seconds (move forward)
# Hold a key for 2 seconds
uloop simulate-keyboard --action Press --key W --duration 2.0

# Sprint forward (hold Shift + W, then release)
# Hold two keys, then release them
uloop simulate-keyboard --action KeyDown --key LeftShift
uloop simulate-keyboard --action KeyDown --key W
uloop screenshot --capture-mode rendering
Expand All @@ -92,9 +94,11 @@ Returns JSON with:
- `Message` (string): Description of what happened or why it failed
- `Action` (string): The `--action` value that was applied (`Press`, `KeyDown`, or `KeyUp`)
- `KeyName` (string, nullable): The key that was acted on; may be `null` when the action could not resolve a key
- `InterruptedByDebugBreak` (boolean): True when Unity paused during Debug Break inspection and the input bookkeeping was safely released
- `DebugBreakId` (string, nullable): The marker id when a `UnityCliLoopDebug.Break` marker caused the interruption
- `DebugBreakHitCount` (integer, nullable): The marker hit count when a `UnityCliLoopDebug.Break` marker caused the interruption
- `InterruptedByPausePoint` (boolean): True when Unity paused during Pause Point inspection and the input bookkeeping was safely released
- `PausePointId` (string, nullable): The marker id when a `UloopPausePoint.Pause` marker caused the interruption
- `PausePointHitCount` (integer, nullable): The marker hit count when a `UloopPausePoint.Pause` marker caused the interruption
- `PausePointHits` (array, nullable): Every marker hit during this input as `{Id, HitCount}` entries, in hit order. Read this when one input may trigger several markers; `PausePointId` only names the latest one
- `PressEdgeObserved` (boolean, nullable): For `Press` and `KeyDown`, whether the press edge (`wasPressedThisFrame`) was actually visible inside a gameplay input update. `false` means the CLI succeeded but gameplay polling most likely missed the edge (e.g. the press was consumed by an editor-only input update) — retry the input or verify with a focused log instead of trusting `Success` alone. `null` only for `KeyUp` and for timed-out responses; pause-point interruptions still report the observed value

## Prerequisites

Expand Down
Loading
Loading