Repository navigation
Sync upstream 01bcc57ff (conflicts) - #5
Open
WrittenByAI wants to merge 417 commits into
Open
WrittenByAI wants to merge 417 commits into
WrittenByAI wants to merge 417 commits into
Conversation
Co-authored-by: Orca <help@stably.ai>
…inals (stablyai#7742 sub-issue B) (stablyai#7836) * fix(pty): stop daemon reattach/kill race from orphaning restored terminals Two cold-start defects let a PTY kill silently orphan a live daemon session after a renderer/app restart — the PTY-orphaning-on-restart half of stablyai#7742: - DaemonPtyAdapter.shutdown() was the only session op that skipped ensureConnected(). The daemon client connects lazily, so a kill arriving before the first spawn (startup sleep/hibernation sweeps, closing a restored tab) threw "DaemonProtocolError: Not connected" against a HEALTHY daemon; the renderer swallows the rejection and the live session survives detached. Fix: connect first, like every other session op. - pty:kill had no startup barrier while pty:spawn did. A kill issued before initDaemonPtyProvider swapped the provider resolved against the pre-daemon LocalPtyProvider, whose shutdown() silently no-ops on daemon ids; the handler then reported success and sent a synthetic pty:exit, permanently clearing the persisted tab->ptyId binding so the session never reattaches. Fix: pty:kill awaits the same getLocalPtyStartupPromise gate as spawn. Both reproduced red-first (real DaemonServer socket rig for the adapter; deferred-barrier IPC rig for the handler) and pass after the fix. Scope: this restores the reattach/teardown invariant. It does NOT address the renderer crash trigger or the daemon-process-death path that produces the Windows PowerShell FailFast symptom (separate follow-ups). * fix(pty): gate runtime shutdown on daemon startup * fix(pty): keep shutdown independent of hook startup
…pretty-print) (stablyai#9290) Co-authored-by: Orca <help@stably.ai>
…chunk 64KB concat) (stablyai#9291) Co-authored-by: Orca <help@stably.ai>
… (crash 99657ab1) (stablyai#9315) * fix(sidebar): guard every worktree sort against undefined displayName (crash 99657ab1) Worktree.displayName is typed non-optional but arrives undefined at runtime for persisted/discovered worktrees (crash 99657ab1). PR stablyai#8683 fixed the kanban board; this extends the same guard to the five other sort sites that share those worktree objects — including the Cmd+J switcher (order-empty-query-worktrees) — via one shared compareWorktreeDisplayName helper in lib/. Behavior-neutral when names are present; a missing name now sorts as '' instead of throwing. Co-authored-by: Orca <help@stably.ai> * docs(agents): add over-commenting anti-pattern example to the comment rule Anchors the existing 'document the why, briefly' rule with a concrete before/after (the worktree-displayName guard) so agents stop dumping the crash id, mechanism, file location, and every call site into a comment. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>
* fix(terminal): bypass rejected macOS login sessions * fix(terminal): bound macOS login preflight * test(terminal): isolate macOS login preflight * fix(terminal): avoid blocking macOS login preflight * fix(terminal): cancel pending PTY preparation * fix(terminal): cancel preparation on daemon shutdown
Groups 1 and 2 are full; point readers at the new third-group QR in EN/ZH README.
Scratch investigation doc is no longer needed on main.
…irst hover (stablyai#9320) Invalidate xterm's linkifier hover cache (throttled) when output streams into a visible pane, so a URL printed under a stationary pointer underlines and becomes Cmd/Ctrl+clickable on the next pointer move instead of after several clicks. Skips while a link is hovered (no flicker) and re-arms so the reset is never dropped mid-hover. Reuses the visibility-resume primitive (stablyai#9061).
…stablyai#9384) On a fork checkout (origin=fork, upstream=parent) PR details failed to load because getOwnerRepo() resolved only the origin remote while GitHub PRs live on the upstream parent. Make getOwnerRepo() prefer upstream (mirroring getIssueOwnerRepo), and pin the call sites that genuinely need the checkout's own origin identity (getRepoSlug, getRepoUpstream, createGitHubPullRequest, resolvePrWorkItemSource) to the origin-only primitive. Lands the fix community-identified in stablyai#7332 and hardened in stablyai#7513. Closes stablyai#7331 Co-authored-by: fsdwen <1214772+fsdwen@users.noreply.github.com> Co-authored-by: brennanb2025 <79079362+brennanb2025@users.noreply.github.com>
… bar (stablyai#5399) Derive the collapsed session limit label from resetsAt and tick it live via a shared boundary-scheduled countdown clock (no polling). Combines stablyai#6252/stablyai#6585. Fixes stablyai#5399. Co-authored-by: gatsby74 <166927047+gatsby74@users.noreply.github.com>
…re/which spawn) (stablyai#9297) Resolve agent CLIs against PATH with fs instead of spawning one where/which subprocess per candidate (~34 at startup). Same found/not-found result (same env/PATH, faithful which/where semantics); subprocess spawns 34->0. Fixes stablyai#9297.
…he dialog (stablyai#9397) Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Orca <help@stably.ai>
* fix(chat): preserve drafts through reconnects * fix(terminal): bound stale handle reconnect polling * refactor(chat): extract native view props * fix(chat): harden reconnect lifecycle * fix(terminal): replace stale reconnect identities atomically * fix(terminal): recover mirrors after reconnect polling * docs(reliability): record merged reconnect coverage * fix(terminal): preserve reconnect lifecycle state * fix(terminal): keep reconnect polling truly bounded
* Guard add-review-note chord to prevent remount (product B) - Scoped guards consume chord at composer level to prevent remount and leakage - Handle OS key-repeat: ignore when no draft, consume when one is mounted - Clear stale block keys in markdown preview when content renumbers - Flush pending selection before reading targets to fix timing races * fix(editor): repair add-review-note guard tests and close remaining chord gaps - Update the product-B guard tests to the Mod+Shift+A default binding (stablyai#9257 retired Mod+Alt+N as AltGr-unsafe); they asserted the old chord, so seven landed red and the rich-editor repeat test passed vacuously. - Monaco: recompute the annotation target from the live selection at keydown instead of the render-lagged ref, so a chord right after a drag cannot open on the previous selection or miss a fresh one. - Preview: key the stale-block-key cleanup on renderedContent (the DOM the block keys live in), which can lag content during external-edit section preservation. Co-authored-by: Orca <help@stably.ai> * fix(editor): mirror shortcut-guard refs in effects instead of render body CodeRabbit on stablyai#9412: render-body ref writes can leak from a render pass React replays and discards. Move the state->ref mirrors for commentPopoverRef / shouldShowMarkdownAnnotationsRef (MonacoEditor) and activeAnnotationBlockKeyRef (MarkdownPreview) into effects; same-tick keydown paths keep their eager event-handler writes. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>
…tablyai#9420) Raise the floating terminal panel from z-30 to z-45 so it sits above notification cards (z-40) but below the modal layer (z-50), preventing notifications from burying the terminal. Raise the toggle button to z-46 to keep it clickable where it overlaps the panel.
* feat(ssh): download folders from remote explorer * fix(ssh): harden remote folder downloads * Add missing getRepo stub to worktree cwd test mock Restoring headless mobile tabs looks up the repo for the active worktree id; the mock lacked getRepo, so the test only passed incidentally. Add it explicitly and return undefined since wt-1 is a worktree id, not a registered repo. * Enable SSH folder downloads, gated for system-SSH connections - Folder downloads require SFTP, unavailable on system SSH (which offers only raw file operations). Add supportsFolderDownload flag to gate the feature in the UI layer. - Reject symlinks at directory-entry level, preventing tree escapes and eliminating unnecessary stat calls. - Check abort signal before opening dialog for better responsiveness when renderer closes. - Log cleanup errors without re-throwing to preserve underlying transfer failures. * Gate SSH folder downloads to SFTP-capable connections Enforce fail-closed gating and add Windows path traversal validation to ensure downloads are only available when explicitly supported and safe. * Gate SSH folder downloads to SFTP-capable connections Enforce fail-closed gating and add Windows path traversal validation to ensure downloads are only available when explicitly supported and safe. * fix(ssh): keep provider types under max-lines after main merge Move FolderDownloadOptions next to the SFTP download implementation and narrow IFilesystemProvider.downloadFolder options to AbortSignal only so types.ts stays within the 300-line oxlint budget when merged with main. --------- Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
…#9070) Only offer 'Proceed Anyway (Unsafe)' if the connected remote runtime advertises browser.certificate-trust.v1 support. Older runtimes cannot honor the request and would fail silently, creating a false affordance. Centralize certificate error normalization to prevent divergence between main and renderer certificate matching, and unify URL redaction for Kagi session token stripping across load-error paths.
…lyai#5785) * Allow hiding Orca Mobile sidebar button once a device is paired Introduce a shared external store (`paired-mobile-devices.ts`) to cache and synchronize the paired mobile device list across the sidebar, Settings pane, and Mobile page. This prevents redundant backend IPC requests when multiple surfaces mount simultaneously. Using this shared pairing status, display an inline "Hide from sidebar" control next to "Orca Mobile" in the navigation sidebar once a device has been paired. This allows users to easily declutter their sidebar after completing setup. * Handle device load errors with recovery on focus/reconnect - Add error flag to distinguish failed device loads from empty device lists - Recover from transient startup IPC failures by retrying on window focus or online - Validate revoke device success before routing or showing success toast - Only show hide control after first device is actually paired - Use snapshot getter to avoid manual device ref tracking in MobilePane * Handle device load errors with recovery on focus/reconnect - Shared module-level listeners for failed load recovery reduce IPC spam compared to per-consumer event listeners on every focus/online event. - Optimistically remove revoked devices if post-revoke reload fails, keeping success toast and intro routing correct. - Prevent repo/branch label overflow with CSS text truncation. - Fix HTML entity rendering: use plain spaces instead of in translations so React text nodes render them correctly. - Add comprehensive tests for the paired devices hook covering load, navigation, revoke, and error recovery paths.
…9437) Resolve Microsoft Store PowerShell App Execution Aliases to their real package executable before ConPTY spawn, while preserving explicit PowerShell choices and the existing fail-safe fallback chain.
…tablyai#9398) * fix(composer): show full worktree path on hover in Run on dropdown Co-authored-by: Orca <help@stably.ai> * refactor(composer): use native title tooltip for Run on paths Co-authored-by: Orca <help@stably.ai> * fix(composer): reliable native-style tooltip for Run on paths The native title attribute won't re-trigger between adjacent rows in Chromium, so the tooltip flickered/dropped as you moved down the list. Use the shared (controlled) Tooltip instead, styled compact + arrowless to read like an OS tooltip; the app-level provider's skip-delay makes row-to-row hovers reliable. Co-authored-by: Orca <help@stably.ai> * fix(composer): stop Run on path tooltip wedging shut Radix's uncontrolled hover state could flash the tooltip open then wedge it closed inside the cmdk list (shared pointer-transit state getting stuck), so re-hovering never reopened it. Drive open state with a controlled hover-intent handler (open after a delay, close after a short grace) so re-entry always reopens and transient enter/leave thrash debounces to a stable state. Co-authored-by: Orca <help@stably.ai> * fix(composer): rebuild Run on path tooltip as a portal (no loop/wedge) Both the native title and Radix Tooltip (controlled or not) misbehaved inside the cmdk list: flashing, wedging shut, or opening/closing in a loop. Replace with a self-contained tooltip that renders a fixed, pointer-events-none portal on document.body and only changes state on pointer enter/leave/down (never pointermove). Opening it cannot reflow the list or become the hover target, so it structurally cannot create the enter/leave feedback loop. Co-authored-by: Orca <help@stably.ai> * fix(composer): trigger Run on path tooltip on the path line, always below - Scope the hover trigger to the truncated path line itself (not the whole row), so only hovering the path reveals it. - Always position the tooltip below the hovered line for predictable placement (was flipping above near the viewport bottom). Co-authored-by: Orca <help@stably.ai> * fix(composer): anchor Run on path tooltip under the path line The old placement anchored to the window's right half when the trigger sat past viewport-center, which shoved the tooltip to the far right edge of the window, disconnected from the dropdown. Always left-align it directly under the hovered path line and cap max-width to the remaining viewport width so long paths wrap instead of overflowing. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>
…n mobile (stablyai#9801) * fix(mobile): persist per-device tab selection so worktree return restores the last open tab A phone's tab selection lived only in the host's in-memory ClientSessionTabSelectionStore. Any host restart wiped it, and the per-device projection then fell back to deterministic topology, so returning to a worktree on mobile always landed on the first tab instead of the tab last opened on the phone. Persist the per-device selections in the Store (keyed deviceId -> worktreeId), hydrate them when the runtime constructs, and guard projection so an early empty snapshot after restart cannot wipe a hydrated selection before tabs arrive. Selections are pruned with the worktree/repo and on device revoke, and malformed persisted payloads degrade to empty instead of throwing. * fix(mobile): harden persisted tab selection cleanup * fix(mobile): preserve tab selection across worktree rename
…ed (stablyai#9780) * feat(mobile): mount ProtocolBlockScreen when protocol compat is blocked ProtocolBlockScreen existed since PR stablyai#1440 but was never mounted: on a 'blocked' compat verdict the only output was a console.warn, so a future MIN_COMPATIBLE_RUNTIME_CLIENT_VERSION bump would have silently shown a broken host UI instead of the update screen. Add HostProtocolGate — a choke point in app/h/_layout.tsx above every /h/[hostId] route — that consumes useHostStatusGates and replaces the blocked host's entire UI (sidebar + detail stack) with ProtocolBlockScreen. The host list and other hosts stay usable; the screen's own 'Back to hosts' escape hatch routes to '/'. Both block reasons render their respective CTAs (mobile-too-old → App Store, desktop-too-old → GitHub Releases). Compat logic stays in the src/shared mirror contract — no fork. * fix(mobile): fence incompatible host routes efficiently * fix(mobile): route Android updates to releases
* feat(source-control): show current branch in header * fix(source-control): keep header focused on branch * fix(source-control): compact detached head identity * fix(source-control): make branch identity keyboard accessible * fix(source-control): keep create review in checks
…erer OOM (stablyai#9872) (stablyai#9936) The live `agentStatusByPaneKey` map had no size cap. `setAgentStatus` rewrites it with a full spread copy on every status ping and keeps rows until a pane/tab teardown event removes them; a missed teardown (agent killed without a Stop hook, pane/tab closed while its status lingered) orphans a row forever. On long multi-agent sessions orphaned heavy rows accumulate without bound, and because each ping spread-copies the whole map, once it is ~1.9 GB one ping transiently doubles it past the 3586 MB old-space limit -> renderer crash (exit -36861). Cap the live map at MAX_LIVE_AGENT_STATUSES=500, shedding only rows whose pane is provably gone (a mounted tab's rooted layout no longer lists the leaf) or long idle, and never an open pane's row (any state, incl. needs-input waiting/blocked). Rootless/empty-snapshot, not-yet-hydrated, and no-renderer-tab (orchestration worker) rows are unprovable: kept while a fresh agent could own them, shed only past the stale window or by a hard-cap fallback that guarantees the bound. Eviction bumps the status/sort epochs so the retention sync snapshots disappeared done rows. Cost is one Object.keys length check on the reducer's already-O(n) spread under the cap; the layout walk + sweeps run only on the rare over-cap ping. Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
…ablyai#9782) * feat(mobile-pairing): surface unpaired-device auth failures instead of silent 4001 loops Desktop: when a phone repeatedly fails direct-transport E2EE auth with a token missing from the device registry (pre-v1.4.106 pairing-path bug left desktops that regenerated their registry rejecting paired phones forever), throttle to one notification per session and show an actionable toast pointing at Settings -> Mobile to re-pair. Mobile: map a bare 4001 close onto the existing auth retry budget (the encrypted e2ee_error is undecryptable when the desktop keypair changed, so the close code is the only surviving signal) instead of looping the generic reconnect forever, and make the auth-failed verdict say 'Pairing invalid - re-pair with your desktop' instead of a bare 'Auth failed'. * fix(mobile-pairing): handle stale keys and startup notification races * fix(mobile-pairing): isolate auth notification failures * fix(mobile-pairing): keep recovery alert actionable
* perf(mobile): gate host polling on foreground The mobile host screen ran two 3s polls (routed + embedded), each firing worktree.ps AND repo.list, with no foreground/background gate — so a connected phone kept pinging every 3s (worktree.ps is a full multi-repo process scan) plus a radio wakeup, including brief background windows while the socket stays parked. Consolidate both into one startHostWorktreeRefresh lifecycle and AppState-gate the interval so BOTH polls stop while backgrounded and refresh immediately on foreground return. worktree.ps keeps its 3s cadence while foregrounded (it carries live agent status/preview/unread that no push event replaces). repo.list stays on the interval as an AppState-gated, self-throttling (REPO_METADATA_REFRESH_MS=60s) convergence safety-net — desktop Settings repo edits notify only the renderer, not the runtime clientEvents stream, so it can't be made purely event-driven without going stale — and additionally gets a reposChanged/worktreesChanged fast-path and reconnect-replay refetch. Verified in a deps-installed mobile checkout: full mobile suite 2232 pass, typecheck, oxlint (within the frozen max-lines budget), and oxfmt --check all clean. Co-authored-by: Orca <help@stably.ai> * chore(mobile): drop stale fetchRepoMetadata dep from the reconnect effect Address CodeRabbit nitpick: the reconnect effect no longer calls fetchRepoMetadata (that refetch moved into startHostWorktreeRefresh), so it shouldn't remain in the effect's dependency array. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Orca <help@stably.ai>
stablyai#9979) * fix(mobile): keep quick-commands button steady while capabilities load The tab-row quick-commands button only rendered once the capability probe resolved true, so it popped in after the row was already visible (and vanished during reconnect re-probes). Render it whenever support is not confirmed absent and disable it until the probe settles — pre-quick-commands hosts strip agentPrompt, so the action (not the button) must wait for confirmation. Confirmed-unsupported hosts still hide it entirely. * fix(mobile): explain unsupported quick commands on tap instead of hiding Per feedback on the disabled/hidden states: the button now always renders and stays tappable. Tapping against a desktop that confirmed no support shows "Desktop update required for quick commands" (mirroring the browser streaming copy); tapping while the capability probe is still resolving says to try again in a moment. The sheet still opens only once support is confirmed, since pre-quick-commands hosts strip agentPrompt. * docs(pr): add QA screenshots for quick-commands button states * test(mobile): lock quick-commands button stability Add a focused source-contract test for the always-mounted tab action and confirmed-support sheet gate. Keep the non-obvious safety comment concise, and remove PR screenshots now hosted as GitHub user attachments. * test(mobile): structurally guard quick-command action mount
…9843) react-markdown's <Markdown> has no internal memoization: it rebuilds the whole unified remark->rehype->highlight->katex processor and re-parses the document on every render. MarkdownPreview re-renders on internal state that does not affect the rendered output — most visibly, every keystroke in Find (query/match-index state) — so a large doc re-ran the full parse + syntax-highlight + KaTeX pass per keypress, making Find laggy. Hoist the two fully-static plugin arrays to module scope (a fresh array identity per render would defeat the memo) and render the body through a React.memo'd MarkdownBody keyed on content + components. The pipeline now re-runs only when the rendered content or the components map actually changes; Find/review-pulse/copied- note re-renders skip it. The components map was already memoized, so its identity is stable across those re-renders. Behavior unchanged: 106 existing MarkdownPreview tests pass. Co-authored-by: Orca <help@stably.ai>
…i#9842) The iOS MJPEG and Android scrcpy device streams are gated only on the pane being the active tab (isActive, PR stablyai#7382). When the emulator tab is frontmost but the whole Orca window is hidden/minimized/occluded/display-asleep, the full-fps pipeline keeps running: main-process socket read + JPEG/H.264 decode + IPC + renderer decode. Renderer background-throttling (stablyai#9395) cannot stop it because the pipeline is IPC-push driven from main. Gate showStream additionally on window visibility via a new occlusion-safe hook that honors the terminal stale-visibility latch (so a display-sleep occlusion wedge can't freeze the emulator on a black frame) and delays the visible->hidden park by 500ms so a quick Cmd+Tab round-trip doesn't renegotiate the device stream. Co-authored-by: Orca <help@stably.ai>
…#9995) Zone.js patches the global Promise with a non-native thenable. When a bare `new Promise(...)` crosses the Electron executeJavaScript boundary, it's serialized as-is, losing { page, target } and exposing __zone_symbol__* fields instead. Wrap in an async IIFE to return a native promise that Electron always unwraps correctly.
…blyai#9985) Production crash diagnostics measured ~128 `git worktree list` execs/min (9,400 in one 80-minute session, ~16% of wall-clock in git subprocesses): the resolved-worktree scan fans out over every registered repo on a 30s cache TTL, and most registered repos on the affected installs were agent-CLI scratch repos (~/.codex-tmp capsules, vendor imports, skill checkouts) that need no freshness. Classify agent-scratch repo roots with a curated shared matcher and stamp their scan-cache entries with a 5-minute TTL instead of 30s. Orca-driven mutations still bypass the TTL via the per-repo generation bump, so only passive pickup of external changes slows for scratch repos. Expected steady-state reduction on the measured install: ~82% fewer git spawns.
…7936) (stablyai#9826) * fix(daemon): retire macOS daemons whose login session died (stablyai#7936) A daemon that survives a full macOS logout is unsalvageable: its PAM context can no longer host login(1) spawns (every new PTY becomes a 'Login incorrect' prompt zombie) and its Mach bootstrap namespace has lost the system DNS resolver, so terminals it hosts have no egress. Today it also keeps the stablyai#9301 preflight's cached 'accepted' verdict, so it keeps wrapping spawns in login(1) forever; only a manual daemon restart recovers. GUI-spawned daemons now watch for login-session death from the inside: a fresh cache-bypassing PAM probe (triggered by PTY-exit bursts, fresh client hellos, and a slow periodic timer) must conclusively reject three consecutive times AND the in-process system resolver must be degraded; then the daemon exits crash-style so session meta stays unclean and the replacement daemon cold-restores scrollback. A conclusive rejection also flips the spawn-wrapper cache off immediately. Headless serve/SSH daemons never get the watch (they must survive their spawning session ending), and a session that never conclusively accepted login(1) never arms it — a PAM anomaly alone can't kill a healthy daemon (fast user switching keeps accepting, so switched-away sessions are preserved). * test(daemon): e2e seam to drive login-session death oracles from a verdict file A dead macOS login session cannot be fabricated without root (PAM owns audit-session teardown), so live lifecycle QA drives the death watch's probe and resolver oracles from ORCA_E2E_LOGIN_SESSION_PROBE_FILE: 'alive' → accepted/healthy, 'dead' → rejected/unhealthy, anything else inconclusive — with compressed watch timing. Mirrors the existing ORCA_E2E_DAEMON_INIT_DELAY_MS seam; inert unless the env var is set. * fix(daemon): close the hang-shaped gap in login-session death detection The conclusive-PAM-verdict trigger had one blind failure shape: login(1) hanging at the prompt past the probe bound (killed → inconclusive forever → the watch never fires). Three changes close it: - The death-watch probe gets its own 4s bound (the 500ms preflight bound exists for spawn-path latency, which doesn't apply off-path), so a slow-but-answering PAM stack isn't misread as a hang. - An inconclusive pipe probe escalates to a PTY-hosted probe via script(1) — a dead session's PAM stack may only misbehave under a real tty (the pipe-vs-PTY fidelity limit the preflight documents). - A streak of timeout-killed probes (which a live session never produces) is a second retirement trigger, at a higher threshold (5) and still gated on the degraded resolver, logged with a distinct cause so field logs discriminate the two paths. Every dead-session behavior — fast reject, prompt-then-EOF, or hang — now fires retirement; all inconclusive states still fail toward preserving the daemon. * fix(daemon): keep login-session retirement conclusive * fix(daemon): stop login watch before clean shutdown * fix(daemon): make login-session PTY probe reliable * fix(daemon): close login-session watch races * fix(daemon): ignore health probes for login watch activity
…ai#9980) * test(e2e): verify Claude is prefilled with issue URL on start Regression test for stablyai#6613: when starting a workspace from a newly created GitHub issue, ensure the issue URL is passed to Claude via `--prefill` and `--dangerously-skip-permissions` flags. This prevents context loss after issue creation. * test(e2e): fix GitHub-issue-start prefill test flakiness - Reorder mock API handlers to ensure `/labels` and `/assignees` paths match before the specific issue endpoint - Replace regex heading matcher with exact string for more reliable assertions - Refactor terminal content polling to capture text once and reuse in subsequent assertions
* fix(terminal): defer remote output ACKs until parse * test(terminal): document synchronous credit claims --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
…tablyai#10000) The workspace-options filter row used the Workflow icon while the Automations nav item and page use CalendarClock. Match them so the filter clearly maps to automation-created workspaces.
… a remote runtime is active (stablyai#6628) * fix(worktrees): refresh local worktrees in the sidebar while a remote runtime is active When a remote runtime is active, a local `worktrees:changed` event for an unbound repo was dropped by the renderer guard in useIpcEvents. Worktrees created outside Orca for that repo (e.g. `orca worktree create` from a CLI or automation flow) therefore stayed invisible in the sidebar until an app restart, even though their sessions were already running. The guard existed because an unbound repo's list fetch routes to the active runtime (settingsForKnownRepoOwner's unbound fall-through), so refreshing with local worktree ids could query — and purge against — the remote host. Instead of dropping the event, pin the refresh to the local host (forceLocalOwner): fetch the worktree list against the local owner and merge additively. The merge is host-scoped and the deletion-purge is skipped on this path, so it only ever adds local-host worktrees and never overwrites the active runtime's worktree state. A genuinely-removed local worktree is reclaimed by the next unguarded full refresh. * test(e2e): regression — CLI-created worktree visible while a remote runtime is active Drives the real `orca worktree create` path: the CLI RuntimeClient calls `worktree.create` over the app's socket, registering a managed worktree and firing the `worktrees:changed` IPC the renderer listens for. Stages a remote runtime as active by injecting `activeRuntimeEnvironmentId` into the renderer store, so no real remote host is needed. Fails on the prior behavior (the worktree never appears while a runtime is active) and passes with this fix. * fix(worktrees): pin local lineage refresh during runtime activity Co-authored-by: Orca <help@stably.ai> * review: trim comments to house style, normalize queue coalescing to booleans * review: sweep rename-grace expiry before early returns in worktrees:changed handler * review: document accepted workspace-space gap, drop imprecise 'additive' wording * fix(worktrees): route duplicate local repo events locally * fix(worktrees): tag local worktree events at origin, gate purge skip on runtime overlap * test: pin origin-based forceLocalOwner with a no-runtime local event assertion --------- Co-authored-by: brennanb2025 <brennankbenson@gmail.com> Co-authored-by: Orca <help@stably.ai> Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
…tablyai#9996) * feat(agent-status): show question glyph for needs-you state everywhere Replace the amber attention dot with the dashboard's MessageCircleQuestion chat glyph for the waiting/permission "needs you" state across all surfaces: the agent dashboard cards, in-app dashboard rows, the sidebar's Agent Dashboard quick-indicator counts, the worktree-level status dot, and the shared agent-row/terminal-tab indicators. On the dashboard card the header glyph is suppressed when a question summary pill is present so "needs you" reads once, not twice. * test(agent-status): assert amber question glyph, not amber dot The needs-you unification replaced the amber dot with the amber MessageCircleQuestion glyph, so update the remaining state assertions in DashboardAgentRow, WorktreeCardStatusSlot, and TerminalTabLeadingIcon to match (lucide-message-circle-question + text-amber-500). * test(agent-status): cover needs-you glyph surfaces
…ablyai#9883) * perf(web): pause runtime heartbeat while hidden Co-authored-by: Orca <help@stably.ai> * fix(web): preserve inbound-liveness baseline across a hidden heartbeat re-arm The visible re-arm rebaselined lastInboundFrameAt=now, so a socket that went silent while the window was hidden looked freshly-heard-from and its death was masked for another full idle window (~25s). Move the fresh-connect baseline into startHeartbeat (the real 'we just connected' moment) and have the visible re-arm only reset the tick clock + clear an in-flight probe, preserving lastInboundFrameAt so the next visible tick probes a stale connection promptly and closes if unanswered. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>
…nected (stablyai#9885) * perf(runtime): idle websocket heartbeat without clients Co-authored-by: Orca <help@stably.ai> * fix(runtime): probe immediately when the WS heartbeat arms Arming the heartbeat on the first accepted connection started a fresh interval, so the first liveness ping was a full interval (~15s) out — a socket that died right after connecting went unprobed for that window. Run one sweep synchronously in start() so the first ping goes out at arm time; the seeded socket is pinged (never reaped on the arm sweep) and reaped on the next tick only if it never pongs. Tests updated for the earlier first probe. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>
…blyai#9888) * perf(mobile): coalesce overlapping home requests Co-authored-by: Orca <help@stably.ai> * fix(mobile): queue a trailing follow-up for triggers during an in-flight read Single-flight returned the in-flight promise to any trigger that arrived mid-read, so a distinct refresh requested while a slow read was on the wire was silently answered by the older response and never re-read the latest state (UI could stay one refresh cycle stale). Coalesce mid-flight triggers into exactly one trailing follow-up (latest params win) whose fresh result is delivered to those callers. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>
…ingle-flight (stablyai#9892) * fix(mobile): gate dictation setup polling Co-authored-by: Orca <help@stably.ai> * fix(mobile): fence a stale dictation refresh against a newer setPolling intent An in-flight setup read resolving 'keep polling' after an explicit setPolling(false) wrote polling=true and rescheduled, resurrecting a poll the caller had just stopped. Snapshot a pollingRevision when each read starts and only apply its result if no explicit setPolling superseded it mid-flight — so a late true can't restart a stopped poll (nor a late false cancel a restart). Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>
Resolved by fork-sync agent; see report.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upstream
01bcc57ffmerged into the fork with conflicts.Unresolved markers remain in: package.json, pnpm-lock.yaml, src/renderer/src/i18n/locales/en.json, src/renderer/src/i18n/locales/es.json, src/renderer/src/i18n/locales/ja.json, src/renderer/src/i18n/locales/ko.json, src/renderer/src/i18n/locales/zh.json
Fork files upstream also touched: package.json, pnpm-lock.yaml, src/main/github/client.ts, src/main/ipc/github.test.ts, src/main/ipc/github.ts, src/main/runtime/orca-runtime.ts, src/main/runtime/rpc/methods/github.test.ts, src/main/runtime/rpc/methods/github.ts, src/main/runtime/runtime-rpc.ts, src/preload/api-types.ts, src/preload/index.ts, src/renderer/src/assets/rich-markdown-editor.css, src/renderer/src/components/editor/EditorContent.tsx, src/renderer/src/components/editor/EditorPanelShell.tsx, src/renderer/src/components/right-sidebar/SourceControl.tsx, src/renderer/src/i18n/locales/en.json, src/renderer/src/i18n/locales/es.json, src/renderer/src/i18n/locales/ja.json, src/renderer/src/i18n/locales/ko.json, src/renderer/src/i18n/locales/zh.json, src/renderer/src/lib/language-detect.ts, src/renderer/src/store/slices/diffComments.test.ts, src/renderer/src/store/slices/diffComments.ts, src/renderer/src/web/web-preload-api.test.ts, src/renderer/src/web/web-preload-api.ts, src/shared/types.ts
Upstream merge conflict report —
01bcc57fforigin/main@01bcc57ff("perf(mobile): gate dictationsetup progress polling on foreground + single-flight (perf(mobile): gate dictation setup progress polling on foreground + single-flight stablyai/orca#9892)") into fork
HEAD@0e6048b34.package.json,pnpm-lock.yaml, and the five localefiles
src/renderer/src/i18n/locales/{en,es,ja,ko,zh}.json.git add/commit/mergerun.git diff --checkis clean; all five localefiles and
package.jsonparse as valid JSON (jq empty).package.jsonpnpm.overridesmap.{ "monaco-editor>dompurify": "3.4.11" }."@modelcontextprotocol/sdk>@hono/node-server": "2.0.10"and bumped
"monaco-editor>dompurify"3.4.11 → 3.4.12."@tiptap/extension-highlight": "3.22.5"— a fork-onlypin required by the tldraw canvas feature (tldraw's rich-text path drags in
tiptap; see the "Грабли форка" note in
CLAUDE.md).(
3.4.12) and keeping the fork's tiptap pin:pnpm-lock.yaml(5 conflict regions)Only 5 regions conflicted; everything else auto-merged. Notably, upstream's
dompurify@3.4.12and@hono/node-server@2.0.10package and snapshot entriesauto-merged in cleanly (verified present at lines 4023/10151 and 1009/7295), so
the combined overrides above are backed by real resolutions.
1.
overrides:block (top of file)Mirror of the
package.jsonconflict. Resolved to the same union, keys/valuesmatching
package.jsonexactly (pnpm compares the lock'soverridesagainstpnpm.overrides):2 & 4.
idb/ieee754(packages + snapshots sections)idb@7.1.1andieee754@1.2.1.buffer@5.7.1).idb@7.1.1is a real dependency of the fork's@tldraw/editor@5.2.4(referenced at the auto-merged snapshot line ~8988) and of
tldraw@5.2.4itself → kept.
ieee754@1.2.1was, in the fork, referenced only bybuffer@5.7.1(
optional: true). Upstream removedbuffer@5.7.1entirely, and thatremoval auto-merged in — so in the merged tree nothing references
ieee754anymore (no
buffer@5.7.1, noieee754: 1.2.1reference remain). Keeping itwould leave a dangling/orphan lock entry → dropped (follows upstream).
idb@7.1.1in both sections, dropieee754@1.2.1from both.3 & 5.
tldraw@5.2.4/tldts-core(packages + snapshots sections)tldraw@5.2.4package + snapshot (the fork's corefeature) plus
tldts-core@7.0.30.tldts-core@7.4.9(upstream bumped the unrelatedtldtsURL-parsing lib
7.0.30 → 7.4.9).tldts@7.4.9(common, auto-merged) depends ontldts-core: 7.4.9; nothing references7.0.30outside the conflict → thefork's
7.0.30was stale.tldraw@5.2.4(package + snapshot, unchanged), takeupstream's
tldts-core@7.4.9in both sections, drop7.0.30.Post-resolution structural checks (all pass): no leftover
7.0.30,dompurify 3.4.11, orbuffer@5.7.1;idb@7.1.1present in both sections;ieee754fully absent;tldts-coreunified at7.4.9; overrides matchpackage.json.The analysis above shows an internally consistent graph, but I could not run
pnpm installin this sandbox to get a green check. CI'spnpm install --frozen-lockfileis the final authority — if it reports thelock as out of date, re-run
pnpm install --lockfile-onlyon the mergedpackage.jsonand commit the regenerated lock.Locale files —
en.json,es.json,ja.json,ko.json,zh.jsonAll five files have the same two conflict regions with identical structure
(only the translated string values differ). Both are clean add/add conflicts:
distinct sibling keys added to the same JSON object by each side.
Region A (~line 9772–9778): a source-control string bucket
"5c951f3e68": "Canvas","897d7c622d": "Canvas"(canvaslabels for the tldraw feature; "Canvas" is intentionally untranslated in every
locale).
"97e7124eac"("Could not refresh Source Control…") and"a4e93c21d7"("Current branch: {{value0}}"), each translated per locale.comma-joined; no trailing comma before the closing brace.
Region B (~line 12344–12404): tldraw blocks vs.
editor.save.failureFork added: four sibling objects —
TldrawIssueDialog,TldrawSelectionOverlay,TldrawViewer, and a nestedtldraw.issue.imagebucket (all fork-feature strings, carried as English fallback in every locale).
Upstream added: a nested
editor.save.failure.notice."8c59ce5075"("Failed to save the file. Please try again.") — also English in every locale
in this diff.
Why they collided: both sides appended keys at the same position, and the
fork's final key was deeply nested (
tldraw → issue → image → …) whileupstream's was deeply nested (
editor → save → failure → notice → …), so theshared closing braces after the marker had to be re-associated.
Resolution: kept the fork's tldraw blocks, closed the
tldraw.issue.imagenesting (
}}},), then appended upstream's fulleditorblock. Verified bracebalance and JSON validity for all five files.
Human must decide: nothing on structure. Optional follow-up: the fork's
tldraw strings and upstream's
editor.savestring are English placeholders inthe non-English locales — real translations can be added later via the normal
localization pass (and the zh value-override script), but that is unrelated to
this merge.
Verdict
All 7 conflicted files resolved confidently. The only item warranting a human/CI
touch is the hand-merged
pnpm-lock.yaml, which should be confirmed bypnpm install --frozen-lockfilein CI (standard for any lockfile merge).