spec: render inline image protocols at shell startup (#10020)#10126
Open
lonexreb wants to merge 1 commit intowarpdotdev:masterfrom
Open
spec: render inline image protocols at shell startup (#10020)#10126lonexreb wants to merge 1 commit intowarpdotdev:masterfrom
lonexreb wants to merge 1 commit intowarpdotdev:masterfrom
Conversation
Adds product.md + tech.md for issue warpdotdev#10020: inline image-protocol escape sequences (Kitty graphics, iTerm2 inline image) emitted from shell init files (~/.zshrc, etc.) are silently dropped. The same bytes typed manually post-prompt render correctly. Investigation traces the drop to the block-level delegate! macro (app/src/terminal/model/block.rs:2882): when the active block is in BlockState::BeforeExecution (which covers the entire ScriptExecution bootstrap stage and the post-prompt early-output window), image-protocol completions are routed to header_grid instead of output_grid. The header_grid is the prompt area and its image placement is not rendered in the visible block body. The reporter's background-subshell test case (`( sleep 0.2 && fastfetch ) &!`) hits the same branch via a different session phase, which is why deferring past the first prompt does not help. Spec proposes a fix at the block-level delegate (not BlockList, not GridHandler) with explicit reasoning against the alternatives. Carves out the WarpInput hidden bootstrap block so Warp's own bootstrap-script bytes never accidentally render. Adds warn-level telemetry on every silent-drop path so this class of bug regresses noisily, not silently. Test plan covers four unit cases (BlockState routing) and six integration cases (per-stage byte-feed end-to-end), including a negative-space test that the WarpInput stage continues to drop and a feature-flag-off regression guard. Three open questions for maintainer review on macro naming, telemetry level, and whether the existing bootstrap-stage gates at blocks.rs:3789/3724/3763 are intentional or symptoms of the same family.
Contributor
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.
Summary
Spec for issue #10020 — inline image-protocol escape sequences (Kitty graphics, iTerm2 inline image) emitted from shell init files (
~/.zshrc,~/.bashrc, etc.) are silently dropped, while the same bytes typed manually after the prompt render correctly. Other terminals (iTerm2, WezTerm, Kitty, Ghostty) render images at shell startup as documented in their respective protocol specs.Investigation
Traced the routing end-to-end:
TerminalModel::handle_completed_iterm_image(terminal_model.rs:3354) →delegate!→BlockList.BlockList::handle_completed_iterm_image(blocks.rs:3794) →delegate_to_block!→ active block (intentionally bypasses the early-output gate).Block::handle_completed_iterm_image(block.rs:3292) → block-leveldelegate!(block.rs:2882).delegate!routes toheader_gridwhenstate == BlockState::BeforeExecution. Theheader_gridis the prompt area; its image placement is not rendered in the visible block body.BeforeExecutionand image bytes land inoutput_grid, which renders. This is why typing the same command works.The reporter's background-subshell case (
( sleep 0.2 && fastfetch ) &!) hits the same branch via a different session phase: the post-prompt block is itself inBeforeExecutionwaiting for the user's first keystroke, so background output emitted during theis_early_output()window is also routed toheader_grid.What's in the spec
product.md— 7 testable behavior invariants (B1–B7), 6 acceptance criteria (A1–A6), explicit non-goals, and a preserved record of the reporter's diagnostic facts (verified byte sequences, alternative approaches that were tried and ruled out).tech.md— picks the fix site with explicit reasoning against the two alternatives, names every file and line range touched, and lays out four unit tests + six integration tests (including a negative-space test for theWarpInputhidden bootstrap block and a feature-flag-off regression guard).Architectural choices
delegate!macro, not atBlockListand not atGridHandler. Rationale:BlockListdoes not know aboutheader_gridvsoutput_grid; pushing the routing decision up would leak grid identity.GridHandleris downstream of the routing decision; pushing it down would require a redirect message back up. The block-leveldelegate!is exactly where the (state, grid) routing decision belongs.BootstrapStage::WarpInput. Warp's own injected bootstrap-script bytes must never accidentally render an image even after the fix.Test plan
block_test.rs— verify routing perBlockStatevalue and perbootstrap_stage.image_protocol_at_startup_test.rs(new file) — feed the exact byte sequences from the issue at each session phase, assertEvent::ImageReceiveddispatch and grid placement.~/.zshrcwith--logo-type kitty-direct(A1),--logo-type iterm(A2), and the background-subshell variant (A3).fastfetchcontinues to render (A4 regression guard).FeatureFlag::ITermImagesdisabled produces no render and no warn-level log noise (A5 + B7).Open questions for maintainer review
delegate_image_completion!(sibling macro) or a boolean parameter on the existingdelegate!?log::warn!vslog::debug!+ a separate metric?blocks.rs:3789(on_reset_grid),3724(precmd), and3763(preexec) are left alone. Confirm they are intentional and not symptoms of the same family.Closes (spec-only) #10020 — implementation PR will follow once spec direction is confirmed.