Skip to content

Conversation

@TooTallNate
Copy link
Member

@TooTallNate TooTallNate commented Feb 12, 2026

Summary

Render the EntityDetailPanel (step/hook/event detail sidebar) outside the trace viewer's TraceViewerContextProvider, so hydrated data no longer passes through the web worker's postMessage structured clone boundary.

Problem

The trace viewer uses a web worker for span layout calculations, sending data via postMessage which requires structured cloning. After moving hydration client-side, the hydrated data (containing URLSearchParams, Headers, and other non-structurally-cloneable types) was embedded in trace span attributes and sent to the worker, causing DOMException: URLSearchParams object could not be cloned.

Solution

Render the detail panel as a sibling to the trace timeline instead of nested inside the context:

Before:                          After:
TraceViewerContext               [flex row]
  └─ Timeline                     ├─ TraceViewerContext
       └─ Panel (inside worker)   │    └─ Timeline (worker)
                                  └─ Panel (direct props)
  • WorkflowTraceViewer: flex layout with timeline + panel as siblings
  • SelectionBridge: lightweight component inside context that reads the selected span and passes it up via callback
  • EntityDetailPanel: no longer imports useTraceViewer(), receives selected span info via selectedSpan prop
  • Panel has independent width/resize state (no longer coupled to the trace viewer context)
  • Strip input/output/error from trace span attributes to keep worker data lightweight

Also fixes

  • Stale customPanelComponent bug — the panel was stored in context state during initialization and never updated, causing data to be lost on re-renders

@changeset-bot
Copy link

changeset-bot bot commented Feb 12, 2026

🦋 Changeset detected

Latest commit: 865a9f1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@workflow/web-shared Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Feb 12, 2026

🧪 E2E Test Results

Some tests failed

Summary

Passed Failed Skipped Total
✅ ▲ Vercel Production 490 0 38 528
✅ 💻 Local Development 418 0 62 480
✅ 📦 Local Production 418 0 62 480
✅ 🐘 Local Postgres 418 0 62 480
✅ 🪟 Windows 45 0 3 48
❌ 🌍 Community Worlds 102 42 9 153
✅ 📋 Other 123 0 21 144
Total 2014 42 257 2313

❌ Failed Tests

🌍 Community Worlds (42 failed)

mongodb (1 failed):

  • webhookWorkflow

turso (41 failed):

  • addTenWorkflow
  • addTenWorkflow
  • should work with react rendering in step
  • promiseAllWorkflow
  • promiseRaceWorkflow
  • promiseAnyWorkflow
  • hookWorkflow
  • webhookWorkflow
  • sleepingWorkflow
  • nullByteWorkflow
  • workflowAndStepMetadataWorkflow
  • fetchWorkflow
  • promiseRaceStressTestWorkflow
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • hookCleanupTestWorkflow - hook token reuse after workflow completion
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument
  • closureVariableWorkflow - nested step functions with closure variables
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly
  • Calculator.calculate - static workflow method using static step methods from another class
  • AllInOneService.processNumber - static workflow method using sibling static step methods
  • ChainableService.processWithThis - static step methods using this to reference the class
  • thisSerializationWorkflow - step function invoked with .call() and .apply()
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE
  • instanceMethodStepWorkflow - instance methods with "use step" directive
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router

Details by Category

✅ ▲ Vercel Production
App Passed Failed Skipped
✅ astro 44 0 4
✅ example 44 0 4
✅ express 44 0 4
✅ fastify 44 0 4
✅ hono 44 0 4
✅ nextjs-turbopack 47 0 1
✅ nextjs-webpack 47 0 1
✅ nitro 44 0 4
✅ nuxt 44 0 4
✅ sveltekit 44 0 4
✅ vite 44 0 4
✅ 💻 Local Development
App Passed Failed Skipped
✅ astro-stable 41 0 7
✅ express-stable 41 0 7
✅ fastify-stable 41 0 7
✅ hono-stable 41 0 7
✅ nextjs-turbopack-stable 45 0 3
✅ nextjs-webpack-stable 45 0 3
✅ nitro-stable 41 0 7
✅ nuxt-stable 41 0 7
✅ sveltekit-stable 41 0 7
✅ vite-stable 41 0 7
✅ 📦 Local Production
App Passed Failed Skipped
✅ astro-stable 41 0 7
✅ express-stable 41 0 7
✅ fastify-stable 41 0 7
✅ hono-stable 41 0 7
✅ nextjs-turbopack-stable 45 0 3
✅ nextjs-webpack-stable 45 0 3
✅ nitro-stable 41 0 7
✅ nuxt-stable 41 0 7
✅ sveltekit-stable 41 0 7
✅ vite-stable 41 0 7
✅ 🐘 Local Postgres
App Passed Failed Skipped
✅ astro-stable 41 0 7
✅ express-stable 41 0 7
✅ fastify-stable 41 0 7
✅ hono-stable 41 0 7
✅ nextjs-turbopack-stable 45 0 3
✅ nextjs-webpack-stable 45 0 3
✅ nitro-stable 41 0 7
✅ nuxt-stable 41 0 7
✅ sveltekit-stable 41 0 7
✅ vite-stable 41 0 7
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 45 0 3
❌ 🌍 Community Worlds
App Passed Failed Skipped
✅ mongodb-dev 3 0 0
❌ mongodb 44 1 3
✅ redis-dev 3 0 0
✅ redis 45 0 3
✅ turso-dev 3 0 0
❌ turso 4 41 3
✅ 📋 Other
App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 41 0 7
✅ e2e-local-postgres-nest-stable 41 0 7
✅ e2e-local-prod-nest-stable 41 0 7

