Skip to content

Keep Alchemy libraries in the published deploy package - #195

Merged
jonbeckman merged 1 commit into
masterfrom
cursor/fix-deploy-runtime-deps-2e72
Nov 13, 2026
Merged

jonbeckman merged 1 commit into
masterfrom
cursor/fix-deploy-runtime-deps-2e72

Conversation

@jonbeckman

Copy link
Copy Markdown
Contributor

Summary

The release workflow builds the registry archive, then runs nub prune --prod before alchemy.new packs it. alchemy.new installs nothing and runs that archive. The API stack imports @alchemy.run/cloudflare and alchemy while deploying, and both were devDependencies of @solzero/background-api, so the prune removed them. A deploy of solzero/platform@3.0.0 then failed with Cannot find package '@alchemy.run/cloudflare' from apps/api/infra/index.ts.

@alchemy.run/cloudflare 2.0.0-beta.84 and alchemy 2.0.0-beta.84 are now production dependencies of apps/api. The pins are unchanged. nub.lock only moves those two importer entries from devDependencies to dependencies.

Deploy-time imports in the Alchemy stack entries, the infra modules they load, the API Worker entry, the agent-container bundle, and apps/web/vite.config.ts were checked against the importing package. The Vite, Tailwind, and TanStack plugins, and the Worker and container packages, were already production dependencies. effect stays a devDependency of the API app because @solzero/api and @solzero/shared already depend on it, and the pruned tree still resolves it.

This is a patch. .tegami/2026-11-13-deploy-published-package.md records it. VERSION and the Version Packages pull request are unchanged.

Validation

  • nub run format — passed
  • nub run lint — passed
  • nub run typecheck — passed (also re-run by the pre-push hook)
  • nub run config:check — passed
  • nub run test — not run. End-to-end tests need Docker, and Docker is not available in this environment.
  • Clean worktree, with CLOUDFLARE_API_TOKEN unset:
    • CI=true nub install --frozen-lockfile — installed 814 packages
    • nub run build — 6 tasks successful
    • nub prune --prod — pruned 147 entries
    • Loaded packages/infra/alchemy.run.ts, alchemy.api.run.ts, alchemy.web.run.ts, apps/api/infra/index.ts, and apps/web/vite.config.ts from the pruned tree. The Vite config returned its three plugins.
    • nubx vite build in apps/web after the prune — built successfully
    • Resolved @alchemy.run/cloudflare, alchemy, and effect/Effect from apps/api/infra/index.ts after the prune

Checklist

  • I added or updated tests for behavior changes, or explained why tests are not needed.
  • I updated documentation and config examples when behavior or configuration changed.
  • I added a .tegami/ release entry, or explained why this pull request uses release:none.
  • I ran nub run config:check, nub run typecheck, nub run lint, nub run format, and nub run test.
  • I did not include credentials, private data, internal URLs, or organization-specific defaults.
  • I updated THIRD_PARTY_NOTICES.md for new third-party code or separately licensed assets.

No new third-party source was added. nub run test did not run because Docker is missing; the other checks in that item passed. No config example changed.

Open in Web Open in Cursor 

The release archive runs after nub prune --prod. The API stack imports
@alchemy.run/cloudflare and alchemy while deploying, so those packages
belong in dependencies and stay in the alchemy.new package.

Co-authored-by: Jonathan Beckman <jonathantbeckman@gmail.com>
@jonbeckman
jonbeckman marked this pull request as ready for review November 13, 2026 17:35
@jonbeckman
jonbeckman enabled auto-merge (squash) November 13, 2026 17:36
@github-actions

Copy link
Copy Markdown
Contributor

Tegami

This repository uses Tegami to manage releases. When your changes affect published packages, add a changelog file under .tegami/ before merging.

Create a changelog → · Changelog format

Release preview

Package Bump Version
solzero patch 3.0.0 → 3.0.1

Changelogs in this PR

Changelog Title
2026-11-13-deploy-published-package.md Deploy a published SolZero package

Run nub run tegami locally to create a changelog interactively.

Managed by Tegami.

@github-actions

Copy link
Copy Markdown
Contributor

🟢 e2e solzero-core: 25 passed, 7 left out by filters

4 agent steps · 4 replayed from cache

Change 3 files changed since fa02d62
Filter decision kept 23 of 30 tests, left out 7 (1 call, 16.7k tokens)

