* fix(orchestration): complete worker tasks and improve coordinator UX
* Fix orchestration lifecycle sender resolution and peek/check compat hand
- Lifecycle sends (worker_done/heartbeat) now use ORCA_TERMINAL_HANDLE
verbatim, skipping the liveness probe and pane remint that could
block delivery during restarts or mismatch stale-runtime assignee
handles.
- --peek now round-trips as {peek:true, unread:false} so older runtimes
that strip unknown params degrade to non-destructive "all" instead of
mark-read, with client-side filtering to restore peek semantics and a
clear error when --peek --wait can't be honored.
- Reject combined read-mode flags (--unread/--peek/--all) before calling
the runtime.
- Distinguish suppressed (already-consumed) lifecycle messages from
ignored ones so send doesn't wake --wait waiters for stale heartbeats.
- Fix task summary truncation to avoid splitting UTF-16 surrogate pairs
and to not misreport whitespace normalization as truncation.
* Add shared helper to abbreviate orchestration task specs for brief listi
- Normalizes whitespace and caps spec length at 160 chars, flagging
truncation separately from whitespace-only changes
- Truncates on UTF-16 code point boundaries to avoid splitting
surrogate pairs and emitting malformed strings
* Add pane-key identity to worker_done/heartbeat reconciliation and server
- Records the sender's pane key on messages and dispatch contexts so
worker_done/heartbeat ownership can be verified by the remint-stable
pane leaf instead of the terminal handle, which is reissued across
restarts.
- Rejects lifecycle messages from a genuinely foreign pane while still
tolerating handle remints, tab break-outs, and older CLIs that lack
pane identity.
- Moves task-spec abbreviation server-side (orchestration.taskList
--brief) so full specs no longer cross SSH/relay transports, with a
client-side fallback for older runtimes; consolidates the shared
abbreviation helper under src/shared.
- Adds a stderr warning when a pre-peek runtime's --peek response hits
the 100-row cap, since older unread messages may be missing.
* Isolate ORCA_PANE_KEY in CLI test beforeEach to fix leaked senderPaneKey
Co-authored-by: Orca <help@stably.ai>
* Fix pane-key remint bypassing dispatch mutual-exclusion lock
- Dispatch locking only matched on assignee_handle, so a reminted
terminal handle (tab break-out) could open a second concurrent
dispatch on the same pane.
- Add leaf-UUID-based pane key comparison (parsePaneKey) as a
secondary lock, falling back to exact handle match for legacy
rows without pane keys.
* Update orchestration skill docs for lifecycle authority and CLI flag add
- Clarify that dispatch lifecycle is tied to taskId+dispatchId verified against
the dispatched pane, not the terminal handle, since handles can be reminted
after restart
- Document new `check --peek`/`--all` and `task-list --brief` flags, with
fallback guidance for older CLIs that reject them
- Note that a valid worker_done auto-completes the task/dispatch, so workers
shouldn't also call task-update manually
---------
Co-authored-by: Orca <help@stably.ai>
Persist and safely restore the active top-level view on startup. Unknown, removed, legacy, or unavailable views fall back to the terminal, while cross-window UI sync cannot navigate the current window.\n\nCloses #8264
* fix(settings): make WSL skill commands pasteable (#7795)
* Fix WSL skill commands so PowerShell 7 pastes match PowerShell 5.1 argv
- Encode the WSL login-shell script as base64 and decode/eval it inside
the sh -c invocation, avoiding raw nested quotes at the paste boundary
- Scope $PSNativeCommandArgumentPassing = 'Legacy' to the invocation so
PS 5.1 and PS 7 both hand wsl.exe the same escaped argv
- Extract powershell-native-argument.ts as the shared quoting module and
reuse it from ssh-remote-powershell.ts
* test(runtime): stub getRepo in mobile-tab startup cwd test
Main's #7892 made listMobileSessionTabs validate selectors via
this.store?.getRepo; the mock store here only defined
getWorkspaceSession, so the merged CI build threw 'getRepo is not a
function'. Return null (wt-1 is a worktree id, not a repo).
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
Automatically resolve and require explicit push targets for linked
GitHub PRs and GitLab MRs before allowing remote actions.
This prevents operations like push or sync from targeting helper
upstreams or falling back to default behaviors when the review target
is unavailable. Also, recover missing push targets during metadata
saves to heal existing linked PRs.
* fix(codex): share global AGENTS.md into managed runtime homes
Orca launches Codex with a managed CODEX_HOME, so host and WSL sessions otherwise lose the user's global instructions. Share AGENTS.md through the existing ownership-aware link-or-copy path, with a narrow WSL launch sync that avoids copying unrelated resource directories.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(codex): copy global AGENTS.md into WSL runtime homes
Symlinking across the \wsl.localhost 9P boundary stores a Windows UNC
target the distro cannot resolve, so the global AGENTS.md silently would
not load inside WSL when the host symlink succeeded. Copy it like the
config mirror already does across the same boundary.
Co-authored-by: Orca <help@stably.ai>
* Fix WSL global-instruction sync to dereference symlinks and skip redunda
- Copy AGENTS.md contents (not the symlink) into WSL runtime homes, since
a host-side symlink is unusable inside the distro
- Skip rewriting the fallback copy when source contents are unchanged,
avoiding needless writes across the UNC boundary on every Codex launch
- Handle non-regular-file sources and malformed/undeletable marker
directories without blocking sync or stranding stale instructions
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
* feat(ssh): support file transfers over system ssh
* fix(ssh): harden system file transfers
* test(runtime): stub getRepo in headless mobile tab cwd test
The mobile-session selector validator (getValidatedExplicitWorktreeIdSelector,
from main) calls this.store?.getRepo to reject repo ids passed as worktree ids.
The store stub only implemented getWorkspaceSession, so the guarded call threw
'getRepo is not a function' once main merged into this branch. Add a getRepo
that returns null (wt-1 is a worktree, not a repo).
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
On Linux the CLI installs as orca-ide so it never shadows /usr/bin/orca
(GNOME's screen reader), but agent-facing surfaces (orca-cli skill,
dispatch preambles, CLI hints) all invoke bare `orca` — so on stock
Ubuntu an agent inside an Orca terminal launched the screen reader,
which started speaking (#7904).
Fix: prepend a userData-scoped shim dir (bare `orca` -> bundled
orca-ide launcher, or the stable AppImage) to the PATH of every
packaged-Linux managed PTY, mirroring the existing dev-mode cli/bin
prepend. The user's own shells — and their real screen reader command —
stay untouched. Also flip the orca-cli skill probe to prefer orca-ide
so agents outside Orca terminals never execute the screen reader.
Fixes#7904
Co-authored-by: Orca <help@stably.ai>
* Fix Codex WSL project trust conflating case-distinct Linux paths
normalizeCodexProjectPathForLookup lowercased the entire Windows/UNC
path, including the case-sensitive Linux portion under \\wsl$\<distro>.
Two distinct WSL project dirs (.../Repo vs .../repo) collapsed onto one
trust key, and the mirror dedupe (codex-config-mirror) inherited it.
Preserve case for the Linux path after the case-insensitive
\\wsl$\<distro> / \\wsl.localhost\<distro> share prefix; true Windows
drive letters and normal UNC shares still case-fold as before.
Co-authored-by: Orca <help@stably.ai>
* Apply the same WSL case-fold fix to hook-trust key lookup
normalizeHookTrustKeyForLookup had the identical latent bug: on a win32
host it lowercased the whole Windows-shaped path, folding the
case-sensitive Linux tail of a \\wsl$\<distro> UNC hook path — contrary
to its own comment that WSL sources stay case-sensitive.
Extract foldWindowsCaseInsensitivePath (shared with the project-path
normalizer): fold only the case-insensitive drive/\\wsl$ share prefix,
preserve the Linux tail. Existing suffix (event:group:handler) is already
lowercase, so behavior is unchanged there.
Co-authored-by: Orca <help@stably.ai>
* Fix Codex WSL trust revocation and hook-key case folding
- Case-drifted or share-spelling-varied WSL revocations were being
ignored on merge, letting stale "trusted" entries survive; fold
revocation lookups fully so matching errs toward revoked.
- Hook-trust key folding was gated on process.platform === 'win32',
so WSL/SSH-remote hook sources weren't folded when Orca itself ran
on macOS/Linux; fold by path shape instead, via the new shared
foldWslUncPathCaseInsensitiveParts helper (also covers /mnt drvfs
automounts and wsl$/wsl.localhost share aliasing).
* Fix Codex WSL trust key case-folding regressions
- Don't fold case-variant `/MNT` dirs as if they were the drvfs
automount; only literal lowercase `/mnt/<drive>` folds.
- Preserve an exact-cased trusted project entry in ~/.codex during
runtime merge instead of letting a loosely-matched, case-drifted
revocation clobber a user's re-granted trust on every mirror pass.
- Minor cleanup: inline foldWindowsCaseInsensitivePath and hoist the
repeated normalizeHookTrustKeyForLookup call in findTrustBlockRanges.
* Refactor case-fold WSL trust test to assert real serializer output
Extract path variables and assert against escapeTomlString(incomingPath) instead of a hardcoded escaped string literal, so the fixture can't silently drift from the actual TOML header serialization.
---------
Co-authored-by: Orca <help@stably.ai>
* fix(runtime): explain full worktree id selectors (#7432)
* Fix full worktree id selectors for bare repo ids and doc guidance
- Reject bare repo-id selectors up front via a shared validator instead
of relying on worktree-list scanning, so RPC callers no longer trigger
an unnecessary rescan just to detect the mistake
- Propagate the structured worktree_id_requires_full_path code through
RPC error mapping so callers get a typed error, not just a message
- Update orca-cli, orca-emulator, and orchestration skill docs to show
the full `<repo-id>::<path>` id shape and stop implying a bare repo
id is a valid worktree selector
---------
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
* fix: work-item naming, usage % rounding, and terminal/delete copy
Address prod-release-scan P2s:
- #8238: recognize Bitbucket Server (/projects|users/.../repos/.../pull-requests/N)
and Azure DevOps (/_git/REPO/pullrequest/N) PR URL shapes in
work-item-reference, alongside Bitbucket Cloud; graceful fallback preserved.
- #7574: getDisplayedUsagePercentage now rounds the used value before taking the
`remaining` complement, so the compact status bar (raw usedPercent) and tooltip
(pre-rounded clampUsedPercent) can no longer disagree by 1% at a .5 fraction.
clampUsedPercent moves to the shared module as the single rounding source.
- #7459: mixed remote+local batch delete confirm no longer claims the whole
batch is a permanent "remote host" delete — it now states remote items are
permanent while local items move to the Trash/Recycle Bin.
- #8322: right-click-to-paste settings copy is platform-aware — "Control-click"
on macOS, "Ctrl+right-click" on Windows/Linux — matching the ctrlKey gate.
Localization catalog synced (also picks up pre-existing UsagePercentageDisplayChangeNotice drift).
* Fix NaN% usage bar and label for non-finite provider values
Non-finite usedPercent inputs (NaN/Infinity) propagated through Math.round/min/max into the CSS bar width (`NaN%`) and displayed copy. clampUsedPercent now short-circuits to 0 in that case, with a test covering the divergence from getDisplayedUsagePercentage for the 'remaining' case.
* fix(cli): don't recover benign typos into destructive commands
CLI did-you-mean ranked purely by Levenshtein, so `orca worktree move`
sole-suggested `orca worktree remove` (distance 2) — an alias of the
destructive `worktree rm`. Suggestions also flow into --json
error.data.nextSteps, the agent recovery channel, so a blind retry could
delete a clean worktree.
Make destructiveness a declared property of the command instead of a verb
heuristic: add `destructive?: true` to CommandSpec and mark the
irreversible commands (worktree rm, environment rm, automations remove,
project setup-delete, tab profile delete, cookie delete, storage
local/session clear). The suggestion ranker excludes destructive
candidates unless the input token is itself a near-miss (distance <=1) of a
destructive verb, so `worktree remov` still recovers `rm`/`remove` while
`worktree move` no longer does. The guard tracks the registry, so it
also covers destructive verbs outside the delete family (e.g. kill).
Fixes#6303
Co-authored-by: Orca <help@stably.ai>
* fix(cli): use Array.at(-1) to satisfy oxlint prefer-at
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
Pi awaits its extension event handlers, so an awaited loopback status
post that stalls (Orca restarting / receiver unavailable) blocked the
running Pi turn and disconnected it. Make post() fire-and-forget with a
latest-only pending slot drained by a single active request and a 1s
AbortController timeout, so a stalled receiver can never hold the turn.
Also stop treating session_shutdown as turn completion: Pi emits it on
reload/new/resume/fork while the PTY stays alive, so only agent_end
proves done (real exit is cleared by PTY teardown). Split the generated
handler registrations into agent-status-handler-source.ts.
Co-authored-by: Orca <help@stably.ai>
* fix(cleanup): reconcile late removal results
* fix(cleanup): report authoritative late removals
* fix(cleanup): reconcile skipped ancestors on late child settlement
Ancestor rows skipped past the removal deadline were reported as
definitive failures even when the blocking child later succeeded or
was still in flight. Track provisional vs. definitive skips, re-derive
them as child settlements arrive mid-batch, requeue unblocked
ancestors for retry, and add a "still removing" toast state so batch
summaries stop contradicting rows that settle later.
* Fix skipped-parent rows going stale after post-batch child settlement
- Post-batch late child results (settling after the batch loop ends)
previously ignored ancestor skip state, so a parent skipped for a
since-resolved child kept a stale "could not be removed" failure
instead of reclassifying and retrying.
- Extracts reclassification logic into
workspace-cleanup-skipped-ancestor-reclassification.ts, shared by the
mid-batch and new post-batch paths.
- Adds workspace-cleanup-post-batch-late-settlement.ts to reconcile
ancestor skips and retry unblocked parents after late child
settlement, serialized via a reconcile chain to avoid interleaving
concurrent settlements.
* docs: design Grok orchestration group
* docs: plan Grok orchestration group implementation
* fix: add Grok orchestration group
* test(orchestration): accept Windows skill newlines
* Fix @grok orchestration group matching and remove stale planning docs
- Reuse the shared buildAgentNameRe matcher in groups.ts instead of a
divergent local regex, so orchestration groups honor the same
Windows launcher-suffix rule (grok.exe/.cmd/.bat/.ps1) as the rest
of Orca's agent-title detection.
- Add test coverage for real Grok OSC title shapes (spinner-collapsed,
session titles) and Windows launcher-suffix titles.
- Delete the now-completed design and implementation-plan docs for
the Grok orchestration group work.
---------
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Prod-release-scan P1+P2 from v1.4.137-rc.1 mobile host-remove.
P1: Host remove could orphan a SecureStore pairing token with no Settings
retry when BOTH the durable pending-queue write failed AND the native delete
rejected/stalled. recordCleanupIntent swallowed the queue-write failure, so
the only recovery handle for the failed keychain delete was silently lost.
Now scheduleHostCredentialCleanup keeps a session-scoped in-memory fallback
handle when the durable write fails, so Settings still surfaces the pending
cleanup and offers a retry; confirmNativeCleanup clears the fallback if the
native delete later lands. removeHost stays non-blocking on the keychain
(freeze fix intact).
P2 (updateLastConnected): the fire-and-forget `void updateLastConnected(...)`
call site threw on unreadable storage, producing an unhandled rejection.
updateLastConnected now swallows unreadable-storage failures internally since
it's a best-effort timestamp.
P2 (soft-read): loadPendingHostCredentialCleanup now reports storageUnreadable
instead of pretending the queue is empty, and Settings surfaces a
"couldn't check cleanup status — retry to be safe" affordance rather than
hiding the section when the durable queue can't be read.
Tests: dual-fault fallback + no-clobber, storageUnreadable reporting,
fallback self-heal on late delete success, and updateLastConnected non-throw.
* fix: host browser popups in an Orca origin-bar window instead of chrome-less child windows
A guest-opened popup previously became a default Electron child window
with no address bar, so users could not verify a popup's origin — a
phishing surface flagged in the prod-release scan of #7392. The reverted
#8332 tried gating on disposition, which is bypassable and breaks
featureless window.open() OAuth flows.
Instead, keep hosting popups in-app (preserving the shared session
partition and live window.opener handle OAuth depends on) but build the
child window ourselves via setWindowOpenHandler's createWindow callback:
a BaseWindow with an Orca-controlled origin-bar WebContentsView on top
and a content WebContentsView that adopts the pre-created popup
WebContents. The bar shows only the destination origin (never path or
query), updates on navigation, and flags plain http to remote hosts.
Also pins secure webPreferences (contextIsolation, no nodeIntegration,
sandbox, no webviewTag) on popup children via
SAFE_POPUP_WINDOW_OPTIONS, attaches guest policies to popup contents
directly (did-create-window does not fire for createWindow children),
emits the existing opened-in-orca renderer notice, and closes popups
with their opener guest.
Co-authored-by: Orca <help@stably.ai>
* fix: show page title in popup title bar instead of doubling the origin
The native title bar and the origin bar both showed the origin, reading
as a doubled header. Match Chrome popup behavior: title bar shows the
page title (reset to origin on navigation so a stale title cannot
outlive its origin); the origin bar below remains the unspoofable trust
surface.
Co-authored-by: Orca <help@stably.ai>
* fix: elide the start of long popup origins so the registrable domain stays visible
Adversarial review findings on the origin bar:
- The bar right-ellipsized long hostnames, hiding exactly the part that
matters: window.open('https://accounts.google.com.<...>.evil.com',
'', 'width=360') rendered as 'https://accounts.google.com.signin.s…'.
Clip from the left instead (rtl container + isolated ltr bdi so host
and port keep normal character order), matching how Chrome elides.
- Re-assert the origin on the popup's did-finish-load so a transiently
dropped executeJavaScript write cannot leave a stale origin up.
- Re-pin view layout on enter/leave-full-screen: verified at runtime
that HTML5 fullscreen keeps the bar visible on macOS (resize fires);
the explicit events make that hold on every platform.
- Test hardening: fake WebContents now flips isDestroyed after
'destroyed' so the double-close guard is actually exercised.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
* fix(preflight): reject Windows paths from WSL lookup
WSL agent discovery previously treated path.win32 absolute results as
valid guest paths, so a Windows absolute path like C:\spoof could be
counted as a found agent. Only POSIX absolute paths are valid inside WSL.
* docs(preflight): explain WSL path boundary
* docs(preflight): correct WSL path rejection rationale
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
Once quitAndInstall commits, Squirrel's ShipIt (and the Win/Linux
installers) wait for the old app process to exit before replacing the
bundle and relaunching. The quit path defers exit behind unbounded async
teardown (daemon checkpoint RPCs at 30s each per session, SSH
disconnects, watcher/emulator shutdown); if any of it wedges, the app
looks closed but the process survives, ShipIt stalls, and the update
never applies — 'Check for updates closes the app but never relaunches'.
Arm a 20s unref'd exit watchdog at the exact install-commit point (where
recovery is already forbidden) and disarm it on pre-commit recovery, so
the old process is guaranteed to exit and the installer can relaunch.
Fixes#4438
Co-authored-by: Orca <help@stably.ai>
Include fallbackGitHubPR alongside linkedGitHubPR/linkedGitLabMR when
determining whether a hosted review link resolves to a push target.
Worktrees without persisted linkedPR metadata (e.g. child worktrees)
were incorrectly blocked with "target unavailable" despite having a
real matching upstream, since their PR was only known via the queue
fallback. Also splits hasPositiveHostedReviewNumberLink to build on
the resolvable subset so the two helpers can't drift.
- Pass the active `worktreePath` through IPC, RPC, and the GitHub client
to ensure we fetch the correct HEAD OID when resolving merged PRs.
- Validate incoming worktree paths against known repository worktrees in
the main process to prevent forged path usage.
- Escalate Checks Panel PR refresh requests from 'swr' to 'active' when
a cached "no PR" miss predates when the panel became visible.
Rich editors reconcile browser editing transactions, while direct value/textContent writes can leave framework state stale. Classify explicit contenteditables through the requested agent-browser target, keep native fill and clear behavior for plain controls, and perform rich replacement or clear as one target-focused eval over stdin. Fail when the browser editing command is unavailable instead of presenting stale DOM state.
Preserves input/change behavior and spinbutton handling for standard fields. Verified against Draft.js and ProseMirror model state plus focused-target clear regressions.
Co-authored-by: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
* Fix F3: use known-tag predicate for explicit-turn decisions
isHarnessInjectedUserTurnText matches any multi-word kebab tag, which is
safe for non-destructive UI classification but wrong for state-transition
decisions: a real prompt starting with a custom <my-element> paste looked
like machinery in resolvePrompt/hasExplicitUserPrompt. Combined with the
post-interrupt working-suppression in agent-hooks/server.ts, that left the
agent visibly done after Ctrl+C. Switch both explicit-turn callsites to the
known-tag isKnownHarnessInjectedUserTurnText predicate; known harness tags
and Grok <user_query> behave unchanged.
Co-authored-by: Orca <help@stably.ai>
* Retire broad harness-tag matcher; unify on known-tag predicate
The broad isHarnessInjectedUserTurnText had one remaining consumer: session
title selection in session-scanner-primary-parsers.ts. Switch it to the
known-tag predicate too — a real first turn that pastes a custom <my-element>
now titles the session instead of being demoted to the meta (fallback) title.
All observed first-turn machinery (system-reminder, caveat, command-name,
task-notification, …) is already in the known list, so the only behavior
change is that unknown, uncatalogued kebab tags stay user turns. Delete the
now-unused broad predicate and fold its coverage into the known-predicate
tests.
Co-authored-by: Orca <help@stably.ai>
* Fix bare <channel> tag being misclassified as harness machinery
Only the attributed `<channel source=…>` form is emitted by the harness;
a bare `<channel>` is legitimate user-pasted RSS/XML content. Remove
'channel' from the known-tag set (which matched any <channel ...>) and
rely solely on the existing '<channel source=' prefix rule.
---------
Co-authored-by: Orca <help@stably.ai>
- gh file-fetch failures (rate limit, auth, unresolved remote) previously
returned an empty array, which the Files tab rendered as "No files
changed." — indistinguishable from a real empty PR
- getPRFiles now returns null on failure; work-item-details surfaces this
as filesUnavailable so GitHubItemDialog and PullRequestPage can show a
retry action instead of a misleading empty state
* skills: prefer agent-first worktree launch; avoid empty shell tabs
Document Orca's first-terminal behavior so agents do not leave dead
shell tabs: --agent runs in the first terminal (one tab), bare
worktree create + terminal create leaves shell + agent (two tabs).
Also: re-resolve live handles via terminal list after create, message
one handle only, and prefer orchestration check --inject over terminal
send for pure orchestration pings. Aligns with CLI docs
(--agent launches the selected agent in the first terminal).
* fix skill guidance for agent-first worktrees
---------
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Blank context lines in the @xterm/addon-webgl patch had trailing spaces,
which made git diff --check fail. Strip only that whitespace and refresh
the pnpm patchedDependencies hash so the lockfile stays consistent.
* fix: resolve daemon shell before spawning
* fix(daemon): reconcile shell-ready barrier with the resolved fallback shell
The adapter computes shellReadySupported from the preferred shell before
spawn. When the daemon falls back (e.g. to /bin/sh), the session would
queue startup commands for the full 15s ready-marker timeout and wrap
multiline prompts in bracketed-paste markers the fallback shell cannot
parse. Expose the spawned shell on SubprocessHandle and downgrade the
barrier and paste wrapping in TerminalHost when the actual shell cannot
emit the marker.
Also apply the Unix shell fallback after the relay env scrub so a
scrubbed SHELL cannot drop the corrected value, and cover the resolve-
before-launch-config ordering, the no-shell throw, and candidate dedup
with tests.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
* Add host removal lifecycle safeguards and credential cleanup retry UI
- Sequence host removal so metadata commits before the client socket
closes, avoiding a stranded host when storage fails, and add a
cancellable open-registry to stop races between host-client opens
and closes/unmounts.
- Queue AsyncStorage host-list mutations (rename/removal/lastConnected)
to prevent concurrent writers from clobbering each other's changes.
- Track keychain credential cleanups that fail or time out as durable
pending intents, surfaced with a manual retry affordance in Settings.
* Fix host removal error handling to reopen confirm dialog and alert user
Previously a failed host removal silently closed the confirm dialog,
leaving the host listed with no feedback and no easy retry path. Now
the confirm modal reopens and an alert surfaces the failure so the
user can retry.
* test: reconcile settings tests with universal right-click paste and promoted worktree symlinks
Merging main surfaced two semantic conflicts against this branch's tests:
- #8322 exposed right-click paste on every platform, so the settings
navigation metadata now indexes it even when only the terminal host is
Windows. Update the stale assertion accordingly.
- #8318 promoted APFS worktree shared paths by dropping the
experimentalWorktreeSymlinks gate, so WorktreeSymlinksSection now always
mounts inside RepositoryPane and reads window.api.fs. Stub a minimal
renderer fs bridge in the pane test, matching the AppearancePane pattern.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
Remove the duplicated open/start workspace buttons and dropdown from
GHEditSection now that the primary CTA lives in the issue header;
show the attached workspace or "None yet" as plain metadata instead.
* Fix stale terminal panes after backgrounding by retrying foreground reco
- Foreground recovery was skipping the replay when resume landed mid-reconnect
(socket typically dies after 60-80s backgrounded), leaving WKWebView panes
blank until a manual tab switch. Recovery now returns a 'deferred' outcome
and the session screen retries it once connState flips back to connected.
- Fix a related race where a newly created tab's web-ready subscribe could be
skipped if a lagging session-tab snapshot reset activeHandleRef before the
subscribe fired; track the intended active handle separately.
* Fix stale pending terminal handle outliving a failed create
Clear pendingActiveTerminalHandleRef when terminal creation returns
no handle, since web-ready subscribe logic gates on this ref being
active and would otherwise see a stale value.
* fix: address pr-bug-scan validated finding from #6799
Retain last-good resolved cwd on empty/error getCwd poll instead of committing null, so a transient lsof timeout no longer flips the followed worktree and resets the panel.
* Add renderer startup timing diagnostics and fix stale terminal-cwd reten
- Wraps each renderer startup hydration step (settings, repos, worktrees,
session, SSH reconnect, etc.) with timing instrumentation gated behind
ORCA_STARTUP_DIAGNOSTICS, wired through a new IPC channel
(app:startupDiagnostic) so cold-start regressions can be measured.
- Fixes the Checks panel's terminal-worktree tracking to clear the
retained cwd when the active terminal itself changes, instead of only
retaining across transient empty/error polls on the same terminal.
---------
Co-authored-by: orca-bug-scan-bot <orca-bug-scan-bot@stably.ai>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
* feat(file-explorer): confirm multi-select deletes with a single batch prompt
Deleting a multi-file selection on a remote host prompted once per file:
requestDeleteAll awaited runDelete per root, and the remote-delete
confirmation lived inside runDelete. Hoist the confirmation for batches —
one 'Permanently delete {{count}} items?' dialog up front, then per-node
deletes with skipConfirmation. Single-file and local (Trash) deletes are
unchanged. Root filtering and the batch loop move to
file-explorer-batch-deletion.ts with unit coverage.
Fixes#7457
* fix(file-explorer): count the full selection in the batch delete prompt
Address review: roots.length undercounts when a selected directory's
children are also selected (could even read 'delete 1 items?'). Use the
visible selection size instead. Also reword the zh strings so 项目
cannot read as 'project' in a file-delete flow.
* review: skip batch delete confirm for unresolved-owner selections
Narrow the batch-confirm gate to a resolvable remote route so an
unresolved-owner multi-select no longer pops a destructive prompt for
deletes that fail closed anyway — mirroring the single-delete path.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Tom de Bres <tomdebres@users.noreply.github.com>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
* feat(markdown): support HTML superscript links
* Add HTML superscript citation links to the rich markdown editor
- Introduce marked-based tokenizer support for `<sup><a>` citation
links, with a shared editor context so key/link handlers can resolve
selection status and open an action bubble for citation atoms
(which markdown setLink/unsetLink can't edit).
- Extract clipboard-write logic shared by cut and cut-visual-line into
rich-markdown-clipboard-write.ts, and surface a cut-limit error when
clipboard readback fails.
- Fix MarkdownPreview same-file anchor scrolling to run before the
unknown-ownership guard so ambiguous folder-workspace ownership
still scrolls within the open document.
- Keep search's replace-disabled state derived from live matches
instead of a stale snapshot.
* Update lockfile to dedupe stale package versions after dependency resolu
- Removes duplicate/superseded resolutions (older @babel/* versions, fs-extra 11.3.4/11.3.5, plist 3.1.0, semver 7.7.4) left over from a prior install
- Aligns transitive deps to the single resolved versions already in use elsewhere in the tree
* feat(status-bar): notify upgraded users usage meters show % used
Show a one-time status-bar callout when upgraded profiles still use the
new percent-used default. Brand-new profiles and users who already chose
remaining stay quiet; dismissing or changing the setting is permanent.
* Add settings deep-link to expand Appearance's Window accordion for one-s
- Replaces the searchQuery-based redirect (fragile, flashed filter UI) with a
dedicated appearanceAccordionDeepLink store field that force-opens the
correct accordion and scrolls to the target row
- Rebuilds the status-bar change notice as a plain elevated card instead of
a Popover, since PopoverContent's glass/backdrop-filter defaults fought
the opaque callout styling and needed heavy overrides
- Simplifies the light/dark card CSS tokens accordingly
* Reposition status-bar usage-change notice via fixed-position portal
Portal the one-shot callout to document.body with fixed positioning
anchored via getBoundingClientRect, since the status-bar's overflow-hidden
flex ancestors clipped or mispositioned the previous in-tree absolute
layout.
* Refine status-bar usage notice styling and test coverage
- Replace hand-tuned light/dark card colors with existing design
tokens (--popover, --border) and the documented floating elevation,
so the callout stays in sync with the design system instead of
duplicating its own palette
- Add tests covering dismiss via X button, "Got it", and Escape
- Scope the foreground-process confirm assertion to the pane's ptyId
so an unrelated pane's delayed confirm can't cause a false failure