Skip to content

Stage child-run deep linking in the web session viewer (Phase 0 + spec) - #15317

Draft
warp-agent-staging[bot] wants to merge 6 commits into
masterfrom
factory/quality-1764-preserve-viewer-url
Draft

Stage child-run deep linking in the web session viewer (Phase 0 + spec)#15317
warp-agent-staging[bot] wants to merge 6 commits into
masterfrom
factory/quality-1764-preserve-viewer-url

Conversation

@warp-agent-staging

@warp-agent-staging warp-agent-staging Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Description

This PR combines the approved child-run deep-link specification with the narrow URL-preservation fix as Phase 0.

When a child pill swaps the child pane into focus, both pane focus and a later ManagerEvent::JoinedSession can ask the shared browser URL handler to commit the child's own link. Before Phase 0, that replaced the orchestrator route. Refreshing or copying the address bar then opened the child without its orchestration context.

Phase 0 adds the pure resolve_browser_url() decision and preserves a current /conversation/:id or /session/:id route against non-forced pane URL requests. Both known write paths funnel through this decision. Forced login and signup redirects continue to bypass it.

The approved final design lives in specs/QUALITY-1764/PRODUCT.md and specs/QUALITY-1764/TECH.md:

  • Phase 1 adds permission-aware cold child-to-root canonicalization and ?view=standalone.
  • Phase 2 adds #child=<run-id>, refresh restoration, and Back/Forward selection history.

Phase 0 is deliberately temporary. It fixes the reported bug now, but refreshes and copied links return to the orchestrator with no child selected. Its blanket viewer-route guard suppresses the explicit fragment write Phase 2 needs. Phase 2 must remove or invert that guard before it adds anchor navigation; layering the anchor writer behind the current guard would silently prevent the fragment from appearing.

Linked Issue

Linear: QUALITY-1764

Testing

  • app/src/uri/uri_tests.rs has direct regression coverage for Phase 0's guard through resolve_browser_url():
    • keeps the parent /conversation/... URL when a child pane requests /session/..., and the reverse
    • keeps the parent conversation-view URL when the focused pane has no link
    • uses the requested URL or the base app URL when the current URL is outside the viewer
    • bypasses the guard when force_redirect is set
    • retains the original WebIntent::is_conversation_or_session_view predicate tests
  • cargo nextest run -p warp -E 'test(/^uri::/)' — 78/78 passed.
  • cargo check -p warp --lib and cargo clippy -p warp --all-targets --tests -- -D warnings — clean, no warnings.
  • ./script/wasm/bundle --check-only (cargo check --target wasm32-unknown-unknown) — the warp library, including the WASM-gated URL resolver, type-checks cleanly under WASM.
  • cargo fmt -- --check on the touched files — clean.
  • Spec merge and phase rewrite: git diff --check — clean; no additional code changed.

Visual verification: blocked, not skipped. A dedicated attempt stood up the full local stack needed to exercise the real flow: a local warp-server with Postgres, Redis, and Temporal; non-destructive fixture seeding; the Warp client built for WASM with with_local_server; and the classic web shell serving /app and /conversation/:id. Opening it in a real browser reached Warp's real sign-in screen. The environment had no guest/anonymous browser path, real Warp test-account credentials, or supported non-UI way to mint a valid local browser session. Therefore the address-bar and refresh behavior is verified by direct resolve_browser_url unit tests and call-graph tracing, not by a live capture.

Next step to unblock visual verification: provide a real test-account login or a supported non-UI way to mint a valid browser session for the local server. The rest of the local pipeline is ready to resume.

  • I have manually tested my changes locally with ./script/run

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

CHANGELOG-BUG-FIX: Fixed the web session viewer rewriting the browser URL to a revealed child agent's URL, which meant refreshing or copying the link landed on the child instead of the orchestrator.

…LITY-1764)

Clicking a child agent's pill in the web session viewer swapped the
child's pane into focus, which then unconditionally recomputed the
browser URL from that focused pane's own shareable link. This
silently rewrote the orchestrator's ConversationView/SessionView URL
to the child's, so a refresh or copied link landed on the child
instead of the orchestrator.

update_browser_url() already special-cased this for one path: when a
focused pane has no shareable link (ShareableLink::Base), it falls
back to the current URL instead of resetting to /app if that URL is
a ConversationView/SessionView. Extend that same guard to the
ShareableLink::Pane case, so a focused pane's own link never
replaces the viewer's entry URL either. Both known write paths
(PaneGroup::focus's own update_browser_url, and the JoinedSession
handler in handle_pane_link_updated) funnel through this single
function, so guarding it there covers both without a second fix.

Move the ConversationView/SessionView predicate onto WebIntent in
web_intent_parser.rs (host-testable, unlike the wasm-gated
browser_url_handler.rs) and add unit tests for it.
@warp-agent-staging

Copy link
Copy Markdown
Contributor Author

This PR was generated with Warp.

Comment @warp-factory on this PR to send it follow-up work.

View run View conversation

The predicate tests alone don't observe update_browser_url()'s guard: they
still pass if the guard is deleted or its wiring regresses. Extract the
actual URL-resolution decision (which URL to commit given the current URL,
the requested URL, and force_redirect) into a pure resolve_browser_url()
function in a new browser_url_resolution.rs, gated to wasm and test builds
since those are its only real callers. update_browser_url() becomes a thin
wrapper around it plus the existing DOM-writing code.

Add tests that exercise resolve_browser_url directly and fail if the guard
regresses: keeping the parent's ConversationView/SessionView URL when a
child pane requests its own link (both directions), keeping it when the
focused pane has no link at all, using the requested URL and falling back
to the base app URL outside the viewer, and bypassing the guard when
force_redirect is set.
@warp-agent-staging warp-agent-staging Bot changed the title Preserve web session viewer URL when a pane inside it is focused (QUALITY-1764) Stage child-run deep linking in the web session viewer (Phase 0 + spec) Aug 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants