Files
orca/tests/e2e/terminal-split-activation-latency-report.unit.test.ts
Neil c558d7e083 Activate terminal splits before inherited CWD resolution (#17601)
* perf(terminal): activate splits before cwd resolution

* test(terminal): prove split focus before cwd publish

* fix(terminal): release stale split cwd fence

* test(terminal): add visible split activation latency benchmark

* docs(reliability): clarify split benchmark provenance

* fix: preserve deferred split handoffs across remounts

* fix: fence late deferred split closes

* docs(reliability): record exact split benchmark runs

* test(reliability): fail benchmark on artifact write errors

* test(reliability): attribute split activation phases

* docs(reliability): record schema-v2 split benchmark

* refactor(terminal): collapse duplicated split-handoff and write-queue paths

- Drop the discardDeferredSplitPaneHandoff alias for its identical clear twin.
- Fold the deferred-cwd resolve/reject settle handlers into one applier.
- Extract settlePaneCwdDeferredSpawn for the repeated read-clear-write pattern.
- Share one head-index FIFO primitive between the ordinary and reply queues.

* fix(terminal): stop retaining a promise reaction per acknowledged write

Racing every accepted write against one queue-lifetime cancel promise kept a
reaction record alive until that promise settled: 200k acknowledged writes
retained 88.6MB, now 0.1MB. Give each in-flight write its own cancel, and
split the shared FIFO primitive into its own module.

Also sanitize the split-latency benchmark report at its single serialization
point so shared artifacts no longer carry the machine-local repo path or
unbounded cleanup error text.

* fix(terminal): settle deferred split input when the spawn is abandoned

An abandoned deferred spawn returns before transport.connect(), so nothing
drained the pre-connect buffer: sendInputAccepted's promise never settled and
a paste into that pane hung forever. Clear the buffer on the abandon fence.

Also re-derive the pre-connect retention cap from the clipboard-paste ceiling
rather than the 16MB single-write ceiling; it is held twice per pane across up
to 64 deferred splits, so 5.59M code units guarded the wrong thing.

* fix(terminal): release the deferred cwd fence on a rejected reattach

A daemon createOrAttach can turn an apparent fresh spawn into a reattach; when
that reattach is refused the spawn ends with deferredSplitSpawn/pendingCwd
still set, permanently arming the pre-bind detach refusal. The release no-ops
when a PTY did bind, so it only fires where the fence would otherwise leak.

The stale-generation return above is deliberately left alone: a newer connect
already owns the pane there, and the fence is not generation-scoped.
2026-08-31 16:45:36 -07:00

193 lines
5.3 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { buildBenchmarkReport, summarizeSamples } from './terminal-split-activation-latency-report'
import {
createSplitLatencySample,
mergeSplitLatencyMainProbeEvents,
type RendererPhaseStamps,
type SplitLatencyMainProbeEvent
} from './terminal-split-activation-latency-phases'
function createRendererStamps(): RendererPhaseStamps {
return {
marker: 'echo-marker',
sourcePaneId: 1,
sourcePtyId: 'pty-source',
newPaneId: 2,
newPtyId: 'pty-child',
rendererTimeOriginEpochMs: 1_000,
keydownAtMs: 10,
focusAtMs: 20,
cwdRequestAtMs: null,
cwdSettledAtMs: null,
ptySpawnRequestAtMs: null,
ptySpawnResultAtMs: null,
ptyBoundAtMs: 82,
fixtureUnlockRequestedAtMs: 83,
fixtureUnlockIpcWriteAtMs: null,
fixtureUnlockIpcWriteChannel: null,
fixtureReadyParsedAtMs: 100,
inputAtMs: 101,
firstEchoAtMs: 103
}
}
function createMainProbeEvents(): SplitLatencyMainProbeEvent[] {
return [
{
kind: 'cwd-request',
operationId: 99,
atEpochMs: 1_010,
ptyId: 'pty-other',
writeChannel: null
},
{
kind: 'cwd-request',
operationId: 1,
atEpochMs: 1_011,
ptyId: 'pty-source',
writeChannel: null
},
{
kind: 'cwd-settled',
operationId: 1,
atEpochMs: 1_060,
ptyId: 'pty-source',
writeChannel: null
},
{
kind: 'pty-spawn-request',
operationId: 2,
atEpochMs: 1_061,
ptyId: null,
writeChannel: null
},
{
kind: 'pty-spawn-result',
operationId: 3,
atEpochMs: 1_070,
ptyId: 'pty-other',
writeChannel: null
},
{
kind: 'pty-spawn-result',
operationId: 2,
atEpochMs: 1_080,
ptyId: 'pty-child',
writeChannel: null
},
{
kind: 'pty-write-cr',
operationId: null,
atEpochMs: 1_081,
ptyId: 'pty-other',
writeChannel: 'pty:write'
},
{
kind: 'pty-write-cr',
operationId: null,
atEpochMs: 1_084,
ptyId: 'pty-child',
writeChannel: 'pty:writeAccepted'
}
]
}
describe('terminal split activation latency report', () => {
it('attributes main-process phases to the matching source and child PTYs', () => {
const stamps = mergeSplitLatencyMainProbeEvents(createRendererStamps(), createMainProbeEvents())
const sample = createSplitLatencySample({
phase: 'measured',
iteration: 0,
stamps,
completedWithinTimeout: true,
paneCountAfterProbe: 2,
ptyExitObserved: true,
cleanupError: null
})
expect(sample).toMatchObject({
cwdRequestAtMs: 11,
cwdSettledAtMs: 60,
ptySpawnRequestAtMs: 61,
ptySpawnResultAtMs: 80,
fixtureUnlockIpcWriteAtMs: 84,
fixtureUnlockIpcWriteChannel: 'pty:writeAccepted',
shortcutToCwdRequestMs: 1,
cwdLookupMs: 49,
cwdSettleToPtySpawnRequestMs: 1,
ptySpawnRequestToResultMs: 19,
ptySpawnResultToBindMs: 2,
fixtureUnlockRequestToIpcWriteMs: 1,
fixtureUnlockIpcWriteToReadyParseMs: 16,
success: true,
missing: []
})
})
it('embeds revision identity and summarizes the attributed phases', () => {
const stamps = mergeSplitLatencyMainProbeEvents(createRendererStamps(), createMainProbeEvents())
const sample = createSplitLatencySample({
phase: 'measured',
iteration: 0,
stamps,
completedWithinTimeout: true,
paneCountAfterProbe: 2,
ptyExitObserved: true,
cleanupError: null
})
const revision = { headSha: 'a'.repeat(40), dirty: false }
const result = buildBenchmarkReport({
label: 'candidate',
revision,
headfulRun: true,
windowState: { browserWindowVisible: true, windowCount: 1 },
documentVisibility: 'visible',
testRepoPath: '/tmp/repo',
warmupSamples: [{ ...sample, phase: 'warmup' }],
measuredSamples: [sample],
abortError: null,
config: {
warmupCycles: 1,
measuredCycles: 1,
maxMeasuredCycles: 200,
testTimeoutMs: 30_000,
splitChord: 'Meta+d',
closeChord: 'Meta+w',
sampleTimeoutMs: 15_000,
cleanupTimeoutMs: 15_000,
processCwdCacheExpiryWaitMs: 1_650
}
})
expect(result.report).toMatchObject({
schemaVersion: 2,
revision,
status: 'passed',
valid: true
})
expect(result.measuredSummary.distributions.cwdLookupMs.p50).toBe(49)
expect(result.measuredSummary.distributions.ptySpawnRequestToResultMs.p50).toBe(19)
expect(result.measuredSummary.distributions.fixtureUnlockIpcWriteToReadyParseMs.p50).toBe(16)
})
it('invalidates a sample when the actual fixture-unlock IPC write is missing', () => {
const stamps = mergeSplitLatencyMainProbeEvents(
createRendererStamps(),
createMainProbeEvents().filter((event) => event.kind !== 'pty-write-cr')
)
const sample = createSplitLatencySample({
phase: 'measured',
iteration: 0,
stamps,
completedWithinTimeout: true,
paneCountAfterProbe: 2,
ptyExitObserved: true,
cleanupError: null
})
expect(sample.success).toBe(false)
expect(sample.missing).toContain('fixture-unlock-ipc-write')
expect(summarizeSamples([sample], 1).counts.missingEvents.fixtureUnlockIpcWrite).toBe(1)
})
})