Skip to content

[P2] Make the Workbench App workspace exercise one real pending-to-terminal invocation lifecycle, with cancellation and stale-session guards #751

Description

@ScriptedAlchemy

Author-facing gap

At main 14c9822bc6c01d8ff2788454d0e1dc7861bc3816, the App workspace says Calling… until controller.invoke() resolves, then creates the App preview from the completed result. An author cannot use that primary workspace to see the App's initial input/loading behavior or cancel its long-running opening call.

This is a source-observed workflow limitation, not a claim that the recently fixed pending bridge/harness is still broken. #741/#743 delivered underlying pending/terminal behavior; the primary workspace has not adopted the same lifecycle.

Evidence

  • application/app-route-workspace.tsx: callTool awaits the terminal result before setCall, and <McpAppPreview> only mounts when call exists. No cancel action is exposed. Promise success/error/finally setters do not check that the controller/session/epoch is still current.
  • mcp/mcp-app-preview.tsx: the artifact preview options still require a completed result.
  • test/browser.ts: the public browser harness now supports omitted toolResult while opening is in flight and subsequent result/cancel publication. Reuse the real binding/bridge semantics it exercises, not a new mock-only protocol.

Direction

For a tool whose listing binds this App, create one authorized preview binding for the opening invocation and carry it from pending input to its one terminal outcome. Add a visible cancellation action. Where the artifact preview endpoint lacks the needed seam, extend that existing owner narrowly; do not create a second App renderer, MCP client or application-local pending map.

Preview must not automatically rerun an opening mutation to obtain its result. Retain native permission/consent, result-schema handling, route identity and build-epoch retirement.

Acceptance

  • A deterministic gated tool shows its App's pending/loading state before the gate resolves; releasing it renders the actual terminal result exactly once.
  • User cancellation reaches the invocation and App terminal state; a later resolve cannot become a successful result.
  • Epoch/target/session change while pending retires the old binding and prevents old then/catch/finally callbacks from repopulating or unlocking a newer invocation. Verify current controller behavior with a regression rather than assuming every promise cancellation settles synchronously.
  • Opening represented error, malformed result, normal success, cancellation before frame initialization and disposal each have a real bridge/workspace test.
  • The same opening mutation is invoked once, including frame reload/reconnection. Do not bypass fix(web): prevent silent opening mutation repeats #646's repeat-prevention policy.
  • Unsupported/unbound resources retain a truthful fallback; no fabricated structured result is used to make a preview look ready.

Keep input, Run/Cancel, rendered App and useful status central. Session IDs, epoch IDs, correlation data and host profile controls are secondary diagnostics—not setup a first-time author must interpret before seeing their page. #747 separately owns valid launch selection; this issue owns lifecycle reuse and the actual preview experience.

Source-only review: no browser/native-host execution was performed here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions