mirror of
https://github.com/stablyai/orca.git
synced 2026-10-23 08:03:39 +00:00
test(serve): strengthen renderer containment contract
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"updatedAt": "2026-08-20",
|
||||
"updatedAt": "2026-08-23",
|
||||
"policy": {
|
||||
"maturityLevels": ["experimental", "soak", "blocking", "accepted-gap", "deprecated"],
|
||||
"blockingPromotion": {
|
||||
@@ -2361,6 +2361,82 @@
|
||||
],
|
||||
"demotionRule": "Demote if a reload revision settles more than once, a stale document or competing window can publish, a timer survives settlement, desktop failure stays indefinitely reloading, headless fallback returns after successful promotion, or either isolated Electron journey loses runtime or PTY identity."
|
||||
},
|
||||
{
|
||||
"id": "runtime.headless-renderer-process-containment",
|
||||
"title": "Headless renderer process death stays isolated from runtime-owned PTYs",
|
||||
"maturity": "experimental",
|
||||
"protection": "partial",
|
||||
"owner": "runtime-platform",
|
||||
"layer": "electron-process-containment",
|
||||
"surfaces": ["headless orca serve", "offscreen browser page", "daemon-backed PTYs"],
|
||||
"platforms": ["macos", "linux", "windows"],
|
||||
"providers": ["local", "daemon"],
|
||||
"coveredPlatforms": ["macos"],
|
||||
"coveredProviders": ["local", "daemon"],
|
||||
"coverageNotes": "An isolated headless serve host creates two daemon-backed terminal sessions and one offscreen browser renderer. Exact WebContents and OS-process fencing prevents a fault from reaching an unrelated process. The oracle is host-local and does not claim paired-viewer continuity, renderer reload, systemd cgroup restart persistence, SSH or WSL coverage, or aggregate memory policy.",
|
||||
"motivatingLinks": [
|
||||
"https://linear.app/stably/issue/STA-5228",
|
||||
"https://github.com/stablyai/orca/issues/16084",
|
||||
"https://github.com/stablyai/orca/pull/16120"
|
||||
],
|
||||
"invariant": "Killing one exact offscreen Chromium renderer cannot replace or terminate the headless main process, runtime, daemon, or unrelated daemon-backed PTYs. The host session inventory retains each original tab-to-PTY binding, and both original PTY processes continue accepting input.",
|
||||
"oracle": "Start an isolated headless serve runtime with zero initial BrowserWindows, create two daemon-backed terminal fixtures, and record main, runtime, daemon, tab, PTY, fixture-process, WebContents, and renderer-process identities. Fence one marked offscreen page by WebContents, URL, and OS process, force that renderer to crash, and require its original process to die while main/runtime/daemon identities, both host tab-to-PTY bindings, and I/O through both original fixture processes remain unchanged.",
|
||||
"commands": [
|
||||
"pnpm exec electron-vite build --mode e2e",
|
||||
"SKIP_BUILD=1 pnpm exec playwright test tests/e2e/headless-serve-renderer-kill-retention.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1"
|
||||
],
|
||||
"testFiles": ["tests/e2e/headless-serve-renderer-kill-retention.spec.ts"],
|
||||
"assertionRefs": [
|
||||
{
|
||||
"file": "tests/e2e/headless-serve-renderer-kill-retention.spec.ts",
|
||||
"assertions": [
|
||||
"the exact original renderer process dies after the fenced WebContents fault",
|
||||
"main, runtime, and daemon identities remain unchanged and reachable",
|
||||
"both original host tab-to-PTY bindings remain published",
|
||||
"both original PTY processes accept post-fault input"
|
||||
]
|
||||
}
|
||||
],
|
||||
"evidenceRuns": [
|
||||
{
|
||||
"date": "2026-08-23",
|
||||
"runner": "local",
|
||||
"platform": "macos",
|
||||
"command": "SKIP_BUILD=1 pnpm exec playwright test tests/e2e/headless-serve-renderer-kill-retention.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1",
|
||||
"result": "passed",
|
||||
"durationSeconds": 31,
|
||||
"summary": "The exact offscreen renderer process died while the headless main process, runtime, daemon, both original host tab-to-PTY bindings, and both original PTY processes remained live; both PTYs accepted post-fault input."
|
||||
}
|
||||
],
|
||||
"runtimeBudget": {
|
||||
"p95Seconds": 60,
|
||||
"scope": "one isolated headless Electron host, one offscreen renderer fault, and two daemon-backed PTY fixtures"
|
||||
},
|
||||
"flakeHistory": {
|
||||
"status": "unknown",
|
||||
"evidence": "Fresh local macOS runs are green; CI and cross-platform soak history are not yet available."
|
||||
},
|
||||
"redGreenEvidence": {
|
||||
"status": "partial",
|
||||
"evidence": "The byte-identical oracle passes on reported v1.4.184 and current main, falsifying renderer-only death as the cause of runtime/session loss. The candidate adds characterization coverage only; reverting it removes the oracle without changing product behavior."
|
||||
},
|
||||
"performanceBudget": {
|
||||
"required": false,
|
||||
"evidence": "The change adds test and gate metadata only. Production startup, fault handling, session inventory, and PTY hot paths are unchanged."
|
||||
},
|
||||
"promotionCriteria": [
|
||||
"Pass the changed-spec Ubuntu/Xvfb PR lane.",
|
||||
"Collect at least 100 consecutive CI or soak passes or 14 days without an unexplained flake.",
|
||||
"Add Windows containment evidence if Electron process behavior diverges."
|
||||
],
|
||||
"knownGaps": [
|
||||
"The fault is an exact WebContents renderer crash, not kernel OOM victim selection or systemd cgroup failure.",
|
||||
"The host-local runtime client proves control-plane reachability but not a separate paired viewer, reconnect, or replay path.",
|
||||
"The test does not require the crashed browser surface to recover; browser-page recovery is a separate lifecycle contract.",
|
||||
"SSH, WSL, folder-workspace, multi-client, mixed-version, and whole-service restart journeys are uncollected; no production or wire behavior changes in this gate."
|
||||
],
|
||||
"demotionRule": "Demote if the exact renderer fault changes main/runtime/daemon identity, removes either tab-to-PTY binding, replaces either fixture process, loses post-fault PTY I/O, or cannot identify the killed renderer unambiguously."
|
||||
},
|
||||
{
|
||||
"id": "runtime.websocket-heartbeat-cadence",
|
||||
"title": "Runtime WebSockets enter an owned shared heartbeat cadence",
|
||||
|
||||
@@ -7,6 +7,7 @@ import { expect, test } from './helpers/orca-app'
|
||||
import {
|
||||
createHostCliTerminal,
|
||||
proveSameLivePty,
|
||||
readHostTerminalInventory,
|
||||
writeRetentionFixture
|
||||
} from './helpers/host-created-terminal-retention-oracle'
|
||||
import { launchHeadlessPairedRuntimeHost } from './helpers/headless-paired-runtime-host'
|
||||
@@ -114,6 +115,9 @@ test('STA-5228 renderer death keeps headless runtime and PTYs alive', async ({ t
|
||||
)
|
||||
await proveSameLivePty(call, terminalA, 'BEFORE_RENDERER_KILL_A')
|
||||
await proveSameLivePty(call, terminalB, 'BEFORE_RENDERER_KILL_B')
|
||||
const beforeInventory = await readHostTerminalInventory(call, worktreeId)
|
||||
expect(beforeInventory.ptyIdByTabId[terminalA.tabId]).toBe(terminalA.ptyId)
|
||||
expect(beforeInventory.ptyIdByTabId[terminalB.tabId]).toBe(terminalB.ptyId)
|
||||
|
||||
const pageId = `sta-5228-${Date.now()}`
|
||||
const markerUrl = `data:text/html,${encodeURIComponent(
|
||||
@@ -212,13 +216,11 @@ test('STA-5228 renderer death keeps headless runtime and PTYs alive', async ({ t
|
||||
expect(await processIdentityIsAlive(daemonIdentity)).toBe(true)
|
||||
await proveSameLivePty(call, terminalA, 'AFTER_RENDERER_KILL_A')
|
||||
await proveSameLivePty(call, terminalB, 'AFTER_RENDERER_KILL_B')
|
||||
const afterInventory = await readHostTerminalInventory(call, worktreeId)
|
||||
expect(afterInventory.ptyIdByTabId[terminalA.tabId]).toBe(terminalA.ptyId)
|
||||
expect(afterInventory.ptyIdByTabId[terminalB.tabId]).toBe(terminalB.ptyId)
|
||||
|
||||
const afterRenderer = await readOffscreenRenderer(launchedHost.app, pageId, false)
|
||||
expect(afterRenderer).toMatchObject({
|
||||
crashed: true,
|
||||
pid: 0,
|
||||
webContentsId: renderer.webContentsId
|
||||
})
|
||||
console.log('[STA-5228] renderer lifecycle snapshot', {
|
||||
afterRenderer,
|
||||
beforeRenderer: renderer,
|
||||
|
||||
Reference in New Issue
Block a user