* Fix automatic branch rename for non-English git locales
A gettext-enabled git (Homebrew git, most Linux distro gits) under a
non-English locale translates every diagnostic, including the `fatal:`
prefix, so Orca's stderr phrase parsers stop matching. The first-message
branch auto-rename was the headline casualty: isNoUpstreamError missed
the translated no-upstream error, branchHasUpstream failed closed to
"has upstream", and the rename settled silently and permanently.
- Force LC_ALL=C on all Orca-spawned machine-parsed git: the local
prompt-guard env chokepoint, the three relay git spawn sites, and both
local clone spawns (progress + failure-message parsing). User
terminals are untouched.
- Replace the boolean upstream check with a tri-state probe: rename
proceeds only on a proven missing upstream; an unreadable probe now
raises the rename-failed badge and retries instead of settling.
Fixes#7808🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
* Consolidate untranslated-git-locale into runner and relay primitives
Replace the five per-site LC_ALL=C patches with one shared
UNTRANSLATED_GIT_OUTPUT_ENV (LANGUAGE=en LC_ALL=en_US.UTF-8
LANG=en_US.UTF-8) injected inside the git runner primitives
(promptGuardGitEnv, gitSpawn, gitExecFileSync, gitExecFileAsyncBuffer)
and a relay buildRelayGitEnv() helper, so every current and future
machine-parsed git spawn is covered by construction — including the
fs-handler-git-fallback sites the per-site approach missed. The UTF-8
English locale keeps a UTF-8 LC_CTYPE for hooks git spawns; LANGUAGE is
pinned because gettext consults it before LC_ALL.
WSL-routed git gets the same values as a shell assignment prefix built
in resolveCommand, since spawn env cannot cross the wsl.exe boundary —
closing the WSL gap the first pass accepted.
Also scrub credential-bearing remote URLs from the probe-failed message
surfaced on the worktree card.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
* Scrub credential-bearing URLs from clone failure messages
---------
Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
Co-authored-by: Claude <noreply@anthropic.com>
* feat(rate-limits): Grok CLI OAuth weekly credit usage in status bar
Read ~/.grok/auth.json (read-only), fetch billing credits via cli-chat-proxy, and surface Grok in Settings, status bar toggles, and rate-limit polling alongside other usage providers.
* fix(grok): clarify comments and address CodeRabbit review
- Shorten Why comments per AGENTS.md; fix billing period end fallback.
- Share GrokAccountStatus type; hash-based locale keys; reload why in Settings.
* docs(grok): plain-language comments and Settings copy
* feat(stats): subscription usage section with Grok in Stats & Usage
Surface rate-limit weekly credits in Settings > Stats & Usage and link to Accounts for setup.
* feat(stats): Grok tab in Usage Analytics dropdown
* refactor(stats): drop Subscription usage block; align Grok pane with Codex
* fix(grok): align settings copy and visibility tests
* fix(grok): add localization catalog entries
* fix(grok): avoid eager usage refresh fanout
* fix(grok): harden usage refresh visibility
* test(grok): cover account status privacy boundary
* fix(grok): target refreshes and redact auth errors
* fix(grok): hide usage UI for signed-out users and align empty states
- Treat a token-less auth.json (e.g. after grok logout) as signed out
instead of surfacing a permanent status-bar error.
- Map billing responses without credit usage to 'unavailable' so plans
with no weekly credits hide the bar like Claude API-key billing.
- Gate the grok status-bar item and toggle on CLI PATH detection,
matching claude/codex/gemini/kimi.
- Guard an empty GROK_CLI_CHAT_PROXY_BASE_URL from producing a
relative billing URL.
- Drop dead minimax/kimi Stats & Usage search keywords left from the
removed subscription section.
- Add missing grok search keyword catalog entries and translate the
English-stubbed stats keywords in es/ja/ko/zh.
* test(ipc): mock grok account registrar in register-core-handlers test
---------
Co-authored-by: Brennan Benson <brennanbenson@Brennans-MacBook-Pro.local>
Add attribute filters (status, priority, assignee, labels) to the Linear
issues list, applied in GraphQL before pagination so hasMore matches the
filtered set. Thread filters through IPC/RPC/store cache with invalidation
on issue mutations, and mirror GitHub-style filter chrome on TaskPage.
* Support WSL Codex settings promotion and harden config write-back
- Enable settings promotion for WSL runtimes using per-distro baselines.
- Create parent directories if missing to prevent promotion ENOENTs.
- Keep restrictive permissions (0600) and follow symlinks on promote.
- Respect CRLF line endings when inserting keys into CRLF config files.
- Skip redundant baseline file writes when settings are unchanged.
- Include the release scan report for the 1.4.131-rc2 prep.
* Refactor sleeping agent wake flow and fetch rate limits via backend
- Background-mount only targeted terminal tabs during passive wake to
prevent spawning unnecessary PTYs for unvisited tabs.
- Latch edge-triggered wake requests that arrive mid-hibernation and
track active claims to prevent double-resuming a provider session.
- Query the ChatGPT wham usage backend API directly with fetch for
rate limits, avoiding launching Codex or WSL login shells.
- Asynchronously probe and serialize WSL auth files with timeouts to
prevent synchronous I/O from stalling Electron's main process.
- Fix config promotion edge cases such as missing parent directories,
dangling symlinks, and atomic write permission widening.
* Support WSL dotfile-symlink write-back and lengthen redeem timeout
- Preserve symlinked Codex config on WSL by writing through the
existing file instead of atomic-rename, since \\wsl$ symlink
metadata isn't reliably detected and rename would clobber the link.
- Tighten new ~/.codex directory creation to 0700 (holds auth.json).
- Give explicit reset-credit redemption a 30s backend timeout instead
of the 10s background-poll default, since it's user-triggered.
- Read sleeping-agent session state from the worktree's actual
execution-host partition instead of always the local one, so the
headless-wake check works correctly for SSH-hosted worktrees.
- Isolate serve-sim watcher tests from the real $TMPDIR/serve-sim
state file to avoid leaking unrelated events.
* fix: propagate hook-only agent status to Remote Orca Server clients
On a headless Remote Orca Server, agent-status hooks (OSC 9999) updated the
retained row map but never republished PTY-backed session snapshots — only
terminal *title* changes did. Paired desktop/web/mobile clients therefore
kept a stale agent state (e.g. opencode working/idle) until relaunch, and
even title-driven updates carried an empty prompt and no agent identity
because the snapshot builder only used the title heuristic (#7970).
- retainAgentRowSnapshot reports client-visible changes (state, prompt,
agent type, tool, interactive prompt, interrupted) so handlePtyData can
republish snapshots on hook-only transitions without fanning out a
rebuild per repeated same-state hook ping.
- buildPtyMobileAgentStatus prefers the fresh retained hook payload over
the title-only fallback, so clients see the real state/prompt/agentType
and interactive prompts. The non-agent-title suppression (#1437 stuck
spinners) still wins unless the hook shows a live tool/question signal,
and it now also covers leaf-backed panes with no PTY record.
Co-authored-by: Orca <help@stably.ai>
* fix: refetch remote projects when the client-events stream replays
worktreesChanged/reposChanged emitted during a transport gap are lost, not
queued. A quick drop can replay without flipping the environment
unreachable, so the reachability-transition refetch never runs and a
server-created worktree stays invisible until relaunch (#7970). Request a
debounced project refresh on the replay tag, mirroring the SSH-state
refetch that already rides it.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
* Harden layout validation, watcher lifecycle, and connection robustness
- Throw instead of silently skipping when the packaged daemon-entry is
missing, preventing layout regressions from passing build checks.
- Terminate idle parcel-watcher processes to reclaim native handles and
avoid crash-prone native node module teardowns on shutdown.
- Bind the persisted WS fallback port first to prevent orphaning active
mobile pairings when the preferred port becomes free again.
- Cap concurrent disk reads for restored dirty tab verification at three
to prevent startup connection bottlenecks on remote SSH workspaces.
* Queue file IDs instead of snapshots in restored conflict scans
This avoids using stale file snapshots (e.g., outdated disk signatures)
if a tab is saved, closed, or re-baselined while waiting in the queue
behind the concurrency limit. The live state is now fetched from the
store and validated immediately before initiating the disk read.
* fix(mobile): normalize Grok rotating OSC titles at the main observation boundary
Desktop already collapses Grok Build's rotating working frames via the
renderer's normalizeTerminalTitle, but the main process stored raw OSC
titles, so mobile session tabs (fed from pty.lastOscTitle) still saw a
distinct title every spinner frame and re-touched snapshots each time.
Apply normalizeTerminalTitle once where main records an observed OSC
title, before the prevTitle comparison that gates session-tab and
mobile-snapshot touches, and normalize hydration-seeded titles the same
way so the first live frame after a seed compares equal. Agent status
stays detected from the raw title, mirroring the renderer tracker.
Covers remoted/SSH PTYs too since they surface through the same main
observation path.
Co-authored-by: Orca <help@stably.ai>
* Fix Grok and Pi terminal title normalization and status detection
- Require a strict "spinner - phrase - grok" pattern for Grok working
titles to prevent false positives on other agent tasks ending in
"- grok" (such as Claude or Codex).
- Treat collapsed "Pi" and "OMP" synthetic titles as idle by default
to prevent them from reverting to neutral status after normalization.
- Prevent duplicate mobile session tab updates during Grok status
frame rotations by ensuring they normalize to a stable title.
---------
Co-authored-by: Orca <help@stably.ai>
* Sweep all persisted carriers of a removed SSH target id on re-adoption
reassignSshTargetId re-pointed repos and worktree metas but left the old
target id embedded in persisted session pty ids (ssh:<id>@@pty-N in tabs,
layouts, remoteSessionIdsByTabId), the startup reconnect list
(activeConnectionIdsAtShutdown, replayed via ssh.connect at boot — the
exact 'SSH target not found' in STA-1468), sleeping-agent resume records,
provisioned project host setups, sidebar host-scope arrays, and relay pty
leases. Any survivor resurfaces later as a failing connect or reattach.
New ssh-target-id-migration module re-points every carrier in one pass,
wired into reassignSshTargetId with per-carrier unit and store-level
round-trip tests.
Co-authored-by: Orca <help@stably.ai>
* Bridge SSH connection state to paired remote clients
The SSH surface was desktop-only: ssh:state-changed went to the host's
own BrowserWindow and the web client's ssh API was a no-op stub, so a
paired client's reconnect overlay never learned the host connected and
its target labels stayed empty (STA-1468 — overlay stuck on 'please
connect' over a live terminal).
- New sshStateChanged runtime client event, emitted from broadcastSshState
through OrcaRuntimeService onto the existing clientEvents stream.
- New ssh.listTargets / ssh.listRemovedTargetLabels RPC methods next to
the previously unused ssh.getState / ssh.connect.
- Web preload now routes listTargets / listRemovedTargetLabels / getState
/ connect to the paired host's runtime RPC instead of stubbing them.
- useIpcEvents applies sshStateChanged on paired web clients through the
same guarded path as desktop ssh.onStateChanged; desktop clients ignore
the event since a foreign runtime's targets would pollute their local
SSH store.
Co-authored-by: Orca <help@stably.ai>
* Harden the SSH reconnect overlay against stale or unknown target state
- Only present the destructive 'SSH host removed' state on positive
evidence (a removal tombstone label, or a hydrated non-empty target
list lacking the id). A client whose SSH state never hydrated has an
empty labels map for every id and must not offer workspace removal.
- After a failed Connect, resync target metadata so a stale overlay
converges to the ghost/re-adopted state instead of offering the same
failing Connect forever (the repeated 'SSH target not found' toast
loop in STA-1468).
Co-authored-by: Orca <help@stably.ai>
* Address CodeRabbit review on #7767
- Re-key workspaceSessionsByHostId partitions stored under a removed SSH
host id during re-adoption (no writer keys partitions by ssh host today,
but the schema tolerates it — re-key instead of stranding; live partition
wins when both keys exist).
- Track SSH target-list hydration explicitly (sshTargetsHydrated) instead
of inferring it from a non-empty label map, so a legitimately empty
target list still counts as removal evidence and a never-hydrated client
still never offers destructive removal.
- Apply the refreshed target list before the best-effort removed-labels
fetch in the overlay resync, so a labels failure can't discard it.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
* fix(runtime): keep same-path imports host-qualified (#7018)
* review: harden runtime repo host match against SSH-repo hijack
An unstamped repo with a connectionId is an SSH repo (resolves to
ssh:<id>), so a same-path runtime import must not adopt it into a
runtime/local host. Match/adopt an unstamped repo only when it has no
connectionId, mirroring the existing local-IPC dedup guard
(src/main/ipc/repos.ts). Adds a regression test that fails without the
guard (SSH repo hijacked into runtime host).
Co-authored-by: Orca <help@stably.ai>
* review: only runtime hosts backfill an unstamped repo
A legacy unstamped repo is indistinguishable from a genuine local repo
(both have null executionHostId and connectionId). Restrict the adoption
branch to runtime incoming hosts so a local/ssh import at a colliding
path can never re-attribute a real local project to the wrong host.
Runtime is the only host that lost its identity to the pre-#7018
path-only import and needs the backfill. Adds a regression test.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
110 files carried an eslint/oxlint-disable max-lines directive but are
already under the default max-lines budget (300 .ts / 400 .tsx / 600 .mjs
/ 800 test), so the suppression is dead. Removing it restores real
max-lines coverage on these files with zero behavior change.
Each removed directive had max-lines as its only rule; verified via a
full oxlint run (0 max-lines violations, 0 new errors). Diff is pure
deletions (200 lines, 0 additions) — no code touched.
Co-authored-by: Orca <help@stably.ai>
Ensure agent CLI startup and draft launch commands use the correct quoting
format based on the user's configured local Windows shell (e.g., cmd.exe).
This avoids using host settings for remote/SSH targets where local shell
preferences do not apply.
Enable three unicorn rules — one correctness, two performance — and fix every
existing violation repo-wide so the rules pass as errors.
prefer-number-properties (76 sites)
- parseInt/parseFloat/NaN -> Number.* : safe aliases (autofixed).
- isNaN -> Number.isNaN (12 sites, hand-converted): global isNaN coerces its
argument, Number.isNaN does not. Verified every call site already passes a
number (Number.parseInt results, number-typed fields, Date.getTime()), so the
conversion is behavior-preserving today and guards against a future non-numeric
argument silently coercing.
prefer-array-find (26 sites)
- .filter(pred)[0] -> .find(pred); .filter(pred).at(-1) / .pop() -> .findLast(pred).
Drops the intermediate array and short-circuits.
prefer-array-index-of (5 sites)
- .findIndex(x => x === v) -> .indexOf(v).
Verified: typecheck (node/cli/web) clean, 53 affected suites pass (1679 tests),
oxlint clean repo-wide. mobile/ uses findLast safely (already ships ES2023
.toReversed()); config scripts and e2e helpers run on Node 24.
* perf(runtime): memoize onPtyData tail wait scan to halve per-chunk work
onPtyData runs per raw PTY chunk (hundreds/sec during verbose builds and
agent token streaming). For any terminal past the 2000-line / 256KB tail
cap it built the full wait text (a map/trim/filter/join over the entire
retained tail) and lower-cased + scanned it twice per chunk — once for the
pre-append tail and once for the post-append tail — producing hundreds of
KB of transient string allocation per chunk and steady main-process GC/CPU
pressure under load.
Cache the post-append wait state (text + lower-cased blocked-signal scan)
on the pty/leaf record and reuse it as the next chunk's pre-append state.
The prior chunk's post-append tail *is* this chunk's pre-append tail, so
the cached scan is exact; reuse is gated on fromTail so the empty-tail
preview fallback (which depends on a value updated after append) is never
reused stale. This drops per-chunk full-tail scans from 2N to N+1.
Adds an equivalence test proving the memoized stamping is byte-for-byte
identical to the recompute-both-sides reference across split prompts,
partial lines, ready-after-blocked demotion, and tail eviction, plus a
count assertion (memoized N+1 vs reference 2N scans).
Co-authored-by: Orca <help@stably.ai>
* fix(runtime): clear memoized wait cache when a disconnected transcript is pruned
pruneDisconnectedPtyTranscript empties a disconnected PTY record's retained
tail but left the new tailWaitState memo untouched. If such a record resumed
output (adoption/reattach while a leaf keeps it alive), onPtyData would reuse
the stale pre-prune wait state (fromTail=true) as the next chunk's previous
state and could miss or mis-time the waitBlockedAt stamp on that first chunk.
Clear tailWaitState in the prune reset so the resumed chunk recomputes from the
emptied tail.
Adds a runtime guard (prune clears the cache) and a sim equivalence test
covering prune-then-resume stamping.
Co-authored-by: Orca <help@stably.ai>
* docs(runtime): reword wait-scan comment that named a removed function
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
- Instruct workers to stop and idle or exit immediately after sending
`worker_done`, rather than running a 10-minute polling loop.
- Distinguish instructions based on worker kind: prompt-returning
agents should remain idle for re-engagement, while bare-shell
workers should exit.
- Prevent infinite polling overhead since the coordinator re-engages
workers via fresh terminal input instead of inbox polling.
Every terminal.subscribe / terminal.multiplex slot registers a runtime
exit-waiter via waitForTerminal(condition:'exit'). With no AbortSignal that
waiter sits in waitersByHandle until the PTY actually exits — but agent
terminals routinely never exit for the life of a session. It is only ever
cleared by real exit or a desktop renderer graph reload (markRendererReloading
/ markGraphUnavailable), neither of which a remote/mobile WebSocket reconnect
triggers. So on long SSH/mobile sessions every reconnect and tab-switch
re-subscribe leaked a waiter, and each captured its closed-connection handler
context (including the dead ws), growing host-process memory monotonically.
- multiplex: give each stream an AbortController and abort it in detachStream
(the single teardown point, reached on slot unsubscribe, re-subscribe
pre-detach, and connection close via closeMultiplex). Passing its signal to
waitForTerminal removes the waiter at detach. The existing .catch no-ops
because the stream is already deleted (streams.get(streamId) !== stream).
- legacy json/binary subscribe: pass the per-connection dispatch signal so the
waiter is removed on socket close/error.
Regression test proves a signalled exit-waiter is released when its signal
aborts (and 25 reconnect churns leave zero waiters), while an unsignalled one
accumulates — the pre-fix behavior.
Co-authored-by: Orca <help@stably.ai>
* feat(native-chat): add runtime owner selector for panes (U1)
Co-authored-by: Orca <help@stably.ai>
* feat(native-chat): add session transport with runtime adapter (U2)
Co-authored-by: Orca <help@stably.ai>
* Add runtimeEnvironmentId to UseNativeChatLiveSessionArgs
Allows the native chat live hook to route read and subscribe requests
to a remote runtime host when a runtime environment ID is specified,
otherwise falling back to the local IPC path.
* feat(native-chat): route live-session hook through owner transport (U3)
Co-authored-by: Orca <help@stably.ai>
* feat(native-chat): select runtime owner in caller view (U4)
Co-authored-by: Orca <help@stably.ai>
* Improve native chat transport and add local Docker SSH VM scripts
- Clamp high pagination limits instead of rejecting to keep paging unstuck.
- Re-subscribe after mid-stream drops with a short backoff.
- Drop explicit unsubscribe RPCs as connection closure reaps watchers.
- Discard stale load-earlier resolves after transport or owner flips.
- Add Docker-SSH scripts and Dockerfile for local Orca VM workspaces.
* rm unrelated files
* Handle errors when loading older native chat history
- Catch and swallow rejected promises from IPC-backed history reads to
prevent unhandled rejections when a "load more" action fails.
- Document focus-containment check in the window-scoped paste bridge.
---------
Co-authored-by: Orca <help@stably.ai>
* Add MiniMax rate-limit tracking and secure cookie storage
* Securely store MiniMax session cookies using an encrypted envelope format and local file hardening.
* Fetch rate limits in an isolated session partition and clear the cookie jar before and after requests to prevent leakage.
* Add a default-on "minimax" status bar item to display subscription usage.
* Expose minimax configuration settings (group ID and models) in settings panes and sync them via the runtime client.
* Isolate MiniMax config resolver and decryption failures from affecting other rate-limit providers.
* Redact MiniMax secrets with whitespace around colons
Update redactMiniMaxSecret to allow and match optional whitespace
surrounding the colon when redacting quoted cookie values. This matches
the spacing tolerance used during parsing.
* Address PR review: harden cookie read, validate IPC, add tests
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
* fix(worktrees): fall back from stale default base refs (#7312)
* docs(worktrees): explain base fallback policy
* fix(worktrees): harden stale base fallback edge cases
---------
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Bare repo-backed terminal creates now reuse Settings agent defaults for exact agent commands while preserving raw commands, disabled agents, and already-managed launches.
Validation:
- PR Checks / verify passed
- Local runtime tests, typecheck, lint, CLI build, and Electron CLI/runtime smoke passed
Resolve terminal CWD and worktree paths to their canonical form using
realpath before validating containment. This blocks symlink escape
routes for local terminal spawns, returning the default workspace
directory if a requested path attempts to escape the worktree.
- Local terminal paths are canonicalized using native realpath logic
- WSL UNC paths and SSH/remote terminals skip canonicalization
- Floating terminal startup directories bypass containment checks
- Missing or unresolvable workspace directories default safely
Creating a workspace hard-failed with "Could not refresh base ref …"
whenever the pre-create git fetch of a remote-tracking base (e.g.
origin/main) failed — offline, transient, or (common on Linux GUI) the
Electron process lacking SSH_AUTH_SOCK so `ssh -o BatchMode=yes` cannot
auth. This blocked creation even when a perfectly usable local
origin/main already existed and `git worktree add` from it would succeed.
Regression introduced by #2310 (5c93579e40), which replaced the prior
best-effort fetch + post-create reconcile with a hard network gate.
Fix: at all three create sites (local runtime, local IPC, SSH), only
throw when the refresh failed AND no usable local base ref exists;
otherwise create from the local ref (a possibly stale but valid base).
Also: move the SSH local-ref probe after session.registerRoot so relays
that gate generic git.exec don't false-negative and defeat the fallback.
Co-authored-by: Orca <help@stably.ai>
* fix(gitlab): port-aware self-hosted host recognition
Use the URL host (including a non-default web/API port) as the GitLab
host identity instead of the port-less hostname, and match known hosts
port-aware:
- A known-host entry without a port matches any port of the same
hostname (preserves legacy bare-host and gitlab.com recognition).
- A known-host entry WITH a port matches only that exact host:port, so
two services sharing a hostname on different ports (e.g. a GitLab and
a Gitea) are no longer conflated.
- For ssh/git remotes the port is a transport port (e.g. ssh :2222) and
is dropped; for http(s) remotes the port is the endpoint and kept.
- Also capture an optional :port in parseGlabAuthStatusHosts so a
self-hosted GitLab on a non-default port is discovered correctly.
* fix(gitlab): per-connection known-hosts cache + port-aware auth-status parsing
getGlabKnownHosts() was connection-blind and cached process-globally,
and on any failure it cached [gitlab.com] forever — so a repo on an SSH
connection never discovered its self-hosted host once a probe failed
before the tunnel was ready.
- getGlabKnownHosts(connectionId?) now caches per connection so a
connected repo's authenticated hosts don't leak into the local
context (or vice versa).
- The failure fallback (canonical default) is no longer cached, so a
later probe can re-discover the real host once auth/tunnel is ready.
- parseGlabAuthStatusHosts captures an optional :port on both the
'Logged in to <host>' and header-style lines, keeping two services on
the same hostname distinct by port.
* fix(gitlab): isolate unresolvable projects instead of cwd-fallback that hits exit 128
listIssues/getIssue fell back to an unscoped 'glab issue list' / 'glab
issue view' that infers the project from cwd. For a repo on an SSH
connection cwd is not the repo dir, so glab runs git resolution in a
non-repo dir and fails with 'git: exit status 128'. In an 'All projects'
aggregate one such failure could sink the whole issues panel.
When a projectRef cannot be resolved, return a structured, isolated
per-project result (listIssues: { items: [], error: not_found };
getIssue: null) and spawn no glab subprocess. Behavior is unchanged when
a projectRef IS resolved (the scoped '-R' / 'api projects/...' path).
* fix(gitlab): recognize modern /-/work_items/<iid> issue URLs
Modern GitLab emits issue URLs as /-/work_items/<iid> in addition to the
legacy /-/issues/<iid>. The URL classifiers only matched /-/issues/, so
work-item-form issue links went unrecognized.
Extend the gitlab-links parsers (parseGitLabIssueOrMRNumber /
parseGitLabIssueOrMRLink, which also backs isWorkItemLookupText) and
isGitLabIssueUrl to accept /-/work_items/<iid>, mapping it to an issue
work item with the same project-path + iid extraction.
* fix(gitlab): thread connectionId into getGlabKnownHosts call sites
Follow the existing connectionId-threading pattern: pass the repo's
connectionId into every getGlabKnownHosts() call (client.ts,
work-item-details.ts, orca-runtime.ts) so the per-connection known-hosts
cache is keyed correctly and self-hosted hosts are discovered against
the right glab context.
* docs(gitlab): use generic example hosts in comments
* fix(gitlab): pass self-hosted host:port via GITLAB_HOST (glab --hostname rejects ports)
* polish: satisfy oxlint curly + oxfmt on merged gitlab port-recognition code
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Ptah-CT <auctor@xinfty.space>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
* fix(browser): keep isolated profile storage on its partition
* fix(browser): keep cloned isolated tabs on their resolved partition
* fix(browser): thread resolved partition through UI profile switches
Keep the isolated-storage invariant universal: UI-initiated profile
switch/create now persist the resolved partition alongside the profile
id, matching the runtime path, so a tab stays on its partition even if
the renderer profile mirror is later stale (issue #6923).
Co-authored-by: Orca <help@stably.ai>
* fix(browser): persist resolved partition through session restore
Add sessionPartition to the workspace-session zod schema so the resolved
partition survives persist->load; without it zod strips the field and a
restored isolated tab whose profile mirror is stale at startup falls back
to the shared default partition, reopening the storage leak (#6923).
Fold the webview teardown branches (parent drift or partition mismatch)
into one and re-resolve the viewport container once, matching the
pre-refactor null-guard behavior.
Split the sleeping-agent parse tests into their own file to keep both
under the 800-line cap.
Co-authored-by: Orca <help@stably.ai>
* fix(browser): keep CLI-created tabs inheriting the default profile
browserTabCreate without an explicit profile was sending sessionProfileId:
null, which the renderer store treats as 'no inheritance' (its guard is
!== undefined). That forced CLI-created tabs onto the shared default
partition even when the user had configured a default browser session
profile, silently changing behavior a #6923 fix should not touch.
Leave sessionProfileId/sessionPartition undefined when no profile is named
so the renderer applies default-profile inheritance; thread the resolved
partition only when a profile is explicitly chosen.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
* Recover exported terminal handles from live PTYs
* Guard terminal-handle adoption: first-wins, no collisions
Discovery adoption of ORCA_TERMINAL_HANDLE is now skipped when the pty
already has a handle bound this session (re-keying would strand waiters
registered under the old handle) or when the reported handle is already
bound to a different pty (provider-reported values are not trusted to be
collision-free). Also adds the relay why-comment and PtyProcessSummary
type alias from review feedback.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
* Cut fseventsd load: fix macOS exclusion cap, drop wide always-on FSEvents streams
- @parcel/watcher maps plain-path ignores to FSEventStreamSetExclusionPaths,
but macOS caps exclusions at 8 per stream and fails closed. Orca passed 9,
silently disabling ALL daemon-side exclusions: fseventsd delivered every
node_modules/.git event to each per-worktree explorer stream (measured 16x
client CPU). Cap plain paths at 8 (extras demoted to userspace globs) via a
shared filesystem-watcher-ignore module, also unifying the runtime
file-watcher host list so identical roots share one native stream.
- worktree-base-directory-watcher subscribed recursive FSEvents streams over
every repo's ENTIRE workspace root (all worktrees) and whole common .git
(objects included) with glob-only ignores (zero daemon-side exclusion),
just to observe a few shallow paths. Replace with a 2s readdir/stat poller
(zero fseventsd clients, measured 70x less delivery CPU); SSH targets keep
provider.watch unchanged.
- serve-sim state watcher held an app-lifetime fs.watch on $TMPDIR (the
noisiest dir on the system); its existing 250ms existence poll makes the
parent watch redundant, so drop it.
Co-authored-by: Orca <help@stably.ai>
* Eliminate base-poller idle cost: mtime-gated ticks + narrow macOS worktree-metadata stream
- base targets: tick is now one stat of each gate dir (root + nested
containers); the readdir + marker fan-out runs only when a gate dir
changed, with a 30s ungated backstop and a bounded pending-marker
recheck list. Idle tick 600us -> 1.1us at 146 worktrees.
- git-common targets on macOS: replace the 2s entry sweep with one narrow
native stream on <common>/.git/worktrees (tiny, rare-churn tree): zero
idle syscalls and external worktree add/remove/HEAD detection back to
sub-second. Re-arms via existence poll across git worktree prune
deleting/recreating the dir. Win/Linux keep the listing poll (no
fseventsd there; a Windows dir handle could block prune).
- split git-common logic into worktree-git-common-watch.ts (max-lines).
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
* fix: reordered default columns in kanban board
* Introduce dedicated flag to repair reversed default workspace statuses
- Add `_workspaceStatusesReorderedDefaultRepaired` to decouple the
one-shot repair from the initial status order migration.
- Ensure the repair runs for users who saved the reversed default
payload (with "Done" on the left) during a short-lived broken build.
- Support both "Completed" and "Done" labels when identifying default
status shapes to migrate or repair.
---------
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
* Add keyboard shortcut to toggle the Quick Commands menu
- New `tab.openQuickCommandsMenu` keybinding action (no default binding)
- TabBarQuickCommandsMenu listens for the binding and toggles open/closed
- Scoped to the active tab group naturally since the component only mounts when its group is focused
* Show keyboard shortcut in Quick Commands menu trigger tooltip
* Add tests
* expand tests
* Expand keyboard toggle to call handleOpenChange and skip repeated keys
- Replace `setMenuOpen` toggle with `handleOpenChange(!menuOpen)` so closing
via keyboard runs the same reset logic (query, focus frame, value override)
- Guard against key-repeat events to prevent rapid toggling on held key
- Wrap `handleOpenChange` in `useCallback` so it's stable enough to include
in the `useEffect` dependency array without causing spurious re-registrations
- Update tests to reflect that re-running the effect between presses is
required for the close path, and add a repeat-event test
* Add docstring to withShortcutHint func
* review: harden quick commands menu shortcut
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
Keep the synthetic floating workspace local while a remote runtime is active, including terminal/browser creation, activation, close, and remote snapshot handling.
Maintainer follow-ups:
- require worktreeId for runtime-session terminal create payloads
- add renderer-backed terminal create reply sender regression coverage
- merge current main and keep the WSL readDir breadcrumb test aligned with main's Windows-only handler coverage