Skip to content

codemode rip, part 3: delete the domain#1447

Merged
jonastemplestein merged 6 commits into
mainfrom
rip-codemode-delete
Jun 10, 2026
Merged

codemode rip, part 3: delete the domain#1447
jonastemplestein merged 6 commits into
mainfrom
rip-codemode-delete

Conversation

@jonastemplestein

@jonastemplestein jonastemplestein commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Stacked on #1446. The codemode domain is deleted — net -8.3k lines.

What went where

  • CodemodeSession DO → tombstone. The class + CODEMODE_SESSION binding deliberately keep existing: production streams carry durable callable subscribers that dial the namespace by name, and a vanished class is exactly the 2026-06-10 legacy-subscriber outage. The tombstone accepts requestStreamSubscription dials and no-ops (with a warning log). Proper removal = follow-up with a DO deletion migration + stream subscriber cleanup, after this soaks.
  • AiCapability / OrpcCapabilitysrc/rpc-targets/os-capabilities.ts (they're itx caps now, not codemode examples).
  • ExecuteCodemodeFunctionCallInputsrc/rpc-targets/legacy-codemode-call.ts; capability entrypoints keep the legacy method while callers migrate to call({ path, args }). SlackCapability gains a real call().
  • Agent contexts gain slack + agents caps (SlackCapability path-call with the old etiquette instructions, AgentCapability members for pipelined subagents) — restoring the full pre-itx provider surface.
  • Per-context workspaces: ctx.workspace on a child context now maps to workspace itx:<contextId> (derived identically in handle.ts and the agent's workspace prep). Existing agents re-clone iterate-config once into the new workspace id.
  • UI/oRPC: project.codemode contract + router, codemode-sessions routes, session controls, and the new-agent tool-provider compiler are deleted — the Agent DO seeds caps (and the LLM-visible capability notes) on wake, so the form stops compiling registration events.
  • slack-integration bootstrap stops subscribing codemode to routed streams.

Test changes

  • Deleted: codemode e2e suites, codemode-builder, and e2e-test-map.e2e.test.ts (built entirely on the codemode fixture; the itx e2e suite covers the replacement model).
  • agents.e2e converted to itx events. Coverage honestly lost with the per-call event mechanism: function-call-level assertions (workspace op sequence, slack-call payload echo, debug-output sanitization) — those now verify via generated code + execution-completed ok + the real side effects.
  • Unit: 205 passing; repo-wide typecheck/lint/format green.

Follow-ups (noted in itx-next.md territory)

  • prd/preview cleanup: tombstone soak → DO deletion migration + subscriber-event cleanup.
  • executeCodemodeFunctionCall legacy methods on capability entrypoints → delete once nothing dials them.
  • packages/shared/src/codemode/* (json-schema type generation) still used by OrpcCapability's listProcedures — rename/move later.

🤖 Generated with Claude Code


Note

High Risk
Large removal of script execution, providers, and oRPC routes touches agent/Slack flows and production stream subscribers; behavior changes until tombstone subscribers are cleaned up.

Overview
Removes the codemode domain (~8k lines): the CodemodeSession DO implementation, stream processor, default/example providers, UI session controls, and the entire project.codemode oRPC surface (sessions, executeScript, streamEvents, describe).

CodemodeSession becomes a tombstone — same class/binding so existing stream callable subscribers keep dialing without outage; requestStreamSubscription no-ops with a warning until subscriber cleanup lands.

Agents run on itx instead of codemode events: script runs use runItxScript with convention: "ctx" and direct LLM code; workspaces are itx:<contextId> (aligned with the itx handle), with single-flight ensureItxContext. Capability types move to rpc-targets/legacy-codemode-call and os-capabilities; tests/assertions shift from codemode/* and per-call function events to itx/execution-* and agent/capability-noted.

E2E: codemode suites, CodemodeBuilder, and e2e-test-map are deleted; agents.e2e is updated for itx (some granular function-call assertions dropped).

Reviewed by Cursor Bugbot for commit 24365a0. 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: e59ceec
Preview: https://os.iterate-preview-9.com
Summary: Preview app released.
Workflow run
Updated: 2026-06-10T15:39:06.376Z

Semaphore

Status: released
Commit: e59ceec
Preview: https://semaphore.iterate-preview-9.com
Summary: Preview app released.
Workflow run
Updated: 2026-06-10T15:38:51.403Z

Comment thread apps/os/src/domains/agents/durable-objects/agent-durable-object.ts
Comment thread apps/os/src/domains/agents/durable-objects/agent-durable-object.ts
jonastemplestein added a commit that referenced this pull request Jun 10, 2026
Bugbot findings: (#1446 High) the agent loop shipped without the slack
cap, breaking Slack bang commands and LLM replies at this point in the
stack — the slack (full guidance text, including the quiet-reply rule and
the Promise.all acknowledgment pattern, addressing the #1447 Medium) and
agents caps move down from part 3 to where the loop lands, with the
SlackCapability call() adapter and allowlist entries. (#1447 High at its
source) ensureItxContext seeding is now versioned: bump
AGENT_CONTEXT_CAPS_VERSION and existing agents re-define caps on next
wake (defines upsert; capability-noted idempotency keys dedupe).

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

Copy link
Copy Markdown
Contributor Author

Both Bugbot findings addressed by moving the fixes down into #1446 where they belong (commit bdda255 there; this branch rebased on top in 14b7083): versioned re-seeding covers agents whose child context predates a deploy, and the seeded slack instructions carry the full quiet-reply + acknowledgment guidance from the deleted default provider.

Comment thread apps/os/src/domains/agents/durable-objects/agent-durable-object.ts
jonastemplestein added a commit that referenced this pull request Jun 10, 2026
Bugbot findings: (#1446 High) the agent loop shipped without the slack
cap, breaking Slack bang commands and LLM replies at this point in the
stack — the slack (full guidance text, including the quiet-reply rule and
the Promise.all acknowledgment pattern, addressing the #1447 Medium) and
agents caps move down from part 3 to where the loop lands, with the
SlackCapability call() adapter and allowlist entries. (#1447 High at its
source) ensureItxContext seeding is now versioned: bump
AGENT_CONTEXT_CAPS_VERSION and existing agents re-define caps on next
wake (defines upsert; capability-noted idempotency keys dedupe).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jonastemplestein added a commit that referenced this pull request Jun 10, 2026
Bugbot findings: (#1446 High) the agent loop shipped without the slack
cap, breaking Slack bang commands and LLM replies at this point in the
stack — the slack (full guidance text, including the quiet-reply rule and
the Promise.all acknowledgment pattern, addressing the #1447 Medium) and
agents caps move down from part 3 to where the loop lands, with the
SlackCapability call() adapter and allowlist entries. (#1447 High at its
source) ensureItxContext seeding is now versioned: bump
AGENT_CONTEXT_CAPS_VERSION and existing agents re-define caps on next
wake (defines upsert; capability-noted idempotency keys dedupe).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jonastemplestein jonastemplestein force-pushed the rip-codemode-delete branch 2 times, most recently from dc0559b to 1a34568 Compare June 10, 2026 14:39
Base automatically changed from rip-codemode-agents to main June 10, 2026 14:49
jonastemplestein and others added 2 commits June 10, 2026 15:50
domains/codemode is gone — 8.3k lines deleted. What remains and where it
went:

- CodemodeSession DO → a tombstone class (src/durable-objects/
  codemode-session-tombstone.ts). The class and CODEMODE_SESSION binding
  MUST keep existing: production streams carry durable callable
  subscribers that dial it by name (see the 2026-06-10 legacy-subscriber
  incident). The tombstone accepts those dials and no-ops; removing the
  namespace properly is a follow-up with a DO deletion migration +
  subscriber cleanup.
- AiCapability/OrpcCapability → src/rpc-targets/os-capabilities.ts.
- ExecuteCodemodeFunctionCallInput → src/rpc-targets/
  legacy-codemode-call.ts; entrypoints keep the legacy method while
  callers migrate to call({ path, args }) (Slack gains a real call()).
- Agent caps grow slack + agents (SlackCapability path-call,
  AgentCapability members) — the full pre-itx provider surface.
- ctx.workspace: child contexts get per-context workspaces
  (itx:<contextId>, derived identically in handle.ts and the agent's
  workspace prep) — agents re-clone iterate-config once into the new id.
- slack-integration bootstrap stops subscribing codemode to routed
  streams.
- oRPC: project.codemode contract + router + UI queries deleted;
  agents/new.tsx loses the tool-provider compiler (the Agent DO seeds
  caps on wake); codemode-sessions routes + session controls deleted.
- e2e: codemode suites + e2e-test-map (codemode-builder-based) deleted —
  the itx suite covers the replacement model; agents.e2e converted to
  itx events (per-call event asserts dropped with the mechanism; the
  event-mediated deadlock + ordering tests died with the machinery).

typecheck (repo) / lint / format / unit (205) green.

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

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…txError test fix

- Single-flight ensureItxContext in the Agent DO and MCP connection
  (Bugbot High: wake-time workspace prep vs script runs could mint two
  context ids; concurrent exec_js likewise).
- MCP session seeding gains MCP_CONTEXT_CAPS_VERSION (same re-seed-on-
  version-bump semantics the agent already had).
- runItxScript gains convention: "ctx" — agent/LLM scripts (async (ctx)
  => …) are invoked directly, killing the async ({ itx, vars }) wrapper
  so the execution record carries exactly what the model wrote. vars is
  an "itx"-convention concern only.
- ItxError e2e test corrected: capnweb 0.8.0 reconstructs unknown error
  names as plain Error and DROPS the name (ERROR_TYPES[name] || Error;
  props loop skips "name"), so name identity is untransmittable — the
  test (which merged in #1456 with its e2e check skipped, so it never
  ran) now asserts the duck-typed code/details contract; errors.ts doc
  corrected to match reality.

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

Copy link
Copy Markdown
Contributor Author

Review round addressed in 24365a0: Parallel itx context initialization (High) — single-flight ensureItxContext in both the Agent DO and the MCP connection. Existing itx contexts skip caps (High) — the agent side was already version-gated (AGENT_CONTEXT_CAPS_VERSION, added in #1446); the MCP session seeding now has the same (MCP_CONTEXT_CAPS_VERSION). Slack quiet-reply guidance (Medium) — stale finding, anchored to a pre-rebase commit; the full guidance text is present.

Also in this commit: the failing ItxError e2e test was broken-on-arrival — it merged in #1456 with its Preview/e2e check skipped, and capnweb 0.8.0 provably drops custom error names on reconstruction (ERROR_TYPES[name] || Error, props loop skips name), so error.name === 'ItxError' is untransmittable. Test now asserts the duck-typed code/details contract; errors.ts doc corrected. And runItxScript gained convention: 'ctx' so agent scripts run unwrapped (execution records carry exactly what the model wrote). The other e2e failure (platform bindings, 40s) passes locally in 2s — preview AI-binding flake.

jonastemplestein and others added 3 commits June 10, 2026 16:31
- runItxScript knows exactly one calling shape, script(itx). The
  convention option and vars are gone from the runner; parameterization
  is the caller's concern (/api/itx/run keeps its vars API by baking
  vars into the source before submitting — client-helper-side wrapping).
- Agent scripts run verbatim; extractCodemodeScript accepts the legacy
  async (ctx) prefix from old histories (the parameter name is the
  author's business — the single argument is the handle either way).
- Vocabulary sweep: system prompt, capability instructions and notes,
  bang-command codegen, MCP exec_js docs (which still taught the
  destructured shape — a real bug with the one-shape runner), tests,
  e2e expectations, ItxFn in types.ts/handle.ts, README glossary, and
  the workspace preview example (renamed) all speak itx.
- iterate-mcp-server DO test: assertions moved to itx/execution-*;
  the provider-matrix test died with the machinery it exercised.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	apps/os/e2e/vitest/codemode-mcp-provider-stack.e2e.test.ts
#	apps/os/src/domains/codemode/example-provider-registrations.ts
#	apps/os/src/domains/codemode/examples.ts
#	apps/os/src/durable-objects/codemode-session.test.ts
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 e59ceec. Configure here.


#ensureItxContextPromise: Promise<string> | undefined;

async #ensureItxContextOnce(params: AgentDurableObjectStructuredName): Promise<string> {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale capability notes after reseed

Medium Severity

When AGENT_CONTEXT_CAPS_VERSION changes, #ensureItxContextOnce re-runs itxDefine with updated cap instructions but appends agent/capability-noted events using the same agent-capability-noted:${cap.name} idempotency keys as the initial seed. The stream likely dedupes those appends, so the agent processor never re-renders tool guidance while runtime caps already changed—models can follow outdated itx.slack (and other) instructions after deploy.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e59ceec. Configure here.

@jonastemplestein jonastemplestein merged commit 625792b into main Jun 10, 2026
7 of 8 checks passed
@jonastemplestein jonastemplestein deleted the rip-codemode-delete branch June 10, 2026 15:36
jonastemplestein added a commit that referenced this pull request Jun 10, 2026
Final follow-up to the codemode rip (#1445/#1446/#1447). MCP's
streamable HTTP transport is a stateless protocol — fetch with metadata
— so nothing about an MCP client belongs in a Durable Object.

## What

- **`OutboundMcpFromOurClientCapability` DO deleted** — class, worker
export, alchemy namespace + `OUTBOUND_MCP_FROM_OUR_CLIENT_CAPABILITY`
binding, vitest harness wiring. Nothing has dialed it since the codemode
rip (its only caller was the deleted provider registration).
- **Core helpers promoted** to `src/itx/caps/mcp-client-core.ts` with
clean names: `connectMcp` (custom-fetch aware, closes on failed
connect), `listMcpTools`, `executeMcpToolCall`. `McpClient` dedupes onto
them; the mock-server unit test moved and adapted.
- **The DO allusion is gone from the docs**: `McpClient`'s header now
states statelessness as the design ("connect → call → close, per
invocation; deliberately no Durable Object anywhere in this path")
instead of presenting connection caching as a future optimization.

## Deploy note

This is the repo's first Durable Object class deletion. The DO had no
SQLite (in-memory cache only) and no inbound subscribers, so deletion is
data-safe; alchemy is expected to emit the `deleted_classes` migration
on deploy — **this PR's preview deploy is the proof**. If it refuses,
the fallback is a tombstone class like `CodemodeSession`'s.

## Testing

Repo typecheck / lint / knip / unit suite green locally (incl. the moved
mock-server core test). The `McpClient` e2e remains gated on a reachable
MCP server.

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

<!-- CLOUDFLARE_PREVIEW -->
## Environment Config Lease
<!-- CLOUDFLARE_PREVIEW_STATE -->
<!--
{
  "apps": {},
  "environmentConfigLease": {
    "dopplerConfig": "preview_4",
    "leasedUntil": 1781109925654,
    "leaseId": "f7427e44-72e2-4e04-8617-122e174b3c57",
    "slug": "preview-4",
    "type": "environment-config-lease"
  }
}
-->
<!-- /CLOUDFLARE_PREVIEW_STATE -->
Lease: `preview-4`
Doppler config: `preview_4`
Type: `environment-config-lease`
Leased until: 2026-06-10T16:45:25.654Z
<!-- /CLOUDFLARE_PREVIEW -->

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
jonastemplestein added a commit that referenced this pull request Jun 10, 2026
… it in transit (#1462)

Narrowed after #1447 landed: that PR fixed the e2e test's assertions
(asserting the real wire shape, `name === "Error"` + raw `code`), which
unblocks preview e2e on main. What it did NOT fix is the detection
helper itself — `getItxErrorCode` still requires `error.name ===
"ItxError"`, and capnweb 0.8.0 drops custom error names in transit (the
receiver maps only builtin names to classes; the props loop skips `name`
on both ends). So after any capnweb hop, every runtime consumer of the
helper — react hooks, `stream-tail`, `isItxAccessError` retry predicates
— fails to recognize kernel errors and treats NOT_FOUND/FORBIDDEN like
connection noise.

Probed against a live preview deployment:

```
name: Error                    ← dropped by capnweb
code: NOT_FOUND                ← survives (own enumerable prop)
details: {"projectIdOrSlug":"definitely-not-a-project"}  ← survives
```

## Fix

`getItxErrorCode` duck-types on the closed five-code set alone; `name`
is not consulted (it cannot be, after capnweb). Set membership keeps
foreign coded errors (`ECONNREFUSED`, …) out. The unit-test
`simulateCapnwebCrossing` helper no longer reattaches `name` by hand —
that hand-modeled reattachment is exactly how the original bug stayed
green in unit tests while failing on the real wire. Docs in `errors.ts`
updated to match (merged with #1447's wording).

## Verification

- The capnweb-crossed shape (plain `Error` + `code`) is now detected;
unit tests assert it
- `pnpm test:itx-stream-subscribe` (real Workers RPC boundary, which
legitimately preserves `name`) still passes
- Full apps/os suite, typecheck, lint clean; e2e verified earlier
against a live preview deployment (preview_6)

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes shared error-classification used for retry vs access-failure
handling across capnweb clients; behavior widens slightly (code-only
shapes now match) but is constrained by the five-code allowlist.
> 
> **Overview**
> **`getItxErrorCode` no longer requires `error.name === "ItxError"`** —
it treats any object whose `code` is one of the five itx codes as an
ItxError. That matches errors after a capnweb RPC crossing, where the
receiver rebuilds a plain `Error` and **drops** the name while `code` /
`details` still arrive as own props.
> 
> Docs on `getItxErrorCode` in `errors.ts` now spell out why `name` must
not be used and how the closed code set avoids colliding with other
`code`-bearing errors (e.g. `ECONNREFUSED`).
> 
> Unit tests were aligned with real capnweb: `simulateCapnwebCrossing`
no longer re-attaches `name`, duck-typed cases use plain `Error` +
`code` only, and rejection cases use foreign codes instead of wrong
`name`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
5c3e6d3. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
mmkal added a commit that referenced this pull request Jun 10, 2026
Conflict resolutions:
- packages/iterate/src/cli.ts: took this branch's version wholesale.
  Main's only change was the superadmin->admin rename (#1453), and every
  renamed region (auth strategies, impersonation dance, device flow,
  --superadmin login flag) was already deleted here in the OAuth PKCE
  rewrite — there is nothing to port.
- apps/os/e2e/vitest/e2e-test-map.e2e.test.ts: accepted main's deletion
  (codemode rip #1447); this branch had only touched a doc comment.
- event-stream-terminal.tsx (auto-merged, needed follow-up): main's new
  listChildren itx walk gets the authedFetch arg, matching the getState
  adaptation from the previous merge.
- apps/iterate-com skills-registry.ts: took main's regenerated copy;
  this branch carried a stale-formatted version of the generated file.

Co-Authored-By: Claude Opus 4.8 (1M context) <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