Skip to content

feat(eve): stamp schedule-dispatched sessions with $eve.schedule#709

Open
warmwind wants to merge 1 commit into
vercel:mainfrom
warmwind:feat-schedule-attribution
Open

feat(eve): stamp schedule-dispatched sessions with $eve.schedule#709
warmwind wants to merge 1 commit into
vercel:mainfrom
warmwind:feat-schedule-attribution

Conversation

@warmwind

Copy link
Copy Markdown

Closes #708

Problem

Sessions started by a schedule dispatch carry no record of which schedule fired. The markdown form only gets $eve.trigger = "schedule", and sessions a handler starts through args.receive(...) carry the target channel's kind instead — so trigger-based filtering can neither attribute runs to a specific schedule nor see channel-dispatched schedule work at all.

Change

  • New ScheduleIdKey (eve.scheduleId) context key.
  • ScheduleDispatcher.trigger wraps the whole dispatch in an eve context scope (the unified contextStorage, per the rule-19 invariant — no new AsyncLocalStorage) carrying the schedule name.
  • buildRunContext inherits the key from the ambient scope into every run started inside the dispatch. This is what covers the args.receive(...) path: those RunInputs are built by the target channel's authored receive hook, out of the dispatcher's hands, so the value cannot be threaded through explicitly.
  • buildSessionAttributes emits it as $eve.schedule. $eve.trigger semantics are unchanged — channel-dispatched sessions keep the channel kind and carry provenance alongside it.

Pure metadata addition, backward compatible: attributes ->> '$eve.schedule' = <name> now yields a schedule's complete run history regardless of dispatch path.

Testing

  • ScheduleDispatcher tests assert the scope is active when runtime.run fires for both the markdown form and the args.receive(...) path, and cleared after the dispatch.
  • Attribute builder tests cover readScheduleId well-formed/missing/malformed slots and the stamped session payload.
  • pnpm test:unit (4435), pnpm test:integration (385), package typecheck, lint, guard:invariants, docs:check all pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_0164WUaSv9mN58wgnnoN2vKG

Sessions started by a schedule dispatch carry no record of which
schedule fired: the markdown form only gets $eve.trigger="schedule",
and sessions a handler starts through args.receive(...) carry the
target channel's kind, so trigger-based filtering cannot attribute
runs to a schedule at all.

The ScheduleDispatcher now wraps the dispatch in an eve context scope
carrying the schedule name under the new ScheduleIdKey.
buildRunContext inherits the key from the ambient scope into each run
started inside the dispatch — covering RunInputs built out of the
dispatcher's hands by authored channel receive hooks — and
buildSessionAttributes emits it as $eve.schedule. $eve.trigger
semantics are unchanged.

Closes vercel#708

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0164WUaSv9mN58wgnnoN2vKG
Signed-off-by: Oscar Jiang <[email protected]>
@vercel

vercel Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

@warmwind is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

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.

Stamp schedule-dispatched runs with a $eve.schedule attribution attribute

1 participant