Skip to content

fix(imessage): gate split-send coalescing on imsg metadata#90858

Merged
omarshahine merged 3 commits into
openclaw:mainfrom
omarshahine:fix/imessage-imsg-balloon-metadata
Jun 8, 2026
Merged

fix(imessage): gate split-send coalescing on imsg metadata#90858
omarshahine merged 3 commits into
openclaw:mainfrom
omarshahine:fix/imessage-imsg-balloon-metadata

Conversation

@omarshahine

@omarshahine omarshahine commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Summary

What problem does this PR solve?

  • Replaces iMessage split-send merge decisions with the new imsg structural URL-balloon metadata from feat: expose message balloon bundle metadata imsg#137.
  • Preserves balloon_bundle_id at the OpenClaw iMessage RPC payload boundary.
  • Merges an opt-in coalesce bucket precisely when a source row carries balloon_bundle_id: "com.apple.messages.URLBalloonProvider".
  • Keeps a capability-gated back-compat path so existing coalesceSameSenderDms users on a released imsg (no balloon metadata yet) are not regressed while the dependency rolls out.

How the merge decision works (capability-gated, three-way)

  • URL-balloon marker present in the bucket: merge it — this is a real Apple URL-preview split-send.
  • Build known to emit balloon metadata (a session-level capability latch, flipped once any inbound row this session carried balloon_bundle_id): a bucket with no URL marker is genuinely not a split-send, so keep the rows as separate turns. This is the precision the structural gate exists for.
  • Build has never emitted balloon metadata (older imsg): we cannot structurally tell a Dump <url> split-send from separate sends, so preserve the pre-metadata merge rather than regress split-send users to two turns.

Why a session-level latch instead of a per-bucket check?

  • imsg omits balloon_bundle_id on the wire for non-balloon rows, so a bucket of plain text rows looks identical on old and new builds. Absence of metadata in one bucket does not prove the build lacks the field. The capability signal therefore has to be session-scoped (monitor-provider.ts), not inferred per-bucket. (Caught by autoreview — see below.)

Important invariant: this never merges more than the shipped behavior already does. With coalesceSameSenderDms enabled, main debounces every same-sender DM and merges each multi-entry bucket unconditionally. An unlatched session (older build, or a metadata-capable build before its first balloon row) is therefore identical to today, not a new regression; once capability is observed it merges strictly less (more precise).

Why does this matter now?

  • The previous OpenClaw workaround guessed from short messages/timing before another row arrived. The corresponding imsg PR gives OpenClaw a structural signal instead — and the back-compat path lets this ship ahead of the imsg release without regressing anyone.

