Skip to content

fix(engine): sweep stray engines machine-wide, not per-port (#1592) - #1593

Merged
jeonghun-jj-lee merged 1 commit into
feature/free-tier-fleetfrom
fix/1592-stray-engine-sweep
Sep 28, 2026
Merged

jeonghun-jj-lee merged 1 commit into
feature/free-tier-fleetfrom
fix/1592-stray-engine-sweep

Conversation

@jeonghun-jj-lee

Copy link
Copy Markdown
Contributor

Closes #1592.

What

Adds a machine-wide stray-engine sweep so the "one opencode serve per machine" invariant survives installs/workspaces that resolve to different ports.

Why

adoptOrSpawn (#1145) + orphan-reclaim (#1178) only ever probe the configured port. When a second install's window dies, its engine is orphaned on its own port, invisible to the guard — it squats with a full MCP child tree, and the two engines' MCP trees churn against each other (the flickering connected/failed MCP status tiles observed live on jjs-macbook-pro: installed-ext PID 48240 on 4094 alongside the hub PID 79829 on 4093).

How

  • sweepStrayEngines(deps) — pure decision logic over injected seams. Reaps every engine that is neither keepPid (the handshake/adopted engine) nor still serving a live client.
  • Production seams: listOpencodeEngines (enumerate all opencode serve + ports via lsof/ps, confirmed by the existing isOpencodeServer signature), hasLiveClient (ESTABLISHED conn from a non-engine PID), reclaimEnginePid (SIGTERM→SIGKILL by PID, any port).
  • Wired into activation after adoptOrSpawn on both the adopted path and the cold-spawn onReady path, keyed off the handshake PID. Non-fatal — a sweep failure never blocks activation.

Invariants (unit-tested, 6 new cases)

  • Reaps a stray on a different port with no client (the bug).
  • Never reaps the adopted/handshake engine, an engine with a live client (a real second workspace), or a foreign process.
  • No-op when only one engine runs.

Verification

  • server_lifecycle.test.ts: 37/37 green (6 new).
  • typecheck: clean.
  • Full fast suite: 5005 passed. The only 2 failures are fleet_peer_e2e.test.ts (CI-gated real-SSH, describe.skipIf) — proven pre-existing: identical 2 failures on the untouched base commit 3da4bc56.

Do not merge until CI is green.

adopt-or-spawn (#1145) and its orphan-reclaim (#1178) only probe the
CONFIGURED port. An engine on any OTHER port — a stale install, a
workspace whose window died — is invisible to them and squats forever
with its MCP child tree, and the two engines' MCP trees churn against
each other (flickering connected/failed status tiles).

Add sweepStrayEngines: after adopt-or-spawn resolves, enumerate every
opencode serve on the machine and reap the ones that are neither the
engine we kept (handshake PID) nor still serving a live client. Pure
decision logic over injected seams (listOpencodeEngines / hasLiveClient
/ killEngine), production seams reap by PID regardless of port. Wired
into activation on both the adopted and cold-spawn ready paths.

Never reaps: the adopted engine, an engine with a live client (a real
second workspace), or a foreign process.
@coderabbitai

coderabbitai Bot commented Sep 28, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 8f0ecc36-cdf1-4681-8964-35a1b9f758c9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jeonghun-jj-lee
jeonghun-jj-lee merged commit 19b49c3 into feature/free-tier-fleet Sep 28, 2026
11 of 12 checks passed
@jeonghun-jj-lee
jeonghun-jj-lee deleted the fix/1592-stray-engine-sweep branch September 28, 2026 00:23
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.

1 participant