7 tests left out by filters
Test Filter Reason
tests/auth.e2e.ts › sign-in gate protects every application route decision 12% likely affected
tests/auth.e2e.ts › credential sign-in opens the requested settings page decision 14% likely affected
tests/auth.e2e.ts › anonymous callers cannot access any protected API group decision 18% likely affected
tests/auth.e2e.ts › sign-out removes authenticated UI access decision 8% likely affected
tests/branding.e2e.ts › the selected deployment brand reaches the browser decision 7% likely affected
tests/branding.e2e.ts › health identifies the configured application without exposing configuration decision 15% likely affected
tests/branding.e2e.ts › OpenAPI uses the selected deployment brand decision 6% likely affected
All 25 tests in 11 files
Test Agent Time
🟢 tests/accounts.e2e.ts · 3 passed 6.3s
🟢 create, use and revoke an isolated user API key 3.1s
🟢 Better Auth 1.7 account APIs select the local account row id 183ms
🟢 Accounts settings shows GitHub as unlinked without OAuth providers 3.0s
🟢 tests/admin.e2e.ts · 1 passed 3.8s
🟢 administrator pages show live control-plane configuration 3.8s
🟢 tests/advanced-sessions.e2e.ts · 2 passed 5.9s
🟢 incognito sessions stay outside normal lists but open directly 2.6s
🟢 session MCP definitions and subagent preferences persist 3.3s
🟢 tests/api-contract.e2e.ts · 1 passed 313ms
🟢 exported API key and session schemas decode actual Worker responses 313ms
🟢 tests/auth.setup.e2e.ts · 2 passed 6.1s
🟢 authenticate isolated admin 4.3s
🟢 authenticate isolated peer 1.8s
🟢 tests/bots.e2e.ts · 1 passed 4.2s
🟢 create a bot and manage a temporary routine through the UI 4.2s
🟢 tests/session-transfer.e2e.ts · 1 passed 1.9s
🟢 admin authentication transfer redeems once and retains its deep link 1.9s
🟢 tests/sessions.e2e.ts · 5 passed 1 step 39.5s
🟢 session tools, archive and restoration persist through the real Worker 1 step 4.7s
🟢 a second account cannot read or mutate another account's session 203ms
🟢 isolate executes a real prompt and persists its output 7.9s
🟢 opencode executes a real prompt and persists its output 14.1s
🟢 codex executes a real prompt and persists its output 12.6s
🟢 tests/settings.e2e.ts · 5 passed 2 steps 20.7s
🟢 all settings categories load real data 6.5s
🟢 runtime default persists after reload 5.4s
🟢 MCP deep link and legacy settings URL open the MCP tab 1.9s
🟢 secret editor creates, finds and deletes a disposable secret 1 step 3.4s
🟢 theme preference survives reload 1 step 3.5s
🟢 tests/skills.e2e.ts · 1 passed 6.7s
🟢 global skill defaults and per-user preferences persist independently 6.7s
🟢 tests/workflows.e2e.ts · 3 passed 1 step 7.0s
🟢 workflow authoring, rename, export, disable and archive persist 1 step 4.8s
🟢 manual workflow executes JavaScript and stores a real R2 artifact 2.1s
🟢 invalid workflow definitions are rejected before storage 71ms

Tested by e2e 0.23.0 · 2m 29s · local-cloudflare · run artifacts

@jonbeckman
jonbeckman merged commit eecb613 into master Nov 13, 2026
20 checks passed
@jonbeckman
jonbeckman deleted the cursor/fix-deploy-runtime-deps-2e72 branch November 13, 2026 17:39
cursor Bot pushed a commit that referenced this pull request Nov 13, 2026
#195 moved @alchemy.run/cloudflare and alchemy to production dependencies
so a pruned publish can still deploy. Keep those packages there, at
2.0.0-beta.85. Effect stays 4.1.2.

Co-authored-by: Jonathan Beckman <jonathantbeckman@gmail.com>
@cursor cursor Bot mentioned this pull request Nov 13, 2026
6 tasks done
jonbeckman added a commit that referenced this pull request Nov 13, 2026
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary

Moves the workspace onto Alchemy `2.0.0-beta.85` and Effect `4.1.2`, and
merges current `master` (through #195).

The root `workerd` override is removed. It held workerd behind the
release Alchemy beta.85's Vite forwarder needs. That forwarder waits for
`HTTP/1.1 100 Continue` before it sends a POST body, and `workerd`
`1.20261006.1` never sends that response.

No published Miniflare release depends on `workerd` `1.20261026.1`, the
exact version `@alchemy.run/cloudflare-runtime@2.0.0-beta.85` depends
on. Miniflare is now `5.20261101.0-beta`, the next published release,
and it depends on `workerd` `1.20261101.1`. Wrangler `4.149.0` also
depended on `workerd` `1.20261006.1` and Miniflare `5.20261006.1-alpha`,
so Wrangler is now `4.156.1`, which uses that same Miniflare and
`workerd` `1.20261101.1`.

`nub why workerd` shows two versions:

- `1.20261026.1`, supplied by `@alchemy.run/cloudflare-runtime` (the
binary `alchemy dev` uses)
- `1.20261101.1`, supplied by `miniflare` and `wrangler`

Both binaries include `100 Continue`. `1.20261006.1` is gone.
`allowScripts` still allows the `workerd` install script. `VERSION` is
untouched. The `release:none` label stays.

Master's versions are kept for everything this pull request does not
bump, including oxlint `1.93.0`, oxfmt `0.78.0`, tsrs
`0.23.0-ts7.1.0-beta`, the AI SDK pins from #192, and the AI Search
config shape from #186. The config JSON schema was regenerated for
Effect 4.1 against that shape.

#195 moved `@alchemy.run/cloudflare` and `alchemy` to production
dependencies of `@solzero/background-api` so a pruned publish can still
deploy. Those packages stay production dependencies, at `2.0.0-beta.85`.
Effect stays a devDependency at `4.1.2`.

## Root cause

File: `@alchemy.run/cloudflare-runtime@2.0.0-beta.85`
`src/vite/worker-request.ts`, in `forwardWorkerRequest`.

- Lines 70–79: a request with `content-length` or `transfer-encoding` is
forwarded with `expect: 100-continue`.
- Lines 169–174: the body is not piped until the upstream emits
`continue`.

That landed in commit `3bb45b0f08` (`feat(cloudflare-runtime): update
workerd and sync workers-sdk`, #2673), which is in `2.0.0-beta.85` and
not in `2.0.0-beta.84`. Beta.84 piped the body immediately.

A packet capture of `POST /api/auth/sign-in/email` to port 3000 showed
the Vite process sending headers, including `expect: 100-continue` and
`content-length: 40`, and then no body. workerd acknowledged the headers
and never replied `100 Continue`. The Worker then failed
`request.arrayBuffer()` with `Network connection lost` once the client
gave up. The same POST to port 3100 does not go through this Vite
forwarder, so it returned 200.

`workerd` `1.20261006.1` has no `100 Continue` string in the binary.
`1.20261026.1` and `1.20261101.1` do.

## Conflicts

- `.npmrc`: kept master's release-age exclusions, including oxfmt
`0.78.0`, oxlint `1.93.0`, and `ai@7.0.166`, and removed the `workerd`
`1.20261006.1` exclusions.
- `package.json`: Miniflare `5.20261101.0-beta` and Wrangler `4.156.1`
from this branch; oxfmt `0.78.0` and oxlint `1.93.0` from master. The
`workerd` override stays removed.
- `apps/api/package.json`: Alchemy `2.0.0-beta.85` and Effect `4.1.2`
from this branch; tsrs `0.23.0-ts7.1.0-beta` from master. After #195,
`@alchemy.run/cloudflare` and `alchemy` are production dependencies.
- `config/s0.config.schema.json`: master's removal of
`aiSearch.serviceTokenId`, then regenerated with Effect 4.1.
- `nub.lock`: regenerated with nub. Not hand-edited.

## Validation

- `nub run format`, `nub run lint`, and `nub run typecheck`: passed,
including the pre-push hook on both pushes.
- `nub run config:check`: passed.
- `nub run test:config`: 31 passed (5 files), including the Miniflare
service-binding and storage fixtures. One workerd stderr line reported a
hung request during the service-binding case; the test still passed.
Re-run after the #195 merge.
- `nub run test`: 30 passed, 2 failed. Sign-in, Isolate, settings,
workflows, and the other core flows passed. OpenCode and Codex timed out
because `cloudflare/proxy-everything` exited before the container could
start (`iptables` `PREROUTING` append failed: missing kernel module).
That is this VM, not an application change. CI runs that suite on a host
that can run the proxy. The #195 follow-up only moves the same Alchemy
packages into production dependencies, so that browser suite was not
repeated.

## Checklist

- [x] I added or updated tests for behavior changes, or explained why
tests are not needed. The existing config suite covers the Miniflare
fixtures.
- [x] I updated documentation and config examples when behavior or
configuration changed. The config JSON schema was regenerated for Effect
4.1. Stale `workerd` `1.20261006.1` entries were removed from `.npmrc`
`minimumReleaseAgeExclude`. The new Miniflare and workerd versions did
not need an age exclusion.
- [x] I added a `.tegami/` release entry. `VERSION` is untouched. This
pull request keeps `release:none`.
- [x] I ran `nub run config:check`, `nub run format`, `nub run lint`,
`nub run typecheck`, `nub run test:config`, and `nub run test`.
- [x] I did not include credentials, private data, internal URLs, or
organization-specific defaults.
- [x] I updated `THIRD_PARTY_NOTICES.md` for new third-party code or
separately licensed assets. No new third-party source was added.

<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-85cb0616-7478-5004-89c8-7a62aca4d1cb?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-85cb0616-7478-5004-89c8-7a62aca4d1cb&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.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.

2 participants