What is intentionally out of scope?

  • No text-shape or URL-shape heuristic. The only fallback is "preserve the existing unconditional merge until the build proves it emits balloon metadata."
  • No non-URL attachment split-send merge, because the new imsg field only proves URL-preview balloon rows.
  • Fully closing the pre-latch window (a metadata-capable session before its first balloon row) needs an imsg-advertised capability flag, which is part of the upstream coalescing work (Coalesce Apple URL-preview split-sends into a single notification imsg#141).

What does success look like?

  • URL-balloon buckets merge; on metadata-capable builds non-URL buckets stay separate; on metadata-less builds the existing merge is preserved; docs describe the metadata requirement, the back-compat fallback, and the latency tradeoff.

What should reviewers focus on?

  • Whether the capability latch is at the right boundary (monitor-provider.ts handleMessage ingress) and whether the three-way gate in coalesce.ts correctly preserves shipped behavior for metadata-less builds.

Linked context

Which issue does this close?

Closes #90795

Which issues, PRs, or discussions are related?

Was this requested by a maintainer or owner?

Requested by maintainer in chat after closing #90795 in favor of the imsg contract fix.

Real behavior proof (required for external PRs)

  • Behavior addressed: iMessage DM split-send coalescing now uses imsg balloon_bundle_id metadata instead of short-message/string-shape inference, with a capability-gated back-compat path that preserves shipped merge behavior on metadata-less imsg builds.
  • Real environment tested:
    • Live end-to-end: the patched OpenClaw gateway from this PR head (11c4454ba3) ran on a real macOS 26.4.1 host, watching the real Messages chat.db through a real imsg Gateway: avoid duplicate block stream replies #137 build (fix/expose-imessage-balloon-metadata, e223709) that emits balloon_bundle_id. A real Dump <url> split-send sent from an iPhone (Messages UI) was merged into one agent turn.
    • Local OpenClaw source checkout with the iMessage monitor through mocked imsg JSON-RPC notifications; sibling imsg source inspected directly for the output-field contract (balloon_bundle_id is String?, omitted on the wire when nil).
  • Exact steps or command run after this patch:
    • node scripts/run-vitest.mjs extensions/imessage/src/monitor/coalesce.test.ts extensions/imessage/src/monitor/parse-notification.test.ts extensions/imessage/src/monitor.last-route.test.ts
    • node scripts/run-oxlint.mjs extensions/imessage/src/monitor/coalesce.ts extensions/imessage/src/monitor/monitor-provider.ts extensions/imessage/src/monitor/coalesce.test.ts
    • npx oxfmt --check --threads=1 <changed .ts files>
    • pnpm tsgo:extensions && pnpm tsgo:extensions:test
    • .agents/skills/autoreview/scripts/autoreview --mode local
  • Evidence after fix: 37 focused Vitest tests passed; oxlint exit 0; oxfmt clean; tsgo:extensions and tsgo:extensions:test clean.
  • Observed result after fix:
    • Live capture: real inbound split-send (text="Dump" no marker, then the URL with balloon_bundle_id="com.apple.messages.URLBalloonProvider" 1s later) → patched gateway logged [PROOF] MERGED bucket size=2 markers=1 buildCapable=true text="Dump https://www.theverge.com/news/..." — debounced into one bucket, saw the marker, latch flipped, merged into one turn. ([PROOF] was a temporary unconditional log added only on the throwaway host checkout, reverted; host restored to production.) See the live-proof comment.
    • A fieldless Dump + URL bucket (metadata-less build) dispatches as one legacy-merged turn — matches shipped main, no regression.
    • A bucket where a row carries balloon_bundle_id: "com.apple.messages.URLBalloonProvider" dispatches as one merged turn.
    • On a session known to emit balloon metadata, a plain two-row bucket dispatches as two separate turns (the precision win).
  • What was not tested: behavior against a released imsg containing feat: expose message balloon bundle metadata imsg#137 (still pre-release) — but the live capture above used a build with the exact Gateway: avoid duplicate block stream replies #137 read-path, so runtime behavior is identical; on metadata-less released imsg the back-compat path preserves shipped main (no regression).
  • Before evidence: old behavior merged coalesced buckets based on timing/text shape without proving the later row was a URL balloon from imsg.

Tests and validation

Which commands did you run?

  • node scripts/run-vitest.mjs extensions/imessage/src/monitor/coalesce.test.ts extensions/imessage/src/monitor/parse-notification.test.ts extensions/imessage/src/monitor.last-route.test.ts
  • node scripts/run-oxlint.mjs <changed monitor .ts files>
  • npx oxfmt --check --threads=1 <changed .ts files>
  • pnpm tsgo:extensions && pnpm tsgo:extensions:test
  • .agents/skills/autoreview/scripts/autoreview --mode local

What regression coverage was added or updated?

  • Parser test for preserving balloon_bundle_id.
  • Coalesce gate tests for: URL-balloon recognition; legacy merge when the build has never emitted balloon metadata; plain bucket kept separate once the build is known to emit metadata (capability latch); non-URL balloon bucket kept separate.
  • Monitor notification-path tests: fieldless bucket legacy-merges into one turn; URL-balloon bucket merges.

Which bot or reviewer comments were addressed?

  • Autoreview round 1 (P1): a per-bucket absence check would over-merge plain DMs on metadata-capable builds. Fixed by introducing the session-level capability latch.
  • Autoreview round 2 (P2): residual pre-latch transient over-merge. Rejected with a recorded inline invariant — it is identical to shipped main behavior (verified main merges every multi-entry bucket unconditionally), and the suggested alternative would re-break old-imsg split-sends; fully closing it needs the imsg capability flag scoped into fix: complete gateway server refactoring and fix Swift compiler crash #141.

Risk checklist

Did user-visible behavior change? (Yes/No)

Yes. On metadata-capable imsg builds, opt-in split-send coalescing becomes precise (only real URL split-sends merge). On metadata-less builds, behavior is unchanged from shipped main.

Did config, environment, or migration behavior change? (Yes/No)

No config shape or migration change. Existing channels.imessage.coalesceSameSenderDms remains the switch. (Its eventual removal + doctor --fix migration is tracked in #91243.)

Did security, auth, secrets, network, or tool execution behavior change? (Yes/No)

No.

What is the highest-risk area?

The capability latch and the back-compat merge decision. Mis-scoping the latch (per-bucket instead of session) would reintroduce over-merging on new builds.

How is that risk mitigated?

The latch is session-scoped at the message ingress; the gate is unit-tested across all three branches; the back-compat path provably never merges more than shipped main, so there is no regression for current users.

Current review state

What is the next action?

Maintainer review. Safe to land ahead of the imsg release because the back-compat path preserves shipped behavior; precision activates automatically once an imsg build with openclaw/imsg#137 reaches users.

What is still waiting on author, maintainer, CI, or external proof?

Nothing outstanding: CI is green, and live end-to-end proof against a real imsg #137 build has been captured (see proof comment). Only the imsg #137 release remains, which gates real-user activation but not correctness — the back-compat path keeps released-imsg behavior identical to shipped main.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: imessage Channel integration: imessage size: M maintainer Maintainer-authored PR labels Jun 6, 2026
@clawsweeper

clawsweeper Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 7, 2026, 9:45 PM ET / 01:45 UTC.

Summary
The branch preserves imsg balloon_bundle_id metadata in iMessage payloads, gates same-sender DM coalescing on URL-balloon metadata with a legacy fallback, and updates focused tests plus iMessage docs.

PR surface: Source +76, Tests +223, Docs +3. Total +302 across 8 files.

Reproducibility: yes. source inspection gives a high-confidence reproduction path: current main combines every multi-entry debounced iMessage DM bucket unconditionally when coalesceSameSenderDms is active. I did not run tests because this was a read-only checkout review.

Review metrics: 2 noteworthy metrics.

  • Compatibility fallback: 1 added. The PR adds a metadata-less fallback branch so released imsg builds keep current merge behavior while new builds get precise separation.
  • Upstream metadata dependency: 1 new field consumed. Correctness of the precise path depends on balloon_bundle_id being emitted by imsg before OpenClaw can distinguish URL balloons from ordinary rows.

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Risk before merge

Maintainer options:

  1. Land With Accepted Interim Semantics (recommended)
    Maintainers can land this as the documented bridge state if they accept that metadata-capable imsg builds will split non-marker rapid DM buckets while metadata-less builds keep legacy merging.
  2. Wait For Upstream Coalescing
    Maintainers can pause or close this PR if they prefer not to carry the client-side compatibility branch before Coalesce Apple URL-preview split-sends into a single notification imsg#141 makes split-sends arrive pre-coalesced.

Next step before merge

  • [P2] The protected maintainer label and compatibility-sensitive opt-in behavior change require a human maintainer land decision; there is no narrow automated repair to queue.

Security
Cleared: The diff only changes iMessage parsing/coalescing logic, docs, and tests; I found no new secrets, package, workflow, install, or code-execution supply-chain concern.

Review details

Best possible solution:

A maintainer should explicitly accept the interim compatibility tradeoff and land this only if OpenClaw wants client-side precision before upstream imsg coalescing replaces the path.

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

Yes, source inspection gives a high-confidence reproduction path: current main combines every multi-entry debounced iMessage DM bucket unconditionally when coalesceSameSenderDms is active. I did not run tests because this was a read-only checkout review.

Is this the best way to solve the issue?

Yes, this is an acceptable interim fix: it moves the merge decision from text/timing inference to imsg structural metadata while preserving released metadata-less behavior. The final cleaner solution is still upstream coalescing in imsg, tracked by #91243.

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against b16a43597d49.

Label changes

Label changes:

  • add rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • remove rating: 🐚 platinum hermit: Current PR rating is rating: 🦞 diamond lobster, so this older rating label is no longer current.

Label justifications:

  • P2: This is a normal-priority iMessage behavior fix with limited blast radius but real user-visible turn grouping impact for opt-in setups.
  • merge-risk: 🚨 compatibility: Existing coalesceSameSenderDms users can see different rapid-DM grouping after upgrading to an imsg build that emits balloon metadata.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (logs): The PR body and live-proof comment report a patched OpenClaw gateway on a real macOS Messages database with an imsg metadata build, including a redacted log showing the split-send bucket merged via the URL-balloon marker.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body and live-proof comment report a patched OpenClaw gateway on a real macOS Messages database with an imsg metadata build, including a redacted log showing the split-send bucket merged via the URL-balloon marker.
Evidence reviewed

PR surface:

Source +76, Tests +223, Docs +3. Total +302 across 8 files.

View PR surface stats
Area Files Added Removed Net
Source 4 89 13 +76
Tests 3 223 0 +223
Docs 1 15 12 +3
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 8 327 25 +302

What I checked:

Likely related people:

  • steipete: Current-main blame in this shallow checkout attributes the iMessage monitor/coalescing surface to c2d825a, making this the clearest local routing signal for the affected code. (role: current-main area contributor; confidence: medium; commits: c2d825ae534c; files: extensions/imessage/src/monitor/coalesce.ts, extensions/imessage/src/monitor/monitor-provider.ts, docs/channels/imessage.md)
  • omarshahine: Beyond this PR branch, the same person authored the upstream imsg head e223709a91e81f3d405a9a8593eafdc3b6ec0e24 that defines the consumed balloon_bundle_id output contract and supplied the live proof comments. (role: upstream dependency contract contributor; confidence: medium; commits: e223709a91e8, 11c4454ba35e; files: Sources/imsg/OutputModels.swift, extensions/imessage/src/monitor/coalesce.ts, extensions/imessage/src/monitor/monitor-provider.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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.

How this review workflow works
  • 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.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 6, 2026
@omarshahine

Copy link
Copy Markdown
Contributor Author

Real behavior proof

Behavior addressed: iMessage split-send coalescing is now gated on the structural balloon_bundle_id metadata from openclaw/imsg#137 — a URL-preview split-send merges into one turn only when a source row carries balloon_bundle_id: "com.apple.messages.URLBalloonProvider"; fieldless/plain rapid DMs flush separately.

Real environment tested: lobster (macOS 26.4.1, Apple Silicon), against the real Messages chat.db. imsg built from openclaw/imsg#137 (fix/expose-imessage-balloon-metadata).

Exact steps / commands run after this patch:

# 1) The metadata input (imsg#137) on real chat.db
imsg history --chat-id 3 --limit 40 --json | grep -o 'balloon_bundle_id[^,]*' | sort | uniq -c

# 2) This PR's coalescing gate logic
node scripts/run-vitest.mjs extensions/imessage/src/monitor/coalesce.test.ts

Evidence after fix:

  • imsg#137 emits the gating field on a real URL message:
    1 balloon_bundle_id":"com.apple.messages.URLBalloonProvider"
    
  • coalesce.test.ts12 passed (12).

Observed result after fix: The exact structural signal this PR keys on (balloon_bundle_id == com.apple.messages.URLBalloonProvider) is present and correctly extracted from real iMessage data, and the coalescing gate (merge-on-marker / flush-otherwise) is unit-verified.

What was not tested: A full live gateway coalescing of a freshly received split-send. That requires running this branch's gateway with the imsg#137 build end-to-end; deploying a newer-main build to the production gateway host hit packaging/config-migration risk, so it was deferred to a disposable VM rather than forced on production. The gate logic + the real metadata input are proven; the only unproven piece is the runtime wiring between them, which monitor-provider.ts carries and the unit tests exercise with representative payloads.

@omarshahine omarshahine force-pushed the fix/imessage-imsg-balloon-metadata branch from db314a7 to d454fa3 Compare June 7, 2026 20:12
@omarshahine

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Two updates since the prior review:

  • Live behavior proof added (the proof gap from your verdict): tested on lobster (macOS 26.4.1, Apple Silicon) against the real Messages chat.db, with imsg built from feat: expose message balloon bundle metadata imsg#137. A URL-preview split-send merges into one turn only when a source row carries balloon_bundle_id: "com.apple.messages.URLBalloonProvider"; fieldless/plain rapid DMs flush separately. Commands run are in the "Real behavior proof" comment above.
  • Rebased onto latest origin/main (was 407 commits behind) so checks run on a current base. Head is now d454fa3de4.

Dependency state: openclaw/imsg#137 (feat: expose message balloon bundle metadata) is open + green CI + mergeable. The older-imsg compatibility change (fieldless buckets flush separately) is intentional and documented; flagging for the maintainer compat decision.

@clawsweeper

clawsweeper Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels Jun 7, 2026
…th back-compat

Use a session-level balloon-capability latch (not a per-bucket absence check)
to decide whether to merge a debounced same-sender DM bucket:
- URL-balloon marker present -> merge (precise split-send).
- build known to emit balloon metadata -> keep non-marker buckets separate.
- build never emitted balloon metadata -> preserve the legacy merge so older
  imsg builds (no balloon_bundle_id) do not regress Dump <url> split-sends.

Never merges more than shipped main already did. Removed once imsg coalesces
split-sends upstream (openclaw/imsg#141, tracked by openclaw#91243).
@omarshahine

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Material update since the last review: added a capability-gated back-compat path so this can ship ahead of the imsg #137 release without regressing existing coalesceSameSenderDms users.

  • New head: 74b8e99484f123c7c5f86596891865d8fe749c0d.
  • Merge decision is now three-way (coalesce.ts): URL-balloon marker → merge; build known to emit balloon metadata (session capability latch in monitor-provider.ts) → keep non-marker buckets separate; build that never emitted balloon metadata → preserve the legacy unconditional merge.
  • Invariant: never merges more than shipped main already does (main debounces every same-sender DM and merges multi-entry buckets unconditionally), so metadata-less builds are unchanged — no regression.
  • Verified: 37 focused tests, oxlint, oxfmt, tsgo:extensions(+test) all clean; two autoreview rounds (latch fix applied; residual pre-latch transient rejected with recorded invariant).
  • Removal of this whole client-side path is tracked in Remove client-side iMessage split-send coalescing once imsg coalesces upstream #91243 once imsg coalesces upstream (Coalesce Apple URL-preview split-sends into a single notification imsg#141).

PR body updated with the full behavior + proof.

@clawsweeper

clawsweeper Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

…g builds

The Flag-on column assumed the strict gate; on older imsg builds with no
balloon metadata the back-compat path legacy-merges fieldless buckets. Note
this on the table header and the attachment/flood rows.
@omarshahine

omarshahine commented Jun 7, 2026

Copy link
Copy Markdown
Contributor Author

Real behavior proof — balloon_bundle_id validated against the real chat.db with imsg #137

(Updated: an earlier version of this comment described an "empty-text filter." That was an artifact of testing against the wrong imsg branch. I rebuilt the actual #137 branch and re-verified — corrected findings below.)

Real environment: macOS 26.4.1, real ~/Library/Messages/chat.db, queried with a freshly built imsg from fix/expose-imessage-balloon-metadata (openclaw/imsg#137, commit e223709). All PII redacted.

A real split-send exists in the data, and #137 surfaces it correctly:

  • A received text row, followed 1 second later by a received URL-preview balloon row carrying balloon_bundle_id = "com.apple.messages.URLBalloonProvider".
  • Across a 200-row sample, exactly 1 row carries a non-null balloon_bundle_id (the URL-balloon row); all others are null — confirming the field is emitted on URL-preview rows and absent elsewhere.
  • That is exactly the constant this PR's gate keys on (IMESSAGE_URL_BALLOON_BUNDLE_ID), and the two rows arrive within the 2.5s debounce window — so fix(imessage): gate split-send coalescing on imsg metadata #90858 merges them into one agent turn.

Why this isn't redundant with imsg: #137's shouldSkipURLBalloonDuplicate only dedups a balloon row whose decoded text exactly matches a recent prior row; it does not coalesce typical Dump <url> split-sends. #137 delivers both the text row and the marker row, and OpenClaw #90858 is the component that merges them. (Full upstream coalescing remains the #141 direction.)

Paired with OpenClaw coverage: 37 unit/integration tests over these exact payload shapes (URL-marker merge; metadata-capable plain-bucket separation via the session latch; metadata-less legacy merge); tsgo:extensions (+test), oxlint, and oxfmt all clean.

Rollout caveat: the marker only reaches OpenClaw when an imsg build exposing balloon_bundle_id is installed (openclaw/imsg#137, currently unreleased). On released imsg the field is absent and #90858's back-compat path preserves shipped main behavior (no regression).

Maintainer acceptance

As maintainer I accept landing this as the interim, compatibility-preserving client-side gate ahead of the imsg release:

@clawsweeper

clawsweeper Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@omarshahine

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Proof comment above corrected after rebuilding imsg #137 (e223709): the marker surfaces correctly on a real split-send pair in the real chat.db; the earlier empty-text-filter note was a wrong-branch-build artifact. Head unchanged at 11c4454.

@clawsweeper

clawsweeper Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Command router queued. I will update this comment with the next step.

Re-review progress:

@omarshahine

Copy link
Copy Markdown
Contributor Author

Live end-to-end proof — patched OpenClaw gateway coalescing a real split-send via imsg #137

Ran the actual OpenClaw gateway from this PR's head (11c4454ba3, including the session-capability latch) on a real macOS 26.4.1 host, watching the real Messages chat.db through a build of imsg #137 (fix/expose-imessage-balloon-metadata, e223709) that emits balloon_bundle_id. A real Dump <url> split-send was then sent from an iPhone via the Messages UI.

Real inbound split-send (raw chat.db):

  • row A: text="Dump", no balloon_bundle_id
  • row B (1 second later): the URL, balloon_bundle_id="com.apple.messages.URLBalloonProvider"

Patched gateway log — the merge:

[PROOF] MERGED bucket size=2 markers=1 buildCapable=true text="Dump https://www.theverge.com/news/..."

([PROOF] is a temporary unconditional log I added at the coalesce decision purely for this capture, reverted afterward. The host was restored to its production build.)

This is the live patched monitor doing exactly what #90858 implements, end-to-end on real Apple data:

  • debounced the two rows into one bucket (size=2),
  • saw the structural URL-balloon marker (markers=1),
  • confirmed the build emits balloon metadata via the session capability latch (buildCapable=true),
  • merged the split-send into a single agent turn.

Combined with the prior real-chat.db contract proof and the unit/integration suite, this closes the end-to-end gap: real imsg #137 emits the marker on a real split-send, and the patched gateway merges it live.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Command router queued. I will update this comment with the next step.

Re-review progress:

@omarshahine

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Prior re-reviews were superseded by concurrency. Re-requesting once: the end-to-end gap is now closed by the live capture above (#90858 (comment)) — the patched PR gateway, running live against a real imsg #137 build, merged a real iPhone-sent Dump-url split-send into one turn ([PROOF] MERGED bucket size=2 markers=1 buildCapable=true). PR body updated. Head 11c4454, CI green.

@clawsweeper

clawsweeper Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Command router queued. I will update this comment with the next step.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jun 8, 2026
@clawsweeper clawsweeper Bot added 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. rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. proof: sufficient ClawSweeper judged the real behavior proof convincing. 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. rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels Jun 8, 2026
@omarshahine omarshahine merged commit 9caff5f into openclaw:main Jun 8, 2026
349 of 365 checks passed
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 8, 2026
…th back-compat (openclaw#90858)

Gate iMessage same-sender DM split-send coalescing on imsg's structural
`balloon_bundle_id` URL-balloon marker (openclaw/imsg#137) instead of timing/
text-shape inference, with a session capability latch and a back-compat path:

- URL-balloon marker present -> merge (precise split-send).
- Build known to emit balloon metadata (session latch) -> keep non-marker
  buckets separate (the precision win).
- Build that never emits balloon metadata (older imsg) -> preserve the legacy
  unconditional merge, so split-send users do not regress to two turns.

Never merges more than shipped main already did. Verified live end-to-end: the
patched gateway, watching a real chat.db via an imsg openclaw#137 build, merged a real
iPhone-sent `Dump <url>` split-send into one turn. Client-side removal once imsg
coalesces upstream is tracked in openclaw#91243 (openclaw/imsg#141).

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

Labels

channel: imessage Channel integration: imessage docs Improvements or additions to documentation maintainer Maintainer-authored PR merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. size: M 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.

1 participant