Repository navigation
perf(ipc): forward session:screen only to a renderer that leased it - #1236
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#762. session:screen was 93% of recorded IPC bytes and nothing live reads it: main does its own prompt delivery, paste confirmation and readiness from the screen, the composer picker is owned by the conditions channel, and the Enter-baseline ref and renderer paste helpers were dead. See docs/plans/2026-09-25-screen-ipc-interest.md. - Main: the forwarder sends a frame only while some renderer holds a lease (sessions/screenInterest.ts), and records every frame in a bounded screen-tail history (shared/debug/screenTail.ts). Main's raw snapshot processing and gate are unchanged. - Leases: session:screen-lease seeds the current screen down the ordinary path; leases belong to the calling webContents and drop on a main-frame reload or destroy. - Debug bundles read session:get-screen-debug (latest raw screen and history). DebugPanel and the three screen-reading dev modules hold a lease while open (useScreenLease). - Renderer: the screen handler applies only the screen strings (no picker). latestScreenRef, claudePaste.ts and ComposerSubmitIo.getScreen are deleted as dead code. Fail-first: the recorded Claude 2.1.278 frame is forwarded with no lease on origin/main. Mutations killed: gate removed, history recorded only for leased frames, lease dropped on a sub-frame navigation, seed removed, picker write restored. Fixes #762 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Juliusolsson05
added a commit
that referenced
this pull request
Sep 25, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> # Conflicts: # src/renderer/src/workspace/hook/ipc/useIpcSubscriptions.ts
…paste chain Review of #1236: - C2: a same-document (hash/history) main-frame navigation no longer drops a renderer's screen leases, matching workflows.ts's identical per-renderer lease contract. - C1: the debug-bundle consumer seam is tested end to end: the real assembleAndSaveDebugBundle with window.api as the only mock saves main's tail history and screen; buildStateSnapshot prefers main's screen; the get-screen-debug handler answers snapshot plus history. M1, M2 and M20 now fail. - C3/C4/C5: the history records `recent` (not `plain`); a recent-only frame applies; the lease seed carries the exact aliased payload. M18, M15 and M19 now fail. - C6 plus cleanup: the whole awaitClaudePastePlaceholder chain (preload API, IPC handler, manager and session methods, AgentSession optional) had no caller, the same dead cluster as the deleted claudePaste.ts; removed, and the comments that pointed at claudePaste.ts corrected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n release - Leases no longer drop on did-start-navigation. Chromium reports it before the throttle where the app window blocks every will-navigate, so a blocked stray link click dropped every lease of a page that never changed, and an open debug panel went stale (review B's suspicion). The preload mints one id per loaded document; a lease from a new id drops the old document's leases, order-independently. Only destroy drops otherwise. - Pins round-1 survivors: a release for a session the owner does not hold cannot cancel another owner's lease (J), the release handler acts for its caller (A), and a lease on a session with no screen sends no empty frame (E). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… lease Steering q15: with leases keyed to the document, a reloaded page that never opened a debug panel took no lease, so the old page's leases kept the heaviest IPC stream forwarding until the window closed. The preload now announces its document id on every load (session:screen-document), which retires an earlier document's leases at once. Blocked navigations still drop nothing, and a dead page's late release still cannot touch the new page's lease. Messages from one renderer arrive in order, so the announcement lands after the old page's last message and before the new page's first lease. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
Author
Review disposition (2 rounds: Codex A, Claude B, Pi C; plus steering)
All round-2 verdicts are MERGE. CI is green on |
Juliusolsson05
added a commit
that referenced
this pull request
Sep 25, 2026
…nce rule Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Juliusolsson05
added a commit
that referenced
this pull request
Sep 25, 2026
…ocess restore size, view size carried to a successor - A2: the attach count now outlives the process, so a renderer that reloads or crashes without its leaf cleanup pinned a count forever. The IPC layer keeps each renderer page's attaches and releases them when the renderer is destroyed or loads a new document (the #1236 screen-lease lifecycle); a late detach from a dead page cannot take the new page's reference. This also covers #1283 item 3. - A1/B: the restore size belongs to the process that had it; it is dropped with the process and recaptured (the natural size) for a successor started under an attached view, so a detach no longer shrinks a live successor to the dead one's size. - A3: a successor under an attached view starts at the view's last size instead of 120x40, since the mounted xterm's size cache never re-sent it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #762
The plan is the first commit:
docs/plans/2026-09-25-screen-ipc-interest.md.Why
session:screenwas 93% of recorded IPC bytes. Recording g00000190 has 16,728 frames of about 8.8 KB over 123 minutes, and the committed fixtureworktree-live-attribution/codex-live-channel-gap.jsonhas 2,358 screen frames among about 12,600 events. Every frame was structured-cloned and committed into the renderer runtime map.A full consumer map (below) shows that nothing live needs these frames.
Consumer map (why each is safe)
session.snapshotScreen()(providers/*/runtime/promptDelivery.ts)sessionManager.tslastScreenSnapshot,ScreenFrameGateapplyConditionSnapshot(claude.slash-picker)latestScreenRefEnter baselineuseComposerKeybinds.ts→getScreencomposerSubmitread it (#855). DeletedclaudePaste.tshelpersCLAUDE_PASTE_THRESHOLDnow imported from@shared/claude/pasteConfirm)useScreenLease)saveDebugBundle.tssession:get-screen-debug: main's latest raw screen plus the tail historyrenderTrace.recordScreenTailSnapshotshared/debug/screenTail.ts); same bundle filesRemoteServertaps mainipc/session.ts,ipc/sessionRouting.tsLease contract
session:screen-leaseacquires a lease and seeds the current screen as one ordinarysession:screenevent, so an idle backend still shows a correct panel.session:screen-releasereleases it. A release the owner does not hold is ignored.destroyeddrops all of that owner's leases, because a dying renderer never runs its cleanup. A leaked lease costs bytes, never correctness.Evidence
image-absorption/wrapped-image-pill-2026-09-21.json), the "unleased frame is not forwarded" assertion fails on a cleanorigin/main(expected [ Array(1) ] to deeply equal []) and passes here.screenInterest.test.ts(counting across owners, foreign release,dropOwner),screenTail.test.ts,useScreenLease.renderer.test.tsx, the forwarder recorded-frame test, and the IPC lease seed plus reload/destroy test.tsc -bclean. Full suite: 6,740 of 6,742 pass. The one failure,workflows/control.system.test.ts(a 5 s timeout), fails identically on cleanorigin/mainlocally, while main's CI is green; it is local environment.Not verified
The live app (house rule). The IPC byte reduction is inferred from the gate, not re-measured in a running app.
🤖 Generated with Claude Code