mirror of
https://github.com/stablyai/orca.git
synced 2026-10-23 00:03:52 +00:00
test(serve): pin zero duplicate agent resumes across headless serve desktop promotion (#12666)
STA-1716 reported that a packaged `orca serve` could become the single-instance owner after the desktop app exits, leaving Dock/Finder unable to restore a window — and that forcing a reopen made the headless process hydrate a renderer that interrupted and DUPLICATED live agent sessions. Verification against main found every criterion already fixed (#8646 for desktop promotion and the fail-closed CLI, #12212 for duplicate serve activation, #12574 + #9729 for the resume/ownership guards). The genuine gap was criterion 6: the ticket's own automated regression never existed. An existing reliability gate asserted PTY identity survives promotion, but nothing asserted what the incident was actually about — how many agents the promoted renderer resumes. This adds that coverage: a unit/service-level journey that drives the real single-instance lock, activation gate, settle and focus paths, then runs the real resume logic against a store seeded as a renderer freshly mounted inside the serve process, asserting zero duplicate resumes. `settleServeDesktopActivation` moved from `index.ts` into its own module with identical semantics, so the test drives the real decision rather than re-implementing it — the earlier repro had to mirror that logic locally, which is the "test passes without running the scenario" failure mode. Proven to be a real oracle: breaking each guard individually turns it red, and reverting the pre-#12574 pane form reproduces the incident exactly (two duplicate `codex resume` tabs).
This commit is contained in:
+7
-6
@@ -174,7 +174,10 @@ import {
|
||||
} from './startup/startup-diagnostics'
|
||||
import { ensureWindowsUserDataAclGrant } from './startup/windows-user-data-acl'
|
||||
import { shouldQuitWhenAllWindowsClosed } from './startup/window-all-closed-quit-policy'
|
||||
import { createServeDesktopActivationGate } from './startup/serve-desktop-activation'
|
||||
import {
|
||||
createServeDesktopActivationGate,
|
||||
settleServeDesktopActivation as settleServeDesktopActivationGate
|
||||
} from './startup/serve-desktop-activation'
|
||||
import { RateLimitService } from './rate-limits/service'
|
||||
import { readMiniMaxSessionCookie } from './minimax/minimax-cookie-store'
|
||||
import { getInitialClaudeRateLimitTarget } from './rate-limits/claude-rate-limit-target'
|
||||
@@ -630,11 +633,9 @@ function getDesktopWindowStatus(): RuntimeDesktopWindowStatus {
|
||||
}
|
||||
|
||||
function settleServeDesktopActivation(): void {
|
||||
if (getLocalPtyProvider() instanceof LocalPtyProvider) {
|
||||
desktopActivationGate.markBlocked('persistent PTY provider unavailable')
|
||||
return
|
||||
}
|
||||
desktopActivationGate.markReady()
|
||||
settleServeDesktopActivationGate(desktopActivationGate, {
|
||||
hasPersistentPtyProvider: !(getLocalPtyProvider() instanceof LocalPtyProvider)
|
||||
})
|
||||
}
|
||||
|
||||
// Why: webContents-scoped auto-expiring flag so an intent can't leak to a later renderer load; `consume` clears on match for one-shot signals.
|
||||
|
||||
@@ -9,6 +9,24 @@ export type ServeDesktopActivationGate = {
|
||||
markBlocked: (reason: string) => void
|
||||
}
|
||||
|
||||
export const SERVE_DESKTOP_ACTIVATION_BLOCKED_REASON = 'persistent PTY provider unavailable'
|
||||
|
||||
/**
|
||||
* Why: promotion is only safe when serve owns daemon-backed (persistent) PTYs —
|
||||
* the desktop renderer then reattaches the surviving sessions instead of
|
||||
* cold-restoring them. Without that provider, fail closed (#8457).
|
||||
*/
|
||||
export function settleServeDesktopActivation(
|
||||
gate: ServeDesktopActivationGate,
|
||||
options: { hasPersistentPtyProvider: boolean }
|
||||
): void {
|
||||
if (!options.hasPersistentPtyProvider) {
|
||||
gate.markBlocked(SERVE_DESKTOP_ACTIVATION_BLOCKED_REASON)
|
||||
return
|
||||
}
|
||||
gate.markReady()
|
||||
}
|
||||
|
||||
export function createServeDesktopActivationGate(options: {
|
||||
initialState: 'initializing' | 'ready'
|
||||
activateWindow: () => void
|
||||
|
||||
Reference in New Issue
Block a user