Skip to content

Commit 6afadc5

Browse files
committed
Drop the vendor/ fork submodules; develop emulate as a standalone repo
The emulate and mcporter forks are consumed only as published npm packages (@executor-js/emulate, @executor-js/mcporter) — nothing imports vendor/ at runtime, and the submodules created persistent friction: empty in every worktree, a pnpm/node>=24 toolchain unlike executor's bun, stale-dist rebuilds, and publish/pointer drift. Remove vendor/emulate and vendor/mcporter and point the guidance at the standalone fork repos: agents develop emulate on its own main with full publish/deploy autonomy, and this repo just bumps the npm dependency. - Remove vendor/emulate, vendor/mcporter, vendor/README.md; .gitmodules keeps only integrationsdotsh - bootstrap.ts: drop the dead --forks submodule-init path - Rewrite the emulate skill (new "Changing or deploying an emulator" section), AGENTS.md, RUNNING.md, README.md, and the e2e mcp surface comment
1 parent 1f9bfe0 commit 6afadc5

10 files changed

Lines changed: 67 additions & 69 deletions

File tree

.claude/skills/emulate/SKILL.md

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@ description: Use the @executor-js/emulate service emulators (GitHub, Google, Str
55

66
# Emulate: production-fidelity service emulators
77

8-
`@executor-js/emulate` (our fork of Vercel Labs' emulate, developed in
9-
`vendor/emulate` but ALWAYS consumed as the published npm package — never
10-
import from `vendor/`) provides stateful, wire-level emulators for 16
11-
services: `github vercel google okta microsoft spotify slack apple aws
12-
resend stripe mongoatlas clerk x workos autumn`. These are not mocks: real
13-
SDKs and real product code run against them unmodified — the cloud e2e
14-
target points the actual WorkOS SDK (sealed sessions, JWKS, hosted AuthKit
15-
login) and Autumn billing at emulators and exercises the product's real
16-
auth code.
8+
`@executor-js/emulate` (our fork of Vercel Labs' emulate) provides stateful,
9+
wire-level emulators for 16 services: `github vercel google okta microsoft
10+
spotify slack apple aws resend stripe mongoatlas clerk x workos autumn`.
11+
These are not mocks: real SDKs and real product code run against them
12+
unmodified — the cloud e2e target points the actual WorkOS SDK (sealed
13+
sessions, JWKS, hosted AuthKit login) and Autumn billing at emulators and
14+
exercises the product's real auth code.
15+
16+
**This repo only consumes the published npm package.** There is no
17+
`vendor/emulate` submodule — everything imports `@executor-js/emulate` from
18+
npm. The emulator _source_ is its own standalone project; to change or deploy
19+
an emulator, see "Changing or deploying an emulator" at the bottom.
1720

1821
## Two ways to get one
1922

@@ -83,6 +86,40 @@ before `createEmulator` so minted MCP access tokens carry the right audience.
8386
app's real dev stack (recipe in `e2e/setup/cloud.boot.ts`), fronted with
8487
tailscale HTTPS.
8588

89+
## Changing or deploying an emulator
90+
91+
The emulators live in their own repo — **not** in executor and **not** a
92+
submodule: `github.com/UsefulSoftwareCo/emulate` (clone it as a sibling of
93+
executor). It's a pnpm + turbo monorepo on node ≥ 24 — a different toolchain
94+
from executor's bun, which is exactly why it's standalone rather than
95+
vendored here.
96+
97+
You have full autonomy over it: **work directly on `main`, and commit, push,
98+
publish, and deploy without asking.** The loop:
99+
100+
1. Edit in the emulate repo, then **rebuild the package you changed.** It
101+
resolves through built `dist`, so a source-only edit does nothing until you
102+
build it — this is the single most common mistake. `@emulators/*` packages
103+
are a `workspace:*` graph, so adding or renaming one needs an install +
104+
rebuild too.
105+
2. Publish a version bump of `@executor-js/emulate` to npm.
106+
3. Deploy the hosted Cloudflare emulators (the `emulate-hosts` worker behind
107+
`*.emulators.dev`) when behavior the hosted instances serve has changed.
108+
4. Back in executor, bump the `@executor-js/emulate` dependency to the version
109+
you just published. Never point a consumer at a local checkout to ship —
110+
publish, then bump.
111+
112+
The emulate repo's own `AGENTS.md` / `README.md` carry the current build,
113+
publish, and deploy commands (npm + Cloudflare creds are in 1Password). Read
114+
them there rather than memorizing flags here — they move.
115+
116+
**A hot deploy can redden other people's e2e.** `*.emulators.dev` service
117+
hosts are shared infrastructure; a control-plane regression there has failed
118+
unrelated PRs' suites before. When a scenario needs isolation or a behavior
119+
that isn't deployed yet, pin to a published package version or mint a private
120+
per-run instance (`POST /_emulate/instances`) instead of mutating the shared
121+
service host.
122+
86123
## Gotchas
87124

88125
- **Secure cookies need HTTPS off-localhost.** Browser-driven flows work on

.gitmodules

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
11
[submodule "integrationsdotsh"]
22
path = integrationsdotsh
33
url = https://github.com/RhysSullivan/integrationsdotsh.git
4-
[submodule "vendor/emulate"]
5-
path = vendor/emulate
6-
url = https://github.com/UsefulSoftwareCo/emulate.git
7-
[submodule "vendor/mcporter"]
8-
path = vendor/mcporter
9-
url = https://github.com/UsefulSoftwareCo/mcporter.git

AGENTS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ with zero setup. See the `emulate` skill
6161
(`.claude/skills/emulate/SKILL.md`) for the control-plane reference and
6262
recipes.
6363

64+
The emulators are a standalone project (`github.com/UsefulSoftwareCo/emulate`),
65+
not vendored here — this repo only consumes the published `@executor-js/emulate`
66+
package. You have full autonomy to change, publish, and deploy the emulators,
67+
working directly on their `main`; the skill covers the loop. Don't re-introduce
68+
a `vendor/` submodule for them.
69+
6470
## Attribution
6571

6672
Do not add any AI assistant, Claude, Anthropic, or Co-Authored-By

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,7 @@ bun run test:e2e # full-stack e2e: boots the cloud and self-host apps and driv
134134
```
135135

136136
The browser e2e scenarios need Playwright's Chromium once per machine:
137-
`bunx playwright install chromium`. The git submodules under `vendor/` are
138-
optional — see [vendor/README.md](vendor/README.md).
137+
`bunx playwright install chromium`.
139138

140139
## Community
141140

RUNNING.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ artifacts dev servers fail without) plus Playwright chromium. A fresh
1515
worktree that skips it dies with "Failed to resolve entry for package
1616
'@executor-js/vite-plugin'".
1717

18-
The `vendor/` submodules (emulate, mcporter) are NOT required — nothing
19-
imports from `vendor/` at runtime; those packages come from npm
20-
(`@executor-js/emulate`, `@executor-js/mcporter`). `bun run bootstrap
21-
--forks` inits them only when deliberately developing a fork (see
22-
`vendor/README.md`).
18+
Our two upstream forks — `@executor-js/emulate` (service emulators) and
19+
`@executor-js/mcporter` (headless MCP client) — are consumed purely as
20+
published npm packages; nothing in this repo references them by path. There
21+
are no `vendor/` submodules. Each fork is its own standalone repo
22+
(`github.com/UsefulSoftwareCo/emulate`, `github.com/UsefulSoftwareCo/mcporter`):
23+
develop on its `main`, publish a bump, then bump the dependency here. The
24+
`emulate` skill covers the emulator publish/deploy loop.
2325

2426
## Dev servers
2527

e2e/src/surfaces/mcp.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
// MCP surface: our mcporter fork (@executor-js/mcporter on npm; develop it in
2-
// the vendor/mcporter submodule) as a programmatic MCP client, with headless
3-
// OAuth via the target's consent strategy. Session methods are Effects;
1+
// MCP surface: our mcporter fork (@executor-js/mcporter on npm; developed in
2+
// its own repo, github.com/UsefulSoftwareCo/mcporter) as a programmatic MCP
3+
// client, with headless OAuth via the target's consent strategy. Session
4+
// methods are Effects;
45
// mcporter itself is promise-native underneath. Assertions are vitest's job.
56
import { createHash, randomBytes, randomUUID } from "node:crypto";
67
import { mkdtempSync, writeFileSync } from "node:fs";

scripts/bootstrap.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
// Playwright browser the e2e suite drives. Idempotent and safe to re-run;
44
// each step prints what it is doing.
55
//
6-
// The vendor/ submodules are intentionally NOT initialized: nothing imports
7-
// from vendor/ at runtime — those forks are consumed as published npm
8-
// packages (see vendor/README.md). Pass --forks only when deliberately
9-
// developing a fork.
6+
// There are no fork submodules: our upstream forks (@executor-js/emulate,
7+
// @executor-js/mcporter) are consumed purely as published npm packages and
8+
// developed in their own standalone repos. Nothing to init here.
109
import { execFileSync } from "node:child_process";
1110
import { existsSync } from "node:fs";
1211
import { resolve } from "node:path";
@@ -19,10 +18,6 @@ const run = (label: string, cmd: string, args: ReadonlyArray<string>) => {
1918
execFileSync(cmd, [...args], { cwd: repoRoot, stdio: "inherit" });
2019
};
2120

22-
if (process.argv.includes("--forks")) {
23-
run("vendor fork submodules", "git", ["submodule", "update", "--init", "--recursive"]);
24-
}
25-
2621
// `bun install` runs the workspace prepare hook, which builds
2722
// @executor-js/vite-plugin and @executor-js/react — the two artifacts the
2823
// apps' vite dev servers fail without in a fresh worktree.

vendor/README.md

Lines changed: 0 additions & 34 deletions
This file was deleted.

vendor/emulate

Lines changed: 0 additions & 1 deletion
This file was deleted.

vendor/mcporter

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)