📋 View full workflow run

@vercel
Copy link
Contributor

vercel bot commented Feb 12, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
example-nextjs-workflow-turbopack Ready Ready Preview, Comment Feb 13, 2026 1:01am
example-nextjs-workflow-webpack Ready Ready Preview, Comment Feb 13, 2026 1:01am
example-workflow Ready Ready Preview, Comment Feb 13, 2026 1:01am
workbench-astro-workflow Ready Ready Preview, Comment Feb 13, 2026 1:01am
workbench-express-workflow Ready Ready Preview, Comment Feb 13, 2026 1:01am
workbench-fastify-workflow Ready Ready Preview, Comment Feb 13, 2026 1:01am
workbench-hono-workflow Ready Ready Preview, Comment Feb 13, 2026 1:01am
workbench-nitro-workflow Ready Ready Preview, Comment Feb 13, 2026 1:01am
workbench-nuxt-workflow Ready Ready Preview, Comment Feb 13, 2026 1:01am
workbench-sveltekit-workflow Ready Ready Preview, Comment Feb 13, 2026 1:01am
workbench-vite-workflow Ready Ready Preview, Comment Feb 13, 2026 1:01am
workflow-docs Ready Ready Preview, Comment, Open in v0 Feb 13, 2026 1:01am
workflow-nest Ready Ready Preview, Comment Feb 13, 2026 1:01am
workflow-swc-playground Ready Ready Preview, Comment Feb 13, 2026 1:01am

Copy link
Member Author

TooTallNate commented Feb 12, 2026

@TooTallNate TooTallNate force-pushed the nate/split-serde-for-browser branch from f9343d5 to 42dad79 Compare February 12, 2026 02:35
@TooTallNate TooTallNate force-pushed the nate/decouple-panel-from-trace-worker branch from 81ebf60 to 3f3fcaa Compare February 12, 2026 02:35
@TooTallNate TooTallNate changed the title web-shared: render detail panel outside trace viewer context Decouple detail panel from trace viewer web worker pipeline Feb 12, 2026
@TooTallNate TooTallNate changed the base branch from nate/split-serde-for-browser to graphite-base/1017 February 13, 2026 00:58
Decouple the EntityDetailPanel from the TraceViewerContextProvider
so it no longer goes through the web worker's postMessage pipeline.

Previously, the panel was rendered as a customPanelComponent inside
the trace viewer context, which meant hydrated data (including
non-structurally-cloneable types like URLSearchParams) had to survive
the worker's structured clone boundary, causing DOMExceptions.

Now the panel is rendered as a sibling to the trace timeline:
- Timeline (inside TraceViewerContextProvider) handles span layout
- Panel (outside context) receives data directly via props
- A lightweight SelectionBridge component reads the selected span
  from context and passes it up to the parent via callback

Changes:
- WorkflowTraceViewer: flex layout with timeline + panel as siblings.
  Panel has its own width/resize state, independent of context.
- EntityDetailPanel: remove useTraceViewer() dependency. Receives
  selected span info via new selectedSpan prop (SelectedSpanInfo).
- TraceViewerContext: deprecate customPanelComponent field, remove
  setCustomPanelComponent action.
- Export SelectedSpanInfo type from web-shared.
Now that the detail panel renders outside the trace viewer's web
worker pipeline (no postMessage boundary), all types can be revived
as proper instances: URLSearchParams, Headers, URL, etc.

Strip input/output/error from step and run data embedded in trace
span attributes to avoid sending hydrated objects through the web
worker's postMessage boundary. The detail panel fetches full data
separately via spanDetailData.
…l delta

PanelResizeHandle was computing delta from the original startX on
every pointermove, but the handler added it incrementally, causing
exponential width growth during drag. Track lastX and send only
the incremental change per move event.
@TooTallNate TooTallNate force-pushed the nate/decouple-panel-from-trace-worker branch from 6214b15 to 865a9f1 Compare February 13, 2026 00:59
@graphite-app graphite-app bot changed the base branch from graphite-base/1017 to main February 13, 2026 00:59
@graphite-app
Copy link

graphite-app bot commented Feb 13, 2026

Merge activity

  • Feb 13, 12:59 AM UTC: Graphite rebased this pull request, because this pull request is set to merge when ready.
  • Feb 13, 1:17 AM UTC: @TooTallNate merged this pull request with Graphite.

@TooTallNate TooTallNate merged commit 4938b24 into main Feb 13, 2026
101 of 164 checks passed
@TooTallNate TooTallNate deleted the nate/decouple-panel-from-trace-worker branch February 13, 2026 01:17
karthikscale3 added a commit that referenced this pull request Feb 13, 2026
Bring the web-shared trace/detail panel files back in sync with main so PR #1017 behavior is preserved and not regressed on this branch.

Co-authored-by: Cursor <cursoragent@cursor.com>
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