Skip to content

chore(deps): upgrade Effect to stable 4.0.0 - #14914

Open
juliusmarminge wants to merge 2 commits into
mainfrom
t3code/effect-v4-stable
Open

juliusmarminge wants to merge 2 commits into
mainfrom
t3code/effect-v4-stable

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

Effect 4.0.0 is out as the first stable v4 release. Main is on 4.0.0-rc.115, which is several breaking releases behind. Between the two, Effect removed the effect/unstable/* export paths and the effect/Encoding module, and changed several APIs we rely on. This reopens #14563 against main after the new orchestrator merged (#2829).

Changes

Imports

  • All 785 files that imported effect/unstable/* now use the flattened effect/<area> paths (httpapi becomes http-api).
  • effect/Encoding is replaced by effect/encoding/{Base64,Base64Url,Hex}.

Dependencies still on the release candidates

  • Alchemy 2.0.0-beta.80 and distilled 1.0.0-rc.13 use the 4.0.0 module paths, so the relay loads again.
  • OpenCode 2 (@opencode/client, protocol, schema):
    • Bumped from 2.0.18 to 2.0.22. Every release through today still targets Effect rc.112, so all three are patched.
    • The patches rewrite the removed import paths, Encoding, and Schema.isStartsWith (renamed isStartingWith).
    • The statics helper assigned over a schema's make, which 4.0.0 caches as a non-configurable property. The patch defines the static make up front instead.
    • The patches can be dropped once OpenCode moves to stable Effect.
  • Drizzle 1.0.0-rc.5-ab785fc only references effect/unstable/sql/SqlError in its .d.ts files. Its runtime JS loads unchanged, so it needs no bump.

Behaviour changes from rc.116 to 4.0.0

  • Tracing: HttpRouter.serve now builds its routes in a private layer cache, so the "don't trace the browser trace proxy" setting stopped applying. It is now provided to the served layer, and a new http.test.ts test fails without it.
    • The same change makes services from layers around serve win over the app's own. The static-file test now provides its tracked FileSystem between serve and NodeHttpServer.layerTest.
  • Closing scopes: Scope.close now only accepts a closeable scope.
    • SSH tunnels take their entry scope explicitly.
    • The ACP and Antigravity runtimes close a child of the caller's scope.
  • ACP malformed lines: RpcSerialization.ndJsonRpc now silently skips lines that aren't valid JSON. effect-acp decodes each line with the strict codec so a malformed agent line still ends the session; the existing protocol tests failed until this was fixed.
  • Smaller API changes:
    • Effect.partition returns successes first.
    • Stream.scan takes a lazy initial state.
    • SchemaGetter.onSome and .compose are replaced.
    • Schema.brand needs a single concrete brand key.
    • Effect.orElseSucceed now passes the error to its callback.
  • One OpenCode adapter test read turn results from two consumers of the same queue. Effect's queue now hands each item to only one of them, so the test hung. It now waits on the single event drain it already forks.

Patches

  • effect:
    • The MCP DELETE session route is re-ported to 4.0.0's internal session store and now lives in the HTTP protocol layer.
    • The RpcClient hooks, the three-missed-pong tolerance and the getSetCookie guard carry over. A ping timeout now fails with upstream's SocketReadError instead of SocketOpenError.
  • @effect/vitest: still the vite-plus/test import swap. pnpm rejects catalog: in the @effect/vitest package extension once it re-resolves, so vite-plus is pinned there literally.

Verification

  • tsc --noEmit is clean for every package: server, web, desktop, mobile, contracts, shared, client-runtime, ssh, tailscale, effect-acp, effect-codex-app-server, scripts, oxlint-plugin-t3code and relay.
  • Focused tests pass: 1,411 across http.test.ts, MCP, RPC session, effect-acp, the codex app server, contracts, ACP runtime, OpenCode 2 client/server/adapter, the Grok, ACP and Antigravity v2 adapters, SSH, replay markers and schema helpers.
    • Two Antigravity client-file tests fail on macOS on unmodified main too: /var is a symlink to /private/var there. CI runs on Linux.
  • The relay's alchemy/Cloudflare and @opencode/client/effect both import at runtime on 4.0.0.

🤖 Generated with Claude Code


Devin Review

Effect 4.0.0 drops the `effect/unstable/*` export paths, so every import
moves to its flattened `effect/<area>` path (`httpapi` becomes `http-api`).
`effect/Encoding` is split into `effect/encoding/{Base64,Base64Url,Hex}`.

Dependencies that still targeted the release candidates:
- Alchemy 2.0.0-beta.80 and distilled 1.0.0-rc.13 ship the flattened layout.
- OpenCode 2 (@opencode/client, protocol, schema) is bumped to 2.0.22 and
  patched: it still imports the removed paths, `Encoding` and
  `Schema.isStartsWith`, and its `statics` helper assigned over a schema's
  `make`, which 4.0.0 caches as a non-configurable property.
- Drizzle's Effect integration only references the old paths in .d.ts
  files and loads unchanged.

Behavior changes picked up from rc.116 through 4.0.0:
- `HttpRouter.serve` builds the app in a private memo map, so the server's
  `TracerDisabledWhen` predicate is now provided to the served layer, with a
  test that fails without it. Services from layers around `serve` now win
  over the app's own, so the static-file test provides its tracked
  FileSystem between `serve` and `NodeHttpServer.layerTest`.
- `Scope.close` requires a closeable scope: SSH tunnels take their entry
  scope explicitly, and the ACP and Antigravity runtimes close a child of
  the caller's scope.
- `RpcSerialization.ndJsonRpc` skips lines that are not JSON, so effect-acp
  decodes each frame with the strict codec to keep failing sessions on a
  malformed agent line.
- `Effect.partition` returns successes first; `Stream.scan` takes a lazy
  initial state; `SchemaGetter.onSome`/`.compose` are replaced; `Schema.brand`
  requires a single concrete brand key.
- One OpenCode adapter test read turn terminals from two consumers of the
  same queue; it now waits on the single drain it already forks.

The effect patch is re-ported: MCP DELETE now lives in the HTTP protocol
layer against the new stateful runtime, and the missed-pong tolerance and
RpcClient hooks keep upstream's `SocketReadError` ping-timeout reason.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. label Oct 2, 2026
@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 2, 2026
@github-actions github-actions Bot added the size:XXL 1,000+ changed lines (additions + deletions). label Oct 2, 2026
@github-actions

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 4.9 KiB 4.9 KiB −40 B (−0.8%) 6.8 KiB ✅
Codex Thread snapshot wire 3.7 KiB 3.7 KiB 0 B (0.0%) 4.9 KiB ✅
Codex Live turn WebSocket wire 1.2 KiB 1.1 KiB −40 B (−3.3%) 2.0 KiB ✅
Codex Live turn WebSocket decoded 20.4 KiB 20.4 KiB −41 B (−0.2%) 29.3 KiB ✅
Codex Live turn messages 2 1 −1 (−50.0%) 8 ✅
Claude Total thread wire 4.9 KiB 4.9 KiB +22 B (+0.4%) 6.8 KiB ✅
Claude Thread snapshot wire 3.7 KiB 3.7 KiB 0 B (0.0%) 4.9 KiB ✅
Claude Live turn WebSocket wire 1.2 KiB 1.2 KiB +22 B (+1.9%) 2.0 KiB ✅
Claude Live turn WebSocket decoded 20.7 KiB 20.8 KiB +41 B (+0.2%) 29.3 KiB ✅
Claude Live turn messages 1 2 +1 (+100.0%) 8 ✅

Baseline: ca7df39 · PR result: c57b5b8 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 106.1 KiB
  • Claude decoded thread snapshot: 106.4 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeapp Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This upgrade spans 822 files and includes production runtime changes beyond import renames, including HTTP tracing, process-scope lifetimes, ACP parsing, patched dependency behavior, and authentication replay-marker handling. Changes under the server auth directory and the breadth of runtime effects require human review.

Notes:

  • No code objects were reviewed. Approvability was decided on eligibility alone.

You can add or adjust custom eligibility rules. Learn more.

Effect 4.0.0 returns a declared MCP tool failure as `isError: true` with
the encoded failure as JSON text, without `structuredContent`. The toolkit
tests now read the failure payload from the text content.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant