Skip to content

fix: make RPC send tests independent of host bridge availability - #277

Merged
steipete merged 1 commit into
openclaw:mainfrom
omarshahine:fix/rpc-tests-live-bridge
Sep 7, 2026
Merged

fix: make RPC send tests independent of host bridge availability#277
steipete merged 1 commit into
openclaw:mainfrom
omarshahine:fix/rpc-tests-live-bridge

Conversation

@omarshahine

Copy link
Copy Markdown
Contributor

Fixes #275.

Problem

Three RPCServerTests cases fail on any macOS host where the bridge helper is actually injected into Messages.app, and pass in CI. That makes make test red for anyone developing on a real, working setup, which hides genuine regressions behind expected noise.

  • rpcSendResolvesChatID()
  • rpcSendReportsMisroutedChatGhost()
  • rpcSendReturnsSentMessageIdentifiersWhenResolved()

Cause

All three construct RPCServer without passing isBridgeReady, which defaults to { true }. The send handler then takes the bridge branch:

if let bridgeChatGUID = bridgeChatGUID(...),
  transport != .applescript,
  transport == .bridge || isBridgeReady()
{

So the injected sendMessage stub is never called.

In CI this is invisible: with no injected helper the bridge invocation throws and the handler falls back to AppleScript, which is exactly what the tests assert. On a machine where the helper is injected the bridge call succeeds, and the assertions see bridge_v2 instead of applescript, with captured left nil:

Expectation failed: (data?["transport"] as? String → "bridge_v2") == "applescript"
Expectation failed: (captured?.chatIdentifier → nil) == "iMessage;+;chat123"

The tests are about RPC result shaping, not about which transport happens to be reachable — so the transport should be pinned rather than inherited from host state.

Change

Pass isBridgeReady: { false } at the three call sites. This matches the existing explicit isBridgeReady: { true } already used elsewhere in the same file, so the pattern is established.

Test-only. No production behavior changes; the parameter was already injectable.

Verify

Host: macOS 26, Apple Silicon, SIP disabled, Messages.app running with imsg-bridge-helper.dylib injected, imsg status reporting v2_ready: true.

Before, on this host:

✘ rpcSendResolvesChatID() failed
✘ rpcSendReportsMisroutedChatGhost() failed
✘ rpcSendReturnsSentMessageIdentifiersWhenResolved() failed
✘ Test run with 746 tests in 10 suites failed

After:

✔ Test run with 744 tests in 10 suites passed

make lint: Found 15 violations, 0 serious in 249 files, exit 0 — identical to base 646ea7a; I diffed the violation sets and this change introduces none.

Disclosure: AI assisted in writing and verifying this change.

Three RPCServerTests cases build an RPCServer without passing isBridgeReady,
which defaults to `{ true }`. The send handler therefore takes the bridge branch
in `transport == .bridge || isBridgeReady()`, and the injected sendMessage stub
is never called.

In CI that goes unnoticed: with no injected helper the bridge invocation throws
and the handler falls back to AppleScript, which is what the tests assert. On a
developer machine with the helper actually injected the bridge call succeeds, so
the assertions see `bridge_v2` instead of `applescript` and nil captured options.

Pin the transport the tests intend to exercise by passing `isBridgeReady:
{ false }`, matching the existing explicit `isBridgeReady: { true }` at the top
of the file. Test-only change; no production behavior is affected.

`make test` on macOS 26 with a live injected bridge: 744 tests, all passing.
Previously 3 failed on the same host.
@clawsweeper

clawsweeper Bot commented Sep 7, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Sep 7, 2026
@clawsweeper

clawsweeper Bot commented Sep 7, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed September 6, 2026, 9:19 PM ET / September 7, 2026, 01:19 UTC.

ClawSweeper review

What this changes

Pins three RPC send tests to their injected AppleScript sender so an available Messages bridge cannot bypass their fixtures.

Merge readiness

Ready for maintainer review

The focused fix remains necessary on current main, preserves the existing assertions, and has relevant verification from the affected host. No blocking defects found.

Likely related people: Peter Steinberger (low-confidence routing candidate from recent RPC history).

Priority: P2
Reviewed head: 0a214f106c092cc455e2b75e5ac7985639d8e436

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) A narrow, maintainable test repair with relevant affected-host verification and no blocking findings.
Proof confidence 🐚 platinum hermit (4/6) Sufficient (terminal): For this test-isolation change, the contributor’s before/after make test output on a real bridge-enabled macOS host directly exercises the reported environmental failure through RPCServer; the post-change run passes. This supports test independence, not a claim about live message delivery.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (terminal): For this test-isolation change, the contributor’s before/after make test output on a real bridge-enabled macOS host directly exercises the reported environmental failure through RPCServer; the post-change run passes. This supports test independence, not a claim about live message delivery.
Evidence reviewed 7 items Exact introduced scope: The pinned base-to-head diff adds false readiness overrides at three existing test constructors; all assertions remain intact and no production files change.
Transport-selection mechanism: The store-based initializer defaults readiness to true. With automatic transport and a resolved chat, the handler attempts the real bridge before the injected sender; false readiness selects the intended fixture path.
Existing bridge coverage remains: Separate tests explicitly exercise bridge selection, uncertain delivery failures, and rejection of threaded replies when the bridge is unavailable.
Findings None None.
Security None None.

How this fits together

imsg’s JSON-RPC server turns client send requests into bridge or AppleScript operations and returns message identifiers or delivery errors. These tests use an in-memory database and injected senders to verify that response behavior.

