Files
oh-my-pi/packages/coding-agent/test/issue-1011-repro.test.ts
T
can1357 6d16e93b86 test(coding-agent): align issue-1011 test with isCompiledBinary hybrid contract
The asset-emission assertion was the false positive flagged in
tab-supervisor.ts: the new pattern intentionally does not bundle the
worker as an asset of the supervisor — it is added as a separate
`--compile` entrypoint in build-binary.ts, and runtime is covered by
`omp --smoke-test` (sync worker).

Replaces it with two cheap static checks that defend the two halves
that actually make the worker survive `bun build --compile`:
1. tab-supervisor.ts branches on `isCompiledBinary()` and uses the
   exact `--root`-relative literal at the `new Worker(...)` site
   that Bun's `--compile` analyzer can discover, while keeping the
   `new URL("./tab-worker-entry.ts", import.meta.url)` branch for
   dev/source spawns.
2. scripts/build-binary.ts lists the same worker as an explicit
   additional `--compile` entrypoint so Bun emits it into bunfs.
2026-05-13 01:56:18 +02:00

79 lines
3.9 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import * as path from "node:path";
/**
* Regression for https://github.com/can1357/oh-my-pi/issues/1011
*
* In v14.5.13 `spawnTabWorker` (in `src/tools/browser/tab-supervisor.ts`)
* resolved the worker entry as `new URL("./tab-worker-entry.ts", import.meta.url)`
* and passed `.href` to `new Worker(...)`. Bun's `--compile` static analyzer
* cannot discover that pattern, so the entry was never embedded in the
* single-file binary and the runtime symptom was "Timed out initializing
* browser tab worker".
*
* The original fix used an `import "./worker.ts" with { type: "file" }`
* trick. That copied the entry as a raw asset but could not resolve its
* relative imports inside the compiled binary, so the worker still failed
* to load (issue #1027 was the same root cause, retriggered).
*
* The working pattern documented in AGENTS.md is a two-part contract:
*
* 1. `spawnTabWorker` branches on `isCompiledBinary()` and uses a literal
* string path under `--compile`. Bun's `--compile` analyzer discovers
* that literal at the `new Worker("...", ...)` call site. The path is
* `--root`-relative (`./packages/coding-agent/src/...`) because the
* build script passes `--root ../..`.
* 2. `scripts/build-binary.ts` lists the worker as an explicit additional
* `--compile` entrypoint. Without this, Bun sees the literal at the
* spawn site but never emits the worker module into bunfs.
*
* Either half alone is insufficient — both must agree on the exact path.
* Runtime end-to-end coverage lives in `omp --smoke-test` (via the stats
* sync worker). This test is the cheap static contract that catches an
* accidental regression of either half in code review / CI.
*/
describe("issue #1011 — tab worker entry must survive `bun build --compile`", () => {
const packageDir = path.resolve(import.meta.dir, "..");
const supervisorPath = path.join(packageDir, "src/tools/browser/tab-supervisor.ts");
const buildBinaryPath = path.join(packageDir, "scripts/build-binary.ts");
// `--root` is `../..` from packages/coding-agent, so the literal that
// matches at runtime inside the compiled bunfs is repo-relative.
const compiledLiteral = "./packages/coding-agent/src/tools/browser/tab-worker-entry.ts";
// The build script's cwd is packages/coding-agent, so its entrypoint
// path is package-relative.
const buildEntrypoint = "./src/tools/browser/tab-worker-entry.ts";
it("tab-supervisor uses the isCompiledBinary() hybrid spawn pattern with a static literal", async () => {
const source = await Bun.file(supervisorPath).text();
// The exact literal at the `new Worker(...)` call must be present
// and discoverable to Bun's `--compile` static analyzer.
expect(
source.includes(`new Worker("${compiledLiteral}"`),
`tab-supervisor.ts must spawn the worker with the literal "${compiledLiteral}" so Bun's --compile analyzer can embed it`,
).toBe(true);
// And the dev-mode branch should keep the portable import.meta.url
// form so spawns work outside of compiled binaries too.
expect(
/new Worker\(\s*new URL\("\.\/tab-worker-entry\.ts",\s*import\.meta\.url\)/.test(source),
"tab-supervisor.ts must keep a `new URL('./tab-worker-entry.ts', import.meta.url)` branch for dev/source spawns",
).toBe(true);
// And the branching must come from `isCompiledBinary()` — not, say,
// a hard-coded check, an env var, or a renamed helper.
expect(
source.includes("isCompiledBinary()"),
"tab-supervisor.ts must select the spawn pattern via isCompiledBinary()",
).toBe(true);
});
it("build-binary.ts lists tab-worker-entry as an explicit --compile entrypoint", async () => {
const source = await Bun.file(buildBinaryPath).text();
expect(
source.includes(`"${buildEntrypoint}"`),
`scripts/build-binary.ts must include "${buildEntrypoint}" as an explicit --compile entrypoint so Bun emits the worker into bunfs`,
).toBe(true);
});
});