Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,3 +448,12 @@ Every outgoing HTTP request from `@workflow/world-vercel` to workflow-server (or
Do **not** rely on ambient OpenTelemetry auto-instrumentation to do this: world-vercel's request paths use custom undici dispatchers / `global fetch`, which auto-instrumentation does not reliably hook. When you add a new request path or API version (e.g. a future v5 events API), wire the injection in the same place you build the request headers. The v4 events path (`fetchV4` in `events-v4.ts`) regressed cross-service correlation precisely by routing around `makeRequest` and skipping this step — workflow-server spans stopped joining the flow-route invocation trace until the injection was added back. Cover new paths with a test in `trace-propagation.test.ts`.

The same rule covers a request path that is not an HTTP request. A non-`fetch` transport must still open the client span callers read a trace through: use `withHttpClientSpan` (`http-core.ts`), the envelope `instrumentedFetch` is built on, so the span carries the same name, kind and attributes rather than a hand-rolled parallel shape. The WS events transport is the worked example — `postEventFrameOverWs` synthesizes an `http POST` span per frame and tags it `workflow.events.transport: 'ws'`, and the handshake gets its own `workflow.events.ws.connect` span (`ws-transport-spans.test.ts`). Adding a transport that writes events without one silently deletes the per-event view of a run.

## Cursor Cloud specific instructions

The startup update script already runs `pnpm install --frozen-lockfile` (Node 22 and pnpm 10.20.0 are preinstalled), so dependencies are present when a session begins. A few non-obvious things about this repo's local dev loop:

- **`pnpm build` (repo root) is required before running or e2e-testing any workbench app.** Workbenches consume the compiled `packages/*` output; a fresh checkout has none. The commands are already documented under "Development Commands" above — this note just flags that the first build is not optional.
- **Building compiles a Rust→WASM artifact.** `@workflow/swc-plugin` (`packages/swc-plugin-workflow`) is built from Rust with `cargo build-wasm32`, and its `Cargo.toml` needs `edition2024` (Rust/Cargo ≥ 1.85). The environment snapshot ships a Rust `stable` toolchain (≥ 1.97) set as default plus the `wasm32-unknown-unknown` target, so `pnpm build` works out of the box; there is no committed prebuilt `.wasm`. If a build ever fails with `feature 'edition2024' is required`, the active Rust toolchain is too old — `rustup default stable && rustup target add wasm32-unknown-unknown`. The first `pnpm build` takes ~50s (mostly the Rust compile); it is turbo-cached afterward.
- **Default backend is `world-local` (filesystem).** No Postgres, Docker, or Vercel credentials are needed for local dev or the HTTP e2e suite. Postgres/Vercel backends are opt-in via `WORKFLOW_TARGET_WORLD` (see "Core Package Testing" above).
- **Primary runnable app for manual/e2e testing is `workbench/nextjs-turbopack`** (`WORKFLOW_PUBLIC_MANIFEST=1 pnpm dev`, port 3000). It exposes a UI at `/` that lists and triggers workflows, and HTTP trigger routes under `app/api/workflows/` (`start`, `await`). A quick smoke test: `POST /api/workflows/start` with `{"workflowName":"simple","args":[42]}` starts a run (id returned in the `x-workflow-run-id` header); `POST /api/workflows/await` with that `runId` returns `{"result":57}`.
Loading