Commit Graph
177 Commits
Author SHA1 Message Date
KyuJoo HanandOrcaWin 6f3845baa4 fix(checks): rank successful checks above skipped and neutral (#11337)
* fix(checks): rank successful checks above skipped and neutral

Checks were ordered with `skipped` (4) and `neutral` (3) ahead of
`success` (5), so a PR with a long tail of skipped jobs pushed every
passing check below the fold — you scroll past a wall of "Skipped" to
find out whether anything actually ran.

Rank the no-signal conclusions last (`success` 3, `neutral` 4, `skipped`
5) and pull the order out of its three duplicated copies
(checks-panel-content, PullRequestPage, GitHubItemDialog) into
`src/shared/pr-check-severity-order.ts`. Unknown conclusions now sink to
the bottom instead of silently ranking as `neutral`.

* fix(checks): look up check ranks through a Map, not an object literal

An object-literal rank table resolves `constructor`, `toString`, and
`__proto__` off Object.prototype, so those keys returned a function
instead of falling through to UNKNOWN_CHECK_RANK — the comparator then
subtracted functions, went NaN, and left the list in arbitrary order.
Conclusions come from provider payloads, so keep the lookup on a Map and
cover prototype property names in the test.

* test(checks): cover provider-neutral ordering states

* fix(checks): preserve actionable provider states

* fix(checks): preserve unresolved provider rollups

* fix(checks): keep unknown GitLab rollups neutral

* fix: preserve neutral review check summaries

* fix: complete provider-neutral check ordering remediation

* fix: use provider-neutral mobile review status input

* fix: hydrate GitLab mobile review status

* fix: type mobile GitLab review hydration

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-07-30 13:29:41 -07:00
Neil badf91101b fix(quality): enforce performance-safe lint baseline (#11074)
* fix(quality): clear safe existing lint findings

* fix(quality): keep lint cleanup allocation-free

* fix(quality): enforce performance-safe baseline

* test(terminal): drain deferred confirmation cleanup
2026-07-27 20:54:02 -07:00
Neil 19d082a164 fix(github): resolve owner/repo through SSH Host aliases (#10284) (#10361)
* fix(github): resolve owner/repo through SSH Host aliases (#10284)

Expand OpenSSH Host → HostName via ssh -G before classifying github.com
identity so PR merge works when origin is git@alias:owner/repo.git.
Transport URLs stay unchanged so IdentityFile selection is preserved.
Do not long-negative-cache indeterminate ssh -G failures.

* fix(github): harden SSH alias resolution
2026-07-25 23:34:17 -07:00
JinjingandOrca 33bd676644 fix(github): align PR source and review head origin (#10677)
* fix(github): align PR source and review head origin

* fix(github): pin number-based work item open to the repo source preference

Open-by-number and details still ran the upstream-first multi-candidate PR
probe, so a fork and its upstream sharing a PR number opened different PRs
than the list and start-point paths did once #10677 pinned those to origin.

Thread repo.issueSourcePreference through dispatchWorkItem, getWorkItemDetails,
getRepoWorkItem, and getRepoWorkItemDetails. getWorkItemByOwnerRepo is left
alone: explicit owner/repo already pins identity. auto/upstream/undefined keep
the multi-candidate probe.

Co-authored-by: Orca <help@stably.ai>

* test(github): enforce origin preference in review head origin resolution

The explicit origin preference must short-circuit before any identity probe, so no remote queries should occur. Add validation to reject unexpected remotes and tighten the test assertion to verify no remote get-url calls happen at all.

* fix(github): enforce origin preference in issue open-by-number lookup

listWorkItems and getWorkItem must share preference so origin/upstream
toggles cannot disagree. Explicit origin preference now fail-closes when
origin identity is unresolved (no bare-lookup fallback), matching the
PR candidate resolution rule.

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-25 22:48:53 -07:00
JinjingandOrca 772081577e Fix fork PR/MR worktree creation race via durable review-head refs (#10429)
* Fix fork PR/MR worktree creation race via durable review-head refs

When creating a fork PR/MR worktree, concurrent `git fetch origin` operations
clobber the shared FETCH_HEAD, causing the wrong commit to be checked out.
Fetch PR/MR heads into dedicated per-review refs (`refs/orca/pull/<N>`,
`refs/orca/merge-requests/<N>`) that persist and isolate each head from other
fetches. Gracefully keep the compare-base when the fetch fails but the local
ref already exists, avoiding silent fallback to the wrong branch on transient
network errors.

* Bound PR/MR head fetches with 60s timeout

Prevent PR/MR creation from hanging when a remote is stalled or
unreachable. Both GitHub and GitLab head fetches now enforce a
60-second timeout, matching the bound used in the create-path
fetch. Durable refs (refs/orca/pull/*, refs/orca/merge-requests/*)
decouple the ref from FETCH_HEAD, preserving legacy client semantics.

* test: align CI expectations with main PowerShell/sparse regressions

PR checks merge into main, which recently changed PowerShell launch args
(cwd restore after profiles) and sparse-checkout detection (require
core.sparseCheckout). Derive PowerShell spawn args from the production
resolver, mock the sparse config flag, reset shared worktree list scan
cache between tests, and stop requiring floating polls to avoid getRepos
hydration.

* Address review follow-ups on durable review-head refs

- Unify PR review-head remote selection: local and SSH GitHub paths share
  resolveGitHubReviewHeadRemote, which prefers the remote mapping to the
  hosting GitHub project (upstream before origin, matching work-item/API
  candidate order) so contributor clones fetch refs/pull from the repo
  that actually hosts the PR.
- Soft-keep durable review heads: when the PR/MR head fetch fails but
  refs/orca/pull/<N> / refs/orca/merge-requests/<iid> still resolves,
  keep the pinned SHA (warn) instead of failing resolve, mirroring the
  compare-base fallback. Extracted shared compare-base soft-keep into
  compare-base-ref-fetch.ts.
- Extract fetchGitLabMergeRequestHeadRef (local + SSH) parallel to the
  GitHub helper; bound its local fetch with the shared 60s timeout.
- Share relay-style fetch validation (positive safe-integer id, remote
  not starting with "-") between relay and local helpers via
  review-head-tracking-ref.ts; move REVIEW_HEAD_FETCH_TIMEOUT_MS there.
- Drop the githubPullRequestHeadLocalRef re-export; resolve head SHAs via
  rev-parse --verify <ref>^{commit}.
- Add GitLab anti-FETCH_HEAD regression test plus durable-head soft-keep
  and remote-selection unit tests.

Co-authored-by: Orca <help@stably.ai>

* test: supply live getRepos for terminal-retirement hydrates

Main's headless tab hydrate (#9343) skips worktree keys whose repo is not
in getRepos. Retirement tests that rebuild mobile tabs from a persisted
session now advertise the fixture repo as live so PR Checks merge stays green.

* fix(editor): extract RichMarkdownEditor props to stay under max-lines

Main's SSH external-image wiring (#10323) pushed RichMarkdownEditor.tsx over
the 400-line tsx budget, failing PR Checks lint on every merge into main.
Move the props type into a sibling module so the component stays under the
limit without disabling max-lines.

* Make durable review-head refs remote-identity scoped

Embed remote name + URL hash into refs/orca/pull|merge-requests refs to prevent soft-keep from serving wrong project's PR/MR when FETCH_HEAD is clobbered by concurrent fetch. Fetch functions now return the written ref path (writer-authoritative) so callers rev-parse exactly what was fetched, not re-derive identity. Soft-keep only applies to transient errors (timeout, network); fails hard on missing refs, auth failures, and stale relay. Relay returns localRef so client avoids re-hashing (URL normalization can disagree).

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-24 12:53:18 -07:00
moseoh 832aa69ce8 fix(tasks): resolve PR work items upstream-first under 'auto' like issues (#8727) 2026-07-23 23:20:52 -07:00
NeilandOrca aab112933e Revert "fix(memory): bound OOM-prone accumulators (#10179)" (#10255)
Co-authored-by: Orca <help@stably.ai>
2026-07-23 18:35:31 -07:00
Neil 8f40ddf328 fix(memory): bound OOM-prone accumulators (#10179) 2026-07-23 06:22:56 -07:00
Brennan Benson e986a7ba1a feat(codex): surface nested subagents (#9637)
* feat(codex): surface nested subagents

* fix(codex): retire child rows on root stop

* fix(codex): preserve nested agent state on restart

* fix(codex): preserve nested agent identity

* fix(codex): preserve subagents across relay restarts

* chore(skills): refresh generated manifests

* fix(codex): keep inferred interrupts terminal

* chore(skills): record latest release snapshots
2026-07-21 15:12:14 -07:00
OrcaWin a97c160363 fix(github): preserve GHES non-default auth ports (#9680) 2026-07-21 11:39:01 -07:00
63da958813 fix(github): keep work-item searches repo-scoped (#9668)
* fix(github): prevent unscoped work item queries

* fix(review): translate non-English rationale comment to English (client.ts:1151)

Restores the English '// Why:' convention and re-states the allSettled partial-results rationale that was dropped when the comment was replaced. Flagged by Ce-code-review (maintainability/previous-comments) and a prior PR reviewer. No behavior change.

Co-authored-by: Orca <help@stably.ai>

* fix(tasks): surface repos with no resolvable GitHub source

Since #9660 an unresolvable GitHub source returns an empty null-source
envelope instead of an unscoped search. That empty was indistinguishable
from a genuine zero-result query — no log, no telemetry, no UI signal.

Surface it in the Tasks list: a per-repo info row with Retry for each
fetched repo that resolved neither an issue nor a PR source (told apart
from genuine-zero and not-yet-fetched purely via the cached `sources`).
Renderer-only — the signal was already threaded through the envelope.

- selectTaskPageUnresolvedSourceRepos selector (+ unit tests)
- per-repo row reusing the existing banner region + handleRetryIssuesFetch
- suppress the generic empty state while those rows show
- assert the null-source envelope contract in client-work-items test

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-20 23:19:35 -07:00
971b167548 fix(github): load PR diffs for Enterprise remotes (#8932)
* fix(github): load PR diffs for Enterprise remotes

* fix(github): encode PR content paths by segment

* Fix PR review actions failing on GitHub Enterprise remotes

- Threads GitHub host identity (not just owner/repo) through the client,
  work-item-details, issues, and RPC layers so gh commands target the
  correct Enterprise server instead of silently falling back to github.com
- Adds a shared github-api-repository helper to resolve/host-qualify repo
  identity consistently across REST, GraphQL, and CLI shorthand calls
- Scopes the gh rate-limit breaker and singleton rate-limit snapshot by
  host/runtime so a github.com block or probe can't affect GHES or WSL
- Coalesces concurrent host-auth probes and paginates PR file fetching
  beyond 100 results
- Propagates `host` through renderer PR caches, checks-panel keys, and
  preload IPC types so Enterprise and github.com data never collide

* Route gh host qualification through runner options instead of argv sniff

Move GHES/GH_HOST resolution from parsing --hostname/--repo out of gh argv to an explicit options.host passed through ghExecFileAsync, since SSH-backed repos spawn gh with no cwd and argv sniffing couldn't reliably detect the target host. The runner now injects --hostname and qualifies --repo/-R at spawn time from options.host, and rate-limit scoping/guards use the same explicit host instead of inferring it. Also adds a shared githubRepoIdentityKey helper to keep cache/store keys consistent with the new host-aware repository identity.

* Fix gh CLI GHES host pinning and rate-limit scope leaks

- Pin `--host` on every gh call site so a process-level GH_HOST can't
  silently redirect requests, and qualify `-R`/`-R=` repo shorthand
  alongside the existing `--repo=` handling.
- Check the target scope for an active rate-limit block before each
  WSL/native or host fallback retry, not just on the initial attempt,
  so a blocked scope can't be hit again through a fallback path.
- Compute idempotency once per call instead of re-deriving it after
  fallback reassigns args.

* Fix GitHub Enterprise host identity loss across PR/work-item paths

- Thread `host` through mobile PR RPC params, IPC work-item lookups, and
  RPC schemas so GHES identity survives the renderer/mobile/main boundary
  instead of silently falling back to a same-named github.com repo.
- Qualify `--repo`/`-R` args for github.com too (not just GHES), since
  gh resolves bare shorthand against a process-level GH_HOST that can
  redirect pinned github.com commands.
- Cache `getOriginGitHubApiRepository` to avoid a per-call uncached
  `git remote get-url` round trip on connection-backed repos.
- Add a local-fork fallback in `getWorkItemDetails` so PRs living on a
  base repo (not visible via the origin slug) still resolve via cwd.
- Centralize the github.com-vs-GHES host predicate in
  `isDefaultGitHubHost` so cache keys, quota scoping, and identity
  checks can't drift out of sync.

* Make repository identity host-aware across all GitHub surfaces

Generalize the auth-gated enterprise resolver to any remote and build a
cached hosted-identity family (origin/issue/candidates/source) on top of
it, then migrate every github.com-only consumer: Tasks listing/counting,
branch-to-PR discovery, push targets, fork upstream, issue operations,
Projects, web links, avatars, and PR-link facts. Scope the rate-limit
breaker probe per runtime:host and classify WSL UNC cwds correctly.

Co-authored-by: Orca <help@stably.ai>

* Fix expected slug to include host field in GitHub PR link test

Updates the smart-source paste-intent test fixture to match the
repository slug shape that now carries a `host` field, keeping GHES
host identity intact through the paste-intent parsing path.

* Surface per-host gh auth state for GitHub Enterprise

diagnoseGhAuth accepts the host a surface needs credentials for, scopes
the account/scope diagnosis to that host, and reports whether gh has any
login there; GhAuthErrorHelp renders host-qualified login/refresh
commands so an unauthenticated GHES host stops masquerading as a
github.com scope problem. Also fixes the mobile paste-intent expectation
for host-carrying parsed links.

Co-authored-by: Orca <help@stably.ai>

* Bound GHES identity caches and preserve non-default ports in host identity

Cap the origin-repo and host-auth caches like ownerRepoCache; keep ports
from remote/link URLs so GHES on a non-default port is a distinct
identity; make positional github.com slugs explicit against GH_HOST;
compare work-item sources by host-aware identity key; bail cwd-less
branch lookups when no repository candidate resolved; thread host
through the renderer work-item slug lookup.

Co-authored-by: Orca <help@stably.ai>

* Thread GitHub host through issue detail requests

Incorporates ghes-issue-host-support (ed6bb96ef): one hosted issue
repository identity is resolved before the details fan-out so comments,
timeline, participants, and mention lookups cannot drift across hosts,
with SSH guards so unresolved issue/PR repositories never fall through
to gh's default host.

Co-authored-by: Orca <help@stably.ai>

* Scope remaining GitHub rate-limit accounting

* Resolve typed PR lookups across hosted repository candidates

getWorkItem's PR path probes upstream-then-origin hosted candidates
instead of origin alone, so fork checkouts resolve the base repo's PR
with the right host; issue detail resolution reuses the up-front hosted
identity and keeps the SSH unresolved-host guards.

Co-authored-by: Orca <help@stably.ai>

* Refactor GitHub repository execution setup

* Carry host on smart-submit link intents

Co-authored-by: Orca <help@stably.ai>

* Carry the project host on GitHub item dialog origins

Co-authored-by: Orca <help@stably.ai>

* Keep GHES web ports but drop SSH transport ports in host identity

Supersedes PR #9118 on this branch: http(s) remote ports identify the
Enterprise web/API endpoint and are preserved, while ssh/git transport
ports (including ssh.github.com:443) never leak into gh's host identity.
Replaces the ssh.github.com:443 special case with the structural
protocol split and ports the PR's parsing test suite.

Co-authored-by: Orca <help@stably.ai>

* Support GitHub Enterprise diffs and mutations with host-scoped caches

Parse GitHub host identity from work-item URLs and carry it through PR/issue mutations, labels, and assignments. Bound rate-limit and scope-probe caches (1024 and 512 entries) to prevent unbounded growth when interacting with multiple GHES instances. Normalize repository identity keys to include host so github.com and GHES slugs don't collide in cache and equality checks.

* Support GitHub Enterprise diffs and mutations with host-scoped caches

- Carry host identity through PR mutations and reads so fork PRs on
  different GHES instances don't collide in cache or state tracking.
- Validate host authentication before routing requests to unconfigured
  Enterprise servers; ambient credentials must never reach untrusted hosts.
- Scope rate-limit guards and spend tracking per host so GHES quota stays
  independent from github.com quota.
- Respect explicit --hostname arguments in gh CLI calls ahead of GH_HOST or
  ambient defaults, so breaker state follows the actual request target.
- Detect implicit WSL runtimes from UNC paths for consistent host auth and
  execution-options scoping across mobile and desktop clients.

* Support GitHub Enterprise work-item diffs with host-scoped execution

Enterprise PRs must use their selected host consistently across diff, comments,
and file-content loads. Validate repository slugs before authenticated execution
to prevent path-injection via renderer overrides. Scope project browsing cache
and rate-limit tracking by host to prevent cross-host pollution. Use parsed
URLs as authoritative over ambient hosts for project resolution.

* Support GitHub Enterprise work-item diffs with host-scoped execution

Preserve host identity on PR/issue work items throughout the mutation and diff
pipeline so Enterprise instances (including ported endpoints like
github.acme.test:8443) can execute mutations without ambiguity. Rate-limit gh
commands by the pre-qualified --repo host, cache auth state per ported host,
and surface Enterprise hosts in project metadata and error messages.

* fix(review): drop dead rateLimitGuard/noteRateLimitSpend re-export

Both callers (project-view.ts, mutations.ts) moved to the host-scoped
repositoryRateLimitGuard/noteRepositoryRateLimitSpend; the bucket-only
re-export in internals.ts had zero importers left.

Co-authored-by: Orca <help@stably.ai>

* fix(ci): split Enterprise host work-item tests under max-lines

Move GHES/SSH host-routing cases out of work-item-details.test.ts so
the suite stays within the 800-line test max-lines budget.

* test(github): align mocks with host-scoped repository resolution

- Route origin repository resolution through getOwnerRepoForRemote, not getOwnerRepo, to match production path
- Pin github.com host on origin results so host-less fixtures pass host gate in resolveGitHubApiRepository
- Add generation-based invalidation to prevent stale slug-cache writes from in-flight resolutions
- Fix ref-sync race in ProjectPicker: use useLayoutEffect so committed tree owns browse cache key
- Defer handledCrossRepoUrlRef assignment in SmartWorkspaceNameField until resolution succeeds
- Update Enterprise host routing: found work items must not silently fall back to default host when unresolved
- Normalize GHES avatar URLs: accept explicit port 443 as canonical form, not a fallback trigger

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-20 18:55:45 -07:00
Brennan Benson aca7d50bab Stop attaching stale closed PRs/MRs to default-branch checkouts (#9469)
* Stop attaching stale closed PRs/MRs to default-branch checkouts

On the repo default branch, the implicit head-branch PR lookup (state=all)
could attach a historical closed/merged PR whose head ref was the default
branch name and show its wrong diffs and checks (#9171).

Add a shared default-branch guard: an implicit branch-name match on the
repository's default branch never surfaces a non-open review. Applied at
the branch-lookup choke point of all five provider clients (GitHub,
GitLab, Bitbucket, Azure DevOps, Gitea). Explicitly linked reviews are
exempt; open reviews from the trunk stay visible; resolution is lazy
(zero git calls unless a non-open candidate appears), TTL-cached,
transport-aware (local/WSL/SSH), probe-time-bounded, and fails open.

* Treat stuck-locked GitLab MRs as non-open in the default-branch guard

Three code-review lanes flagged (one reproduced) that 'locked' — normally
a seconds-long merge transition, but a known GitLab wedge state — leaked
past the closed/merged-only check and would re-create the #9171 symptom
for a stuck-locked MR whose source branch is the trunk.

* Bound default-branch lookup to one refresh budget

* Coalesce default-branch resolution probes
2026-07-20 11:54:30 -07:00
NeilandOrca 190de8223e refactor(comments): slim verbose comments in main integrations (git/providers/…) (#9543)
Collapse multi-line explanatory comment blocks into single-line "why" statements
per AGENTS.md ("Document the Why, Briefly"): drop restatements of the code and
mechanism narration; keep the non-obvious reason, external refs, and directives.

Comments-only — verified no code changed via a Babel/esbuild comment-strip
token-equality gate against origin/main; typecheck and oxlint clean.

Area: main — git, source-control, providers & integrations. 40 files changed, 1432 insertions(+), 4473 deletions(-).

Co-authored-by: Orca <help@stably.ai>
2026-07-20 03:18:28 -07:00
Jinjing d67ede1594 Implement confirm-only PR panel composer with classified error blocking (#9428)
* Clarify PR panel guidance: classify errors and confirm-only composer

Replace the ambiguous GitHub hosted-review boolean with a four-state evidence
model (found/positive_unresolved/not_found/unknown) so "No PR found" never
appears without an accepted lookup result. Classify GitHub refresh failures
into types (rate_limited, auth, network, permission, repo_unavailable,
gh_unavailable, unknown) for stable, honest copy. Confirmed-only composer:
preserve drafts across transient failures; hide Create during hard errors and
positive-unresolved evidence. Hard errors clear only when an eligibility
request starts after the error and returns an accepted outcome. Propagate
error types and unified retry schedule through the store. Sync mobile parity
with shouldOpenChecksPanelCreateComposer gating. Localize all new copy.

* Clarify PR panel guidance: classify errors and confirm-only composer

Add reviewLookupOutcome to hosted-review eligibility and thread it through
the panel so it never claims "No PR found" without accepted evidence. A
failed lookup is unavailable, not a settled no-PR. Fail closed on positive
unresolved evidence, hard refresh errors, and unavailable lookups. Add
structured GitHub refresh-error classification with Retry-After parsing.
Implement confirmed-only composer gating based on fresh, matching-context
eligibility with hard-error clearing. Mobile gates on reviewLookupOutcome
to prevent false Create claims. Surface throwOnFailure variants for each
provider so transport failures cross the RPC boundary instead of collapsing
to null. (Design success criteria 1–4; invariant 8.)

* Add exec-error helpers for subprocess error classification

Extracts stderr/stdout parsing and Retry-After detection into a
lightweight module that can be imported without pulling in the heavier
runner machinery. Supports PR-refresh error classification and proper
rate-limit handling for gh commands.

* test(mobile): include reviewLookupOutcome in create eligibility fixtures

Create / Push & Create now fails closed unless the lookup is not_found.
Update mobile test fixtures so accepted-no-PR cases can still proceed.

* Add OrThrow mock variants to forge-provider test mocks

forge-provider resolves branch reviews via the OrThrow variant so
lookup failures surface as unavailable instead of "no PR found".
2026-07-19 16:32:36 -07:00
4930c87219 fix(github): load PR details on fork checkouts by preferring upstream (#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 #7332 and hardened in #7513.

Closes #7331

Co-authored-by: fsdwen <1214772+fsdwen@users.noreply.github.com>
Co-authored-by: brennanb2025 <79079362+brennanb2025@users.noreply.github.com>
2026-07-18 14:53:22 -07:00
Brennan Benson ef03a50b1d fix(github): attribute GitHub API outages instead of blank/"failed" states (#9106)
* fix(github): attribute GitHub API outages instead of blank/"failed" states

When GitHub's API is unreachable (5xx outage, network, or rate limit), Orca
showed no PR data with no explanation, so it read as an Orca bug rather than a
GitHub-side problem.

- Add a shared classifier (classifyGitHubUnavailable) reused by the main
  process and the renderer so every surface attributes an outage identically.
  A live outage returns HTTP 5xx, which the PR-refresh classifier previously
  had no branch for (fell through to the un-attributed "refresh failed").
- Right-sidebar Checks panel: show GitHub-attributed copy in the error
  empty-state, plus an inline banner over stale cached PR data so an outage
  doesn't look like a normal (silently out-of-date) panel.
- Tasks/PR-list page: replace the vague "N of M projects failed to load" with
  a GitHub-attributed banner when the failure is a reachability problem.

Copy names GitHub as the source and reassures it isn't an Orca problem, with no
status-page link. Stays GitHub-scoped so GitLab/other providers aren't
mislabeled.

* fix(github): keep outage attribution accurate

* fix(github): preserve outage attribution edge cases

* fix(github): preserve Tasks outage attribution

* fix(github): avoid false outage attribution

* fix(runtime): tolerate absent browser certificate state

* fix(ui): preserve exhaustive optional state handling

* fix(github): preserve outage attribution for combined queries

* fix(github): preserve runtime failure attribution

* chore: restore unrelated UI files to main (out of scope)

native-chat-session-option-labels.ts and skill-freshness-group.tsx switch
tweaks were unrelated to GitHub API outage attribution — they fix pre-existing
switch-exhaustiveness lint on main, which this PR's CI (oxlint) doesn't gate on.
Restore them to origin/main so this PR's diff stays focused; the exhaustiveness
cleanup belongs in its own change. (sync-runtime-graph.ts is already identical
to main, so no diff there to revert.)

* fix(github): drop Orca self-reference from outage copy

* fix(github): drop em-dashes from outage copy
2026-07-17 15:16:07 -07:00
539e0601d5 fix(github): render GitHub Enterprise PR avatars via API avatar_url (#9107)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: davkim1030 <davkim1030@gmail.com>
2026-07-16 19:24:10 -07:00
fsdwenandJinjing 78d2b958bf fix(issues): replace cursor-based pagination with page-number Search API (#8680)
* fix(issues): replace cursor-based pagination with page-number Search API

Problem
=======
Issue pagination (#8649) had two bugs:
1. Pages 6-16 were unreachable — clicking page 16 highlighted page 5;
   clicking 6/7 did nothing. The old cursor-based approach
   (updated:<CURSOR) broke with Search API's relevance sorting —
   pages after the first few returned no items even though more
   issues existed.
2. Issue numbers appeared out of order on loaded pages (e.g. #1082
   between #1308 and #1499), because client-side sort used
   updatedAt instead of issue number.

Root Cause
==========
The pagination used two separate GitHub API strategies:
- Initial page 0 load: REST endpoints (repos/:owner/:repo/issues,
  repos/:owner/:repo/pulls) sorted by updatedAt
- Subsequent pages: Search API with cursor (updated:<DATE)

These two sources returned items in different orders, causing items
to go missing or appear on wrong pages across page boundaries.

Solution
========
1. Unified on GitHub Search API for all pages — initial load and
   pagination both use search/issues?q=...&page=N, eliminating the
   REST-vs-Search inconsistency.
2. Changed from cursor-based (update:<DATE) to page-number-based
   pagination (page=N), which the Search API supports natively.
3. Switched client-side sort from updatedAt to issue number
   (sortWorkItemsByNumber), matching GitHub's default Issues view.
4. Parallelized page fetches in handleLoadNextPage — clicking page
   16 now fetches all intermediate pages concurrently (~2s) instead
   of sequentially (~30s).
5. Cleaned up dead legacy gh issue list / gh pr list code path,
   extracted quoteForSearch helper, shortened overlong comments.

Files changed: 11 files, +140/-127 lines

Closes #8649

* chore: remove unrelated merge formatting

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-07-15 18:52:37 -07:00
Brennan Benson a1778d93d3 Fix PR checks sticking to a stale linked PR after a terminal branch switch (#8760)
* Fix PR checks sticking to a stale linked PR after a terminal branch switch

A worktree's linked PR is a branch-scoped hint, but two refresh paths race
when a terminal switches branches: the git-status identity path clears
branch-scoped review links, while the worktree-listing path rehydrates the
new branch together with the stale persisted link and clears nothing. When
the listing lands first (the common case — worktree listing is much faster
than git status), the identity path sees no branch change and the stale
link survives. Every subsequent refresh then re-fetches the linked PR by
exact number, which ignores the branch, so Checks stays pinned to the old
branch's PR and the Refresh button cannot recover.

Two-part fix:
- Prevention: listing refreshes now route observed branch switches through
  updateWorktreeGitIdentity before merging, so the existing link clear and
  tombstone machinery runs no matter which refresh path wins. Gated on the
  entry still carrying branch-scoped review context so a stale listing row
  cannot roll back a newer branch identity.
- Recovery: PRInfo now carries headRefName, and a fetch that returns the
  linked OPEN PR whose head branch matches neither the current branch, the
  worktree push target, nor the worktree HEAD clears the durable link and
  re-resolves by branch. Wired into both fetchPRForBranch and the
  background refresh coordinator, mirroring the merged-PR divergence clear.
  This also heals wedged workspaces persisted by earlier builds.

* Harden stale PR recovery across refresh races

* Avoid duplicate PR recovery refresh work

* Index linked PR refresh aliases once
2026-07-15 15:52:41 -07:00
moseohandOrcaWin 7d8c4fdca1 fix(github): pin work-item list ordering to updated-desc so cursor pagination reaches every page (#8658)
* fix(github): pin work-item list ordering to updated-desc so cursor pagination reaches every page

The Tasks page paginates work items with an updatedAt cursor
(updated:<oldest-item), but the underlying gh calls never pinned a sort:
'gh issue list' defaults to created-desc and '--search' defaults to
best-match. Items created long ago but updated recently therefore never
appeared on any page — page 0 (created order) skipped them and every
later page excluded them via the cursor — so the pager advertised pages
the fetch chain could never reach, clicks on them clamped to the last
real page, and cross-page ordering was scrambled.

Append sort:updated-desc to every list/search invocation so the fetch
order matches the cursor field on the first and all subsequent pages.

Verified against a live 588-issue repo: the cursor chain previously
died around page 5; it now traverses 585/588 unique issues (the
remainder is the pre-existing strict '<' boundary edge for items
sharing the cursor's exact timestamp).

Fixes #8649

* fix(github): make work-item cursor pagination lossless at updatedAt boundaries

Builds on the sort-pin fix: switch the pagination cursor from strict
'updated:<' to inclusive 'updated:<=' so items sharing the boundary row's
exact updatedAt are no longer skipped between pages (the residual 3/588 edge
in #8649).

The inclusive bound re-fetches the boundary rows, so dedupe them by repoId+id
(a bare item.id like 'issue:9' collides across repos). Extract the page
accumulation out of the 12k-line TaskPage component into a pure, unit-tested
helper (accumulateWorkItemPages) that dedupes and backfills: it accumulates
fresh rows across fetches and emits uniform pageSize pages, so deduped pages
never shrink below the size totalPages (count / effectivePageSize) assumes —
which would otherwise strand the tail items and break the no-count degraded
pager.

Also hoist the updated-desc ordering into a named WORK_ITEM_LIST_SORT_QUALIFIER
constant so the cursor's ordering contract has one home.

Tradeoff: when per-repo fetch size equals pageSize, the boundary dedupe costs
one extra fetch per page; acceptable for interactive pagination and bounded by
the gh rate-limit guard. Persisting the cursor/buffer across calls is a
possible follow-up.

---------

Co-authored-by: OrcaWin <alpha-eng@stably.ai>
2026-07-13 22:37:46 -07:00
Brennan Benson 2f660a6028 fix(source-control): route GitHub Enterprise Server remotes to the GitHub provider for PR creation (#8312) (#8603)
* fix(source-control): route GHES remotes to the GitHub provider for PR creation

A GitHub Enterprise Server user could not submit a PR — Orca demanded
ORCA_GITEA_TOKEN — while issue sync worked fine (#8312).

Root cause: GitHub owner/repo resolution (parseGitHubOwnerRepo) hard-rejects
any host that is not literally github.com. A GHES remote lives on a custom
host, so GitHub's forge resolveRepository returned null and provider detection
fell through the list to Gitea, whose KNOWN_NON_GITEA_HOSTS denylist cannot
enumerate arbitrary GHES domains. Issue sync was unaffected because gh
issue/pr list run with cwd=repoPath and let gh resolve the GHES host natively.

Fix mirrors GitLab self-hosted detection (getGlabKnownHosts): a new
getEnterpriseGitHubRepoSlug resolves a custom-host origin to owner/repo only
when gh is authenticated to that host — gh only ever manages GitHub/GHES
credentials, so a logged-in host is definitively GitHub. Wired into:
- forge-provider GitHub resolveRepository (fallback after github.com miss),
  so detection claims GHES before Gitea is consulted;
- createGitHubPullRequest owner/repo resolution;
- isGitHubAuthenticated, which now probes the repo's real host instead of a
  hardcoded --hostname github.com.

github.com repos keep the cached getRepoSlug fast path and never spawn the
extra gh auth probe.

* fix(github): host-qualify GHES gh commands and probe auth in the repo runtime

Addresses two correctness issues found in review of the #8312 fix.

1. GHES host was discarded before `gh pr create`. `--repo owner/repo` shorthand
   resolves against gh's default host (usually github.com), so for a user
   authed to both github.com and GHES it could target a same-named github.com
   repo or fail — deterministic for SSH repos, which run gh with no cwd. Now
   `createGitHubPullRequest` and the `findOpenPRByHeadBase` fallback pass a
   host-qualified `HOST/owner/repo` for GHES (github.com keeps the shorthand).
   Also generalize `parseCreatePRPayload`'s URL regex off github.com so a GHES
   PR URL parses directly instead of limping through the list fallback.

2. GHES auth was probed on the wrong gh runtime. `getAuthenticatedGitHubHosts`
   ran a global `gh auth status` with no cwd/WSL/SSH context and cached every
   runtime under one "local" key, so a GHES login present only in the repo's
   WSL distro was missed and the repo fell back to Gitea. Replaced with
   `isGitHubHostAuthenticated`, which runs `gh auth status --hostname <host>`
   with the repository's execution options (cwd/WSL distro, or SSH-local like
   the create path) and caches per runtime+host — mirroring GitLab's
   isGlabConfiguredForRemoteHost. This also honors GH_ENTERPRISE_TOKEN inferred
   from repo context. Spawn failures stay indeterminate (uncached).

Adds createGitHubPullRequest-level tests asserting the actual gh `--repo`
arguments (create + fallback) and the WSL/SSH runtime of the auth probe.

* perf(source-control): drop redundant GHES gh auth probe in eligibility

Review follow-up. Detection only routes a GHES remote to the GitHub provider
after getEnterpriseGitHubRepoSlug has confirmed gh is authenticated to its
host, so isGitHubAuthenticated can trust a non-null slug as authenticated and
skip a second, rate-limited `gh auth status` spawn per eligibility poll.
Reaching the github.com probe now implies the remote is github.com. Tests
assert the enterprise path fires no redundant gh probe.
2026-07-13 18:06:06 -07:00
Jinjing e9f79850be Distinguish failed PR file fetches from genuinely empty PRs and add a re (#8342)
- 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
2026-07-11 19:26:17 -07:00
Neil b5cdab3a26 Fix tracked upstream generation cache leak (#7674) 2026-07-11 13:43:17 -07:00
Rod BoevandJinjing b677b2a209 fix(github): recover oversized issue creation (#8217)
* fix(github): recover oversized issue creation (#7704)

* fix(github): preserve partial issue creation

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-07-10 23:16:13 -07:00
Neil 435de94102 perf(main): avoid hosted-review IPC fanout (#8171) 2026-07-10 20:52:22 -07:00
Neil 533992bdda fix(git): cache unsupported capabilities per host (#8109)
* fix(git): cache unsupported capabilities per host

Old Git worktree, ref-search, and merge-tree fallbacks retried unsupported flags on recurring operations, flooding subprocess traces. Centralize capability probing per native, WSL, and SSH execution host, coalesce concurrent probes, and retry periodically for in-place Git upgrades.

* fix(git): recognize real old-Git merge-tree rejection

* test(git): enforce real binary compatibility matrix

* fix(ci): preserve Git compatibility test ownership

* fix(git): retain supported capability state
2026-07-10 18:19:36 -07:00
Jinjing 3a3e33f14b The --sandbox flag (or terminal sandboxing) in Google Antigravity is a (#8017)
Here is a summary of how the sandbox behaves on your macOS system:

### ⚙️ How it Works
When `--sandbox` is enabled (either via the launch flag or the `enableTerminalSandbox` setting in your `settings.json`), terminal commands run inside a lightweight containment boundary:
- **macOS Native Isolation**: It utilizes macOS's native `sandbox-exec` utility to restrict system calls, network sockets, and directory access.
- **Secure File Boundaries**: File system writes are locked down to designated safe zones (such as your designated workspace or scratch directory). Access to critical system paths, private user data, and external network resources is restricted.

---

### 🛡️ Active Permissions for this Session
In this current session, the permission model is configured as follows:

| Action / Resource | Permission Status | Details / Paths |
| :--- | :--- | :--- |
| **Command Execution** | ✅ **Allowed** | Terminal command execution is enabled. |
| **File Reads (Allowed)** | ✅ **Allowed** | `/scratch`, `/browser_recordings`, `/html_artifacts`, `/knowledge`, `/worktrees`, `/skills`, `/builtin` |
| **File Writes (Allowed)**| ✅ **Allowed** | `/scratch`, `/browser_recordings`, `/html_artifacts`, `/knowledge`, `/worktrees` |
| **Sensitive Files** | ⚠️ **Ask** | `.env`, `.npmrc`, `.vscode`, `.git-credentials`, etc. |
| **Root/App Settings** | 🚫 **Denied** | Direct modifications to `/config` and main `.gemini` configurations |

---

### 🔧 Configuration and Management

* **Persistent Settings**:
  To enable sandboxing by default for all future sessions, configure the `enableTerminalSandbox` setting in your `~/.gemini/antigravity-cli/settings.json`:
  ```json
  {
    "enableTerminalSandbox": true
  }
  ```

* **Dynamic Adjustments**:
  Within an active CLI (`agy`) session, you can run the `/permissions` slash command to view or modify your autonomy and sandboxing levels on the fly.

> [!NOTE]
> Running in sandbox mode provides an excellent balance of autonomy and security, allowing me to execute build commands, run test scripts, and manage project files safely without risk to your primary host environment.

Please let me know if you would like me to set up a new project workspace or run any specific tasks within this session!
2026-07-09 22:01:22 -07:00
Brennan BensonandOrca 46a67cb2eb perf(source-control): cache PR conflict-summary derivation and throttle base fetch (#7606)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 22:02:59 -07:00
Brennan BensonandOrca 82eeac6194 Keep GitHub PR status working when the rate-limit budget can't be read (GHES with rate limiting disabled) (#7632)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 21:45:10 -07:00
Jinwoo HongandOrca 417723411e perf(source-control): stop gh rate-limit storms and idle git-status spawn churn (#7595)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 15:12:56 -07:00
NeilandOrca e33b2006f4 Remove stale max-lines lint disables from files under the limit (#7548)
110 files carried an eslint/oxlint-disable max-lines directive but are
already under the default max-lines budget (300 .ts / 400 .tsx / 600 .mjs
/ 800 test), so the suppression is dead. Removing it restores real
max-lines coverage on these files with zero behavior change.

Each removed directive had max-lines as its only rule; verified via a
full oxlint run (0 max-lines violations, 0 new errors). Diff is pure
deletions (200 lines, 0 additions) — no code touched.

Co-authored-by: Orca <help@stably.ai>
2026-07-06 02:12:32 -07:00
Brennan BensonandOrca eb8435950a Clear a worktree's merged pull request after it switches to a different branch (#7460)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 01:26:10 -07:00
Neil ce687221d3 lint(unicorn): enable prefer-number-properties, prefer-array-find, prefer-array-index-of (#7516)
Enable three unicorn rules — one correctness, two performance — and fix every
existing violation repo-wide so the rules pass as errors.

prefer-number-properties (76 sites)
- parseInt/parseFloat/NaN -> Number.* : safe aliases (autofixed).
- isNaN -> Number.isNaN (12 sites, hand-converted): global isNaN coerces its
  argument, Number.isNaN does not. Verified every call site already passes a
  number (Number.parseInt results, number-typed fields, Date.getTime()), so the
  conversion is behavior-preserving today and guards against a future non-numeric
  argument silently coercing.

prefer-array-find (26 sites)
- .filter(pred)[0] -> .find(pred); .filter(pred).at(-1) / .pop() -> .findLast(pred).
  Drops the intermediate array and short-circuits.

prefer-array-index-of (5 sites)
- .findIndex(x => x === v) -> .indexOf(v).

Verified: typecheck (node/cli/web) clean, 53 affected suites pass (1679 tests),
oxlint clean repo-wide. mobile/ uses findLast safely (already ships ES2023
.toReversed()); config scripts and e2e helpers run on Node 24.
2026-07-05 23:56:37 -07:00
Jinjing c641e55486 Normalize GitHub work item type from URL to prevent issue/PR mismatch (#7371)
- Resolve true work item identity (issue vs. PR) using the URL path to
  override stale or incorrect cached payload types.
- Prevent invalid PR start point resolution when launching an issue
  misclassified as a PR.
- Validate and reject mismatched URL types in the worktree metadata
  dialog fields to avoid incorrect associations.
2026-07-04 15:16:50 -07:00
Brennan BensonandOrca b099e27703 fix(checks): keep a merged PR visible when the worktree sits behind its own PR head (#7277)
Co-authored-by: Orca <help@stably.ai>
2026-07-03 19:30:10 -07:00
PPandping 69415946dd fix(github): count PR diff lines whose added content starts with ++ (#6819)
Co-authored-by: ping <ping6174@gmail.com>
2026-07-03 17:25:32 -07:00
Brennan BensonandNeil 5b7611ddcb fix(win): release PR-refresh aliases when a worktree is removed (#6861)
The OOM reports (F0BDMD16LJ2 and the taifunk many-worktree sessions)
show memory creeping over long sessions with churning worktrees. One
contributor: in pr-refresh-coordinator, many local worktrees that track
the same linked PR coalesce into a single queue entry whose 'aliases'
map keeps one entry per worktree. Aliases were only pruned when a
candidate was re-enqueued as invalid — never when a worktree was simply
removed/closed — so the maps grew unbounded across a session.

Add pruneWorktreePRRefreshAliases(worktreeId) and call it from
removeWorktreeMetadataAndTransientState (the existing central
worktree-removal cleanup, alongside removeWorktreeMeta /
forgetWorktree / deleteWorktreeHistoryDir). It drops the removed
worktree's aliases, deletes the queue entry when none remain, and
rebinds the representative candidate if the removed worktree owned it.

Covered by 3 new coordinator tests (accumulate-then-prune, keep-entry-
on-remaining-aliases with candidate rebind, no-op for unknown worktree)
plus two test-only inspection helpers.

Co-authored-by: Neil <neil@stably.ai>
2026-06-30 00:55:54 -07:00
NeilandOrca 46646d7ff1 chore(lint): upgrade oxlint to 1.71 + enable 7 new rules (autofixed backlog) (#6841)
* chore(lint): upgrade oxlint to 1.71 and enable 7 new rules

Upgrade oxlint 1.67.0 -> 1.71.0 (1.72 was blocked by the repo's 3-day
minimum-release-age supply-chain guard; nothing here needs it). The
bump is a no-op on the existing config.

Enable 3 error rules (backlog autofixed to zero in this commit) and
4 warn rules (surface signal without gating CI):

error (autofixed, behavior-preserving):
- unicorn/prefer-node-protocol        (~1531 sites: bare builtin -> node:)
- typescript/no-import-type-side-effects (~36: all-inline-type -> import type)
- unicorn/no-array-reverse            (19: copy-then-reverse -> toReversed)

warn (real signal, current fires are test-only/correct):
- unicorn/no-array-fill-with-reference-type  (aliasing footgun guard)
- typescript/no-unsafe-function-type         (bans bare Function type)
- unicorn/prefer-array-flat-map              (map().flat() -> flatMap())
- unicorn/prefer-regexp-test                 (.match() in bool ctx -> .test())

mobile/.oxlintrc.json extends root, so it inherits all 7; the autofix
ran from root and covered mobile/ too.

Verification (all green): oxlint 0 errors (root+mobile+aux configs),
oxfmt clean, typecheck (node+cli+web), vitest 22795 passed / 0 failed,
builds (electron-vite + web + cli) succeed. node: rewrites confirmed to
skip embedded SSH/CLI string payloads (AST-only); all toReversed sites
verified to operate on fresh copies or write-once locals.

* chore(lint): bump mobile oxlint to 1.71 so inherited rules parse

mobile/ is a standalone pnpm project pinning its own oxlint@1.67, which
lacks unicorn/no-array-fill-with-reference-type (needs >=1.70). Since
mobile/.oxlintrc.json extends the root config, mobile CI's 'cd mobile &&
oxlint' failed to parse the new rule. Bump mobile to match root (1.71).

Verified in mobile/: oxlint 0 errors, oxfmt --check clean, tsc --noEmit
pass, vitest 978 passed / 0 failed.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-06-29 22:38:29 -07:00
NeilandAlexander Kirilin 4776ac1fe5 fix: include legacy commit statuses in PR checks (#6556)
Co-authored-by: Alexander Kirilin <github@alexanderkirilin.com>
2026-06-29 19:04:09 -07:00
Jinjing a978222184 Clarify auto-merge UI and errors when direct merge is available (#6777)
GitHub rejects enabling auto-merge on a PR that is already mergeable
with a "Pull request is in clean status" error.

* Suppress "Enable auto-merge" option in the UI when direct merge
  is available, while retaining "Disable auto-merge".
* Translate the GitHub "clean status" GraphQL error into an actionable
  message recommending direct merge.
2026-06-29 14:40:53 -07:00
Jinjing 1c30d28113 Surface GitHub check suites awaiting approval (#6717)
* Surface GitHub check suites awaiting approval to unblock merge

- Query the check-suites API endpoint to find suites with an
  "action_required" conclusion, which are often workflows awaiting
  "Approve and run" and do not have any associated check runs.
- Map the "action_required" status distinctly instead of treating it as
  a standard failure or omitting it entirely.
- Update the UI to render these suites with a warning icon, a dedicated
  "Action required" label, and a localized hint explaining that manual
  approval is required on GitHub.
- Count "action_required" checks as failed/blocking when deriving overall
  PR and task statuses so the UI does not report all checks passing.

* Enhance visibility and handling of action-required PR check suites

* Include check suite IDs in pending approval check names and URLs to
  allow navigating directly to the specific workflow run.
* Add an "action required" count badge to PR dialog and page checks tabs.
* Prioritize action-required checks in the checks preview summary.
* Use correct check run state for the action-required fallback hint in
  the right sidebar details panel.
* Add translations for the new status across all supported locales.
2026-06-29 12:05:57 -07:00
Jinjing 7c6f88ba6e fix: address review findings (#6666) 2026-06-28 16:53:32 -07:00
Jinjing cea920a3e4 Harden failed check details links (#6661)
* fix: harden failed check details links

* chore: remove tracked node_modules symlink
2026-06-28 16:17:32 -07:00
Jinjing 3d3453c216 Propagate upstream errors from branch-based PR discovery (#6660)
Previously, transient errors during candidate branch discovery (such as
rate limits or network issues) were silently ignored, leading to a
false "no-pr" result and causing the sidebar PR state to flicker.

Now, track and return any pending error encountered during branch
lookups, propagating it as an upstream error if no PR is successfully
recovered.
2026-06-28 16:17:01 -07:00
Brennan BensonandOrca a71b865867 Show PR status for branch worktrees at a merged PR head (#6607)
Co-authored-by: Orca <help@stably.ai>
2026-06-28 11:22:07 -07:00
Brennan BensonandNeil 85d626b998 Fix fork PR detection for same-name upstreams (#6446)
Co-authored-by: Neil <neil@stably.ai>
2026-06-26 14:49:19 -07:00
Jinjing dd0fa77882 Enhance PR auto-merge controls and switch to GraphQL mutation (#6405)
- Centralize and align auto-merge eligibility logic across web and
  mobile clients.
- Use the `enablePullRequestAutoMerge` GraphQL mutation instead of
  `gh pr merge --auto` to prevent immediate merges on clean branches.
- Fall back to `gh pr merge --auto` when a merge queue is required on
  the base branch.
- Hide the auto-merge control when only optional checks are pending.
2026-06-25 22:00:34 -07:00
Brennan BensonandOrca c10b77d160 Reduce Git refresh subprocess fanout (#6324)
Co-authored-by: Orca <help@stably.ai>
2026-06-25 13:00:44 -07:00
Brennan BensonandOrca c37ab96b57 Remove split terminal from onboarding checklist (#6340)
Co-authored-by: Orca <help@stably.ai>
2026-06-25 01:49:56 -07:00