On Windows, an alternate-screen TUI pane (Claude Code) could lose scroll-up
after being hidden (tab/worktree switch or app backgrounded) and shown again.
Root cause: on hidden->visible restore, applyMainBufferSnapshot
unconditionally wrote a destructive clear (\x1b[2J\x1b[3J\x1b[H) before
replaying the snapshot, wiping xterm's scrollback. The attach/reattach path
already guards this same clear behind !isAlternateScreen (pty-transport.ts);
the snapshot path did not.
Thread an alternateScreen flag from the backend headless serialization
through the pty:getMainBufferSnapshot IPC + preload types into
applyMainBufferSnapshot, and skip the destructive clear when restoring an
alternate-screen buffer. Add a regression test asserting the clear is NOT
emitted for an alt-screen restore (and the existing normal-buffer test still
asserts it IS).
Fixes#5723
Catch errors during hosted review lookup if local blockers are present.
This ensures that network or API failures do not completely hide the
Create PR preparation UI if we can still guide the user to resolve local
issues first.
* fix Orca CLI path resolution and improve registration UI
- Hydrate the shell PATH before running installer actions on macOS to
match the user's terminal instead of launchd.
- Resolve the active macOS command path dynamically against shell PATH
candidates, ignoring broken symlinks and non-executable files.
- Detect and report conflicts with unmanaged executables shadowing the
configured command path.
- Add "Preparing..." and "Registering..." loading states to the settings
and setup panels during preflight checks.
* Fix Orca CLI detection and installation path conflict checks
- Allow detecting a managed Orca command located later in PATH when the
default path entry is missing or non-executable.
- Avoid raising installation conflicts for unmanaged commands located
after the default install path, as they will be safely shadowed.
- Translate terminal setup and Orca CLI registration strings for
Spanish, Japanese, Korean, and Chinese locales.
* Only open terminal when pre-install checks succeed
Prevent the terminal from opening and setting the terminal command if
onBeforeOpenTerminal or refreshPreInstallNotice throws an error.
* Fix browser pane stuck in HTML fullscreen (#6442)
Guest content in a browser pane could enter HTML fullscreen but not
exit it: requestFullscreen() resized the host BrowserWindow into native
fullscreen, and exitFullscreen() had nothing to restore, leaving the
pane stuck.
Set the webview's disableHtmlFullscreenWindowResize preference so HTML
fullscreen is contained to the <webview> element. Exit then works and
fullscreenchange fires as guests expect.
* Apply browser guest fullscreen policy consistently
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
- Centralize and align auto-merge eligibility logic across web and
mobile clients.
- Use the `enablePullRequestAutoMerge` GraphQL mutation instead of
`gh pr merge --auto` to prevent immediate merges on clean branches.
- Fall back to `gh pr merge --auto` when a merge queue is required on
the base branch.
- Hide the auto-merge control when only optional checks are pending.
Windows runs managed hooks through a shell, and #6078 wrapped the
launcher in `powershell -EncodedCommand` to survive spaces in profile
paths. Combined with the inner PowerShell Invoke-WebRequest post, every
hook spawned two PowerShell processes (~300ms startup each), so a hook
took ~650ms+ and fired up to 6x per turn. Codex 0.140 renders that as
lingering "Running <event> hook" rows. The earlier RC worked around it
by deleting SessionStart/UserPromptSubmit/Stop, which loses lifecycle
status fidelity.
Keep all six Codex events and make them fast instead:
- Codex runs hooks as `cmd.exe /C <command>` and forwards our string
verbatim when it has no spaces/quotes, so emit the bare .cmd path for
cmd-safe profiles (zero shell startup) and fall back to the encoded
PowerShell launcher only for spaced/metachar paths (#6078 robustness).
- Replace the inner PowerShell post with curl.exe (Windows 10 1803+),
posting the same form fields as the POSIX hook and reading the raw
payload from stdin via `--data-urlencode payload@-` so UTF-8 (e.g. CJK)
survives without code-page translation.
Result: the common Codex case is 0 PowerShell (~70-150ms vs ~650ms);
spaced-path profiles drop to 1.
Claude runs hooks through Git Bash, so its launcher must stay
PowerShell-encoded (a bare path is what breaks it), but its inner post
moves to curl.exe too, cutting Claude from two PowerShell startups to
one.
Validated against the real Codex 0.140 binary (interactive TUI + exec):
all managed hooks fire, render briefly, and clear with no lingering
rows; the listener receives every post in 1-6ms.
Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* fix(automations): track exact run terminal targets
Record terminal pane keys and PTY ids on automation dispatches, persist them across run updates, and propagate them through runtime launch results.
Use the recorded pane and PTY for completion detection, session reuse, prompt submission, and View run navigation so split-pane tabs reopen the actual run terminal.
Keep legacy runs compatible by falling back to workspace resume when exact terminal identity is absent.
* chore: address automation targeting review cleanup
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
* fix(ports): stop cursor-move redraws corrupting advertised dev-server hosts
The Live Ports panel showed `localhst:5199` (and opened a broken URL with the
missing `o`) for a dev server that printed `http://localhost:5199`.
AdvertisedUrlWatcher cleans raw PTY bytes with stripTerminalControls, which
*deletes* ANSI/cursor sequences instead of emulating them. CLIs that redraw a
line differentially step the cursor forward over characters already on screen
(`ESC[1C`) rather than reprinting them; a real terminal renders the underlying
glyph, but deleting the move splices the two text runs together and drops the
skipped cell — `http://localh` + `ESC[1C` + `st` collapses to `localhst`.
`new URL()` then accepts the corrupted, plausible-looking host verbatim, so it
gets cached, displayed, copied, and opened.
Neutralize horizontal cursor moves (forward/back `C`/`D`, absolute column `G`,
position `H`/`f`) to a space before the CSI delete pass, so the URL candidate
matcher breaks at the seam and can't fuse a corrupted hostname. Worst case we
skip that frame and fall back to the kernel bind, which is the safe default.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(ports): document stripTerminalControls
Add a docstring to the exported helper to clear CodeRabbit's docstring
coverage warning and explain why horizontal cursor moves are neutralized.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(ports): invalidate cursor-redrawn URL candidates
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
* Adopt pending terminal tab reveals
* Materialize pending remote terminal tabs
Wait for mobile terminal creates to produce a ready PTY handle before resolving. If the renderer only publishes a pending tab shell, materialize a headless PTY into the same tab/leaf identity so later renderer focus adopts it instead of duplicating the tab.
Add a pane-key spawn reservation shared by runtime materialization and renderer pty:spawn so focus racing fallback reuses the winning PTY, including when SSH env stripping removes ORCA_PANE_KEY. Cover the pending-surface fallback and both overlapping spawn race directions with regression tests.
* Settle pane spawn reservation on any post-spawn failure
The per-paneKey spawn reservation was only settled on spawn error, persist
error, or final resolve. A throw in the post-spawn region (seedHeadlessTerminal,
registerPty, rememberPaneKeyForPty, track) rejected the IPC promise but left the
reservation in paneSpawnReservationsByPaneKey forever, so every later spawn for
that pane awaited a promise that never settled and hung.
Wrap each post-reservation body (both spawn paths) in a catch-all that rejects
the reservation with the real error and rethrows; reject is a no-op once
resolved. Remove the now-redundant inner reject calls. Add regression tests for
both paths.
* Tear down runtime-owned headless tabs on mobile session close
The renderer-attached branch of closeMobileSessionTab closed the renderer's
pane but never pruned mobileSessionTabsByWorktree or dropped the persisted
binding. For runtime-owned headless terminals — serve/SSH materialized, or a
pending shell the renderer never adopted, all introduced by the pending-surface
materialize fallback — syncMobileSessionTabs then re-hydrates the closed tab
from the persisted session, resurrecting it with a live PTY. "Close others" on
a paired client showed closed remote tabs reappearing with their sessions still
running.
Add isRuntimeOwnedHeadlessMobileTab (serve/SSH-owned, or no live PTY and absent
from the renderer graph). When the whole parent of such a tab is closed, route
through closeHeadlessMobileTerminalTab to kill the PTY, remove the persisted
binding, and prune+emit, then best-effort notify the renderer so no adopted
pane is left dead. Genuinely renderer-owned tabs and exact split-leaf closes
keep the existing path. Cover the serve parent close, renderer-published vs
runtime-unadopted pending tabs, and the serve split-leaf case with regressions.
* Tear down only headless tabs the renderer never published on mobile close
The close-others teardown discriminator returned false for any resolved
non-serve/ssh PTY, so headless tabs carrying a daemon session id
(<worktreeId>@@<shortUuid>) that the host materialized but the renderer never
published leaked into the session snapshot and the client mirrored them
(confirmed live: host published 5 tabs for a worktree the renderer showed 1 for).
That id shape is ALSO minted for ordinary renderer-owned daemon-backed local
terminals, so it can't classify ownership by shape — the renderer graph
(this.tabs) does. Classify a tab as runtime-owned when it is serve/ssh (always,
they're preserved + re-hydrated) or when the renderer graph never published it
(a leaked/unadopted shell); delegate everything the renderer graph lists,
including ordinary @@ local terminals and pending tabs.
Regression tests: renderer-owned @@ tab is delegated (not de-persisted); leaked
@@ tab the renderer never published is torn down + de-persisted.
* Style commit text area to match input tokens and fix disabled state
- Update borders and shadows to match standard input tokens.
- Style the disabled state explicitly to prevent Chromium's user-agent
styles from washing out the field outline.
- Add dark mode background styling overrides.
* Improve timeline items assertions in work-item-details test
Extract timelineItems to a local variable and add an explicit null check to prevent TypeScript compilation errors when calling the .at method.
* Add GitHub issue timeline activity feed to details dialog
Fetch and display issue timeline events (assignments, mentions, closes,
reopenings, and project board column moves) in a unified activity tab
within the GitHub item details dialog.
- Query the GitHub REST timeline endpoint up to a bounded 300 items.
- Merge comments and timeline events into a single sorted conversation.
- Render tailored icons, links, and localizable messages per event.
- Ensure issue reply targets are not incorrectly filtered by stale PR state.
- Correctly update local item state from details payload.
* Cap issue timeline pagination by supported activities
Count only mapped, supported timeline items instead of raw REST events
when checking the maximum item threshold. This prevents pagination from
stopping early when pages contain many unsupported event types.
* feat(agents): native Xiaomi MiMo Code support
Add mimo-code TUI agent (detect mimo, --prompt, --session resume).
Inject MIMOCODE_HOME overlay and /hook/mimo-code status plugin on mimo
launch when agent status hooks are enabled; restore via shell-ready
wrappers. Reuse OpenCode-family hook normalization in the listener.
SSH remote MiMo hook overlays are not included (local/daemon first).
Closes#6220
* fix(mimo): remirror overlay config idempotently
rmSync overlay config before mirror so a second mimo launch does not
hit EEXIST in mirrorEntry and fall back to the user MIMOCODE_HOME.
* review: harden mimo code support
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Doan Bac Tam <24356000+doanbactam@users.noreply.github.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
- Decouple heartbeat and worker_done logic from the main coordinator
to allow re-use in the orchestration.check RPC method.
- Reconcile unread lifecycle messages during orchestration.check so that
manual coordinators can authoritatively process completions and
heartbeats even if they bypass the main coordinator loop.
- Add unit tests validating task completion, heartbeat recording, and
safety checks against stale or unauthorized worker_done payloads.