From ae7f30318a5802ff0a1e2063052dd098fd4441b2 Mon Sep 17 00:00:00 2001 From: Jinwoo-H Date: Wed, 12 Aug 2026 22:18:46 -0400 Subject: [PATCH] test(terminal): close scanner ordering gaps --- config/reliability-gates.jsonc | 11 ++++++----- src/main/shell-startup-output-scanner.test.ts | 10 ++++++++++ src/main/shell-startup-output-scanner.ts | 5 +---- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/config/reliability-gates.jsonc b/config/reliability-gates.jsonc index ebb7c20b9a1..3c270c3ebce 100644 --- a/config/reliability-gates.jsonc +++ b/config/reliability-gates.jsonc @@ -54,7 +54,8 @@ "file": "src/main/shell-startup-output-scanner.test.ts", "assertions": [ "Fish bracketed-paste output stays byte-exact across marker and ESC chunk splits", - "identity and readiness markers strip together without reordering prompt output", + "every byte after readiness is preserved across every chunk boundary, even when it resembles an identity marker", + "pre-ready identity and readiness markers strip across every chunk boundary without reordering prompt output", "incomplete scanner prefixes drain in byte order" ] }, @@ -105,8 +106,8 @@ "platform": "macos", "command": "pnpm exec vitest run --config config/vitest.config.ts src/main/daemon/repro-13767-shell-ready-marker-lost-to-exec.test.ts src/main/line-editor-ready-output-scanner.test.ts src/main/shell-startup-identity-scanner.test.ts src/main/shell-startup-output-scanner.test.ts src/main/shell-prompt-readiness-probe.test.ts src/shared/pty-slave-line-discipline-echo.test.ts src/shared/shell-process-readiness.test.ts src/main/daemon/session.test.ts src/main/daemon/shell-ready.test.ts src/main/providers/local-pty-shell-ready.test.ts src/main/providers/local-pty-provider.test.ts src/relay/pty-shell-launch.test.ts src/relay/pty-handler.test.ts", "result": "passed", - "durationSeconds": 4, - "summary": "All real exec, silent-read, line-init-hook, renamed-image, disabled-bracketed-paste, and relay-owner oracles plus identity, foreground, executable-image, protocol, and line-editor contracts passed." + "durationSeconds": 6, + "summary": "473 tests passed with one local Fish skip, including every-boundary scanner composition, real exec, silent-read, line-init-hook, renamed-image, disabled-bracketed-paste, and relay-owner oracles." } ], "runtimeBudget": { @@ -119,11 +120,11 @@ }, "redGreenEvidence": { "status": "complete", - "evidence": "The Fish chunk oracle patch SHA-256 fd49a4d3d91bd5f0d10c1b1f44f4cfbd92cef9155a5505b415c8680184cdc765 is byte-identical across runs. Scan target e4c278eb52, latest main d9b390f4fd, and candidate 1f9715c87b with the fix commit reverted each failed the ESC-introducer split in both local and daemon owners while passing both marker-only splits. Candidate 1f9715c87b passed all four cases plus the independent headless-xterm render oracle. The original exec-readiness oracle SHA-256 b13b08006a38b2adc2acb51ae9342909514e55ab4822fac4fbb76cd49b344cc6 remains 14/14 green." + "evidence": "The Fish chunk oracle patch SHA-256 fd49a4d3d91bd5f0d10c1b1f44f4cfbd92cef9155a5505b415c8680184cdc765 is byte-identical across runs. Scan target e4c278eb52, latest main bc2e30000b, and candidate b19ca10a4c with shared scanner integration disabled each failed only the ESC-introducer split in both local and daemon owners (2 failures, 161 passes). Candidate b19ca10a4c passed all 163 local/daemon cases plus the independent headless-xterm render oracle. The original exec-readiness oracle SHA-256 b13b08006a38b2adc2acb51ae9342909514e55ab4822fac4fbb76cd49b344cc6 remains 14/14 green." }, "performanceBudget": { "required": true, - "evidence": "One bounded composition pass replaces two sequential scanner passes at each owner and retains only the existing bounded prefixes. The normal ready-marker path cancels before external probing. A missing marker triggers a debounced stty read only after a line-editor enable sequence, followed by narrow PID status and executable-image inspection only when termios matches. Slow ordinary startup output triggers zero probes; rejected protocol emissions are capped at four probes per startup. There is no per-command hook or steady-state polling." + "evidence": "Two bounded linear scans partition identity ownership at the exact ready-marker boundary and retain only the existing bounded prefixes. The normal ready-marker path cancels before external probing. A missing marker triggers a debounced stty read only after a line-editor enable sequence, followed by narrow PID status and executable-image inspection only when termios matches. Slow ordinary startup output triggers zero probes; rejected protocol emissions are capped at four probes per startup. There is no per-command hook or steady-state polling." }, "promotionCriteria": [ "Collect Linux, SSH-daemon, and paired-runtime live evidence.", diff --git a/src/main/shell-startup-output-scanner.test.ts b/src/main/shell-startup-output-scanner.test.ts index 80dbfe4f7bf..1a0930b9395 100644 --- a/src/main/shell-startup-output-scanner.test.ts +++ b/src/main/shell-startup-output-scanner.test.ts @@ -108,4 +108,14 @@ describe('shell startup output scanner', () => { expect(drainShellStartupOutputScanState(state)).toBe('\x1b]777;orca-shell-st') }) + + it('drains simultaneous identity and readiness prefixes in input order', () => { + const state = createShellStartupOutputScanState() + expect(scanShellStartupOutput(state, '\x1b]777;orca-shell-st').output).toBe('') + expect(scanShellStartupOutput(state, '\x1b]777;orca-shell-rea').output).toBe('') + + expect(drainShellStartupOutputScanState(state)).toBe( + '\x1b]777;orca-shell-st\x1b]777;orca-shell-rea' + ) + }) }) diff --git a/src/main/shell-startup-output-scanner.ts b/src/main/shell-startup-output-scanner.ts index a0b086865ba..b87626c24eb 100644 --- a/src/main/shell-startup-output-scanner.ts +++ b/src/main/shell-startup-output-scanner.ts @@ -62,10 +62,7 @@ export function scanShellStartupOutput( } export function drainShellStartupOutputScanState(state: ShellStartupOutputScanState): string { - let output = state.identity ? drainShellStartupIdentityHeldBytes(state.identity) : '' + const output = state.identity ? drainShellStartupIdentityHeldBytes(state.identity) : '' state.identity = null - if (output) { - output = scanForShellReadyBoundary(state.ready, output).output - } return output + drainShellReadyHeldBytes(state.ready) }