Avoid automatically managing or overwriting manually entered or prefilled
workspace names in the composer state. This ensures user-authored names
are preserved and not overridden by linked-item or AI-generated naming,
unless the prefilled name matches the linked work item seed.
* Wire terminal-initiated worktree navigation to back-and-forth stack
* Unify terminal-driven worktree activation and Cmd+J recency marking.
* Record worktree visits in the back/forward history stack unless navigating history.
* Resolve stale terminal focus and ignore late exits from old PTYs
- Repair the active terminal pane leaf selection when a pane's PTY exits, preventing focus from being stranded on a dead pane.
- Ensure stale, pruned, or unbound terminal leaves are not persisted as active in visual layouts or shutdown snapshots.
- Ignore late exit notifications and subscription end events from old PTY transports or remote stream handles after a reconnect or rebind.
* Prevent active terminal focus on dead panes and ignore stale PTY events
- Redirect active keyboard focus to a live, PTY-backed sibling pane
if the focused pane dies, fails to spawn, or is hydrated without a
live connection.
- Ignore stale data, replay messages, and subscription rejection errors
from older PTY sessions after a transport has reconnected.
- Avoid persisting stale PTY bindings and dead pane focus inside
terminal shutdown layout snapshots.
* Clear pending input when attaching a different remote terminal handle
When switching between different remote terminal handles, debounced input
meant for the previous terminal could get incorrectly flushed and sent
to the newly attached terminal.
Fix this by clearing the batcher's pending state (text and byte counts)
and invoking `inputBatcher.clear()` if the attached terminal handle
changes.
* Add window wake recovery hook for visible terminal panes
- Extract and enhance window focus and visibility change recovery logic
into a dedicated `useTerminalWindowWakeRecovery` hook.
- Recover the xterm renderer, input surface, and WebGL texture atlases
when macOS/display wakes or the window/tab regains focus.
- Schedule recovery steps with requestAnimationFrame to ensure the
terminal layout settles correctly.
* Fix mutable variable capturing in remote transport test
Avoid mutating a local `let` variable from inside a Promise executor
closure by wrapping the rejection callback in a `const` object.
* Prevent duplicate terminal wake recovery on overlapping window events
When window focus and visibility events fire concurrently, they can trigger multiple redundant wake recovery passes.
- Return early if a wake recovery frame is already scheduled.
- Keep the scheduled animation frame instead of canceling it to ensure we get a settled recovery pass.
Defect 1: the typed GitLab MR search query was dropped before reaching
the API. Thread query?: string end-to-end through the renderer effect,
the source-lookup, the preload/RPC args, and the desktop IPC handlers
(which previously passed a hardcoded undefined), and honor it on both the
glab REST path (&search=) and the cwd-inferred 'glab mr list' fallback.
Defect 2: when MR base resolution failed the renderer silently returned,
leaving baseBranch undefined so the worktree was created off the repo
default branch (origin/master) with no feedback. Surface the failure via
toast and clear stale base state, mirroring the GitHub PR path. Also make
resolveManagedMrBase resilient to an optional compare-base (target branch)
fetch failure: degrade gracefully by dropping compareBaseRef instead of
aborting, so a merged MR with a deleted target ref still resolves to its
valid source-branch base.
Fixes#6263
Co-authored-by: Orca <help@stably.ai>
* perf: dedupe relay process-table scans behind a short-TTL cache (#6288)
Agent foreground-process inspection runs `ps -axo pid=,ppid=,stat=,command=`
(a full system process-table scan) on a 750ms/2000ms per-pane cadence. On a
shared SSH relay every tracked agent terminal drives it, so concurrent panes
each forked their own `ps` — sustaining up to the per-second inspection cap of
full-table scans for as long as agents are open, pinning idle relay CPU and
amplified by AV process scanning. This is the CPU half of #6288 (PR #6564
covers the memory-leak half).
Memoize the scan behind a single in-flight promise + 500ms TTL shared by the
relay and local main-process call sites. 500ms sits below the active poll's
minimum inter-poll gap (~675ms after jitter), so a single pane never reuses a
snapshot older than it would have scanned itself — same data and freshness,
just deduplicated within the cadence window (worst case ~8 scans/sec -> ~2).
Failures are never cached (in-flight cleared on settle) so a transient `ps`
error retries and the existing best-effort fall-through is preserved. Windows
branches are untouched; no git-provider implications.
Co-authored-by: Orca <help@stably.ai>
* test: regression guard for #6288 ps-scan volume (repro + measurement)
Drives the real local foreground-inspection call site under the documented
750ms agent-completion cadence across 6 concurrently-inspecting agent panes
over a 30s window, counting actual `ps -axo pid=,ppid=,stat=,command=`
full-table scans.
Reproduces the waste on `main` (240 inspections -> 240 scans, 1.0/inspection;
the test fails there) and proves the fix (240 inspections -> 40 scans,
0.167/inspection — bounded by poll ticks, not pane count) while every pane
still resolves its foreground agent. Guards against regressing the cache back
to a per-call scan.
Co-authored-by: Orca <help@stably.ai>
* docs: clarify 500ms TTL covers cadence floor + tolerated event-driven staleness (#6288)
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
Fixes#6288. Bounds preload runtime subscription IPC listeners to one active dispatcher per renderer and releases subscription state on terminal cleanup paths.
Pi (pi.dev) and OMP are goal/mission agents whose normalizePiCompatibleEvent
maps milestone agent_end -> hook state 'done' while they are still working.
observeHookStatus gated the quiet window on `workingStatusObserved`, so these
intermediate 'done' events (workingStatusObserved === false) fell through to an
immediate "agent finished" notification while the TUI kept spinning, and a
follow-up working event could not cancel it.
Route Pi/OMP 'done' through the existing quiet window via a new
doneShouldUseQuietWindow() predicate (delegating to a shared
isPiCompatibleAgentType on the canonical PiAgentKind), so resumed work cancels
the premature notification. Codex and other turn-end-only producers keep their
immediate dispatch.
Also harden the process-exit backstop: skip the agent-evidence teardown while a
quiet-window 'done' is pending, otherwise a poll that finds the agent gone would
clear hasAgentRunEvidence and the timer would silently drop the real completion.
Co-authored-by: Orca <help@stably.ai>
Add Project → Browse folder on a monorepo subfolder (e.g. /tmp/monorepo/packages/web)
stored the subfolder as Repo.path because isGitRepo() uses
`git rev-parse --is-inside-work-tree`, which is true for any subdirectory.
Authoritative worktree resolution then snapped activation back to the repo root,
so the import identity mismatched and the first terminal landed at the repo root
rather than the selected subfolder.
Canonicalize local git imports to the actual repo root via getGitRepoRoot()
(mirroring the SSH import path that snaps to check.rootPath, including its
post-resolution dedup), and preserve the user-selected subfolder as a one-shot
initial terminal cwd consumed only by the first activation-created pane.
Selecting the repo root applies no override, and re-importing a subfolder of an
existing project dedupes.
Supersedes community PR #6362.
Fixes#6336
Co-authored-by: Rod Boev <rodboev@users.noreply.github.com>
* Remove tracked node_modules symlink
The node_modules directory was accidentally committed as a symlink
pointing to a developer's local absolute path. This breaks builds in
CI and on other developer environments.
* Fix direct launch remote test expectations
* fix(terminal): forward synthesized/dictated text dropped under kitty keyboard protocol
With xterm's kitty keyboard protocol active, xterm encodes a printable key
on keydown and preventDefaults it, which cancels Chromium's native
insertText on the helper textarea. The IME punctuation forwarder added in
#6417 was gated to CJK input sources (isEnabled), so on a non-CJK (e.g. U.S.
Latin) input source it never armed and any synthesized text — dictation,
text expanders, accessibility / CGEvent injection — was silently dropped
before reaching the PTY.
Part A: drop the CJK-only gate so the forwarder arms on macOS regardless of
input source (the drop affects every locale, not just CJK punctuation).
Part B: forward a standalone non-composing insertText that no key event
produced. Injected prose/words never satisfy the punctuation-keydown claim
path, so recover them from the helper-textarea input event, guarded against
double-send (key-activity attribution, unresolved claimed press), against
composition (insertCompositionText + composition-commit), and via
stopImmediatePropagation so xterm's own _inputEvent cannot also forward.
Fixes#6513
Co-authored-by: Orca <help@stably.ai>
* fix: broaden terminal injected text forwarding
---------
Co-authored-by: Orca <help@stably.ai>
Previously, transient errors during candidate branch discovery (such as
rate limits or network issues) were silently ignored, leading to a
false "no-pr" result and causing the sidebar PR state to flicker.
Now, track and return any pending error encountered during branch
lookups, propagating it as an upstream error if no PR is successfully
recovered.
* Migrate terminal scrollback setting from bytes to rows
Transition terminal scrollback configuration from a byte-based (MB)
limit to a row-based count to align with standard terminal emulator
behavior.
- Introduce a shared scrollback policy to handle normalization and
safe migration of legacy byte presets to row equivalents.
- Update persistence logic to automatically convert and clean up legacy
settings on startup and write-back.
- Refactor the advanced settings interface and localization strings
to let users configure scrollback in terms of rows (up to 50k).
- Live-apply row limit changes directly to mounted xterm instances
without recreating panes or restarting PTY sessions.
* Migrate terminal scrollback setting from bytes to rows
Transition terminal scrollback configuration from a byte-based (MB)
limit to a row-based count to align with standard terminal emulator
behavior.
- Introduce a shared scrollback policy to handle normalization and
safe migration of legacy byte presets to row equivalents.
- Update persistence logic to automatically convert and clean up legacy
settings on startup and write-back.
- Refactor the advanced settings interface and localization strings
to let users configure scrollback in terms of rows (up to 50k).
- Live-apply row limit changes directly to mounted xterm instances
without recreating panes or restarting PTY sessions.
* defer updating terminal scrollback rows until blur or Enter
Avoid committing terminal scrollback row setting changes on every
keystroke, which can trigger rapid updates with incomplete or
invalid numbers. Instead, manage a local draft state and commit to
settings only when the input is blurred or the user presses Enter.
* Replace automation pause/resume button with an on/off toggle
The External automations list showed two play-glyph icon buttons side by
side when a job was paused: a run button and a pause/resume button. Replace
the pause/resume button with an on/off Switch beside the Active/Paused badge,
leaving the action cluster with just Run, Edit, and Delete.
Co-authored-by: Orca <help@stably.ai>
* Document why the in-flight spinner matches both action keys
Co-authored-by: Orca <help@stably.ai>
* Move automation toggle to the trailing edge of the row
Co-authored-by: Orca <help@stably.ai>
* Align automation toggle to the right of the title line
Co-authored-by: Orca <help@stably.ai>
* Pin automation toggle to the row's right edge
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
* fix(terminal): support Windows shell selection for SSH hosts
* fix(runtime): register SSH Windows capability preflight RPC
* fix(terminal): honor remote Git Bash and split preflight IPC seams
* fix(terminal): keep SSH Windows shell state tied to the selected host
* fix(terminal): preserve Windows SSH shell selection
---------
Co-authored-by: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
* Redesign the search button in the sidebar to look like a standard input field with a border, background, and absolute icon positioning.
* Replace the basic `<kbd>` label with `ShortcutKeyCombo` elements driven by `useShortcutKeyComboDetails`.
* Show the shortcut combinations when the search container is focused as well as hovered.
Follow-up to #6644. The merged fix used a single post-spawn
requestAnimationFrame, which did not fully close the first-mount column
race: the pane's real layout can keep changing for several frames (split
equalize, sidebar/title reflow), so a one-shot re-fit could still measure a
stale width and leave the PTY pinned. The golden 'during initial mount' e2e
test failed ~1 in 9 runs with the single-frame version.
Poll for up to 12 frames, forwarding the settled size to the PTY only when
it differs from what the PTY was last told (mirroring the existing
ResizeObserver stability loop). Each resize is gated on an actual change, so
a TUI sees at most a couple of SIGWINCH during startup, not a loop.
Verified: golden test passes 6/6 with repeat-each + retries; full spec
15/15. Without this change the single-frame version is intermittently flaky.
Co-authored-by: Orca <help@stably.ai>