A stray github.com or bitbucket.org entry in glab's config made the failed
`glab auth status --hostname <host>` probe print a status block headed by a
bare hostname, which the configured-host parser accepted as evidence. The
known-host inventory could likewise list github.com. Because GitLab has
precedence among forge providers, GitHub and Bitbucket repos were offered
GitLab merge requests and GitLab login prompts.
Before trusting any glab evidence, resolveProjectRefForRemote now returns null
when the remote's real host (aliases folded via normalizeForgeWebHost) is
github.com or bitbucket.org. Scp remotes on an SSH alias named e.g. `github`
are unaffected.
Fixes#40386
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
* perf(tasks): look up the GitLab comment viewer only on phone reads
The phone is the only reader of viewerDidAuthor, so GitLab detail reads
from desktop IPC and the Checks poll skip the `glab api user` lookup.
The phone sends markViewerComments on every GitLab detail read.
Ported from #39749 (GitLab part only); GitHub REST-fallback viewer
lookup is unchanged.
Co-authored-by: AmoabaKelvin <97001695+AmoabaKelvin@users.noreply.github.com>
* perf(tasks): keep GitLab viewer marks by default; desktop detail reads opt out
Older phones and callers that omit markViewerComments keep author marks.
Co-authored-by: AmoabaKelvin <97001695+AmoabaKelvin@users.noreply.github.com>
---------
Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
Co-authored-by: AmoabaKelvin <97001695+AmoabaKelvin@users.noreply.github.com>
* fix(tasks): confirm a lost Tasks comment by author on GitLab and GitHub REST reads
Only GitHub GraphQL's viewerDidAuthor marked the viewer's comments, so on GitLab,
the GitHub REST fallbacks (including issues with more than 100 comments) and the
gh view fallbacks the phone kept an unconfirmed draft even after the comment
posted. Those reads now match the login of the account that made them, and an
explicit PR refresh reads comments uncached.
* fix(mobile): settle an unconfirmed comment only on one posted after the send
A refresh of an issue with more than 100 comments reads comments the first
load never showed, so an older identical comment by the same account looked
new and could clear the draft.
* refactor(gitlab): share the glab viewer read and skip it on Checks polling
* test(mobile): pin the clock in the unconfirmed comment test
* fix(gitlab): paginate pipeline jobs and bridges past 100 items
The Checks panel fetched one 100-item page of a pipeline's jobs and
bridges, so larger pipelines (and expanded child pipelines) silently lost
the rest. Move the header-aware page walker used for labels and members
into its own module and use it for pipeline jobs and bridges too.
Fixes STA-13623
Co-authored-by: alexcastgonz <82875882+pcbeingused333@users.noreply.github.com>
* fix(gitlab): follow every advertised page and keep fetched pages on a later failure
Review repairs for #39046: follow advancing x-next-page headers without a
page cap (the cap now bounds only guessed pages for missing or unusable
headers), keep rows already fetched when a later page fails, and stop
bridge paging once the parent job list fails.
* fix(gitlab): fail the details read on an incomplete page walk
A later-page failure now fails the MR details read, so Checks and the
dialog keep the jobs they last showed and report the failure, instead of
replacing a complete list with a prefix. Forbidden child pipelines (first
page refused) stay tolerated. Paging also stops on empty pages and
rejects page numbers past the safe-integer range so it always ends.
* fix(gitlab): treat exhausted page guesses as incomplete and translate the dialog load error
* fix(gitlab): follow only the consecutive next page and name the dialog load-error key
A next-page header that skips ahead or carries trailing text is now
treated like a missing header, so no page is skipped. The dialog's
load-error message uses an intent-named translation key.
---------
Co-authored-by: alexcastgonz <82875882+pcbeingused333@users.noreply.github.com>
* feat(checks): show when each check ran and how long it took
Check rows in the right-sidebar Checks panel now show how long a
finished check took and how long ago it finished (or started, while it
runs), with exact start and finish times on hover. GitHub check runs,
legacy commit statuses and GitLab jobs carry provider run times; rows
without times show nothing.
A GitLab pipeline that ran on a commit the merge request has since moved
past says so. The GitHub rollup read keys its 60s cache by the expected
head, so a push never serves the previous head's checks.
* test(checks): bound the clock work of check time labels
* perf(checks): rebuild check time text only when its data changes
Clock ticks now move only each row's age; exact times, duration and copy
are built once per data or language change. Move the run-time mapping
tests to the mapping layer to keep the client test file within budget.
* fix(checks): annotate the gh pr checks reply instead of casting it
* fix(checks): say when a running check started; key the rollup cache by a query comment
A running row reads 'started 5m ago' so its age isn't read as when it
ran. The expected head now rides in a GraphQL comment, which servers
ignore but gh's cache key includes. Add the new copy to the English
catalog and test behavior rather than formatted copy.
* fix(checks): let check times truncate before names in a narrow sidebar
At the narrowest sidebar the time text never shrank, squeezing check
names to nothing and pushing status labels out of their rows. The time
now sits beside the name, gives up width first, and the name keeps a
minimum width.
* fix(checks): rebuild check time copy when translation catalogs change
* fix(checks): reserve room for a running check's growing start age
* test(checks): keep REST check-run times covered through the schema
* fix(checks): read the checks rollup without gh's disk cache
gh's cache key ignores the PR head, so after a push it answered with the
previous head's checks, and it never evicts expired entries. Orca's own
head-keyed checks cache and read coalescing already bound the requests.
* fix(checks): hide check times in rows too narrow to show them
Below a 17rem row the time text is hidden, so the narrowest sidebar keeps
main's name, status and link layout; wider rows truncate the time before
the name, which keeps a 36px minimum.
* fix(checks): truncate a check's duration before its age
The age answers when a check ran, so in a tight row the duration now
gives up its width first.
* test(checks): type the rollup fixture
* fix(checks): show check times only in rows with room for them
Between a 17rem and 19rem row the times squeezed names to their minimum
and clipped; hold them back until 19rem, which the default 350px sidebar
clears.
* fix(checks): keep a minimum name width only while check times show
Rows too narrow for times, including the narrower folder-workspace parent
PR rows, now lay out exactly as before.
* fix(checks): show a running check's elapsed time instead of its start age
'started 10m ago' reserved so much room that running check names shrank
to a few characters at the default sidebar width; beside a running status
the elapsed time ('10m') says the same thing in a quarter of the space.
* test(checks): use a type import for the mocked module
* feat(gitlab): filter Tasks merge requests to ones you wrote or review
Tasks > GitLab > MRs could only filter by state, so on busy projects you
had to scan every open MR to find yours. A second set of chips (Everyone,
Mine, Needs review) now combines with the state chips, so "my merged MRs"
works too.
The filter runs on the host that owns the repo's GitLab sign-in, looks up
the signed-in user fresh on the project's own host, and filters by
author_id or reviewer_id in one request per project. A failed lookup
shows an error instead of everyone's MRs, and older paired servers that
would drop the filter ask to be updated.
Co-authored-by: Yash Kakade <yashkakade2015@gmail.com>
* fix(gitlab): keep filtered MR lists honest while loading and on old servers
- The reviewer chip reads "Reviewing": GitLab lists MRs you were asked to
review even after you reviewed them, so "Needs review" overpromised.
- Rows belong to the query that loaded them: after a chip change the list
shows loading, never the previous filter's rows with Start enabled.
- A refresh checks each paired server's filter support once, not once per
project; failed checks show the real error instead of "update the server",
and the web client sends the filtered list to the runtime it checked.
- Signed-out GitLab gets a sign-in message, and an unresolved SSH project
under a filter shows an error instead of an empty list.
Co-authored-by: Yash Kakade <yashkakade2015@gmail.com>
* fix(gitlab): pin filtered MR lists to the server that confirmed support
A refresh now shares one support check per paired server and pairing, and
the filtered list is sent to the exact runtime and pairing that answered,
so a server replaced mid-refresh can't serve "Mine" unchecked. The web
client scopes its shared check to the current pairing and reuses the
existing result unwrapping. The capability test now counts real status
probes: one per server per refresh for 12 or 120 projects.
Co-authored-by: Yash Kakade <yashkakade2015@gmail.com>
* fix(gitlab): discard filter-support answers from a replaced pairing
A paired server re-paired while Orca was asking whether it supports the
MR filter no longer leaves "update the server" from the old pairing's
answer; the check fails with the usual pairing-changed error instead.
Signed-out detection no longer matches a 401 inside a host or port.
Co-authored-by: Yash Kakade <yashkakade2015@gmail.com>
* test(gitlab): type the filter-change test's props without a cast
---------
Co-authored-by: Yash Kakade <yashkakade2015@gmail.com>
* Show failed pipelines and check suites without jobs
* Use the parent pipeline as the GitLab checks verdict
The MR's own pipeline status now leads the Source Control Checks panel,
the MR dialog and the phone checks badge whenever the details reply
carries it, even when the returned jobs are empty, partial or all
passing. Job rows and counts stay a separate breakdown. The parent
follows pipeline-level policy (required manual is pending, canceled and
skipped are not failures, mergeable manual is neutral) from one shared
rule, and it is a provider link rather than an expandable job, so it
never shows a details error with Retry. A failed parent leads the
triage strip and joins the Fix prompt by name and link.
Drops the GitHub zero-run failed check-suite rows from this change;
existing approval-required suite rows are unchanged.
* Name the GitLab pipeline outcome and keep its verdict in one rule
The host now settles the parent pipeline's verdict with the same rule
and reply that produce the MR status, so a manual pipeline on older
GitLab reads pending everywhere. The phone checks badge names the
pipeline outcome (Pipeline passed/failed/pending) instead of an
unlabeled one-item count; job wording without a parent is unchanged.
The desktop parent row's status is localized, and a failed MR-details
read still shows its error beside a kept parent with no jobs.
* Keep Fix for failed GitLab jobs and treat waiting_for_callback as pending
The triage strip shows again when a returned job failed under a passing
parent pipeline, so its Fix stays available; a failed parent still
leads. A waiting_for_callback pipeline now reads pending instead of
neutral, in the MR status and the parent pipeline alike.
* Mark the checks-panel action test fixture cast as safe
* Pause the pipeline row spinner offscreen and under reduced motion
* Make explicit hosted review refresh read current provider state
* Name the right provider and keep GitHub's own copy when a Checks refresh fails
A failed manual refresh now names the repo's provider (from the review, its link, or the remote), clears once a newer read lands for the panel, never stops GitHub checks and comments from refreshing, and gives way to GitHub's classified sign-in or rate-limit copy. The copy is one interpolated line in every locale.
* Read after the write when Orca merges, closes, reopens or edits a GitLab MR
Every GitLab merge request write now drops the host's cached review lookups for the repository, and the Checks panel's follow-up read can't join a poll that began before the write, so merging in Orca shows Merged and Delete Workspace without a manual Refresh. A user refresh also forgets Gitea's shared repository scan before reading.
* Clear a failed Checks refresh only on a real provider read
The host now tells the desktop store, when asked, whether its answer came
from a provider read it stored as current or from a cache or last-good
fallback. The Checks panel keeps a failed Refresh until such a read lands,
a click succeeds, or the context changes. On GitHub the PR read owns the
refresh status, so a failed review-card read no longer raises the generic
failure.
* Don't let a joined host lookup clear a failed Checks refresh
A poll that joins a lookup already running for an earlier request didn't
start that read, so its answer can't show the provider recovered after the
failure. Only the request that started the stored lookup reports a provider
read now. The host read also uses the shared reply outcome directly, and the
renderer writes the provider-read generation where it publishes the entry.
* Type the Checks refresh breadcrumb for every review provider
The breadcrumb already received Bitbucket, Azure DevOps and Gitea values; its
annotation now says so. Tests build typed fixtures instead of asserting types.
* Test the read-outcome reply at IPC, RPC and runtime, and the post-merge read
The flag reaches the runtime, and only a caller that asks gets the envelope,
including for a definitive null. After Orca merges, the card read starts after
the write, and its failure leaves the merge reported as done.
* Use a boolean for the empty-state fixture's remote-operation flag
* Trim redundant hosted-review refresh tests
* Keep the signed-out GitHub empty-state test
Cwd-less gh/glab calls whose host CLI is missing fell back to the default
WSL distro with no running check, so background work (rate limits, auth
status, Settings, task-source probes) booted a stopped distro. The
fallback now asks the background exec gate first: stopped or
unverifiable refuses with the distro-stopped error, running and user
acts fall back as before.
GitHub issue close/reopen swallowed every gh failure mentioning "already"
(e.g. "API rate limit already exceeded"), and GitLab MR close/reopen did the
same for glab. gh exits 0 when the issue is already in the target state, so
every gh failure is now reported. For glab, only its fixed no-op refusals
("this merge request has been closed" / "this merge request is already open")
count as success; "has already been merged" and all other errors surface.
Fixes#28766
Co-authored-by: Neil <neil@stably.ai>
* fix(gitlab): retain successful hosts from partial auth failures
Read rejected auth-status output without treating failed host headings or
API error advice as successful logins. Publish positive results through
the existing context-owned cache; keep backoff when no login succeeds.
Co-authored-by: David Anderson <cantspamdave@gmail.com>
* fix(gitlab): preserve discovery retries with partial host evidence
* fix(gitlab): escape auth marker for ASCII server bundle
---------
Co-authored-by: David Anderson <cantspamdave@gmail.com>
* Correct GitLab MR check status for failed and manual pipelines
Use the same single-MR read for linked and branch-discovered reviews so a
list summary cannot hide a failed pipeline. Preserve lookup failures for
strict callers and keep detail reads within the existing branch cache.
Set mergeable manual pipelines to neutral without claiming an unrun stage
passed; keep blocking manual pipelines pending.
Co-authored-by: Son of Odin <2700975-son-of-odin@users.noreply.gitlab.com>
Co-authored-by: Emily <hadikcze@gmail.com>
* test: cover GitLab MR check status consumers
* test: type GitLab MR fixtures from mapper input
* chore: document GitLab MR boundary assertion exceptions
* test: share GitLab MR producer and consumer fixtures
---------
Co-authored-by: Son of Odin <2700975-son-of-odin@users.noreply.gitlab.com>
Co-authored-by: Emily <hadikcze@gmail.com>
* fix(gitlab): keep paging merge requests when GitLab omits the totals
When total headers are absent, a full response advertises another page to probe and a short response ends pagination. Keep the existing header precedence and unknown total count.
Tracked in #33800
* test(gitlab): cover MR pagination exhaustion and header precedence
* test(gitlab): verify unknown-total metadata across list consumers
* test(gitlab): cover remaining screen consumers of list metadata
* test: use checked GitLab RPC runtime fixtures
---------
Co-authored-by: Hotragn <103170876+Hotragn@users.noreply.github.com>
Main now tags each Orca-authored PR/MR create failure with a reason code
(the English error is unchanged for mobile, older clients and logs), and
the renderer maps the reason to translated copy in the Source Control
notice, the Checks panel and the pre-create blocked notice. Sign-in steps
are single-sourced across providers.
Fixes#33321
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
* fix: back off failed GitLab authentication probes
* fix(gitlab): use short exponential backoff for failed host-discovery probes
Start at 15s and double up to the existing 5-minute negative TTL, and
clear the backoff on auth refresh (rememberGlabKnownHosts), successful
probes and forced preflight resets so recovered auth is seen promptly.
Keeps the positive host cache shape unchanged.
---------
Co-authored-by: Neil <neil@stably.ai>
* feat(ci): ratchet raw repo connectionId host reads; one drop-in resolver
Codex review 6 class fix (#4/#6/#7): host decisions read off a repo row's
legacy connectionId miss rows that name SSH only as executionHostId.
- getRepoRoutingConnectionId (shared/execution-host.ts): drop-in for a raw
repo.connectionId routing check that also finds executionHostId-only SSH.
- check-repo-host-read-ratchet: per-file count of raw repo connectionId
reads in src/main, src/shared, src/cli; counts may only shrink.
- Migrated 66 cheap reads: runtime GitHub/GitLab commands, PR/MR head ref
fetches, preserved-branch cleanup, ref queries, base-ref IPC, worktree
preparation, trash sweep, scan cache TTL, usage metadata.
* fix(ipc): PR base IPC routes executionHostId-only SSH rows; ratchet is a stated lower bound
Review follow-up (Opus on #31096):
- worktrees:resolvePrBase decided git/gh routing on the raw connectionId while
its head-ref fetches already used the resolver; one resolved connectionId
now drives all of it (test fails on main).
- getRepoRoutingConnectionId's contract is stated exactly: never local when the
raw field is set; on a contradictory ssh row executionHostId wins.
- The ratchet regex no longer matches report.connectionId; header and docs
say it is a lower bound.
- Regression tests for a runtime GitHub and GitLab command site.
* test(ci): pin the repo host-read ratchet step to the static phase
* fix(ci): repo host-read ratchet skips verbatim field copies into projected rows
A copy of connectionId into a projected row decides nothing; migrating it to
the resolver would change what the projection publishes. The sidebar feed
catalog's copy (added after the baseline) and two older projections no longer
count; baseline pruned to 91.
* refactor(providers): delete the SSH git and filesystem providers and relay-only wiring
* refactor(ssh): drop relay-protocol exports only the deleted stream readers used
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
Extract subprocess execution and process contracts into @orca/process-host with explicit public entry points, independent checks, and one Node 18 compatible CommonJS runtime. Migrate application consumers and integrate package builds, dependency selection, import enforcement, and runtime resource staging.
Preserve daemon startup ownership and profile isolation, and qualify development rebuild recovery and concurrent output publication. Remove unnecessary aliases, test forwarding exports, and a duplicate output scan.
Validation: full typechecks, changed-code quality, package and artifact checks, native Windows builds/types plus 306 runtime tests, and independent native reviews.
Matched full E2E controls on original main and unchanged reviewed head both pass all 17 applicable tests (nine skips). Earlier intermittent E2E failures are documented in the PR; no assertions were weakened. The final combined-tree audit preserves both branches with no import-boundary violations.