Skip to content

fix: scoped bus close() tears down shared bus (P1) #10#11

Merged
four-bytes-robby merged 1 commit into
mainfrom
fix/10-scoped-close-should-not-tear-down-shared-bus
Jun 14, 2026
Merged

fix: scoped bus close() tears down shared bus (P1) #10#11
four-bytes-robby merged 1 commit into
mainfrom
fix/10-scoped-close-should-not-tear-down-shared-bus

Conversation

@four-bytes-robby

@four-bytes-robby four-bytes-robby commented Jun 14, 2026

Copy link
Copy Markdown
Member

P1 Bug Fix

ScopedBusTui.close() (src/bus-tui.ts) called this.inner.close(), which closed the shared WebSocket connection — breaking every other consumer of the same parent bus. A scoped view is a channel-namespace wrapper, not a connection owner; its close() must be a no-op.

Changes

src/bus-tui.tsScopedBusTui.close(): no longer calls inner.close().

src/bus-client.tsScopedBusClient had no close() override at all (base BusClient had no close() either). Latent footgun: the moment BusClient gains lifecycle management, the scoped wrapper would inherit and tear down the shared bus. Fix: added an explicit no-op close() on the base BusClient (HTTP is stateless, so no-op is correct) and override close() on ScopedBusClient.

test/scoped-close.test.ts — 3 regression tests, all fail without the fix (verified via git stash):

  1. ScopedBusTui.close() does not close the parent bus
  2. ScopedBusClient.close() is a no-op (defense in depth)
  3. Multiple scoped close() calls are idempotent

Verification

$ bun run build
✅ Built @four-bytes/opencode-plugin-lib

$ bun test test/scoped-close.test.ts
3 pass, 0 fail

Note on integration.test.ts

test/integration.test.ts references /home/robby/four-opencode-plugin-bus/bus — a path that doesn't exist (the binary is now ~/.local/bin/four-local-bus per the wave-1 rename). This is pre-existing test infrastructure rot, out of scope for the P1 fix. The new scoped-close.test.ts is hermetic and self-contained.

Closes #10


Summary by cubic

Fixes a P1 bug where closing a scoped bus shut down the shared connection, breaking other consumers. ScopedBusTui.close() is now a no-op so scoped views never tear down the parent bus.

  • Bug Fixes

    • ScopedBusTui.close() no longer calls the parent’s close(); it does nothing.
    • Added a no-op close() to BusClient and an explicit no-op override in ScopedBusClient to prevent any future lifecycle teardown from propagating to scoped clients.
  • Tests

    • Added test/scoped-close.test.ts with 3 regression cases:
      • ScopedBusTui.close() does not close the parent bus.
      • ScopedBusClient.close() is a no-op.
      • Multiple scoped close() calls are idempotent.

Written for commit 9503626. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes

    • Scoped bus clients and services no longer close the underlying parent connection when closed, ensuring the parent bus remains active for other operations.
    • Multiple close operations on scoped views are now safe and idempotent.
  • Tests

    • Added regression tests for scoped client and service close behaviors.

ScopedBusTui.close() previously called inner.close(), which closed the
shared WebSocket connection and broke every other consumer of the same
parent bus. A scoped view is a channel-namespace wrapper, not a
connection owner — its close() must be a no-op.

Also adds an explicit close() override on ScopedBusClient. The base
BusClient had no close() method, so ScopedBusClient was inheriting
nothing — but that becomes a footgun the moment the base class gains
lifecycle management (HTTP keep-alive pooling, binary shutdown).
Added a no-op close() on the base BusClient to document the contract
and let ScopedBusClient override it cleanly.

Regression test in test/scoped-close.test.ts: 3 cases, all pass with
the fix and all fail without it (verified via git stash).
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

Recent review info
Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 004e4a02-50cf-444f-b132-3585ed2c0adc

Commits

Reviewing files that changed from the base of the PR and between 75c3e9a and 9503626.

Files ignored due to path filters (5)
  • dist/bus-client.d.ts is excluded by !**/dist/**
  • dist/index.js is excluded by !**/dist/**
  • dist/index.js.map is excluded by !**/dist/**, !**/*.map
  • dist/tui.js is excluded by !**/dist/**
  • dist/tui.js.map is excluded by !**/dist/**, !**/*.map
Files selected for processing (3)
  • src/bus-client.ts
  • src/bus-tui.ts
  • test/scoped-close.test.ts

Walkthrough

Walkthrough

ScopedBusTui.close() is changed to a no-op, removing its call to the underlying inner bus. BusClient gains a documented base close(): void no-op method, and ScopedBusClient adds an explicit override that is also a no-op. A new regression test file validates all three behaviors against a hermetic local bus process.

Changes

Scoped Close Lifecycle Fix

Layer / File(s) Summary
No-op close() on scoped wrappers
src/bus-tui.ts, src/bus-client.ts
ScopedBusTui.close() removes the call to this.inner.close(), leaving only a comment. BusClient adds a documented base close(): void no-op. ScopedBusClient adds an explicit close() override that is also a no-op.
Regression test for scoped close
test/scoped-close.test.ts
New test suite spawns four-local-bus directly, clears cached port state, then asserts that ScopedBusTui.close() does not break the shared parent connection, that ScopedBusClient.close() is a safe no-op, and that repeated close() calls are idempotent.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Finishing Touches
Generate docstrings
  • Create stacked PR
  • Commit on current branch
Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/10-scoped-close-should-not-tear-down-shared-bus
Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/10-scoped-close-should-not-tear-down-shared-bus

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

@four-bytes-robby four-bytes-robby merged commit 799dee7 into main Jun 14, 2026
3 of 4 checks passed
@four-bytes-robby four-bytes-robby deleted the fix/10-scoped-close-should-not-tear-down-shared-bus branch June 14, 2026 15:15
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.

[BUG] Scoped bus close() tears down shared bus connection

1 participant