mirror of
https://github.com/stablyai/orca.git
synced 2026-09-23 00:02:29 +00:00
* 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.
54 lines
1.7 KiB
TypeScript
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 }
|
|
)
|
|
}
|
|
}
|