Files
orca/tests/e2e/terminal-split-activation-latency-artifact.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

54 lines
1.7 KiB
TypeScript

import { writeFileSync } from 'node:fs'
const MAX_ERROR_TEXT_LENGTH = 200
// Absolute POSIX/Windows paths, which routinely appear inside cleanup error text.
const ABSOLUTE_PATH = /(?:[A-Za-z]:\\|\/)[\w.\-\\/]{2,}/g
function redactText(value: unknown): string | null {
if (typeof value !== 'string') {
return null
}
return value.replace(ABSOLUTE_PATH, '<path>').slice(0, MAX_ERROR_TEXT_LENGTH)
}
function redactSamples(samples: unknown): unknown {
if (!Array.isArray(samples)) {
return samples
}
return samples.map((sample) =>
sample && typeof sample === 'object' && 'cleanupError' in sample
? { ...sample, cleanupError: redactText((sample as { cleanupError: unknown }).cleanupError) }
: sample
)
}
/**
* Strips machine-identifying data so a report can be shared verbatim: the seeded
* repo lives under an operator-overridable path, and cleanup/abort text is
* unbounded free-form error output.
*/
export function sanitizeTerminalSplitLatencyReport(
report: Record<string, unknown>
): Record<string, unknown> {
return {
...report,
testRepoPath: '<test-repo>',
abortReason: redactText(report.abortReason),
warmupSamples: redactSamples(report.warmupSamples),
measuredSamples: redactSamples(report.measuredSamples)
}
}
/** Persist the benchmark report so a passing run cannot silently lose its artifact. */
export function writeTerminalSplitLatencyArtifact(outputPath: string, body: string): void {
try {
writeFileSync(outputPath, body, 'utf8')
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
throw new Error(
`[terminal-split-activation-latency] unable to write ${outputPath}: ${message}`,
{ cause: error }
)
}
}