Skip to content

itx: one example catalogue across REPL UI and every e2e runtime#1480

Merged
jonastemplestein merged 7 commits into
mainfrom
thin-tarsier
Jun 10, 2026
Merged

itx: one example catalogue across REPL UI and every e2e runtime#1480
jonastemplestein merged 7 commits into
mainfrom
thin-tarsier

Conversation

@jonastemplestein

@jonastemplestein jonastemplestein commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

What

Refactors the itx e2e suite to work like the old capnweb e2e suite: the same script runs across every runtime, and the scripts themselves are the catalogue the REPL UI shows as Examples.

One catalogue (src/itx/examples.ts)

  • Each entry: { id, title, description, context, runtimes, code }. The UI renders title/description/context/runtimes; the e2e suite executes code.
  • Examples are written against a project-scoped handle: the harness creates the project and connects into it, and the script gets straight to work (itx.streams.get("/repl/demo").append(...)). Only the narrowing example itself is global-context.
  • Script bodies run with itx and vars in scope and end with an explicit return — the one shape every runtime accepts.

The runtime matrix (e2e/example-matrix.ts)

Each example runs in every runtime it's tagged for:

  • nodeAsyncFunction over a Cap'n Web WebSocket stub
  • clipnpm cli itx run -e … (new command; a real spawned CLI evaluating over its own connection, so it can hold live caps like node -e)
  • dynamic-worker — POST /api/itx/run with the body wrapped as async ({ itx, vars }) => { … }
  • config-worker — the catalogue baked into the project's iterate-config worker.js (one git push per suite), each example invoked via itx.worker.runItxExample({ id, vars }) and executed against the worker's own env.ITERATE.context
  • browser — headless Chromium drives the real REPL evaluation pipeline (itx.browser.test.ts)

Assertions live in e2e/example-cases.ts; a guard test fails when a runnable example has no case, so UI examples can't silently rot.

REPL compatibility

  • Top-level return no longer shows a tsc error (TS1108 filtered in the REPL's TS worker; the runtime always wrapped snippets in an async function body anyway).
  • Top-level import works: bare specifiers rewrite to awaited dynamic imports from esm.sh (import { z } from "zod"const … = await import("https://esm.sh/zod")). The rewrite reuses the comment/string-aware statement scanner, so worker sources inside template literals are untouched, and imported bindings persist across REPL entries. New browser-only catalogue example demonstrates it.
  • vars is always in REPL scope (with projectId declared for the editor) so catalogue examples run unchanged.

CLI

pnpm cli itx run -e "<body>" [--context <project>] [--vars '{...}'] [--file …] — verified against prd:

$ doppler run --config prd -- pnpm cli itx run -e "const page = await itx.projects.list({ limit: 1 }); return { total: page.total, ... }"
{ "total": 3, "first": "test-b44jsh" }

Verification

  • pnpm typecheck && pnpm lint && pnpm format && pnpm test green locally.
  • Preview CI runs the node-project itx e2e; the browser project will be run locally in headless Chromium against this PR's preview deployment (results to follow in a comment).

🤖 Generated with Claude Code


Note

Medium Risk
Large test and execution-surface change (CLI eval, config-worker git pushes, dynamic AsyncFunction/new Function in REPL and CLI); behavior is heavily covered by e2e but touches admin-authenticated script execution and deployed worker loading.

Overview
Unifies itx Examples and e2e coverage around a single catalogue in src/itx/examples.ts (id, context, runtimes, script body with itx + vars + trailing return). The REPL Examples panel and tests both consume that list; example-cases.ts holds assertions and a guard so runnable examples cannot rot without a case.

Adds a cross-runtime matrix (example-matrix.ts): the same script runs on node (Cap'n Web), cli (itx run — new scripts/itx-run.ts, wired into the iterate CLI router), dynamic-worker (/api/itx/run), and config-worker (catalogue baked into iterate-config worker.js via git push). Browser e2e runs catalogue snippets through the real REPL pipeline (itx.browser.test.ts).

REPL/runtime alignment: default scope includes vars; editor globals add vars, projectId, and wildcard modules; TS1108 is filtered so top-level return typechecks; top-level import rewrites to awaited esm.sh dynamic imports with session-persisted bindings. Global vs project REPL disables project-only snippets in the UI when context does not match.

Removes inlined REPL examples and the old itx-scripts typed script builder in favor of the catalogue; shared e2e worker sources stay in slim itx-scripts.ts.

Reviewed by Cursor Bugbot for commit 925f20f. 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: 925f20f
Preview: https://os.iterate-preview-6.com
Summary: Preview app released.
Workflow run
Updated: 2026-06-10T22:27:41.380Z

The browser REPL examples and the e2e shared scripts collapse into one
catalogue (src/itx/examples.ts): each entry has a title, description,
context, runtimes tags, and a script body written against a PROJECT-scoped
handle — the harness connects into the project and the script gets straight
to work (itx.streams.get("/repl/demo").append(...)).

The e2e suite runs each catalogue entry through every runtime it is tagged
for: node (AsyncFunction over Cap'n Web), the new `pnpm cli itx run -e`
(a real spawned CLI evaluating over its own WebSocket), /api/itx/run
(dynamic worker), the project's iterate-config worker (baked in via git
push, invoked through itx.worker), and the browser REPL pipeline in
headless Chromium. Assertions live in e2e/example-cases.ts; a guard test
fails when a runnable example lacks a case.

REPL compatibility: top-level `return` no longer angers the editor (TS1108
filtered in the typescript worker; runtime already wrapped bodies in an
async function), and top-level imports now work — bare specifiers rewrite
to awaited dynamic imports from esm.sh, comment/string-aware so worker
sources inside template literals stay untouched. `vars` joins the REPL
scope so examples run unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread apps/os/src/routes/_app/itx-repl.tsx
jonastemplestein and others added 2 commits June 10, 2026 22:55
… — keep diagnostics filter + catalogue

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread apps/os/src/itx/examples.ts
jonastemplestein and others added 2 commits June 10, 2026 23:04
The catalogue's project examples assume a project-scoped handle; offering
them unmodified in the global REPL ran them against the wrong namespace
(Bugbot finding on #1480). The REPL now knows its context: the global page
shows project examples with a pointer to a project REPL instead of a Use
button; a project REPL can run everything (the global narrowing example
narrows to itself).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Worker-heavy catalogue examples running while the other itx e2e files load
their own dynamic workers can trip the deployment's 'Too many concurrent
dynamic workers' cap (seen 3/48 on a parallel full-suite run against
preview-6). Shared-load contention, not behavior — retry that one error
with backoff; everything else still fails immediately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit bfcd25e. Configure here.

Comment thread apps/os/scripts/itx-run.ts
jonastemplestein and others added 2 commits June 10, 2026 23:15
A fresh crypto.randomUUID() cacheKey per run made every matrix runtime load
a brand-new isolate for every cap; the accumulated residents tripped
Cloudflare's loader concurrency cap deterministically by the third
worker-heavy example ('Too many concurrent dynamic workers' — same three
failures solo or parallel). Static sources get static keys: re-running an
example reuses the loaded worker, and the keys read as what they are —
content versions you bump when you edit the module text.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jonastemplestein jonastemplestein merged commit 4c3a5e6 into main Jun 10, 2026
7 checks passed
@jonastemplestein jonastemplestein deleted the thin-tarsier branch June 10, 2026 22:26
@jonastemplestein

Copy link
Copy Markdown
Contributor Author

Verification record for this PR (all against the preview-6 deployment of this branch, post-merge-with-main):

CI (Preview / deploy + e2e, real run — 5 itx e2e files, 34 passed / 1 env-skipped): all 10 catalogue matrix examples green across node, cli, dynamic-worker, config-worker.

Headless Chromium, run locally against the same deployment (pnpm e2e:itx --project browser): 14/14 green — every browser-tagged catalogue example through the real REPL evaluation pipeline, including import { z } from "zod" via esm.sh, the live-capability alert flow, and the browser-as-provider path-call cap.

CLI smoke (prd, read-only): pnpm cli itx run -e "…projects.list…" returns JSON as expected.

Two follow-up fixes landed during babysitting: stable content-version cacheKeys in the catalogue (fresh-uuid keys accumulated isolates until Cloudflare's loader cap tripped — deterministic after ~3 worker-heavy examples), and the global REPL no longer offers project-context examples as runnable (Bugbot finding).

🤖 Generated with Claude Code

jonastemplestein added a commit that referenced this pull request Jun 10, 2026
Main moved the REPL examples into examples.ts (#1480) mid-flight; the
live-cap examples now teach caps.define with a live target (one alias
mention survives), and the REPL harness mock speaks the same verb.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.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.

1 participant