Skip to content

fix(terminal): replay cold restores at recovered grid - #9043

Merged
brennanb2025 merged 1 commit into
stablyai:mainfrom
slashdevcorpse:slashdevcorpse/bug-bug-on-windows-upon-returning-session
Jul 18, 2026
Merged

brennanb2025 merged 1 commit into
stablyai:mainfrom
slashdevcorpse:slashdevcorpse/bug-bug-on-windows-upon-returning-session

Conversation

@slashdevcorpse

@slashdevcorpse slashdevcorpse commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Preserve disk cold-restore cols/rows across the daemon provider, IPC/preload, renderer, and main headless terminal.
  • Replay cold ANSI at its recovered grid without forwarding that temporary resize to the fresh PTY.
  • Clear stale viewport cells at the destination grid (CSI 2J + home), await parsing before any recovered-grid shrink can promote clipped rows into scrollback, continue to forbid CSI 3J, blank enough source/immediate-destination rows, then use the existing structural replay barrier and authoritative fit.
  • Keep older dimensionless cold-restore payloads compatible.

This is a cold-restore parity follow-up found while investigating #8751. Runtime evidence indicates the screenshot's immediate warm-reattach race is separately addressed by #8674; this PR does not claim that the cold path alone produced the screenshot or replace #8674.

Screenshots

No visual design change. The failure screenshot and investigation are in #8751.

Testing

  • pnpm lint — full repository lint not run; touched oxlint and oxfmt --check passed
  • pnpm typecheck
  • pnpm test — full repository suite not run; affected 5-file matrix passed with 904 tests / 15 skipped
  • pnpm build — full production/native build not run; the Electron E2E bundle built successfully
  • Added or updated high-quality tests that would catch regressions, or explained why tests were not needed

Commands run:

  • pnpm test -- src/main/daemon/daemon-pty-adapter.test.ts src/main/ipc/pty.test.ts src/renderer/src/components/terminal-pane/pty-connection.test.ts src/renderer/src/lib/pane-manager/terminal-structural-replay-coordinator.test.ts src/renderer/src/components/terminal-pane/pty-transport.test.ts
  • pnpm typecheck
  • pnpm exec electron-vite build --mode e2e
  • touched-file pnpm exec oxfmt --check ...
  • touched-file pnpm exec oxlint ...
  • pnpm run check:max-lines-ratchet
  • git diff --check

The initial regression was red in three focused assertions: missing adapter dimensions, undefined runtime seed dimensions, and no renderer resize to the recovered grid. A strengthened dirty-grid regression then caught a blocker in the first implementation: shrinking from a dirty 10x5 destination to the recovered 20x3 grid before clearing promoted clipped stale rows into scrollback, beyond a later viewport-only clear. Its clear-before-resize ordering assertion failed before the correction and passes after the clear parse barrier. The final five-file matrix passed.

Same-PC Windows Electron verification

The exact PR-head app bundle (877a3c28c04b54037f983c8b25029b7fd95e2cbe) was exercised with disposable user data on the affected Windows PC:

  • clean close/relaunch retained the same daemon PID/session and the restored pane accepted keyboard-path and direct PTY input;
  • daemon-snapshot replay restored the cursor to a shell prompt rather than an older output row;
  • killing the disposable daemon between launches forced disk cold restore, created the replacement PTY, and left the completed restore interactive in isolated repeats.

On the final amended bundle, both warm checks passed and all 3 repeated cold runs that reached the input assertion passed. One serial run began the delayed keyboard probe during the intentional replay guard: PowerShell received only the suffix RED_OK, while direct PTY input already worked before pty:listSessions. Independent trace and code reviews classified this as an E2E replay-readiness race, not a persistent transport or ownership failure. Two further repetitions ended earlier during app setup when navigation destroyed the Playwright execution context; neither reached the cold-input assertion.

The committed E2E drivers assume POSIX Ctrl+U/export PS1, and the cold case is normally skipped on Windows, so only the temporary test driver was adapted; the built application stayed at the exact PR head and all driver edits were restored afterward. The packaged installer/update harness was not run because it correctly refuses while an unrelated Orca app process is active.

AI Review Report

Parallel investigation covered the issue/release history, local Windows runtime chronology, restore-path code tracing, test-first implementation, and independent adversarial diff, external-state, and Windows-runtime reviews.

Main risks checked:

  • A recovered-height shrink can promote dirty destination rows into scrollback; the patch clears and awaits xterm parsing before that structural resize, and the regression preserves pre-existing scrollback sentinels.
  • A full clear would regress Fix Windows ConPTY overlay after cold restore #7310 by erasing restored scrollback; the patch uses viewport-only CSI 2J and tests that CSI 3J is absent.
  • The incident's immediate warm-return mechanism belongs to unreleased fix(terminal): make viewport ownership transactional across output, replay, and reflow #8674; PR and issue wording were narrowed to the independently proven cold-restore gap.
  • Cold dimensions remain optional at public boundaries so older payloads retain their current fallback.
  • Synthetic source-grid resizes are suppressed from PTY forwarding; only the post-replay destination fit reaches the PTY.
  • The main headless emulator uses cold dimensions rather than accidentally borrowing warm snapshot fields.
  • The headless oracle starts from adversarial dirty state and proves stale-content absence, recovered cursor spacing, scrollback retention, reflow, and a clean final viewport.
  • Existing delayed-parse tests cover the shared replay barrier, fit/SIGWINCH gating, and live-byte ordering used by snapshot, replay, and cold restore.