flowchart LR
  A[Test send request] --> B[RPC server]
  C[In-memory chat database] --> B
  B --> D{Bridge readiness}
  D -->|Available| E[Messages bridge]
  D -->|Pinned false| F[Injected sender]
  F --> G[Response assertions]
Loading

Before merge

None.

Agent review details

Security

None.

Review metrics

None.

Root-cause cluster

Relationship: fixed_by_candidate
Canonical: #275
Summary: This PR is the proposed fix for the same author's open report of these three host-dependent failures.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Technical review

Best possible solution:

Keep response-shaping tests deterministic through the existing readiness injection while retaining separate bridge-routing coverage.

Do we have a high-confidence way to reproduce the issue?

Yes: current-main source explains how these tests reach the host bridge instead of their sender stubs, and the paired report records failures with the bridge injected. This review did not execute the tests.

Is this the best way to solve the issue?

Yes: using the existing injectable readiness predicate is a narrow repair that preserves test assertions and production defaults.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 646ea7af9616.

Labels

Label changes:

  • add P2: Repairs three host-dependent test failures that obscure local regression checks, with no production behavior change.
  • add proof: sufficient: Contributor real behavior proof is sufficient. For this test-isolation change, the contributor’s before/after make test output on a real bridge-enabled macOS host directly exercises the reported environmental failure through RPCServer; the post-change run passes. This supports test independence, not a claim about live message delivery.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): For this test-isolation change, the contributor’s before/after make test output on a real bridge-enabled macOS host directly exercises the reported environmental failure through RPCServer; the post-change run passes. This supports test independence, not a claim about live message delivery.

Label justifications:

  • P2: Repairs three host-dependent test failures that obscure local regression checks, with no production behavior change.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): For this test-isolation change, the contributor’s before/after make test output on a real bridge-enabled macOS host directly exercises the reported environmental failure through RPCServer; the post-change run passes. This supports test independence, not a claim about live message delivery.
  • proof: sufficient: Contributor real behavior proof is sufficient. For this test-isolation change, the contributor’s before/after make test output on a real bridge-enabled macOS host directly exercises the reported environmental failure through RPCServer; the post-change run passes. This supports test independence, not a claim about live message delivery.

Evidence

What I checked:

  • Exact introduced scope: The pinned base-to-head diff adds false readiness overrides at three existing test constructors; all assertions remain intact and no production files change. (Tests/imsgTests/RPCServerTests.swift:153, 0a214f106c09)
  • Transport-selection mechanism: The store-based initializer defaults readiness to true. With automatic transport and a resolved chat, the handler attempts the real bridge before the injected sender; false readiness selects the intended fixture path. (Sources/imsg/RPCServer+Handlers.swift:272, 0a214f106c09)
  • Existing bridge coverage remains: Separate tests explicitly exercise bridge selection, uncertain delivery failures, and rejection of threaded replies when the bridge is unavailable. (Tests/imsgTests/RPCServerBridgeTests.swift:9, 0a214f106c09)
  • Still absent from main and release: The verified PR base is fetched main, and its test constructors lack these overrides. Inspection of v0.15.1 also shows the unpinned constructor. (Tests/imsgTests/RPCServerTests.swift:144, 646ea7af9616)
  • Affected-host verification and paired issue: The supplied complete PR body reports the three failures before the change and a passing make test run afterward on macOS 26 with the helper injected and v2_ready true; make lint reportedly exits zero with unchanged violations. Aggregate totals differ, 746 before versus 744 after, but the verified patch removes no tests. The paired open report tests: three RPCServerTests fail on any host with a live injected bridge (green only in CI) #275 identifies the same three failures on current main. Captured context sourceRevision: c17e1994177b025b27b6ee2bdf3c9c2014f026ce0097863f9ae9aed2fc8349ae. (0a214f106c09)
  • Area history and inspection limits: Available file history repeatedly lists Peter Steinberger for merged RPC work, including cdc09c1. Deeper blame and historical patch reads failed because required objects were unavailable and GitHub DNS resolution failed; no source-line introduction attribution is claimed. Source inspection succeeded, and no builds or tests were executed during this read-only review. (Tests/imsgTests/RPCServerTests.swift, cdc09c1f2de8)

Likely related people:

  • Peter Steinberger: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@steipete

steipete commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

Verified head 0a214f106c092cc455e2b75e5ac7985639d8e436. The three changed constructors correctly select their injected AppleScript sender through the existing readiness seam; production routing and assertions are unchanged.

  • All three repaired RPC cases pass locally. make lint passes with 15 existing warnings and no serious violations.
  • Independent branch autoreview against origin/main is clean at P0–P2.
  • macOS and Linux CI passed on this exact head: https://github.com/openclaw/imsg/actions/runs/34072572862.
  • Built the actual CLI, signed it with the matching Developer ID, ran --version, and read one real Messages chat as NDJSON. Exit 0; private fields withheld.

The affected-host bridge-on before/after evidence in this PR remains the transport-isolation proof. This verification Mac has SIP enabled. The full local suite exposed a separate output-capture deadlock that also reproduces serially: the subprocess helper waits before draining its pipes. That root cause is repaired independently in #279, with a failing-before/passing-after 128 KiB regression and an unchanged three-second timeout. Land #279 first so the remaining local validation is reproducible on constrained hosts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tests: three RPCServerTests fail on any host with a live injected bridge (green only in CI)

2 participants