[upstream #13232] fix(windows): keep Ctrl-W in Git Bash terminals - #164
Open
innocarpe wants to merge 1326 commits into
Open
[upstream #13232] fix(windows): keep Ctrl-W in Git Bash terminals#164innocarpe wants to merge 1326 commits into
innocarpe wants to merge 1326 commits into
Conversation
* fix(terminal): clear stranded link hover tooltip * fix(terminal): declare the tooltip reserve var where it resolves --orca-terminal-link-tooltip-height was declared on .pane-manager-root, a class no live element carries, so both .xterm-container height calc()s were invalid at computed-value time and collapsed to height:auto — the element FitAddon measures, making rows a fixed point. Also isolate _clearCurrentLink() so a throwing provider leave() cannot skip the cache invalidation, and bound the e2e gap assertion on both sides. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>
…omation denials (STA-3491) (stablyai#12848) * fix(daemon): detect severed macOS TCC attribution and surface daemon-restart remedy (STA-3491) macOS pins the detached PTY daemon's TCC responsible process to the app binary that forked it. Once that binary is deleted (packaged updates replace the bundle), Accessibility/Automation grants on Orca silently stop covering every daemon-hosted terminal: osascript/System Events fails with -25211 no matter what the user grants. - record spawnerExecPath in the daemon pid file at fork - adoption checks it: severed + 0 live sessions -> replace the daemon (reason severed_tcc_attribution); live sessions are preserved - Settings (Developer Permissions + Manage Sessions) show a visible banner pointing at Manage Sessions -> Restart while severed * fix(daemon): harden TCC attribution recovery
…tablyai#12842) - `truncate` has no effect on inline boxes, so long branch names would overflow their flex item and run under the line-total chip - Adding `block` display forces text truncation with ellipsis instead - Increase gap from 1.5 to 2 so ellipsis doesn't visually merge with chip
…i#12681) hasCursorAgentReattachPayloadScreenSignal built a char-by-char copy of the entire reattach payload so it could read the last header plus 5000 chars. On a 2MB daemon snapshot that cost 17.5ms of synchronous renderer main-thread work — ~75% of what xterm then spends parsing the same bytes — and the miss case paid it in full for a result that is always false. Two changes, both matching existing in-tree precedent: bound the scan to a 256KB tail (as the kitty tracker already bounds its own scan), and strip via the shared precompiled CSI_SEQUENCE_PATTERN instead of a hand-rolled loop, which is also faster in V8 because it copies spans rather than building a rope per character. 2MB snapshot, header hit 17.5ms -> 0.80ms (22x) 2MB snapshot, miss 8.7ms -> 0.52ms (17x) 200KB snapshot, header hit 1.5ms -> 0.62ms (2.4x) config/scripts/terminal-reattach-payload-scan-benchmark.mjs reproduces this and asserts every candidate agrees with the baseline before timing it. It also records a negative result: porting the daemon mouse mirror's includes() pre-filter to the kitty tracker makes reattach slower, because snapshots always contain the introducer. Adds guards for the two behaviours a future shortcut would silently break: a CSI-split header must still match, and a header behind the tail bound must not. Also byte-pins POST_REPLAY_REATTACH_RESET_KEEP_MOUSE, which shipped unpinned. Co-authored-by: Orca <help@stably.ai>
* Retire SSH worktree metadata an authoritative scan proved gone The metadata fallback's protection against resurrecting externally deleted worktrees lived only in renderer module state, so it died on every reload while the SSH WorktreeMeta it guarded against persists forever (gcStaleWorktreeMeta exempts any repo with a connectionId, because a local existsSync cannot probe a remote path). Repro: `git worktree remove` on the SSH host, let the authoritative scan purge the row, restart — the startup fetch runs before SSH connects and the fallback re-lists the deleted worktree as a ghost row. Chose option (a), deleting the stale persisted meta in main, over persisting the removal memory: the metadata is the thing that outlives the worktree, and Orca's own removals already delete it (removeWorktreeMetadataAndTransientState), so external removals now converge on the same end state instead of accumulating a second, parallel tombstone list that would itself need eviction. The in-session memory stays for the window before the async delete lands. New `worktrees:forgetRemovedForExecutionHost` only accepts SSH hosts, requires an exact repo owner, skips metas owned by another host, and refuses folder repos — a folder workspace's meta IS the workspace record (gcStaleWorktreeMeta skips those keys for the same reason) and no remote scan can retire one. The renderer only calls it from the authoritative-removal path, so a mere disconnect never deletes anything. Also: - hoist resetAuthoritativelyRemovedWorktreeMemoryForTests into a top-level beforeEach; removeWorktree writes that memory too, so suppression could leak across describes and silently hide a row. - cover the requireAuthoritative gate that skips the fallback, which had no test. - replace the raw NUL byte committed inside the coalesce-key template literal with a \0 escape; it made the file scan as binary to grep/ripgrep. * test(worktrees): verify non-authoritative fallback skips removal The non-authoritative fallback must not trigger worktree cleanup when it observes an absence — only an authoritative scan should. Tighten the expectation to ensure cleanup happens exactly once, when new data arrives after the connection state changes.
…12796) * refactor(mobile): demote address picker to optional disclosure on Relay Relay provides remote access without requiring a specific local address, so hide the picker behind a disclosure to keep the direct fast path accessible without visual clutter. Reposition Sign in between the Relay and LAN options to clarify it's Relay-specific. Keep custom addresses always visible and force the disclosure open when settings search targets the address picker. * refactor(mobile): improve relay pairing guide and interface ranking - Rank Docker/VirtualBox bridges below real LAN addresses so they're never auto-advertised as the default - Clarify UI copy: 'Local network address (optional)' → 'Direct connection on this network' - Better explain direct connection vs Relay roles and when each is used - Fix Relay unavailability to be a build property, not dependent on current selection * refactor(mobile): reframe local network address as optional in relay pai Demote the address picker from primary action styling to an optional disclosure with quieter visual treatment. Update messaging from "Direct connection on this network" to "Also use a faster local path" to clarify Relay is the default path and local addressing only applies when nearby. Add explanatory hint text to set expectations that Relay remains available when away.
… session (stablyai#12803) * fix(ai-vault): group OMP task subagent transcripts under their parent session OMP persists task-child transcripts inside the parent session's same-named artifact directory (<stamp>_<uuid>/), and discovery scanned them as ordinary top-level sessions - a coordinator's history drowned under its own workers. Extend the existing Claude subagent model to OMP, classifying purely by the artifact-dir layout (never by a transcript's parentSession field, which also describes non-task lineage): - prune artifact dirs from the top-level scan (name-pattern predicate) - count direct-child transcripts onto the parent row (local readdir; remote walks partition their listing instead, mirroring Claude's SSH posture) - list children on demand via the existing listSubagentSessions IPC, titled by their coordinator-given task label and linked to the layout-derived parent id - refresh the count on zero-turn cache reuse, matching Claude - extract session-scanner-roots.ts so the renderer-supplied-path allowlist for both agents lives in one module Fixes stablyai#9330 * review: harden OMP subagent classification and cover its uncovered branches Prune predicate now skips depth 0 (the workspace dir), so a workspace whose name happens to look like a session stem keeps its sessions. Drop degenerate OMP roots in ompSessionsRootDirs: OMP_CODING_AGENT_DIR='/' normalizes to '', which resolve()s to the process cwd and would have allowlisted it for the renderer-supplied subagent path. Rename session-scanner-omp-subagents.ts to -omp-subagent-transcripts.ts so it mirrors Claude's transcripts/lister split by role rather than inverting it. Correct two comments that asserted things the codebase contradicts: OMP task children do carry their own sessionId and would resume by path (OMP's own picker globs `*/*.jsonl`, so it never offers them either), and workspace dir names are not uniformly dash-prefixed. Cover branches the change added with no test: the remote/SSH partition wiring, the IPC `omp` gate and per-agent allowlist, the parse-cache zero-turn recount, and the executionHostId disk-ownership guard. Extract the remote scanner's in-memory provider into a fixtures module to stay under the max-lines cap. * review: note why child rows carry an unrendered grandchild count * review: describe the real OMP grandchild layout in the pattern comment --------- Co-authored-by: Dan Cieslak <dcieslak19973@users.noreply.github.com> Co-authored-by: Jinwoo-H <Jinwoo-H@users.noreply.github.com>
…o load (stablyai#12867) * fix(repo-icon): fall back to a lucide icon when an image icon fails to load Private-mode GitHub Enterprise avatars need a logged-in web session, so the stored avatar URL fails to load and the image branch rendered blank space. The lucide and missing-icon paths already fall back to Folder; the image branch had no equivalent. Track the failed src in state so a repo switched to a different icon still renders that icon instead of staying on the fallback. Fixes stablyai#11211 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test(repo-icon): assert the specific fallback icon instead of any svg The fallback and unchanged-icon tests only checked that an svg rendered, so they passed even if the wrong icon came back. Assert the lucide class name, and cover an unknown lucide name falling back to Folder. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: prioritize filenames in new-tab file results * fix: preserve root separator in filename-first paths * refactor: use native file path tooltips * fix: position file path tooltips * fix: use the native OS tooltip for new-tab file paths Co-authored-by: Orca <help@stably.ai> * fix: show new-tab file paths in a system-style tooltip Co-authored-by: Orca <help@stably.ai> * fix: anchor new-tab path tooltip to the cursor Co-authored-by: Orca <help@stably.ai> * fix: tighten cursor tooltip to file rows and design tokens Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>
* fix: show full paths in quick open results * refactor: use native file path tooltips * fix: position file path tooltips * refactor: share the cursor path tooltip with quick open Co-authored-by: Orca <help@stably.ai> * fix: let path tooltips run wider before wrapping Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>
…blyai#12828) * perf: bound repeated watcher, vault, and terminal work * fix(terminal): preserve redraw recovery while bounding fit retries * fix(watcher): retain structural fallback after crash fuse * fix(ai-vault): preserve forced scan budget
* fix(mobile): choose host for new workspace * fix(mobile): close stale workspace host picker * fix(mobile): disambiguate workspace host choices * fix(mobile): keep host endpoint paths private * fix(mobile): redact invalid host endpoints * fix(mobile): handle opaque host endpoints * fix(mobile): announce host picker options * fix(mobile): harden workspace host picker * fix(mobile): preserve host through workspace creation
…tablyai#12816) Reverts the classification change and keeps behavior at base. cursor-agent's native OSC title is the bare literal "Cursor Agent" and never carries a status word, so it names the agent without proving one is present. The title tracker drops it live, so main records it only when the stale-working timer strips the spinner off the synthesized "⠋ Cursor Agent" — and that fires both when Cursor parks idle and when cursor-agent exited and the shell reclaimed the pane. The two states are observationally identical: same title, same null foreground read. Classifying it as an agent therefore removes a refusal rather than adding evidence. Guarded sends auto-submit Enter, so the false positive types into the user's shell. A null foreground is also not "unreadable" on the default local provider, which returns null when the pty is gone. hasPty, probePtyLiveness, hasChildProcesses and inspectProcess were each checked as corroborating signals; none separates alive-with-agent from alive-with-shell when the foreground read is unavailable. Tests pin every no-evidence branch fail-closed and document the mechanism, so both attempted fixes fail loudly if reintroduced. Real gap tracked in stablyai#12946.
* fix(terminal): use provider-native session titles * refactor(terminal): source session names from AI Vault * fix(tabs): harden AI Vault title sync
…evel Git base for on-prem Server (STA-3494) (stablyai#12832) * fix(azure-devops): retry with -preview api-version and keep project-level Git base for on-prem Server (STA-3494) Azure DevOps Server rejects api-version=7.1 with 400 VssInvalidPreviewVersionException unless the -preview suffix is supplied, so auth and every Git endpoint failed. Retry once with -preview on that rejection and remember the requirement per origin. Also stop letting a same-origin ORCA_AZURE_DEVOPS_API_BASE_URL (collection-level, needed only for the connectionData auth probe) override the project-level base derived from the remote for Git endpoints; cross-origin (proxy) overrides keep working. * fix(azure-devops): constrain preview retry and base override
…3505) (stablyai#12833) * fix(permissions): surface macOS silent Local Network denial with diagnostic and workaround (STA-3505) On macOS 27 beta, NECP silently denies Orca's whole process tree Local Network access: no prompt fires, the app never appears in System Settings, and terminal child processes fail with EHOSTUNREACH. The Settings trigger swallowed the probe's socket error and reported 'unknown' + a 'Permission request sent' toast, indistinguishable from success. Classify the mDNS probe outcome (EHOSTUNREACH/EHOSTDOWN -> denied, clean send -> granted, else unknown), remember the verdict for the status chip, and render an inline diagnostic with the documented NECP re-evaluation workaround when denial is detected. * fix(permissions): avoid false Local Network grants * fix(permissions): use standard Local Network request flow * feat(permissions): add local network connection test * fix(permissions): nest local network connection test * fix(permissions): collapse connection test by default * fix(permissions): emphasize connection test action * fix(permissions): restore outlined connection action
…ever lands (stablyai#12950) * fix(renderer): contain corrupt lazy chunks when the recovery reload never lands 9 react-error-boundary crash reports across v1.4.171-1.4.175 (macOS, Linux, Windows) all end the same way: a corrupt lazy chunk fails to import, recovery requests a reload, the reload never lands, and loadLazyWithRetry re-throws the raw SyntaxError/TypeError. RecoverableRenderErrorBoundary only suppresses LazyChunkLoadError, so the raw error files a user-facing crash report. LazyChunkLoadError was unreachable in production. Its precondition is a guard written by a *different* document ('reload-landed'), but the finally block clears that guard before the throw, so the only path that could construct it never ran. Confirmed by the shipped bundles: 16/16 lazy_chunk_reload_vetoed breadcrumbs carry outcome=never-landed, zero carry any other outcome, and no bundle contains a boundary-degraded breadcrumb. Route every exhausted-recovery path through exhaustedRecoveryFailure() so an attempted-and-failed recovery yields a LazyChunkLoadError the boundary can contain, and record a lazy_chunk_recovery_exhausted breadcrumb carrying the call site, the real chunk error, and the outcome. Deliberately unchanged: when recovery is never *attempted* (no window/SSR, blocked sessionStorage, guard write failure) the raw error is still thrown so normal crash reporting is unaffected. Only isKnownDynamicImportFailure matches are contained, so module logic bugs keep reporting. * perf(renderer): trim redundant work on the lazy-chunk failure path Hoist the dynamic-import message patterns to module scope so classification stops allocating seven RegExp objects per call, thread the already-computed classification into exhaustedRecoveryFailure so the guard-not-landed path does not re-run it, and bound recordedExhaustionKeys the way the breadcrumb and renderer-error key stores are bounded, since error.name is library-controlled. Failure path only; the success path is unchanged. * refactor(renderer): remove a transposition trap on the lazy-chunk failure path exhaustedRecoveryFailure ended in two adjacent booleans with opposite consequences: transposing them would have returned the raw SyntaxError and silently restored the crash this branch fixes, with no test able to catch it (the only call site passed true for both). The isChunkFailure parameter saved one regex scan on a path that only runs after a 10s reload wait, so drop it. Also evict recordedExhaustionKeys oldest-first instead of clearing wholesale, matching the breadcrumb and renderer-error key stores the comment cites, so an overflow cannot re-open the entire set to a repeat burst. * test(renderer): cover the exhaustion dedupe bound The bound had no coverage, unlike the crash-breadcrumb store it mirrors, so a refactor could drop it or invert the comparison with every test still green. Drive 200 distinct error names through the contained path and assert the set stays capped. Also move MAX_RECORDED_EXHAUSTION_KEYS above the comment that describes the set, not between them. * test(renderer): pin the exhaustion eviction policy, not just the cap The bound test asserted only the size cap, so it stayed green under the old wholesale clear(): after 200 distinct keys a clear-on-overflow leaves 72, which still satisfies the cap. Replay a key that oldest-first eviction retains and assert it emits no second breadcrumb — that fails under clear(), which would otherwise silently re-open the whole set to a repeat burst and flush the 30-entry ring the dedupe exists to protect. * refactor(renderer): cut the breadcrumb machinery down to the actual fix The lazy_chunk_recovery_exhausted breadcrumb was an optional addition that paid for itself in complexity and nothing else: it needed a dedupe set to avoid flushing the 30-entry ring, the set needed a bound because error.name is library-controlled, the bound needed an oldest-first eviction policy, and that needed two more tests plus a boolean parameter that review flagged as a transposition trap. On the dominant never-landed path it did not even fire, because lazy_chunk_reload_vetoed already records the same reloadKey, message and outcome. Drop it. Observability on every path returns to the main baseline, and the fix is what it always was: name an exhausted recovery so the boundary can contain it. Also revert the unrelated regex hoist -- its only caller is the failure path, so the saved allocations are noise. * Verify ordinary errors bypass lazy chunk containment Add test ensuring module evaluation bugs still surface despite never-landed reload attempts. Clarify containment scope: recovery only applies to known dynamic-import failures, not ordinary errors.
…tablyai#12945) * fix(terminal): per-pane WebGL attach latch and fit-anchored reattach The attach-failure latch was module-global: one pane's failed WebGL context creation stranded every other pane on the DOM renderer — whose cell metrics and rasterization differ visibly (bolder, ~5% wider text) — until the next recovery boundary. The latch is now per-pane. A successful fit additionally offers an event-anchored reattach: a pane that is WebGL-eligible but addon-less (late mount that missed the coalesced reveal repaint, stale fallback) regains WebGL the moment it proves measurable, so a user resize now heals a DOM-stuck pane instead of leaving it. Failed attaches still retry only at recovery boundaries. A webgl-fit-attach diagnostic records each late attach so the stuck state is finally visible in telemetry. Client-size fit helpers move to pane-fit-client-size.ts to stay under the pane-fit.ts line cap. * fix(terminal): refit onto WebGL cell metrics after a fit-anchored attach The fit that triggers the reattach measures DOM cell metrics; WebGL floors the device cell width, so healing a DOM-stuck pane left it on the DOM-derived column count — an unpainted right gutter and a PTY narrower than the pane. Refit on the next frame, mirroring the dispose-side refreshDimensions. Also cover the real wiring: the existing fit-anchored tests drive the signal module directly, so they stay green even if safeFit stops calling it. The new suite goes through safeFit, which is also what proves the import-time hook registration works. * test(terminal): gate the fit-anchored refit frame on a deferred rAF The existing suites stub requestAnimationFrame synchronously, so the window in which the refit handle is live never exists there — nothing covered the two properties that window has to hold. With a deferred stub: - disposing the pane cancels the refit, so it cannot fit (and forward a PTY resize for) an already-disposed terminal; - the deferred fit re-enters the hook exactly once and settles, so there is no fit -> attach -> fit cycle. Both fail against mutated production code (handle kept out of the cancellable slot; addon-less guard dropped).
stablyai#12955) This reverts commit ae1ed5e.
…lyai#12584) Co-authored-by: Jinwoo-H <Jinwoo-H@users.noreply.github.com>
stablyai#12954) * Fix cmd+j search ranking to require coverage of meaningful query words Extract tokenization logic into a shared module to ensure consistent ranking across settings and project search bands. Enhance ranking with: - Coverage requirement: candidates must match most meaningful words, not just one (fixes "linear triage" matching all projects on "linear" alone) - Filler words: ignore navigation words like "open", "go", "the" when measuring coverage - Unicode support: split on Unicode word boundaries, not ASCII only * Fix cmd+j search to require query coverage and handle Unicode The search ranking now requires all query words to match candidate values before applying shortcut rules, preventing false positives where middle words could be ignored. Query normalization now iterates over Unicode characters instead of code units to properly lowercase supplementary-plane characters.
…ng (stablyai#12822) * fix(github-project): index fork upstream slugs for project row matching Project cards often reference the public upstream repo while the open clone's origin is a personal fork. Map the parent slug to the same Repo so selected-repo filters no longer hide every board row. Preserves origin-based getRepoSlug identity for non-project callers. Fixes stablyai#12647 * fix(github-project): match project rows against fork upstream slugs Resolve the referenced call to a nonexistent `resolveRepoUpstreamSlug` and match the persisted `repo.upstream` parent instead of issuing an extra `github.repoUpstream` RPC per repo on every index build — that lookup shells out to `gh repo view` for non-forks, so it would have gated the Projects tab on N network calls. `repo.upstream` is already resolved at repo-add time and backfilled at startup, so the fix costs no IPC. Origin matches take precedence over upstream ones so an open clone of the upstream repo itself is never made ambiguous by someone's fork of it. Also covers the two surfaces the origin-only match broke alongside the desktop table: mobile's project row matcher and the store-slice row-mutation routing. * fix(github-project): scope fork upstream matching by host and selection Round-1 review fixes on top of the upstream-slug index: - Apply origin-over-upstream precedence among *selected* repos instead of globally. An open-but-unselected clone of the upstream repo was shadowing the selected fork, so stablyai#12647 still reproduced for anyone holding both — and repo selection collapses to one repo per project key, which is exactly that case. - Scope a fork's upstream identity key to the fork's own origin host. Persistence strips upstream.host, so GHES forks never matched their own rows and a GHES fork's parent could bind a same-named github.com row. * fix(github-project): skip the fork alias when its own origin is unresolved Round-2 review fix. `githubHostFromIdentityKey` cannot tell "origin resolved to github.com" from "origin did not resolve" — both yield no host. A GHES fork whose slug resolution had failed (auth lapse, unreachable runtime) therefore landed in the github.com namespace, so an unrelated public Project row matched it and Start work opened the wrong clone on the wrong server. Require a resolved origin before indexing the upstream alias: it is the only host evidence there is, and a repo with an unresolved origin was already absent from the origin index, so nothing is lost that origin matching had. * fix(repos): persist the fork upstream host instead of dropping it `sanitizeRepoUpstream` kept only `{owner, repo}`, so a fork's parent lost the server it lives on every time the record round-tripped through disk. That forced the Project row matcher to re-infer the host from `origin`. The inference is right for an API-resolved fork parent — `getRepoUpstream` stamps `origin.host` there precisely because "a fork parent lives on the same server as the fork". It is wrong for the other branch: a local `upstream` remote carries its own host, so a github.com clone with a GHES `upstream` remote was indexed into the github.com namespace, where an unrelated same-owner/name public repo could claim it and Start work would open the wrong clone. Keeping the host removes the guess. Absent stays absent, so records written before this hydrate unchanged and the origin-derived fallback still covers them. Also fixes the avatar for rehydrated GHES forks, which resolved against github.com for the same reason. * docs(github-project): correct upstream host fallback comment Persistence now keeps non-empty upstream.host; originIdentityKey remains the host fallback for older records without one (CodeRabbit nit). * fix(github-project): own slug-index retry timer cleanup Move the failure-retry setTimeout into its own effect so cleanup always clears it. Scheduling from the async buildIndex then-handler failed the react-doctor effect-needs-cleanup gate in static analysis. * test(github-project): guard the slug-index retry timer, fix the mobile twin comment Two follow-ups on 52298d8 and 2f89c20: - Cover the retry timer both ways: a failed resolution still re-resolves after the TTL and recovers the match, and the pending timer is gone after unmount. The second fails if the timer moves back into the async then-handler, so the property is guarded by more than the lint rule. - The mobile matcher's comment made the same stale "persistence strips upstream.host" claim that 2f89c20 fixed on the renderer side. * test(github-project): unmount slug-index hooks so React cannot flush after teardown CI shard `tests node 24 6/16` failed with 10 unhandled `ReferenceError: window is not defined` traced to this file. The tests mounted hooks without unmounting, so React scheduler work flushed after the DOM environment was disposed. All assertions passed; the shard failed on the unhandled errors alone. `cleanup()` after each test unmounts the trees. Does not reproduce locally in isolation — it needs CI's worker pooling and file ordering. --------- Co-authored-by: Jinwoo-H <Jinwoo-H@users.noreply.github.com>
…#12965) * feat(diff): HTML preview + always-visible open actions in View all Expose Open Preview to the Side for HTML sections in combined diffs when the working-tree file still exists, and keep the open-file external-link icon visible without hover. Split DiffSectionItem props/lifecycle helpers to stay under the max-lines limit. * Fix HTML preview: always-visible buttons and multi-pane group selection - Make preview buttons always visible (not hover-reveal) for touch support - Fix event propagation so clicking preview doesn't toggle sections - Use combined-diff tab's group for sourceGroupId in multi-pane layouts - Add accessibility label to open-section button - Support untracked, renamed, and uppercase HTML file extensions * fix(diff): avoid render-time ref mutation in section model lifecycle React Doctor fails static analysis when refs are written during render. Move the disposer ref sync into an effect so the stable callback-ref still disposes with the latest model paths.
…e-host count (stablyai#12478) * fix(i18n): localize the status bar Resource Manager tooltip and remote-host count The Resource Manager tooltip/aria label and the SSH segment's host count were assembled from bare English literals inside helper functions, so they stayed English under every non-English UI language while the labels around them translated. Route them through the catalog with _one/_other plural keys and whole-line messages (locales reorder and repunctuate the summary), and add en/es/ja/ko/zh entries. Root cause of the miss: audit-localization-coverage bailed on any ancestor binary expression whose operator was not `+`, which hid every string under a `cond && <JSX/>` guard or a `?? 'fallback'` — including this segment's 'Connecting…'. Only comparison operands are code, so keep `??`, `||` and `&&` walking, and localize the four real strings that surfaced. Co-authored-by: Orca <help@stably.ai> * fix(status-bar): flag the space-scan tooltip row instead of matching its English text The tooltip tinted a row with `line === 'Space scan ready'`, so routing that copy through the catalog silently dropped the tint in every translated build. Return `{ text, emphasized }` and let the segment read the flag. Adopted from stablyai#12439 by @smwbev. Co-authored-by: Evgenii <smwbev@users.noreply.github.com> Co-authored-by: Orca <help@stably.ai> * fix(status-bar): key Resource Manager tooltip rows by role instead of array index Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>
stablyai#12962) * fix(mobile): never auto-advertise virtual bridge addresses for pairing Container/VM bridges stay manually pickable, but automatic defaults skip them so QR codes do not race an unreachable direct path. Relay pairs without a local address; LAN-only and runtime pairing fail closed on bridge-only hosts. * fix(mobile): never auto-advertise virtual bridge addresses for pairing - Set endpoint to null when no direct address is advertised, so the QR doesn't show an unreachable address to the scanning phone - Distinguish "No address selected" (bridge exists but not advertised) from "No interfaces found" (genuinely nothing to pick) - Add tests for NetworkInterfacePicker placeholder behavior
…i#13646) * perf(browser): avoid synchronous URL IPC during render * fix(browser): sync live URL after CDP navigation
…blyai#11585) * fix(settings): widen font size input so values are fully visible The number input for terminal font size was too narrow (w-14) to display two-digit values cleanly. Changed to w-24 to ensure 10-24px values fit. * fix(settings): hide the native spin buttons clipping the font size value The overlapping webkit spinner was what cut off the second digit, not the box width. Adopt the number-input-clean idiom every other numeric settings input already uses; the spinner also duplicated the -/+ steppers. * fix(settings): keep font size stepper compact --------- Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
…ized in ko/zh/es (stablyai#13124) * fix(i18n): restore identifiers and commands machine translation localized 39 values in ko, zh and es are code rather than copy — shell commands, CSS class strings, git-style identifiers, sample filenames and hostnames — and had been machine-translated. pnpm install read pnpm 설치, text-foreground read 文本前景, pr-view read PR视图, and localhost:3000 read 本地主机:3000. pnpm install is the font-mono placeholder of the setup-script input, and gh auth login / glab auth login are the commands the integration panes tell the user to run, so the translated forms are shown to users as text to type. Catalog-only. Running repair-locale-catalog.mjs over these locales fixes the same values but rewrites several hundred unrelated ones, because the catalogs are stale against the current policy. * fix(i18n): restore the zh code strings found by call-site context @smwbev scanned by where a translate() renders — inside <code> or a font-mono element — rather than by value shape, and found nine more in zh: upstream read 上游 in the base-ref picker, nbformat read nb格式, orca.yaml read Orca.yaml, LIN-329 read 林-329, GH stablyai#1799 lost its space, and orca · zsh read Orca·zsh. The matching NEVER_TRANSLATE_VALUES entries landed with stablyai#12934. * test(i18n): guard restored technical literals --------- Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
* fix: stop unchanged worktree refresh churn * fix: preserve smart sort telemetry recomputations * fix: preserve duplicate worktree host identities * perf: skip reconciled catalog traversal * test: strengthen worktree refresh regressions
* fix(terminal): forward copy to TUI selections * fix(terminal): narrow recovery selection cleanup
) * feat(ai-vault): isolate scanning in service processes * fix(ai-vault): retire idle service processes * fix(ai-vault): discard unverified cache processes * fix(ai-vault): clear relay sidecar cancel watchdog on acknowledgement A cancelled relay call is settled before its 2s cancel watchdog is armed, so the acknowledgement path bailed out of settle() before clearing the timer. The watchdog then faulted a healthy sidecar two seconds after every aborted scan, killing whatever request had since become active. * fix(ai-vault): clear the pending restart before scheduling another recordFault overwrote this.timer, stranding a restart that dispose() could no longer cancel. * refactor(ai-vault): drop the orphaned first-prompt IPC wrapper session-first-user-prompt-handler.ts now owns this entry point and routes through the service; the copy left in the read module had no callers. * fix(ai-vault): retry a faulted cold start before surfacing it A slow first start surfaced a raw 'did not become ready' error to the caller even though the supervisor was already respawning. Requeue an unsent call once onto the scheduled respawn instead. Also stop arming the cancellation watchdog for a call the child never received: no acknowledgement is coming, so it killed a healthy service and stalled the lane. Invalidation bookkeeping and ready-waiter construction move to the state module to stay under the max-lines cap. * fix(ai-vault): give relay title reads their own lane Before this branch the relay read title files directly, concurrently with scans. Routing both through one sidecar lane put title resolution behind a list scan that may run up to 130s, so SSH tab titles could lag minutes behind. Split cache and interactive lanes in both the relay client and the sidecar entry, mirroring the desktop service. Also: clear the ready deadline on fault, so a sidecar that dies before ready cannot fault its healthy replacement five seconds later; retry an unsent call once across a respawn; and skip the cancellation watchdog for a call the sidecar never received. Restart/circuit bookkeeping moves to its own module, mirroring the desktop policy, to stay under the max-lines cap. * fix(ai-vault): degrade relay title resolution on sidecar failure listSessions already returns a host issue when the sidecar is unavailable; titles propagated the raw RPC error instead. Return no titles so callers fall back to preview text, and keep cancellation propagating. * fix(ai-vault): scrub the service child environment The children are forked with a 384 MiB heap cap and no loader, but both spawn sites handed them the full parent environment, so an exported NODE_OPTIONS silently raised the cap or --require'd code into them. Allowlist both, following the plugin worker. The desktop child keeps the eleven agent-root overrides it resolves its own roots from; the relay sidecar takes remoteHome and hostPlatform from its init message and so needs none of them. Both children share one priority module while they share this one. * fix(ai-vault): soft-disable relay vault when the service is missing A missing service threw out of the constructor, so a Vault wiring bug would abort relay startup and take every PTY on the host with it. The unsupported-platform branch three lines above already treats a Vault failure as a soft disable; do the same here. Threading the service through the two handlers instead of a field also retires the definite-assignment assertion the throw was propping up. * fix(ai-vault): drain consumed cache invalidations invalidatedPaths was re-applied in every request's finally and never drained, so once N paths had been invalidated every later request paid N evictions for the life of the process; the 4096 cap only bounded how bad that got. The re-apply exists to cover a read that overlapped the invalidation, so drain once nothing is executing. Clearing unconditionally would drop the re-apply for a request still running on the other lane. * fix(ai-vault): keep a busy child through slow invalidation acks invalidate() reused the 5s ready budget as its acknowledgement deadline and killed the child on expiry, so a delete issued during a large scan could kill a healthy process mid-scan and burn a slot toward the restart circuit. Fault only when nothing is executing. Fork IPC ordering already puts the invalidation ahead of any later request, so a busy child owes no ack here, and the 130s/15s request deadlines still catch a wedged one. The start-retry predicate moves to the state module to stay under the line cap, matching the shape the relay client already uses. * fix(ai-vault): report a failed local scan as a host issue A local-scope scan let its error escape to the renderer, which paints it over the session list. Service supervision now produces those errors, so "AI Vault service restart circuit is open." replaced the list. Route local scope through the degradation the all-hosts leg and every SSH leg already use, so it lands as a retryable host issue row instead. Same result shape either way, so no IPC or wire contract changes. * test(ai-vault): cover the relay restart circuit transitions The relay policy shipped without tests. Pin both circuit edges, the aging-out case, the forced-refresh reopen the relay has and the desktop does not, and the backoff schedule. * fix(ai-vault): keep the OpenCode roots in the service child env The scrubbed allowlist dropped XDG_DATA_HOME and OPENCODE_DB, which the child reads to locate the OpenCode store and database. The pre-PR worker thread inherited them, so a user who sets either lost every OpenCode session. * test(ai-vault): anchor the service spawn env assertion
* perf(runtime): batch legacy recovery persistence * fix(runtime): preserve concurrent recovery state * fix(runtime): require durable recovery retry
* fix(notifications): route clicks to main window * fix(notifications): reveal hidden main window on click
* perf(terminal): stop clearing glyph atlas on output * test(terminal): gate output atlas reset removal * test(terminal): harden atlas recovery gates
* fix(tabs): keep widths stable during title updates * review(tabs): reduce the width rule to the definite width and harden its tests Why: once the tab container has a definite width the shrink-wrapped strip never has free space, so flex-grow and max-w-[280px] were unreachable and only duplicated the 180/220 numbers across two properties. Measured widths, strip scrollWidth and clientWidth are identical to the flex-based version across four window widths, five tab counts and short/long titles. Tests: pin the width classes literally so the guarantee cannot be edited away via the constant, and guard the e2e check against passing vacuously on a saturated strip. --------- Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
… unavailable (stablyai#13378) * fix(agent-hooks): refresh existing shared hook scripts when the CLI is no longer detected A CLI that falls off PATH (moved npm prefix, relocated shim) keeps its user-wide config invoking Orca's launcher script under ~/.orca/agent-hooks, but the presence gate skips install() with no removal — freezing the script at whatever Orca generated last. Anyone in that state kept the pre-stablyai#11568 more.com-leaking .cmd forever, because no launcher script is ever deleted and Windows startup deliberately skips shell PATH hydration. Reconcile before gating: every existing shared launcher/statusline script is rewritten to the current template on each install pass. Creating scripts stays behind the presence gate — an existing file is proof of a prior install; a missing one means the gate did its job. Amp and Hermes are deliberately absent: they write provider-native plugin code with its own install lifecycle, not shared launchers. - refreshManagedScriptIfPresent() in installer-utils (no-op unless the file exists) - refreshManagedScripts() on the 11 launcher-writing services (openclaude via the shared Claude class) - reconcile pass in installManagedAgentHooks before presence detection, filtered by the agents option, best-effort per agent - coverage gate: a launcher written to ~/.orca/agent-hooks without a matching refresher entry fails the suite, in both directions * perf(agent-hooks): refresh launchers off the main thread * test(agent-hooks): keep refresh mode assertion POSIX-only
* fix(release): quarantine unauthorized publications * fix(release): remove unauthorized publication tags * fix(release): require canonical version tags * refactor(release): narrow policy to one workflow * fix(release): reassert latest stable release
…blyai#13292) * improve automations page ui * Improve automations page UI: fix menu interactions, extract components, - Extract status cell to reusable component - Fix portaled context menu clicks re-selecting rows - Use explicit selection IDs instead of resolved objects for reliable detail state - Close detail when selection is lost during refresh or deletion - Improve escape key navigation through nested detail views - Use native input for search field to avoid unwanted shadow elevation - Add i18n keys for table and button labels * fix: merge duplicate type imports in AutomationListLocalRows test Static analysis fails under --deny-warnings when the same module is imported twice; combine the Automation and external types into one import. * Fix row keyboard activation to not intercept nested controls Row handlers for Enter/Space were preventing the actions menu button from opening when activated via keyboard. Extract a reusable check that only treats these keys as row activation when they originate on the row itself, not on child controls. Also consolidate the search input to use the shared Input component for consistency. * fix: use stable keys for automations page skeleton rows React Doctor no-array-index-as-key failed static analysis on the loading skeleton map. Give each static row an id for the React key. * Reorganize i18n keys for automation components Move translation keys to their proper component namespaces (rowActions to AutomationListLocalRows, normalize loading key), update all locale files. * fix: move automations detail selection refs out of render React Doctor fails CI when refs are mutated during render. Sync selectedExternalKey and isDetailOpen into refs in effects instead. * style: soften automation search field focus state - Reduce focus ring opacity to 70% for a subtler focus indicator - Set focus-visible:ring-0 to eliminate elevation effect - Add dark:bg-background for consistent dark mode appearance
innocarpe
force-pushed
the
fix/windows-git-bash-ctrl-w
branch
from
August 11, 2026 01:02
7a50a60 to
bbcce40
Compare
Owner
Author
Sync update (
|
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
Summary
Description Windows Git Bash now receives Ctrl-W when the terminal-first shortcut policy is enabled instead of Orca closing the active tab. The shortcut policy recognizes the Git Bash terminal family and keeps shell-native word deletion ahead of the global close-tab binding.
Note
innocarpe/orcamainuntil the upstream PR is merged.