itx: execution events — two-event durable record for script runs#1442
Merged
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 00bfb0e. Configure here.
31496c0 to
6ac16d9
Compare
a9a7a7c to
cc2a9cd
Compare
jonastemplestein
added a commit
that referenced
this pull request
Jun 10, 2026
Bugbot finding on #1442: loader.load/getEntrypoint threw outside the outcome try/catch, leaving a dangling execution-requested record and an executionId-less HTTP error. One try/catch now spans loading through running. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cc2a9cd to
9a7224d
Compare
Contributor
Author
|
Bugbot finding addressed in 9a7224d: one try/catch now spans loader.load → getEntrypoint → run, so a loader failure produces an ok:false outcome and the matching execution-completed event instead of a dangling execution-requested record. |
jonastemplestein
added a commit
that referenced
this pull request
Jun 10, 2026
Bugbot finding on #1442: loader.load/getEntrypoint threw outside the outcome try/catch, leaving a dangling execution-requested record and an executionId-less HTTP error. One try/catch now spans loading through running. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
9a7224d to
825791f
Compare
Adds events.iterate.com/itx/execution-requested|completed (the pair that replaces codemode's six-event execution protocol, itx-next.md §4) and a shared runner, src/itx/run.ts, extracted from /api/itx/run: - runItxScript() loads the one-off isolate (env.ITERATE scoped to the target context, globalOutbound = ProjectEgress for project scripts), appends execution-requested before and execution-completed after, and returns the outcome with an executionId. - Record-only mode: the events are history, not transport — appends are best-effort (D1 posture), recorded results bounded at 64k chars. - /api/itx/run becomes a thin shim (resolve + access-check, delegate) and now returns the executionId alongside the result. - Global-context scripts record no events (no owning project stream). The shared runner is what the codemode-drop PR points the inbound-MCP exec_js and agent execution paths at. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Scripts' console.log/warn/error lines come back in the outcome (and the
completed event, bounded at 200 lines) — exec_js parity for the codemode
drop. runItxScript gains record?: { namespace, path } so callers whose
loop lives on another stream (the agent) can record there; default stays
the project /itx stream.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bugbot finding on #1442: loader.load/getEntrypoint threw outside the outcome try/catch, leaving a dangling execution-requested record and an executionId-less HTTP error. One try/catch now spans loading through running. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
825791f to
f43fee8
Compare
jonastemplestein
added a commit
that referenced
this pull request
Jun 10, 2026
Bugbot finding on #1442: loader.load/getEntrypoint threw outside the outcome try/catch, leaving a dangling execution-requested record and an executionId-less HTTP error. One try/catch now spans loading through running. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jonastemplestein
added a commit
that referenced
this pull request
Jun 10, 2026
Stacked on #1442. First slice of the codemode rip-out (itx-next.md §4): the inbound MCP server's `exec_js` no longer touches codemode. ## What - **exec_js scripts are itx scripts** — `async ({ itx }) => { ... }` — run through the shared `runItxScript` harness, with the two-event execution record landing on the MCP session's stream. Console capture and result formatting preserved. - **Each (MCP session, project) gets a child context** (`ctx_…`, the prototype chain in action) seeded with three caps: `ai` (raw AI binding ref), `os` (OrpcCapability, path-call), `gmail` (GmailCapability, members). The caps' `instructions` feed both the exec_js tool description and `itx.describe()`. - **OrpcCapability** gains a real `call({ path, args })`; the legacy `executeCodemodeFunctionCall` delegates to it. **GmailCapability needs no adapter at all** — `request()` is a real method and members-replay reaches it. - **Security**: the registry now force-injects `projectId` into loopback dial props (alongside `cap`/`context`), so dialable entrypoints that scope by project can never be pointed at someone else's project by a definer. Orpc + Gmail added to `DIALABLE_LOOPBACKS` with that contract documented. - Deleted from the MCP DO: tool-provider registrations, codemode session start/wait, the stream-decoding result watcher, debug provider limits (~200 lines). Codemode itself still exists (agent loop + web UI consume it); parts 2 and 3 take those, then the domain deletes. ## Testing typecheck / lint / format / unit (208 tests) green. e2e exec_js coverage rides the existing inbound-MCP suite against a deployment. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > Changes authenticated remote code execution and project-bound API/Gmail loopback dialing; registry-injected projectId is the main cross-tenant guard. > > **Overview** > Inbound MCP **`exec_js`** no longer uses codemode sessions, tool-provider registrations, or stream polling for completion. Scripts run as **`async ({ itx }) => { ... }`** via **`runItxScript`**, with execution recorded on the MCP session stream and the same console/result formatting for tool responses. > > Each **(MCP session, project)** gets a persisted **child itx context** (`ITX_CONTEXT`) parented to the project, seeded with **`ai`**, **`os`** (path-call → **`OrpcCapability`**), and **`gmail`** (members → **`GmailCapability`**). Cap **`instructions`** drive both the **`exec_js`** tool docs and **`itx.describe()`**. > > **`OrpcCapability`** adds **`call({ path, args })`** for itx path-call; legacy **`executeCodemodeFunctionCall`** delegates to it (with mount-aware **`listProcedures`** for old callers). **`DIALABLE_LOOPBACKS`** now includes **`OrpcCapability`** and **`GmailCapability`**, and the registry **force-injects `projectId`** on loopback dial props so project-scoped entrypoints cannot be aimed at another project. **`codemode-event-payload`** helpers are removed from this path (~200 lines of MCP DO codemode wiring deleted). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit d0c631f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- CLOUDFLARE_PREVIEW --> ## Environment Config Lease <!-- CLOUDFLARE_PREVIEW_STATE --> <!-- { "apps": { "os": { "appDisplayName": "OS", "appSlug": "os", "status": "deployed", "updatedAt": "2026-06-10T14:28:35.934Z", "headSha": "d0c631fac58817753474480f5926e72e6c09d814", "message": null, "publicUrl": "https://os.iterate-preview-3.com", "runUrl": "https://github.com/iterate/iterate/actions/runs/27282903658", "shortSha": "d0c631f" }, "semaphore": { "appDisplayName": "Semaphore", "appSlug": "semaphore", "status": "deployed", "updatedAt": "2026-06-10T14:13:37.187Z", "headSha": "071375e4a5b3d9f546ea4c6caae492d60891f6d3", "message": null, "publicUrl": "https://semaphore.iterate-preview-3.com", "runUrl": "https://github.com/iterate/iterate/actions/runs/27282171935", "shortSha": "071375e" } }, "environmentConfigLease": { "dopplerConfig": "preview_3", "leasedUntil": 1781104923528, "leaseId": "9fd945b0-2dbe-4589-83ce-0dd8370a9739", "slug": "preview-3", "type": "environment-config-lease" } } --> <!-- /CLOUDFLARE_PREVIEW_STATE --> Lease: `preview-3` Doppler config: `preview_3` Type: `environment-config-lease` Leased until: 2026-06-10T15:22:03.528Z ### OS Status: deployed Commit: `d0c631f` Preview: https://os.iterate-preview-3.com [Workflow run](https://github.com/iterate/iterate/actions/runs/27282903658) Updated: 2026-06-10T14:28:35.934Z ### Semaphore Status: deployed Commit: `071375e` Preview: https://semaphore.iterate-preview-3.com [Workflow run](https://github.com/iterate/iterate/actions/runs/27282171935) Updated: 2026-06-10T14:13:37.187Z <!-- /CLOUDFLARE_PREVIEW --> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Stacked on #1441 (McpClient). Part of the codemode rip-out sequence (itx-next.md §4).
What
The two-event execution record that replaces codemode's six-event protocol:
events.iterate.com/itx/execution-requested{ executionId, code, vars, context }events.iterate.com/itx/execution-completed{ executionId, ok, result | error+stack, durationMs, context }Both land on the owning project's
/itxstream (D9-consistent: context id in the payload).Record-only mode: the events are the durable history, not the transport — callers get the outcome from the return value/HTTP response, and everything between the two events is invisible to the stream. Appends are best-effort, matching the registry's audit posture. Recorded results are bounded (64k chars, truncated with a preview beyond that); the full value still returns to the caller.
Mechanically: the loader harness moves out of
fetch.tsinto a sharedsrc/itx/run.ts(runItxScript()),/api/itx/runbecomes a thin resolve-and-delegate shim, and the response now includes theexecutionIdfor correlation. Global-context scripts record no events (no owning project stream).The shared runner is the function the upcoming codemode-drop PR points the inbound-MCP
exec_jsand agent execution paths at.Testing
typecheck / lint / format green. New e2e test runs a script via
/api/itx/runand asserts both events land on the/itxstream with the returnedexecutionIdand the correct outcome payload.🤖 Generated with Claude Code
Note
Medium Risk
Touches dynamic code execution and stream audit payloads; auth stays at the existing
/api/itx/runboundary, but execution records and API response shape change for all script runs.Overview
Introduces record-only script execution auditing: each project-context run appends
execution-requestedthenexecution-completedon the project/itxstream (replacing codemode’s six-event protocol), while callers still get the outcome from the HTTP/return value.The loader harness moves from
fetch.tsinto sharedrunItxScript()inrun.ts;POST /api/itx/runonly resolves access and delegates. Responses now includeexecutionId(and on errors too) for correlation. The runner captures isolate console lines, truncates large results on the stream (64k), always emits completed even on loader failures, and skips stream writes for global (admin-only) scripts.A new e2e test runs a script via
/api/itx/runand asserts both events match the returnedexecutionIdand result.Reviewed by Cursor Bugbot for commit f43fee8. Bugbot is set up for automated code reviews on this repo. Configure here.
Environment Config Lease
No active environment config lease.
OS
Status: released
Commit:
f43fee8Preview: https://os.iterate-preview-7.com
Summary: Preview app released.
Workflow run
Updated: 2026-06-10T14:07:32.827Z
Semaphore
Status: released
Commit:
f43fee8Preview: https://semaphore.iterate-preview-7.com
Summary: Preview app released.
Workflow run
Updated: 2026-06-10T14:07:20.109Z