feat(core): record replay lineage in run executionContext#2872
Conversation
recreateRunFromExisting now stamps the source run id into the new run's executionContext as `replayedFromRunId`, and `start` accepts a matching option. This lets tooling (e.g. the dashboard runs list) surface a run as a replay and link back to the run it was replayed from — previously a replay started a brand-new run with no link to its origin. Co-authored-by: Cursor <cursoragent@cursor.com>
🦋 Changeset detectedLatest commit: f6029ed The changes in this PR will be included in the next version bump. This PR includes changesets to release 16 packages
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 |
🧪 E2E Test Results
⏳ Tests are running... _Started at: _ ✅ All tests passed Summary
Details by Category✅ ▲ Vercel Production
✅ 💻 Local Development
✅ 📦 Local Production
✅ 🐘 Local Postgres
✅ 🪟 Windows
✅ 📋 Other
❌ Some E2E test jobs failed:
Check the workflow run for details. |
📊 Workflow Benchmarks⏳ Benchmarks are running for
commit Backend:
📜 Previous results (1)df8ab47Fri, 10 Jul 2026 15:34:19 GMT · run logs
Avg deltas compare against the most recent benchmark run on Metrics — TTFS: time to first step body execution · STSO: step-to-step overhead (gap between consecutive step bodies) · WO: workflow overhead (time outside step bodies, client start → last step body exit) · SL: stream latency (first chunk write → visible to the reader) Scenarios — stream: one step that streams chunks back to the client; no hooks, so the run stays in turbo mode · hook + stream: registers a hook before the same streaming step, which exits turbo mode · 1020 steps: 1020 trivial sequential steps; STSO is measured between consecutive steps in the given step ranges 🟢/🔴 mark percentiles within/above target. Targets (p75/p90/p99, ms) — TTFS 200/300/600 · SL 50/60/125 · STSO (1-20) 20/30/60 · STSO (101-120) 30/45/90 · STSO (1001-1020) 40/60/120 TTFS/WO compare client vs deployment clocks and SL compares the step runner’s clock vs the client’s (NTP-synced in CI). WO ends at the last step body exit, the closest observable proxy for the final step-completion request. |
Signed-off-by: Mitul Shah <mitulxshah@gmail.com>
Summary
Replays currently start a brand-new run with no link back to the run they were replayed from, so tooling can't tell that a run originated as a replay. This adds that link.
recreateRunFromExistingnow stamps the source run id into the new run'sexecutionContextasreplayedFromRunId.startgains an optionalreplayedFromRunIdoption (used byrecreateRunFromExisting; rarely needed directly) that is merged into the run'sexecutionContexton both therun_createdevent and the resilient-start queue input.executionContextis the right home per the repo's own architecture notes ("flexible object that can store arbitrary data without schema changes… flows through all worlds"), and it's already returned onWorkflowRunWithoutDatafromruns.list, so consumers can read it without resolving full run data.Motivation
This is the SDK half of a dashboard feature in
vercel/frontthat shows a "Replay of <run id>" indicator next to the workflow name in the all-runs table (mirroring the deployment list's "Redeploy of …"). That PR already readsexecutionContext.replayedFromRunId; this change is what populates it. Until this lands, the indicator is a no-op because the origin is never recorded.Changes
packages/core/src/runtime/start.ts— addreplayedFromRunId?toStartOptionsBase; include it inexecutionContextwhen set.packages/core/src/runtime/runs.ts— passreplayedFromRunId: runIdfromrecreateRunFromExistingintostart.startrecords/omits the key correctly;recreateRunFromExistingforwards the source run id.minor,@workflow/core).Testing
pnpm -F @workflow/core vitest run src/runtime/runs.test.ts src/runtime/start.test.ts→ 50 passed (incl. 3 new).pnpm -F @workflow/core typecheck→ clean.Notes
hydrateResourceIO) stripsexecutionContextbefore UI display in this repo's own dashboard; thevercel/frontruns list readsworld.runs.listdirectly and is unaffected. If the workflow-repo dashboard should also show this, the value would need to be extracted before stripping (follow-up).Made with Cursor