From 30953d3bfe02204618a024ea31c14c0baa46d82a Mon Sep 17 00:00:00 2001 From: roboomp Date: Thu, 16 Jul 2026 14:15:44 +0000 Subject: [PATCH] fix(cli): errored on unknown __omp_worker_ selectors Unknown reserved __omp_worker_* selectors hit the worker-host re-entry seam, runWorkerEntrypoint returned false, and the ignored result let the process exit 0 with empty stdout/stderr. A stale or mistyped selector looked healthy to parent processes and install smoke paths. Check runWorkerEntrypoint's return at the dispatch seam: an unrecognized selector now writes "Error: unknown worker selector: " to stderr and sets a nonzero exit code without starting a worker. Known selectors and normal CLI arguments are unchanged. Fixes #5712 --- packages/coding-agent/CHANGELOG.md | 4 ++ packages/coding-agent/src/cli.ts | 6 ++- .../coding-agent/test/worker-selector.test.ts | 37 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 packages/coding-agent/test/worker-selector.test.ts diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 0e753ced7..7901f6300 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed unknown `__omp_worker_*` CLI selectors exiting 0 with empty output instead of erroring; an unrecognized worker-host selector now writes `Error: unknown worker selector: …` to stderr and exits nonzero, so a stale or mistyped selector can no longer look healthy to a parent process or install smoke path ([#5712](https://github.com/can1357/oh-my-pi/issues/5712)). + ## [17.0.1] - 2026-07-16 ### Changed diff --git a/packages/coding-agent/src/cli.ts b/packages/coding-agent/src/cli.ts index a5c64fc03..996e12fbc 100755 --- a/packages/coding-agent/src/cli.ts +++ b/packages/coding-agent/src/cli.ts @@ -338,7 +338,11 @@ export async function runCli(argv: string[]): Promise { // worker's parked initial messages as soon as the entry module's // top-level evaluation finishes. if (resolvedArgv[0]?.startsWith("__omp_worker_")) { - await runWorkerEntrypoint(resolvedArgv[0]); + const dispatched = await runWorkerEntrypoint(resolvedArgv[0]); + if (!dispatched) { + process.stderr.write(`Error: unknown worker selector: ${resolvedArgv[0]}\n`); + process.exitCode = 1; + } return; } diff --git a/packages/coding-agent/test/worker-selector.test.ts b/packages/coding-agent/test/worker-selector.test.ts new file mode 100644 index 000000000..8dd294e49 --- /dev/null +++ b/packages/coding-agent/test/worker-selector.test.ts @@ -0,0 +1,37 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from "bun:test"; +import { runCli } from "../src/cli"; + +// The worker-host re-entry seam dispatches any `__omp_worker_*` selector to +// `runWorkerEntrypoint`. An unrecognized selector must fail loudly rather than +// exit 0 with empty output, so a stale/mistyped selector cannot look healthy to +// a parent process or install smoke path (issue #5712). +describe("worker selector dispatch", () => { + beforeEach(() => { + process.exitCode = 0; + }); + + afterEach(() => { + vi.restoreAllMocks(); + process.exitCode = 0; + }); + + it("fails with a nonzero exit and stderr error on an unknown selector", async () => { + const stderr = vi.spyOn(process.stderr, "write").mockImplementation(() => true); + + await runCli(["__omp_worker_does_not_exist"]); + + expect(process.exitCode).toBe(1); + expect(stderr).toHaveBeenCalledWith("Error: unknown worker selector: __omp_worker_does_not_exist\n"); + }); + + it("leaves normal root flags untouched", async () => { + const stdout = vi.spyOn(process.stdout, "write").mockImplementation(() => true); + const stderr = vi.spyOn(process.stderr, "write").mockImplementation(() => true); + + await runCli(["--version"]); + + expect(process.exitCode).toBe(0); + expect(stdout).toHaveBeenCalled(); + expect(stderr).not.toHaveBeenCalledWith(expect.stringContaining("unknown worker selector")); + }); +});