Cross-platform review explicitly covered macOS, Linux, Windows/ConPTY, SSH relay, and remote-runtime behavior. No shortcut, label, path, shell-command, Git-provider, or local-only assumption was added. SSH relay restore remains on its existing replay branch; optional cold metadata is transport-neutral.

Security Audit

No dependency, command execution, filesystem path, auth, secret, network, or new IPC-channel surface was added. The existing internal cold-restore result gains two numeric metadata fields sourced from recovered terminal history. Renderer use requires finite positive dimensions before resizing; legacy/missing values fall back safely. Replay remains under the existing query-response guard so recorded terminal queries cannot write replies into the fresh shell.

Notes

@slashdevcorpse
slashdevcorpse force-pushed the slashdevcorpse/bug-bug-on-windows-upon-returning-session branch 2 times, most recently from 2b65ba4 to 877a3c2 Compare July 16, 2026 18:11
@slashdevcorpse

Copy link
Copy Markdown
Contributor Author

Companion Windows restart-regression PR: #9064.

#9043 contains the product correction; #9064 makes the PowerShell/replay-readiness harness deterministic and adds the targeted Windows gate. They are independently mergeable, but I recommend they go hand in hand. Merge #9064 first so the workflow exists on main, then synchronize or mark #9043 ready so the gate runs on its matching product paths.

@brennanb2025
brennanb2025 marked this pull request as ready for review July 18, 2026 00:19
@coderabbitai

coderabbitai Bot commented Jul 18, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5e99b9d6-6a73-4bfe-98db-badeb1539ef8

📥 Commits

Reviewing files that changed from the base of the PR and between 877a3c28c04b54037f983c8b25029b7fd95e2cbe and 614fafe.

📒 Files selected for processing (5)
  • src/main/daemon/daemon-pty-adapter.test.ts
  • src/main/daemon/daemon-pty-adapter.ts
  • src/main/ipc/pty.test.ts
  • src/main/ipc/pty.ts
  • src/main/providers/types.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/main/providers/types.ts
  • src/main/daemon/daemon-pty-adapter.test.ts
  • src/main/ipc/pty.ts
  • src/main/daemon/daemon-pty-adapter.ts
  • src/main/ipc/pty.test.ts

📝 Walkthrough

Walkthrough

Cold-restore payloads now include optional terminal dimensions across daemon, provider, preload, IPC, and renderer types. Headless terminal seeding uses separate snapshot and cold-restore sizes while retaining compatibility with dimensionless legacy payloads. Renderer replay suppresses structural resize forwarding, clears the destination viewport using calculated row counts, restores recovered dimensions, and replays scrollback with expanded tests.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: replaying cold restores at the recovered terminal grid.
Description check ✅ Passed The description follows the template and includes summary, screenshots, testing, AI review, security audit, and notes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@brennanb2025

Copy link
Copy Markdown
Contributor

Thanks @slashdevcorpse — reviewed this end to end and it's in good shape.

What it does: when the daemon has lost a session and Orca cold-restores a pane from disk-recorded scrollback, that scrollback carries absolute cursor-positioning escapes that only make sense at the grid the session was recorded at. Replaying it at the current pane size garbled restored TUI content. This PR threads the recorded cols/rows from the daemon adapter → IPC/preload → renderer + headless emulator, clears the viewport, then replays at the recovered grid (kept from reaching the fresh PTY) before the authoritative fit resizes back to the real grid. It mirrors the existing snapshot-replay path, so the two restore routes now behave consistently.

Why it holds up:

  • Clears the viewport before the recovered-grid resize, so a shrink can't promote stale rows into scrollback; viewport-only 2J (never 3J) preserves restored scrollback (Fix Windows ConPTY overlay after cold restore #7310).
  • New cols/rows are optional at every boundary with finite/> 0 guards — older dimensionless payloads fall back to prior behavior.
  • suppressSnapshotReplayPtyResize → suppressStructuralReplayPtyResize is a pure rename shared by mutually-exclusive branches; the layout-only resize never SIGWINCHes the fresh PTY.

Verified locally:

  • Affected suite green (919 tests), including a headless-xterm oracle that models the exact op order and asserts the rendered buffer (no stale rows, recovered content kept, clean viewport) plus the legacy dimensionless fallback.
  • Typecheck + lint clean on touched files; perf is a once-per-reattach path with no added polling/leak (the extra await is FIFO-parse-gated, not a delay).
  • Live Electron: warm reattach (window reload) preserves scrollback and grid alignment with no garble — confirming the renamed shared flag doesn't regress the warm path.

The cold path itself is a Windows-restart scenario I couldn't reproduce deterministically on macOS, but it's covered by the real-xterm regression test and your same-PC Windows runs. Per the description, this should land alongside #9064 (merge that first).

@brennanb2025
brennanb2025 force-pushed the slashdevcorpse/bug-bug-on-windows-upon-returning-session branch from 877a3c2 to 614fafe Compare July 18, 2026 01:25
@brennanb2025
brennanb2025 merged commit ad20602 into stablyai:main Jul 18, 2026
8 checks passed
enrick-dev pushed a commit to enrick-dev/orca that referenced this pull request Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants