Skip to content

Make codemode function calls event-driven#1305

Merged
jonastemplestein merged 46 commits into
mainfrom
raspy-produce
May 8, 2026
Merged

Make codemode function calls event-driven#1305
jonastemplestein merged 46 commits into
mainfrom
raspy-produce

Conversation

@jonastemplestein

@jonastemplestein jonastemplestein commented May 5, 2026

Copy link
Copy Markdown
Contributor

Motivation

This PR makes OS2 codemode a smaller event-driven runtime boundary.

The old shape mixed too much into the codemode processor:

  • provider registration meant both model-visible documentation and runtime callable wiring;
  • codemode requested function calls and also dispatched provider callables;
  • correlation leaked committed event offsets into verbose payload names;
  • ctx.codemode.* was a privileged escape hatch that bypassed the function-call event protocol.

The new shape keeps codemode responsible for script execution, durable function-call event schemas, correlation IDs, logs, and waiting for completions. Function implementations live outside codemode. A provider can be a stream processor that consumes function-call-requested and appends function-call-completed.

Event Vocabulary Owned By Codemode

Codemode owns this durable event vocabulary:

type CodemodeEvent =
  | "events.iterate.com/codemode/tool-provider-registered"
  | "events.iterate.com/codemode/script-execution-requested"
  | "events.iterate.com/codemode/script-execution-completed"
  | "events.iterate.com/codemode/function-call-requested"
  | "events.iterate.com/codemode/function-call-completed"
  | "events.iterate.com/codemode/log-emitted";

tool-provider-registered is documentation, not dispatch:

{
  type: "events.iterate.com/codemode/tool-provider-registered",
  payload: {
    path: ["slack"],
    docs: "Slack functions are available under ctx.slack.",
    instructions: "Use channel IDs, not channel names.",
    typeDefinitions: "declare namespace slack { ... }"
  }
}

The provider documentation schema now lives with the codemode processor contract in packages/shared/src/stream-processors/codemode/contract.ts. The OS2 oRPC contract intentionally accepts provider inputs loosely as unknown[]; the OS2 router validates those values by reading the codemode processor contract's tool-provider-registered payload schema. This keeps processor/event design as the source of truth instead of making the HTTP contract own processor internals.

Script Execution

A script starts with:

{
  type: "events.iterate.com/codemode/script-execution-requested",
  payload: {
    scriptExecutionId: "scr_...",
    code: "async (ctx) => { ... }"
  }
}

Codemode runs the block and appends exactly one completion:

{
  type: "events.iterate.com/codemode/script-execution-completed",
  payload: {
    scriptExecutionId: "scr_...",
    durationMs: 25,
    outcome: { status: "succeeded", output: { ok: true } }
  }
}

Failures use the same event type with a failed outcome:

{
  type: "events.iterate.com/codemode/script-execution-completed",
  payload: {
    scriptExecutionId: "scr_...",
    durationMs: 25,
    outcome: { status: "failed", error: { message: "boom" } }
  }
}

Design decision: completion is one event with an outcome union, not separate succeeded/failed events. That keeps correlation, duration, and future common metadata in one schema.

Function Calls

Scripts call ordinary paths on the injected context:

await ctx.slack.chat.sendMessage({
  channel: "C123",
  text: "hello from codemode"
});

Codemode turns that into:

{
  type: "events.iterate.com/codemode/function-call-requested",
  payload: {
    functionCallId: "fn_...",
    scriptExecutionId: "scr_...",
    path: ["slack", "chat", "sendMessage"],
    input: { channel: "C123", text: "hello from codemode" }
  }
}

Then codemode waits for a matching completion. It does not append the completion itself:

{
  type: "events.iterate.com/codemode/function-call-completed",
  payload: {
    functionCallId: "fn_...",
    scriptExecutionId: "scr_...",
    path: ["slack", "chat", "sendMessage"],
    outcome: { status: "succeeded", output: { ts: "..." } }
  }
}

Failures again use the same completion event with a failed outcome:

{
  type: "events.iterate.com/codemode/function-call-completed",
  payload: {
    functionCallId: "fn_...",
    scriptExecutionId: "scr_...",
    path: ["slack", "chat", "sendMessage"],
    outcome: { status: "failed", error: { message: "Slack API rejected request" } }
  }
}

Design decision: the IDs are explicit (scriptExecutionId, functionCallId). We can populate them from offsets later, but the event schema stays small and readable.

Script Context API

The script context remains path-addressed:

await ctx.slack.chat.sendMessage({ channel: "C123", text: "hello" });
await ctx.github.issues.create({ title: "Bug" });

The special privileged branch is removed:

// Removed
await ctx.codemode.append(...);
await ctx.codemode.executeScript(...);
await ctx.codemode.getStreamPath();

Stream operations should be exposed as normal path-addressed functions later, for example:

await ctx.streams.append({ event: { type: "...", payload: {} } });

That requires a streams provider/processor to observe the requested event, perform the append, and append the matching function-call completion. This PR does not add that production provider yet, so bundled runnable examples avoid external provider calls that would wait forever.

console.log(...) is still captured by the executor and written as a codemode log event:

{
  type: "events.iterate.com/codemode/log-emitted",
  payload: {
    scriptExecutionId: "scr_...",
    level: "log",
    message: "hello"
  }
}

Provider-To-Provider POC

This PR includes the vanilla event-sourced provider-to-provider proof of concept requested in review.

See packages/shared/src/stream-processors/codemode/implementation.test.ts, especially the test named:

"lets stream processor providers complete function calls and call each other via events"

The test defines a real provider processor contract:

const providerProcessorContract = defineProcessorContract({
  slug: "test-function-provider",
  processorDeps: [CodemodeProcessorContract],
  events: {},
  consumes: [
    "events.iterate.com/codemode/function-call-requested",
    "events.iterate.com/codemode/function-call-completed",
  ],
  emits: [
    "events.iterate.com/codemode/function-call-requested",
    "events.iterate.com/codemode/function-call-completed",
  ],
});

The flow is deliberately low-level:

  1. The script calls providerA.compose.exclaimViaB.
  2. Codemode appends function-call-requested for Provider A and waits.
  3. Provider A is an actual stream processor. Its afterAppend observes the request, stores the parent request in memory keyed by child functionCallId, and appends a second function-call-requested for Provider B.
  4. Provider B is also an actual stream processor. It observes the child request and appends function-call-completed for Provider B.
  5. Provider A observes Provider B's completion, looks up its in-memory parent request, and appends function-call-completed for Provider A.
  6. Codemode sees Provider A's completion, resumes the script, and appends script-execution-completed.

Expected event order from the test:

function-call-requested   providerA.compose.exclaimViaB  fn-a
function-call-requested   providerB.text.exclaim          fn-b
function-call-completed   providerB.text.exclaim          fn-b
function-call-completed   providerA.compose.exclaimViaB  fn-a
script-execution-completed                              scr-1

There is no helper abstraction in this PR. The POC shows the raw processor shape first: processors that call other providers juggle in-memory state while waiting for the matching completion event.

Removed

  • Callable descriptor dispatch from the codemode processor.
  • Automatic provider __describe calls.
  • tool-provider-described events.
  • tool-function-call-requested, tool-function-call-succeeded, and tool-function-call-failed durable events.
  • script-execution-finished durable events.
  • ctx.codemode.* in the script context.

The legacy codemode.execute streaming API still adapts durable codemode events into older client event names for existing callers, but the durable stream source of truth is the new event schema.

How To Test Locally

Focused codemode/shared validation:

pnpm --dir packages/shared exec vitest run src/stream-processors/codemode/implementation.test.ts
pnpm --dir packages/shared test:stream-processors
pnpm --dir packages/shared typecheck

OS2 contract/app validation:

pnpm --dir apps/os2-contract typecheck
pnpm --dir apps/os2 typecheck
pnpm --dir apps/os2 test:codemode-session
pnpm --dir apps/os2 test:project-mcp-server-connection
pnpm exec oxlint . --threads 1 --deny-warnings

Full regular OS2 unit suite:

pnpm --dir apps/os2 test

Note: the Cloudflare worker-pool tests currently print sourcemap warnings and a WebSocket close message, but the test scripts exit successfully.

How To Test In Preview

  1. Wait for Preview / deploy and Preview / e2e to pass on the latest commit.
  2. Use the OS preview URL from the Cloudflare preview block on this PR. The previous deployment was https://os2.iterate-preview-2.com; after this commit, prefer the refreshed preview block/check output.
  3. Log in normally.
  4. Open a project and go to:
/orgs/<organizationSlug>/projects/<projectSlug>/codemode-sessions/new
  1. Create a codemode session with a script that does not require an external provider:
async () => {
  console.log("codemode preview smoke");
  return { ok: true, value: 2 + 2 };
}
  1. Open the session detail page and verify the durable stream contains:
events.iterate.com/codemode/script-execution-requested
events.iterate.com/codemode/log-emitted
events.iterate.com/codemode/script-execution-completed
  1. The completed event should contain:
{
  outcome: { status: "succeeded", output: { ok: true, value: 4 } }
}

Provider-to-provider calling is currently proven by the shared processor test, not by a production Slack/streams provider in the preview UI. In preview, only run scripts that call provider paths if the stream has a processor expected to append the matching function-call-completed; otherwise codemode is correctly waiting for an event that never arrives.

Validation Done On This Commit

pnpm --dir packages/shared exec vitest run src/stream-processors/codemode/implementation.test.ts
pnpm --dir packages/shared test:stream-processors
pnpm --dir packages/shared typecheck
pnpm exec oxlint packages/shared/src/stream-processors/codemode/implementation.test.ts --deny-warnings

Earlier validation on this PR, before the latest POC-only test update:

pnpm exec oxlint . --threads 1 --deny-warnings
pnpm --dir apps/os2-contract typecheck
pnpm --dir apps/os2 typecheck
pnpm --dir packages/shared typecheck
pnpm --dir packages/shared test:stream-processors
pnpm --dir apps/os2 test
pnpm --dir apps/os2 test:codemode-session
pnpm --dir apps/os2 test:project-mcp-server-connection

Environment Config Lease

No active environment config lease.

Agents

Status: released
Commit: ca511be
Preview: https://agents.iterate-preview-2.com
Summary: Preview app released.
Workflow run
Updated: 2026-05-08T10:14:06.478Z

Events

Status: released
Commit: ca511be
Preview: https://events.iterate-preview-2.com
Summary: Preview app released.
Workflow run
Updated: 2026-05-08T10:13:53.795Z

Example

Status: released
Commit: ca511be
Preview: https://example.iterate-preview-2.com
Summary: Preview app released.
Workflow run
Updated: 2026-05-08T10:14:05.713Z

Ingress Proxy

Status: released
Commit: 946d482
Preview: https://ingress-proxy.iterate-preview-2.com
Summary: Preview app released.
Workflow run
Updated: 2026-05-08T10:14:04.815Z

OS

Status: released
Commit: ca511be
Preview: https://os2.iterate-preview-2.com
Summary: Preview app released.
Workflow run
Updated: 2026-05-08T10:14:08.788Z

Semaphore

Status: released
Commit: 946d482
Preview: https://semaphore.iterate-preview-2.com
Summary: Preview app released.
Workflow run
Updated: 2026-05-08T10:14:08.771Z


Note

High Risk
High risk because it changes stream identity semantics (projectSlugnamespace/projectId), Durable Object naming/routing for stream processor runners, and includes D1 schema migrations for secrets, all of which can break cross-service compatibility and existing data access if misaligned.

Overview
Unifies stream identity and types across the repo. Most call sites stop importing stream/event schemas from @iterate-com/events-contract and instead use @iterate-com/shared/streams/types, while “project slug” semantics are renamed to namespace/projectId and propagated through Agents and Events clients/URLs.

Simplifies runner addressing. Stream processor runner WebSocket callback URLs and server handlers are changed so the Durable Object name is the StreamPath (encoded in the URL path), removing the separate derived runnerInstance + ?streamPath= parameter and deleting streamPathToAgentInstance.

Reshapes Events/contract boundaries and deployment wiring. apps/events-contract is reduced to exporting only eventsContract (dropping extra types/tests), apps/events can now bind STREAM to an OS2-deployed StreamDurableObject via DEPLOYMENT_CONFIG_STREAM_DURABLE_OBJECT_BINDING_SCRIPT_NAME, and preview/local add an E2E_APPEND_CHAIN_SUBSCRIBER DO plus a new deployed e2e covering callable-subscriber recursion.

Updates Events data/UI and misc config. Secrets storage migrates from project_slugproject_idnamespace with new indexes/migrations, the Events stream page adds debug links (__kv, __outerbase) built from structured DO names, MCP Cloudflare config is switched to the general cloudflare-api endpoint, and a daemon code block viewer is forced to vsCodeLight theme.

Reviewed by Cursor Bugbot for commit ca511be. Bugbot is set up for automated code reviews on this repo. Configure here.

@jonastemplestein jonastemplestein marked this pull request as ready for review May 5, 2026 18:49
Comment thread apps/os2/src/durable-objects/project-mcp-server-connection.ts Outdated
Comment thread apps/os2-contract/src/index.ts Outdated
@jonastemplestein jonastemplestein changed the title [codex] Refactor codemode around function call events Refactor codemode around durable function call events May 5, 2026
Comment thread apps/os2/src/codemode/examples.ts Outdated
Comment thread apps/os2/src/durable-objects/codemode-session.ts Outdated
Comment thread packages/shared/src/stream-processors/codemode/implementation.ts
@jonastemplestein jonastemplestein force-pushed the raspy-produce branch 3 times, most recently from d0e108c to 5830ffc Compare May 5, 2026 19:57
@jonastemplestein jonastemplestein changed the title Refactor codemode around durable function call events Make codemode function calls event-driven May 5, 2026
Comment thread apps/agents/src/lib/events-urls.ts
Comment thread apps/events/src/entry.workerd.ts
# Conflicts:
#	apps/agents/alchemy.run.ts
#	apps/agents/scripts/event-stream-terminal.ts
#	apps/agents/src/orpc/routers/create-agent.ts
#	apps/events-contract/src/external-subscriber-types.test.ts
#	packages/shared/src/streams/external-subscriber-types.ts
Comment thread apps/agents/src/lib/events-urls.ts
jonastemplestein and others added 10 commits May 7, 2026 17:43
Dark mode is off in all apps, so drop vsCodeDark and the useTheme
dependency from code block components.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The append-event form now starts collapsed, giving priority to the
event stream. A "Show controls" toggle reveals the form when needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Session names containing slashes (e.g. JSON with streamPath) caused
%2F in the URL path. On reload the server decodes %2F to / before
route matching, creating phantom path segments and an infinite
redirect.

Use TanStack Router's idiomatic params.parse/stringify to base64url-
encode the session name in the URL. safeDecodeBase64Url falls back to
the raw value so old-style links still work.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread apps/agents/src/lib/events-urls.ts

@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 aa95536. Configure here.

const extensions: CodeMirrorProps["extensions"] = [
basicSetup,
codeMirrorTheme,
vsCodeLight,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Dark mode theme support silently removed from code block

Low Severity

The useTheme hook and vsCodeDark import were removed, hardcoding vsCodeLight regardless of the user's dark/light mode preference. Users in dark mode will now see a light-themed code block, which is a visual regression unrelated to the PR's stated goals.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit aa95536. Configure here.

jonastemplestein and others added 7 commits May 8, 2026 08:59
Adds a renderer mode dropdown to the shared EventsStreamView header
(next to the element type filter). Consumers in apps/os2 can now toggle
between the default "Raw + Pretty" view and a "Raw YAML" dump of all
events. Also adds lightweight semantic renderers for the new
script-execution-requested and script-execution-completed codemode events,
reusing the existing codemode-block and codemode-result element types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
next-themes' enableColorScheme injects an inline script that sets
color-scheme on the html element based on system preference, even when
forcedTheme is set. This caused CodeMirror editors to render with dark
backgrounds in apps that force light theme (like apps/events).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jonastemplestein jonastemplestein merged commit 284193e into main May 8, 2026
11 checks passed
@jonastemplestein jonastemplestein deleted the raspy-produce branch May 8, 2026 10:12
jonastemplestein added a commit that referenced this pull request Jun 10, 2026
- tasks/cf-prd-orphaned-resources-cleanup.md: completed — prd account is down to 14 worker scripts and 6 D1 databases per live 2026-06-10 Cloudflare API check (was 1026 at the 2026-05-18 sweep)
- tasks/complete/2026-05-22-os-captun-worker-test-tunnel.md: completed — shipped via merged PR #1361; all described artifacts exist on main and survived the golden-path rebuild (#1411)
- tasks/dead-code-and-docs-cleanup-audit.md: completed — all high-confidence items shipped; pnpm-workspace.yaml now uses apps/*/packages/* globs and no longer lists the dead packages
- tasks/github-oauth-use-repo-id.md: obsolete — all referenced code (linkExternalIdToGroups / repoId / repository.id) is gone repo-wide
- tasks/ignoreme-email-security.md: obsolete — every targeted code path was deleted with the legacy OS1 stack in commit 545854d (#1341)
- tasks/os-auth-spurious-logout-refresh.md: completed — commit ad6da76 (#1410, merged 2026-06-10) shipped exactly this work
- tasks/os-codemode-router.md: completed — task file was added in the very PR that implemented it (commit 98ee148, #1294)
- tasks/os-domain-capability-orpc-refactor-design.md: completed — every major pillar of the design (domains layout, capabilities, oRPC structure) exists on main
- tasks/os-domain-capability-orpc-refactor-prd.md: completed — shipped in PR #1305 "Make codemode function calls event-driven" (squash commit 284193e, merged 2026-05-08)
- tasks/os-stream-runtime-big-refactors.md: obsolete — os2-era brainstorm list largely superseded or done differently; item 2 shipped via PR #1394
- tasks/realtime-pusher-efficiency.md: obsolete — targets the legacy OS1 realtime pusher, which no longer exists
- tasks/semaphore-lease-renewal.md: completed — lease renewal exists on main as resources.renew in apps/semaphore
- tasks/signup-slug-uniqueness.md: completed — shipped with the auth worker (PR #1273); packages/shared/src/slug.ts implements resolveUniqueSlug/slugifyWithSuffix
- tasks/stream-processor-ergonomics.md: obsolete — targets the legacy hook-style processor API replaced by the class-based StreamProcessor model
- apps/os/tasks/codemode-session-night-plan.md: completed — planned outcomes verifiably shipped on main in evolved form (codemode session UI and friends)
- apps/os/tasks/codemode-session-vertical-slice.md: completed — all 11 ticked checklist items shipped via PRs #1294/#1305 and follow-ups
- apps/os/tasks/refactor-lifecycle-init-params-as-structured-name.md: completed — every acceptance criterion implemented in with-lifecycle-hooks.ts mixin on main
- apps/os/tasks/repos-vertical-slice.md: completed — frontmatter says state: done and the described slice exists on main
- apps/os/tasks/slack-google-auth-poc-implementation.md: historical log — explicitly an implementation log (state: done); work shipped in merged PR #1317
- apps/os/tasks/slack-processor-unwind.md: completed — all target-shape items exist on main (/integrations/slack stream path, no webhooks refs)
- apps/os/tasks/stream-processor-class-design-notes.md: historical log — design notes written alongside the class-based StreamProcessor migration, not a task
- apps/os/tasks/workspace-codemode-implementation-log.md: historical log — frontmatter state: done, all 9 checkpoints ticked, work verifiably shipped on main

Already deleted by earlier commits on this branch (skipped):
apps/os/tasks/project-egress-secrets-mvp.md,
apps/os/tasks/simplify-context-cloudflare-native.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jonastemplestein added a commit that referenced this pull request Jun 10, 2026
- tasks/cf-prd-orphaned-resources-cleanup.md: completed — prd account is down to 14 worker scripts and 6 D1 databases per live 2026-06-10 Cloudflare API check (was 1026 at the 2026-05-18 sweep)
- tasks/complete/2026-05-22-os-captun-worker-test-tunnel.md: completed — shipped via merged PR #1361; all described artifacts exist on main and survived the golden-path rebuild (#1411)
- tasks/dead-code-and-docs-cleanup-audit.md: completed — all high-confidence items shipped; pnpm-workspace.yaml now uses apps/*/packages/* globs and no longer lists the dead packages
- tasks/github-oauth-use-repo-id.md: obsolete — all referenced code (linkExternalIdToGroups / repoId / repository.id) is gone repo-wide
- tasks/ignoreme-email-security.md: obsolete — every targeted code path was deleted with the legacy OS1 stack in commit 545854d (#1341)
- tasks/os-auth-spurious-logout-refresh.md: completed — commit ad6da76 (#1410, merged 2026-06-10) shipped exactly this work
- tasks/os-codemode-router.md: completed — task file was added in the very PR that implemented it (commit 98ee148, #1294)
- tasks/os-domain-capability-orpc-refactor-design.md: completed — every major pillar of the design (domains layout, capabilities, oRPC structure) exists on main
- tasks/os-domain-capability-orpc-refactor-prd.md: completed — shipped in PR #1305 "Make codemode function calls event-driven" (squash commit 284193e, merged 2026-05-08)
- tasks/os-stream-runtime-big-refactors.md: obsolete — os2-era brainstorm list largely superseded or done differently; item 2 shipped via PR #1394
- tasks/realtime-pusher-efficiency.md: obsolete — targets the legacy OS1 realtime pusher, which no longer exists
- tasks/semaphore-lease-renewal.md: completed — lease renewal exists on main as resources.renew in apps/semaphore
- tasks/signup-slug-uniqueness.md: completed — shipped with the auth worker (PR #1273); packages/shared/src/slug.ts implements resolveUniqueSlug/slugifyWithSuffix
- tasks/stream-processor-ergonomics.md: obsolete — targets the legacy hook-style processor API replaced by the class-based StreamProcessor model
- apps/os/tasks/codemode-session-night-plan.md: completed — planned outcomes verifiably shipped on main in evolved form (codemode session UI and friends)
- apps/os/tasks/codemode-session-vertical-slice.md: completed — all 11 ticked checklist items shipped via PRs #1294/#1305 and follow-ups
- apps/os/tasks/refactor-lifecycle-init-params-as-structured-name.md: completed — every acceptance criterion implemented in with-lifecycle-hooks.ts mixin on main
- apps/os/tasks/repos-vertical-slice.md: completed — frontmatter says state: done and the described slice exists on main
- apps/os/tasks/slack-google-auth-poc-implementation.md: historical log — explicitly an implementation log (state: done); work shipped in merged PR #1317
- apps/os/tasks/slack-processor-unwind.md: completed — all target-shape items exist on main (/integrations/slack stream path, no webhooks refs)
- apps/os/tasks/stream-processor-class-design-notes.md: historical log — design notes written alongside the class-based StreamProcessor migration, not a task
- apps/os/tasks/workspace-codemode-implementation-log.md: historical log — frontmatter state: done, all 9 checkpoints ticked, work verifiably shipped on main

Already deleted by earlier commits on this branch (skipped):
apps/os/tasks/project-egress-secrets-mvp.md,
apps/os/tasks/simplify-context-cloudflare-native.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jonastemplestein added a commit that referenced this pull request Jun 10, 2026
…capnweb pointers, fix task states (#1432)

Documentation sweep over `apps/os`. Every statement written into a doc
was verified against the code on this branch.

## Changes

**`apps/os/README.md` (= `AGENTS.md`)**
- Important Files: `src/app.ts` / `src/entry.workerd.ts` do not exist —
replaced with `src/worker.ts` (Worker entrypoint) and `src/config.ts`
(`AppConfig` schema). All other listed files verified to exist.
- Real-worker tests: the documented vitest configs
(`src/capnweb/e2e/vitest.config.ts`,
`src/domains/capability-prototype/e2e.vitest.config.ts`) are gone —
replaced with the real lanes `pnpm e2e` (`e2e/vitest.config.ts`) and
`pnpm e2e:itx` (`src/itx/e2e/vitest.config.ts`), verified against
`apps/os/package.json`.
- `pnpm cf:deploy # production deploy` was wrong and dangerous:
`cf:deploy` deploys to whatever Doppler/Alchemy stage is ambient. Now
documents both `cf:deploy` (ambient stage) and `pnpm deploy` (the
`doppler --config prd` wrapper).
- Removed the nonexistent `/org/:organizationSlug` route; remaining
routes verified against `src/routes/`; added `/new-project`.

**`apps/os/CONTEXT.md`** — fixed the example-dialogue claim that
organization UI lives under `/org/:organizationSlug` (no such route;
orgs live in the auth worker).

**`apps/os/docs/architecture-and-operations.md`** — rewritten. The old
doc described the pre-migration world: Clerk auth (whole `## Clerk`
section, `sync-clerk-apps.ts`, `APP_CONFIG_CLERK__*`),
`/orgs/:organizationSlug` route maps, inbound MCP via
`ProjectMcpServerEntrypoint` (now a hardcoded 410 tombstone), wrong
redirect claims, and an unprefixed `/durable-objects/stream` debug
route. The new doc describes current reality: `src/worker.ts` dispatch
pipeline, Iterate Auth middleware, real route map and root-redirect
behavior (`/` → `/projects/$projectSlug` or `/projects`; project root
renders `ProjectHomePage`), canonical MCP endpoint from
`APP_CONFIG_MCP__BASE_URL` with Iterate Auth protected-resource
metadata, `/__durable-objects/<kind>/<name>/<path>` debug proxy (kinds
verified), itx endpoints, `scripts/sync-auth-clients.ts`, current
codemode default/example providers, and current smoke-test env vars
(verified in the e2e test files).

**`apps/os/docs/headless-local-debugging.md`** — `/projects/new` → the
real route `/new-project`.

**`apps/os/docs/iterate-context.md`, `iterate-context-learnings.md`** —
both pointed at the deleted `src/capnweb/` tree as "the current design";
now short tombstones pointing at the successor (`src/itx/` README +
DECISIONS, `docs/itx-spec.md`).

**`apps/os/docs/capability-system-research-and-design-notes.md`,
`rpc-target-constructor-shape-research.md`** — added status headers
marking them historical research notes superseded by itx; bodies
untouched.

**`apps/os/src/itx/README.md` + `src/itx/handle.ts`** — the "Typed caps"
`ProjectCaps` declaration-merging pattern does not exist in code (no
`ProjectCaps` interface anywhere). Rewrote the README section to the
thing that actually works: casting `itx.cap("name")` through the
exported `Stubify<T>` type. Also fixed the same false claim in the
`Stubify` doc comment in `handle.ts` (comment-only change).

**`apps/os/docs/itx-spec.md`** — status header said "IMPLEMENTED on the
`itx-implementation` branch"; PR #1407 is merged to main (verified in
git history). Marked the one known divergence honestly: the §6.3 client
reconnect loop was never built — `connectItx` (`src/itx/client.ts`) is
one-shot, and there is no `itx.cap.disconnected` event. Corrected §6.3
and the related §4 caveat.

**`apps/os/tasks/`**
- Deleted `simplify-context-cloudflare-native.md` (state: todo, but
shipped — `src/worker.ts` imports `env` from `cloudflare:workers`
directly, `RequestContext` is the narrow request-scoped shape the task
specified, auth lives in Start request middleware, the
manifest/`src/app.ts` is gone).
- Deleted `project-egress-secrets-mvp.md` (state: todo, but shipped —
`ProjectEgress` entrypoint, `ProjectDurableObject.egressFetch` with
`substituteProjectEgressSecretHeaders`, D1-backed
`SecretsCapability.getSecret`, and the `/api/itx/egress-echo` echo proof
covered by `src/itx/e2e/itx-egress.e2e.test.ts`).
- Grooming rules (`docs/tasks-grooming.md`) say "Delete when done", so
deletion rather than state edits.
- Added brief status notes (no rewrite) to
`codemode-session-vertical-slice.md` (checked-off "tiny worker" box
diverged: `CodemodeSession` lives in the main OS worker) and
`codemode-session-night-plan.md` (plan superseded by itx).

## Skipped
- Nothing skipped; all nine items verified and addressed.

## Flags for reviewers
- `src/itx/handle.ts` got a comment-only edit (the `Stubify` doc comment
made the same false declaration-merging claim as the README). No runtime
change; typecheck/lint/tests pass.
- The two deleted task files: please sanity-check the "shipped" verdicts
above if you have more context on intended remaining scope.
- Carve-outs respected: no changes to the streams type systems or to how
the os-streams worker is deployed.

## Checks
- `pnpm install`, `pnpm format` (oxfmt), `pnpm typecheck`, `pnpm lint`,
`pnpm test` — all pass.

## Task-file audit

A follow-up commit deletes 22 task files whose work was verified as
shipped, obsolete, or purely historical. (Two more from the audit —
`apps/os/tasks/project-egress-secrets-mvp.md` and
`apps/os/tasks/simplify-context-cloudflare-native.md` — were already
deleted by earlier commits on this branch, see above.)

### Deleted: completed

- `tasks/cf-prd-orphaned-resources-cleanup.md` — live Cloudflare API
check of the prd account (2026-06-10) shows 14 worker scripts (was 1026
at the task's 2026-05-18 sweep) and 6 D1 databases; cleanup is done.
- `tasks/complete/2026-05-22-os-captun-worker-test-tunnel.md` — shipped
via merged PR #1361 ("codemode++ e2e++"); all described artifacts exist
on main and survived the golden-path rebuild (#1411).
- `tasks/dead-code-and-docs-cleanup-audit.md` — high-confidence items
all shipped; `pnpm-workspace.yaml` no longer lists the dead packages and
now uses `apps/*`/`packages/*` globs.
- `tasks/os-auth-spurious-logout-refresh.md` — commit ad6da76 "Fix
5-min logout, deploy-time JWKS, and stream append skeleton flash
(#1410)" (merged 2026-06-10) shipped exactly this work.
- `tasks/os-codemode-router.md` — task file was added in the very PR
that implemented it (commit 98ee148, #1294).
- `tasks/os-domain-capability-orpc-refactor-design.md` — every major
pillar of the design (domains layout, capabilities, oRPC structure)
exists on main.
- `tasks/os-domain-capability-orpc-refactor-prd.md` — shipped in PR
#1305 "Make codemode function calls event-driven" (squash commit
284193e, merged 2026-05-08).
- `tasks/semaphore-lease-renewal.md` — the described lease-renewal
feature exists on main as `resources.renew` (named "renew" rather than
the proposed "extend") in `apps/semaphore`.
- `tasks/signup-slug-uniqueness.md` — shipped with the auth worker (PR
#1273); `packages/shared/src/slug.ts` implements
`resolveUniqueSlug`/`slugifyWithSuffix`.
- `apps/os/tasks/codemode-session-night-plan.md` — planned outcomes
verifiably shipped on main, in evolved form (codemode session browser UI
and follow-ons).
- `apps/os/tasks/codemode-session-vertical-slice.md` — all 11 ticked
checklist items shipped via PRs #1294/#1305 and follow-ups.
- `apps/os/tasks/refactor-lifecycle-init-params-as-structured-name.md` —
every acceptance criterion implemented in the `with-lifecycle-hooks.ts`
mixin on main.
- `apps/os/tasks/repos-vertical-slice.md` — frontmatter already says
`state: done` and the described slice verifiably exists on main.
- `apps/os/tasks/slack-processor-unwind.md` — all target-shape items
exist on main (`/integrations/slack` stream path; no
`/integrations/slack/webhooks` references).

### Deleted: obsolete / nonsense

- `tasks/github-oauth-use-repo-id.md` — all referenced code is gone:
`linkExternalIdToGroups` / `repoId` / `repository.id` return zero hits
repo-wide.
- `tasks/ignoreme-email-security.md` — every code path the task targets
was deleted with the legacy OS1 stack (commit 545854d, #1341).
- `tasks/os-stream-runtime-big-refactors.md` — os2-era brainstorm list
largely superseded or done differently; item 2 shipped via PR #1394.
- `tasks/realtime-pusher-efficiency.md` — targets the legacy OS1
realtime pusher, which no longer exists.
- `tasks/stream-processor-ergonomics.md` — targets the legacy hook-style
processor API, replaced by the class-based StreamProcessor model.

### Deleted: historical logs

- `apps/os/tasks/slack-google-auth-poc-implementation.md` — explicitly
an "Implementation Log" (`state: done`), not actionable work; shipped in
merged PR #1317.
- `apps/os/tasks/stream-processor-class-design-notes.md` — design notes
written alongside the class-based StreamProcessor migration, not a task.
- `apps/os/tasks/workspace-codemode-implementation-log.md` — `state:
done`, all 9 checkpoints ticked; the described work verifiably shipped
on main.

### Kept but flagged for maintainer judgment

- `tasks/cf-prd-orphaned-resources-cleanup.md`: Explicit not-in-scope
follow-ups (preview account 376ef7ed cleanup, Doppler os-legacy-backup
pruning) were never broken out into their own tasks; spin them out only
if still wanted.
- `tasks/codemode-capability-policy.md`: Still-unshipped, still-wanted
design work, but duplicates
`apps/os/tasks/codemode-capability-access-policy.md` and overlaps the
active itx capability-system design notes — maintainer should
consolidate into a single task.
- `tasks/complete/2026-05-22-os-captun-worker-test-tunnel.md`: apps/os
still depends on the unpublished pkg.pr.new/captun@14 build (the task's
stated stopgap); a published captun/worker release would be a separate
follow-up, not a reason to keep this file.
- `tasks/dead-code-and-docs-cleanup-audit.md`: Residual from this audit:
packages/iterate is still excluded from root build/typecheck/test
(`--filter '!iterate'`); if that CI gap matters, open a fresh small task
rather than keeping this stale inventory.
- `tasks/doppler-shared-and-os-secrets-audit.md`: Audit still unrun and
wanted, but needs a rewrite first: replace Clerk-key expectations with
iterateAuth, point AppConfig refs at `apps/os/src/config.ts` (`app.ts`
and `packages/shared/src/apps/config.ts` were deleted in PR #1411), and
refresh the 2026-05-18 baseline.
- `tasks/ignoreme-email-security.md`: If outbound email via Resend is
ever reintroduced in the rebuilt apps/os, recipient allowlisting should
be designed fresh against the itx/egress-secret-substitution layer, not
this OS1-era plan.
- `tasks/iterate-cli-distribution.md`: Live but ~90% of the file is
OpenCode architecture research notes, not actionable steps; npm
distribution already exists, so the remaining work (bun binary, brew,
install script) should be restated as concrete tasks or the research
trimmed.
- `tasks/os-auth-spurious-logout-refresh.md`: PR #1410 left one open
thread: a manual end-to-end "wait 5 minutes in prod" verification was
never done, and the claims-staleness force-refresh was consciously
skipped (≤30m propagation accepted) — file a new narrow task only if
either still matters.
- `tasks/os-deploy-time-jwks-fetch.md`: Code shipped in PR #1410; only
remaining action is deleting `ITERATE_AUTH_JWKS` from Doppler os
prd/preview (still present and shadowing the deploy-time fetch) — after
that, delete this task.
- `tasks/os-domain-capability-orpc-refactor-prd.md`: Sibling task
`os-domain-capability-orpc-refactor-design.md` (its dependsOn target) is
likely also completed and should be audited/deleted together.
- `tasks/os-project-do-projection-reconciliation.md`: Scope item "rename
IterateMcpServer to ProjectMcpServerConnection" is already done and
could be ticked off; the rest is unshipped and still relevant.
- `tasks/os-project-hostname-base-singular.md`: Scope file paths are
stale post-PR #1411 (`app.ts`→`src/config.ts`,
`sync-clerk-apps.ts`→`sync-auth-clients.ts`, `entry.workerd.ts` deleted,
routing files moved to `src/ingress/`); task itself is still valid.
- `tasks/os-project-route-authorization.md`: Still-wanted design work
(referenced by live project-ingress-architecture task), but needs
rewrite: Clerk OAuth and `ProjectMcpServerEntrypoint` references are
dead — MCP moved off project ingress (410 stub) and auth is now
apps/auth Principal-based.
- `tasks/os-stream-runtime-big-refactors.md`: Only surviving idea:
cosmetic no-compat rename of `events.iterate.com/...` event-type names
(events app is deleted); re-file as a small standalone task if still
wanted.
- `apps/os/tasks/codemode-capability-access-policy.md`: Live work, but
near-duplicates root-level `tasks/codemode-capability-policy.md` (same
PR #1294); keep this copy and consolidate/delete the root one.
- `apps/os/tasks/codemode-session-night-plan.md`: Open capability-scope
questions from this plan live on in
`codemode-capability-access-policy.md`; checkboxes are unticked but the
work shipped via PRs #1294/#1305/#1402.
- `apps/os/tasks/codemode-session-vertical-slice.md`: Last unchecked box
(generalize self-callable bindings) shipped as the loopback-binding
pattern used repo-wide; follow-on work lives in
`codemode-session-night-plan.md`.
- `apps/os/tasks/project-egress-and-secrets-architecture.md`: Design doc
whose first vertical slice shipped (egress + secret substitution MVP);
remaining secret-DO/policy/approval/OAuth design is still live but needs
grooming: drop completed PoC sections, update Clerk-scope terminology,
and reconcile with itx DECISIONS.md as the newer design-of-record for
egress wiring.
- `apps/os/tasks/project-egress-intercept-tunnel-latency.md`:
Still-relevant latency work, but file refs are stale (`entry.workerd.ts`
→ `src/worker.ts`; vendored `apps/os/src/lib/captun` removed for the
published captun package in #1361) and the benchmark numbers predate the
#1411 worker rebuild — re-benchmark before picking an option.
- `apps/os/tasks/project-ingress-architecture.md`: Live,
actively-maintained ingress reference (edited today in #1416), but needs
a refresh: Clerk auth sections, `Project.checkAccess`, and the
streams-upstream proxy model are superseded (auth worker, principal
claims, bundled project worker), and the 2026-05-05 status checklist is
partly outdated.
- `apps/os/tasks/stream-processor-class-migration-log.md`: Migration log
(merged today via #1402, which links to it as the canonical rationale) —
not an actionable task; contains unique I6-I8 forensics not in the PR
body, consider moving to docs/ alongside `tasks/migration-notes/` rather
than deleting.
- `apps/os/tasks/stream-subscriber-delivery-refactor.md`: Core design
shipped differently via the class-model cutover (#1401/#1402/#1394);
only live remainder is migrating `codemode.streamEvents`,
`StreamsCapability.stream()`, and project-mcp-server-connection off the
OS-internal NDJSON shim in `new-stream-runtime.ts` — consider replacing
this large draft with a small task for that.
- `apps/os/tasks/workspace-codemode-implementation-log.md`: Done
implementation log; only marginally unique note is the rationale that
plain method objects (not class instances) cross DO RPC, which is now
embodied in the shipped workspace DO code.
- `apps/os/tasks/migration-notes/`: Historical migration logs (not
tasks) committed with and cited by merged PR #1402 one day ago; contain
unique per-domain decisions plus the legacy-subscriber gap behind the
2026-06-10 prd Slack outage — maintainer should relocate to docs/ or
delete deliberately.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Documentation and task-file deletions only; no application runtime or
API behavior changes in the diff.
> 
> **Overview**
> **Aligns OS documentation with the current worker, auth, routing, and
itx reality**, and **removes a large set of completed or obsolete task
files** from `apps/os/tasks/` and `tasks/`.
> 
> The **README / AGENTS** and **`architecture-and-operations.md`**
rewrites drop Clerk-era and deleted-entrypoint references (`src/app.ts`,
`src/entry.workerd.ts`, `/org/:organizationSlug`) in favor of
**`src/worker.ts`**, **Iterate Auth**, **project-scoped routes**
(`/projects/...`, `/new-project`), **canonical MCP**
(`APP_CONFIG_MCP__BASE_URL`, auth-worker OAuth), **itx** endpoints, and
**`sync-auth-clients.ts`**. Deploy docs now distinguish ambient **`pnpm
cf:deploy`** from production **`pnpm deploy`**. E2E docs point at
**`pnpm e2e`** and **`pnpm e2e:itx`** instead of removed capnweb vitest
configs.
> 
> **Cap'n Web tombstones** in `iterate-context*.md` redirect readers to
**itx** (`src/itx/`, `itx-spec.md`). Research notes get **historical**
headers; **itx-spec** notes merged status on main and documents that
**`connectItx` is one-shot** (no §6.3 reconnect loop). **itx README /
`Stubify`** docs are corrected: typed caps use **`itx.cap("name") as
Stubify<...>`**, not declaration merging.
> 
> **CONTEXT.md** fixes the example that claimed org UI lived under
`/org/...`. **headless-local-debugging** uses **`/new-project`**.
> 
> **Task grooming** deletes many markdown tasks whose work is done,
superseded (itx, auth worker), or OS1-dead — including codemode
vertical-slice plans, domain oRPC refactor design, egress MVP, Slack
processor unwind, and similar inventory items.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a4f093f. 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-10T12:23:34.040Z",
      "headSha": "a4f093f29684fc65b851dbf53847ccd85ddf8ffc",
      "message": null,
      "publicUrl": "https://os.iterate-preview-5.com",
"runUrl": "https://github.com/iterate/iterate/actions/runs/27275677688",
      "shortSha": "a4f093f"
    }
  },
  "environmentConfigLease": {
    "dopplerConfig": "preview_5",
    "leasedUntil": 1781097591555,
    "leaseId": "36e57584-6cc7-4024-a027-103a3cb0b29b",
    "slug": "preview-5",
    "type": "environment-config-lease"
  }
}
-->
<!-- /CLOUDFLARE_PREVIEW_STATE -->
Lease: `preview-5`
Doppler config: `preview_5`
Type: `environment-config-lease`
Leased until: 2026-06-10T13:19:51.555Z

### OS
Status: deployed
Commit: `a4f093f`
Preview: https://os.iterate-preview-5.com
[Workflow
run](https://github.com/iterate/iterate/actions/runs/27275677688)
Updated: 2026-06-10T12:23:34.040Z
<!-- /CLOUDFLARE_PREVIEW -->

---------

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