diff --git a/src/shared/release-channel.test.ts b/src/shared/release-channel.test.ts index a2d66242d93..fb530d66347 100644 --- a/src/shared/release-channel.test.ts +++ b/src/shared/release-channel.test.ts @@ -324,4 +324,24 @@ describe('release channel', () => { '1.4.160-adhoc.20260728090000' ]) }) + + it('sorts dev builds by their cut time across different base versions', () => { + const build = (version: string): ReleaseBuild => ({ + tag: `v${version}`, + version, + channel: 'adhoc', + name: null, + publishedAt: null, + releaseUrl: `https://github.com/stablyai/orca-adhoc/releases/tag/v${version}`, + installerUrl: null + }) + const sorted = sortReleaseBuildsNewestFirst([ + build('1.4.207-adhoc.20260919025813'), + build('1.4.206-adhoc.20260919173504') + ]) + expect(sorted.map((entry) => entry.version)).toEqual([ + '1.4.206-adhoc.20260919173504', + '1.4.207-adhoc.20260919025813' + ]) + }) }) diff --git a/src/shared/release-channel.ts b/src/shared/release-channel.ts index 056152ffcc9..7a7f3aa96b0 100644 --- a/src/shared/release-channel.ts +++ b/src/shared/release-channel.ts @@ -319,5 +319,28 @@ export type ReleaseBuild = { /** Newest first, so the picker's first row is always the channel's current tip. */ export function sortReleaseBuildsNewestFirst(builds: ReleaseBuild[]): ReleaseBuild[] { - return [...builds].sort((left, right) => compareAppVersions(right.version, left.version)) + return [...builds].sort((left, right) => { + // Dev build base versions can move backwards when a branch was cut before + // the latest main build. Their stamped build time, not semver, is the + // meaningful "newest" signal for the picker. + const leftStamp = parseDevBuildStamp(left.version)?.getTime() ?? null + const rightStamp = parseDevBuildStamp(right.version)?.getTime() ?? null + if (leftStamp !== null && rightStamp !== null && leftStamp !== rightStamp) { + return rightStamp - leftStamp + } + + if (hasDedicatedReleaseRepo(left.channel) && hasDedicatedReleaseRepo(right.channel)) { + const leftPublished = left.publishedAt ? Date.parse(left.publishedAt) : Number.NaN + const rightPublished = right.publishedAt ? Date.parse(right.publishedAt) : Number.NaN + if ( + Number.isFinite(leftPublished) && + Number.isFinite(rightPublished) && + leftPublished !== rightPublished + ) { + return rightPublished - leftPublished + } + } + + return compareAppVersions(right.version, left.version) + }) }